ESP8266 MQTT

最近接了个小项目

ESP8266使用SDK来开发

1,airkiss配网(微信)
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
        {
            
        }
    }
}

 

posted @ 2019-03-21 09:51  XZHDJH  阅读(565)  评论(0)    收藏  举报