一、问题描述
基于文章
<单片机stm32使用rt-thread软件包at-device的AT指令>
,测试发现使用MQTT AT指令发送主题信息时,直接发送字符串正常,发送json字符串时出问题,提示错误。数据格式的区别如下:
"%s"//正常发送
"\"%s\""//提示错误有,发送失败
二、解决办法
查看文档,发现指令
AT+MQTTPUBRAW:发布 MQTT 消息(二进制),
该指令格式如下:
AT+MQTTPUBRAW=<LinkID>,<"topic">,<length>,<qos>,<retain>
参数:
<LinkID>:当前仅支持 link ID 0。
<topic>:MQTT topic,最大长度:128 字节。
<length>:MQTT 消息长度,不同 ESP 设备的最大长度不同:
对于 ESP32 设备:最大长度受到可利用内存的限制;
对于 ESP8266 设备,最大长度受到可利用内存和 MQTT_BUFFER_SIZE_BYTE 宏的限制。该宏的默认值为 512,可在 build.py menuconfig 中设置它的值,以此更改对最大长度的限制。该宏的值 = 消息的最大长度 + MQTT 报头长度(取决于 topic 名称的长度)。
<qos>:发布消息的 QoS,参数可选 0、1、或 2,默认值:0。
<retain>:发布 retain。
三、代码修改
修改代码如下:
#include <rtthread.h>
#include <rtdevice.h>
#include <at.h>
#include <at_device.h>
#include <at_log.h>
#define AT_SEND_MQTT_CMD(client, resp, cmd) \
do { \
(resp) = at_resp_set_info((resp), 256, 0, 10 * RT_TICK_PER_SECOND); \
if (at_obj_exec_cmd((client), (resp), (cmd)) < 0) \
{ \
result = -RT_ERROR; \
goto __exit; \
} \
} while(0) \
//mqtt 发布主题,测试不同的信息,看是否可以正常发布json信息
static int mqtt_at_send(int argc, char **argv)
{
rt_uint8_t retry_num=3;
at_response_t resp = RT_NULL;
int result=-RT_ERROR;
int i=0;
at_client_t client=RT_NULL;
struct at_device *device = RT_NULL;
device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, "esp0");
if(device == RT_NULL)
{
rt_kprintf("no find esp0.\r\n");
return -1;
}
client=device->client;
resp = at_create_resp(128, 0, 10 * RT_TICK_PER_SECOND);
if (resp == RT_NULL)
{
rt_kprintf("no memory for resp create.\r\n");
return -1;
}
while (retry_num--)
{
if(argc == 1)//字符串发送
{
/*mqtt pubTopic*/
//AT_SEND_MQTT_CMD(client, resp, "AT+MQTTPUB=0,\"testTopic1\",\"{\"testTopic1\":\"data_test1\"}\",0,0");
AT_SEND_MQTT_CMD(client, resp, "AT+MQTTPUB=0,\"testTopic1\",\"test123456\",0,0");
}
else if(argc == 2)//字符串发送
{
AT_SEND_MQTT_CMD(client, resp, "AT+MQTTPUB=0,\"testTopic1\",\"{key0:data_test1}\",0,0");
}
else if(argc == 3)//二进制发送信息
{
// if (at_obj_exec_cmd(client, at_resp_set_info(resp, 128, 0, 20 * RT_TICK_PER_SECOND),
// "AT+MQTTPUB=0,\"testTopic1\",\"%s%s\",0,0", argv[1], argv[2]) != RT_EOK)
// {
// LOG_D("device send failed.\r\n");
// }
AT_SEND_MQTT_CMD(client, resp, "AT+MQTTPUBRAW=0,\"testTopic1\",30,0,0");
/* show pubTopic message */
// for (i = 0; i < resp->line_counts - 1; i++)
// {
// LOG_D("%s", at_resp_get_line(resp, i + 1));
// }
rt_device_write(client->device,0,"{\"key0\":\"data_test1\",\"key1\":1}",rt_strlen("{\"key0\":\"data_test1\",\"key1\":1}"));
}
/* show pubTopic message */
for (i = 0; i < resp->line_counts - 1; i++)
{
LOG_D("%s", at_resp_get_line(resp, i + 1));
}
//rt_thread_mdelay(5000);
/* initialize successfully */
result = RT_EOK;
break;
__exit:
if (result != RT_EOK)
{
rt_thread_mdelay(1000);
rt_kprintf("%s device send retry...", device->name);
}
}
if (resp)
{
at_delete_resp(resp);
}
if(result != RT_EOK)
{
return -1;
}
return 0;
}
MSH_CMD_EXPORT(mqtt_at_send, esp8266 mqtt at send message);
static int esp8266_mqtt_at_init(void)
{
rt_uint8_t retry_num=3;
at_response_t resp = RT_NULL;
int result=-RT_ERROR;
int i=0;
at_client_t client=RT_NULL;
struct at_device *device = RT_NULL;
device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, "esp0");
if(device == RT_NULL)
{
rt_kprintf("no find esp0.\r\n");
return -1;
}
client=device->client;
resp = at_create_resp(128, 0, 10 * RT_TICK_PER_SECOND);
if (resp == RT_NULL)
{
rt_kprintf("no memory for resp create.\r\n");
return -1;
}
while (retry_num--)
{
/* mqtt para */
AT_SEND_MQTT_CMD(client, resp, "AT+MQTTUSERCFG=0,1,\"123cli\",\"\",\"\",0,0,\"\"");
rt_thread_mdelay(3000);
/* mqtt connect para*/
AT_SEND_MQTT_CMD(client, resp, "AT+MQTTCONNCFG=0,120,0,\"lwt_topic\",\"lwt_msg\",0,0");
rt_thread_mdelay(3000);
/* mqtt connect */
AT_SEND_MQTT_CMD(client, resp, "AT+MQTTCONN=0,\"47.107.99.203\",1883,1");
/* show connect info */
for (i = 0; i < resp->line_counts - 1; i++)
{
rt_kprintf("%s", at_resp_get_line(resp, i + 1));
}
//rt_thread_mdelay(5000);
/*mqtt subTopic*/
AT_SEND_MQTT_CMD(client, resp, "AT+MQTTSUB=0,\"testTopic1\",0");
rt_thread_mdelay(3000);
/* initialize successfully */
result = RT_EOK;
break;
__exit:
if (result != RT_EOK)
{
rt_thread_mdelay(1000);
rt_kprintf("%s device initialize retry...", device->name);
}
}
if (resp)
{
at_delete_resp(resp);
}
if(result != RT_EOK)
{
return -1;
}
return 0;
}
//mqtt 参数初始化,订阅主题
void mqtt_at_init(int argc, char **argv)
{
int result=-1;
result = esp8266_mqtt_at_init();
if (result!=RT_EOK)
{
rt_kprintf("mqtt at cmd err.\r\n");
}
}
MSH_CMD_EXPORT(mqtt_at_init, esp8266 mqtt at cmd demo);
四、测试结果
欢迎关注个人公众号:嵌入式学习与实践