文章目录[隐藏]
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 下载地址:链接
版权声明:本文为CSDN博主「嵌入式up笔记」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_45396672/article/details/122788684
暂无评论