本帖最后由 Jack_tang 于 2021-3-5 11:20 编辑
最近在学习ESP8266的MQTT事,我通过MQTT连接到腾讯云MQTT服务器。现在ESP8266可以订阅并接收来自腾讯云MQTT的信息,但是在使用mqtt发布上报信息给腾讯云时出现了问题。
上报信息的JOSN格式:"{\"method\":\"report\",\"clientToken\":\"xxxxx-8gauvcWJrb\",\"params\":{\"switch_1\": 1}}"
但是腾讯云无法接收到完成的上报信息,因为我使用在线调试只能看到report_reply消息,但是无法查看到report消息。而我用MQTT.fx软件模拟时,当我只发送{"method": "report"}时会出现这样的现在。但是当我发送完整的JOSN上报信息时就不会只有report_reply消息。
MQTT.fx模拟正常的JOSN上报数据:
MQTT.fx模拟异常的JOSN上报数据:
异常JOSN数据
目前ESP8266使用以下代码,将JOSN数据上报给腾讯云会出现和MQTT.fx模拟异常的JOSN上报数据现象。
- #define TEST_SW1_REPORT_OFF "{"method":"report","clientToken":"MBN7N5MMO8-8gauvcWJrb","params":{"switch_1": 0}}"
复制代码- void mqttDataCb(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t data_len)
- {
- char *topicBuf = (char*)os_zalloc(topic_len+1),
- *dataBuf = (char*)os_zalloc(data_len+1);
- uint8_t res = 0;
- static uint8_t flag = 0;
- MQTT_Client* client = (MQTT_Client*)args;
- //===========如果数据接收出现丢失,应该使用环形缓冲区来保存没有来得及处理的数据================
- os_memcpy(topicBuf, topic, topic_len);
- topicBuf[topic_len] = 0;
- os_memcpy(dataBuf, data, data_len);
- dataBuf[data_len] = 0;
- INFO("Receive topic: %s, data: %s \r\n", topicBuf, dataBuf);
- //===解析JOSN数据====
- res = Parse_Josn_data(dataBuf,&sw_status);
- if(res == JOSN_OK) //成功获取到腾讯云发的“智能插座”MQTT的JOSN并解析
- {
- //====执行命令========
- smartSW_action.Control(sw_status);
- if(flag == 1)
- {
- flag = 0;
- MQTT_Publish(client, MQTT_UP_TOPIC, TEST_SW2_REPORT_OFF, os_strlen(TEST_SW2_REPORT_OFF) + 1, 0, 0);
- INFO("flag = 1\n");
- INFO(TEST_SW2_REPORT_OFF)
- INFO("\n");
- }
- else
- {
- flag = 1;
- MQTT_Publish(client, MQTT_UP_TOPIC, TEST_SW2_REPORT_ON, os_strlen(TEST_SW2_REPORT_ON) + 1, 0, 0);
- INFO("flag = 0\n");
- INFO(TEST_SW2_REPORT_ON)
- INFO("\n");
- }
- }
- os_free(topicBuf);
- os_free(dataBuf);
- }
复制代码
解决方法及分析过程:
原因:多发了一个字节的00数据。其实就是在发送JOSN字符串时,考虑了字符串的结束标志'\0'
1. 通过WireShark抓包工具抓取MQTT的PUBLISH报文数据包
WireShark抓包PUBLISH消息
数据:
30 57 00 29 24 74 68 69 6e 67
2f 75 70 2f 70 72 6f 70 65 72 74 79 2f 4d 42 4e
37 4e 35 4d 4d 4f 38 2f 53 6d 61 72 74 5f 53 57
30 30 31 7b 22 6d 65 74 68 6f 64 22 3a 22 72 65
70 6f 72 74 22 2c 22 70 61 72 61 6d 73 22 3a 7b
22 73 77 69 74 63 68 5f 32 22 3a 20 30 7d 7d
2. 在ESP8266的SDK开发源代码中获取到的PUBLISH消息数据包内容。
串口打印PUBLISH消息
数据:
30 58 00 29 24 74 68 69 6e 67 2f 75 70 2f 70 72 6f 70 65 72 74 79 2f 4d 42 4e 37 4e 35 4d 4d 4f 38 2f 53 6d 61 72 74 5f 53 57 30 30 31 7b 22 6d 65 74 68 6f 64 22 3a 22 72 65 70 6f 72 74 22 2c 22 70 61 72 61 6d 73 22 3a 7b 22 73 77 69 74 63 68 5f 32 22 3a 20 31 7d 7d 00
总结:
通过比较两个数据包的内容很容易发现,在串口输出的信息中多了一个字节的00数据。再结合ESP8266 SDK开发中的源代码,在调用MQTT_Publish()函数中发送的时多了一个字节(考虑到了字符串结束标志....)。
即将以下代码
- MQTT_Publish(client, MQTT_UP_TOPIC, TEST_SW2_REPORT_ON, os_strlen(TEST_SW2_REPORT_ON) + 1, 0, 0);
复制代码
修改为正确的代码
- MQTT_Publish(client, MQTT_UP_TOPIC, TEST_SW2_REPORT_ON,os_strlen(TEST_SW2_REPORT_ON),0,0);
复制代码
|