LiteOS + PahoMQTT 连接华为云

Posted JeckXu666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LiteOS + PahoMQTT 连接华为云相关的知识,希望对你有一定的参考价值。

文章目录

LiteOS + PahoMQTT 连接华为云

一、前言

使用小熊派连接华为云平台,实现数据的上传与下放,软件层使用 LiteOS 做系统支撑,移植 PahoMQTT 做通讯

二、平台端配置

2.1 创建 IOTDA 云产品

进入华为云控制台,进入 IOTDA 中,创建一个产品:

2.2 定义产品模型

进入到产品,创建产品模型

2.3 创建属性和命令

创建模型的温度接受属性

创建模型的 LED 控制命令

2.4 添加设备

进入设备控制台,添加设备:

添加后会生成设备ID和设备密钥,这两个很重要,我们要保存好,后面要使用到

三、设备端配置

3.1 设备端配置

准备小熊派,建立工程,移植 LiteOS,这里我使用的是我之前移植的一个 MDK LiteOS 项目,同时移植了 LVGL,基于这个项目继续配置 esp8266

项目地址:链接

开启工程 LUART,配置 LUART 参数同时开启 DMA:

移植 Paho MQTT 工程代码:

Paho MQTT 开源地址:Github ,将 MQTTPacket 下面的 SRC 源码移植进去

关于代码移植我们只需要关注 transport.c 和 .h 文件,这两个文件是 MQTT 的物理层接口,这里我移植串口发送进去,使用 信号量+DMA 的方式进行开发,防止串口资源使用冲突,同时进一步提高串口速率,部分代码如下:

具体代码可以参考我后面完整的工程代码:

这里是 MQTT 的底层代码,除此之外我们建立一个 ESP8266 文件用于发送数据到 ESP,配置 WIFI 模块,主要就是设置 WIFI 模块工作模式,连接 WIFI 以及连接华为云服务平台,参考代码如下,具体代码见实际工程:

连接 WIFI 主要就是 WIFI 的账号和密码,连接服务平台的话则需要服务平台的域名和端口,域名获取端口在控制台的 IOTDA 接口下面

接口如下,这里使用明文 MQTT 接口:

放到代码如下位置:

3.2 连接华为云

下面创建 huawei.c 和 .h 文件用于连接华为云进行数据上报和下发:

根据 ID 和用户名以及密码调用 MQTT 接口连接华为云,这三个数据通过生成器生成,生成器下载地址:下载地址

将ID、用户名、密钥都填写到代码里面

然后调用 MQTT 接口连接

uint8_t huawei_connect()

		uint32_t len;

		printf("进入连接云服务器函数\\r\\n");
		memset(buf,0,buflen);
		MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
		data.MQTTVersion = 3;
		data.clientID.cstring = ClientID;
		data.keepAliveInterval = 120;
		data.cleansession = 1;	
		data.username.cstring = Username;	
		data.password.cstring = Password;
		len = MQTTSerialize_connect(buf, buflen, &data); 
		transport_sendPacketBuffer(3,buf, len);				//发送连接请求
		
		unsigned char sessionPresent, connack_rc;
		do
		
				while(MQTTPacket_read(buf, buflen, transport_getdata) != CONNACK)
				
						osDelay(10);
				
		
		while(MQTTDeserialize_connack(&sessionPresent, &connack_rc, buf, buflen) != 1 || connack_rc != 0);
		
		if(connack_rc != 0)
		
			printf("connack_rc:%uc\\r\\n",connack_rc);
		else			
			printf("Connect Success!\\r\\n");		
		return 0;

3.3 上传数据

使用 Paho MQTT 到华为云的上传数据分为两步,第一步订阅主题,主题格式如下

#define POST_TOPIC "$oc/devices/devices_id/sys/properties/report"

devices_id 填写设备 ID,然后定义一个数据上传格式

#define PAY_LOAD "\\"services\\":[\\"service_id\\":\\"Home\\",\\"properties\\":\\"Temp\\":\\"%d\\",\\"eventTime\\":\\"NULL\\"]"

service_id 是产品添加时设置 Home

Temp 是产品的属性,然后调用宏接口填写数据:

void test_post(void)

	int len = 0;
	int rc = 0;
	unsigned char topic[]= POST_TOPIC;
	unsigned char payload[100]=0;
	
	sprintf((char*)payload,PAY_LOAD,19);
	
	memset(buf,0,buflen);
	MQTTString topicString = MQTTString_initializer;
	topicString.cstring = (char *)topic;
	
	len=MQTTSerialize_publish(buf,buflen,0,0,0,0,topicString,payload,strlen((char *)payload));
	
	rc = transport_sendPacketBuffer(3, buf, len);
	if(!rc)
		printf("Send OK!\\r\\n");
	else
		printf("Send WRONG!\\r\\n");

编写完成后,我们在 mian 文件中创建相关任务,调用代码:

编译下载程序,在华为云的实验平台上进入设备调试模式,观察数据上传情况,可以看到数据正常上传:

3.4 接受命令

接受命令主要分为三步

第一步先订阅命令接受主题并读返回数据检验有没有订阅成功

	topicString.cstring = GET_TOPIC;
	len = MQTTSerialize_subscribe(buf, buflen, 0, msgid, 1, &topicString, &req_qos);

	rc = transport_sendPacketBuffer(3, buf, len);
	if (MQTTPacket_read(buf, buflen, transport_getdata) == SUBACK) 	/* wait for suback */
	
		unsigned short submsgid;
		int subcount;
		int granted_qos;

		rc = MQTTDeserialize_suback(&submsgid, 1, &subcount, &granted_qos, buf, buflen);
		if (granted_qos != 0)
		
			printf("granted qos != 0, %d\\n", granted_qos);
		
	

订阅主题如下:

#define GET_TOPIC "$oc/devices/61f4c4b0de9933029be530e7_ESP8266/sys/commands/#"

具体格式可以查看华为云手册

订阅后就是一个死循环来循环读取订阅主题发送的命令,然后解析命令,将接受的命令打印出来,这里是 JSON 格式的返回数据,想进一步处理的话可以使用 CJSON

		if (MQTTPacket_read(buf, buflen, transport_getdata) == PUBLISH)
		
			unsigned char dup;
			int qos;
			unsigned char retained;
			unsigned short msgid;
			int payloadlen_in;
			unsigned char* payload_in;
			int rc;
			MQTTString receivedTopic;

			rc = MQTTDeserialize_publish(&dup, &qos, &retained, &msgid, &receivedTopic,
					&payload_in, &payloadlen_in, buf, buflen);
			
			id = &receivedTopic.lenstring.data[strlen("$oc/devices/61f4c4b0de9933029be530e7_ESP8266/sys/commands/request_id=")];
			
			memcpy(&ropicString.cstring[strlen("$oc/devices/61f4c4b0de9933029be530e7_ESP8266/sys/commands/response/request_id=")],
						id,
						strlen("0b2e0999-55a1-43f9-a432-d46a8d58ae7e")
						);

			printf("message arrived %.*s\\r\\n", payloadlen_in, payload_in);

		

接受到数据后,要返回命令下发成功信息,先将接受的 ID 复制到新主题上,这个操作就是上个代码的 ropicString 字符串操作部分,然后我们根据主题发送成功信息

		memset(buf,0,buflen);
		printf("publishing reading\\r\\n");
		
		len = MQTTSerialize_publish(buf, buflen, 0, 0, 0, 0, ropicString, (unsigned char*)payload, payloadlen);
		rc = transport_sendPacketBuffer(3, buf, len);

代码编写成功后在任务中调用该函数:

编译下载代码,我们在云端打开设备调试,给设备发送命令:

可以看到命令发送成功,接受返回的命令也成功了

小熊派的串口也打印出接受到的数据:

到此使用 LiteOS 移植 PahoMQTT 对华为云进行数据收发基本完成

四、代码链接

GitHub 工程地址:链接

CSDN 下载地址:链接

以上是关于LiteOS + PahoMQTT 连接华为云的主要内容,如果未能解决你的问题,请参考以下文章

华为云数据转发与分析

华为云技术分享小熊派华为物联网操作系统LiteOS裸机驱动移植02-LCD驱动移植及使用

深入学习华为云IOT云平台与LiteOS轻量级物联网系统

深入学习华为云IOT云平台与LiteOS轻量级物联网系统

华为云技术分享漫谈LIteOS-物联网操作系统介绍

华为如何打造物联网开发新平台—DevCloud和LiteOS的完美结合