esp8266自定义工程框架

丶灬走出姿态 提交于 2019-12-23 09:23:04

esp8266自定义工程框架

如何再起官方rtos sdk中规范的建立一个工程了,现在我们基于上一篇博客-esp8266对接阿里云平台做下规范。

首先将user_main.c中mqtt连接部分分离出来,写入user_mqtt.c中,分离是注意头文件包含,及一些全局变量设置。
user_main.c

/*
   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/

#include <stdio.h>

//#include "esp_system.h"

//#include "freertos/FreeRTOS.h"
//#include "freertos/task.h"

#include <stddef.h>
#include <stdio.h>
#include <string.h>

#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event_loop.h"
#include "esp_log.h"
#include "nvs_flash.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"

#include "MQTTClient.h"

#include "user_mqtt.h"


#define  DBG_C(...) printf("[%s,%d]",__FUNCTION__,__LINE__);printf(__VA_ARGS__)


/* FreeRTOS event group to signal when we are connected & ready to make a request */
EventGroupHandle_t wifi_event_group;

/* The event group allows multiple bits for each event,
   but we only care about one event - are we connected
   to the AP with an IP? */
int CONNECTED_BIT = BIT0;


#define MQTT_CLIENT_THREAD_NAME         "mqtt_client_thread"
#define MQTT_CLIENT_THREAD_STACK_WORDS  4096
#define MQTT_CLIENT_THREAD_PRIO         8

static const char *TAG = "example";

static esp_err_t event_handler(void *ctx, system_event_t *event)
{
    switch (event->event_id) {
    case SYSTEM_EVENT_STA_START:
        DBG_C("SYSTEM_EVENT_STA_START\n");
        esp_wifi_connect();
        break;

    case SYSTEM_EVENT_STA_GOT_IP:
        DBG_C("SYSTEM_EVENT_STA_GOT_IP\n");
        xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
        break;

    case SYSTEM_EVENT_STA_DISCONNECTED:
        /* This is a workaround as ESP32 WiFi libs don't currently
           auto-reassociate. */
        DBG_C("SYSTEM_EVENT_STA_DISCONNECTED\n");
        esp_wifi_connect();
        xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
        break;

    default:
        break;
    }

    return ESP_OK;
}

static void initialise_wifi(void)
{
   //wifi相关初始化
    tcpip_adapter_init();
    wifi_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
    //设备需要连接wifi的ssid password配置
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = "cmcc",
            .password = "qwe123456",
        },
    };
    DBG_C("Setting WiFi configuration SSID %s...\n", wifi_config.sta.ssid);
    //设置wifi 模式 station模式
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
    //开启wif,联网
    ESP_ERROR_CHECK(esp_wifi_start());
}


/******************************************************************************
 * FunctionName : app_main
 * Description  : entry of user application, init user function here
 * Parameters   : none
 * Returns      : none
*******************************************************************************/
void app_main(void)
{
   //modify cdb 2019-12-19
   // printf("SDK version:%s\n", esp_get_idf_version());
   // Initialize NVS
    esp_err_t ret = nvs_flash_init();
    int i=0;
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }

    ESP_ERROR_CHECK(ret);
    //初始化wifi,并且联网
    initialise_wifi();
    //创建mqtt 处理线程
    ret = xTaskCreate(&mqtt_client_thread,
                  MQTT_CLIENT_THREAD_NAME,
                  MQTT_CLIENT_THREAD_STACK_WORDS,
                  NULL,
                  MQTT_CLIENT_THREAD_PRIO,
                  NULL);

    if (ret != pdPASS)  {
        DBG_C("mqtt create client thread %s failed\n", MQTT_CLIENT_THREAD_NAME);
    }
    //程序将进入死循环,防止退出,并且打印运行时间log,单位s,也开启rtos任务调度
    while(1)
    {
        DBG_C("the system is runing,runtime:%d\n",i++);
        vTaskDelay(1000 / portTICK_RATE_MS);
    }

}

user_mqtt.c

#include <stdio.h>

#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"

#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event_loop.h"
#include "esp_log.h"
#include "nvs_flash.h"


#include "MQTTClient.h"

/* FreeRTOS event group to signal when we are connected & ready to make a request */
extern EventGroupHandle_t wifi_event_group;

/* The event group allows multiple bits for each event,
   but we only care about one event - are we connected
   to the AP with an IP? */
extern int CONNECTED_BIT;



#define  DBG_C(...) printf("[%s,%d]",__FUNCTION__,__LINE__);printf(__VA_ARGS__)

//mqtt 相关参数
#define CONFIG_MQTT_PAYLOAD_BUFFER    (1*1024)
#define CONFIG_MQTT_BROKER            "a1PC1yDIZoi.iot-as-mqtt.cn-shanghai.aliyuncs.com"   // "106.15.83.29"//
#define CONFIG_MQTT_PORT              1883
#define CONFIG_MQTT_SUB_TOPIC         "/a1PC1yDIZoi/hMdcyQzFeEa86qEwmOhf/user/report"
#define CONFIG_MQTT_PUB_TOPIC         "/a1PC1yDIZoi/hMdcyQzFeEa86qEwmOhf/user/data"

static void messageArrived(MessageData *data)
{
   char recvbuf[512];
   memset(recvbuf,0,512);
   strncpy(recvbuf,(char *)data->message->payload,data->message->payloadlen);
   DBG_C("Message arrived[%d]:%s\n", data->message->payloadlen, recvbuf);

}


//publish
static int mqtt_client_send(MQTTClient * client)
{
      MQTTMessage message;
      static uint32_t count = 0;
      char payload[512];
      int rc=0;
      
      memset(payload,0,512);
      message.qos = QOS0;
      message.retained = 0;
      message.payload = payload;
      sprintf(payload, "message number %d", ++count);
      message.payloadlen = strlen(payload);

      if((count%50) != 10)
         return 0;

      if ((rc = MQTTPublish(client, CONFIG_MQTT_PUB_TOPIC, &message)) != 0) {
          DBG_C("Return code from MQTT publish is %d\n", rc);
      } else {
          DBG_C("MQTT published topic %s, len:%u heap:%u\n", CONFIG_MQTT_PUB_TOPIC, message.payloadlen, esp_get_free_heap_size());
      }
    
      if (rc != 0) {
          return -1;
      }

      return rc;
}


void mqtt_client_thread(void *pvParameters)
{
    char *payload = NULL;
    MQTTClient client;
    Network network;
    int rc = 0;
    char clientID[32] = {0};



    MQTTPacket_connectData connectData = MQTTPacket_connectData_initializer;
  
    //mqtt 网络连接初始化
    NetworkInit(&network);

    if (MQTTClientInit(&client, &network, 0, NULL, 0, NULL, 0) == false) {
        DBG_C("mqtt init err\n");
        vTaskDelete(NULL);
    }

    payload = malloc(CONFIG_MQTT_PAYLOAD_BUFFER);

    if (!payload) {
        DBG_C("mqtt malloc err\n");
    } else {
        memset(payload, 0x0, CONFIG_MQTT_PAYLOAD_BUFFER);
    }

    for (;;) {
        DBG_C("wait wifi connect...\n");
        xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);
        //创建mqtt socket连接,底层就是调用socket connect 
        if ((rc = NetworkConnect(&network, CONFIG_MQTT_BROKER, CONFIG_MQTT_PORT)) != 0) {
            DBG_C("Return code from network connect is %d\n", rc);
            continue;
        }

        connectData.MQTTVersion = 3;

        //sprintf(clientID, "%s_%u", CONFIG_MQTT_CLIENT_ID, esp_random());

        connectData.clientID.cstring = "a1PC1yDIZoi.hMdcyQzFeEa86qEwmOhf|securemode=3,timestamp=2524608000000,signmethod=hmacsha1,gw=0,ext=0,partner_id=example.demo.partner-id,module_id=example.demo.module-id|";
        connectData.keepAliveInterval = 60;

        connectData.username.cstring = "hMdcyQzFeEa86qEwmOhf&a1PC1yDIZoi";
        connectData.password.cstring = "92ee26a897d43004c78e94065d6209d5f8ba1c65";

        connectData.cleansession = 0;

        DBG_C("MQTT Connecting\n");
        //建立mqtt连接
        if ((rc = MQTTConnect(&client, &connectData)) != 0) {
            DBG_C("Return code from MQTT connect is %d\n", rc);
            network.disconnect(&network);
            continue;
        }

        DBG_C("MQTT Connected\n");

        //订阅CONFIG_MQTT_SUB_TOPIC topic
        rc = MQTTSubscribe(&client, CONFIG_MQTT_SUB_TOPIC, QOS0, messageArrived);
        MQTTYield(&client, 500);
        if (rc != 0) {
            printf("[%s] Client Subscribed %d\n",__func__, rc);
            goto fail;
        }
        DBG_C("MQTT subscribe to topic %s OK\n", CONFIG_MQTT_SUB_TOPIC);


        int timeout_count = 0;
        while (timeout_count < 10 ) {
            rc = MQTTYield(&client, 500);
        
            if(client.isconnected == 0)
            {
                printf("[%s]mqtt has disconnect!\n",__func__);
                break;
            }

            if(client.ping_outstanding == 1)    //pin失败!
            {
                timeout_count++;
                printf("[%s]rc=%d, c->ping_outstanding=%d\r\n",__func__,rc, client.ping_outstanding);
            }else{
                timeout_count = 0;
            }

//            rc = mqtt_client_send(&client);
//            if(rc < 0)
//                DBG_C("MQTT PUBLISH FAIL\n");
            vTaskDelay(100);
        }

    }
fail:
    network.disconnect(&network);
    DBG_C("mqtt_client_thread going to be deleted\n");
    vTaskDelete(NULL);
    return;
}

同时建立一个对应的头文件,user_mqtt.h(user_main,c中包含)

#ifndef _ESP8266_MY_MQTT_H_
#define _ESP8266_MY_MQTT_H_

void mqtt_client_thread(void *pvParameters);

#endif

现在看怎么修改component.mk
首先了解下sdk目录结构
在这里插入图片描述
如上图结构,想添加自己的功能模块,如上面方法添加即可。
代码添加完成,如何将起编译进代码呢?
我们需要修改工程目录下的components目录中的component.mk
在这里插入图片描述
修改如下:

#
# Component Makefile
#

#添加.c代码
COMPONENT_SRCDIRS := mqtt
#添加头文件
COMPONENT_ADD_INCLUDEDIRS += mqtt/include

看到这里,就能够再自定义工程里随意添加自己的功能了。

注意:这里建立说下修改项目名称
在这里插入图片描述

编译
make clean
make

查看结果:
在这里插入图片描述

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!