目录
引言
在上一篇博文中已经介绍了WiFi的使用。今天介绍一下如何使用MQTT协议连接到华为云上。
WS63E对MQTT的支持
WS63E的代码参考直接提供了MQTT的支持,文档介绍见docs/board/WS63V100 MQTT 开发指南.pdf。MQTT 基于开源组件paho.mqtt.c-1.3.12 实现,详细说明请参考官方说明: https://www.eclipse.org/paho/files/mqttdoc/MQTTClient/html/index.html
在网上也找到一位网友的MQTT例子,值得大家参考:GitHub - chenyunbovo/nearlink_ws63_demo: 用于展示WS63的使用示例。
程序修改
华为云平台的设置可以参考我以前的博文:MQTTX连接华为云IoTDA_华为iot mqtt-CSDN博客。在云平台方面,我们仍然使用的是以前配置过的温湿度计。
我在前面的WiFi实例基础上进行修改。主要增加了以下内容:
cpp
#include "MQTTClient.h"
#include "MQTTClientPersistence.h"
#include "osal_debug.h"
#include "MQTTClient.h"
#include "los_memory.h"
#include "los_task.h"
#define QOS 0
#define TIMEOUT 10000L
#define KEEPALIVEINTERVAL 20
#define CLEANSESSION 1
#define USE_SSL 0
#define ADDRESS "tcp://xxxx.iotda-device.cn-north-4.myhuaweicloud.com:1883"
#define USERNAME "xxxxxxx_test1"
#define PASSWORD "xxxxxxxxxxxxxxx"
#define CLIENTID "xxxxxxx_test1_0_0_2024102012"
static MQTTClient client;
void publish(MQTTClient client, char *topic, char *payload) ;
static td_u8 g_wifi_state = WIFI_STA_SAMPLE_INIT;
// Define the on_message callback function to print the content of the messages received by the subscribed topic
static int on_message(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
UNUSED(context);
UNUSED(topicLen);
char *payload = message->payload;
printf("Received `%s` from `%s` topic \n", payload, topicName);
MQTTClient_freeMessage(&message);
MQTTClient_free(topicName);
return 1;
}
int mqtt_init(void)
{
int rc;
MQTTResponse ret;
MQTTClient_init_options ops;
ops.do_openssl_init = 0;
MQTTClient_global_init(&ops);
MQTTClient_createOptions create_opts = { {'M', 'Q', 'C', 'O'}, 0, MQTTVERSION_5 };
rc = MQTTClient_createWithOptions(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_DEFAULT, NULL, &create_opts);
if (rc != MQTTCLIENT_SUCCESS) {
printf("Failed to create mqtt client, return code %d\n", rc);
return -1;
}
// 设置MQTT消息接受回调函数
MQTTClient_setCallbacks(client, NULL, NULL, on_message, NULL);
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer5;
conn_opts.username = USERNAME;
conn_opts.password = PASSWORD;
MQTTProperties props = MQTTProperties_initializer;
MQTTProperties willProps = MQTTProperties_initializer;
ret = MQTTClient_connect5(client, &conn_opts, &props, &willProps);
if (ret.reasonCode == MQTTREASONCODE_SUCCESS) {
printf("Connected to MQTT Broker!\n");
} else {
printf("failed to connect to MQTT Broker, return code %d\n", (int8_t)ret.reasonCode);
MQTTResponse_free(ret);
return -1;
}
MQTTResponse_free(ret);
char msg[500];
sprintf_s(msg, 499, "{ \
\"services\": [ \
{ \
\"serviceId\": \"温湿度\", \
\"properties\": { \
\"温度\": %d, \
\"湿度\": %d \
} \
} \
] \
}", 12, 76);
for (int i = 0; i < 5; i++) {
publish(client, "$oc/devices/XXXX_test1/sys/properties/report",
msg);
(void)osDelay(1000);
}
MQTTResponse_free(ret);
return 0;
}
void publish(MQTTClient client, char *topic, char *payload)
{
MQTTClient_message message = MQTTClient_message_initializer;
message.payload = payload;
message.payloadlen = strlen(payload);
message.qos = QOS;
message.retained = 0;
MQTTClient_deliveryToken token;
MQTTClient_publishMessage5(client, topic, &message, &token);
MQTTClient_waitForCompletion(client, token, TIMEOUT);
printf("Send `%s` to topic `%s` \n", payload, topic);
}
td_s32 example_sta_function(td_void)
{
td_char ifname[WIFI_IFNAME_MAX_SIZE + 1] = "wlan0"; /* 创建的STA接口名 */
wifi_sta_config_stru expected_bss = {0}; /* 连接请求信息 */
struct netif *netif_p = TD_NULL;
td_u32 wait_count = 0;
/* 创建STA接口 */
if (wifi_sta_enable() != 0) {
return -1;
}
PRINT("%s::STA enable succ.\r\n", WIFI_STA_SAMPLE_LOG);
do {
(void)osDelay(1); /* 1: 等待10ms后判断状态 */
if (g_wifi_state == WIFI_STA_SAMPLE_INIT) {
............
} else if (g_wifi_state == WIFI_STA_SAMPLE_GET_IP) {
if (example_check_dhcp_status(netif_p, &wait_count) == 0) {
mqtt_init();
break;
}
wait_count++;
}
} while (1);
return 0;
}
我在WiFi连上路由器并获得IP后启动了MQTT客户端。客户端连接到华为IoT云,然后定时发布了温湿度信息。绝大多数内容在前面的博文中都已经介绍了,这里就不再赘述了。
测试结果
程序烧写之后,登录华为云的控制台,就可以看到上传的温湿度信息。
设备侧的部分日志如下:
bash
+NOTICE:CONNECTED
drv_soc_ioctl ioctl_cmd->cmd=6.
Srv:548:recive event = 2
APP|[WIFI_STA_SAMPLE]::Connect succ!.
APP|[WIFI_STA_SAMPLE]::DHCP start.
xo update temp:4,diff:0,xo:0x3083c
APP|[WIFI_STA_SAMPLE]::STA DHCP success.
Connecting to serverURI bde4cbe7aa.st1.iotda-device.cn-north-4.myhuaweicloud.com:1883 with MQTT ver
New socket 0 for bde4cbe7aa.st1.iotda-device.cn-north-4.myhuaweicloud.com:1883, port 1883
0 66991e97a559ef622669048e_test1_0_0_2024102012 -> CONNECT version 5 clean: 0 (0)
Posting connack semaphore for client 66991e97a559ef622669048e_test1_0_0_2024102012
0 66991e97a559ef622669048e_test1_0_0_2024102012 <- CONNACK rc: 0
Connected to MQTT Broker!
0 66991e97a559ef622669048e_test1_0_0_2024102012 -> PUBLISH rc: 0
Send `{ "services": [ { "serviceId": "温湿度", "properties": { "温度": 12, "湿度": 76 } } ] }` to topic `$oc/devices/66991e97a559ef622669048e_test1/sys/properties/report`
APP|[SYS INFO] mem: used:138600, free:223804; log: drop/all[0/0], at_recv 0.
0 66991e97a559ef622669048e_test1_0_0_2024102012 -> PUBLISH rc: 0
Send `{ "services": [ { "serviceId": "温湿度", "properties": { "温度": 12, "湿度": 76 } } ] }` to topic `$oc/devices/66991e97a559ef622669048e_test1/sys/properties/report`
APP|[SYS INFO] mem: used:138600, free:223804; log: drop/all[0/0], at_recv 0.
0 66991e97a559ef622669048e_test1_0_0_2024102012 -> PUBLISH rc: 0
Send `{ "services": [ { "serviceId": "温湿度", "properties": { "温度": 12, "湿度": 76 } } ] }` to topic `$oc/devices/66991e97a559ef622669048e_test1/sys/properties/report`
APP|[SYS INFO] mem: used:138600, free:223804; log: drop/all[0/0], at_recv 0.
0 66991e97a559ef622669048e_test1_0_0_2024102012 -> PUBLISH rc: 0
Send `{ "services": [ { "serviceId": "温湿度", "properties": { "温度": 12, "湿度": 76 } } ] }` to topic `$oc/devices/66991e97a559ef622669048e_test1/sys/properties/report`
APP|[SYS INFO] mem: used:138600, free:223804; log: drop/all[0/0], at_recv 0.
结语
WS63E在WiFi和MQTT的编程和OpenHarmony差不多,所以遇到的问题并不多。WS63E采用的是CMake系统,比OpenHarmony的GN要更熟悉一些。但是它也有个问题,就是有时候稍微修改一下C语言文件,即使不涉及头文件的修改,系统也会从头编译700多个文件,时间偏长,估计是系统在计算文件依赖方面有一些问题。