O_嵌入式专题目录
O_K210_WifiLte远程抓拍图传

问题

  • 4G AT流程太慢,鉴于稳定性优化空间也有限,所以考虑在Air724UG单独做一套代码,用并行IO进行命令传递。
  • 从整体功耗和响应速度来说最好还是再加一片单片机进行主要逻辑工作,控制Wifi/Lte的电源使能。目前ESP32S开机时间太长,不适合快速响应的超低功耗方案。
  • Wifi的save_power模式待测试。
  • 串口发送Hex数组由于0x00的原因用strlen()与sizeof()均无法得到正确的长度,所以只能指定发送长度。
  • 主体task还有优化空间,现在按 1024 的接收最大长度和 1024*4 的堆栈大小正常剩余空间为2000左右,但瞬间接收到大量无效字符串后还是会导致Core dump,具体是不是堆栈溢出还有待验证,不过这个问题必须要解决。
  • 目前临时服务器可进行Wifi/Lte切换,Wifi账号密码理论可实现。
  • 监视任务堆栈大小及其它调试信息在app_main()中调整各LOG标签的级别即可。

WxMiniPro


  • index.wxml

    <!--index.wxml-->
    <view style="text-align: center;">
      <view style="text-align: center; margin-bottom: 20px;">{{currentMode}}</view>
      <image style="width: 320px; height: 240px; background-color: #eeeeee; margin-bottom: 20px;" mode="aspectFit" src="{{imgSrc}}"></image>
      <view>
        <button style="margin-bottom: 10px;" bindtap="btnOpen" disabled="{{btnOpenState}}">{{currentState}}</button>
        <button style="margin-bottom: 10px;" bindtap="btnWifiLte" disabled="{{btnWifiLtwState}}">{{settingMode}}</button>
        <button style="margin-bottom: 10px;" bindtap="btnClean">Clean</button>
        <button style="margin-bottom: 10px;" bindtap="btnDisconnect">Disconnect</button>
      </view>
    </view>
  • index.js

    // index.js
    var mqtt = require("../../utils/mqtt.js")
    let url = 'wxs://bemfa.com:9504/wss'
    let date = new Date().getTime()
    let client = mqtt.connect(url, {
    connectTimeout: 2000,
    clientId: '7d54f85af42976ee3c2693e6xxxxxxxx',
    username: '',
    password: ''
    })
    let clientConnectFlag = 0
    // 获取应用实例
    const app = getApp()
    
    
    Page({
    data: {
      btnOpenState: true,
      currentState: 'Open',
      btnWifiLtwState: true,
      currentMode: 'Wifi',
      settingMode: 'Set to Lte',
      codeState: 'DEBUG',
      imgUrl: '',
      imgSrc: 'https://res.wx.qq.com/wxdoc/dist/assets/img/0.4cb08bb4.jpg',
    },
    // 事件处理函数
    bindViewTap() {
      wx.navigateTo({
        url: '../logs/logs'
      })
    },
    onLoad() {
        this.initSocket();
        this.getMessage();
    },
    initSocket()
    {
      client.on('connect', () => {
        console.log('Connect mqtt success!')
      })
      client.subscribe('K210T1', {
        qos: 1
      }, function (err) {
        if (!err) {
          clientConnectFlag = 1
          console.log("Subscribe success: K210T1")
        }
      })
      client.on('disconnect', () => {
        console.log('Connection disconnet!')
      })
      client.on('close', () => {
        console.log('Connection close!')
      })
      client.on('offline', () => {
        console.log('Connection offline!')
      })
      client.on('error', () => {
        console.log('Cannot connect!')
        this.initSocket()
      })
      client.publish('K210T1', 'WxMiniPro', {qos: 1});
    },
    getMessage()
    {
      console.log('Waiting message ...')
      client.on('message', (topic, payload) => {
        console.log('$Get: ', payload.toString());
        if(payload == 'Door-Od')
        {
          this.setData({
            btnOpenState: true,
            currentState: 'Open', 
            btnWifiLtwState: true,
          });
          wx.showToast({
            title: 'Door opened!',
            icon: 'none',
            duration: 2000
          });
        }
        if(payload == 'Door-Cd')
        {
          this.setData({
            btnOpenState: true,
            currentState: 'Open', 
            btnWifiLtwState: true,
          });
          wx.showToast({
            title: 'Door closed!',
            icon: 'none',
            duration: 2000
          });
        }
        if(payload == 'Door-ASKw')
        {
          this.setData({
            btnOpenState: false,
            currentState: 'Open', 
            currentMode: 'Wifi',
            btnWifiLtwState: false,
            settingMode: 'Set to Lte',
          });
          wx.showToast({
            title: 'Door ASK!',
            icon: 'none',
            duration: 2000
          });
        }
        if(payload == 'Door-ASKl')
        {
          this.setData({
            btnOpenState: false,
            currentState: 'Open', 
            currentMode: 'Lte',
            btnWifiLtwState: false,
            settingMode: 'Set to Wifi',
          });
          wx.showToast({
            title: 'Door ASK!',
            icon: 'none',
            duration: 2000
          });
        }
        /*
        if(payload == 'CMD-SUCCESS')
        {
          if(this.data.settingMode == 'Set to Wifi')
          {
            this.setData({
              btnOpenState: true,
              currentState: 'Open', 
              currentMode: 'Wifi',
              btnWifiLtwState: true,
              settingMode: 'Set to Lte',
            });
            wx.showToast({
              title: 'Setting Wifi success!',
              icon: 'none',
              duration: 2000
            });
          }
          else if(this.data.settingMode == 'Set to Lte')
          {
            this.setData({
              btnOpenState: true,
              currentState: 'Open', 
              currentMode: 'Lte',
              btnWifiLtwState: true,
              settingMode: 'Set to Wifi',
            });
            wx.showToast({
              title: 'Setting Lte success!',
              icon: 'none',
              duration: 2000
            });
          }
        }
        */
      })
    },
    btnOpen(e)
    {
      console.log("Open door ...");
      this.setData({
        currentState: 'Opening ...'
      });
      wx.showToast({
        title: 'Open door ...',
        icon: 'none',
        duration: 2000
      });
      client.publish('K210T1', 'Door-Oc', {qos: 1});
    },
    btnWifiLte(e)
    {
      if(this.data.currentMode == 'Wifi')
      {
        console.log("Setting to Lte ...");
        client.publish('K210T1', 'CMD-LTE', {qos: 1});
        this.setData({
          btnOpenState: true,
          currentState: 'Open', 
          currentMode: 'Lte',
          btnWifiLtwState: true,
          settingMode: 'Set to Wifi',
        });
      }
      else if(this.data.currentMode == 'Lte')
      {
        console.log("Setting to Wifi ...");
        client.publish('K210T1', 'CMD-WIFI', {qos: 1});
        this.setData({
          btnOpenState: true,
          currentState: 'Open', 
          currentMode: 'Wifi',
          btnWifiLtwState: true,
          settingMode: 'Set to Lte',
        });
      }
    },
    btnClean(e)
    {
      this.setData({
        btnOpenState: true,
        currentState: 'Open', 
        imgSrc: 'https://res.wx.qq.com/wxdoc/dist/assets/img/0.4cb08bb4.jpg',
      });
    },
    btnDisconnect(e)
    {
      client.unsubscribe('K210T1');
      console.log('Dissubscribe');
      client.end();
    }
    })

Embeded Code

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

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

#include "esp_system.h"
#include "esp_event.h"
#include "esp_wifi.h"
#include "esp_http_client.h"
#include "esp_log.h"

#include "nvs_flash.h"

#include "driver/gpio.h"
#include "driver/uart.h"

#include "lwip/err.h"
#include "lwip/sys.h"

#include "sdkconfig.h"

/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
#define DEBUG_ATY   1
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
#define BLINK_GPIO  2

#define WIFI_EN_PIN 19
#define LTE_EN_PIN  21
/*
    Use default 9/10 will cause core dump:
    Guru Meditation Error: Core  0 panic'ed (IllegalInstruction). Exception was unhandled.
    Memory dump at 0x40115950: ffffffff ffffffff ffffffff
    0x40115950: lmac_stop_hw_txq at ??:?
*/
#define TXD1_PIN (GPIO_NUM_23)
#define RXD1_PIN (GPIO_NUM_22)
#define TXD2_PIN (GPIO_NUM_17)
#define RXD2_PIN (GPIO_NUM_16)
#define RTS_PIN  (UART_PIN_NO_CHANGE)
#define CTS_PIN  (UART_PIN_NO_CHANGE)

/*----------------------------------------------------------------------------*/
static nvs_handle_t nvsHandle;
/*----------------------------------------------------------------------------*/
#define SSID                "ESPT"
#define PASSWORD            "00000000"
#define MAXIMUM_WIFI_RETRY  5

uint8_t wifiLte = 0;    //0:Wifi, 1:Lte
uint8_t wifiState = 0;
uint8_t lteState = 0;
uint8_t wifiRetryNum = 0;
/* FreeRTOS event group to signal when we are connected*/
static EventGroupHandle_t s_wifi_event_group;
/* The event group allows multiple bits for each event, but we only care about two events:
 * - we are connected to the AP with an IP
 * - we failed to connect after the maximum amount of retries */
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT      BIT1

/*----------------------------------------------------------------------------*/
#define MAXIMUM_GET_RETRY   5
#define MAXIMUM_SEND_RETRY  20
#define MAX_HTTP_OUTPUT_BUFFER 2048
char output_buffer[MAX_HTTP_OUTPUT_BUFFER] = {0};
uint8_t httpGetFlag = 0;
uint8_t httpGetRetryCount = 0;
uint8_t httpSendRetryCount = 0;

#define RX_BUF_SIZE 1024
uint8_t doorOpenStateFlag = 0;   //Flag 0:None, 1:First, 2:Check sure, 3:Sure at end
uint8_t doorCloseStateFlag = 0;
uint8_t doorAskStateFlag = 0;
uint8_t doorOpenCmdFlag = 0;
const char sureBackCmd[10] = {0xFF, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A};
const char addUserCmd[10] = {0xFF, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A};
const char openDoorCmd[10] = {0xFF, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A};
const char imgSureCmd[10] = {0xFF, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A};

/*----------------------------------------------------------------------------*/
int Uart1SendDataHex(const char* data, const uint8_t length);
int Uart1SendData(const char* data);
int Uart2SendData(const char* data);
void NvsInit(void);
esp_err_t NvsReadMode(void);
esp_err_t NvsWriteMode(void);
void ChipRestart(int seconds);
void OpenCloseDoor(void);



/*----------------------------------------------------------------------------*/
static void event_handler(void* arg, esp_event_base_t event_base,
                            int32_t event_id, void* event_data)
{
    if(event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
    {
        esp_wifi_connect();
    }
    else if(event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
    {
        if(wifiRetryNum < MAXIMUM_WIFI_RETRY)
        {
            esp_wifi_connect();
            wifiRetryNum++;
            ESP_LOGI("WifiInit", "Retry to connect to the AP");
        }
        else
        {
            xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
        }
        ESP_LOGI("WifiInit","Connect to the AP fail");
    }
    else if(event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
    {
        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
        ESP_LOGI("WifiInit", "Got ip:" IPSTR, IP2STR(&event->ip_info.ip));
        wifiRetryNum = 0;
        xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
    }
}

void WifiInit(void)
{
    s_wifi_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_create_default_wifi_sta();
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    esp_event_handler_instance_t instance_any_id;
    esp_event_handler_instance_t instance_got_ip;
    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
                                                        ESP_EVENT_ANY_ID,
                                                        &event_handler,
                                                        NULL,
                                                        &instance_any_id));
    ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
                                                        IP_EVENT_STA_GOT_IP,
                                                        &event_handler,
                                                        NULL,
                                                        &instance_got_ip));

    wifi_config_t wifi_config = {
        .sta = {
            .ssid = SSID,
            .password = PASSWORD,
            /* Setting a password implies station will connect to all security modes including WEP/WPA.
             * However these modes are deprecated and not advisable to be used. Incase your Access point
             * doesn't support WPA2, these mode can be enabled by commenting below line */
            .threshold.authmode = WIFI_AUTH_WPA2_PSK,
            //.listen_interval = DEFAULT_LISTEN_INTERVAL,   //Power Save
            .pmf_cfg = {
                .capable = true,
                .required = false
            },
        },
    };
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
    ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
    ESP_ERROR_CHECK(esp_wifi_start() );
    //esp_wifi_set_ps(DEFAULT_PS_MODE);     //Power Save
    ESP_LOGI("WifiInit", "Wifi_init_sta finished.");

    /* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
     * number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
    EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
            WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
            pdFALSE,
            pdFALSE,
            portMAX_DELAY);

    /* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
     * happened. */
    if(bits & WIFI_CONNECTED_BIT)
    {
        wifiState = 1;
        ESP_LOGI("WifiInit", "Connected to ap SSID:%s password:%s",
                 SSID, PASSWORD);
    }
    else if(bits & WIFI_FAIL_BIT)
    {
        ESP_LOGI("WifiInit", "Failed to connect to SSID:%s, password:%s",
                 SSID, PASSWORD);
    }
    else
    {
        ESP_LOGE("WifiInit", "UNEXPECTED EVENT");
    }

    /* The event will not be processed after unregister */
    ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, instance_got_ip));
    ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id));
    vEventGroupDelete(s_wifi_event_group);
}


/*----------------------------------------------------------------------------*/
static uint8_t HttpGetWifi(const char *urlGet)
{
    if(wifiState)
    {
        int content_length = 0;
        esp_http_client_config_t config = {
            .url = urlGet,
        };
        esp_http_client_handle_t client = esp_http_client_init(&config);

        // GET Request
        esp_http_client_set_method(client, HTTP_METHOD_GET);
        esp_err_t err = esp_http_client_open(client, 0);
        if(err != ESP_OK)
        {
            ESP_LOGE("HttpGetWifi", "Failed to open HTTP connection: %s", esp_err_to_name(err));
        }
        else
        {
            content_length = esp_http_client_fetch_headers(client);
            if(content_length < 0)
            {
                ESP_LOGE("HttpGetWifi", "HTTP client fetch headers failed");
            }
            else
            {
                int data_read = esp_http_client_read_response(client, output_buffer, MAX_HTTP_OUTPUT_BUFFER);
                if(data_read >= 0) 
                {
                    ESP_LOGI("HttpGetWifi", "HTTP GET Status = %d, content_length = %d",
                    esp_http_client_get_status_code(client),
                    esp_http_client_get_content_length(client));
                    ESP_LOGI("HttpGetWifi", "%d - %s", strlen(output_buffer), output_buffer);
                    
                    esp_http_client_close(client);
                    esp_http_client_cleanup(client);
                    return 1;
                }
                else
                {
                    ESP_LOGE("HttpGetWifi", "Failed to read response");
                }
            }
        }
        esp_http_client_close(client);
        esp_http_client_cleanup(client);
    }
    else
    {
        ESP_LOGE("HttpGetWifi", "No wifi connected!");
    }
    return 0;
}

uint8_t sendStep = 5;
static uint8_t HttpGetLte(const char *urlGet)
{
    uint8_t *data = (uint8_t*) malloc(RX_BUF_SIZE+1);
    uint8_t successFlag = 0;
    uint8_t sleepTime = 0;
    while(1)
    {
        if(sendStep == 0)
        {
            //Check 4G model
            while(1)
            {
                Uart2SendData("AT\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT\r\n\r\nOK\r\n"))
                        sendStep = 1;
                    else
                        ESP_LOGI("HttpGetLte", "@0:%s", (char *)data);
                    break;
                }
            }
            if(sleepTime)
                vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
        }
        else if(sendStep == 1)
        {
            //Check SIM card
            while(1)
            {
                Uart2SendData("AT+CPIN?\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+CPIN?\r\n\r\n+CPIN: READY\r\n\r\nOK\r\n"))
                        sendStep = 2;
                    else
                        ESP_LOGI("HttpGetLte", "@1:%s", (char *)data);
                    break;
                }
            }
            if(sleepTime)
                vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
        }
        else if(sendStep == 2)
        {
            //Check regist
            while(1)
            {
                Uart2SendData("AT+CGATT?\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+CGATT?\r\n\r\n+CGATT: 1\r\n\r\nOK\r\n"))
                        sendStep = 3;
                    else
                        ESP_LOGI("HttpGetLte", "@2:%s", (char *)data);
                    break;
                }
            }
            if(sleepTime)
                vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
        }
        else if(sendStep == 3)
        {
            //Set APN
            while(1)
            {
                Uart2SendData("AT+CSTT\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+CSTT\r\n\r\nOK\r\n"))
                        sendStep = 4;
                    else if(strstr((char *)data, "AT+CSTT\r\n\r\n") && strstr((char *)data, "+CME ERROR"))
                        sendStep = 5;
                    else
                        ESP_LOGI("HttpGetLte", "@3:%s", (char *)data);
                    break;
                }
            }
            if(sleepTime)
                vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
        }
        else if(sendStep == 4)
        {
            //Active network
            while(1)
            {
                Uart2SendData("AT+CIICR\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+CIICR\r\n\r\nOK\r\n"))
                        sendStep = 5;
                    else if(strstr((char *)data, "AT+CIICR\r\n\r\n") && strstr((char *)data, "+CME ERROR"))
                        sendStep = 0;
                    else
                        ESP_LOGI("HttpGetLte", "@4:%s", (char *)data);
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else if(sendStep == 5)
        {
            //Check ip
            while(1)
            {
                Uart2SendData("AT+CIFSR\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+CIFSR\r\n\r\n") && !strstr((char *)data, "+CME ERROR"))
                        sendStep = 6;
                    else if(strstr((char *)data, "AT+CIFSR\r\n\r\n") && strstr((char *)data, "+CME ERROR"))
                    {
                        while(1)
                        {
                            Uart2SendData("AT+CIPSHUT\r\n");
                            const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                            if(rxBytes > 0)
                            {
                                data[rxBytes] = 0;
                                if(strstr((char *)data, "AT+CIPSHUT\r\n\r\nSHUT OK\r\n"))
                                    sendStep = 3;
                                else
                                    ESP_LOGI("HttpGetLte", "@5-1:%s", (char *)data);
                                break;
                            }
                        }
                    }
                    else
                        ESP_LOGI("HttpGetLte", "@5-2:%s", (char *)data);
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else if(sendStep == 6)
        {
            while(1)
            {
                Uart2SendData("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"\r\n\r\nOK\r\n"))
                        sendStep = 7;
                    else
                        ESP_LOGI("HttpGetLte", "@6:%s", (char *)data);
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else if(sendStep == 7)
        {
            while(1)
            {
                Uart2SendData("AT+SAPBR=3,1,\"APN\",\"\"\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+SAPBR=3,1,\"APN\",\"\"\r\n\r\nOK\r\n"))
                        sendStep = 8;
                    else
                        ESP_LOGI("HttpGetLte", "@7:%s", (char *)data);
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else if(sendStep == 8)
        {
            while(1)
            {
                Uart2SendData("AT+SAPBR=1,1\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+SAPBR=1,1\r\n\r\nOK\r\n"))
                        sendStep = 9;
                    else if(strstr((char *)data, "AT+SAPBR=1,1\r\n\r\n") && strstr((char *)data, "+CME ERROR"))
                        sendStep = 9;
                    else
                        ESP_LOGI("HttpGetLte", "@8:%s", (char *)data);
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else if(sendStep == 9)
        {
            while(1)
            {
                Uart2SendData("AT+SAPBR=2,1\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+SAPBR=2,1\r\n\r\n") && strstr((char *)data, "+SAPBR: 1,1,"))
                        sendStep = 10;
                    else if(strstr((char *)data, "AT+SAPBR=2,1\r\n\r\n") && !strstr((char *)data, "+SAPBR: 1,1,"))
                        sendStep = 8;
                    else
                        ESP_LOGI("HttpGetLte", "@9:%s", (char *)data);
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else if(sendStep == 10)
        {
            //Init http
            while(1)
            {
                Uart2SendData("AT+HTTPINIT\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+HTTPINIT\r\n\r\nOK\r\n"))
                        sendStep = 11;
                    else if(strstr((char *)data, "AT+HTTPINIT\r\n\r\n") && strstr((char *)data, "+CME ERROR: 3"))
                        sendStep = 11;
                    else
                        ESP_LOGI("HttpGetLte", "@10:%s", (char *)data);
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else if(sendStep == 11)
        {
            //Set http CID
            while(1)
            {
                Uart2SendData("AT+HTTPPARA=\"CID\",1\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+HTTPPARA=\"CID\",1\r\n\r\nOK\r\n"))
                        sendStep = 12;
                    else
                        ESP_LOGI("HttpGetLte", "@11:%s", (char *)data);
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else if(sendStep == 12)
        {
            //Set url
            char *sendUrlTempStr = (char *) malloc(MAX_HTTP_OUTPUT_BUFFER);
            sprintf(sendUrlTempStr, "AT+HTTPPARA=\"URL\",\"%s\"\r\n", urlGet);
            while(1)
            {
                Uart2SendData(sendUrlTempStr);
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+HTTPPARA=\"URL\",") && strstr((char *)data, "OK\r\n"))
                        sendStep = 13;
                    else
                        ESP_LOGI("HttpGetLte", "@12:%s", (char *)data);
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else if(sendStep == 13)
        {
            //Send http
            while(1)
            {
                Uart2SendData("AT+HTTPACTION=1\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    //if(strstr((char *)data, "AT+HTTPACTION=1\r\n\r\nOK\r\n"))
                        //sendStep = 14;
                        //break;
                    if(strstr((char *)data, "+HTTPACTION: 1,200,"))
                    {
                        sendStep = 14;
                        // break;
                    }
                    else
                        ESP_LOGI("HttpGetLte", "@13:%s", (char *)data);
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else if(sendStep == 14)
        {
            //Get response
            while(1)
            {
                Uart2SendData("AT+HTTPREAD\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+HTTPREAD\r\n\r\n+HTTPREAD:"))
                    {
                        successFlag = 1;
                        strcpy(output_buffer, (char *)data);
                        ESP_LOGI("HttpGetLte", "%s", output_buffer);
                        sendStep = 15;
                    }
                    else
                        ESP_LOGI("HttpGetLte", "@14:%s", (char *)data);
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else if(sendStep == 15)
        {
            //Terminate http
            while(1)
            {
                Uart2SendData("AT+HTTPTERM\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+HTTPTERM\r\n\r\nOK\r\n"))
                        sendStep = 16;
                    else if(strstr((char *)data, "AT+HTTPTERM\r\n\r\n") && strstr((char *)data, "+CME ERROR: 3"))
                        sendStep = 16;
                    else
                        ESP_LOGI("HttpGetLte", "@15:%s", (char *)data);
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else if(sendStep == 16)
        {
            //Shutdown network
            while(1)
            {
                Uart2SendData("AT+CIPSHUT\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+CIPSHUT\r\n\r\nSHUT OK\r\n"))
                        sendStep = 20;
                    else if(strstr((char *)data, "AT+CIPSHUT\r\n\r\n") && strstr((char *)data, "+CME ERROR: 3"))
                        sendStep = 20;
                    else
                    {
                        //sendStep = 20;
                        ESP_LOGI("HttpGetLte", "@16:%s", (char *)data);
                    }
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else
        {
            if(successFlag)
            {
                sendStep = 5;
                return 1;
            }
            else
            {
                //sendStep = 17;
                return 0;
            }
            //vTaskDelay(1000 / portTICK_PERIOD_MS);
        }
        ESP_LOGI("HttpGetLteStep", "%d", sendStep);
    }
    free(data);
    return 0;
}

static int HttpSendQos(const char *urlGet)
{
    if(wifiLte || wifiState)
    {
        uint8_t responseFlag = 0;
        if(!wifiLte)
        {
            responseFlag = HttpGetWifi(urlGet);
            ESP_LOGI("HttpSendQos", "Use wifi.");
        }
        else
        {
            responseFlag = HttpGetLte(urlGet);
            ESP_LOGI("HttpSendQos", "Use lte.");
        }
        if(responseFlag)
        {
            if(strstr(output_buffer, "sendok")) //Null
            {
                ESP_LOGI("HttpSendQos", "OK!");
                memset(output_buffer, 0x00, sizeof(output_buffer));
                return 1;
            }
            else if(strstr(output_buffer, "getok") || strstr(output_buffer, "msg"))
            {
                if(strstr(output_buffer, "Door-Oc"))
                {
                    memset(output_buffer, 0x00, sizeof(output_buffer));
                    ESP_LOGW("HttpSendQos", "Open door!");
                    return 1;
                }
                else if(strstr(output_buffer, "CMD-WIFI"))
                {
                    ESP_LOGI("HttpSendQos", "Setting wifi mode ...");
                    wifiLte = 0;
                    if(NvsWriteMode() == ESP_OK)
                    {
                        ESP_LOGI("HttpSendQos", "Set wifi mode success!");
                        Uart1SendDataHex(openDoorCmd, 10);
                        ChipRestart(1);
                    }
                    else
                        ESP_LOGI("HttpSendQos", "Set wifi mode fail!");
                }
                else if(strstr(output_buffer, "CMD-LTE"))
                {
                    ESP_LOGI("HttpSendQos", "Setting lte mode ...");
                    wifiLte = 1;
                    if(NvsWriteMode() == ESP_OK)
                    {
                        ESP_LOGI("HttpSendQos", "Set lte mode success!");
                        Uart1SendDataHex(openDoorCmd, 10);
                        ChipRestart(1);
                    }
                    else
                        ESP_LOGI("HttpSendQos", "Set lte mode fail!");
                }
            }
        }
    }
    else
    {
        ESP_LOGE("HttpSendQos", "No wifi/lte connected!");
    }
    return 0;
}

/*----------------------------------------------------------------------------*/
void UartInit(void)
{
    const uart_config_t uart_config = {
        .baud_rate = 9600,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_APB,
    };
    // We won't use a buffer for sending data.
    uart_driver_install(UART_NUM_1, RX_BUF_SIZE * 2, 0, 0, NULL, 0);
    uart_param_config(UART_NUM_1, &uart_config);
    uart_set_pin(UART_NUM_1, TXD1_PIN, RXD1_PIN, RTS_PIN, CTS_PIN);
    uart_driver_install(UART_NUM_2, RX_BUF_SIZE * 2, 0, 0, NULL, 0);
    uart_param_config(UART_NUM_2, &uart_config);
    uart_set_pin(UART_NUM_2, TXD2_PIN, RXD2_PIN, RTS_PIN, CTS_PIN);
}

int Uart1SendDataHex(const char* data, const uint8_t length)
{
    const int txBytes = uart_write_bytes(UART_NUM_1, data, length);
    // ESP_LOGW("RX1_TASK", "txBytes:%d length:%d %s", txBytes, length, data);
    // ESP_LOG_BUFFER_HEXDUMP("RX1_TASK", data, txBytes, ESP_LOG_WARN);
    return txBytes;
}
int Uart1SendData(const char* data)
{
    const int txBytes = uart_write_bytes(UART_NUM_1, data, strlen(data));
    // ESP_LOGW("RX1_TASK", "txBytes:%d strlen:%d %s", txBytes, strlen(data), data);
    // ESP_LOG_BUFFER_HEXDUMP("RX1_TASK", data, txBytes, ESP_LOG_WARN);
    return txBytes;
}
int Uart2SendData(const char* data)
{
    const int txBytes = uart_write_bytes(UART_NUM_2, data, strlen(data));
    return txBytes;
}

#define INCLUDE_uxTaskGetStackHighWaterMark 1
xTaskHandle rx1_task_handle;
//I (619096) rx1_task: Tsak free heap: 2064(1024*4)

static void rx1_task(void *arg)
{
    uint8_t *data = (uint8_t*) malloc(RX_BUF_SIZE+1);
    int rxBytes = 0;
    uint8_t addUserFlag = 0;
    while(1)
    {
        ESP_LOGI("rx1_task_heap", "Tsak free heap: %d\n", uxTaskGetStackHighWaterMark(rx1_task_handle));
        // rxBytes = uart_read_bytes(UART_NUM_1, data, RX_BUF_SIZE, 1000 / portTICK_RATE_MS);
        rxBytes = uart_read_bytes(UART_NUM_1, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);
        if(rxBytes > 0)
        {
            data[rxBytes] = 0;
            for(int i = 0; i < rxBytes; i++)
            {
                if((data[i] == 0xAA) && (data[i+1] == 0x55))
                {
                    if((data[i+2] == 0x06) && (data[i+9] == 0x05))
                    {
                        addUserFlag = 1;
                        Uart1SendDataHex(sureBackCmd, 10);
                        ESP_LOGW("RX1_TASK", "AA 55 06");
                    }
                    else if((data[i+2] == 0x01) && (data[i+3] == 0x16))
                    {
                        addUserFlag = 0;
                        Uart1SendDataHex(addUserCmd, 10);
                        ESP_LOGW("RX1_TASK", "AA 55 01 16");
                    }
                    else if((data[i+2] == 0x1C) && (data[i+9] == 0x1B))
                    {
                        // Uart1SendDataHex(imgSureCmd, 10);
                        // ESP_LOGW("RX1_TASK", "AA 55 1C");
                    }
                    else if((data[i+2] == 0x03) && (data[i+3] == 0x01))
                    {
                        addUserFlag = 0;
                        httpSendRetryCount = 0;
                        doorOpenStateFlag = 1;
                        doorCloseStateFlag = 0;
                        httpGetFlag = 0;
                        Uart1SendDataHex(sureBackCmd, 10);
                        ESP_LOGW("RX1_TASK", "Door opened!");
                    }
                    else if((data[i+2] == 0x03) && (data[i+3] == 0x00))
                    {
                        addUserFlag = 0;
                        httpSendRetryCount = 0;
                        doorOpenStateFlag = 0;
                        doorCloseStateFlag = 1;
                        httpGetFlag = 0;
                        Uart1SendDataHex(sureBackCmd, 10);
                        ESP_LOGW("RX1_TASK", "Door closed!");
                    }
                    else if((data[i+2] == 0x03) && (data[i+3] == 0x03))
                    {
                        httpSendRetryCount = 0;
                        doorAskStateFlag = 1;
                        httpGetFlag = 0;
                        doorCloseStateFlag = 0;
                        doorOpenStateFlag = 0;
                        //Uart1SendDataHex(sureBackCmd, 10);
                        ESP_LOGW("RX1_TASK", "Door ask!");
                    }
                    else
                        ESP_LOGE("RX1_TASK", "Wrong command!");
                }
            }
            ESP_LOGI("RX1_TASK", "Read %d bytes: '%s'", rxBytes, data);
            ESP_LOG_BUFFER_HEXDUMP("RX1_TASK", data, rxBytes, ESP_LOG_INFO);
        }
        rxBytes = 0;
        //memset(data, 0, RX_BUF_SIZE+1);
        
        if(doorOpenStateFlag)
        {
            httpSendRetryCount++;
            if(HttpSendQos("http://api.bemfa.com/api/device/v1/data/3/push/get/?uid=7d54f85af42976ee3c2693e6xxxxxxxx&topic=K210T1&msg=Door-Od") || (httpSendRetryCount > MAXIMUM_GET_RETRY))
            {
                httpSendRetryCount = 0;
                doorOpenStateFlag = 0;
                doorOpenCmdFlag = 0;
            }
        }
        else if(doorCloseStateFlag)
        {
            httpSendRetryCount++;
            if(HttpSendQos("http://api.bemfa.com/api/device/v1/data/3/push/get/?uid=7d54f85af42976ee3c2693e6xxxxxxxx&topic=K210T1&msg=Door-Cd") || (httpSendRetryCount > MAXIMUM_GET_RETRY))
            {
                httpSendRetryCount = 0;
                doorCloseStateFlag = 0;
                doorOpenCmdFlag = 0;
            }
        }
        else if(doorAskStateFlag)
        {
            httpSendRetryCount++;
            if(wifiLte)
            {
                if(HttpSendQos("http://api.bemfa.com/api/device/v1/data/3/push/get/?uid=7d54f85af42976ee3c2693e6xxxxxxxx&topic=K210T1&msg=Door-ASKl") || (httpSendRetryCount > MAXIMUM_GET_RETRY))
                {
                    httpGetRetryCount = 0;
                    doorAskStateFlag = 0;
                    httpGetFlag = 1;
                }
            }
            else
            {
                if(HttpSendQos("http://api.bemfa.com/api/device/v1/data/3/push/get/?uid=7d54f85af42976ee3c2693e6xxxxxxxx&topic=K210T1&msg=Door-ASKw") || (httpSendRetryCount > MAXIMUM_GET_RETRY))
                {
                    httpGetRetryCount = 0;
                    doorAskStateFlag = 0;
                    httpGetFlag = 1;
                }
            }
        }
        if(httpGetFlag)
        {
            httpGetRetryCount++;
            if(HttpSendQos("http://api.bemfa.com/api/device/v1/data/3/get/?uid=7d54f85af42976ee3c2693e6xxxxxxxx&topic=K210T1&num=1"))
            {
                httpGetRetryCount = 0;
                httpGetFlag = 0;
                doorOpenCmdFlag = 1;
            }
            if(httpGetRetryCount > MAXIMUM_SEND_RETRY)
            {
                httpGetRetryCount = 0;
                httpGetFlag = 0;
                doorOpenCmdFlag = 0;
            }
        }
        if(doorOpenCmdFlag)
        {
            ESP_LOGI("RX1_TASK", "Open door ...");
            Uart1SendDataHex(openDoorCmd, 10);
            doorOpenCmdFlag = 0;
            vTaskDelay(200 / portTICK_PERIOD_MS);
        }
        if(addUserFlag)
        {
            Uart1SendDataHex(sureBackCmd, 10);
            ESP_LOGI("RX1_TASK", "addUserFlag");
        }
    }
    free(data);
}

/*----------------------------------------------------------------------------*/
void InitShowToSerial(void)
{
    /* Print chip information */
    esp_chip_info_t chip_info;
    esp_chip_info(&chip_info);
    ESP_LOGI("InitShowToSerial", "This is %s chip with %d CPU cores, WiFi%s%s",
            CONFIG_IDF_TARGET,
            chip_info.cores,
            (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
            (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");

    ESP_LOGI("InitShowToSerial", "Silicon revision %d", chip_info.revision);

    ESP_LOGI("InitShowToSerial", "%dMB %s flash", spi_flash_get_chip_size() / (1024 * 1024),
            (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");

    ESP_LOGI("InitShowToSerial", "Free heap: %d\n", esp_get_free_heap_size());

    printf("Welcome to SH products!\n");
    Uart1SendData("Welcome to SH products!\n");
    Uart2SendData("Welcome to SH products!\n");

}
/*----------------------------------------------------------------------------*/
void NvsInit(void)
{
    //Initialize NVS
    esp_err_t err = nvs_flash_init();
    if(err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
      ESP_ERROR_CHECK(nvs_flash_erase());
      err = nvs_flash_init();
    }
    ESP_ERROR_CHECK(err);
}
esp_err_t NvsReadMode(void)
{
    // Open
    esp_err_t err = nvs_open("lsStorage", NVS_READWRITE, &nvsHandle);
    if (err != ESP_OK) return err;
    // Read mode
    err = nvs_get_u8(nvsHandle, "wifiLte", &wifiLte);
    if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND)
    {
        wifiLte = 0;
        ESP_LOGE("NvsInit", "No wifiLte nvs value!");
        return err;
    }
    ESP_LOGI("NvsReadMode", "Mode %d", wifiLte);
    // Close
    nvs_close(nvsHandle);
    return ESP_OK;
}
esp_err_t NvsWriteMode(void)
{
    // Open
    esp_err_t err = nvs_open("lsStorage", NVS_READWRITE, &nvsHandle);
    if (err != ESP_OK) return err;
    // Write mode
    err = nvs_set_u8(nvsHandle, "wifiLte", wifiLte);
    if (err != ESP_OK) return err;
    // Commit written value.
    // After setting any values, nvs_commit() must be called to ensure changes are written
    // to flash storage. Implementations may write to storage at other times,
    // but this is not guaranteed.
    err = nvs_commit(nvsHandle);
    if (err != ESP_OK) return err;
    // Close
    nvs_close(nvsHandle);
    return ESP_OK;
}
/*----------------------------------------------------------------------------*/
static xQueueHandle gpio_evt_queue = NULL;

static void IRAM_ATTR gpio_isr_handler(void* arg)
{
    uint32_t gpio_num = (uint32_t) arg;
    xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}
static void wifiEnTask(void* arg)
{
    uint32_t io_num;
    for(;;)
    {
        if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY))
        {
            if(gpio_get_level(io_num))
                Uart1SendData("http://api.bemfa.com/api/device/");
            ESP_LOGI("wifiEnTask", "GPIO[%d] intr, val: %d\n", io_num, gpio_get_level(io_num));
        }
    }
}
#define GPIO_OUTPUT_PIN_SEL  (1ULL<<WIFI_EN_PIN)
#define GPIO_INPUT_PIN_SEL  (1ULL<<WIFI_EN_PIN)
#define ESP_INTR_FLAG_DEFAULT 0
void IoInit(void)
{
    gpio_config_t io_conf;
    //interrupt of rising edge
    io_conf.intr_type = GPIO_INTR_POSEDGE;
    //bit mask of the pins
    io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
    //set as input mode
    io_conf.mode = GPIO_MODE_INPUT;
    io_conf.pull_up_en = 0;
    io_conf.pull_down_en = 1;
    gpio_config(&io_conf);
    //create a queue to handle gpio event from isr
    gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
    //install gpio isr service
    gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
    //hook isr handler for specific gpio pin
    gpio_isr_handler_add(WIFI_EN_PIN, gpio_isr_handler, (void*) WIFI_EN_PIN);
    xTaskCreate(wifiEnTask, "wifiEnTask", 2048, NULL, configMAX_PRIORITIES, NULL);
    gpio_pad_select_gpio(LTE_EN_PIN);
    gpio_set_direction(LTE_EN_PIN, GPIO_MODE_OUTPUT);
    gpio_set_level(LTE_EN_PIN, 0);
}
/*----------------------------------------------------------------------------*/
void BlinkTask(void *pvParameter)
{
    /* Configure the IOMUX register for pad BLINK_GPIO (some pads are
       muxed to GPIO on reset already, but some default to other
       functions and need to be switched to GPIO. Consult the
       Technical Reference for a list of pads and their default
       functions.)
    */
    gpio_pad_select_gpio(BLINK_GPIO);
    /* Set the GPIO as a push/pull output */
    gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
    while(1)
    {
        gpio_set_level(BLINK_GPIO, 1);
        vTaskDelay(100 / portTICK_PERIOD_MS);
        gpio_set_level(BLINK_GPIO, 0);
        vTaskDelay(100 / portTICK_PERIOD_MS);
        
        gpio_set_level(BLINK_GPIO, 1);
        vTaskDelay(100 / portTICK_PERIOD_MS);
        gpio_set_level(BLINK_GPIO, 0);
        vTaskDelay(800 / portTICK_PERIOD_MS);
    }

}

/*----------------------------------------------------------------------------*/
void ChipRestart(int seconds)
{
    for(int i = seconds; i >= 0; i--)
    {
        ESP_LOGW("ChipRestart", "Restarting in %d seconds...\n", i);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
    ESP_LOGW("ChipRestart", "Restarting now!");
    fflush(stdout);
    esp_restart();
}


/*----------------------------------------------------------------------------*/
void app_main(void)
{
    /*------------------------------------------------------------------------*/
    esp_log_level_set("*", ESP_LOG_ERROR);
    if(DEBUG_ATY)
    {
        esp_log_level_set("*", ESP_LOG_VERBOSE);
        ESP_LOGI("AppMain", "Debug mode!");
        //WifiInit();
    }
    else
    {
        ESP_LOGE("AppMain", "Product mode!");
    }
    // esp_log_level_set("HttpGetLte", ESP_LOG_ERROR);
    esp_log_level_set("HttpGetLteStep", ESP_LOG_ERROR);
    esp_log_level_set("rx1_task_heap", ESP_LOG_ERROR);
    /*------------------------------------------------------------------------*/
    IoInit();
    UartInit();
    InitShowToSerial();
    NvsInit();
    NvsReadMode();
    if(!wifiLte)
    {
        gpio_set_level(LTE_EN_PIN, 0);  //LOW
        WifiInit();
    }
    else
    {
        gpio_set_level(LTE_EN_PIN, 1);
    }
    /*------------------------------------------------------------------------*/
    // 参数:任务函数,任务别名,任务堆栈的深度,参数的指针,任务优先级,回传句柄
    xTaskCreate(rx1_task, "uart1_rx_task", 1024*4, NULL, configMAX_PRIORITIES, &rx1_task_handle);
    if(DEBUG_ATY)
        xTaskCreate(&BlinkTask, "LedBlinkTask", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES, NULL);

    /*------------------------------------------------------------------------*/

}

其他方式代码备份(未完全实现)

Arduino-裸机-指令

#include <Arduino.h>
#include <WiFiClient.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>


#define DEBUG_ATY 1


#define LTE_EN_PIN  14

#define SSID        "ESPL"
#define PASSWORD    "00000000"

ESP8266WiFiMulti WiFiMulti;

uint8_t ledState = LOW;
unsigned long previousMillis = 0;
const long interval = 1000;

uint8_t lteEn = 0;
uint8_t lteState = 0;

uint8_t wifiState = 0;


uint8_t readByte = 0;
uint8_t cmdStep = 0;
uint8_t cmdFlag = 0;        //0:No cmd, 1:Start cmd, 2:Cmd finished
uint8_t doorOpenStateFlag = 0;   //Flag 0:None, 1:First, 2:Check sure, 3:Sure at end
uint8_t doorCloseStateFlag = 0;
uint8_t doorAskStateFlag = 0;
uint8_t httpGetFlag = 0;
uint8_t doorOpenCmdFlag = 0;
char *readStr = "";
char *cmdStr = "";
char doorOpenStateCmd[8] = {0xF5, 0x01, 0x05, 0x02, 0x01, 0x01, 0xF3, 0x0A};
char doorCloseStateCmd[8] = {0xF5, 0x01, 0x05, 0x02, 0x01, 0x00, 0xF2, 0x0A};
char doorAskStateCmd[7] = {0xF5, 0x01, 0x04, 0x09, 0x03, 0xFA, 0x0A};
char doorOpenCmd[8] = {0xF5, 0x01, 0x05, 0x02, 0x01, 0x01, 0xF3, 0x0A};



void LedBlink(uint8_t timeS)
{
    uint8_t LED_PIN = 12;
    pinMode(LED_PIN, OUTPUT);
    unsigned long currentMillis = millis();

    if(currentMillis - previousMillis >= interval*timeS)
    {
        previousMillis = currentMillis;
        if(ledState == LOW)
        {
            ledState = HIGH;
        }
        else
        {
            ledState = LOW;
        }
        if(DEBUG_ATY)
            Serial.print(ledState);
        digitalWrite(LTE_EN_PIN, ledState);
    }
}

void WifiInit(const char *ssid, const char *password)
{
    uint8_t wifiConnectCount = 0;
    if(!lteEn && !wifiState)
    {
        WiFi.mode(WIFI_STA);
        WiFiMulti.addAP(ssid, password);
        while(!wifiState)
        {
            if(DEBUG_ATY)
                Serial.printf("Wifi connecting ... %d\n", wifiConnectCount++);
            if((WiFiMulti.run() == WL_CONNECTED))
            {
                wifiState = 1;
                wifiConnectCount = 0;
                if(DEBUG_ATY)
                {
                    Serial.printf("WiFi connected!\n");
                    Serial.printf("IP address: ");
                    Serial.println(WiFi.localIP());
                }
            }
            delay(1000);
        }
    }
}

void LteInit(void)
{
    pinMode(LTE_EN_PIN, OUTPUT);
    if(lteEn)
    {
        digitalWrite(LTE_EN_PIN, HIGH);
        if(DEBUG_ATY)
            Serial.printf("\nHello LTE.\n");
    }
    else
    {
        digitalWrite(LTE_EN_PIN, LOW);
    }
}


//String url
String HttpSend(const char *url)
{
    String returnStr = "0";
    if(wifiState)
    {
        WiFiClient client;
        HTTPClient http;

        if(DEBUG_ATY)
            Serial.print("[HTTP] Begin...\n");
        if(http.begin(client, url))
        {
            if(DEBUG_ATY)
                Serial.print("[HTTP] GET...\n");
            // start connection and send HTTP header
            int httpCode = http.GET();
            // httpCode will be negative on error
            if(httpCode > 0)
            {
                // HTTP header has been send and Server response header has been handled
                if(DEBUG_ATY)
                    Serial.printf("[HTTP] GET... code: %d\n", httpCode);
                if(httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY)
                {
                    String payload = http.getString();
                    returnStr = payload;
                    if(DEBUG_ATY)
                        Serial.println(payload);
                }
            }
            else
            {
                if(DEBUG_ATY)
                    Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
            }
            http.end();
        }
        else
        {
            if(DEBUG_ATY)
                Serial.printf("[HTTP} Unable to connect!\n");
        }
    }
    return returnStr;
}


void LockUartDeal(void)
{
    if(Serial.available() > 0)
    {
        readByte = Serial.read();
        if(!cmdFlag && (readByte == 0xF5))
        {
            readStr = "";
            cmdStep = 0;
            cmdFlag = 1;
            readStr[cmdStep] = readByte;
        }
        if(cmdFlag == 1)
        {
            readStr[cmdStep++] = readByte;
            if(readByte == 0x0A)
            {
                cmdStep = 0;
                cmdFlag = 2;
                strcpy(cmdStr, readStr);
                readStr = "";
                Serial.flush();
                //while(Serial.read()>=0);
                if(DEBUG_ATY)
                    Serial.println(cmdStr);
            }
            if(cmdStep > 10)
            {
                cmdStep = 0;
                cmdFlag = 0;
                cmdStr = "";
                readStr = "";
                Serial.printf("Bad command!\n");
            }
        }
    }
    
    if((cmdFlag == 2) && (strcmp(cmdStr, "")))
    {
        if((cmdStr[5] == 0x01) && (strncmp(cmdStr, doorOpenStateCmd, 8) == 0))
        {
            cmdFlag = 0;
            cmdStr = "";
            doorOpenStateFlag = 1;
            doorCloseStateFlag = 0;
            httpGetFlag = 0;
            if(DEBUG_ATY)
                Serial.print("Door opened!\n");
        }
        else if((cmdStr[5] == 0x00) && (strncmp(cmdStr, doorCloseStateCmd, 8) == 0))
        {
            cmdFlag = 0;
            cmdStr = "";
            doorCloseStateFlag = 1;
            doorOpenStateFlag = 0;
            httpGetFlag = 0;
            if(DEBUG_ATY)
                Serial.print("Door closed!\n");
        }
        else if((cmdStr[5] == 0xFA) && (strncmp(cmdStr, doorAskStateCmd, 7) == 0))
        {
            cmdFlag = 0;
            cmdStr = "";
            doorAskStateFlag = 1;
            httpGetFlag = 0;
            doorCloseStateFlag = 0;
            doorOpenStateFlag = 0;
            if(DEBUG_ATY)
                Serial.print("Door ask!\n");
        }
        else
        {
            cmdFlag = 0;
            cmdStr = "";
            if(DEBUG_ATY)
                Serial.print("Wrong command!\n");
        }
    }
    /*
    
    if(doorOpenStateFlag)
    {
        String sendState = HttpSend("http://api.bemfa.com/api/device/v1/data/3/push/get/?uid=c8665cdc8f0a5f8d908155f36ab8038b&topic=K210T1&msg=Door-Od");
        sendState = sendState.substring(sendState.indexOf("status")+9, sendState.indexOf("status")+15);
        if(sendState == "sendok")
            doorOpenStateFlag = 0;
        if(DEBUG_ATY)
            Serial.println(sendState);
    }
    else if(doorCloseStateFlag)
    {
        String sendState = HttpSend("http://api.bemfa.com/api/device/v1/data/3/push/get/?uid=c8665cdc8f0a5f8d908155f36ab8038b&topic=K210T1&msg=Door-Cd");
        sendState = sendState.substring(sendState.indexOf("status")+9, sendState.indexOf("status")+15);
        if(sendState == "sendok")
            doorCloseStateFlag = 0;
        if(DEBUG_ATY)
            Serial.println(sendState);
    }
    else if(doorAskStateFlag)
    {
        String sendState = HttpSend("http://api.bemfa.com/api/device/v1/data/3/push/get/?uid=c8665cdc8f0a5f8d908155f36ab8038b&topic=K210T1&msg=Door-Ask");
        sendState = sendState.substring(sendState.indexOf("status")+9, sendState.indexOf("status")+15);
        if(sendState == "sendok")
        {
            doorAskStateFlag = 0;
            //httpGetFlag = 1;
        }
        if(DEBUG_ATY)
            Serial.println(sendState);
    }
    */
    if(httpGetFlag)
    {
        String getState = HttpSend("http://api.bemfa.com/api/device/v1/data/3/get/?uid=c8665cdc8f0a5f8d908155f36ab8038b&topic=K210T1&num=1");
        String getMessage = getState;
        getState = getState.substring(getState.indexOf("status")+9, getState.indexOf("status")+14);
        if(getState == "getok")
        {
            getMessage = getMessage.substring(getMessage.indexOf("msg")+6, getMessage.indexOf("time")-3);
            if(getMessage == "Door-Oc")
            {
                httpGetFlag = 0;
                Serial.printf(doorOpenCmd);
                if(DEBUG_ATY)
                    Serial.printf("Get open command!\n");
            }
            if(DEBUG_ATY)
                Serial.println(getMessage);
        }
        if(DEBUG_ATY)
            Serial.println(getState);
    }
}


void setup()
{
    if(DEBUG_ATY)
    {
        Serial.begin(74880);
        Serial.printf("\nHello PC!\n");
        WifiInit(SSID, PASSWORD);
    }
    else
    {
        Serial.begin(9600);
    }

}


void loop()
{
    LockUartDeal();
    
    
    
    if(1)
    {
        String sendState = HttpSend("http://api.bemfa.com/api/device/v1/data/3/push/get/?uid=c8665cdc8f0a5f8d908155f36ab8038b&topic=K210T1&msg=Door-Ask");
        sendState = sendState.substring(sendState.indexOf("status")+9, sendState.indexOf("status")+15);
        if(sendState == "sendok")
        {
            doorAskStateFlag = 0;
            //httpGetFlag = 1;
        }
        if(DEBUG_ATY)
            Serial.println(sendState);
        delay(2000);
    }
    if(0)
    {
        String getState = HttpSend("http://api.bemfa.com/api/device/v1/data/3/get/?uid=c8665cdc8f0a5f8d908155f36ab8038b&topic=K210T1&num=1");
        String getMessage = getState;
        getState = getState.substring(getState.indexOf("status")+9, getState.indexOf("status")+14);
        if(getState == "getok")
        {
            Serial.printf("OK!!!\n");
            getMessage = getMessage.substring(getMessage.indexOf("msg")+6, getMessage.indexOf("time")-3);
            if(DEBUG_ATY)
                Serial.println(getMessage);
        }
        if(DEBUG_ATY)
            Serial.println(getState);
        //delay(2000);
    }
}

Arduino-裸机-摄像

#include "WiFi.h"
#include "FS.h"
#include "SD_MMC.h"
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include "esp_camera.h"

#define BLINK_PIN 33


// CAMERA_MODEL_AI_THINKER
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27
#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22

typedef struct {
    uint8_t * buf;
    size_t len;
} fileFb_s;


/*----------------------------------------------------------------------------*/
void WifiInit(void)
{
    Serial.print("\nConnect wifi ...");
    WiFi.begin();
    int count = 0;
    while(WiFi.status() != WL_CONNECTED)
    {
        delay(1000);
        Serial.printf(".%d", 10-count);
        count++;
        if(count > 10)
        {
            WiFi.mode(WIFI_AP_STA);
            WiFi.beginSmartConfig();
            Serial.print("\nWaiting for Smartconfig ...");
            while(!WiFi.smartConfigDone())
            {
                delay(1000);
                Serial.printf(".");
            }
            Serial.println("\nSmartconfig done!");
            WiFi.setAutoConnect(true);
            count = 0;
            break;
        }
    }
    Serial.println("\nWifi connected.");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
}
/*----------------------------------------------------------------------------*/
void listDir(fs::FS &fs, const char * dirname, uint8_t levels)
{
    Serial.printf("Listing directory: %s\n", dirname);

    File root = fs.open(dirname);
    if(!root)
    {
        Serial.println("Failed to open directory");
        return;
    }
    if(!root.isDirectory())
    {
        Serial.println("Not a directory");
        return;
    }

    File file = root.openNextFile();
    while(file){
        if(file.isDirectory())
        {
            Serial.print("  DIR : ");
            Serial.println(file.name());
            if(levels)
                listDir(fs, file.name(), levels -1);
        }
        else
        {
            Serial.print("  FILE: ");
            Serial.print(file.name());
            Serial.print("  SIZE: ");
            Serial.println(file.size());
        }
        file = root.openNextFile();
    }
}

void createDir(fs::FS &fs, const char * path)
{
    Serial.printf("Creating Dir: %s\n", path);
    if(fs.mkdir(path))
        Serial.println("Dir created");
    else
        Serial.println("mkdir failed");
}

void removeDir(fs::FS &fs, const char * path)
{
    Serial.printf("Removing Dir: %s\n", path);
    if(fs.rmdir(path))
        Serial.println("Dir removed");
    else
        Serial.println("rmdir failed");
}

void readFile(fs::FS &fs, const char * path)
{
    Serial.printf("Reading file: %s\n", path);

    File file = fs.open(path);
    if(!file)
    {
        Serial.println("Failed to open file for reading");
        return;
    }

    Serial.print("Read from file: ");
    while(file.available())
        Serial.write(file.read());
}

void writeFile(fs::FS &fs, const char * path, const char * message)
{
    Serial.printf("Writing file: %s\n", path);

    File file = fs.open(path, FILE_WRITE);
    if(!file)
    {
        Serial.println("Failed to open file for writing");
        return;
    }
    if(file.print(message))
        Serial.println("File written");
    else
        Serial.println("Write failed");
}

void appendFile(fs::FS &fs, const char * path, const char * message)
{
    Serial.printf("Appending to file: %s\n", path);

    File file = fs.open(path, FILE_APPEND);
    if(!file)
    {
        Serial.println("Failed to open file for appending");
        return;
    }
    if(file.print(message))
        Serial.println("Message appended");
    else
        Serial.println("Append failed");
}

void renameFile(fs::FS &fs, const char * path1, const char * path2)
{
    Serial.printf("Renaming file %s to %s\n", path1, path2);
    if(fs.rename(path1, path2))
        Serial.println("File renamed");
    else
        Serial.println("Rename failed");
}

void deleteFile(fs::FS &fs, const char * path)
{
    Serial.printf("Deleting file: %s\n", path);
    if(fs.remove(path))
        Serial.println("File deleted");
    else
        Serial.println("Delete failed");
}

void SdInit(void)
{
    if(!SD_MMC.begin())
    {
        Serial.println("Card Mount Failed");
        return;
    }
    
    uint8_t cardType = SD_MMC.cardType();
    Serial.print("SD_MMC Card Type: ");
    if(cardType == CARD_MMC)
        Serial.println("MMC");
    else if(cardType == CARD_SD)
        Serial.println("SDSC");
    else if(cardType == CARD_SDHC)
        Serial.println("SDHC");
    else
        Serial.println("UNKNOWN");
    
    Serial.printf("Card Size: %lluMB\n", SD_MMC.cardSize() / (1024 * 1024));
    Serial.printf("Total space: %lluMB\n", SD_MMC.totalBytes() / (1024 * 1024));
    Serial.printf("Used space: %lluMB\n", SD_MMC.usedBytes() / (1024 * 1024));
    
    //listDir(SD_MMC, "/", 2);
}
/*----------------------------------------------------------------------------*/
void CamInit(void)
{
    camera_config_t config;
    config.ledc_channel = LEDC_CHANNEL_0;
    config.ledc_timer = LEDC_TIMER_0;
    config.pin_d0 = Y2_GPIO_NUM;
    config.pin_d1 = Y3_GPIO_NUM;
    config.pin_d2 = Y4_GPIO_NUM;
    config.pin_d3 = Y5_GPIO_NUM;
    config.pin_d4 = Y6_GPIO_NUM;
    config.pin_d5 = Y7_GPIO_NUM;
    config.pin_d6 = Y8_GPIO_NUM;
    config.pin_d7 = Y9_GPIO_NUM;
    config.pin_xclk = XCLK_GPIO_NUM;
    config.pin_pclk = PCLK_GPIO_NUM;
    config.pin_vsync = VSYNC_GPIO_NUM;
    config.pin_href = HREF_GPIO_NUM;
    config.pin_sscb_sda = SIOD_GPIO_NUM;
    config.pin_sscb_scl = SIOC_GPIO_NUM;
    config.pin_pwdn = PWDN_GPIO_NUM;
    config.pin_reset = RESET_GPIO_NUM;
    config.xclk_freq_hz = 20000000;
    config.pixel_format = PIXFORMAT_JPEG;
    config.frame_size = FRAMESIZE_UXGA;
    config.jpeg_quality = 50;
    config.fb_count = 1;
    
    esp_err_t err = esp_camera_init(&config);

    if(err != ESP_OK)
    {
        Serial.printf("Camera init failed with error 0x%x", err);
        return;
    }
}


/*----------------------------------------------------------------------------*/
void ClientInit(void)
{
    fileFb_s *fileFb = NULL;
    fileFb = (fileFb_s *)malloc(sizeof(fileFb_s));
    *fileFb->buf = NULL;
    fileFb->len = 0;
    Serial.println(*fileFb->buf);

    File fileC = SD_MMC.open("/0/1.jpg", FILE_READ);
    Serial.println("A4");
    if(!fileC)
    {
        Serial.println("Failed to open file!");
        fileC.close();
    }
    else
    {
        Serial.println("A5");
        fileFb->len = fileC.size();
        Serial.println("A6");
        //fileC.read(fileBuf, fileLen);
        //Serial.println("A7");
        fileC.close();
        Serial.println("A8");
        //Serial.println(*fileBuf);
        Serial.printf("Img size: %d\n", fileFb->len);
    }

    HTTPClient http;
    //http.begin("http://192.168.1.232/files/");
    http.begin("http://images.bemfa.com/upload/v1/upimages.php");
    
    http.addHeader("Content-Type", "image/jpg");
    http.addHeader("Authorization", "c8665cdc8f0a5f8d908155f36ab8038b");
    http.addHeader("Authtopic", "esp32img");
    http.addHeader("Wechatmsg", "Pic come!");
/*
    int httpResponseCode = http.POST((uint8_t *)fileBuf, fileLen);
    if(httpResponseCode==200)
    {
        //获取post请求后的服务器响应信息,json格式
        String response = http.getString();
        Serial.print("Response Msg:");
        Serial.println(response);

        //json数据解析
        StaticJsonDocument<200> doc;
        DeserializationError error = deserializeJson(doc, response);
        if (error)
        {
          Serial.print(F("deserializeJson() failed: "));
          Serial.println(error.c_str());
        }
        const char* url = doc["url"];
        Serial.print("Get URL:");
        Serial.println(url);
    }
    else
    {
        Serial.print("Error on sending POST: ");
        Serial.println(httpResponseCode);
    }
   
    Serial.print("HTTP Response code: ");
    Serial.println(httpResponseCode);
    */
    http.end();
}
/*----------------------------------------------------------------------------*/
void ClientI(void)
{
    camera_fb_t * fb = esp_camera_fb_get(); 
    fb->len=0;
    *fb->buf=NULL;
    Serial.println(*fb->buf);

    File file = SD_MMC.open("/0/1.jpg", FILE_READ);
    if(!file)
    {
        Serial.println("文件打开失败");
        file.close();
    }
    else
    {
        fb->len = file.size();
        file.read(fb->buf, fb->len);
        file.close();
        Serial.println("成功读取照片");
    }

    HTTPClient http;
    http.begin("http://images.bemfa.com/upload/v1/upimages.php");
    
    http.addHeader("Content-Type", "image/jpg");
    http.addHeader("Authorization", "c8665cdc8f0a5f8d908155f36ab8038b");
    http.addHeader("Authtopic", "esp32img");
    http.addHeader("Wechatmsg", "Pic come!");

    int httpResponseCode = http.POST((uint8_t *)fb->buf, fb->len);
    if(httpResponseCode==200)
    {
        //获取post请求后的服务器响应信息,json格式
        String response = http.getString();
        Serial.print("Response Msg:");
        Serial.println(response);

        //json数据解析
        StaticJsonDocument<200> doc;
        DeserializationError error = deserializeJson(doc, response);
        if (error)
        {
          Serial.print(F("deserializeJson() failed: "));
          Serial.println(error.c_str());
        }
        const char* url = doc["url"];
        Serial.print("Get URL:");
        Serial.println(url);
    }
    else
    {
        Serial.print("Error on sending POST: ");
        Serial.println(httpResponseCode);
    }
   
    Serial.print("HTTP Response code: ");
    Serial.println(httpResponseCode);
    http.end();
    
    esp_camera_fb_return(fb);
}


void setup() {
    Serial.begin(115200);

    WifiInit();
    SdInit();
    //CamInit();
    ClientInit();
    //ClientI();
}

void loop() {
  // put your main code here, to run repeatedly:

}

Arduino-RTOS-摄像

#if CONFIG_FREERTOS_UNICORE
#define ARDUINO_RUNNING_CORE 0
#else
#define ARDUINO_RUNNING_CORE 1
#endif

#include "WiFi.h"
#include "FS.h"
#include "SD_MMC.h"
#include <HTTPClient.h>
#include "esp_camera.h"

#define BLINK_PIN 33

void BlinkTask( void *pvParameters );
void InitTask( void *pvParameters );


/*----------------------------------------------------------------------------*/
void WifiInit(void)
{
    Serial.print("\nConnect wifi ...");
    WiFi.begin();
    int count = 0;
    while(WiFi.status() != WL_CONNECTED)
    {
        delay(1000);
        Serial.printf(".%d", 10-count);
        count++;
        if(count > 10)
        {
            WiFi.mode(WIFI_AP_STA);
            WiFi.beginSmartConfig();
            Serial.print("\nWaiting for Smartconfig ...");
            while(!WiFi.smartConfigDone())
            {
                delay(1000);
                Serial.printf(".");
            }
            Serial.println("\nSmartconfig done!");
            WiFi.setAutoConnect(true);
            count = 0;
            break;
        }
    }
    Serial.println("\nWifi connected.");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
}
/*----------------------------------------------------------------------------*/
void listDir(fs::FS &fs, const char * dirname, uint8_t levels)
{
    Serial.printf("Listing directory: %s\n", dirname);

    File root = fs.open(dirname);
    if(!root)
    {
        Serial.println("Failed to open directory");
        return;
    }
    if(!root.isDirectory())
    {
        Serial.println("Not a directory");
        return;
    }

    File file = root.openNextFile();
    while(file){
        if(file.isDirectory())
        {
            Serial.print("  DIR : ");
            Serial.println(file.name());
            if(levels)
                listDir(fs, file.name(), levels -1);
        }
        else
        {
            Serial.print("  FILE: ");
            Serial.print(file.name());
            Serial.print("  SIZE: ");
            Serial.println(file.size());
        }
        file = root.openNextFile();
    }
}

void createDir(fs::FS &fs, const char * path)
{
    Serial.printf("Creating Dir: %s\n", path);
    if(fs.mkdir(path))
        Serial.println("Dir created");
    else
        Serial.println("mkdir failed");
}

void removeDir(fs::FS &fs, const char * path)
{
    Serial.printf("Removing Dir: %s\n", path);
    if(fs.rmdir(path))
        Serial.println("Dir removed");
    else
        Serial.println("rmdir failed");
}

void readFile(fs::FS &fs, const char * path)
{
    Serial.printf("Reading file: %s\n", path);

    File file = fs.open(path);
    if(!file)
    {
        Serial.println("Failed to open file for reading");
        return;
    }

    Serial.print("Read from file: ");
    while(file.available())
        Serial.write(file.read());
}

void writeFile(fs::FS &fs, const char * path, const char * message)
{
    Serial.printf("Writing file: %s\n", path);

    File file = fs.open(path, FILE_WRITE);
    if(!file)
    {
        Serial.println("Failed to open file for writing");
        return;
    }
    if(file.print(message))
        Serial.println("File written");
    else
        Serial.println("Write failed");
}

void appendFile(fs::FS &fs, const char * path, const char * message)
{
    Serial.printf("Appending to file: %s\n", path);

    File file = fs.open(path, FILE_APPEND);
    if(!file)
    {
        Serial.println("Failed to open file for appending");
        return;
    }
    if(file.print(message))
        Serial.println("Message appended");
    else
        Serial.println("Append failed");
}

void renameFile(fs::FS &fs, const char * path1, const char * path2)
{
    Serial.printf("Renaming file %s to %s\n", path1, path2);
    if(fs.rename(path1, path2))
        Serial.println("File renamed");
    else
        Serial.println("Rename failed");
}

void deleteFile(fs::FS &fs, const char * path)
{
    Serial.printf("Deleting file: %s\n", path);
    if(fs.remove(path))
        Serial.println("File deleted");
    else
        Serial.println("Delete failed");
}

void SdInit(void)
{
    if(!SD_MMC.begin())
    {
        Serial.println("Card Mount Failed");
        return;
    }
    
    uint8_t cardType = SD_MMC.cardType();
    Serial.print("SD_MMC Card Type: ");
    if(cardType == CARD_MMC)
        Serial.println("MMC");
    else if(cardType == CARD_SD)
        Serial.println("SDSC");
    else if(cardType == CARD_SDHC)
        Serial.println("SDHC");
    else
        Serial.println("UNKNOWN");
    
    Serial.printf("Card Size: %lluMB\n", SD_MMC.cardSize() / (1024 * 1024));
    Serial.printf("Total space: %lluMB\n", SD_MMC.totalBytes() / (1024 * 1024));
    Serial.printf("Used space: %lluMB\n", SD_MMC.usedBytes() / (1024 * 1024));
    
    //listDir(SD_MMC, "/", 2);
}
/*----------------------------------------------------------------------------*/

void ClientInit(void)
{
    Serial.println("C00");
    camera_fb_t *fb = esp_camera_fb_get();
    fb->len = 0;
    Serial.println("C01");
    *fb->buf = NULL;

    Serial.println("C0");
    File fileC = SD_MMC.open("/CaptureLS01/87.JPG");
    Serial.println("C1");
    if(!fileC)
    {
        Serial.println("Failed to open file!");
        return;
    }
    else
    {
        fb->len = fileC.size();
        fileC.read(fb->buf, fb->len);
        fileC.close();
        Serial.println("C6");
    }
    Serial.println("C2");

    int httpResponseCode = 0;
    HTTPClient http;
    Serial.println("C3");
    http.begin("http://192.168.1.232/files/");
    
    Serial.println("C4");
    http.addHeader("Content-Type", "image/jpg");
    //http.addHeader("Authorization", uid); //设置用户UID私钥
    http.addHeader("Authtopic", "ESP");

    Serial.println("C5");
    httpResponseCode = http.POST((uint8_t *)fb->buf,  fb->len);
    Serial.println("C7");
    if(httpResponseCode==200){
        String response = http.getString();  //Get the response to the request
        Serial.println(response);           //Print request answer
    }else{
        Serial.print("Error on sending POST: ");
        Serial.println(httpResponseCode);
    }
   
    Serial.print("HTTP Response code: ");
    Serial.println(httpResponseCode);
    http.end();
}




// The setup function runs once when you press reset or power the board
void setup()
{
  
    Serial.begin(115200);
    
    xTaskCreatePinnedToCore(
        BlinkTask
        ,  "BlinkTask"  // A name just for humans
        ,  1024         // This stack size can be checked & adjusted by reading the Stack Highwater
        ,  NULL
        ,  2            // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
        ,  NULL 
        ,  0);          // Core

    xTaskCreatePinnedToCore(
        InitTask
        ,  "InitTask"
        ,  10240     // Stack size
        ,  NULL
        ,  2        // Priority
        ,  NULL 
        ,  0);

    // Now the task scheduler, which takes over control of scheduling individual tasks, is automatically started.
}

void loop()
{
    // Empty. Things are done in Tasks.
}

/*--------------------------------------------------*/
/*---------------------- Tasks ---------------------*/
/*--------------------------------------------------*/

void BlinkTask(void *pvParameters)
{
    (void) pvParameters;
    pinMode(BLINK_PIN, OUTPUT);
    for (;;) // A Task shall never return or exit.
    {
        // Turn the LED on (LOW is the voltage level)
        digitalWrite(BLINK_PIN, LOW);
        vTaskDelay(100);
        digitalWrite(BLINK_PIN, HIGH);
        vTaskDelay(100);
        digitalWrite(BLINK_PIN, LOW);
        vTaskDelay(100);
        digitalWrite(BLINK_PIN, HIGH);
        vTaskDelay(1000);
    }
}

void InitTask(void *pvParameters)
{
    (void) pvParameters;

    WifiInit();
    SdInit();
    ClientInit();

    for (;;)
    {
        vTaskDelay(10);
    }
}

ESP-RTOS-指令

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_wifi.h"
#include "esp_http_client.h"
#include "esp_log.h"
#include "nvs_flash.h"

#include "sdkconfig.h"

#include "driver/gpio.h"
#include "driver/uart.h"

#include "lwip/err.h"
#include "lwip/sys.h"

/*----------------------------------------------------------------------------*/
#define DEBUG_ATY   1
/*----------------------------------------------------------------------------*/
uint8_t wifiLte = 0;    //0:Wifi, 1:Lte
#define LTE_EN_PIN 21
static nvs_handle_t nvsHandle;
uint8_t lteState = 0;
/*----------------------------------------------------------------------------*/
#define SSID        "ESPL"
#define PASSWORD    "00000000"
#define MAXIMUM_WIFI_RETRY 5
// char *SSID = "ESPL";
// char *PASSWORD = "00000000";
#define WIFI_EN_PIN 19

uint8_t wifiState = 0;
static int wifiRetryNum = 0;
/* FreeRTOS event group to signal when we are connected*/
static EventGroupHandle_t s_wifi_event_group;
/* The event group allows multiple bits for each event, but we only care about two events:
 * - we are connected to the AP with an IP
 * - we failed to connect after the maximum amount of retries */
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT      BIT1

/*----------------------------------------------------------------------------*/
#define MAXIMUM_GET_RETRY   5
#define MAXIMUM_SEND_RETRY  20
uint8_t doorOpenStateFlag = 0;   //Flag 0:None, 1:First, 2:Check sure, 3:Sure at end
uint8_t doorCloseStateFlag = 0;
uint8_t doorAskStateFlag = 0;
uint8_t httpGetFlag = 0;
uint8_t doorOpenCmdFlag = 0;
uint8_t httpRetryCount = 0;
uint8_t httpGetRetryCount = 0;
char *httpGetMsg = "";
const char sureBackCmd[10] = {0xAA, 0x55, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
const char addUserCmd[10] = {0xAA, 0x55, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02};
const char openDoorCmd[10] = {0xAA, 0x55, 0x13, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13};
const char imgSureCmd[10] = {0xAA, 0x55, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C};
// const char doorOpenCmd[8] = {0xF5, 0x01, 0x05, 0x02, 0x01, 0x01, 0xF3, 0x0A};
// const char doorOpenStateCmd[8] = {0xF5, 0x01, 0x05, 0x02, 0x01, 0x01, 0xF3, 0x0A};
// const char doorCloseStateCmd[8] = {0xF5, 0x01, 0x05, 0x02, 0x01, 0x00, 0xF2, 0x0A};
// const char doorAskStateCmd[7] = {0xF5, 0x01, 0x04, 0x09, 0x03, 0xFA, 0x0A};

/*----------------------------------------------------------------------------*/
/* Can use project configuration menu (idf.py menuconfig) to choose the GPIO to blink,
   or you can edit the following line and set a number here.
*/
//#define BLINK_GPIO CONFIG_BLINK_GPIO
#define BLINK_GPIO 2
// #define TXD0_PIN (GPIO_NUM_1)
// #define RXD0_PIN (GPIO_NUM_3)
/* Use default 9/10 will cause core dump:
   Guru Meditation Error: Core  0 panic'ed (IllegalInstruction). Exception was unhandled.
   Memory dump at 0x40115950: ffffffff ffffffff ffffffff
   0x40115950: lmac_stop_hw_txq at ??:?
*/
#define TXD1_PIN (GPIO_NUM_23)
#define RXD1_PIN (GPIO_NUM_22)
#define TXD2_PIN (GPIO_NUM_17)
#define RXD2_PIN (GPIO_NUM_16)
#define RTS_PIN  (UART_PIN_NO_CHANGE)
#define CTS_PIN  (UART_PIN_NO_CHANGE)
// #define RX_BUF_SIZE 1024
#define RX_BUF_SIZE 2048

/*----------------------------------------------------------------------------*/
int Uart1SendDataHex(const char* data, const uint8_t length);
int Uart1SendData(const char* data);
int Uart2SendData(const char* data);
void NvsInit(void);
esp_err_t NvsReadMode(void);
esp_err_t NvsWriteMode(void);
void ChipRestart(int seconds);
void OpenCloseDoor(void);



/*----------------------------------------------------------------------------*/
static void event_handler(void* arg, esp_event_base_t event_base,
                            int32_t event_id, void* event_data)
{
    if(event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
    {
        esp_wifi_connect();
    }
    else if(event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
    {
        if(wifiRetryNum < MAXIMUM_WIFI_RETRY)
        {
            esp_wifi_connect();
            wifiRetryNum++;
            ESP_LOGI("WifiInit", "Retry to connect to the AP");
        }
        else
        {
            xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
        }
        ESP_LOGI("WifiInit","Connect to the AP fail");
    }
    else if(event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
    {
        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
        ESP_LOGI("WifiInit", "Got ip:" IPSTR, IP2STR(&event->ip_info.ip));
        wifiRetryNum = 0;
        xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
    }
}

void WifiInit(void)
{
    s_wifi_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_create_default_wifi_sta();
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    esp_event_handler_instance_t instance_any_id;
    esp_event_handler_instance_t instance_got_ip;
    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
                                                        ESP_EVENT_ANY_ID,
                                                        &event_handler,
                                                        NULL,
                                                        &instance_any_id));
    ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
                                                        IP_EVENT_STA_GOT_IP,
                                                        &event_handler,
                                                        NULL,
                                                        &instance_got_ip));

    wifi_config_t wifi_config = {
        .sta = {
            .ssid = SSID,
            .password = PASSWORD,
            /* Setting a password implies station will connect to all security modes including WEP/WPA.
             * However these modes are deprecated and not advisable to be used. Incase your Access point
             * doesn't support WPA2, these mode can be enabled by commenting below line */
            .threshold.authmode = WIFI_AUTH_WPA2_PSK,
            //.listen_interval = DEFAULT_LISTEN_INTERVAL,   //Power Save
            .pmf_cfg = {
                .capable = true,
                .required = false
            },
        },
    };
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
    ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
    ESP_ERROR_CHECK(esp_wifi_start() );
    //esp_wifi_set_ps(DEFAULT_PS_MODE);     //Power Save
    ESP_LOGI("WifiInit", "Wifi_init_sta finished.");

    /* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
     * number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
    EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
            WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
            pdFALSE,
            pdFALSE,
            portMAX_DELAY);

    /* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
     * happened. */
    if(bits & WIFI_CONNECTED_BIT)
    {
        wifiState = 1;
        ESP_LOGI("WifiInit", "Connected to ap SSID:%s password:%s",
                 SSID, PASSWORD);
    }
    else if(bits & WIFI_FAIL_BIT)
    {
        ESP_LOGI("WifiInit", "Failed to connect to SSID:%s, password:%s",
                 SSID, PASSWORD);
    }
    else
    {
        ESP_LOGE("WifiInit", "UNEXPECTED EVENT");
    }

    /* The event will not be processed after unregister */
    ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, instance_got_ip));
    ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id));
    vEventGroupDelete(s_wifi_event_group);
}


/*----------------------------------------------------------------------------*/
#define MAX_HTTP_OUTPUT_BUFFER 2048
char output_buffer[MAX_HTTP_OUTPUT_BUFFER] = {0};
static uint8_t HttpGetWifi(const char *urlGet)
{
    if(wifiState)
    {
        int content_length = 0;
        esp_http_client_config_t config = {
            .url = urlGet,
        };
        esp_http_client_handle_t client = esp_http_client_init(&config);

        // GET Request
        esp_http_client_set_method(client, HTTP_METHOD_GET);
        esp_err_t err = esp_http_client_open(client, 0);
        if(err != ESP_OK)
        {
            ESP_LOGE("HttpGetWifi", "Failed to open HTTP connection: %s", esp_err_to_name(err));
        }
        else
        {
            content_length = esp_http_client_fetch_headers(client);
            if(content_length < 0)
            {
                ESP_LOGE("HttpGetWifi", "HTTP client fetch headers failed");
            }
            else
            {
                int data_read = esp_http_client_read_response(client, output_buffer, MAX_HTTP_OUTPUT_BUFFER);
                if(data_read >= 0) 
                {
                    ESP_LOGI("HttpGetWifi", "HTTP GET Status = %d, content_length = %d",
                    esp_http_client_get_status_code(client),
                    esp_http_client_get_content_length(client));
                    ESP_LOGI("HttpGetWifi", "%d - %s", strlen(output_buffer), output_buffer);
                    
                    esp_http_client_close(client);
                    esp_http_client_cleanup(client);
                    return 1;
                }
                else
                {
                    ESP_LOGE("HttpGetWifi", "Failed to read response");
                }
            }
        }
        esp_http_client_close(client);
        esp_http_client_cleanup(client);
    }
    else
    {
        ESP_LOGE("HttpGetWifi", "No wifi connected!");
    }
    return 0;
}

uint8_t sendStep = 5;
static uint8_t HttpGetLte(const char *urlGet)
{
    uint8_t *data = (uint8_t*) malloc(RX_BUF_SIZE+1);
    uint8_t successFlag = 0;
    uint8_t sleepTime = 0;
    while(1)
    {
        if(sendStep == 0)
        {
            //Check 4G model
            while(1)
            {
                Uart2SendData("AT\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT\r\n\r\nOK\r\n"))
                        sendStep = 1;
                    else
                        ESP_LOGI("HttpGetLte", "@0:%s", (char *)data);
                    break;
                }
            }
            if(sleepTime)
                vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
        }
        else if(sendStep == 1)
        {
            //Check SIM card
            while(1)
            {
                Uart2SendData("AT+CPIN?\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+CPIN?\r\n\r\n+CPIN: READY\r\n\r\nOK\r\n"))
                        sendStep = 2;
                    else
                        ESP_LOGI("HttpGetLte", "@1:%s", (char *)data);
                    break;
                }
            }
            if(sleepTime)
                vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
        }
        else if(sendStep == 2)
        {
            //Check regist
            while(1)
            {
                Uart2SendData("AT+CGATT?\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+CGATT?\r\n\r\n+CGATT: 1\r\n\r\nOK\r\n"))
                        sendStep = 3;
                    else
                        ESP_LOGI("HttpGetLte", "@2:%s", (char *)data);
                    break;
                }
            }
            if(sleepTime)
                vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
        }
        else if(sendStep == 3)
        {
            //Set APN
            while(1)
            {
                Uart2SendData("AT+CSTT\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+CSTT\r\n\r\nOK\r\n"))
                        sendStep = 4;
                    else if(strstr((char *)data, "AT+CSTT\r\n\r\n") && strstr((char *)data, "+CME ERROR"))
                        sendStep = 5;
                    else
                        ESP_LOGI("HttpGetLte", "@3:%s", (char *)data);
                    break;
                }
            }
            if(sleepTime)
                vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
        }
        else if(sendStep == 4)
        {
            //Active network
            while(1)
            {
                Uart2SendData("AT+CIICR\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+CIICR\r\n\r\nOK\r\n"))
                        sendStep = 5;
                    else if(strstr((char *)data, "AT+CIICR\r\n\r\n") && strstr((char *)data, "+CME ERROR"))
                        sendStep = 0;
                    else
                        ESP_LOGI("HttpGetLte", "@4:%s", (char *)data);
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else if(sendStep == 5)
        {
            //Check ip
            while(1)
            {
                Uart2SendData("AT+CIFSR\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+CIFSR\r\n\r\n") && !strstr((char *)data, "+CME ERROR"))
                        sendStep = 6;
                    else if(strstr((char *)data, "AT+CIFSR\r\n\r\n") && strstr((char *)data, "+CME ERROR"))
                    {
                        while(1)
                        {
                            Uart2SendData("AT+CIPSHUT\r\n");
                            const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                            if(rxBytes > 0)
                            {
                                data[rxBytes] = 0;
                                if(strstr((char *)data, "AT+CIPSHUT\r\n\r\nSHUT OK\r\n"))
                                    sendStep = 3;
                                else
                                    ESP_LOGI("HttpGetLte", "@5-1:%s", (char *)data);
                                break;
                            }
                        }
                    }
                    else
                        ESP_LOGI("HttpGetLte", "@5-2:%s", (char *)data);
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else if(sendStep == 6)
        {
            while(1)
            {
                Uart2SendData("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"\r\n\r\nOK\r\n"))
                        sendStep = 7;
                    else
                        ESP_LOGI("HttpGetLte", "@6:%s", (char *)data);
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else if(sendStep == 7)
        {
            while(1)
            {
                Uart2SendData("AT+SAPBR=3,1,\"APN\",\"\"\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+SAPBR=3,1,\"APN\",\"\"\r\n\r\nOK\r\n"))
                        sendStep = 8;
                    else
                        ESP_LOGI("HttpGetLte", "@7:%s", (char *)data);
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else if(sendStep == 8)
        {
            while(1)
            {
                Uart2SendData("AT+SAPBR=1,1\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+SAPBR=1,1\r\n\r\nOK\r\n"))
                        sendStep = 9;
                    else if(strstr((char *)data, "AT+SAPBR=1,1\r\n\r\n") && strstr((char *)data, "+CME ERROR"))
                        sendStep = 9;
                    else
                        ESP_LOGI("HttpGetLte", "@8:%s", (char *)data);
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else if(sendStep == 9)
        {
            while(1)
            {
                Uart2SendData("AT+SAPBR=2,1\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+SAPBR=2,1\r\n\r\n") && strstr((char *)data, "+SAPBR: 1,1,"))
                        sendStep = 10;
                    else if(strstr((char *)data, "AT+SAPBR=2,1\r\n\r\n") && !strstr((char *)data, "+SAPBR: 1,1,"))
                        sendStep = 8;
                    else
                        ESP_LOGI("HttpGetLte", "@9:%s", (char *)data);
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else if(sendStep == 10)
        {
            //Init http
            while(1)
            {
                Uart2SendData("AT+HTTPINIT\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+HTTPINIT\r\n\r\nOK\r\n"))
                        sendStep = 11;
                    else if(strstr((char *)data, "AT+HTTPINIT\r\n\r\n") && strstr((char *)data, "+CME ERROR: 3"))
                        sendStep = 11;
                    else
                        ESP_LOGI("HttpGetLte", "@10:%s", (char *)data);
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else if(sendStep == 11)
        {
            //Set http CID
            while(1)
            {
                Uart2SendData("AT+HTTPPARA=\"CID\",1\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+HTTPPARA=\"CID\",1\r\n\r\nOK\r\n"))
                        sendStep = 12;
                    else
                        ESP_LOGI("HttpGetLte", "@11:%s", (char *)data);
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else if(sendStep == 12)
        {
            //Set url
            char *sendUrlTempStr = (char *) malloc(MAX_HTTP_OUTPUT_BUFFER);
            sprintf(sendUrlTempStr, "AT+HTTPPARA=\"URL\",\"%s\"\r\n", urlGet);
            while(1)
            {
                Uart2SendData(sendUrlTempStr);
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+HTTPPARA=\"URL\",") && strstr((char *)data, "OK\r\n"))
                        sendStep = 13;
                    else
                        ESP_LOGI("HttpGetLte", "@12:%s", (char *)data);
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else if(sendStep == 13)
        {
            //Send http
            while(1)
            {
                Uart2SendData("AT+HTTPACTION=1\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    //if(strstr((char *)data, "AT+HTTPACTION=1\r\n\r\nOK\r\n"))
                        //sendStep = 14;
                        //break;
                    if(strstr((char *)data, "+HTTPACTION: 1,200,"))
                    {
                        sendStep = 14;
                        // break;
                    }
                    else
                        ESP_LOGI("HttpGetLte", "@13:%s", (char *)data);
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else if(sendStep == 14)
        {
            //Get response
            while(1)
            {
                Uart2SendData("AT+HTTPREAD\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+HTTPREAD\r\n\r\n+HTTPREAD:"))
                    {
                        successFlag = 1;
                        strcpy(output_buffer, (char *)data);
                        ESP_LOGI("HttpGetLte", "%s", output_buffer);
                        sendStep = 15;
                    }
                    else
                        ESP_LOGI("HttpGetLte", "@14:%s", (char *)data);
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else if(sendStep == 15)
        {
            //Terminate http
            while(1)
            {
                Uart2SendData("AT+HTTPTERM\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+HTTPTERM\r\n\r\nOK\r\n"))
                        sendStep = 16;
                    else if(strstr((char *)data, "AT+HTTPTERM\r\n\r\n") && strstr((char *)data, "+CME ERROR: 3"))
                        sendStep = 16;
                    else
                        ESP_LOGI("HttpGetLte", "@15:%s", (char *)data);
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else if(sendStep == 16)
        {
            //Shutdown network
            while(1)
            {
                Uart2SendData("AT+CIPSHUT\r\n");
                const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);;
                if(rxBytes > 0)
                {
                    data[rxBytes] = 0;
                    if(strstr((char *)data, "AT+CIPSHUT\r\n\r\nSHUT OK\r\n"))
                        sendStep = 20;
                    else if(strstr((char *)data, "AT+CIPSHUT\r\n\r\n") && strstr((char *)data, "+CME ERROR: 3"))
                        sendStep = 20;
                    else
                    {
                        //sendStep = 20;
                        ESP_LOGI("HttpGetLte", "@16:%s", (char *)data);
                    }
                    break;
                }
                if(sleepTime)
                    vTaskDelay(sleepTime*1000 / portTICK_PERIOD_MS);
            }
        }
        else
        {
            if(successFlag)
            {
                sendStep = 5;
                return 1;
            }
            else
            {
                //sendStep = 17;
                return 0;
            }
            //vTaskDelay(1000 / portTICK_PERIOD_MS);
        }
        ESP_LOGI("HttpGetLteStep", "%d", sendStep);
    }
    free(data);
    return 0;
}


static int HttpSendQos(const char *urlGet)
{
    if(wifiLte || wifiState)
    {
        uint8_t responseFlag = 0;
        if(!wifiLte)
        {
            responseFlag = HttpGetWifi(urlGet);
            ESP_LOGI("HttpSendQos", "Use wifi.");
        }
        else
        {
            responseFlag = HttpGetLte(urlGet);
            ESP_LOGI("HttpSendQos", "Use lte.");
        }
        if(responseFlag)
        {
            if(strstr(output_buffer, "sendok")) //Null
            {
                ESP_LOGI("HttpSendQos", "OK!");
                memset(output_buffer, 0x00, sizeof(output_buffer));
                return 1;
            }
            else if(strstr(output_buffer, "getok") || strstr(output_buffer, "msg"))
            {
                // strcpy(httpGetMsg, resState);
                if(strstr(output_buffer, "Door-Oc"))
                {
                    memset(output_buffer, 0x00, sizeof(output_buffer));
                    ESP_LOGW("HttpSendQos", "Open door!");
                    return 1;
                }
                else if(strstr(output_buffer, "CMD-WIFI"))
                {
                    ESP_LOGI("HttpSendQos", "Setting wifi mode ...");
                    wifiLte = 0;
                    if(NvsWriteMode() == ESP_OK)
                    {
                        ESP_LOGI("HttpSendQos", "Set wifi mode success!");
                        Uart1SendDataHex(openDoorCmd, 10);
                        ChipRestart(1);
                    }
                    else
                        ESP_LOGI("HttpSendQos", "Set wifi mode fail!");
                }
                else if(strstr(output_buffer, "CMD-LTE"))
                {
                    ESP_LOGI("HttpSendQos", "Setting lte mode ...");
                    wifiLte = 1;
                    if(NvsWriteMode() == ESP_OK)
                    {
                        ESP_LOGI("HttpSendQos", "Set lte mode success!");
                        Uart1SendDataHex(openDoorCmd, 10);
                        ChipRestart(1);
                    }
                    else
                        ESP_LOGI("HttpSendQos", "Set lte mode fail!");
                }
            }
        }
    }
    else
    {
        ESP_LOGE("HttpSendQos", "No wifi/lte connected!");
    }
    return 0;
}

/*----------------------------------------------------------------------------*/



void UartInit(void)
{
    const uart_config_t uart_config = {
        .baud_rate = 9600,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_APB,
    };
    // We won't use a buffer for sending data.
    uart_driver_install(UART_NUM_1, RX_BUF_SIZE * 2, 0, 0, NULL, 0);
    uart_param_config(UART_NUM_1, &uart_config);
    uart_set_pin(UART_NUM_1, TXD1_PIN, RXD1_PIN, RTS_PIN, CTS_PIN);
    uart_driver_install(UART_NUM_2, RX_BUF_SIZE * 2, 0, 0, NULL, 0);
    uart_param_config(UART_NUM_2, &uart_config);
    uart_set_pin(UART_NUM_2, TXD2_PIN, RXD2_PIN, RTS_PIN, CTS_PIN);
}

int Uart1SendDataHex(const char* data, const uint8_t length)
{
    const int txBytes = uart_write_bytes(UART_NUM_1, data, length);
    // ESP_LOGW("RX1_TASK", "txBytes:%d length:%d %s", txBytes, length, data);
    // ESP_LOG_BUFFER_HEXDUMP("RX1_TASK", data, txBytes, ESP_LOG_WARN);
    return txBytes;
}
int Uart1SendData(const char* data)
{
    const int txBytes = uart_write_bytes(UART_NUM_1, data, strlen(data));
    // ESP_LOGW("RX1_TASK", "txBytes:%d strlen:%d %s", txBytes, strlen(data), data);
    // ESP_LOG_BUFFER_HEXDUMP("RX1_TASK", data, txBytes, ESP_LOG_WARN);
    return txBytes;
}
int Uart2SendData(const char* data)
{
    const int txBytes = uart_write_bytes(UART_NUM_2, data, strlen(data));
    return txBytes;
}

#define INCLUDE_uxTaskGetStackHighWaterMark 1
xTaskHandle rx1_task_handle;
//I (619096) rx1_task: Tsak free heap: 2064(1024*4)

static void rx1_task(void *arg)
{
    uint8_t *data = (uint8_t*) malloc(RX_BUF_SIZE+1);
    int rxBytes = 0;
    uint8_t addUserFlag = 0;
    while(1)
    {
        ESP_LOGI("rx1_task_heap", "Tsak free heap: %d\n", uxTaskGetStackHighWaterMark(rx1_task_handle));
        // rxBytes = uart_read_bytes(UART_NUM_1, data, RX_BUF_SIZE, 1000 / portTICK_RATE_MS);
        rxBytes = uart_read_bytes(UART_NUM_1, data, RX_BUF_SIZE, 100 / portTICK_RATE_MS);
        if(rxBytes > 0)
        {
            data[rxBytes] = 0;
            for(int i = 0; i < rxBytes; i++)
            {
                if((data[i] == 0xAA) && (data[i+1] == 0x55))
                {
                    if((data[i+2] == 0x06) && (data[i+9] == 0x05))
                    {
                        addUserFlag = 1;
                        Uart1SendDataHex(sureBackCmd, 10);
                        ESP_LOGW("RX1_TASK", "AA 55 06");
                    }
                    else if((data[i+2] == 0x01) && (data[i+3] == 0x16))
                    {
                        addUserFlag = 0;
                        Uart1SendDataHex(addUserCmd, 10);
                        ESP_LOGW("RX1_TASK", "AA 55 01 16");
                    }
                    else if((data[i+2] == 0x1C) && (data[i+9] == 0x1B))
                    {
                        // Uart1SendDataHex(imgSureCmd, 10);
                        // ESP_LOGW("RX1_TASK", "AA 55 1C");
                    }
                    else if((data[i+2] == 0x03) && (data[i+3] == 0x01))
                    {
                        addUserFlag = 0;
                        httpRetryCount = 0;
                        doorOpenStateFlag = 1;
                        doorCloseStateFlag = 0;
                        httpGetFlag = 0;
                        Uart1SendDataHex(sureBackCmd, 10);
                        ESP_LOGW("RX1_TASK", "Door opened!");
                    }
                    else if((data[i+2] == 0x03) && (data[i+3] == 0x00))
                    {
                        addUserFlag = 0;
                        httpRetryCount = 0;
                        doorOpenStateFlag = 0;
                        doorCloseStateFlag = 1;
                        httpGetFlag = 0;
                        Uart1SendDataHex(sureBackCmd, 10);
                        ESP_LOGW("RX1_TASK", "Door closed!");
                    }
                    else if((data[i+2] == 0x03) && (data[i+3] == 0x03))
                    {
                        httpRetryCount = 0;
                        doorAskStateFlag = 1;
                        httpGetFlag = 0;
                        doorCloseStateFlag = 0;
                        doorOpenStateFlag = 0;
                        //Uart1SendDataHex(sureBackCmd, 10);
                        ESP_LOGW("RX1_TASK", "Door ask!");
                    }
                    else
                        ESP_LOGE("RX1_TASK", "Wrong command!");
                }
            }
            ESP_LOGI("RX1_TASK", "Read %d bytes: '%s'", rxBytes, data);
            ESP_LOG_BUFFER_HEXDUMP("RX1_TASK", data, rxBytes, ESP_LOG_INFO);
        }
        rxBytes = 0;
        //memset(data, 0, RX_BUF_SIZE+1);
        
        if(doorOpenStateFlag)
        {
            httpRetryCount++;
            if(HttpSendQos("http://api.bemfa.com/api/device/v1/data/3/push/get/?uid=c8665cdc8f0a5f8d908155f36ab8038b&topic=K210T1&msg=Door-Od") || (httpRetryCount > MAXIMUM_GET_RETRY))
            {
                httpRetryCount = 0;
                doorOpenStateFlag = 0;
                doorOpenCmdFlag = 0;
            }
        }
        else if(doorCloseStateFlag)
        {
            httpRetryCount++;
            if(HttpSendQos("http://api.bemfa.com/api/device/v1/data/3/push/get/?uid=c8665cdc8f0a5f8d908155f36ab8038b&topic=K210T1&msg=Door-Cd") || (httpRetryCount > MAXIMUM_GET_RETRY))
            {
                httpRetryCount = 0;
                doorCloseStateFlag = 0;
                doorOpenCmdFlag = 0;
            }
        }
        else if(doorAskStateFlag)
        {
            httpRetryCount++;
            if(wifiLte)
            {
                if(HttpSendQos("http://api.bemfa.com/api/device/v1/data/3/push/get/?uid=c8665cdc8f0a5f8d908155f36ab8038b&topic=K210T1&msg=Door-ASKl") || (httpRetryCount > MAXIMUM_GET_RETRY))
                {
                    httpGetRetryCount = 0;
                    doorAskStateFlag = 0;
                    httpGetFlag = 1;
                }
            }
            else
            {
                if(HttpSendQos("http://api.bemfa.com/api/device/v1/data/3/push/get/?uid=c8665cdc8f0a5f8d908155f36ab8038b&topic=K210T1&msg=Door-ASKw") || (httpRetryCount > MAXIMUM_GET_RETRY))
                {
                    httpGetRetryCount = 0;
                    doorAskStateFlag = 0;
                    httpGetFlag = 1;
                }
            }
        }
        if(httpGetFlag)
        {
            httpGetRetryCount++;
            if(HttpSendQos("http://api.bemfa.com/api/device/v1/data/3/get/?uid=c8665cdc8f0a5f8d908155f36ab8038b&topic=K210T1&num=1"))
            {
                httpGetRetryCount = 0;
                httpGetFlag = 0;
                doorOpenCmdFlag = 1;
            }
            if(httpGetRetryCount > MAXIMUM_SEND_RETRY)
            {
                httpGetRetryCount = 0;
                httpGetFlag = 0;
                doorOpenCmdFlag = 0;
            }
        }
        if(doorOpenCmdFlag)
        {
            ESP_LOGI("RX1_TASK", "Open door ...");
            Uart1SendDataHex(openDoorCmd, 10);
            doorOpenCmdFlag = 0;
            vTaskDelay(200 / portTICK_PERIOD_MS);
        }
        if(addUserFlag)
        {
            Uart1SendDataHex(sureBackCmd, 10);
            ESP_LOGI("RX1_TASK", "addUserFlag");
        }
    }
    free(data);
}

/*----------------------------------------------------------------------------*/
void InitShowToSerial(void)
{
    /* Print chip information */
    esp_chip_info_t chip_info;
    esp_chip_info(&chip_info);
    ESP_LOGI("InitShowToSerial", "This is %s chip with %d CPU cores, WiFi%s%s",
            CONFIG_IDF_TARGET,
            chip_info.cores,
            (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
            (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");

    ESP_LOGI("InitShowToSerial", "Silicon revision %d", chip_info.revision);

    ESP_LOGI("InitShowToSerial", "%dMB %s flash", spi_flash_get_chip_size() / (1024 * 1024),
            (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");

    ESP_LOGI("InitShowToSerial", "Free heap: %d\n", esp_get_free_heap_size());

    printf("Welcome to LS products!\n");
    Uart1SendData("Welcome to LS products!\n");
    Uart2SendData("Welcome to LS products!\n");

}
/*----------------------------------------------------------------------------*/
void NvsInit(void)
{
    //Initialize NVS
    esp_err_t err = nvs_flash_init();
    if(err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
      ESP_ERROR_CHECK(nvs_flash_erase());
      err = nvs_flash_init();
    }
    ESP_ERROR_CHECK(err);
}
esp_err_t NvsReadMode(void)
{
    // Open
    esp_err_t err = nvs_open("lsStorage", NVS_READWRITE, &nvsHandle);
    if (err != ESP_OK) return err;
    // Read mode
    err = nvs_get_u8(nvsHandle, "wifiLte", &wifiLte);
    if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND)
    {
        wifiLte = 0;
        ESP_LOGE("NvsInit", "No wifiLte nvs value!");
        return err;
    }
    ESP_LOGI("NvsReadMode", "Mode %d", wifiLte);
    // Close
    nvs_close(nvsHandle);
    return ESP_OK;
}
esp_err_t NvsWriteMode(void)
{
    // Open
    esp_err_t err = nvs_open("lsStorage", NVS_READWRITE, &nvsHandle);
    if (err != ESP_OK) return err;
    // Write mode
    err = nvs_set_u8(nvsHandle, "wifiLte", wifiLte);
    if (err != ESP_OK) return err;
    // Commit written value.
    // After setting any values, nvs_commit() must be called to ensure changes are written
    // to flash storage. Implementations may write to storage at other times,
    // but this is not guaranteed.
    err = nvs_commit(nvsHandle);
    if (err != ESP_OK) return err;
    // Close
    nvs_close(nvsHandle);
    return ESP_OK;
}
/*----------------------------------------------------------------------------*/
static xQueueHandle gpio_evt_queue = NULL;

static void IRAM_ATTR gpio_isr_handler(void* arg)
{
    uint32_t gpio_num = (uint32_t) arg;
    xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}
static void wifiEnTask(void* arg)
{
    uint32_t io_num;
    for(;;)
    {
        if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY))
        {
            if(gpio_get_level(io_num))
                Uart1SendData("http://api.bemfa.com/api/device/");
            ESP_LOGI("wifiEnTask", "GPIO[%d] intr, val: %d\n", io_num, gpio_get_level(io_num));
        }
    }
}
#define GPIO_OUTPUT_PIN_SEL  (1ULL<<WIFI_EN_PIN)
#define GPIO_INPUT_PIN_SEL  (1ULL<<WIFI_EN_PIN)
#define ESP_INTR_FLAG_DEFAULT 0
void IoInit(void)
{
    gpio_config_t io_conf;
    //interrupt of rising edge
    io_conf.intr_type = GPIO_INTR_POSEDGE;
    //bit mask of the pins
    io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
    //set as input mode
    io_conf.mode = GPIO_MODE_INPUT;
    io_conf.pull_up_en = 0;
    io_conf.pull_down_en = 1;
    gpio_config(&io_conf);
    //create a queue to handle gpio event from isr
    gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
    //install gpio isr service
    gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
    //hook isr handler for specific gpio pin
    gpio_isr_handler_add(WIFI_EN_PIN, gpio_isr_handler, (void*) WIFI_EN_PIN);
    xTaskCreate(wifiEnTask, "wifiEnTask", 2048, NULL, configMAX_PRIORITIES, NULL);
}
/*----------------------------------------------------------------------------*/
void BlinkTask(void *pvParameter)
{
    /* Configure the IOMUX register for pad BLINK_GPIO (some pads are
       muxed to GPIO on reset already, but some default to other
       functions and need to be switched to GPIO. Consult the
       Technical Reference for a list of pads and their default
       functions.)
    */
    gpio_pad_select_gpio(BLINK_GPIO);
    /* Set the GPIO as a push/pull output */
    gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
    while(1)
    {
        gpio_set_level(BLINK_GPIO, 1);
        vTaskDelay(100 / portTICK_PERIOD_MS);
        gpio_set_level(BLINK_GPIO, 0);
        vTaskDelay(100 / portTICK_PERIOD_MS);
        
        gpio_set_level(BLINK_GPIO, 1);
        vTaskDelay(100 / portTICK_PERIOD_MS);
        gpio_set_level(BLINK_GPIO, 0);
        vTaskDelay(800 / portTICK_PERIOD_MS);
    }

}

/*----------------------------------------------------------------------------*/
void ChipRestart(int seconds)
{
    for(int i = seconds; i >= 0; i--)
    {
        ESP_LOGW("ChipRestart", "Restarting in %d seconds...\n", i);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
    ESP_LOGW("ChipRestart", "Restarting now!");
    fflush(stdout);
    esp_restart();
}


/*----------------------------------------------------------------------------*/
void app_main(void)
{
    /*------------------------------------------------------------------------*/
    esp_log_level_set("*", ESP_LOG_ERROR);
    if(DEBUG_ATY)
    {
        esp_log_level_set("*", ESP_LOG_VERBOSE);
        ESP_LOGI("AppMain", "Debug mode!");
        //WifiInit();
    }
    else
    {
        ESP_LOGE("AppMain", "Product mode!");
    }
    // esp_log_level_set("HttpGetLte", ESP_LOG_ERROR);
    esp_log_level_set("HttpGetLteStep", ESP_LOG_ERROR);
    esp_log_level_set("rx1_task_heap", ESP_LOG_ERROR);
    /*------------------------------------------------------------------------*/
    
    
    /*------------------------------------------------------------------------*/
    UartInit();
    InitShowToSerial();
    // wifiLte = 0;
    // wifiLte = 1;
    NvsInit();
    NvsReadMode();
    gpio_pad_select_gpio(LTE_EN_PIN);
    gpio_set_direction(LTE_EN_PIN, GPIO_MODE_OUTPUT);
    if(!wifiLte)
    {
        gpio_set_level(LTE_EN_PIN, 0);  //LOW
        WifiInit();
    }
    else
    {
        gpio_set_level(LTE_EN_PIN, 1);
    }
    /*------------------------------------------------------------------------*/
    IoInit();
    // 参数:任务函数,任务别名,任务堆栈的深度,参数的指针,任务优先级,回传句柄
    xTaskCreate(rx1_task, "uart1_rx_task", 1024*4, NULL, configMAX_PRIORITIES, &rx1_task_handle);

    /*------------------------------------------------------------------------*/
    while(0)
    {
        if(0)//DEBUG_ATY)
            xTaskCreate(&BlinkTask, "LedBlinkTask", configMINIMAL_STACK_SIZE, NULL, 5, NULL);
        if(HttpSendQos("http://api.bemfa.com/api/device/v1/data/3/push/get/?uid=c8665cdc8f0a5f8d908155f36ab8038b&topic=K210T1&msg=Door-Od"))
            break;
    }
    /*------------------------------------------------------------------------*/
}

ESP-RTOS-摄像

/******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


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

#include "esp_system.h"
#include "esp_log.h"
#include "esp_spi_flash.h"
#include "nvs_flash.h"
#include "sdkconfig.h"

#include "driver/gpio.h"
#include "driver/ledc.h"
#include "esp_camera.h"

#include "esp_vfs_fat.h"
#include "sdmmc_cmd.h"
#include "driver/sdmmc_host.h"

#include "esp_wifi.h"
#include "esp_wpa2.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "esp_smartconfig.h"
#include "esp_sntp.h"
#include "mdns.h"

#include "esp_websocket_client.h"


#include "screen_driver.h"

#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "lwip/dns.h"

/******************************************************************************/



/******************************************************************************/
static const char *TAG = "LS_SmartEye";

#define BLINK_PIN 33
#define SMARTCONFIG_PIN 2
#define BELL_PIN 4

#define CAM_BOARD         "AI-THINKER"
#define CAM_PIN_PWDN    32
#define CAM_PIN_RESET    -1
#define CAM_PIN_XCLK      0
#define CAM_PIN_SIOD     26
#define CAM_PIN_SIOC     27

#define CAM_PIN_D7       35
#define CAM_PIN_D6       34
#define CAM_PIN_D5       39
#define CAM_PIN_D4       36
#define CAM_PIN_D3       21
#define CAM_PIN_D2       19
#define CAM_PIN_D1       18
#define CAM_PIN_D0        5
#define CAM_PIN_VSYNC    25
#define CAM_PIN_HREF     23
#define CAM_PIN_PCLK     22

/******************************************************************************/
// FreeRTOS event group to signal when we are connected & ready to make a request
static EventGroupHandle_t s_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? */
static const int CONNECTED_BIT = BIT0;
static const int ESPTOUCH_DONE_BIT = BIT1;

wifi_config_t wifi_config;
uint8_t ssid[33] = { 0 };
uint8_t password[65] = { 0 };
bool ipGettedFlag = 0;
bool newConnectFlag = 1;
/******************************************************************************/


/******************************************************************************/
void ChipRestart(int seconds);
void BlinkTask(void *pvParameter);
void InitShowToSerial(void);
void InitWifi(void);
void SmartconfigTask(void * parm);
void InitCam(void);
void InitSd(void);
void InitLcd(void);


void tcp_client_task(void *pvParameters);
static void http_get_task(void *pvParameters);
static void websocket_app_task(void *pvParameters);
/******************************************************************************/

/******************************************************************************/
void app_main(void)
{
    // 参数:任务函数,任务别名,任务堆栈的深度,参数的指针,任务优先级,回传句柄
    xTaskCreate(&BlinkTask, "LedBlinkTask", configMINIMAL_STACK_SIZE, NULL, 5, NULL);
    InitShowToSerial();
    InitWifi();
    //InitCam();
    InitSd();
    //InitLcd();
    //xTaskCreate(&tcp_client_task, "tcp_client", 4096, NULL, 5, NULL);
    //xTaskCreate(&http_get_task, "http_get_task", 4096, NULL, 5, NULL);
    xTaskCreate(&websocket_app_task, "websocket_app_task", 4096, NULL, 5, NULL);

}
/******************************************************************************/

/******************************************************************************/
void ChipRestart(int seconds)
{
    for(int i = seconds; i >= 0; i--)
    {
        printf("Restarting in %d seconds...\n", i);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
    printf("Restarting now.\n");
    fflush(stdout);
    esp_restart();
}
/******************************************************************************/
void BlinkTask(void *pvParameter)
{
    /* Configure the IOMUX register for pad BLINK_PIN (some pads are
       muxed to GPIO on reset already, but some default to other
       functions and need to be switched to GPIO. Consult the
       Technical Reference for a list of pads and their default
       functions.)
    */
    gpio_pad_select_gpio(BLINK_PIN);
    // Set the GPIO as a push/pull output
    gpio_set_direction(BLINK_PIN, GPIO_MODE_OUTPUT);
    while(1)
    {
        // Blink on (output high)
        gpio_set_level(BLINK_PIN, 0);
        vTaskDelay(100 / portTICK_PERIOD_MS);
        // Blink off (output low)
        gpio_set_level(BLINK_PIN, 1);
        vTaskDelay(100 / portTICK_PERIOD_MS);
        
        gpio_set_level(BLINK_PIN, 0);
        vTaskDelay(100 / portTICK_PERIOD_MS);
        gpio_set_level(BLINK_PIN, 1);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }

}
/******************************************************************************/
void InitShowToSerial(void)
{
    printf("Welcome to LS products!\n");

    // Print chip information
    esp_chip_info_t chip_info;
    esp_chip_info(&chip_info);
    printf("This is %s chip with %d CPU cores, WiFi%s%s, ",
            CONFIG_IDF_TARGET,
            chip_info.cores,
            (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
            (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");

    printf("silicon revision %d, ", chip_info.revision);

    printf("%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024),
            (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");

    printf("Free heap: %d\n", esp_get_free_heap_size());

}
/******************************************************************************/
void time_sync_notification_cb(struct timeval *tv)
{
    ESP_LOGI(TAG, "SNTP OK ");
}
static void InitSntp(void)
{
    ESP_LOGI(TAG, "Initializing SNTP");
    sntp_setoperatingmode(SNTP_OPMODE_POLL);
    sntp_setservername(0, "pool.ntp.org");
    sntp_set_time_sync_notification_cb(time_sync_notification_cb);
#ifdef CONFIG_SNTP_TIME_SYNC_METHOD_SMOOTH
    sntp_set_sync_mode(SNTP_SYNC_MODE_SMOOTH);
#endif
    sntp_init();
}
void GetSntpData(void)
{
//#if CONFIG_ESP_SNTP_ENABLED
    if(ipGettedFlag)
    {
        InitSntp();

        // Wait for time to be set
        time_t now = 0;
        char strftime_buf[64];
        struct tm timeinfo = { 0 };
        int retry = 0;
        const int retry_count = 10;
        while(sntp_get_sync_status() == SNTP_SYNC_STATUS_RESET && ++retry < retry_count)
        {
            ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count);
            vTaskDelay(1000 / portTICK_PERIOD_MS);
        }
        // Set timezone to China Standard Time
        setenv("TZ", "CST-8", 1);
        time(&now);
        localtime_r(&now, &timeinfo);
        strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
        ESP_LOGI(TAG, "The current date/time in Shanghai is: %s", strftime_buf);
    }
//#endif
}
/******************************************************************************/
void router_wifi_save_info(uint8_t *ssid, uint8_t *password)
{
    nvs_handle out_handle;
    char data[65];
    if (nvs_open("wifi_info", NVS_READWRITE, &out_handle) != ESP_OK)
    {
        return;
    }

    memset(data, 0x0, sizeof(data));
    strncpy(data, (char *)ssid, strlen((char *)ssid));
    if (nvs_set_str(out_handle, "ssid", data) != ESP_OK)
    {
        ESP_LOGI(TAG,"Set NVS ssid fail");
    }

    memset(data, 0x0, sizeof(data));
    strncpy(data, (char *)password, strlen((char *)password));
    if (nvs_set_str(out_handle, "password", data) != ESP_OK)
    {
        ESP_LOGI(TAG,"Set NVS password fail");
    }
    nvs_commit(out_handle);
    nvs_close(out_handle);
}

bool router_wifi_read()
{
    nvs_handle out_handle;
    size_t size = 0;
    nvs_open("wifi_info", NVS_READONLY, &out_handle);
    memset(&wifi_config, 0x0, sizeof(wifi_config));
    size = sizeof(wifi_config.sta.ssid);
    if(nvs_get_str(out_handle, "ssid", (char *)wifi_config.sta.ssid, &size) == ESP_OK)
    {
        if (size > 0)
        {
            size = sizeof(wifi_config.sta.password);
            if (nvs_get_str(out_handle, "password", (char *)wifi_config.sta.password, &size) == ESP_OK)
            {
                ESP_LOGI(TAG,"NVS get ssid: %s", wifi_config.sta.ssid);
                ESP_LOGI(TAG,"NVS get password: %s", wifi_config.sta.password);
                return 1;
            }
        }
    }
    nvs_close(out_handle);
    return 0;
}

static int s_retry_num = 0;
static int s_retry_num_maximum = 5;
static void WifiConnectHandler(void* arg, esp_event_base_t event_base,
                                int32_t event_id, void* event_data)
{
    if(event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
    {
        esp_wifi_connect();
    }
    else if(event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
    {
        ip_event_got_ip_t* ipEvent = (ip_event_got_ip_t*) event_data;
        ESP_LOGI(TAG, "Got ip: " IPSTR, IP2STR(&ipEvent->ip_info.ip));
        ipGettedFlag = 1;
        GetSntpData();
    }
    else if(event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
    {
        if(s_retry_num < s_retry_num_maximum)
        {
            esp_wifi_connect();
            s_retry_num++;
            ESP_LOGI(TAG,"Retry to connect to the AP");
        }
        ESP_LOGI(TAG,"Connect to the AP fail");
    }
    //mdns_handle_system_event(ctx, event);
}

void WifiConnect(void)
{
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    esp_netif_init();
    ESP_ERROR_CHECK( esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &WifiConnectHandler, NULL) );
    ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &WifiConnectHandler, NULL) );
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
    ESP_ERROR_CHECK(esp_wifi_start());
}
/******************************************************************************/
static void SmartconfigEventHandler(void* arg, esp_event_base_t event_base, 
                                    int32_t event_id, void* event_data)
{
    if(event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
    {
        xTaskCreate(SmartconfigTask, "SmartconfigTask", 4096, NULL, 3, NULL);
    }
    else if(event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
    {
        esp_wifi_connect();
        xEventGroupClearBits(s_wifi_event_group, CONNECTED_BIT);
    }
    else if(event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
    {
        xEventGroupSetBits(s_wifi_event_group, CONNECTED_BIT);
        ip_event_got_ip_t* ipEvent = (ip_event_got_ip_t*) event_data;
        ESP_LOGI(TAG, "Got ip: " IPSTR, IP2STR(&ipEvent->ip_info.ip));
        ipGettedFlag = 1;
    }
    else if(event_base == SC_EVENT && event_id == SC_EVENT_SCAN_DONE)
    {
        ESP_LOGI(TAG, "Scan done");
    }
    else if(event_base == SC_EVENT && event_id == SC_EVENT_FOUND_CHANNEL)
    {
        ESP_LOGI(TAG, "Found channel");
    }
    else if(event_base == SC_EVENT && event_id == SC_EVENT_GOT_SSID_PSWD)
    {
        ESP_LOGI(TAG, "Got SSID and password");

        smartconfig_event_got_ssid_pswd_t *evt = (smartconfig_event_got_ssid_pswd_t *)event_data;

        bzero(&wifi_config, sizeof(wifi_config_t));
        memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid));
        memcpy(wifi_config.sta.password, evt->password, sizeof(wifi_config.sta.password));
        wifi_config.sta.bssid_set = evt->bssid_set;
        if(wifi_config.sta.bssid_set == true)
        {
            memcpy(wifi_config.sta.bssid, evt->bssid, sizeof(wifi_config.sta.bssid));
        }

        memcpy(ssid, evt->ssid, sizeof(evt->ssid));
        memcpy(password, evt->password, sizeof(evt->password));
        ESP_LOGI(TAG, "SSID:%s", ssid);
        ESP_LOGI(TAG, "PASSWORD:%s", password);

        ESP_ERROR_CHECK( esp_wifi_disconnect() );
        ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
        ESP_ERROR_CHECK( esp_wifi_connect() );
    }
    else if(event_base == SC_EVENT && event_id == SC_EVENT_SEND_ACK_DONE)
    {
        xEventGroupSetBits(s_wifi_event_group, ESPTOUCH_DONE_BIT);
    }
}

void SmartconfigTask(void * parm)
{
    ESP_LOGI(TAG, "Wifi task start.");
    EventBits_t uxBits;
    ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH_AIRKISS) );
    smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT();
    ESP_ERROR_CHECK( esp_smartconfig_start(&cfg) );
    while(1)
    {
        uxBits = xEventGroupWaitBits(s_wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY); 
        if(uxBits & CONNECTED_BIT)
        {
            ESP_LOGI(TAG, "WiFi Connected to ap");
        }
        if(uxBits & ESPTOUCH_DONE_BIT)
        {
            ESP_LOGI(TAG, "Smartconfig over");
            router_wifi_save_info(ssid,password);
            esp_smartconfig_stop();
            GetSntpData();
            vTaskDelete(NULL);
        }
    }
}

void InitWifi(void)
{
    ESP_LOGI(TAG, "Init nvs_falsh ...");
    esp_err_t ret = nvs_flash_init();
    if(ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);
    ESP_LOGI(TAG, "Init nvs_falsh done!");

    ESP_ERROR_CHECK(esp_netif_init());
    s_wifi_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
    assert(sta_netif);

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK( esp_wifi_init(&cfg) );

    if((router_wifi_read()==0) || (0/* GPIO */))
    {
        ESP_ERROR_CHECK( esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &SmartconfigEventHandler, NULL) );
        ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &SmartconfigEventHandler, NULL) );
        ESP_ERROR_CHECK( esp_event_handler_register(SC_EVENT, ESP_EVENT_ANY_ID, &SmartconfigEventHandler, NULL) );

        ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
        ESP_ERROR_CHECK( esp_wifi_start() );
    }
    else
    {
        WifiConnect();
    }
}
/******************************************************************************/
static camera_config_t camera_config = {
    .pin_pwdn  = CAM_PIN_PWDN,
    .pin_reset = CAM_PIN_RESET,
    .pin_xclk = CAM_PIN_XCLK,
    .pin_sscb_sda = CAM_PIN_SIOD,
    .pin_sscb_scl = CAM_PIN_SIOC,

    .pin_d7 = CAM_PIN_D7,
    .pin_d6 = CAM_PIN_D6,
    .pin_d5 = CAM_PIN_D5,
    .pin_d4 = CAM_PIN_D4,
    .pin_d3 = CAM_PIN_D3,
    .pin_d2 = CAM_PIN_D2,
    .pin_d1 = CAM_PIN_D1,
    .pin_d0 = CAM_PIN_D0,
    .pin_vsync = CAM_PIN_VSYNC,
    .pin_href = CAM_PIN_HREF,
    .pin_pclk = CAM_PIN_PCLK,
    // XCLK 20MHz or 10MHz for OV2640 double FPS (Experimental)
    .xclk_freq_hz = 20000000,
    .ledc_timer = LEDC_TIMER_0,
    .ledc_channel = LEDC_CHANNEL_0,

    // YUV422,GRAYSCALE,RGB565,JPEG
    .pixel_format = PIXFORMAT_RGB565,
    // Init with high specs to pre-allocate larger buffers
    //.frame_size = FRAMESIZE_QSXGA,
    // QQVGA-QXGA Do not use sizes above QVGA when not JPEG
    .frame_size = FRAMESIZE_QQVGA,
    // 0-63 lower number means higher quality
    .jpeg_quality = 12,
    // If more than one, i2s runs in continuous mode. Use only with JPEG
    .fb_count = 1
};

void InitCam(void)
{
    ESP_LOGI(TAG, "Init camera ...");

#ifdef CONFIG_LED_ILLUMINATOR_ENABLED
    ESP_LOGI(TAG, "Init led_cam ...");
    gpio_set_direction(CONFIG_LED_LEDC_PIN,GPIO_MODE_OUTPUT);
    ledc_timer_config_t ledc_timer = {
        .duty_resolution = LEDC_TIMER_8_BIT,        // resolution of PWM duty
        .freq_hz         = 1000,                    // frequency of PWM signal
        .speed_mode      = LEDC_LOW_SPEED_MODE,     // timer mode
        .timer_num       = CONFIG_LED_LEDC_TIMER    // timer index
    };
    ledc_channel_config_t ledc_channel = {
        .channel    = CONFIG_LED_LEDC_CHANNEL,
        .duty       = 0,
        .gpio_num   = CONFIG_LED_LEDC_PIN,
        .speed_mode = LEDC_LOW_SPEED_MODE,
        .hpoint     = 0,
        .timer_sel  = CONFIG_LED_LEDC_TIMER
    };
    #ifdef CONFIG_LED_LEDC_HIGH_SPEED_MODE
    ledc_timer.speed_mode = ledc_channel.speed_mode = LEDC_HIGH_SPEED_MODE;
    #endif
    switch(ledc_timer_config(&ledc_timer))
    {
        case ESP_ERR_INVALID_ARG: ESP_LOGE(TAG, "ledc_timer_config() parameter error"); break;
        case ESP_FAIL: ESP_LOGE(TAG, "ledc_timer_config() Can not find a proper pre-divider number base on the given frequency and the current duty_resolution"); break;
        case ESP_OK:
            if(ledc_channel_config(&ledc_channel) == ESP_ERR_INVALID_ARG)
                ESP_LOGE(TAG, "ledc_channel_config() parameter error");
          break;
        default: break;
    }
    ESP_LOGI(TAG, "Init led_cam done!");
#endif

    // Power up the camera if PWDN pin is defined
    if(CAM_PIN_PWDN != -1)
    {
        gpio_set_direction(CAM_PIN_PWDN, GPIO_MODE_OUTPUT);
        gpio_set_level(CAM_PIN_PWDN, 0);
    }

    // Camera init
    esp_err_t err = esp_camera_init(&camera_config);
    if(err != ESP_OK)
    {
        ESP_LOGE(TAG, "Camera init failed with error 0x%x", err);
        return;
    }

    sensor_t * s = esp_camera_sensor_get();
    // Initial sensors are flipped vertically and colors are a bit saturated
    if(s->id.PID == OV2640_PID)
    {
        s->set_vflip(s, 1);//flip it back
        s->set_brightness(s, 1);//up the blightness just a bit
        s->set_saturation(s, -2);//lower the saturation
    }
    /*
    // Drop down frame size for higher initial frame rate
    //s->set_framesize(s, FRAMESIZE_HD);
    */
    
    ESP_LOGI(TAG, "Init camera done!");
    return;
}
/******************************************************************************/

#define HOST_IP_ADDR "192.168.1.232"
#define PORT 8858
static const char *payload = "Message from ESP32\n";

void tcp_client_task(void *pvParameters)
{
    char rx_buffer[128];
    char host_ip[] = HOST_IP_ADDR;
    int addr_family = 0;
    int ip_protocol = 0;

    while(1)
    {
        if(ipGettedFlag)
        {
            struct sockaddr_in dest_addr;
            dest_addr.sin_addr.s_addr = inet_addr(host_ip);
            dest_addr.sin_family = AF_INET;
            dest_addr.sin_port = htons(PORT);
            addr_family = AF_INET;
            ip_protocol = IPPROTO_IP;
            
            int sock =  socket(addr_family, SOCK_STREAM, ip_protocol);
            if (sock < 0) {
                ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
                break;
            }
            ESP_LOGI(TAG, "Socket created, connecting to %s:%d", host_ip, PORT);

            int err = connect(sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in6));
            if (err != 0) {
                ESP_LOGE(TAG, "Socket unable to connect: errno %d", errno);
                break;
            }
            ESP_LOGI(TAG, "Successfully connected");
            while (1) {
                int err = send(sock, payload, strlen(payload), 0);
                if (err < 0) {
                    ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);
                    break;
                }

                int len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0);
                // Error occurred during receiving
                if (len < 0) {
                    ESP_LOGE(TAG, "recv failed: errno %d", errno);
                    break;
                }
                // Data received
                else {
                    // Null-terminate whatever we received and treat like a string
                    rx_buffer[len] = 0; 
                    ESP_LOGI(TAG, "Received %d bytes from %s:", len, host_ip);
                    ESP_LOGI(TAG, "%s", rx_buffer);
                }

                vTaskDelay(2000 / portTICK_PERIOD_MS);
            }

            if (sock != -1) {
                ESP_LOGE(TAG, "Shutting down socket and restarting...");
                shutdown(sock, 0);
                close(sock);
            }
        }
    }
    vTaskDelete(NULL);
}


#define SCREEN_WIDTH 240
#define SCREEN_HEIGHT 320
scr_driver_t lcd;

static void screen_clear(scr_driver_t *lcd, int color)
{
    scr_info_t lcd_info;
    lcd->get_info(&lcd_info);

    uint16_t *buffer = malloc(lcd_info.width * sizeof(uint16_t));
    if (NULL == buffer) {
        for (size_t y = 0; y < lcd_info.height; y++) {
            for (size_t x = 0; x < lcd_info.width; x++) {
                lcd->draw_pixel(x, y, color);
            }
        }
    } else {
        for (size_t i = 0; i < lcd_info.width; i++) {
            buffer[i] = color;
        }

        for (int y = 0; y < lcd_info.height; y++) {
            lcd->draw_bitmap(0, y, lcd_info.width, 1, buffer);
        }

        free(buffer);
    }
}

void CamShow(void)
{
    camera_fb_t *fb = esp_camera_fb_get();
    int i = 0, x = 0, y = 0;
    for(y = 0; y < SCREEN_HEIGHT; y++)
    {
        for(x = 0;x < SCREEN_WIDTH; x++)
        {
            lcd.draw_pixel(x, y, ((fb->buf[2*i])<<8)|(fb->buf[2*i+1]));
            /*
            switch(fb->buf[i]%2)
            {
                case 0:
                    lcd.draw_pixel(x, y, COLOR_BLACK);
                    break;
                case 1:
                    lcd.draw_pixel(x, y, COLOR_WHITE);
                    break;
                case 2:
                    //lcd->draw_pixel(x, y, COLOR_INVERSE);
                    break;
            }
            */
            i++;
        }
    }
    esp_camera_fb_return(fb);
}

void InitLcd(void)
{
    ESP_LOGI(TAG, "Init LCD ...");

    spi_config_t spi_cfg = {
        .miso_io_num = -1,
        .mosi_io_num = 13,
        .sclk_io_num = 14,
        .max_transfer_sz = SCREEN_WIDTH * SCREEN_HEIGHT,
    };
    spi_bus_handle_t spi_bus = spi_bus_create(2, &spi_cfg);
    //TEST_ASSERT_NOT_NULL(spi_bus);

    scr_interface_spi_config_t spi_lcd_cfg = {
        .spi_bus = spi_bus,
        .pin_num_cs = 15,
        .pin_num_dc = 4,
        .clk_freq = 20000000,
        .swap_data = true,
    };

    scr_interface_driver_t *iface_drv;
    if(ESP_OK == scr_interface_create(SCREEN_IFACE_SPI, &spi_lcd_cfg, &iface_drv))
        ESP_LOGI(TAG, "Creat ok.");

    scr_controller_config_t lcd_cfg = {0};
    lcd_cfg.interface_drv = iface_drv;
    lcd_cfg.pin_num_rst = 2;
    lcd_cfg.pin_num_bckl = -1;
    lcd_cfg.rst_active_level = 0;
    lcd_cfg.bckl_active_level = 1;
    lcd_cfg.offset_hor = 0;
    lcd_cfg.offset_ver = 0;
    lcd_cfg.width = SCREEN_WIDTH;
    lcd_cfg.height = SCREEN_HEIGHT;
    lcd_cfg.rotate = SCR_DIR_LRTB;
    if(ESP_OK == scr_find_driver(SCREEN_CONTROLLER_ILI9341, &lcd))
        ESP_LOGI(TAG, "Lcd find driver ili9341.");
    if(ESP_OK == lcd.init(&lcd_cfg))
        ESP_LOGI(TAG, "Lcd init ok.");

    screen_clear(&lcd, COLOR_BLUE);
    //vTaskDelay(2000 / portTICK_PERIOD_MS);
    //screen_clear(&lcd, COLOR_GREEN);
    //vTaskDelay(2000 / portTICK_PERIOD_MS);
    //screen_clear(&lcd, COLOR_RED);
    CamShow();

    //lcd.deinit();
    //scr_interface_delete(iface_drv);
    //spi_bus_delete(&spi_bus);
    
    ESP_LOGI(TAG, "Init LCD done!");
}


#define MOUNT_POINT "/sdcard"

void InitSd(void)
{
    esp_err_t ret;
    // Options for mounting the filesystem.
    // If format_if_mount_failed is set to true, SD card will be partitioned and
    // formatted in case when mounting fails.
    esp_vfs_fat_sdmmc_mount_config_t mount_config = {
#ifdef CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED
        .format_if_mount_failed = true,
#else
        .format_if_mount_failed = false,
#endif // EXAMPLE_FORMAT_IF_MOUNT_FAILED
        .max_files = 5,
        .allocation_unit_size = 16 * 1024
    };
    sdmmc_card_t* card;
    const char mount_point[] = MOUNT_POINT;
    ESP_LOGI(TAG, "Initializing SD card");
    
    ESP_LOGI(TAG, "Using SDMMC peripheral");
    sdmmc_host_t host = SDMMC_HOST_DEFAULT();

    // This initializes the slot without card detect (CD) and write protect (WP) signals.
    // Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
    sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();

    // To use 1-line SD mode, uncomment the following line:
    // slot_config.width = 1;

    // GPIOs 15, 2, 4, 12, 13 should have external 10k pull-ups.
    // Internal pull-ups are not sufficient. However, enabling internal pull-ups
    // does make a difference some boards, so we do that here.
    gpio_set_pull_mode(15, GPIO_PULLUP_ONLY);   // CMD, needed in 4- and 1- line modes
    gpio_set_pull_mode(2, GPIO_PULLUP_ONLY);    // D0, needed in 4- and 1-line modes
    gpio_set_pull_mode(4, GPIO_PULLUP_ONLY);    // D1, needed in 4-line mode only
    gpio_set_pull_mode(12, GPIO_PULLUP_ONLY);   // D2, needed in 4-line mode only
    gpio_set_pull_mode(13, GPIO_PULLUP_ONLY);   // D3, needed in 4- and 1-line modes

    ret = esp_vfs_fat_sdmmc_mount(mount_point, &host, &slot_config, &mount_config, &card);
    
    if (ret != ESP_OK) {
        if (ret == ESP_FAIL) {
            ESP_LOGE(TAG, "Failed to mount filesystem. "
                "If you want the card to be formatted, set the EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option.");
        } else {
            ESP_LOGE(TAG, "Failed to initialize the card (%s). "
                "Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret));
        }
        return;
    }

    // Card has been initialized, print its properties
    sdmmc_card_print_info(stdout, card);
    
    // Use POSIX and C standard library functions to work with files.
    // First create a file.
    ESP_LOGI(TAG, "Opening file");
    FILE* f = fopen(MOUNT_POINT"/hello.txt", "w");
    if (f == NULL) {
        ESP_LOGE(TAG, "Failed to open file for writing");
        return;
    }
    fprintf(f, "Hello %s!\n", card->cid.name);
    fclose(f);
    ESP_LOGI(TAG, "File written");

    // Check if destination file exists before renaming
    struct stat st;
    if (stat(MOUNT_POINT"/foo.txt", &st) == 0) {
        // Delete it if it exists
        unlink(MOUNT_POINT"/foo.txt");
    }

    // Rename original file
    ESP_LOGI(TAG, "Renaming file");
    if (rename(MOUNT_POINT"/hello.txt", MOUNT_POINT"/foo.txt") != 0) {
        ESP_LOGE(TAG, "Rename failed");
        return;
    }

    // Open renamed file for reading
    ESP_LOGI(TAG, "Reading file");
    f = fopen(MOUNT_POINT"/foo.txt", "r");
    if (f == NULL) {
        ESP_LOGE(TAG, "Failed to open file for reading");
        return;
    }
    char line[64];
    fgets(line, sizeof(line), f);
    fclose(f);
    // strip newline
    char* pos = strchr(line, '\n');
    if (pos) {
        *pos = '\0';
    }
    ESP_LOGI(TAG, "Read from file: '%s'", line);

    // All done, unmount partition and disable SDMMC or SPI peripheral
    esp_vfs_fat_sdcard_unmount(mount_point, card);
    ESP_LOGI(TAG, "Card unmounted");
}



#define WEB_SERVER "192.168.1.232"
#define WEB_PORT "80"
#define WEB_PATH "/files/testA1.php"

static const char *REQUEST =
    "GET " WEB_PATH " HTTP/1.1\r\n"
    "Host: "WEB_SERVER":"WEB_PORT"\r\n"
    "User-Agent: esp-idf/1.0 esp32\r\n"
    "\r\n";

static void http_get_task(void *pvParameters)
{
    const struct addrinfo hints = {
        .ai_family = AF_INET,
        .ai_socktype = SOCK_STREAM,
    };
    struct addrinfo *res;
    struct in_addr *addr;
    int s, r;
    char recv_buf[64];

    while(1) {
        while(!ipGettedFlag){}
        
        int err = getaddrinfo(WEB_SERVER, WEB_PORT, &hints, &res);

        if(err != 0 || res == NULL) {
            ESP_LOGE(TAG, "DNS lookup failed err=%d res=%p", err, res);
            vTaskDelay(1000 / portTICK_PERIOD_MS);
            continue;
        }

        /* Code to print the resolved IP.

           Note: inet_ntoa is non-reentrant, look at ipaddr_ntoa_r for "real" code */
        addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
        ESP_LOGI(TAG, "DNS lookup succeeded. IP=%s", inet_ntoa(*addr));

        s = socket(res->ai_family, res->ai_socktype, 0);
        if(s < 0) {
            ESP_LOGE(TAG, "... Failed to allocate socket.");
            freeaddrinfo(res);
            vTaskDelay(1000 / portTICK_PERIOD_MS);
            continue;
        }
        ESP_LOGI(TAG, "... allocated socket");

        if(connect(s, res->ai_addr, res->ai_addrlen) != 0) {
            ESP_LOGE(TAG, "... socket connect failed errno=%d", errno);
            close(s);
            freeaddrinfo(res);
            vTaskDelay(4000 / portTICK_PERIOD_MS);
            continue;
        }

        ESP_LOGI(TAG, "... connected");
        freeaddrinfo(res);

        if (write(s, REQUEST, strlen(REQUEST)) < 0) {
            ESP_LOGE(TAG, "... socket send failed");
            close(s);
            vTaskDelay(4000 / portTICK_PERIOD_MS);
            continue;
        }
        ESP_LOGI(TAG, "... socket send success");

        struct timeval receiving_timeout;
        receiving_timeout.tv_sec = 5;
        receiving_timeout.tv_usec = 0;
        if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &receiving_timeout,
                sizeof(receiving_timeout)) < 0) {
            ESP_LOGE(TAG, "... failed to set socket receiving timeout");
            close(s);
            vTaskDelay(4000 / portTICK_PERIOD_MS);
            continue;
        }
        ESP_LOGI(TAG, "... set socket receiving timeout success");

        /* Read HTTP response */
        do {
            bzero(recv_buf, sizeof(recv_buf));
            r = read(s, recv_buf, sizeof(recv_buf)-1);
            for(int i = 0; i < r; i++) {
                putchar(recv_buf[i]);
            }
        } while(r > 0);

        ESP_LOGI(TAG, "... done reading from socket. Last read return=%d errno=%d.", r, errno);
        close(s);
        /*
        for(int countdown = 10; countdown >= 0; countdown--) {
            ESP_LOGI(TAG, "%d... ", countdown);
            vTaskDelay(1000 / portTICK_PERIOD_MS);
        }
        ESP_LOGI(TAG, "Starting again!\n\n");
        */
        vTaskDelete(NULL);
    }
}




void InitHttp(void)
{
    
}



static void websocket_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
    esp_websocket_event_data_t *data = (esp_websocket_event_data_t *)event_data;
    switch (event_id) {
    case WEBSOCKET_EVENT_CONNECTED:
        ESP_LOGI(TAG, "WEBSOCKET_EVENT_CONNECTED");
        break;
    case WEBSOCKET_EVENT_DISCONNECTED:
        ESP_LOGI(TAG, "WEBSOCKET_EVENT_DISCONNECTED");
        break;
    case WEBSOCKET_EVENT_DATA:
        ESP_LOGI(TAG, "WEBSOCKET_EVENT_DATA");
        ESP_LOGI(TAG, "Received opcode=%d", data->op_code);
        ESP_LOGW(TAG, "Received=%.*s", data->data_len, (char *)data->data_ptr);
        ESP_LOGW(TAG, "Total payload length=%d, data_len=%d, current payload offset=%d\r\n", data->payload_len, data->data_len, data->payload_offset);
        break;
    case WEBSOCKET_EVENT_ERROR:
        ESP_LOGI(TAG, "WEBSOCKET_EVENT_ERROR");
        break;
    }
}

static void websocket_app_task(void *pvParameters)
{
    gpio_pad_select_gpio(BELL_PIN);
    gpio_set_direction(BELL_PIN, GPIO_MODE_INPUT);
    ESP_LOGI(TAG, "Current BELL_PIN level: %d", gpio_get_level(BELL_PIN));
    
    esp_websocket_client_config_t websocket_cfg = {
        .uri = "ws://192.168.1.232:2202",
    };
    ESP_LOGI(TAG, "Connecting to %s...", websocket_cfg.uri);

    esp_websocket_client_handle_t client = esp_websocket_client_init(&websocket_cfg);
    esp_websocket_register_events(client, WEBSOCKET_EVENT_ANY, websocket_event_handler, (void *)client);
    
    while(!ipGettedFlag){}
    esp_websocket_client_start(client);
    
    while(1)
    {
        if(esp_websocket_client_is_connected(client))
        {
            if(newConnectFlag)
            {
                esp_websocket_client_send_text(client, "espT1", sizeof("espT1"), portMAX_DELAY);
                newConnectFlag = 0;
            }

            if(gpio_get_level(BELL_PIN))
            {
                vTaskDelay(600 / portTICK_PERIOD_MS);
                if(gpio_get_level(BELL_PIN))
                {
                    esp_websocket_client_send_text(client, "wxT1&bell", sizeof("wxT1&bell"), portMAX_DELAY);
                }
            }
        }
    }

    /*
    esp_websocket_client_stop(client);
    ESP_LOGI(TAG, "Websocket Stopped");
    esp_websocket_client_destroy(client);
    */
}

Workerman-eyeWebT1.php

<?php
use Workerman\Worker;
require_once '/home/webFilesT/Workerman/Autoloader.php';
//require '/home/webFilesT/vendor/autoload.php';

/*
$worker = new Worker('http://0.0.0.0:8080');

$worker->onMessage = function($connection, $request)
{
    if($request->get('requestId') == 'wxT1')
    {
        if($request->get('action') == 'open')
        {
            $connection->send('o1');
        }
        else if($request->get('action') == 'close')
        {
            $connection->send('c1');
        }
    }
    else if($request->get('requestId') == 'lockT1')
    {
        $connection->send('Hello lockT1!');
    }
    else if($request->get('requestId') == 'pcT1')
    {
        if($request->get('action') == 'bell')
        {
            $connection->send('Action bell ...');
            $http = new Workerman\Http\Client();
            $http->post('http://192.168.1.102/', ['key1'=>'value1','key2'=>'value2'],
                function($response){
                    //var_dump($response->getStatusCode());
                    echo $response->getStatusCode();
                    //echo $response->getBody();
                }, 
                function($exception){
                    echo $exception;
                });
        }
        else
        {
            $connection->send('Action none ...');
        }
    }
    else
    {
        $connection->send('Unregistered!');
    }
};
*/



//$worker = new Worker('websocket://0.0.0.0:1234');
$worker = new Worker('tcp://0.0.0.0:1234');
$worker->count = 1;
$worker->uidConnections = array();

$worker->onMessage = function($connection, $data)
{
    global $worker;
    // 判断当前客户端是否已经验证,即是否设置了uid
    if(!isset($connection->uid))
    {
       // 没验证的话把第一个包当做uid(这里为了方便演示,没做真正的验证)
       $connection->uid = $data;
       /* 保存uid到connection的映射,这样可以方便的通过uid查找connection,
        * 实现针对特定uid推送数据
        */
       $worker->uidConnections[$connection->uid] = $connection;
       echo $connection->uid . ' connected!' . "\n";
       return $connection->send('Login success, your uid is: ' . $connection->uid);
    }
    echo $data . "\n";
    // 其它逻辑,针对某个uid发送 或者 全局广播
    // 假设消息格式为 uid:message 时是对 uid 发送 message
    // uid 为 all 时是全局广播
    list($recv_uid, $action) = explode('&', $data);
    // 全局广播
    if($recv_uid == 'all')
    {
        broadcast($action);
    }
    // 给特定uid发送
    else
    {
        sendMessageByUid($recv_uid, $action);
    }
};

// 当有客户端连接断开时
$worker->onClose = function($connection)
{
    global $worker;
    if(isset($connection->uid))
    {
        // 连接断开时删除映射
        unset($worker->uidConnections[$connection->uid]);
        echo $connection->uid . ' disconnected!' . "\n";
    }
};

// 向所有验证的用户推送数据
function broadcast($message)
{
   global $worker;
   foreach($worker->uidConnections as $connection)
   {
        $connection->send($message);
   }
}

// 针对uid推送数据
function sendMessageByUid($uid, $message)
{
    global $worker;
    if(isset($worker->uidConnections[$uid]))
    {
        $connection = $worker->uidConnections[$uid];
        $connection->send($message);
    }
}


// 运行worker
Worker::runAll();

链接备份

评论已关闭

Loading...
Fullscreen Image