(2)打开网页查看
完成上面的操作之后,打开华为云网页后台,可以看到设备已经在线了。
点击详情页面,可以看到上传的数据:
如果想查看历史数据,点击这里:
到此,云平台的部署已经完成,设备已经可以正常上传数据了。
(3)MQTT登录测试参数总结
IP地址:117.78.5.125
端口号:1883
DeviceId 64000697352830580e48df07_dev1
DeviceSecret 12345678
ClientId 64000697352830580e48df07_dev1_0_0_2023030206
Username 64000697352830580e48df07_dev1
Password a695af9883c5d0e3817bc6971beeecadf8c7c595677c461b1fe75882ed2bf449
订阅主题:$oc/devices/64000697352830580e48df07_dev1/sys/messages/down
发布主题:$oc/devices/64000697352830580e48df07_dev1/sys/properties/report
发布的消息:{"services": [{"service\_id": "stm32","properties":{"DHT11\_T":18,"DHT11\_H":80,"MQ2":1,"water":1,"flame":1,"light":0,"LED1":0,"LED2":0,"LED3":0}}]}
四、上位机开发
为了方便查看设备上传的数据,对设备进行远程控制,接下来利用Qt开发一款Android和windows系统的上位机。
使用华为云平台提供的API接口获取设备上传的数据,也可以给设备下发指令,控制设备。
为了方便查看设备上传的数据,对设备进行远程控制,接下来利用Qt开发一款Android和windows系统的上位机。
使用华为云平台提供的API接口获取设备上传的数据,也可以给设备下发指令,控制设备。
4.1 Qt开发环境安装
Qt的中文官网: https://www.qt.io/zh-cn/
QT5.12.6的下载地址:https://download.qt.io/archive/qt/5.12/5.12.6
打开下载链接后选择下面的版本进行下载:
qt-opensource-windows-x86-5.12.6.exe 13-Nov-2019 07:28 3.7G Details
软件安装时断网安装,否则会提示输入账户。
安装的时候,第一个复选框里勾选一个mingw 32
编译器即可,其他的不管默认就行,直接点击下一步继续安装。
说明: 我这里只是介绍PC端的环境搭建(这个比较简单)。 Android的开发环境比较麻烦,可以去我的博客里看详细文章。
选择MinGW 32-bit 编译器:
4.2 创建IAM账户
创建一个IAM账户,因为接下来开发上位机,需要使用云平台的API接口,这些接口都需要token进行鉴权。简单来说,就是身份的认证。 调用接口获取Token时,就需要填写IAM账号信息。所以,接下来演示一下过程。
地址: https://console.huaweicloud.com/iam/?region=cn-north-4#/iam/users
获取Token时,除了AIM账号外,还需要项目凭证:
22ef548bdacc41a9ade0b3c83bcc3b21
鼠标放在左上角头像上,在下拉菜单里选择统一身份认证
。
点击左上角创建用户
。
创建成功:
4.3 获取影子数据
帮助文档:https://support.huaweicloud.com/api-iothub/iot_06_v5_0079.html
设备影子介绍:
设备影子是一个用于存储和检索设备当前状态信息的JSON文档。
每个设备有且只有一个设备影子,由设备ID唯一标识
设备影子仅保存最近一次设备的上报数据和预期数据
无论该设备是否在线,都可以通过该影子获取和设置设备的属性
简单来说:设备影子就是保存,设备最新上传的一次数据。
我们设计的软件里,如果想要获取设备的最新状态信息,就采用设备影子接口。
如果对接口不熟悉,可以先进行在线调试:https://apiexplorer.developer.huaweicloud.com/apiexplorer/doc?product=IoTDA&api=ShowDeviceShadow
在线调试接口,可以请求影子接口,了解请求,与返回的数据格式。
设备影子接口返回的数据如下:
{
"device\_id": "64000697352830580e48df07\_dev1",
"shadow": [
{
"service\_id": "stm32",
"desired": {
"properties": null,
"event\_time": null
},
"reported": {
"properties": {
"DHT11\_T": 18,
"DHT11\_H": 85,
"MQ2": 1,
"water": 1,
"flame": 1,
"light": 0,
"LED1": 0,
"LED2": 0,
"LED3": 0
},
"event\_time": "20230302T063135Z"
},
"version": 4
}
]
}
4.4 修改设备属性
地址: https://support.huaweicloud.com/api-iothub/iot_06_v5_0034.html
接口说明
设备的产品模型中定义了物联网平台可向设备下发的属性,应用服务器可调用此接口向指定设备下发属性。平台负责将属性以同步方式发送给设备,并将设备执行属性结果同步返回。
修改设备属性的接口,可以让服务器给设备下发指令,如果需要控制设备。
在线调试地址:
https://apiexplorer.developer.huaweicloud.com/apiexplorer/doc?product=IoTDA&api=UpdateProperties
修改设备属性是属于同步命令,需要设备在线才可以进行调试,先使用MQTT客户端登录服务器,模拟设备上线。
然后进行调试,测试数据远程下发给设备。
【1】利用MQTT客户端先登录设备 (这是同步命令,必须在线才能调试)
【2】点击调试
{"services":{"LED":1}}
【4】可以看到,MQTT客户端软件上已经收到了服务器下发的消息
由于是同步命令,服务器必须要收到设备的响应才能顺利完成一个流程,设备响应了服务器才能确定数据下发成功。
MQTT设备端如何响应呢?
设备响应格式说明:https://support.huaweicloud.com/api-iothub/iot_06_v5_3008.html
下面进行实操:
当服务器通过在线调试,发送指令下来之后,客户端将请求ID复制下来,添加到发布主题的格式里,再回复回去,服务器收到了响应,一次属性修改就完美完成了。
就是成功的状态:
**下面是请求的总结: ** (响应服务器的修改设备属性请求)
上报主题的格式:$oc/devices/{device_id}/sys/properties/set/response/request_id=
$oc/devices/64000697352830580e48df07_dev1/sys/properties/set/response/request_id=
响应的数据:
{"result\_code": 0,"result\_desc": "success"}
4.5 设计上位机
前面2讲解了需要用的API接口,接下来就使用Qt设计上位机,设计界面,完成整体上位机的逻辑设计。
【1】新建Qt工程
选择工程路径,放在英文路径下。
创建完毕。
新建Android的模板:
【2】打开现有的Qt工程
如果想打开已经设计好的工程,可以在保存上位机源码的目录下,找到工程文件xxx.pro,双击打开工程,详细操作看下面截图红框。
【3】设计UI界面
打开UI设计师界面:
这是默认的界面:
下面是设计好的界面:
【4】配置参数读取与保存
/\*
功能: 保存数据到文件
\*/
void Widget::SaveDataToFile(QString text)
{
/\*保存数据到文件,方便下次加载\*/
QString file;
file=QCoreApplication::applicationDirPath()+"/"+ConfigFile;
QFile filesrc(file);
filesrc.open(QIODevice::WriteOnly);
QDataStream out(&filesrc);
out << text; //序列化写字符串
filesrc.flush();
filesrc.close();
}
/\*
功能: 从文件读取数据
\*/
QString Widget::ReadDataFile(void)
{
//读取配置文件
QString text,data;
text=QCoreApplication::applicationDirPath()+"/"+ConfigFile;
//判断文件是否存在
if(QFile::exists(text))
{
QFile filenew(text);
filenew.open(QIODevice::ReadOnly);
QDataStream in(&filenew); // 从文件读取序列化数据
in >> data; //提取写入的数据
filenew.close();
}
return data; //返回值读取的值
}
【5】通信交互代码
//解析反馈结果
void Widget::replyFinished(QNetworkReply \*reply)
{
QString displayInfo;
int statusCode = reply->attribute(QNet