ESP8266 MQTT
最近接了个小项目
ESP8266使用SDK来开发
1,airkiss配网(微信)
2,mqtt
3,http远程升级程序
4串口接收的数据直接发给mqtt,mqtt接收的直接发给串口
2,mqtt
3,http远程升级程序
4串口接收的数据直接发给mqtt,mqtt接收的直接发给串口
经分析
选择RTOS_SDK2.0进行开发
乐鑫的MQTT是采用github paho embedded-c库版本来修改的
经过半颗心脏大神的CSDN
https://blog.csdn.net/xh870189248/article/details/81181707
发现MQTT有些问题,可以看相应的issue
https://github.com/espressif/ESP8266_RTOS_SDK/issues/292
我这里没有测试到有bcn_timerout问题,应该路由器问题已经解决了。
然后我根据issue,将MQTTClient库里面的MQTTRun修改了一下(还是不建议。。因为改了就会将任务delete掉了,就必须重复调starttask了)
重新./make_lib.sh mqtt 再编译(注意别make all lib了,不然某些库会重定义一些变量)
void MQTTRun(void* parm) { Timer timer; MQTTClient* c = (MQTTClient*)parm; int rc = 0; TimerInit(&timer); while (1) { TimerCountdownMS(&timer, 500); // Don't wait too long if no traffic is incoming #if defined(MQTT_TASK) MutexLock(&c->mutex); #endif rc = cycle(c, &timer); #if defined(MQTT_TASK) MutexUnlock(&c->mutex); #endif if (rc < 0){ break; } } vTaskDelete(NULL); return; }
注意点如下:
1.心跳时间最好设成10-15S,太长会忽然断掉的
2.定期检查 isconnect变量,若有问题则退出
3.MqttStartTask别重复调用了,查看了一下是开启任务的
基本逻辑如下:
static void ICACHE_FLASH_ATTR mqtt_task(void *pvParameters) { uint8_t wait_ip_cont=0; uint8_t mqtt_err_cont=0; uint8_t mqtt_reconnect_flag=0; bool task_first_flag = false; MQTTClient client; Network network; unsigned char sendbuf[512], readbuf[512] = {0}; int rc = 0, count = 0; MQTTPacket_connectData connectData = MQTTPacket_connectData_initializer; pvParameters = 0; NetworkInit(&network); MQTTClientInit(&client, &network, 30000, sendbuf, sizeof(sendbuf), readbuf, sizeof(readbuf)); char* address = MQTT_BROKER; if(storage_list.ssid[0]==0&&storage_list.passowrd[0]==0)//没ip { wifi_set_mode(STATION_MODE); smartconfig_stop(); //vTaskDelay(2000/portTICK_RATE_MS); smartconfig_set_type(SC_TYPE_ESPTOUCH_AIRKISS); //SC_TYPE_ESPTOUCH,SC_TYPE_AIRKISS,SC_TYPE_ESPTOUCH_AIRKISS smartconfig_start(smartconfig_done); printf("\r\n smartconfig \r\n"); } else { wifi_set_mode(STATION_MODE); start_wifi_station(storage_list.ssid, storage_list.passowrd); printf("\r\n start_wifi_station \r\n"); } for(;;) { printf("\r\n waitforip \r\n"); vTaskDelay(3000 / portTICK_RATE_MS); wait_ip_cont++; if(storage_list.ssid[0]==0&&storage_list.passowrd[0]==0)//没ip { mqtt_task_status=mqtt_task_status_WAITMARTLINK; //if(wait_ip_cont==60)system_restart(); } else { mqtt_task_status=mqtt_task_status_WAITWIFI; if(wait_ip_cont==60)system_restart();//60秒没连上路由器 } if(true==wifi_station_connected()) { mqtt_task_status=mqtt_task_status_WAITM2M; wait_ip_cont=0; mysntp_init(); printf("mqtt client thread starts\n"); //ota_start(); if(mqtt_err_cont++==4) { printf( "\r\n mqtt_err_cont 4 restart\r\n"); system_restart(); } if ((rc = NetworkConnect(&network, address, MQTT_PORT)) != 0) { printf("Return code from network connect is %d\n", rc); continue; } connectData.MQTTVersion = 3; connectData.clientID.cstring = "ESP8266_sample"; connectData.clientID.cstring = MQTT_CLIENTID; connectData.username.cstring = MQTT_USERNAME; connectData.password.cstring = MQTT_PASSWORD; connectData.keepAliveInterval = MQTT_KEEPALIVEINTERVAL; connectData.cleansession = true; if ((rc = MQTTConnect(&client, &connectData)) != 0) { printf("Return code from MQTT connect is %d\n", rc); network.disconnect(&network); continue;//重复等待 } else { printf("MQTT Connected\n"); } if(task_first_flag==false)//TASK只运行一次 { task_first_flag=true; if ((rc = MQTTStartTask(&client)) != pdPASS) { printf("Return code from start tasks is %d\n", rc); network.disconnect(&network); continue;//重复等待 } else { printf("Use MQTTStartTask\n"); } } if ((rc = MQTTSubscribe(&client,MQTT_SUBSCRIBE, QOS0, messageArrived)) != 0) { printf("Return code from MQTT subscribe is %d\n", rc); network.disconnect(&network); continue;//重复等待 } else { printf("MQTT subscribe to topic \"ESP8266/sample/pub\"\n"); } mqtt_task_status=mqtt_task_status_IDLE; mqtt_err_cont=0; for(;;) { if(false == wifi_station_connected()) break; if(mqtt_task_cont++==50003)mqtt_task_cont=0; vTaskDelay(30/portTICK_RATE_MS); switch(mqtt_task_status) { case mqtt_task_status_IDLE: { if(mqtt_task_cont%200==2) { sntp_gettime(); /* MQTTMessage message; char payload[30]=""; message.qos = QOS0; message.retained = 0; message.payload = payload; sprintf(payload, "message number %d", ++count); message.payloadlen = strlen(payload); if ((rc = MQTTPublish(&client, "ESP8266/sample/pub", &message)) != 0) { printf("Return code from MQTT publish is %d\n", rc); network.disconnect(&network); break; } else { printf("MQTT publish topic \"ESP8266/sample/pub\", message number is %d\n", count); } */ printf("\r\nmqtt_client.isconnected=%d\r\n",client.isconnected); if(client.isconnected==0) { mqtt_reconnect_flag=1; } os_printf("freeHeap: %d\n",system_get_free_heap_size()); } if(FIFO_IsDataExit(&mqtt_fifo))//若FIFO还存在 { uint16_t len; uint8_t data_buf[256]; memset(data_buf,0,sizeof(data_buf)); len=FIFO_ReadData(&mqtt_fifo,(uint8_t *)&data_buf);// if(len>0) { printf("len=%d,data_buf=%s\r\n",len,data_buf); MQTTMessage message; message.qos = QOS0; message.retained = 0; message.payload = data_buf; message.payloadlen = len; if ((rc = MQTTPublish(&client, MQTT_PUBLISH, &message)) != 0) { printf("Return code from MQTT publish is %d\n", rc); network.disconnect(&network); mqtt_reconnect_flag=1; } else { printf("\r\nMQTT publish topic %s\r\n",MQTT_PUBLISH); } } } } break; case mqtt_task_status_OTA: { ota_start(); mqtt_task_status_set(mqtt_task_status_IDLE); break; } default: break; } if(mqtt_reconnect_flag) { mqtt_reconnect_flag=0; break; } } //mqtt断开处理 } else { } } }

浙公网安备 33010602011771号