QT学习开发笔记(项目实战之智能家居物联 UI 界面开发 )

智能家居物联 UI 界面开发

项目路径为 4/01_smarthome/01_smarthome/01_smarthome.pro,先看项目界面。项目界面如
下,采用暗黑主题设计,结合黄色作为亮色,让用户一目了然。界面笔者从一些智能家居界面
中找到灵感的,编写设计完成的效果不错!请自行查阅源码,掌握了本教程前面第七章的内容,
就可以理解这个界面是如何设计的。

在这里插入图片描述

原子云 API 接口

我们想要与原子云通信,那么必须先了解原子云平台的 API 接口。请参阅原子云平台 API

文档 V1.2.pdf 文档。原子云平台 API 写的非常详细了,请自行翻阅。需要我们从原子云平台了
解原子云 API 的通信流程。

下图是原子云平台 API 的使用流程图。 在这里插入图片描述
我们写 Qt 应用就应该重点放在 HTTPS 与 WebSocket 方向上。查阅原子云平台 API 可以知
道,下面是重点!一些帐号信息,与设备信息是通过 HTTPS 协议接口获取的,通信用 WebSocket

协议接口。那么我们就按原子云平台的协议流程编写应用程序。
源码路径为 4/01_smarthome/webapi/webapi.cpp。内容如下。

 /****************************************************************** Copyright © Deng Zhimao Co., Ltd. 1990-2021. All rights reserved. * @projectName webapi * @brief webapi.cpp * @author Deng Zhimao * @email 1252699831@qq.com * @net www.openedv.com * @date 2021-05-27 *******************************************************************/ 1 #include "webapi.h" 2 #include <QUuid> 3 #include <QRegularExpression> 4 5 Webapi::Webapi(QObject *parent) 6 { 7 this->setParent(parent); 8 /* 数组清空 */ 9 groupID.clear(); 10 deviceID.clear(); 11 deviceNumber.clear(); 12 13 timer = new QTimer(); 
14 connect(timer, SIGNAL(timeout()), this, SLOT(onTimerTimeOut())); 15 16 networkAccessManager = new QNetworkAccessManager(this); 17 18 orgURL = "https://cloud.alientek.com/api/orgs"; 19 /* 请填写自己的 token 信息!!! */ 20 api_token = "bf591984c8fa417584d18f6328e0ef73"; 21 22 /* 获取账号机构列表 */ 23 getOrgURL(); 24 25 QUuid uuid = QUuid::createUuid(); 26 random_token = uuid.toString(); 27 28 webSocket = new QWebSocket(); 29 /* 需要加一些安全配置才能访问 https */ 30 QSslConfiguration config; 31 config.setPeerVerifyMode(QSslSocket::VerifyNone); 32 config.setProtocol(QSsl::TlsV1SslV3); 33 webSocket->setSslConfiguration(config); 34 35 connect(webSocket, SIGNAL(connected()), 36 this, SLOT(webSocketConnected())); 37 connect(webSocket, SIGNAL(binaryMessageReceived(QByteArray)), 38 this, SLOT(onBinaryMessageReceived(QByteArray))); 39 } 40 41 Webapi::~Webapi() 42 { 43 delete timer; 44 delete webSocket; 45 webSocket = nullptr; 46 } 47 48 void Webapi::getOrgURL() 49 { 50 getDataFromWeb(QUrl(orgURL)); 51 } 52 53 /* 获取设备分组列表 */ 54 void Webapi::getGroupListUrl() 55 { 56 getDataFromWeb(QUrl(groupListUrl)); 57 } 58 59 /* 获取设备的信息 */ 60 void Webapi::getDevOfGroupUrl() 61 { 62 getDataFromWeb(QUrl(devOfGroupUrl)); 63 } 64 65 /* 获取设备连接状态 */ 66 void Webapi::getConStateUrl() 67 { 68 getDataFromWeb(QUrl(conStateUrl)); 69 } 70 71 /* 从云服务器获取数据 */ 72 void Webapi::getDataFromWeb(QUrl url) 73 { 74 /* 网络请求 */ 75 QNetworkRequest networkRequest; 76 77 /* 需要加一些安全配置才能访问 https */ 78 QSslConfiguration config; 79 config.setPeerVerifyMode(QSslSocket::VerifyNone); 80 config.setProtocol(QSsl::TlsV1SslV3); 81 networkRequest.setSslConfiguration(config); 82 83 /* 设置访问的地址 */ 84 networkRequest.setUrl(url); 85 86 /* 网络响应 */ 87 networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, 88 "application/json;charset=UTF-8"); 89 90 /* 参数二为原子云帐号的 token 信息,填写自己的 */ 91 networkRequest.setRawHeader("token", api_token.toLatin1()); 92 93 QNetworkReply *newReply = 94 networkAccessManager->get(networkRequest); 95 96 connect(newReply, SIGNAL(finished()), 97 this, SLOT(replyFinished())); 98 connect(newReply, SIGNAL(readyRead()), 99 this, SLOT(readyReadData())); 100 101 } 102 void Webapi::replyFinished() 103 { 104 QNetworkReply *reply = (QNetworkReply *)sender(); 105 106 if (reply->url() == QUrl(orgURL)) { 107 /* 设备分组列表 ID */ 108 getID(dataString, reply); 109 } 110 111 if (reply->url() == QUrl(groupListUrl)) { 112 /* 列表 ID */ 113 getID(dataString, reply); 114 115 /* 获取到组 ID 再开启定时器 */ 116 if (!timer->isActive()) 117 timer->start(2000); 118 } 119 120 /* 设备的信息 */ 121 if (reply->url() == QUrl(devOfGroupUrl)) { 122 getID(dataString, reply); 123 getNumber(dataString); 124 getName(dataString); 125 } 126 127 /* 设备的连接状态 */ 128 if (reply->url() == QUrl(conStateUrl)) { 129 getConnectState(dataString); 130 } 131 132 reply->deleteLater(); 133 reply = nullptr; 134 } 135 void Webapi::readyReadData() 136 { 137 QNetworkReply *reply = (QNetworkReply *)sender(); 138 QByteArray data = reply->readAll(); 139 dataString = QString(data); 140 qDebug()<<dataString<<endl; 141 } 142 143 /* 获取 ID,包括分组 id,设备 id */ 144 void Webapi::getID(QString data, QNetworkReply *reply) 145 { 146 /* 多个匹配,因为可能有多个合适的字段 */ 147 QRegularExpression pattern("\"id\":(\\d+)"); 148 149 QRegularExpressionMatchIterator i = pattern.globalMatch(data); 150 while (i.hasNext()) { 151 QRegularExpressionMatch match = i.next(); 152 if (match.hasMatch()) { 153 if (reply->url() == QUrl(orgURL)) { 154 org_id = match.captured(1); 155 groupListUrl = "https://cloud.alientek.com/api/orgs/" 156 + org_id + "/grouplist"; 157 getGroupListUrl(); 158 /* Socket 连接 */ 159 
webSocket->open(QUrl(QString("wss://cloud.alientek.com/connection/%1/or
g/%2?token=%3") 160 .arg(api_token).arg(org_id).arg(rando
m_token))); 161 } 162 163 if (reply->url() == QUrl(groupListUrl)) { 164 group_id = match.captured(1); 165 /* 存储组 ID,再由定时器根据组的 ID 获取设备信息 */ 166 groupID.append(group_id); 167 qDebug()<<"组 ID:"<<group_id<<endl; 168 169 } 170 171 if (reply->url() == QUrl(devOfGroupUrl)) { 172 device_id = match.captured(1); 173 /* 存储设备 ID,再由定时器根据设备的 ID 获取连接状态 */ 174 deviceID.append(device_id); 175 qDebug()<<"设备 ID:"<<device_id<<endl; 176 } 177 } 178 } 179 } 180 181 void Webapi::getNumber(QString data) 182 { 183 QRegularExpression pattern("\"number\":\"(\\d+)\""); 184 185 QRegularExpressionMatchIterator i = pattern.globalMatch(data); 186 while (i.hasNext()) { 187 QRegularExpressionMatch match = i.next(); 188 if (match.hasMatch()) { 189 device_number = match.captured(1); 190 deviceNumber.append(device_number); 191 qDebug()<<"设备编号:"<<device_number<<endl; 192 } 193 } 194 } 195 196 void Webapi::getName(QString data) 197 { 198 /* 匹配中文字符,设备起名需要为中文 */ 199 QRegularExpression pattern("\"name\":\"([\u4e00-\u9fa5]*)"); 200 201 QRegularExpressionMatchIterator i = pattern.globalMatch(data); 202 while (i.hasNext()) { 203 QRegularExpressionMatch match = i.next(); 204 if (match.hasMatch()) { 205 device_name = match.captured(1); 206 deviceName.append(device_name); 207 qDebug()<<"设备名称:"<<device_name<<endl; 208 } 209 } 210 } 211 212 /* 获取设备的连接状态 */ 213 void Webapi::getConnectState(QString data) 214 { 215 QString pattern = "\"data\":\"(\\S*)\""; 216 QRegularExpression regularExpression(pattern); 217 QRegularExpressionMatch match = regularExpression.match(data, 0); 218 if(match.hasMatch()) { 219 qDebug()<<"设备连接状态"<<match.captured(1); 220 deviceConnectState.append(match.captured(1)); 221 } 222 } 223 224 void Webapi::webSocketConnected() 225 { 226 qDebug()<<"webSocket 连接原子云成功"<<endl; 227 } 228 229 void Webapi::onBinaryMessageReceived(QByteArray str) 230 { 231 232 QString temp(str); 233 if (temp.contains("online")) { 234 for (int i = 0; i < deviceNumber.count() ; i++) { 235 if (temp.contains(deviceNumber[i])) { 236 /* 发送如客厅灯在线信号*/ 237 emit deviceStateChanged(deviceName[i] + "|在线"); 238 qDebug()<<deviceName[i] + "|在线"<<endl; 239 break; 240 } 241 } 242 } 243 } 244 245 /* 延时函数 */ 246 void Webapi::sleep(double second) 247 { 248 usleep(second * 1000000); 249 } 250 251 void Webapi::onTimerTimeOut() 252 { 253 static int i = 0; 254 if (i < groupID.count()) { 255 /* 获取分组下的设备列表 */ 256 devOfGroupUrl = "https://cloud.alientek.com/api/orgs/" 257 + org_id + "/groups/" 258 + groupID[i] + "/devices"; 259 dataString.clear(); 260 getDevOfGroupUrl(); 261 } else if (i >= groupID.count() 262 && i < groupID.count() + deviceID.count() ) { 263 timer->start(1000); 264 conStateUrl = "https://cloud.alientek.com/api/orgs/" 265 + org_id + "/devicestate/" 266 + deviceID[i - groupID.count()]; 267 getConStateUrl(); 268 269 } else { 270 /* 订阅设备的消息 */ 271 for (int j = 0; j < deviceNumber.count(); j++) { 272 QByteArray cmd; 273 cmd[0] = 0x01; 274 sendCmd(deviceNumber[j], cmd); 275 } 276 277 timer->stop(); 278 } 279 280 i++; 281 } 282 283 /* 订阅指定设备的消息,cmd = 0x01 */ 284 void Webapi::sendCmd(QString number, QByteArray cmd) 285 { 286 QStringList list = number.split(""); 287 for (int i = 0; i < list.count(); i++) { 288 if (!list[i].isEmpty()) { 289 cmd.append(list[i]); 290 } 291 } 292 293 webSocket->sendBinaryMessage(cmd); 294 } 295 296 /* 发送消息到指定设备,cmd = 0x03 */ 297 void Webapi::sendCmdMessage(QString number, 298 QByteArray cmd, QString message) 299 { 300 QStringList list = number.split(""); 301 for (int i = 0; i < list.count(); i++) { 302 if (!list[i].isEmpty()) { 303 cmd.append(list[i]); 304 } 305 } 306 307 cmd.append(message); 308 309 webSocket->sendBinaryMessage(cmd); 310 } 311 312 void Webapi::whichDeviceNameSendCmd(QString name, 313 QString message) { 314 315 for (int i = 0; i < deviceName.count(); i++) { 316 if (name == deviceName[i]) { 317 QByteArray cmd; 318 cmd[0] = 0x03; 319 sendCmdMessage(deviceNumber[i], cmd, message); 320 break; 321 } 322 } 323 } 

第 20 行,需要填写自己的原子云平台帐号 api_token 信息,请在原子云》帐号信息中查看!
剩余的代码都按照原子云平台 API 文档编写,首先是通过网络请求 networkRequest,访问
需要访问的地址,然后通过网络回应对象 newReply 来接收网络回复的结果。结果是 JSION 格
式的文本,笔者使用正则表达式提取回复的内容,作为下一个地址的参数,如此反复,就可以
将原子云服务器的帐号下的设备信息提取出来。
第 159 行,提取出来的信息转交 webSocket 对象,让 webSocket 获取原子云平台的鉴权,
就可以实现通信了。
流程都是按照原子云平台 API 文档的走,剩下的就是 webSocket 通信了,与 TCP,UDP 的

socket 通信相似,这里就不多解释了,和第十一章的 TCP/UDP Socket 通信内容相似。重点是流
程,再参考代码看。

查看全文

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.dgrt.cn/a/2203362.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章:

在这里插入图片描述

QT学习开发笔记(项目实战之智能家居物联 UI 界面开发 )

智能家居物联 UI 界面开发
项目路径为 4/01_smarthome/01_smarthome/01_smarthome.pro,先看项目界面。项目界面如 下,采用暗黑主题设计,结合黄色作为亮色,让用户一目了然。界面笔者从一些智能家居界面 中找到灵感的,编……

D、Bulbasaur C语言

目录
题目
题目分析:
通过代码:
需要注意的:
C语言中整型(int)与长整型(long long)的范围
C语言中整型(int)与长整型(long long)在标准化输……

Open3D 点云颜色渲染:RGB颜色转换为灰度(Python版本)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 在视频中,Luma表示图像中的亮度(即我们常说的“黑白”或图像的色差部分)。该值通常与色度配对,它表示消色差图像,色度分量则表示颜色信息。将RGB三原色(如三ccd相机的输出)转换为亮度和色度可以实现色度子采样:因……

《Netty》从零开始学netty源码(二十七)之ChannelPipeline.add

当向pipeline中添加handler时可以从头部添加addFirst,可以添加到某个handler的前面addBefore,可以添加到指定handler的后面addAfter,当然也可以添加到链表的末尾addLast,本文分析addLast,源码过程如下: 接下……

GlusterFS(GFS)分布式文件系统

目录
一.文件系统简介
1.文件系统的组成
2.文件系统的作用
3.文件系统的挂载使用
二.GlusterFS概述
1.GlusterFS是什么?
2.GlusterFS的特点
3.GlusterFS术语介绍
3.1 Brick(存储块)
3.2 Volume(逻辑卷)
3.3……

多媒体(视频容量计算)-软件设计(四十二)

真题详解(有向图)-软件设计(四十一)https://blog.csdn.net/ke1ying/article/details/129942490
一、音频概念
声音带宽:
人耳:20Hz-20KHz (说话300-3400Hz)
小于20Hz次声波,大于20KHz是超……

【Unity3d开发】Unity插件之海洋模拟Ocean_Community_Next_Gen

文章目录1、简介2、下载3、安装4、测试5、开发5.1 预制体方式添加Ocean5.2 脚本方式创建Ocean5.3 添加Fps预制体结语1、简介
Next gen iteration of the unity community ocean shader。 Based on ocean community : http://forum.unity3d.com/threads/wanted-ocean-shader.1……

Java题目训练——汽水瓶和查找两个字符串a,b中的最长公共子串

目录
一、汽水瓶
二、查找两个字符串a,b中的最长公共子串 一、汽水瓶
题目描述: 某商店规定:三个空汽水瓶可以换一瓶汽水,允许向老板借空汽水瓶(但是必须要归还)。 小张手上有n个空汽水瓶,她……

蓝桥杯-历届试题-小数第n位

蓝桥杯-历届试题-小数第n位
时间限制:1.0s 内存限制:256.0MB 问题描述   我们知道,整数做除法时,有时得到有限小数,有时得到无限循环小数。   如果我们把有限小数的末尾加上无限多个0,它们就有了统一的……

[C/C++]快速幂精讲

[C/C]快速幂精讲
**一、**假如我们就求a^n(a的n次幂),如果用for循环,时间复杂度就是O(n)了,但是用快速幂就可以降低时间复杂度为O(log n),为什么呢,接下来讲解:
比如我们要求:3^3
注意&#……

Pandas入门实践2 -数据处理

为了准备数据进行分析,我们需要执行数据处理。在本节中,我们将学习如何清理和重新格式化数据(例如,重命名列和修复数据类型不匹配)、对其进行重构/整形,以及对其进行丰富(例如,离散化……

一、lua基础知识1

一、lua 的数据类型
–类型 a1; –number print(type(a)) –number b"HelloWorld"; print(type(b)) –string 两种数据类型 ctrue; print(type(c)) –boolean true 或者 false d print; d("HelloWorld"); print(type(d)); –function类型 ……

二、lua语言基础2

1.lua的类型有哪些?答:lua的数据类型有:number,string,nil function,table,thread,userdata(用户自定义的类型),boolean(布尔类型) 2.什么是尾调用,尾调用有什么优点尾调用:在一个函数的最后一步开始调用另……

quick-cocos2dx-luaUI控件讲解

–MyApp部分 require("config") require("cocos.init") require("framework.init") local MyApp class("MyApp", cc.mvc.AppBase) function MyApp:ctor() MyApp.super.ctor(self) end function MyApp:run() cc.FileUti……

quick-cocos2dx lua语言讲解 (动作,定时器,触摸事件,工程的类的讲解)

–MainScene部分
— display.newScene 创建一个场景 — 在quick里面我们的控件、精灵 一般是加载到场景上的 local MainScene class("MainScene", function() return display.newScene("MainScene") end) function MainScene:ctor() –创……

使用quick-cocos2dx-lua 实现的小游戏(包含碰撞检测,触屏发子弹)

–主界面local MainScene class("MainScene", function()return display.newScene("MainScene")end)ON true;function MainScene:ctor()local bg cc.Sprite:create("main_background.png");bg:setScale(2);bg:setPosition(display.cx,display……

cocos2d-js 中scrollview详解

/****
开头的一些废话:
1、多思考,善于思考
2、懂得变通
3、多多查询API首先复制一段 API中的源码:(UIScrollView.js)这段代码可以看出 scrollview
中的容器是一个node,并且他的位置是:代码最后……

cocos2d-js中的回调函数中世界坐标系和节点坐标系的相互转换

世界坐标系和节点坐标系都是OPENGL 坐标系 1、世界坐标系原点就是屏幕的左下角; 2、节点坐标系的原点就是一个节点的左下角; 3、两个坐标系可以通过已经写好的cocosAPI进行想换转换; 4、所有的节点需要转为一个节点上或者是统一的世界坐标系……

通过JavaScript实现漂浮

<html>
<head><meta http-equiv"Content-Type" content"text/html"; charset"gb2312" /><title>漂浮广告</title><style type"text/css">div{position:absolute;}</style>
</head>
&……

序列动画和图片内存问题

一、帧动画问题 /*** 帧动画总结:* 1、如果精灵进行新建时,加载了纹理,那么setRestoreOriginalFrame可以设置为false或者true* 2、如果精灵新建时,没有加载纹理的话,那么setRestoreOriginalFrame需要设置为false&#……

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注