ESP8266 mqtt OS2.0调试源码
mqtt内部原理,请自行查阅相关资料。至于为什么不想说这些东西,请查看下图1。
我的代码实在官网Demo下,发现一些问题,经过修改完善的。下面直接看代码。
这个代码就是一个任务,包括初始化以及发布消息。我是使用了一个队里,有消息来了,就把消息发送出去。其中MQTT_BROKER是服务器IP地址。
typedef struct esp_mqtt_msg_type {
long unsigned int len;
char allData[1460];
} xMessage;
xMessage pMsg_temp;
static void mqtt_client_thread(void* pvParameters)
{
vTaskSuspend(MQTTSubscribe_Monitor_handle);
printf("mqtt client thread starts\n");
// MQTTClient mqtt_client;
Network network;
unsigned char sendbuf[2048], readbuf[2048] = {0};
int rc = 0, count = 0;
MQTTPacket_connectData connectData = MQTTPacket_connectData_initializer;
pvParameters = 0;
NetworkInit(&network);
MQTTClientInit(&mqtt_client, &network, 30000, sendbuf, sizeof(sendbuf), readbuf, sizeof(readbuf));
for(;;){
while (wifi_station_get_connect_status() != STATION_GOT_IP) {
vTaskDelay(1000 / portTICK_RATE_MS);
}
char* address = MQTT_BROKER;
connectData.MQTTVersion = 3;
connectData.clientID.cstring = "admin";
connectData.username.cstring = "admin";
connectData.password.cstring = "public";
connectData.keepAliveInterval = 40;
connectData.cleansession = true;
//底层的TCP开始连接
if ((rc = NetworkConnect(&network, address, MQTT_PORT)) != 0) {
printf("Return code from network connect is %d\n", rc);
}
#if defined(MQTT_TASK)
if ((rc = MQTTStartTask(&mqtt_client)) != pdPASS) {
printf("Return code from start tasks is %d\n", rc);
} else {
printf("Use MQTTStartTask\n");
}
#endif
//连接MQTT服务器
if ((rc = MQTTConnect(&mqtt_client, &connectData)) != 0) {
printf("Return code from MQTT connect is %d\n", rc);
} else {
printf("MQTT Connected\n");
}
vTaskResume(MQTTSubscribe_Monitor_handle);
xQueueReset(xQueue_mqtt_pb_handle);
while (1) {
pMsg_Data_Typedef pMsg;
xQueueReceive(xQueue_mqtt_pb_handle, &pMsg, portMAX_DELAY);
pMsg_temp.len=pMsg.len;
memcpy(pMsg_temp.allData,pMsg.addr,pMsg.len);
MQTTMessage message;
message.qos = QOS2;
message.retained = 0;
message.payload = pMsg_temp.allData;
message.payloadlen =(long unsigned int)pMsg_temp.len;
rc = MQTTPublish(&mqtt_client, "ESP8266/sample/pub", &message);
printf("%d ",pMsg_temp.len);
printf("%d\r\n",rc);
if(rc==SUCCESS){
uint8_t CMD_Buf[]={0x43,0x4F,0x44,0x45,0x2E,0x01,0x00};
server_recv_handler(CMD_Buf,7);
}
if (rc != 0) {
break;
}
}
network.disconnect(&network);
}
printf("mqtt_client_thread going to be deleted\n");
vTaskDelete(NULL);
return;
}
这个是订阅注册回调函数
static void MessageArrived(MessageData* data)
{
printf("Message arrived payload: %s\r\n", data->message->payload);
printf("Message arrived payloadlen: %d\r\n", data->message->payloadlen);
xRingbufferSend(spi_slave_tx_ring_buf, (void *) data->message->payload,data->message->payloadlen, portMAX_DELAY);
}
大家发现没有,我上面还确实接收订阅的代码。其实就是MQTTSubscribe这个函数。在Demo里,它是直接放在上面任务初始化里。我后面调试发现,得每隔一段时间去调用这个函数才能接收到数据。如果只是初始化一次,回调函数是用不了的。然后我根据这个情况,重新定义了一个监视任务。
static void MQTTSubscribe_Monitor(void* pvParameters){
int rc = 0;
for(;;)
{
MQTTSubscribe(&mqtt_client, "ESP8266/sample/sub", QOS2, MessageArrived);
vTaskDelay(1000 / portTICK_RATE_MS);
}
}
这样的话,每隔1S就会调用一次。经过调试就可以用啦。
我的服务器是搭建在阿里云上的,这个可以提供一个搭建服务器的包。里面包括了安装步骤。需要的自行下载。
服务器搭建安装包