【嵌入式linux开发】智能家居入门6:最新ONENET,物联网开放平台(QT、微信小程序、MQTT协议、ONENET云平台、旭日x3派)

前言

ONENET云平台更新之后,已经将以前的多协议接入这部分融合进了物联网开放平台,以前在多协议接入里创建的产品和设备,虽然还可以用,但实际上已经过时了,因为新用户根本没有多协议接入这个选项。我的这系列前几篇文章有的也已经失去了实际意义,但是使用mqtt服务器的这两篇(入门三入门四)仍然有效!因为它们使用mqtt服务器和onenet没关系。本篇文章给想接入最新版onenet的小伙伴提供参考。

须知:新版的http协议接入已经跟之前的完全不一样了,看了官方文档和亲身实践,http协议只能上传数据至服务器,已经不能从服务器获取数据了,所以对于需要双向控制的智能家居而言已经没有啥价值了,本文使用MQTT协议接入,响应快、可靠度高,程序的健壮性也已经测试,在板端跑了几天也没有出问题!
本文下位机(旭日x3派运行QT)与服务器的通信使用mqtt协议,而上位机(微信小程序)与服务器的通信使用的是标准http方法!这是因为官方文档中,服务器的API接口就是使用标准HTTP方法实现资源CURD操作,这个在本文第四节有介绍,如果有小伙伴在微信小程序端也使用mqtt协议与服务器通信的话,可以互相交流一下。

***最重要的参考就是官方文档:https://open.iot.10086.cn/doc/v5/fuse/detail/1464
QT端的mqtt报文构建直接使用DS小龙哥的代码
微信小程序在之前的基础上改改即可


最终现象

linux QT智能家居演示


一、ONENET云平台创建产品与设备

这部分直接以视频的形式给出:

需要注意的点:
①数据协议:
这里选择的是OneJson,当然也可以选择数据流,但是它们对应的发送数据和接收数据的topic是不一样的,所以如果想省事直接使用本文代码,那就选择OneJson。
在这里插入图片描述

②新版三元组:
按照视频创建完毕后,进入设备管理的详情中,可以看到后续会用到的三个参数:
在这里插入图片描述


二、使用MQTT客户端软件测试

2.1 测试前的准备

①token:
产品与设备创建完成之后,按照文档指示,需要计算token,在连接时会用到:
在这里插入图片描述
这里的clienid和username就是前面截图中包含的两个参数:设备名称、产品ID,这里的password就是使用官方软件计算生成的token。
接下来视频演示如何计算token:

重点如下:
在这里插入图片描述
纠错:上图中的时间过小,在后面多加随便一个数字既可:2810295937232。
②OneJson数据协议对应的发布、订阅topic:
文档中有明确给出OneJson数据协议(物模型)的发布和订阅topic,如果数据协议选择数据流的小伙伴,在文档的这个界面往后翻翻就可以看到对应的。
在这里插入图片描述
在连上服务器之后,对这两个topic操作就可以上传和接收数据啦!

2.2 测试

下载客户端软件,提取码:q1a1,这是DS小龙哥开源的,填入自己的信息:
在这里插入图片描述
①数据上传测试:
点击登录即可连接上服务器,然后点击发布主题就可以把数据发布到特定的物模型中,可以在onenet云平台中观察是否成功:
在这里插入图片描述
②数据下发测试:
onenet中进入设备调试界面,将fan_ctl设置为true,然后点击属性期望值设置。客户端软件同样连接服务器之后,点击订阅主题,观察是否收到服务器下发的消息:
在这里插入图片描述

在这里插入图片描述
这样双向测试就算完成了,接下来就是下位机与上位机的代码简介。

三、LInux QT代码

既然上面的MQTT客户端软件已经可以实现连接服务器、发布话题、订阅话题了,那说明在自己的界面中编写代码是可行的。如果不知道如何设计界面可以参考本系列第五篇文章
项目的目录结构如下:
在这里插入图片描述
其中mqtt这两个文件是DS小龙哥开源的,具体哪篇文章我也找不见了,我加了一个信号来解析接收到的服务器下发的json数据。这个mqtt代码的好处就是短小精悍,完全够用,避免了使用官方库麻烦的缺点,当然喜欢使用官方qmqtt库的小伙伴可以参考网上的教程进行编译和移植,然后自己编写相关逻辑。
由于找不到原文章,这里就给出原博主的代码:
mqtt.cpp

#include "mqtt.h"

//连接成功服务器回应 20 02 00 00
//客户端主动断开连接 e0 00
const quint8 parket_connetAck[] = {0x20,0x02,0x00,0x00};
const quint8 parket_disconnet[] = {0xe0,0x00};
const quint8 parket_heart[] = {0xc0,0x00};
const quint8 parket_heart_reply[] = {0xc0,0x00};
const quint8 parket_subAck[] = {0x90,0x03};

MQTT_WorkClass::~MQTT_WorkClass()
{
    qDebug()<<"析构函数---TCP";
}

void MQTT_WorkClass::run()
{
    qDebug()<<"执行:run";

    if(timer)
    {
        delete  timer;
        timer=nullptr;
    }
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(EndEvenLoop()));

    socket_type=0;
    //连接到服务器
    ConnectMqttServer(m_ip,m_port);
    //开始事件循环
    StartEvenLoop();

    //初始化mqtt协议
    MQTT_Init();

    //连接mqtt协议
    if(MQTT_Connect(m_MQTT_ClientID.toUtf8().data(),m_MQTT_UserName.toUtf8().data(),m_MQTT_PassWord.toUtf8().data()))
    {
        LogSend("MQTT服务器登录失败.\n");
    }
    else
    {
        LogSend("MQTT服务器登录成功.\n");
    }
}


void MQTT_WorkClass::MQTT_Init(void)
{
    //缓冲区赋值
	mqtt_rxbuf = _mqtt_rxbuf;
    mqtt_rxlen = sizeof(_mqtt_rxbuf);
	mqtt_txbuf = _mqtt_txbuf;
    mqtt_txlen = sizeof(_mqtt_txbuf);
	memset(mqtt_rxbuf,0,mqtt_rxlen);
	memset(mqtt_txbuf,0,mqtt_txlen);
}

/*
函数功能: 登录服务器
函数返回值: 0表示成功 1表示失败
*/
quint8 MQTT_WorkClass::MQTT_Connect(char *ClientID,char *Username,char *Password)
{
    quint8 i,j;
    int ClientIDLen = strlen(ClientID);
    int UsernameLen = strlen(Username);
    int PasswordLen = strlen(Password);
    int DataLen;
	mqtt_txlen=0;
	//可变报头+Payload  每个字段包含两个字节的长度标识
    DataLen = 10 + (ClientIDLen+2) + (UsernameLen+2) + (PasswordLen+2);
	
	//固定报头
	//控制报文类型
    mqtt_txbuf[mqtt_txlen++] = 0x10;		//MQTT Message Type CONNECT
	//剩余长度(不包括固定头部)
	do
	{
        quint8 encodedByte = DataLen % 128;
		DataLen = DataLen / 128;
		// if there are more data to encode, set the top bit of this byte
		if ( DataLen > 0 )
			encodedByte = encodedByte | 128;

猜你喜欢

转载自blog.csdn.net/m0_71523511/article/details/141276130