1.455升级
authord15521469561 <1731678236@qq.com>
Fri, 22 May 2026 10:51:24 +0000 (18:51 +0800)
committerd15521469561 <1731678236@qq.com>
Fri, 22 May 2026 10:51:24 +0000 (18:51 +0800)
2.蓝牙连接灯效
3.物理按键会场出厂
4.绑定接口

18 files changed:
main/CMakeLists.txt
main/app_main.c
main/ble.c
main/gap.c
main/https_ota.c
main/https_ota.h
main/n455_ota.c [new file with mode: 0644]
main/n455_ota.h [new file with mode: 0644]
main/project_common.c
main/project_common.h
main/uart.c
main/uart.h
main/user_flash.c
main/user_http.c
main/user_http.h
main/user_mqtt.c
main/user_mqtt.h
main/wifi.c

index 84847da..7e466c7 100644 (file)
@@ -12,7 +12,8 @@ idf_component_register(SRCS
                                                        "crc.c"
                                                        "uart.c"
                                                        "https_ota.c" 
-                                                       "user_http.c"        
+                                                       "user_http.c"   
+                                                       "n455_ota.c"     
                                                     
                     PRIV_REQUIRES mqtt
                                                                esp_wifi
index 688a99c..2f6a10e 100644 (file)
@@ -13,6 +13,7 @@
 #include "user_http.h"
 #include "wifi.h"
 #include "ble.h"
+#include "n455_ota.h"
 #include "esp_chip_info.h"
 static const char *MAIN_TAG = "main";
 // MAIN_LOOP
@@ -23,13 +24,14 @@ StaticTask_t main_loop_task_tcb;
 // 1秒定时器句柄
 static esp_timer_handle_t onesec_timer_handle = NULL;
 
+
 // 1秒定时器回调函数
 static void onesec_timer_callback(void* arg)
 {
     #if ENABLE_MQTT_FUNC
     Mqtt_Send_Data();
     #endif
-    #if ENABLE_SYNC_SNTP_TIME
+    #if 0
     struct timeval tv;
     gettimeofday(&tv, NULL);
 
@@ -42,10 +44,40 @@ static void onesec_timer_callback(void* arg)
     ESP_LOGI("TIME", "当前时间:%s", buf);
     #endif
     
+    time_t Time_Sec=Get_Time_Stamp();
+    
+    
+    char time_str[24]={0};
+    int64_to_str((int64_t)Time_Sec, time_str,sizeof(time_str)-1);
+    ESP_LOGI("TIME","time: %s",time_str);
+    #if ENABLE_HTTP_N455_OTA_FUNC
+    static uint8_t onesec_timer_count = 0;
+    if(onesec_timer_count < 65)
+    {
+        onesec_timer_count++;
+        if(onesec_timer_count % 10){
+            
+            // Uart_Reply_Send(COMMON_UART_BLE_CONNECT_STATUS,NULL,0,HOST_TYPE_UART);
+            // Https_Ota_Start();
+            // xEventGroupSetBits(common_event_group, COMMON_HTTPS_N455_OTA_BIT);
+        }
+        
+    }
+    #endif
+    #if ENABLE_HTTPS_OTA_FUNC
+    //===========esp32 ota timeout=================//
     Https_Ota_Check_TimeOut();
+    #endif
+    
+    #if ENABLE_HTTP_N455_OTA_FUNC
+    //===========455  ota timeout=================//
+    N455_Ota_Check_TimeOut();
+    #endif
+    //================mqtt is cnnect===========//
+    mqtt_check_isconnect();
     // 在这里添加每秒执行的代码
     #if ENABLE_HTTPS_OTA_FUNC
-    ESP_LOGI(MAIN_TAG, "onesec_timer:ota %d ota_cur_status %d %" PRIu32 " bytes",common_setting.https_ota_cfg.https_ota_start_flag,g_ota_status,esp_get_free_heap_size());
+    // ESP_LOGI(MAIN_TAG, "onesec_timer:ota %d ota_cur_status %d %" PRIu32 " bytes",common_setting.https_ota_cfg.https_ota_start_flag,g_ota_status,esp_get_free_heap_size());
     #else
     ESP_LOGI(MAIN_TAG, "onesec_timer:ota %d %" PRIu32 " bytes",common_setting.https_ota_cfg.https_ota_start_flag,esp_get_free_heap_size());
     #endif
@@ -56,7 +88,7 @@ static void onesec_timer_callback(void* arg)
 
 #if (IOT_ENABLE)
 #if (1)
-const char* device_name = "PXN-W GTL";
+const char* device_name = "W GTL";
 const char* http_url = "http://192.168.66.85:8080";//"http://107.23.202.137:8080";//"http://192.168.66.80:8080";//http://107.23.202.137:8080
 const char* http_token = "Bearer eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6ImJhZWRiZjUyLTUzMDgtNDRlOS04MWI3LTE1MmU4NGYwYzk5ZCJ9.fyxIGmmYD-pKd7VQ02DrL6FwBKVkqXoIu4iKSVMOUj8WubDvuSdbX6j8YzQw8K_t6UTRVZsRDTlO5me2KKhs7A";//"eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjRhNjBlZDdiLTExMDUtNDU5Ny1iNDBhLTg5ZDRiMzMzNTIyYSJ9.CUxkgU2F6BoxzE3HHVdXAin2OEDD1-D_iI0zh7VWTnlNsjsHHulvZVMq2hQLXF4cAQIJpLWwiMZJQO6Bvy9vwg";
 const char* user_id = "617086929577717760";
@@ -98,7 +130,7 @@ void Main_Loop_Task(void *pvParameters)
     // common_setting.mcu_info.product_name_len = strlen(device_name);
     // common_setting.mcu_info_got_flag = 1;
     
-#if (0)
+#if (ENABLE_HTTP_N455_OTA_FUNC)
     // BLE Test
     
     common_setting.mcu_info.vid = mcu_vid;
@@ -119,8 +151,8 @@ void Main_Loop_Task(void *pvParameters)
     common_setting.net_pairing_info.http_url_length = strlen(http_url);
     common_setting.net_pairing_info.http_token_length = strlen(http_token);
 
-    common_setting.net_pairing_info.user_id = user_id;
-    memcpy(common_setting.net_pairing_info.user_id,user_id,sizeof(net_pairing_info.user_id))
+    // common_setting.net_pairing_info.user_id = user_id;
+    // memcpy(common_setting.net_pairing_info.user_id,user_id,sizeof(net_pairing_info.user_id))
 
 
     common_setting.net_pairing_info.http_url_flag = 1;
@@ -135,7 +167,7 @@ void Main_Loop_Task(void *pvParameters)
     common_storage.net_info.wifi_info_flag=1;
     common_storage.net_info.serial_number_flag=1;
     // Esp_Check_Mcu_info_Flag();
-    
+    common_setting.ble_status.nimble_flag=1; 
     Wifi_Queue_Send(0, 0x03, 0);
 #endif
 #endif
@@ -158,6 +190,9 @@ void Main_Loop_Task(void *pvParameters)
         Mqtt_Connect_Status_Check();
         #endif
 
+        #if ENABLE_HTTP_N455_OTA_FUNC
+        N455_Ota_Status_Check();
+        #endif
         #if ENABLE_SYNC_SNTP_TIME
         wait_for_sntp_sync();
         #endif
index d3ff797..14ce555 100644 (file)
@@ -128,6 +128,9 @@ void Ble_Nimble_Init(void)
 
 //串口接收主控发过来的消息 才开启判断是否需要配网
 static uint8_t check_mcu_init = 0;
+/*
+FUNC:是否开启配网功能还是是否直连mqtt
+*/
 void Ble_Start_Nimble_NetWork(void)
 {
     //如果产品信息改变 需要配网 或者蓝牙状态是关闭的 需要配网清除配网信息
@@ -136,6 +139,7 @@ void Ble_Start_Nimble_NetWork(void)
         return;
     }
     check_mcu_init=1;
+    common_setting.ble_status.nimble_flag=0; //代表当前配网成功
     if(common_setting.mcu_info_got_flag == 1) //flag=2uart发送的信息 并且没有连接wifi
     {
         //无serial_number wifi info 并且蓝牙关闭状态开启蓝牙配网功能 
@@ -158,6 +162,7 @@ void Ble_Start_Nimble_NetWork(void)
                 ESP_LOGI(BLE_TAG, "have mqtt_sub_url  on: %d %d %d %d %d %d\n", common_storage.net_info.mqtt_url_len,common_storage.net_info.wifi_ssid_len,\
                     common_storage.net_info.wifi_pwd_len,common_storage.ssl_cert[SSL_SERVER_CRT].length,common_storage.ssl_cert[SSL_CLIENT_KEY].length,\
                     common_storage.ssl_cert[SSL_CLIENT_CRT].length);
+                
                 xEventGroupSetBits(ble_event_group, BLE_ON_BIT);//开启配网模式
             }else//有mqtt地址 密码 名称 证书才能直连mqtt服务器
             {
@@ -189,7 +194,11 @@ void Ble_Start_Nimble_NetWork(void)
         }
     }
 }
-
+/*
+func:ble开关状态检查
+BLE_ON_BIT:开广播
+BLE_OFF_BIT:关广播
+*/
 void Ble_Enable_Status_Check(void)
 {
     
index f537033..d3d40da 100644 (file)
@@ -226,6 +226,7 @@ static int gap_event_handler(struct ble_gap_event *event, void *arg) {
             }
             common_setting.ble_enable_tick = 0;
             common_setting.ble_status.ble_state = 2;
+            Uart_Set_Ble_Status();
         }
         /* Connection failed, restart advertising if allowed */
         else
index 5eb2c4f..bb3ddb0 100644 (file)
@@ -16,6 +16,7 @@
 #include "project_common.h"
 #include "user_mqtt.h"
 #include "wifi.h"
+#include "n455_ota.h"
 #if (ENABLE_HTTPS_OTA_FUNC)
 static const char *HTTPS_OTA = "HTTPS_OTA";
 #if CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
@@ -31,23 +32,22 @@ ota_status_t g_ota_status = OTA_STATUS_IDLE; // 全局OTA状态
 
 #define HTTPS_OTA_TIMEOUT_TIME  300 //单位s
 
-static uint8_t retry_ota_num = 0;
-static bool ota_full_failed_flag = false;  // 新增:三次失败锁定标记
-static uint16_t ota_timeout_count = 0;
+static volatile uint8_t ota_timeout_req = 0; //超时升级失败
+static volatile uint16_t ota_timeout_count = 0;
+
+static volatile uint16_t ota_faile_count  = 0;
+
+static uint8_t https_ota_init = 0;
 #define HTTPS_OTA_RETRY_NUM  0
 
 #define OTA_URL_SIZE 255
-#define OTA_HTTP_OTA   0 //是否使用http请求ota固件包
-#if OTA_HTTP_OTA
-#define HTTPS_OTA_STACK_SIZE   (8*1024)
-static const char *https_ota_url ="http://pxn-iot.s3.us-east-2.amazonaws.com/iot01/2026/04/11/ssl_mutual_auth.bin";
-#else
+
 #define HTTPS_OTA_STACK_SIZE   (4*1024)
-char https_ota_url[OTA_URL_SIZE] = {0};
-#endif
-//使用http请求还需要 配置表 ESP_HTTPS_OTA_ALLOW_HTTP = y ESP_TLS_INSECURE=y  ESP_TLS_SKIP_SERVER_CERT_VERIFY=y这三个都要打开
+static char https_ota_url[OTA_URL_SIZE] = "https://pxn-iot.s3.us-east-2.amazonaws.com/iot01/2026/05/22/6a0fb4324db40762648f18b3.bin";
 /* Event handler for catching system events */
-
+/*
+FUNC:sdk原生自动版本校验 未使用
+*/
 static esp_err_t validate_image_header(esp_app_desc_t *new_app_info)
 {
     return ESP_OK;
@@ -92,8 +92,10 @@ static esp_err_t _http_client_init_cb(esp_http_client_handle_t http_client)
     return err;
 }
 
-static uint8_t ota_timeout_req = 0; //超时升级失败
-//ota升级失败重复升级次数 连续三次都升级不成功不升级了
+
+/*
+func:OTA升级回调函数
+*/
 esp_https_ota_handle_t https_ota_handle = NULL;
 static void Https_Ota_Task_Cb(void *pvParameter)
 {
@@ -101,54 +103,63 @@ static void Https_Ota_Task_Cb(void *pvParameter)
     Mqtt_Disconnect();  // 关闭MQTTs
     // 2. 延迟一下确保资源释放
     vTaskDelay(200 / portTICK_PERIOD_MS);
+
     https_ota_handle=NULL;
     ESP_LOGI(HTTPS_OTA, "Starting Advanced OTA example:%s\n",https_ota_url);
     g_ota_status = OTA_STATUS_UPGRADING;  // 标记升级开始
-    Https_Ota_Status_Set(g_ota_status);
-    vTaskDelay(500 / portTICK_PERIOD_MS);
+    Https_Ota_Report_Status(g_ota_status);
+
+    vTaskDelay(100 / portTICK_PERIOD_MS);
     esp_err_t ota_finish_err = ESP_OK;
     esp_http_client_config_t config = {
         .url = https_ota_url,
-        
-        .timeout_ms = 20000,
+        .timeout_ms = 10000,
         .keep_alive_enable = false,
     };
-    #if (!OTA_HTTP_OTA)
+
     config.crt_bundle_attach = esp_crt_bundle_attach;//需要访问https一定要加这句
-    #else
-    config.skip_cert_common_name_check = true;
-    #endif
 
     esp_https_ota_config_t ota_config = {
         .http_config = &config,
         .http_client_init_cb = _http_client_init_cb, // Register a callback to be invoked after esp_http_client is initialized
     };
-    #if (OTA_HTTP_OTA)
-    
-    ota_config.partial_http_download=true;
-    #endif
-
-    esp_err_t err = esp_https_ota_begin(&ota_config, &https_ota_handle);
-    if (err != ESP_OK) {
-        ESP_LOGI(HTTPS_OTA, "ESP HTTPS OTA Begin failed");
-        g_ota_status = OTA_STATUS_FAILED;  // ←失败
+    esp_err_t err = ESP_FAIL;
+    for(uint8_t i=0;i < 3;i++)
+    {
+        if (https_ota_handle != NULL)
+        {
+            esp_https_ota_abort(https_ota_handle);
+            https_ota_handle = NULL;
+        }
+        err = ESP_FAIL;
+        err = esp_https_ota_begin(&ota_config, &https_ota_handle);
+        if(err == ESP_OK)
+        {
+            break;
+        }
+        vTaskDelay(500 / portTICK_PERIOD_MS);
+    }
+    if(err != ESP_OK)
+    {   
+        ESP_LOGI(HTTPS_OTA, "ESP HTTPS OTA Begin failed after 3 attempts");
+        g_ota_status = OTA_STATUS_FAILED;  // 
+        vTaskDelay(10 / portTICK_PERIOD_MS);
         goto ota_end;
-        // vTaskDelete(NULL);
-    }else{
-        ESP_LOGI(HTTPS_OTA, "ESP HTTPS OTA Begin success");
     }
     
+    err = ESP_FAIL;
     esp_app_desc_t app_desc;
     err = esp_https_ota_get_img_desc(https_ota_handle, &app_desc);
     if (err != ESP_OK) {
         ESP_LOGI(HTTPS_OTA, "esp_https_ota_get_img_desc failed");
-        g_ota_status = OTA_STATUS_FAILED;  // ← 失败
+        g_ota_status = OTA_STATUS_FAILED;  // 
         goto ota_end;
     }
+    err = ESP_FAIL;
     err = validate_image_header(&app_desc);
     if (err != ESP_OK) {
         ESP_LOGI(HTTPS_OTA, "image header verification failed");
-        g_ota_status = OTA_STATUS_FAILED;  // ← 失败
+        g_ota_status = OTA_STATUS_FAILED;  // 
         goto ota_end;
     }else{
         ESP_LOGI(HTTPS_OTA, "image header verification success");
@@ -166,6 +177,7 @@ static void Https_Ota_Task_Cb(void *pvParameter)
             
             break;
         }
+        err = ESP_FAIL;
         err = esp_https_ota_perform(https_ota_handle);
         
         if (err != ESP_ERR_HTTPS_OTA_IN_PROGRESS) {
@@ -192,10 +204,9 @@ static void Https_Ota_Task_Cb(void *pvParameter)
             g_ota_status = OTA_STATUS_SUCCESS;  //成功
             ota_timeout_count=0;
             //成功不走下面失败的
-            uint8_t ret = Https_Ota_Status_Set(g_ota_status);
-
+            #if (!ENABLE_HTTP_N455_OTA_FUNC) //n455升级成功后上报状态 esp32升级成功后b不需要上报了 因为n455升级成功后会发一个特定的ack 包给esp32 esp32收到这个ack包就知道n455升级成功了 就不需要esp32再发一次mqtt消息上报了
+            uint8_t ret = Https_Ota_Report_Status(g_ota_status);
             
-            // 
             g_ota_status = OTA_STATUS_IDLE;
             common_setting.https_ota_cfg.https_ota_start_flag = 0;
             if(!ret)
@@ -204,6 +215,19 @@ static void Https_Ota_Task_Cb(void *pvParameter)
                     xEventGroupSetBits(common_event_group, COMMON_MQTT_CONNECT_BIT);
                 }
             }
+            #else
+            // xEventGroupSetBits(common_event_group, COMMON_HTTPS_N455_OTA_BIT);
+            if(N455_Ota_Task() == 1) //初始化失败回滚固件
+            {
+                // 短延时等待任务尝试创建
+                esp_err_t ret = esp_ota_mark_app_invalid_rollback();
+                ESP_LOGI(HTTPS_OTA, "esp32 restart: %d", ret);
+                ESP_LOGI(HTTPS_OTA, "455 task failed to start, rollback esp32");
+                Https_Ota_Report_Status(OTA_STATUS_FAILED); //上报标识 升级失败了
+                Https_Ota_Clear_Upgrade_Flag();
+                xEventGroupSetBits(common_event_group, COMMON_MQTT_CONNECT_BIT);//
+            }
+            #endif
             vTaskDelete(NULL);
         } else {
             if (ota_finish_err == ESP_ERR_OTA_VALIDATE_FAILED) {
@@ -224,31 +248,86 @@ ota_end:
     ESP_LOGI(HTTPS_OTA, "ESP_HTTPS_OTA upgrade failed");
     ota_timeout_count=0;
      // (失败/超时 都在这里发)
-    Https_Ota_Status_Set(g_ota_status);
-
+    Https_Ota_Report_Status(OTA_STATUS_FAILED);
     // 
-    g_ota_status = OTA_STATUS_IDLE;
-    common_setting.https_ota_cfg.https_ota_start_flag = 0;
-
+    Https_Ota_Clear_Upgrade_Flag(); //清除升级标识
     if(common_setting.wifi_status.wifi_state == 1){
         xEventGroupSetBits(common_event_group, COMMON_MQTT_CONNECT_BIT);
     }
-        
-
+    
     // 删除
     vTaskDelete(NULL);
 }
 
+//清空升级标识
+void Https_Ota_Clear_Upgrade_Flag(void)
+{
+    g_ota_status = OTA_STATUS_IDLE;
+    common_setting.https_ota_cfg.https_ota_start_flag = 0;
+    ota_timeout_count = 0;
+    https_ota_init=0;
+    ota_timeout_req=0;
+}
 
 
+static uint8_t version_check_flag = 0;
+// OTA版本检查
+//versin字符串转16进制版本号 0x0103
+// url 升级地址
+uint8_t Https_Ota_Version_Check(char *version,char *url)
+{
+    version_check_flag=0;
+    if(version == NULL || url == NULL)
+    {
+        return 0;
+    }
+    uint16_t new_version = version_str_to_hex(version);
+    // 核心:把 0x0A15 转成浮点数 10.21
+    ESP_LOGI(HTTPS_OTA, "ver: %s %04x FW_VERSION:%04x", version,new_version,FW_VERSION);
+    if(new_version != FW_VERSION && new_version != 0xffff)
+    {
+        version_check_flag = 1;
+        strncpy(https_ota_url, url, OTA_URL_SIZE - 1);
+        https_ota_url[OTA_URL_SIZE - 1] = '\0'; // 确保字符串以null结尾
+        ESP_LOGI(HTTPS_OTA, "need upgrade\n");
+        Https_Ota_Start();
+        return 1;
+    }else{
+        ESP_LOGI(HTTPS_OTA, "no need upgrade\n");
+    }
+    return 0;
+}
+
+uint8_t Https_Ota_Version_Flag(void)
+{
+
+    return version_check_flag;
+
+}
 
 
-//ota版本校验 不一致需要升级 一直不需要升级ota
-uint8_t Https_Ota_Version_Check(void)
+/*
+func:获取OTA状态
+0:空闲
+1: 正在OTA升级.......
+*/
+uint8_t Https_Get_Ota_Status(void)
 {
-    return 0;
+    if(g_ota_status != 0 || common_setting.https_ota_cfg.https_ota_start_flag == 1)
+    {
+        return 1;
 
+    }
+    return 0;
 }
+uint8_t Https_Get_Ota_Success(void)
+{
+    return g_ota_status;
+}
+
+/*
+func:OTA开始
+*/
 void Https_Ota_Start(void)
 {
     if(g_ota_status != 0 || common_setting.https_ota_cfg.https_ota_start_flag == 1)
@@ -257,13 +336,14 @@ void Https_Ota_Start(void)
         return;
     }
     ESP_LOGI(HTTPS_OTA, "ota is start\n");
-    retry_ota_num=0;
     ota_timeout_count = 0;
-    ota_full_failed_flag = false;   // 新OTA任务,清空三次失败锁
     common_setting.https_ota_cfg.https_ota_start_flag = 1;
     xEventGroupSetBits(common_event_group, COMMON_HTTPS_OTA_BIT);
 
 }
+/*
+func:OTA停止
+*/
 void Https_Ota_Stop(void)
 {
     if(g_ota_status != OTA_STATUS_SUCCESS && g_ota_status > 0 && common_setting.https_ota_cfg.https_ota_start_flag == 1)
@@ -273,48 +353,38 @@ void Https_Ota_Stop(void)
         }
     }
 
+
 }
 
+/*
+func:OTA任务
+*/
 
 void Https_Ota_Task(void)
 {
-    if(ota_full_failed_flag)
+    if(https_ota_init)
     {
-        retry_ota_num=0;
-        ota_timeout_count = 0;
-        g_ota_status = OTA_STATUS_IDLE;
-        common_setting.https_ota_cfg.https_ota_start_flag=0;
         return;
     }
-
-    if(HTTPS_OTA_RETRY_NUM > 0)
-    {
-        retry_ota_num++;
-        if(retry_ota_num > HTTPS_OTA_RETRY_NUM){ //重试三次ota升级失败后不再升级 后续要重连mqtt
-            common_setting.https_ota_cfg.https_ota_start_flag=0;
-            retry_ota_num=0;
-            g_ota_status = OTA_STATUS_IDLE;
-            xEventGroupSetBits(common_event_group, COMMON_MQTT_CONNECT_BIT);//连接mqtt
-            return;
-        }
-    }
-    
+    https_ota_init=1;
     BaseType_t ret = xTaskCreate(&Https_Ota_Task_Cb, "https_ota_task", HTTPS_OTA_STACK_SIZE, NULL, 4, NULL);
     if(ret !=pdPASS )
     {
-        if(HTTPS_OTA_RETRY_NUM > 0){
-            xEventGroupSetBits(common_event_group, COMMON_HTTPS_OTA_BIT);
-        }
+        Https_Ota_Clear_Upgrade_Flag();
+        g_ota_status = OTA_STATUS_IDLE;
     }else{
-        
+        https_ota_init=1;
+        g_ota_status = OTA_STATUS_UPGRADING;
         ESP_LOGI(HTTPS_OTA, "task success\n");
 
     }
 }
-
+/*
+func:OTA超时检查
+*/
 void Https_Ota_Check_TimeOut(void)
 {
-    if(g_ota_status != OTA_STATUS_SUCCESS && g_ota_status > 0 && common_setting.https_ota_cfg.https_ota_start_flag == 1) //一直没有成功
+    if(g_ota_status == OTA_STATUS_UPGRADING && g_ota_status > 0 && common_setting.https_ota_cfg.https_ota_start_flag == 1) //一直没有成功
     {
         if(ota_timeout_count > 0)
         {
@@ -327,10 +397,22 @@ void Https_Ota_Check_TimeOut(void)
                 }
             }
         }
+    }else{
+        ota_timeout_count=0;
     }
+    // if(ota_faile_count > 0)
+    // {
+    //     ota_faile_count--;
+    //     if(ota_faile_count == 0)
+    //     {
+    //         Https_Ota_Start();
+
+    //     }
+
+    // }
 
 }
-// wifi事件处理函数 断开 连接 获取ip等事件都会进入这个函数
+// OTA升级回调事件处理函数
 static void ota_event_handler(void* arg, esp_event_base_t event_base,
                                 int32_t event_id, void* event_data)
 {
@@ -348,7 +430,7 @@ static void ota_event_handler(void* arg, esp_event_base_t event_base,
                 ESP_LOGI(HTTPS_OTA, "Reading Image Description");
                 break;
             case ESP_HTTPS_OTA_VERIFY_CHIP_ID:
-                ESP_LOGI(HTTPS_OTA, "Verifying chip id of new image: %d", *(esp_chip_id_t *)event_data);
+                // ESP_LOGI(HTTPS_OTA, "Verifying chip id of new image: %d", *(esp_chip_id_t *)event_data);
                 break;
             case ESP_HTTPS_OTA_DECRYPT_CB:
                 ESP_LOGI(HTTPS_OTA, "Callback to decrypt function");
@@ -376,10 +458,12 @@ void Https_Ota_Handler_Init(void)
 {
     ESP_ERROR_CHECK(esp_event_handler_register(ESP_HTTPS_OTA_EVENT, ESP_EVENT_ANY_ID, &ota_event_handler, NULL));
 }
+/*
+func:https OTA状态检查
+*/
 void Https_Ota_Status_Check(void)
 {
-    if((xEventGroupWaitBits(common_event_group, COMMON_HTTPS_OTA_BIT, pdFALSE, pdFALSE, 0) & COMMON_HTTPS_OTA_BIT) != 0 && common_setting.ble_status.ble_state == 0 \
-    && common_setting.wifi_status.wifi_state == 1)
+    if((xEventGroupWaitBits(common_event_group, COMMON_HTTPS_OTA_BIT, pdFALSE, pdFALSE, 0) & COMMON_HTTPS_OTA_BIT) != 0)
     {
         xEventGroupClearBits(common_event_group, COMMON_HTTPS_OTA_BIT);
         vTaskDelay(50 / portTICK_PERIOD_MS);
@@ -387,7 +471,7 @@ void Https_Ota_Status_Check(void)
     }
     
 }
-static esp_err_t _https_ota_event_handler(esp_http_client_event_t *evt)
+static esp_err_t _http_ota_status_event_handler(esp_http_client_event_t *evt)
 {
     switch (evt->event_id) {
     case HTTP_EVENT_ERROR:
@@ -427,13 +511,12 @@ static esp_err_t _https_ota_event_handler(esp_http_client_event_t *evt)
     }
     return ESP_OK;
 }
-uint8_t Https_Ota_Status_Set(uint8_t ota_status)
-{
 
-    if(common_setting.wifi_status.wifi_state==0)
-    {
-        return 0;
-    }
+/*
+FUNC:OTA升级状态上报 http请求
+*/
+uint8_t Https_Ota_Report_Status(uint8_t ota_status)
+{
     // http://192.168.66.85:8089/iot/firmware/task/detailadd     {
     // "serialNumber": "PXN1LJ1QUR078E",
     // "upgradeStatus": 4 升级失败 3升级成功,
@@ -441,9 +524,8 @@ uint8_t Https_Ota_Status_Set(uint8_t ota_status)
     // } 
     esp_http_client_config_t http_config = 
     {
-        .event_handler = _https_ota_event_handler,
+        .event_handler = _http_ota_status_event_handler,
         .disable_auto_redirect = true,
-        .keep_alive_enable = true,
     };
     int result = 0;
     esp_http_client_handle_t http_client = NULL;
@@ -466,11 +548,23 @@ uint8_t Https_Ota_Status_Set(uint8_t ota_status)
             continue;
         }      
         cJSON_AddStringToObject(pRoot, "serialNumber", (const char*)common_storage.net_info.serial_number);
-        if(ota_status == OTA_STATUS_SUCCESS)
+        if(ota_status == OTA_STATUS_SUCCESS 
+        #if ENABLE_HTTP_N455_OTA_FUNC
+            || ota_status == N455_OTA_STATUS_SUCCESS
+        )
+        #else
+        )
+        #endif
         {
             cJSON_AddNumberToObject(pRoot,"upgradeStatus", 3);
             cJSON_AddStringToObject(pRoot, "detailMsg", "升级成功");
-        }else if(ota_status == OTA_STATUS_UPGRADING)
+        }else if(ota_status == OTA_STATUS_UPGRADING 
+            #if ENABLE_HTTP_N455_OTA_FUNC
+            || ota_status == OTA_STATUS_UPGRADING
+        )
+        #else
+        )
+        #endif
         {
             cJSON_AddStringToObject(pRoot, "detailMsg", "升级中");
             cJSON_AddNumberToObject(pRoot,"upgradeStatus", 5);
@@ -485,7 +579,6 @@ uint8_t Https_Ota_Status_Set(uint8_t ota_status)
         if(strlen(post_data) == 0 && post_data == NULL)//数据为空说明cJSON构建失败
         {
             cJSON_Delete(pRoot);
-            
             vTaskDelay(50);
             continue; 
         }
@@ -546,7 +639,13 @@ uint8_t Https_Ota_Status_Set(uint8_t ota_status)
         vTaskDelay(50);
     }
 
-    if(ota_status == OTA_STATUS_SUCCESS)
+    if(ota_status == OTA_STATUS_SUCCESS
+    #if ENABLE_HTTP_N455_OTA_FUNC
+            || ota_status == OTA_STATUS_UPGRADING
+    )
+    #else
+    )
+    #endif
     {
         Wifi_Stop();//断开wifi
         esp_restart();
@@ -554,4 +653,6 @@ uint8_t Https_Ota_Status_Set(uint8_t ota_status)
     }
     return 0;
 }
+
+
 #endif
index 9277b99..d46b88d 100644 (file)
@@ -17,14 +17,19 @@ extern ota_status_t g_ota_status;
 
 void Https_Ota_Task(void);//ota升级任务
 void Https_Ota_Status_Check(void);//是否需要ota升级状态
-uint8_t Https_Ota_Version_Check(void); //固件版本检查
+/*
+ota版本检查
+*/
+uint8_t Https_Ota_Version_Check(char *version,char *url);
 
 void Https_Ota_Start(void); //开始ota升级
 void Https_Ota_Stop(void);
 void Https_Ota_Handler_Init(void); //ota注册回调
-uint8_t Https_Ota_Status_Set(uint8_t ota_status);//report_ota_status(uint8_t ota_status);
-extern char https_ota_url[255];
+uint8_t Https_Ota_Report_Status(uint8_t ota_status);//report_ota_status(uint8_t ota_status);
 void Https_Ota_Check_TimeOut(void); //ota超时检查
-
+uint8_t Https_Get_Ota_Status(void);
+void Https_Ota_Clear_Upgrade_Flag(void);//清除升级标识
+uint8_t Https_Get_Ota_Success(void);//是否升级成功
+uint8_t Https_Ota_Version_Flag(void);//版本检查结果标识
 #endif
 #endif
\ No newline at end of file
diff --git a/main/n455_ota.c b/main/n455_ota.c
new file mode 100644 (file)
index 0000000..6c314fc
--- /dev/null
@@ -0,0 +1,646 @@
+#include <string.h>
+#include <inttypes.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/event_groups.h"
+#include "esp_system.h"
+#include "esp_event.h"
+#include "esp_log.h"
+#include "esp_ota_ops.h"
+#include "esp_http_client.h"
+#include "nvs.h"
+#include "nvs_flash.h"
+#include "protocol_examples_common.h"
+#include "n455_ota.h"
+#include "project_common.h"
+#include "user_mqtt.h"
+#include "wifi.h"
+#include "uart.h"
+#include "https_ota.h"
+#if (ENABLE_HTTP_N455_OTA_FUNC)
+static const char *N455_OTA = "455_OTA";
+#if CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
+#include "esp_efuse.h"
+#endif
+
+#if CONFIG_EXAMPLE_CONNECT_WIFI
+#include "esp_wifi.h"
+#endif
+#include "esp_crt_bundle.h"
+
+N455_ota_status_t n455_g_ota_status = N455_OTA_STATUS_IDLE; // 
+#define OTA_URL_MAX_LEN 255
+#define OAT_CONNECT_RETRY_NUM  3 //重连服务器次数 3
+#define OTA_TOTAL_TIMEOUT_S 30 //总超时时间 单位s
+#define HTTPS_OTA_STACK_SIZE   (4*1024)
+static char n455_ota_url[OTA_URL_MAX_LEN] = "https://pxn-iot.s3.us-east-2.amazonaws.com/iot01/2026/05/19/6a0c013d7911aa4f1c76a42e.lsuf";
+
+
+// BIN 文件头
+#define FW_HEADER_SIZE          256     // 前256字节是头,需要跳过
+
+// 全局升级应答
+static volatile bool  uart_ack_received = false; // UART应答的 1 标识uart收到回复 
+static volatile uint8_t uart_ack = 0xFF; //UART应答的 1 成功 2 失败 0xFF未收到应答 0表示收到但失败
+static  uint8_t n455_ota_init = 0;
+static volatile uint8_t n455_ota_stop = 0;
+static volatile uint16_t n455_ota_timeout = 0;
+// 捕获455升级应答(给uart.c调用)
+void N455_Ota_Capture_Ack(uint8_t cmd, uint8_t ack)
+{
+    if(cmd == CMD1_N455)
+    {
+        uart_ack = ack;
+        uart_ack_received = true;
+    }
+}
+
+// 等待应答
+static bool ota_wait_ack(uint8_t expect_cmd2)
+{
+    uart_ack_received = false;
+    uart_ack = 0xFF;
+
+    uint32_t start = xTaskGetTickCount();
+    uint32_t ack_outime = OTA_TIMEOUT_MS;
+    if(expect_cmd2 == CMD2_READY ) //开始升级 复制搬运需要时间等待应答,适当增加超时时间
+    {
+        ack_outime = 10000; // 增加超时时间
+    }else if(expect_cmd2 == CMD2_CRC_CHECK) //写入每一包数据等待应答,时间不宜过长,否则影响升级速度
+    {
+        ack_outime = 5000; // 写入每包数据等待2秒
+    }
+    while((xTaskGetTickCount() - start) < ack_outime)
+    {
+        if(n455_ota_stop)
+        {
+            uart_ack_received=false;
+            break;
+        }
+        if(uart_ack_received)
+        {
+           break;
+        }
+        vTaskDelay(1 / portTICK_PERIOD_MS);
+    }
+    if(uart_ack_received == false)
+    {
+        ESP_LOGW(N455_OTA, "TIMEOUT %02X", expect_cmd2);
+        return false;
+    }
+    if(uart_ack == 1) // 1表示成功
+    {
+        return true;
+    }
+    else // 其他表示失败
+    {
+        return false;
+    }
+}
+
+// 带3次重发机制发送
+static bool ota_send_with_retry(uint8_t cmd2, uint8_t *data, uint8_t len)
+{
+    uint8_t retry = 0;
+    bool ok = false;
+
+    while(retry < MAX_RETRY_TIMES && !ok)
+    {
+        IAP_LITE_CMD_T cmd = {0};
+        switch (cmd2)
+        {
+            case CMD2_READY:
+                cmd.ready.protocol_version = 0x01;
+                cmd.ready.replay = 0x00;
+                cmd.ready.sub_cmd = CMD2_READY;
+                Uart_Reply_Send(COMMON_UART_MCU_FIRMWARE_UPDATE_CMD, (uint8_t*)&cmd.ready, sizeof(cmd.ready), HOST_TYPE_UART);
+                break;
+            case CMD2_ERASE:
+
+                cmd.erase.protocol_version = 0x01;
+                cmd.erase.replay = 0x00;
+                cmd.erase.sub_cmd = CMD2_ERASE;
+                Uart_Reply_Send(COMMON_UART_MCU_FIRMWARE_UPDATE_CMD, (uint8_t*)&cmd.erase, sizeof(cmd.erase), HOST_TYPE_UART);
+                break;
+            case CMD2_WRITE:
+                cmd.write.protocol_version = 0x01;
+                cmd.write.replay = 0x00;
+                cmd.write.sub_cmd = CMD2_WRITE;
+                if(data != NULL && len > 0)
+                {
+                    memcpy(&cmd.write.offset, data, 4); // 前4字节是偏移
+                    memcpy(&cmd.write.size, data+4, 2); // 接着2字节是长度
+                    memcpy(cmd.write.content, data+6, len-6); // data前6字节是偏移和长度
+                }
+                Uart_Reply_Send(COMMON_UART_MCU_FIRMWARE_UPDATE_CMD, (uint8_t*)&cmd.write, sizeof(cmd.write), HOST_TYPE_UART);
+                break;
+            case CMD2_WRITE_END:
+                cmd.write_done.protocol_version = 0x01;
+                cmd.write_done.replay = 0x00;
+                cmd.write_done.sub_cmd = CMD2_WRITE_END;
+                Uart_Reply_Send(COMMON_UART_MCU_FIRMWARE_UPDATE_CMD, (uint8_t*)&cmd.write_done, sizeof(cmd.write_done), HOST_TYPE_UART);
+                break;
+            case CMD2_CRC_CHECK:
+                cmd.crc.protocol_version = 0x01;
+                cmd.crc.replay = 0x00;
+                cmd.crc.sub_cmd = CMD2_CRC_CHECK;
+                if(data != NULL && len > 0)
+                {
+                    memcpy(&cmd.crc.size, data, 4); // 前4字节是大小
+                    memcpy(&cmd.crc.crc32, data+4, 4); // 接着4字节是CRC32
+                }
+                Uart_Reply_Send(COMMON_UART_MCU_FIRMWARE_UPDATE_CMD, (uint8_t*)&cmd.crc, sizeof(cmd.crc), HOST_TYPE_UART);
+                break;
+            case CMD2_FINISH:
+                cmd.end.protocol_version = 0x01;
+                cmd.end.replay = 0x00;
+                cmd.end.sub_cmd = CMD2_FINISH;
+                Uart_Reply_Send(COMMON_UART_MCU_FIRMWARE_UPDATE_CMD, (uint8_t*)&cmd.end, sizeof(cmd.end), HOST_TYPE_UART);
+                break;
+            case CMD2_MOVE:
+                cmd.move.protocol_version = 0x01;
+                cmd.move.replay = 0x00;
+                cmd.move.sub_cmd = CMD2_MOVE;
+                Uart_Reply_Send(COMMON_UART_MCU_FIRMWARE_UPDATE_CMD, (uint8_t*)&cmd.move, sizeof(cmd.move), HOST_TYPE_UART);
+                break;
+            default:
+                break;
+        }
+        ok = ota_wait_ack(cmd2);//等待结果回复
+        if(!ok)
+        {
+            if(n455_ota_stop)
+            {
+                retry=MAX_RETRY_TIMES; // 停止升级,退出重试
+                return false;
+            }
+            retry++;
+            ESP_LOGW(N455_OTA, "RETRY:%d", MAX_RETRY_TIMES - retry);
+            vTaskDelay(pdMS_TO_TICKS(10));
+        }
+    }
+    return ok;
+}
+static esp_err_t _http_ota_event_handler(esp_http_client_event_t *evt)
+{
+    switch (evt->event_id) {
+    case HTTP_EVENT_ERROR:
+        ESP_LOGI(N455_OTA, "HTTP_EVENT_ERROR");
+        n455_g_ota_status = N455_OTA_STATUS_FAILED;
+        break;
+    case HTTP_EVENT_ON_CONNECTED:
+        ESP_LOGI(N455_OTA, "HTTP_EVENT_ON_CONNECTED");
+        break;
+    case HTTP_EVENT_HEADER_SENT:
+        // ESP_LOGI(N455_OTA, "HTTP_EVENT_HEADER_SENT");
+        break;
+    case HTTP_EVENT_ON_HEADER:
+        // ESP_LOGI(N455_OTA, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
+        break;
+    case HTTP_EVENT_ON_DATA:
+
+        break;
+    case HTTP_EVENT_ON_FINISH:
+        // ESP_LOGI(N455_OTA, "HTTP_EVENT_ON_FINISH");
+        break;
+    case HTTP_EVENT_DISCONNECTED:
+        ESP_LOGI(N455_OTA, "HTTP_EVENT_DISCONNECTED");
+        break;
+    case HTTP_EVENT_REDIRECT:
+        // ESP_LOGI(N455_OTA, "HTTP_EVENT_REDIRECT");
+        break;
+    }
+    return ESP_OK;
+}
+
+
+/*
+FUNC:N455 OTA升级状态上报 http请求
+*/
+void N455_Ota_Task_Cb(void *param)
+{
+    esp_http_client_config_t config = {
+        .url = n455_ota_url,
+        .crt_bundle_attach = esp_crt_bundle_attach,//需要访问https一定要加这句
+        .event_handler = _http_ota_event_handler,
+        .timeout_ms = 10000,
+        .keep_alive_enable = true,
+    };
+    uint8_t buf[MAX_PACKET_CONTENT];
+    uint32_t real_write_len = 0;
+    CRC32_CTX_T crc_ctx;
+    CRC32_Init(&crc_ctx);
+    uint32_t offset_size = 0;
+    uint8_t write_data[MAX_PACKET_CONTENT+6] = {0};
+    int wlen = 0;
+
+    
+    esp_http_client_handle_t client = NULL;
+    n455_ota_timeout = OTA_TOTAL_TIMEOUT_S;
+    n455_g_ota_status = N455_OTA_STATUS_UPGRADING;
+    for (size_t i = 0; i < OAT_CONNECT_RETRY_NUM; i++)
+    {
+        if(n455_ota_stop)
+        {
+            ESP_LOGI(N455_OTA, "ota stopped");
+            n455_ota_stop=0;
+            n455_g_ota_status = N455_OTA_STATUS_FAILED;
+            goto ota_end;
+            return;
+        }
+        client = esp_http_client_init(&config);
+        if(client == NULL)
+        {
+            n455_g_ota_status = N455_OTA_STATUS_FAILED;
+            vTaskDelay(10 / portTICK_PERIOD_MS);
+            goto ota_end;
+        }
+        esp_err_t err = esp_http_client_open(client, 0);
+        if (err != ESP_OK)
+        {
+            ESP_LOGI(N455_OTA, "connect failed");
+            n455_g_ota_status = N455_OTA_STATUS_FAILED;
+            esp_http_client_close(client);
+            esp_http_client_cleanup(client);
+            client = NULL;
+            vTaskDelay(50 / portTICK_PERIOD_MS);
+            continue;
+        }else{
+            int header_ret = esp_http_client_fetch_headers(client);
+            int code = esp_http_client_get_status_code(client);
+            if(code != 200 && header_ret < 0)
+            {
+                ESP_LOGI(N455_OTA, "code=%d, header_ret=%d", code, header_ret);
+                n455_g_ota_status = N455_OTA_STATUS_FAILED;
+                esp_http_client_close(client);
+                esp_http_client_cleanup(client);
+                client = NULL;
+                vTaskDelay(50 / portTICK_PERIOD_MS);
+                continue;
+            }
+           
+            int64_t total_file_len = esp_http_client_get_content_length(client);
+            ESP_LOGI(N455_OTA, "%ld", (long)total_file_len);
+            if(total_file_len <= 0) 
+            {
+                ESP_LOGI(N455_OTA, "filesize invalid");
+                n455_g_ota_status = N455_OTA_STATUS_FAILED;
+                esp_http_client_close(client);
+                esp_http_client_cleanup(client);
+                client = NULL;
+                vTaskDelay(50 / portTICK_PERIOD_MS);
+                continue;
+            }
+
+            // ====================== 跳过前256字节头 ======================
+            uint8_t header_skip_buf[FW_HEADER_SIZE]={0};
+            int read = esp_http_client_read(client, (char *)header_skip_buf, FW_HEADER_SIZE);
+
+           
+            if(read < FW_HEADER_SIZE)
+            {
+                ESP_LOGI(N455_OTA, "header read failed");
+                n455_g_ota_status = N455_OTA_STATUS_FAILED;
+                goto ota_end;
+                return;
+            }
+            //FE CA 00 EE FF C0 D0 BA
+            if(header_skip_buf[0] != 0xFE || header_skip_buf[1] != 0xCA || \
+                header_skip_buf[2] != 0x00 || header_skip_buf[3] != 0xEE || \
+                header_skip_buf[4] != 0xFF || header_skip_buf[5] != 0xC0 || \
+                header_skip_buf[6] != 0xD0 || header_skip_buf[7] != 0xBA) 
+            {
+                ESP_LOGI(N455_OTA, "header signature invalid");
+                n455_g_ota_status = N455_OTA_STATUS_FAILED;
+                goto ota_end;
+                return;
+            }
+            // ESP_LOG_BUFFER_HEX("OTA", header_skip_buf, FW_HEADER_SIZE);
+
+            // 强制类型转换,直接解析
+            // FW_FILE_HEADER_T *file_hdr = (FW_FILE_HEADER_T *)header_skip_buf;
+
+            // // 读取你要的所有信息
+            // uint16_t vid        = file_hdr->vid_app;          // VID
+            // uint16_t pid        = file_hdr->pid_app;          // PID
+            // uint16_t fw_ver     = file_hdr->fw_version;       // 固件版本
+            // uint16_t build_ver  = file_hdr->build_version;    // 编译版本
+            // char product_code[65] = {0};                      // 产品代码
+            // memcpy(product_code, file_hdr->code, 64);
+            // uint32_t erase_addr = file_hdr->write_erase_start_addr; // 擦除地址
+            // uint32_t erase_size = file_hdr->write_erase_size;      // 擦除大小
+            // uint32_t file_addr  = file_hdr->file_start_addr;       // 文件写入地址
+            // uint32_t file_len   = file_hdr->file_size;             // 固件真实长度
+
+            // ====================== 升级流程 ======================
+            //1.获取设备信息已经有了不需要获取了,直接比对,确认一致才继续后续步骤
+
+
+            //搬运0x00 type = 1
+            if(!ota_send_with_retry(CMD2_READY, NULL,0))
+            {
+                ESP_LOGI(N455_OTA, "ready failed");
+                n455_g_ota_status = N455_OTA_STATUS_FAILED;
+                goto ota_end;
+                return;
+            }
+            // 3. 擦除根据bin文件里面的地址和长度来擦除对应区域,擦除命令格式:地址(3字节)+长度(1字节)
+            if(!ota_send_with_retry(CMD2_ERASE, NULL, 0))
+            {
+                ESP_LOGI(N455_OTA, "erase failed");
+                n455_g_ota_status = N455_OTA_STATUS_FAILED;
+                goto ota_end;
+                return;
+            }
+            uint32_t start_time = xTaskGetTickCount();
+            real_write_len=0;
+            offset_size=0;
+            while (1)
+            {
+                if(n455_ota_stop)
+                {
+                    ESP_LOGI(N455_OTA, "ota stopped");
+                    n455_ota_stop = 0;
+                    n455_g_ota_status = N455_OTA_STATUS_FAILED;
+                    goto ota_end;
+                    return;
+                }
+                read = esp_http_client_read(client, (char *)buf, MAX_PACKET_CONTENT);
+                if(read <= 0)
+                {
+                    break;
+                }
+                memset(write_data, 0, sizeof(write_data));
+                wlen=0;
+                CRC32_Update(&crc_ctx, buf, read); // 从地址开始算CRC
+
+                //偏移量 4字节
+
+                write_data[wlen++] = (offset_size) & 0xFF;
+                write_data[wlen++] = (offset_size >> 8) & 0xFF;
+                write_data[wlen++] = (offset_size >> 16) & 0xFF;
+                write_data[wlen++] = (offset_size >> 24) & 0xFF;
+                //字节长度 2字节
+                write_data[wlen++] = read & 0xFF;
+                write_data[wlen++] = (read >> 8) & 0xFF;
+
+                //内容
+                memcpy(&write_data[wlen], buf, read);
+                wlen+=read;
+                if(!ota_send_with_retry(CMD2_WRITE, write_data, wlen))
+                {
+                    ESP_LOGI(N455_OTA, "write failed");
+                    n455_g_ota_status = N455_OTA_STATUS_FAILED;
+                    goto ota_end;
+                    return;
+                }
+
+                offset_size += read;
+                real_write_len += read;
+                ESP_LOGI(N455_OTA, "wr:%d", real_write_len);
+            }
+            if(total_file_len > 0 && real_write_len != (total_file_len-256)) // 减去256字节头)
+            {
+                ESP_LOGI(N455_OTA, "file len mismatch, real:%d, total:%ld", real_write_len, (long)total_file_len);
+                n455_g_ota_status = N455_OTA_STATUS_FAILED;
+                goto ota_end;
+                return;
+            }
+            if(n455_ota_stop)
+            {
+                ESP_LOGI(N455_OTA, "ota stopped");
+                n455_ota_stop = 0;
+                n455_g_ota_status = N455_OTA_STATUS_FAILED;
+                goto ota_end;
+                return;
+            }
+            ESP_LOGI(N455_OTA, "start_time:%lu", xTaskGetTickCount()-start_time);
+            if (!ota_send_with_retry(CMD2_WRITE_END, NULL, 0))
+            {
+                n455_g_ota_status = N455_OTA_STATUS_FAILED;
+                goto ota_end;
+                return;
+            }
+            // ---------------- 5. CRC校验(0x05) ----------------
+            // 
+            uint32_t crc_value = CRC32_Final(&crc_ctx);
+            uint8_t crc_data[8] = {0};
+            memcpy(crc_data, &real_write_len, 4); // 前4字节是固件大小
+            memcpy(crc_data+4, &crc_value, 4); // 接着4字节是CRC32
+            if(n455_ota_stop)
+            {
+                ESP_LOGI(N455_OTA, "ota stopped");
+                n455_ota_stop = 0;
+                n455_g_ota_status = N455_OTA_STATUS_FAILED;
+                goto ota_end;
+                return;
+            }
+            if (!ota_send_with_retry(CMD2_CRC_CHECK, crc_data, sizeof(crc_data)))
+            {
+                ESP_LOGI(N455_OTA, "crc check failed");
+                n455_g_ota_status = N455_OTA_STATUS_FAILED;
+                goto ota_end;
+                return;
+            }
+            if(n455_ota_stop)
+            {
+                ESP_LOGI(N455_OTA, "ota stopped");
+                n455_ota_stop = 0;
+                n455_g_ota_status = N455_OTA_STATUS_FAILED;
+                goto ota_end;
+                return;
+            }
+            if(!ota_send_with_retry(CMD2_MOVE, NULL,0))
+            {
+                ESP_LOGI(N455_OTA, " move failed");
+                n455_g_ota_status = N455_OTA_STATUS_FAILED;
+                goto ota_end;
+                return;
+            }
+            if(n455_ota_stop)
+            {
+                ESP_LOGI(N455_OTA, "ota stop");
+                n455_ota_stop = 0;
+                n455_g_ota_status = N455_OTA_STATUS_FAILED;
+                goto ota_end;
+                return;
+            }
+            // 4. 结束复位
+            if(!ota_send_with_retry(CMD2_FINISH, NULL, 0))
+            {
+                ESP_LOGI(N455_OTA, "end failed");
+                n455_g_ota_status = N455_OTA_STATUS_FAILED;
+                goto ota_end;
+                return;
+            }
+            if(n455_ota_stop)
+            {
+                ESP_LOGI(N455_OTA, "ota stop");
+                n455_ota_stop = 0;
+                n455_g_ota_status = N455_OTA_STATUS_FAILED;
+                
+                goto ota_end;
+                return;
+            }
+            ESP_LOGI(N455_OTA, "start_timeend:%lu", xTaskGetTickCount()-start_time);
+            n455_g_ota_status = N455_OTA_STATUS_SUCCESS;
+            ESP_LOGI(N455_OTA, "ota success");
+            Https_Ota_Report_Status(n455_g_ota_status);
+            vTaskDelay(1000 / portTICK_PERIOD_MS);
+
+            Wifi_Stop();
+            Https_Ota_Clear_Upgrade_Flag(); // 清除32升级标识
+            
+            n455_ota_init=0;
+            vTaskDelay(10 / portTICK_PERIOD_MS);
+            esp_restart();
+            vTaskDelete(NULL);
+            return;
+        }
+    }  
+    if(n455_g_ota_status == N455_OTA_STATUS_FAILED)
+    {
+        goto ota_end;
+    }
+ota_end:
+    if(client != NULL)
+    {
+        esp_http_client_close(client);
+        esp_http_client_cleanup(client);
+        client = NULL;
+    }
+    n455_ota_init=0;
+    n455_g_ota_status = N455_OTA_STATUS_FAILED;
+    n455_ota_stop = 0;
+    //如果32ota成功了 455升级失败了 清除32的升级标识 回滚固件
+    if(Https_Get_Ota_Success() == OTA_STATUS_SUCCESS)
+    {
+        
+        // 标记 ESP32 新固件无效,不重启
+        esp_err_t ret = esp_ota_mark_app_invalid_rollback();
+        ESP_LOGI(N455_OTA, "esp32 restart: %d", ret); 
+    }else{
+        // 如果32升级都失败了,才重启让设备回到正常状态
+       ESP_LOGI(N455_OTA, "32OTA: %d", Https_Get_Ota_Success()); 
+    }
+    Https_Ota_Clear_Upgrade_Flag();
+    Https_Ota_Report_Status(N455_OTA_STATUS_FAILED);//上报升级结果
+    vTaskDelay(10 / portTICK_PERIOD_MS);
+    N455_Ota_Clear_Upgrade_Flag(); // 清除升级标识
+    xEventGroupSetBits(common_event_group, COMMON_MQTT_CONNECT_BIT); // 清除MQTT连接位,触发重连机制
+    vTaskDelete(NULL);
+}
+
+/*
+func:OTA任务
+*/
+
+uint8_t N455_Ota_Task(void)
+{
+    if(n455_ota_init)
+    {
+        ESP_LOGI(N455_OTA, "N455 OTA running\n");
+        return 2;
+    }
+    n455_ota_init=1;
+    BaseType_t ret = xTaskCreate(&N455_Ota_Task_Cb, "https_n455_ota_task", HTTPS_OTA_STACK_SIZE, NULL, 6, NULL);
+    if(ret !=pdPASS )
+    {
+        ESP_LOGI(N455_OTA, "task err\n");
+        n455_ota_init=0;
+        //升级失败了也可以选择重启让设备回到正常状态
+        //esp32回滚固件
+        n455_g_ota_status = N455_OTA_STATUS_IDLE;
+        return 1;
+    }else{
+        n455_g_ota_status = N455_OTA_STATUS_UPGRADING;
+        //成功创建任务后在回调函数里根据升级结果来决定是否重启或者上报mqtt消息等后续操作
+        ESP_LOGI(N455_OTA, "task success\n");
+        return 0;
+    }
+}
+/*
+func:OTA超时检查
+*/
+void N455_Ota_Check_TimeOut(void)
+{
+    if(n455_g_ota_status == N455_OTA_STATUS_UPGRADING && n455_g_ota_status > 0) //一直没有成功
+    {
+        if(n455_ota_timeout > 0)
+        {
+            n455_ota_timeout--;
+            if(n455_ota_timeout == 0)
+            {
+                ESP_LOGI(N455_OTA, "ota timeout");
+                if(!n455_ota_stop)
+                {
+                    n455_ota_stop = 1;
+                }
+            }
+        }
+    }else{
+        n455_ota_timeout=0;
+    }   
+}
+static uint8_t n455_version_check_flag = 0;
+// OTA版本检查
+//versin字符串转16进制版本号 0x0103
+// url 升级地址
+uint8_t N455_Ota_Version_Check(char *version,char *url)
+{
+    n455_version_check_flag=0;
+    if(version == NULL || url == NULL)
+    {
+        return 0;
+    }
+    uint16_t new_version = version_str_to_hex(version);
+    // 核心:把 0x0A15 转成浮点数 10.21
+    ESP_LOGI(N455_OTA, "ver: %s %04x FW_VERSION:%04x", version,new_version,FW_VERSION);
+    if(new_version != FW_VERSION && new_version != 0xffff)
+    {
+        n455_version_check_flag = 1;
+        strncpy(n455_ota_url, url, OTA_URL_MAX_LEN - 1);
+        n455_ota_url[OTA_URL_MAX_LEN - 1] = '\0'; // 确保字符串以null结尾
+        ESP_LOGI(N455_OTA, "need upgrade\n");
+        return 1;
+    }else{
+        ESP_LOGI(N455_OTA, "no need upgrade\n");
+    }
+    return 0;
+}
+
+uint8_t N455_Ota_Version_Flag(void)
+{
+
+    return n455_version_check_flag;
+
+}
+//455升级失败清空32升级标识
+void N455_Ota_Clear_Upgrade_Flag(void)
+{
+    n455_g_ota_status = N455_OTA_STATUS_IDLE; // 状态重置为空闲
+    n455_ota_init=0; //升级初始化标志清零
+    n455_ota_timeout =0; //升级超时标志清零
+    n455_ota_stop = 0;//升级停止标志清零
+
+}
+
+uint8_t N455_Get_Ota_Status(void)
+{
+    return n455_g_ota_status;
+}
+
+/*
+func:455 OTA状态检查
+*/
+void N455_Ota_Status_Check(void)
+{
+    if((xEventGroupWaitBits(common_event_group, COMMON_HTTPS_N455_OTA_BIT, pdFALSE, pdFALSE, 0) & COMMON_HTTPS_N455_OTA_BIT) != 0)
+    {
+        xEventGroupClearBits(common_event_group, COMMON_HTTPS_N455_OTA_BIT);
+        vTaskDelay(50 / portTICK_PERIOD_MS);
+        N455_Ota_Task();
+    }
+    
+}
+#endif
diff --git a/main/n455_ota.h b/main/n455_ota.h
new file mode 100644 (file)
index 0000000..b96a5e0
--- /dev/null
@@ -0,0 +1,114 @@
+#ifndef _HTTP_N455_OTA_H_
+#define _HTTP_N455_OTA_H_
+#define ENABLE_HTTP_N455_OTA_FUNC          1 //是否开启HTTPS_OTA升级
+#if ENABLE_HTTP_N455_OTA_FUNC
+#include <stdint.h>
+#include <stdbool.h>
+typedef enum
+{
+       CMD2_READY = 0,
+       CMD2_ERASE,
+       CMD2_WRITE,
+       CMD2_WRITE_END,
+       CMD2_CRC_CHECK,
+       CMD2_MOVE,
+       CMD2_FINISH,
+}IAP_LITE_SUB_CMD_E;
+/*
+func:OTA停止
+*/
+// ====================模组 uart升级 455 升级协议 ====================
+#define CMD1_N455               COMMON_UART_MCU_FIRMWARE_UPDATE_CMD    // 盘面:0xE0,基座:0xB0,582:0xB2
+#define MAX_PACKET_CONTENT      64     // 协议规定最大64字节 测试建议值
+#define OTA_TIMEOUT_MS          2000
+#define MAX_RETRY_TIMES         3
+
+// 应答
+#define ACK_SUCCESS(cmd)        (cmd)
+#define ACK_FAILED(cmd)         (cmd)
+typedef union
+{
+       struct
+       {
+               uint8_t protocol_version;
+               uint8_t replay;
+               uint8_t sub_cmd;
+       }__attribute__((packed))payload;
+       
+       struct
+       {
+               uint8_t protocol_version;
+               uint8_t replay;
+               uint8_t sub_cmd;
+       }__attribute__((packed))ready;
+       
+       struct
+       {
+               uint8_t protocol_version;
+               uint8_t replay;
+               uint8_t sub_cmd;
+       }__attribute__((packed))erase;
+       
+       struct
+       {
+               uint8_t protocol_version;
+               uint8_t replay;
+               uint8_t sub_cmd;
+               
+               uint32_t offset;
+               uint16_t size;
+               uint8_t content[MAX_PACKET_CONTENT];
+       }__attribute__((packed))write;
+       
+       struct
+       {
+               uint8_t protocol_version;
+               uint8_t replay;
+               uint8_t sub_cmd;
+       }__attribute__((packed))write_done;
+       
+       struct
+       {
+               uint8_t protocol_version;
+               uint8_t replay;
+               uint8_t sub_cmd;
+               
+               uint32_t size;
+               uint32_t crc32;
+       }__attribute__((packed))crc;
+       
+       struct
+       {
+               uint8_t protocol_version;
+               uint8_t replay;
+               uint8_t sub_cmd;
+       }__attribute__((packed))move;
+       struct
+       {
+               uint8_t protocol_version;
+               uint8_t replay;
+               uint8_t sub_cmd;
+       }__attribute__((packed))end;
+
+
+       
+}__attribute__((packed))IAP_LITE_CMD_T;
+// OTA 升级状态枚举
+typedef enum {
+    N455_OTA_STATUS_IDLE = 0,        // 空闲
+    N455_OTA_STATUS_UPGRADING = 1,   // 升级中
+    N455_OTA_STATUS_SUCCESS = 2,     // 升级成功
+    N455_OTA_STATUS_FAILED = 3,      // 升级失败
+} N455_ota_status_t;
+
+extern N455_ota_status_t n455_g_ota_status;
+uint8_t N455_Ota_Task(void); //n455 ota升级任务
+void N455_Ota_Status_Check(void); //455 ota升级状态检查
+void N455_Ota_Capture_Ack(uint8_t cmd, uint8_t ack); //捕获455升级ack
+uint8_t N455_Ota_Version_Flag(void); //版本检查结果标识
+uint8_t N455_Ota_Version_Check(char *version,char *url); //版本检查
+void N455_Ota_Clear_Upgrade_Flag(void); //清除升级标识
+void N455_Ota_Check_TimeOut(void); //ota超时检查
+uint8_t N455_Get_Ota_Status(void);
+#endif
+#endif
\ No newline at end of file
index 4f1848b..e7078ee 100644 (file)
@@ -70,9 +70,6 @@ COMMON_SETTING_T common_setting =
     },
     #endif
 
-    //MQTT
-    // .mqtt_cfg = NULL,
-    .mqtt_client_handle = NULL,
 };
 
 // static BLE_SEND_REPLY_T net_pairing_reply;
@@ -101,7 +98,13 @@ void Check_Host_Type(uint8_t cmd, uint8_t* pbuf, uint16_t len, uint8_t host_type
 //*pub不包含帧头 命令 crcr长度等协议字段,纯数据部分,len为数据部分长度
 
 
-
+/*
+函数功能:ble replay
+cmd:协议指令
+pbuf:发送的数据
+len:数据长度
+host_type:预留
+*/
 void Ble_Pairing_Reply(uint8_t cmd, uint8_t* pbuf, uint16_t len, uint8_t host_type)
 {
     if(common_setting.ble_status.ble_state == 0) //只有蓝牙开启才允许发送蓝牙数据
@@ -133,6 +136,12 @@ void Ble_Pairing_Reply(uint8_t cmd, uint8_t* pbuf, uint16_t len, uint8_t host_ty
     xQueueSend(ble_notify_queue_handle, &net_pairing_reply, 0);
     #endif
 }
+/*
+功能函数: ble protocol
+data:原数据
+len:数据长度
+host_type:预留
+*/
 void Ble_Pairing_Handle(uint8_t *data ,uint16_t len, uint8_t host_type)
 {
     //APP-ESP PROTUCOL协议指令解析 ble接收的数据不需要做数据长度判断 app层处理即可
@@ -933,14 +942,11 @@ void Ble_Pairing_Handle(uint8_t *data ,uint16_t len, uint8_t host_type)
             //清除配网信息
             case COMMON_BLE_CLEAR_NETWORK_INFOR_CMD: 
             {
-                common_setting.ble_status.nimble_flag=0;
                 Wifi_Stop();
                 Mqtt_Disconnect();
                 User_Erase_NotReset();
-                if(common_setting.ble_status.ble_adv_flag == 0) //蓝牙广播关闭状态重新打开
-                {
-                    xEventGroupSetBits(ble_event_group, BLE_ON_BIT);
-                }
+                common_setting.ble_status.nimble_flag=0;
+                xEventGroupSetBits(ble_event_group, BLE_ON_BIT);
             }
             break;
             // 欺骗编译器,勿删
@@ -1047,7 +1053,9 @@ void Ble_Pairing_Handle(uint8_t *data ,uint16_t len, uint8_t host_type)
     }
 }
 
-//配网状态回复
+/*
+配网状态回复
+*/
 void network_request_replay(uint8_t status)
 {
     //失败
@@ -1071,7 +1079,9 @@ void network_request_replay(uint8_t status)
 }
 
 #include "esp_chip_info.h"
-//获取模组的芯片型号
+/*
+获取模组的芯片型号
+*/
 static const char *CHIP_LOG = "CHIP_TAG";
 void get_chip_info(char *chip_id,uint8_t *chip_len)
 {
@@ -1190,7 +1200,7 @@ void wait_for_sntp_sync(void)
     {
         
         int TimeZone = 8;//默认是东八区 8 
-        ESP_LOGI("TIME", "ret : %d", ret);
+       
         common_setting.time_flash_cfg.time_flash=1;
         sntp_sync_init=1;//同步成功
         return;
@@ -1202,7 +1212,34 @@ void wait_for_sntp_sync(void)
 }
 #endif
 
+/*
+将时间戳字符串转换成int64数字
+*/
+void int64_to_str(uint64_t ts, char *out,size_t out_len) {
+    char buf[24] = {0};
+    int i = 0;
+
+    if (ts == 0) {
+        out[0] = '0';
+        out[1] = 0;
+        return;
+    }
+
+    // 数字转字符  17787 的出来是 78771 需要反转 变成17787
+    while (ts > 0) {
+        if(i >= out_len)break;
+        buf[i++] = (ts % 10) + '0';
+        ts /= 10;
+    }
 
+    // 反转
+    int idx = 0;
+    while (i > 0) {
+        out[idx++] = buf[--i];
+    }
+    out[idx] = 0;
+}
+//获取本地的时间戳INT64
 time_t Get_Time_Stamp(void)
 {
     time_t Time_Stamp = 0;
@@ -1210,5 +1247,158 @@ time_t Get_Time_Stamp(void)
     gettimeofday(&tv, NULL);
 
     Time_Stamp = tv.tv_sec;
+
     return Time_Stamp;
-}
\ No newline at end of file
+}
+//是不是有效的时区格式 UTC开头
+static bool is_valid_timezone(const char *tz)
+{
+    // 不能为空
+    if (!tz || strlen(tz) < 4 || strlen(tz) > 8) 
+        return false;
+
+    // 前3个字符必须是 UTC
+    if (strncmp(tz, "UTC", 3) != 0) 
+        return false;
+
+    // 第4位必须是 + 或 -
+    char sign = tz[3];
+    if (sign != '+' && sign != '-') 
+        return false;
+
+    // 后面必须是数字
+    for (int i = 4; i < strlen(tz); i++) {
+        if (!isdigit((unsigned char)tz[i])) 
+            return false;
+    }
+
+    return true;
+}
+/*
+utc_timestamp_sec   :时间戳单位s
+*timeZone           :字符串 UTC+-8
+
+*/
+void set_system_time_str_from_utc(int64_t utc_timestamp_sec, const char *timeZone)
+{
+    if(!is_valid_timezone((const char *)timeZone))
+    {
+        return;
+    }
+    struct timeval tv;
+    struct timezone tz = {0};
+
+    // 1. 直接设置 UTC 时间戳(系统永远存 UTC)
+    tv.tv_sec = utc_timestamp_sec;
+    tv.tv_usec = 0;
+    settimeofday(&tv, &tz);
+
+    // 2. 设置时区(告诉系统怎么转本地时间)
+    
+    setenv("TZ", timeZone, 1);
+    tzset(); // 生效
+}
+//根据时时间戳和时区设置本地时间
+/*
+utc_timestamp_sec:时间戳64
+timezone         : 时区int 8 - 8
+*/
+void set_system_time_int_from_utc(int64_t utc_timestamp_sec, int timeZone)
+{
+    struct timeval tv;
+    struct timezone tz = {0};
+
+    // 1. 直接设置 UTC 时间戳(系统永远存 UTC)
+    tv.tv_sec = utc_timestamp_sec;
+    tv.tv_usec = 0;
+    settimeofday(&tv, &tz);
+
+    // 2. 设置时区(告诉系统怎么转本地时间)
+    char tz_buf[16];
+    if (timeZone >= 0) {
+        // 东时区:UTC-8
+        snprintf(tz_buf, sizeof(tz_buf), "UTC+%d", timeZone);
+    } else {
+        // 西时区:UTC+5
+        snprintf(tz_buf, sizeof(tz_buf), "UTC-%d", timeZone);
+    }
+    setenv("TZ", tz_buf, 1);
+    tzset(); // 生效
+}
+
+/*
+func:版本转换
+云端 version 转 16 进制版本号(例如 1.03 → 0x0103)
+*/
+uint16_t version_str_to_hex(char *version)
+{
+    if(version ==  NULL)
+    {
+        return 0xffff;
+    }
+    if(strlen(version)==0)
+    {
+        ESP_LOGI(COMMON_TAG,"len err%s\n", version);   // 1
+        return 0xffff;
+    }
+    //
+    // // "1.03" → 1
+    char *dot = strchr(version, '.'); 
+    if(dot == NULL) //没有找到.号 不合法
+    {
+        ESP_LOGI(COMMON_TAG,"version%s\n", version);   // 1
+        return 0xffff;
+    }
+    int major = atoi(version);       // 转成数字 10.09 = 10 20.1 =20-
+
+
+    // --------------------
+    // 取小数点后面:03
+    // --------------------
+    int minor = atoi(dot + 1);         // dot+1 指向 "03" → 转成 3
+    // 输出结果
+    ESP_LOGI(COMMON_TAG,"major:%d\n", major);   // 1
+    ESP_LOGI(COMMON_TAG,"minor:%d\n", minor);   // 3
+    ESP_LOGI(COMMON_TAG,"total version:%04x\n", (major << 8) | minor);
+    // 合成 0x0103
+    return (major << 8) | minor;
+}
+
+//恢复出厂重新配网 不需要重启设备
+void Esp32_Factory_Reset(void)
+{
+    ESP_LOGI(COMMON_TAG,"Esp32_Factory_Reset!!%d %d",common_storage.net_info.serial_number_flag,common_storage.net_info.wifi_info_flag);
+    if(common_storage.net_info.serial_number_flag == 1 && common_storage.net_info.wifi_info_flag == 1){
+            
+        if(common_storage.net_info.mqtt_url_len == 0 || common_storage.net_info.wifi_ssid_len == 0 || common_storage.net_info.wifi_pwd_len == 0 || \
+        common_storage.ssl_cert[SSL_CLIENT_CRT].length == 0 || common_storage.ssl_cert[SSL_CLIENT_KEY].length == 0 || common_storage.ssl_cert[SSL_SERVER_CRT].length == 0)
+        {
+            ESP_LOGI(COMMON_TAG,"Esp32_Factory_Reset!!");
+        
+        }else{
+            ESP_LOGI(COMMON_TAG,"common_setting.ble_status.ble_adv_flag:%d",common_setting.ble_status.ble_adv_flag);
+            if(!common_setting.ble_status.ble_adv_flag)
+            {
+                //断开wifi
+                Wifi_Stop();
+                //断开mqtt释放资源
+                Mqtt_Disconnect();
+                vTaskDelay(50 / portTICK_PERIOD_MS);
+                //擦除flash
+                User_Erase_NotReset();
+                common_setting.net_pairing_info.http_url_flag=0;
+                common_setting.net_pairing_info.http_token_flag = 0;
+                common_setting.net_pairing_info.user_id_flag = 0;
+
+                common_setting.ble_status.nimble_flag=0; //配网成功 开机置1
+                common_setting.mqtt_user_cfg.mqtt_start_flag=0; //开始连接mqtt
+                common_setting.ble_status.is_bind = 0; //绑定失败
+                xEventGroupSetBits(ble_event_group, BLE_ON_BIT);
+                ESP_LOGI(COMMON_TAG,"open ble");
+            }
+        }
+    }
+    else{
+        ESP_LOGI(COMMON_TAG,"NO NETWOR INIFOR");
+    }
+}
index 65205d7..bbe7594 100644 (file)
 #include "iap.h"
 #include "esp_ota_ops.h"
 
-
+#define PID_A00D   0
 
 // 定义原始版本
-#define FW_VERSION_B        0x0001
+#define FW_VERSION_B        0x0100
 
 // 安全检查:如果大于 9999,强制改为 0x270F
 #if (FW_VERSION_B > 9999)
@@ -62,7 +62,7 @@
 
 // 最终对外版本
 #define FW_VERSION                             (FW_VERSION_B)          // 固件版本 //10.22         // 固件版本 //10.22         // 固件版本 //10.22         // 固件版本 //0A00 10.00 10.21
-#define BUILD_VERSION                  (0x000A)        // 编译测试版本
+#define BUILD_VERSION                  (0x000C)        // 编译测试版本
 #define DEVICE_VID                  (0x36E6)        // 设备厂商代码
 #define DEVICE_PID                  (0xEC01)        // 设备型号代码
 #define LWIP_LOCAL_HOSTNAME         "PXN-Device"    // WIFI本地主机名称
@@ -153,8 +153,8 @@ typedef enum
 
 }COMMON_STATUS_E;
 
-
-typedef enum
+// #define COMMON_HTTP_BIND_BIT (1u << 6)
+typedef enum 
 {
     COMMON_NONE_BIT = 0,
     COMMON_RESET_BIT = BIT0,
@@ -163,6 +163,9 @@ typedef enum
     COMMON_MQTT_DISCONNECT_BIT = BIT3,
     COMMON_MQTT_INIT_BIT = BIT4,
     COMMON_HTTPS_OTA_BIT = BIT5,
+    COMMON_HTTP_GET_URL_BIT = BIT6,
+    COMMON_HTTP_BIND_BIT = BIT7,
+    COMMON_HTTPS_N455_OTA_BIT = BIT8,
 }COMMON_EVENT_GROUP_BIT_E;
 
 typedef enum
@@ -277,6 +280,7 @@ typedef struct
     uint8_t ble_state;  // 0:蓝牙断开   1:连接中 2:连接成功
     uint8_t nimble_flag; // 0:配网失败 1: 配网成功
     uint8_t ble_adv_flag; //1:开启广播 0: 关闭广播
+    uint8_t is_bind; //1 需绑定 0无需绑定
 }__attribute__((packed)) BLE_STATUS_T;
 
 typedef struct
@@ -311,6 +315,8 @@ typedef struct
     uint8_t mqtt_sub_url_flag:1;
     uint8_t reserved:2;
 
+
+
     // int32_t net_pair_cooldown;
 
     uint16_t serial_number_length;
@@ -352,7 +358,7 @@ typedef struct
     uint8_t heart_beat_enable:1;
     uint8_t mcu_info_got_flag:1;
     uint8_t mcu_platform_mode:1;
-    uint8_t clear_network_info:1;
+    uint8_t is_connect_usb:1;
     uint8_t reserved:4;
     
     // UNIVERSAL
@@ -373,8 +379,8 @@ typedef struct
     NET_PAIR_INFO_T net_pairing_info;
 
     // MQTT
-    esp_mqtt_client_config_t mqtt_cfg;
-    esp_mqtt_client_handle_t mqtt_client_handle;
+    // esp_mqtt_client_config_t mqtt_cfg;
+    // esp_mqtt_client_handle_t mqtt_client_handle;
     MQTT_CONFIG_INFO_T mqtt_user_cfg;
 
     //https ota
@@ -492,11 +498,16 @@ typedef struct
 
 
 //获取时间戳单位是s
+void int64_to_str(uint64_t ts, char *out,size_t out_len);
 time_t Get_Time_Stamp(void);
+void set_system_time_int_from_utc(int64_t utc_timestamp_sec, int timeZone);
+void set_system_time_str_from_utc(int64_t utc_timestamp_sec, const char *timeZone);
 void network_request_replay(uint8_t status);
 
 void get_chip_info(char *chip_id,uint8_t *chip_len);
 void print_chip_info(void);
+uint16_t version_str_to_hex(char *version);
+void Esp32_Factory_Reset(void);
 #if ENABLE_SYNC_SNTP_TIME
 void wait_for_sntp_sync(void);
 #endif
index 0894e26..01cd0ef 100644 (file)
@@ -2,6 +2,7 @@
 #include "user_mqtt.h"
 #include "uart.h"
 #include "ble.h"
+#include "n455_ota.h"
 static const char *UART_TAG = "UART_TASK";
 static const char *COMMON_TAG = "UART_RECV";
 // static const int uart_rx_max = UART_BUF_SIZE;
@@ -11,7 +12,7 @@ uint8_t uart_tx_queue_storage[UART_TX_QUEUE_LENGTH*UART_TX_QUEUE_ITEM_SIZE];
 QueueHandle_t uart_tx_queue_handle;
 StaticQueue_t uart_tx_queue_buffer;
 
-//
+// //
 uint8_t uart_rx_queue_storage[UART_RX_QUEUE_LENGTH*UART_RX_QUEUE_ITEM_SIZE];
 QueueHandle_t uart_rx_queue_handle;
 StaticQueue_t uart_rx_queue_buffer;
@@ -20,7 +21,9 @@ StaticQueue_t uart_rx_queue_buffer;
 TaskHandle_t uart_task_handler;
 StackType_t uart_task_stack[UART_TASK_STACK];
 StaticTask_t uart_task_tcb;
-
+/*
+func:uart初始化
+*/
 void Uart_Initialize(void)
 {
     const uart_config_t uart_config = {
@@ -141,74 +144,20 @@ void Uart_Rx_Queue_Process(void)
 #else
 void Uart_Rx_Queue_Process(void)
 {
-    static UART_RECV_DATA_T uart_rx_tmp_struct = {0};
-    if(xQueueReceive(uart_rx_queue_handle, &uart_rx_tmp_struct, 0) == pdTRUE)
-    {
-
-        // 这里可以对uart_rx_temp进行解析,处理粘包/断包等问题
-        // ESP_LOGI(UART_TAG, "Received %d bytes: ", uart_rx_temp.size);
-        // ESP_LOG_BUFFER_HEX(UART_TAG, uart_rx_temp.buffer, uart_rx_temp.size);
-        uint16_t uart_buf_offset = 0;
-        while(uart_buf_offset < uart_rx_tmp_struct.size)
-        {
-            if(uart_rx_tmp_struct.size > UART_BUF_SIZE)
-            {
-                break;
-            }
-            // ESP_LOGI(COMMON_TAG, "uart_buf_offset recv2 %d %d",uart_buf_offset,uart_rx_size);
-            if(uart_rx_tmp_struct.buffer[uart_buf_offset] == FRAMEHEAD_PANEL_TO_IOT)
-            {
-                //uart_rx_data[uart_buf_offset+1] //data
-                //uart_rx_data[uart_buf_offset+2] len
-                //uart_rx_data[uart_buf_offset]+2-1) crc
-                // Crc8_ROHC_Cal(&data[1], len-2) == data[len-1]
-                if(uart_buf_offset+4 > uart_rx_tmp_struct.size || uart_rx_tmp_struct.size < 4) 
-                {
-                    break;
-                }
-                uint8_t len = uart_rx_tmp_struct.buffer[uart_buf_offset+2];//长度字段
-                //f2 00 00 c2 f2 00 01 0f c2
-                //f2 00 01 0f c2
-                uint16_t full_len = 1+1+1+len+1;//header+cmd+len类型+实际数据的长度+crc 无论len是否为0 full_len一定要大于4
-                if(len == 0)
-                {
-                    full_len = 1+1+1+1;//header+cmd+len类型+crc
-                }else{
-                    full_len = 1+1+1+len+1;//header+cmd+len类型+实际数据的长度+crc
-                }
-                if(uart_buf_offset + full_len > UART_BUF_SIZE)//254+4 > 256 //防止溢出
-                {
-                    break;
-                }
-                // ESP_LOGI(COMMON_TAG, "uart_buf_offset recv3 %d %d",uart_buf_offset,uart_rx_size);
-                //if(crcr8(data,len) == crc)
-                //f2 00 00 00 crc uart_buf_offset=0
-                //f2 00 01 0f c2
-                
-                uint8_t crc_cal = Crc8_ROHC_Cal(&uart_rx_tmp_struct.buffer[uart_buf_offset + 1],len+2);//00 cmd+len类型
-                uint8_t crc_pkt = uart_rx_tmp_struct.buffer[uart_buf_offset + full_len-1];//1+1+2=4
-                if(crc_cal == crc_pkt)
-                {
-                    // ESP_LOGI(COMMON_TAG, "uart_buf_offset recv5 %d %d",uart_buf_offset,uart_rx_size);
-                    Uart_Pairing_Handle(&uart_rx_tmp_struct.buffer[uart_buf_offset],full_len, HOST_TYPE_UART);
-
-                }
-                //header+cmd+len+crc
-                uart_buf_offset=uart_buf_offset+full_len;
-            }
-            else
-            {
-                uart_buf_offset++;
-            }
-        }
-        
+    return;
     
-    }
-
-
 
 }
+static volatile uint8_t ble_connected_notify_flag = 0;
+static uint8_t ble_connected_notify_count  = 0;
+static uint8_t ble_connected_notify_retry  = 0;
+void Uart_Set_Ble_Status(void)
+{
+    ble_connected_notify_count=0;
+    ble_connected_notify_retry=0;
+    ble_connected_notify_flag = 1;
 
+}
 // 直接解析完整帧
 void Uart_Recv_Handle(uint8_t *data, uint16_t len)
 {
@@ -240,12 +189,15 @@ void Uart_Recv_Handle(uint8_t *data, uint16_t len)
 }
 #endif
 
-
+/*
+func:uart接收发送task
+*/
 void Uart_Task(void *arg)
 {
     esp_log_level_set(UART_TAG, ESP_LOG_INFO);
     memset(uart_rx_data, 0x00, sizeof(uart_rx_data));
-    static UART_RECV_DATA_T uart_rx_data_struct = {0};
+    // static UART_RECV_DATA_T uart_rx_data_struct = {0};
+    // static uint8_t tx_count = 0;
     while (1)
     {
         static uint8_t read_buf[256]={0};
@@ -253,7 +205,7 @@ void Uart_Task(void *arg)
         if (uart_rx_size > 0)
         {
             // ESP_LOGI(UART_TAG, "Received %d bytes: %d\n", uart_rx_size,rx_timeout_cnt);
-            uart_rx_data_struct.size = uart_rx_size;
+            // uart_rx_data_struct.size = uart_rx_size;
             // Uart_Recv_Handle(uart_rx_data_struct.buffer,uart_rx_size);
             if (rx_cache_len + uart_rx_size < RX_CACHE_MAX_LEN)
             {
@@ -269,20 +221,41 @@ void Uart_Task(void *arg)
             rx_timeout_cnt--;
             if(rx_timeout_cnt == 0 && rx_cache_len > 0)
             {
-                // if(uart_rx_queue_handle){
-                //     xQueueSend(uart_rx_queue_handle, &uart_rx_data_struct, 0);
-                // }
+                
                 Uart_Recv_Handle(rx_cache,rx_cache_len);
                 rx_cache_len=0;
                 memset(rx_cache,0x00,sizeof(rx_cache));
             }
         }
         Uart_Tx_Queue_Process();
-       
-        Uart_Rx_Queue_Process();
+        
+        if(ble_connected_notify_flag)
+        {
+            ble_connected_notify_count++;
+            if(ble_connected_notify_count > 5)
+            {
+                ble_connected_notify_count=0;
+                if(ble_connected_notify_retry < 3)
+                {
+                    ble_connected_notify_retry++;
+                    Uart_Reply_Send(COMMON_UART_BLE_CONNECT_STATUS,NULL,0,HOST_TYPE_UART);
+                }
+                else{
+                    ble_connected_notify_retry=0;
+                    ble_connected_notify_flag = 0;
+                }
+            }
+        }
+        // Uart_Rx_Queue_Process();
         vTaskDelay(1/ portTICK_PERIOD_MS);
     }
 }
+/*
+func:uart协议解析
+data:数据不包含crcr header
+len:纯数据长度
+host_type:预留
+*/
 void Uart_Pairing_Handle(uint8_t *data ,uint16_t len, uint8_t host_type)
 {
     // 
@@ -292,7 +265,7 @@ void Uart_Pairing_Handle(uint8_t *data ,uint16_t len, uint8_t host_type)
         if(data[1] != 0xb7)
         {
             // ESP_LOG_BUFFER_HEX(COMMON_TAG,data,len);
-            ESP_LOGI(COMMON_TAG, "uart recv %d bytes:cmd %0x", len, data[1]);
+            
         }
         // ESP_LOGI(COMMON_TAG, "Read %d bytes:", len);
         // ESP_LOG_BUFFER_HEX(COMMON_TAG, data, len);
@@ -320,8 +293,14 @@ void Uart_Pairing_Handle(uint8_t *data ,uint16_t len, uint8_t host_type)
                 if(data[2] >= 2)
                 {
                     common_setting.mcu_platform_mode = data[4];//mcu连接的pc的模式
-                    ESP_LOGI(COMMON_TAG,"common_setting.mcu_platform_mode:%d\n",common_setting.mcu_platform_mode);
+                    // ESP_LOGI(COMMON_TAG,"common_setting.mcu_platform_mode:%d\n",common_setting.mcu_platform_mode);
+                }
+                if(data[2] >= 3)
+                {
+                    common_setting.is_connect_usb = data[5];//是否连接基座还是电脑
+                    // ESP_LOGI(COMMON_TAG,"common_setting.is_connect_usb:%d\n",common_setting.is_connect_usb);
                 }
+
                 
                 //0x01
             }
@@ -334,7 +313,12 @@ void Uart_Pairing_Handle(uint8_t *data ,uint16_t len, uint8_t host_type)
                 if (len >= 12 && data[2] >= 9)
                 {
                     common_setting.mcu_info.vid = *(uint16_t*)&data[3];
+                    #if PID_A00D
+                    common_setting.mcu_info.pid = 0xA00D;//
+                    #else
                     common_setting.mcu_info.pid = *(uint16_t*)&data[5];
+                    #endif
+                    // 
                     common_setting.mcu_info.fw_version = *(uint16_t*)&data[7];
                     common_setting.mcu_info.build_version = *(uint16_t*)&data[9];
                     memset(common_setting.mcu_info.product_name, 0x00, sizeof(common_setting.mcu_info.product_name));
@@ -355,7 +339,7 @@ void Uart_Pairing_Handle(uint8_t *data ,uint16_t len, uint8_t host_type)
                             uart_pairing_reply.content[0]=0x01;
                             ESP_LOGI(COMMON_TAG, "start nimble 0x%04x 0x%04x 0x%04x 0x%04x %s\n",common_setting.mcu_info.vid,common_setting.mcu_info.pid,\
                             common_setting.mcu_info.fw_version,common_setting.mcu_info.build_version,common_setting.mcu_info.product_name);
-                            #if ENABLE_BLE_FUNC
+                            #if !ENABLE_HTTP_N455_OTA_FUNC
                             Ble_Start_Nimble_NetWork();////开启蓝牙配网
                             #endif
                             
@@ -502,6 +486,20 @@ void Uart_Pairing_Handle(uint8_t *data ,uint16_t len, uint8_t host_type)
             }
             break;
 
+            //
+            case COMMON_UART_FACTORY_RESET:
+            {
+               Esp32_Factory_Reset();
+               uart_pairing_reply.send_flag=1;
+               uart_pairing_reply.len = 0;
+            }
+            break;
+            case COMMON_UART_BLE_CONNECT_STATUS:
+            {
+                ble_connected_notify_flag=0;
+            }
+            break;
+
             // 其它命令
             case 0x20://APP检查到iot服务器地址不可达,通知iot模块停止配网,等待APP重新发起配网
             {
@@ -514,6 +512,22 @@ void Uart_Pairing_Handle(uint8_t *data ,uint16_t len, uint8_t host_type)
                 }
             }
             break;
+            case COMMON_UART_MCU_FIRMWARE_UPDATE_CMD:
+            {
+                // ESP_LOG_BUFFER_HEX(COMMON_TAG,data,len);
+                #if ENABLE_HTTP_N455_OTA_FUNC
+                N455_Ota_Capture_Ack(data[1],data[4]);
+                #endif
+            }
+            break;
+            case 0XB1:
+            {
+                // ESP_LOG_BUFFER_HEX(COMMON_TAG,data,len);
+                #if ENABLE_HTTP_N455_OTA_FUNC
+                N455_Ota_Capture_Ack(data[1],data[4]);
+                #endif
+            }
+            break;
 
             // 固件升级
             case COMMON_UART_ESP_FIRMWARE_UPDATE_CMD:
@@ -537,8 +551,10 @@ void Uart_Pairing_Handle(uint8_t *data ,uint16_t len, uint8_t host_type)
         if(uart_pairing_reply.send_flag)
         {
             Uart_Reply_Send(uart_pairing_reply.cmd, uart_pairing_reply.content, uart_pairing_reply.len, HOST_TYPE_UART);
+            
             // Check_Host_Type(uart_pairing_reply.cmd, uart_pairing_reply.content, uart_pairing_reply.len, host_type);
         }
+        ESP_LOGI(COMMON_TAG, "uart recv %d bytes:cmd %0x", len, data[1]);
     }
     else if(data[0] == FRAMEHEAD_PANEL_TO_IOT)
     {
@@ -553,7 +569,14 @@ void Uart_Pairing_Handle(uint8_t *data ,uint16_t len, uint8_t host_type)
         }
     }
 }
-
+//0x08048000
+/*
+func:uart函数回复send
+cmd:协议指令
+pbuf:数据 不包含header crc 
+len:pbuf的长度
+host_type:预留
+*/
 //*pub不包含帧头 命令 crcr长度等协议字段,纯数据部分,len为数据部分长度
 void Uart_Reply_Send(uint8_t cmd, uint8_t* pbuf, uint8_t len, uint8_t host_type)
 {
@@ -584,3 +607,4 @@ void Uart_Reply_Send(uint8_t cmd, uint8_t* pbuf, uint8_t len, uint8_t host_type)
     xQueueSend(uart_tx_queue_handle, &uart_pairing_reply, 0);
 }
 
+
index 95abe6f..7c9aa87 100644 (file)
@@ -41,8 +41,14 @@ typedef enum
     COMMON_UART_PROPERTY_SYNC_CMD = 0x11,//属性同步通知
     COMMON_UART_GET_TIMESTAMP_CMD = 0x12,//获取时间戳
 
-    //0x13-0xB0
-    COMMON_UART_MCU_FIRMWARE_UPDATE_CMD = 0xB1,//主控固件升级
+    COMMON_UART_FACTORY_RESET = 0x13, //恢复出厂设置
+    COMMON_UART_BLE_CONNECT_STATUS = 0x14, //蓝牙成功
+    //0x15-0xB0
+
+    COMMON_UART_MCU_FIRMWARE_UPDATE_CMD = 0xE0,//主控固件升级
+
+    // COMMON_UART_MCU_FIRMWARE_UPDATE_CMD = 0xE0,//主控固件升级
+
     //0xB2-0xB6保留
     COMMON_UART_ESP_FIRMWARE_UPDATE_CMD = 0xB7,//模组固件升级
 
@@ -51,6 +57,8 @@ typedef enum
 
 }COMMON_UART_CMD_E;
 
+
+
 typedef enum
 {
        REPLY_STATUS_NONE = 0,
@@ -117,4 +125,5 @@ void Uart_Rx_Queue_Process(void);
 void Uart_Task(void *arg);
 void Uart_Reply_Send(uint8_t cmd, uint8_t* pbuf, uint8_t len, uint8_t host_type);
 void Uart_Pairing_Handle(uint8_t *data ,uint16_t len, uint8_t host_type);
+void Uart_Set_Ble_Status(void);
 #endif
index 3e6fe8d..1c2810d 100644 (file)
@@ -15,7 +15,7 @@ void User_Flash_Check(void)
        //寻找分区表
        partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, PARA_FLASH_NAME);
        assert(partition != NULL);
-       // User_Erase_Nimble_NetWork_Infor();
+       User_Erase_Nimble_NetWork_Infor();
        //读取flash数据到common_storage
        
        if(User_Flash_Read_Check(UF_OFFSET_USER_CONFIG_INFO_ADDR, UF_OFFSET_USER_CONFIG_INFO_FLAG, &common_storage.net_info, sizeof(NET_INFO_T)) != ESP_OK)
@@ -110,39 +110,15 @@ void User_Erase_NotReset(void)
        User_Erase_Nimble_NetWork_Infor();
        //read wifi 信息
        User_Flash_Check();
+       memset(&common_storage, 0, sizeof(common_storage));
 
-       memset(common_setting.wifi_status.cur_ssid,0,sizeof(common_setting.wifi_status.cur_ssid));
-       common_setting.wifi_status.cur_ssid_len = 0;
-       memset(common_setting.wifi_status.cur_pwd,0,sizeof(common_setting.wifi_status.cur_pwd));
-       common_setting.wifi_status.cur_pwd_len = 0;
-
-       memset(common_storage.net_info.wifi_ssid,0,sizeof(common_storage.net_info.wifi_ssid));
-       common_storage.net_info.wifi_ssid_len=0;
-       memset(common_storage.net_info.wifi_pwd,0,sizeof(common_storage.net_info.wifi_pwd));
-       common_storage.net_info.wifi_pwd_len=0;
-
-       common_storage.net_info.wifi_info_flag=0;
-
-       memset(common_setting.net_pairing_info.http_url, 0x00,sizeof(common_setting.net_pairing_info.http_url));
-       common_setting.net_pairing_info.http_url_length = 0;
-    common_setting.net_pairing_info.http_url_flag = 0;
-
-       memset(common_setting.net_pairing_info.http_token, 0x00,sizeof(common_setting.net_pairing_info.http_token));
-       common_setting.net_pairing_info.http_token_length = 0;
-    common_setting.net_pairing_info.http_token_flag = 0;
-
+       memset(&common_setting.net_pairing_info,0x00,sizeof(common_setting.net_pairing_info));
 
-       memset(common_setting.net_pairing_info.user_id, 0x00,sizeof(common_setting.net_pairing_info.user_id));
-       common_setting.net_pairing_info.user_id_flag = 0;
-    common_storage.net_info.user_id_flag =0;
+       memset(&common_setting.wifi_status,0x00,sizeof(common_setting.wifi_status));
 
-       memset(common_setting.net_pairing_info.mqtt_sub_url, 0x00, sizeof(common_setting.net_pairing_info.mqtt_sub_url));
-       common_setting.net_pairing_info.mqtt_sub_url_length = 0;
-    common_setting.net_pairing_info.mqtt_sub_url_flag = 0;
+       memset(&common_setting.mqtt_user_cfg,0x00,sizeof(common_setting.mqtt_user_cfg));
 
-       memset(common_setting.net_pairing_info.serial_number, 0x00, sizeof(common_setting.net_pairing_info.serial_number));
-       common_setting.net_pairing_info.serial_number_length = 0;
-       common_setting.net_pairing_info.serial_number_flag = 0;
+       memset(&common_setting.https_ota_cfg,0x00,sizeof(common_setting.https_ota_cfg));
        
        
 }
index 882ee8e..b553510 100644 (file)
@@ -1,10 +1,14 @@
 #include "project_common.h"
 #include "https_ota.h"
 #include "user_http.h"
+#include "user_mqtt.h"
 #if ENABLE_HTTP_FUNC
 #define CLOSE_HTTP_LOG  0
 static const char *HTTP_TAG = "http";
+/*
+func:http请求回调函数
 
+*/
 static esp_err_t _http_event_handler(esp_http_client_event_t *evt)
 {
     switch (evt->event_id) {
@@ -62,37 +66,62 @@ HTTP_GET_CERT_TASK_PARAM_T http_get_cert_task_param;
 static const char *HTTP_DOWNLOAD_TASK_TAG = "http_download_task";
 const esp_partition_t *s_ota_partition = NULL;
 esp_ota_handle_t s_ota_handle = 0;
+// 超轻量校验证书是否合法(只检查格式,几乎不占FLASH)
+bool is_valid_certificate(const char *cert)
+{
+    if (cert == NULL || strlen(cert) < 200) {
+        return false;
+    }
+
+    // 必须包含开头和结尾
+    if (strstr(cert, "-----BEGIN CERTIFICATE-----") == NULL) {
+        ESP_LOGI(HTTP_TAG,"HTTP CER ERR");
+        return false;
+    }
+    if (strstr(cert, "-----END CERTIFICATE-----") == NULL) {
+        ESP_LOGI(HTTP_TAG,"HTTP CER ERR");
+        return false;
+    }
+
+    return true;
+}
+
+// // 超轻量校验私钥是否合法
+// bool is_valid_private_key(const char *key)
+// {
+//     if (key == NULL || strlen(key) < 200) {
+//         return false;
+//     }
+
+//     if (strstr(key, "-----BEGIN RSA PRIVATE KEY-----") == NULL)
+//     {
+//         ESP_LOGI(HTTP_TAG,"HTTP KEY ERR");
+//         return false;
+//     }
+
+//     if (strstr(key, "-----END RSA PRIVATE KEY-----") == NULL)
+//     {
+//         ESP_LOGI(HTTP_TAG,"HTTP KEY ERR");
+//         return false;
+//     }
 
+//     return true;
+// }
 static void Http_Download_Task_Cb(void *pvParameters)
 {
-    #if ENABLE_CHECK_BLE_STATUS
-    if(common_setting.ble_status.ble_state == 0)
-    {    
-        User_Erase_NotReset();//清除配网信息
-        vTaskDelete(NULL);
-    }
-    #endif
     if(common_setting.net_pairing_info.http_url_flag == 0 || common_setting.net_pairing_info.http_token_flag == 0 || common_setting.net_pairing_info.serial_number_flag == 0)
     {
-        User_Erase_NotReset();//清除配网信息
         vTaskDelete(NULL);
     }
     uint8_t success_bit = 0;
-    uint8_t ret = 0;
+
     for(uint8_t cert_type=0;cert_type<3;cert_type++)
     {
-        ret=0;
         if(common_setting.net_pairing_info.http_url_flag == 0 || common_setting.net_pairing_info.http_token_flag == 0 || common_setting.net_pairing_info.serial_number_flag == 0)
         {
-            
+            success_bit = 0;
             break;
         }
-        #if ENABLE_CHECK_BLE_STATUS
-        if(common_setting.ble_status.ble_state == 0)
-        {    
-            break;
-        }
-        #endif
         if(http_get_cert_task_param.url[cert_type][strlen(&http_get_cert_task_param.url[cert_type][0])-1] == ' ')
         {
             http_get_cert_task_param.url[cert_type][strlen(&http_get_cert_task_param.url[cert_type][0])-1] = 0;
@@ -118,14 +147,6 @@ static void Http_Download_Task_Cb(void *pvParameters)
                 err = ESP_FAIL;
                 break;
             }
-            #if ENABLE_CHECK_BLE_STATUS
-            if(common_setting.ble_status.ble_state == 0)
-            {    
-                err = ESP_FAIL;
-                break;
-                
-            }
-            #endif
             ESP_LOGI(HTTP_DOWNLOAD_TASK_TAG, "get cer on: %" PRIu32 " bytes", esp_get_free_heap_size());
             // printf("剩余堆内存: %" PRIu32, esp_get_free_heap_size());
             http_client = esp_http_client_init(&http_config);
@@ -154,10 +175,9 @@ static void Http_Download_Task_Cb(void *pvParameters)
                         int read_len = 0;
                         memset(http_download_cache, 0x00, sizeof(http_download_cache));
                         read_len = esp_http_client_read(http_client, http_download_cache, total_size);
-                        ESP_LOGI(HTTP_DOWNLOAD_TASK_TAG, "\nread_len len%d: total_size:%d\n", read_len, total_size);
+                        ESP_LOGI(HTTP_DOWNLOAD_TASK_TAG, "\nread_len len%d: http_download_cache:%s\n", read_len, http_download_cache);
                         if(read_len == total_size && read_len <= MAX_HTTP_OUTPUT_BUFFER)
                         {
-                            // 成功
                             // ESP_LOGI(HTTP_DOWNLOAD_TASK_TAG, "\nrecv data len%d: %s\n", total_size, http_download_cache);
                             if(common_storage.ssl_cert[cert_type].length == total_size && memcmp(http_download_cache, common_storage.ssl_cert[cert_type].content, total_size) == 0)
                             {
@@ -231,19 +251,6 @@ static void Http_Download_Task_Cb(void *pvParameters)
         }
         vTaskDelay(50 / portTICK_PERIOD_MS);
     }
-    if(common_setting.net_pairing_info.http_url_flag == 0 || common_setting.net_pairing_info.http_token_flag == 0 || common_setting.net_pairing_info.serial_number_flag == 0)
-    {
-        User_Erase_NotReset();//清除配网信息
-        vTaskDelete(NULL);
-    }
-    #if ENABLE_CHECK_BLE_STATUS
-    if(common_setting.ble_status.ble_state == 0)
-    {    
-        
-        User_Erase_NotReset();//清除配网信息
-        vTaskDelete(NULL);
-    }
-    #endif
     if(success_bit == ((1 << SSL_CLIENT_CRT) | (1 << SSL_CLIENT_KEY) | (1 << SSL_SERVER_CRT)))
     {
         #if (USER_TEST_ENABLE) //开机直连测试使用
@@ -252,21 +259,19 @@ static void Http_Download_Task_Cb(void *pvParameters)
         #endif
         #if (NIMBLE_NETWORK_MODE)
         //回复配网状态
-        #if ENABLE_CHECK_BLE_STATUS
-        
-        //请求服务器做绑定动作 在当前线程请求绑定接口
-        #else
-        // common_setting.net_pairing_info.http_url_flag=0;
-        // common_setting.net_pairing_info.http_token_flag = 0;
-        // common_setting.net_pairing_info.user_id_flag = 0;
+       
         network_request_replay(NETWORK_HTTPS_DOWNLOAD_CERTIFICATE_OK);
         vTaskDelay(200);
+        common_setting.net_pairing_info.http_url_flag=0;
+        common_setting.net_pairing_info.http_token_flag = 0;
+        common_setting.net_pairing_info.user_id_flag = 0;
         xEventGroupSetBits(ble_event_group, BLE_OFF_BIT);//关闭蓝牙配网
         vTaskDelay(100);
         ESP_LOGI(HTTP_TAG, "download mqtt \n");
-        common_setting.ble_status.nimble_flag=1;
+        common_setting.ble_status.nimble_flag=1; //配网成功
+        common_setting.mqtt_user_cfg.mqtt_start_flag=1; //开始连接mqtt
+        common_setting.ble_status.is_bind = 1; //开始绑定
         xEventGroupSetBits(common_event_group, COMMON_MQTT_CONNECT_BIT);
-        #endif
        
         #endif
        
@@ -274,17 +279,122 @@ static void Http_Download_Task_Cb(void *pvParameters)
         //失败
         network_request_replay(NETWORK_HTTPS_DOWNLOAD_CERTIFICATE_FAILED);
     }
-
     vTaskDelete(NULL);
     return;
 }
+//下载证书
+void Http_Download_Task(void){
+    xTaskCreate(Http_Download_Task_Cb, "http_download_task", HTTP_DOWNLOAD_CRT_TASK_STACK, NULL, 3, NULL);
+}
+
+/*
+
+func:获取绑定结果
+*/
+static uint8_t get_bind_flag = 0;
+void Http_Get_Bind_Result(void *pvParameters)
+{
+    if(get_bind_flag == 1)
+    {
+        return;
+    }
+    get_bind_flag=1;
+    esp_http_client_config_t http_config = 
+    {
+        .event_handler = _http_event_handler,
+        .disable_auto_redirect = true,
+        .keep_alive_enable = true,
+    };
+    int status_code = 0;
+    esp_http_client_handle_t http_client = NULL;
+    int result = 0;
+    ESP_LOGI(HTTP_TAG, "\nget bing");
+    static char url[255]={0};
+    for(uint8_t retry=0;retry<HTTP_RETRY_NUMBER_MAX;retry++)
+    {
+        result = 0;
+        http_client=NULL;
+        memset(url,0x00,sizeof(url));
+        uint8_t mac[6] = {0};
+        char str_mac[32] = {0};
+        esp_read_mac(mac, ESP_MAC_BT);//获取mac地址
+        sprintf(str_mac, "%02X-%02X-%02X-%02X-%02X-%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
 
+        snprintf(url, sizeof(url)-1, "%s%s?userId=%s&macAddress=%s",common_setting.net_pairing_info.http_url,"/iot/device/relateUserByMac", common_setting.net_pairing_info.user_id, str_mac);
+        http_config.url = url;
+        ESP_LOGI(HTTP_TAG, "http_config.url = %s", http_config.url);
+        
+        http_client = esp_http_client_init(&http_config);
+        if(http_client == NULL)
+        {
+            vTaskDelay(50);
+            continue;
+        }
+        esp_http_client_set_header(http_client, "Authorization", (const char*)common_setting.net_pairing_info.http_token);
+        esp_http_client_set_method(http_client, HTTP_METHOD_POST);
 
-#define HTTP_CONTENT_AMX_LEN  2048
+        esp_err_t err = esp_http_client_perform(http_client);
+        if (err == ESP_OK)
+        {
+            status_code = esp_http_client_get_status_code(http_client);
+            int read_len = esp_http_client_get_content_length(http_client);
+            if(status_code == 200)
+            {
+                result =  1;
+            }
+            else
+            {
+                result =  2;
+            }
+            ESP_LOGI(HTTP_TAG, "post bind %d", status_code, read_len);
+        }
+        else
+        {
+            result = 2;
+            ESP_LOGE(HTTP_TAG, "post bind err: %s", esp_err_to_name(err));
+        }
+        if(http_client != NULL)
+        {   
+            esp_http_client_close(http_client);
+            esp_http_client_cleanup(http_client);
+            http_client=NULL;
+        }
+        
+        // 结果
+        if(result == 1)
+        {
+            break;
+        }
+        vTaskDelay(50);
+    }
+    if(result != 1) //绑定结果失败了 重新配网
+    {
+       
+        //已经又通过恢复出厂开始广播配网了 
+        Esp32_Factory_Reset();
+    }
+    get_bind_flag=0;
+    vTaskDelete(NULL);
+    
+}
+//获取绑定结果
+void Http_Get_Bing_Result_Task(void){
+    ESP_LOGI(HTTP_TAG,"BIND TASK ER\n");
+    BaseType_t ret = xTaskCreate(Http_Get_Bind_Result, "http_get_bing_result_task", 2*1024, NULL, 2, NULL);
+    if(ret != pdPASS)
+    {
+        ESP_LOGI(HTTP_TAG,"BIND TASK ER\n");
+    }else{
+        ESP_LOGI(HTTP_TAG,"BIND TASK ok\n");
+    }
+}
+#define HTTP_CONTENT_MAX_LEN  2048
 #define USE_MALLOC_DATA_SIZE  0
 #define HTTP_CHUNK_SIZE     512
 
-
+/*
+func:请求下发serialNumber 上传设备信息
+*/
 static void Http_Get_Url_Task_Cb(void *pvParameters)
 {
     if(common_setting.net_pairing_info.http_url_flag == 0 || common_setting.net_pairing_info.http_token_flag == 0 || common_setting.net_pairing_info.user_id_flag == 0 || common_setting.mcu_info_got_flag == 0 || common_setting.net_pairing_info.http_url_length == 0 || common_setting.net_pairing_info.http_token_length == 0 || common_setting.net_pairing_info.http_url_length > HTTP_URL_MAX_LEN || common_setting.net_pairing_info.http_token_length > HTTP_TOKEN_MAX_LEN)
@@ -310,32 +420,21 @@ static void Http_Get_Url_Task_Cb(void *pvParameters)
     esp_http_client_handle_t http_client = NULL;
     int content_len = 0;
     int status_code=0;
-    #if (!USE_MALLOC_DATA_SIZE)
     int data_read=0;
-    #endif
     for(uint8_t retry=0;retry<HTTP_RETRY_NUMBER_MAX;retry++)
     {
         result = 0;
         
-        #if ENABLE_CHECK_BLE_STATUS
-        if(common_setting.net_pairing_info.http_url_flag == 0 || common_setting.net_pairing_info.http_token_flag == 0 || common_setting.ble_status.ble_state == 0)
-        #else
         if(common_setting.net_pairing_info.http_url_flag == 0 || common_setting.net_pairing_info.http_token_flag == 0)
-        #endif
         {
             result = 3;
             break;
         }
 
         char url[HTTP_REQUEST_RUL_LEN] = {0};//预留一个结束符\0 请求地址不能大于255
-        const char path[] = "/iot/device/getDeviceByPid/";
+        const char path[] = "/iot/device/getClientTimeByIp?pid=";// "/iot/device/getDeviceByPid/";//;//;
         memset(url, 0x00, sizeof(url));
         
-        // if(common_setting.net_pairing_info.http_url_length < (sizeof(url) - sizeof(path)-6)){
-        //     memcpy(url, common_setting.net_pairing_info.http_url, sizeof(url)-common_setting.net_pairing_info.http_url_length);
-        //     memcpy(&url[common_setting.net_pairing_info.http_url_length], path, strlen(path));
-        //     snprintf(&url[common_setting.net_pairing_info.http_url_length+strlen(path)], sizeof(url) - (common_setting.net_pairing_info.http_url_length+strlen(path)), "0x%04x", common_setting.mcu_info.pid);
-        // }
         
         // const char *path = "/iot/device/getDeviceByPid/";
         //注意http_url不能大于255-sizeof(path)-sizeof(common_setting_mcu_info.pid) //会编译出错
@@ -353,7 +452,7 @@ static void Http_Get_Url_Task_Cb(void *pvParameters)
             vTaskDelay(50);
             continue;
         }
-        ESP_LOGI(HTTP_TAG, "\nHTTP STEP 1..%s",(const char*)common_setting.net_pairing_info.http_token);
+        ESP_LOGI(HTTP_TAG, "\nHTTP STEP %s",(const char*)common_setting.net_pairing_info.http_token);
         esp_http_client_set_header(http_client, "Authorization", (const char*)common_setting.net_pairing_info.http_token);//设置header,key为Authorization,value为http_token
         esp_http_client_set_method(http_client, HTTP_METHOD_GET);//设置请求方法为GET
         // ESP_LOGI(HTTP_TAG, "%s esp_http_client_open...1.....%d %" PRIu32 " bytes",__func__,result,esp_get_free_heap_size());
@@ -375,7 +474,7 @@ static void Http_Get_Url_Task_Cb(void *pvParameters)
                 {
                     content_len = esp_http_client_get_content_length(http_client);
                     
-                    data_read = esp_http_client_read_response(http_client, http_download_cache, HTTP_CONTENT_AMX_LEN);
+                    data_read = esp_http_client_read_response(http_client, http_download_cache, HTTP_CONTENT_MAX_LEN);
                     //获取HTTP响应体的长度,返回值为响应体的字节数,如果返回值小于0表示获取响应体长度失败
                     ESP_LOGI(HTTP_TAG, "HTTP GET Status = %d, content_length = %d", status_code, content_len);
                     // ESP_LOG_BUFFER_CHAR(HTTP_TAG, http_download_cache, data_read);
@@ -392,10 +491,28 @@ static void Http_Get_Url_Task_Cb(void *pvParameters)
                             if(pData != NULL)
                             {
                             //  "serialNumber": "PXN1LJ1QUR078E"
+                                 
+                                cJSON* utc = cJSON_GetObjectItem(pData,"utc");
+                                cJSON* utcOffset = cJSON_GetObjectItem(pData,"utcOffset");
+                                cJSON* timestamp = cJSON_GetObjectItem(pData,"timestamp");
+                                if(utcOffset != NULL && cJSON_IsNumber(utcOffset) && timestamp != NULL && cJSON_IsString(timestamp))
+                                {
+                                    
+                                    int64_t utc_timestamp = strtoll(timestamp->valuestring, NULL, 10); //这个是已经加了时区的时间戳
+                                    int timezone = utcOffset->valueint;
+                                   
+                                     //服务器返回的timestamp已经是加了时区的时间戳了,如果直接用这个时间戳设置系统时间,系统时间就会比实际时间快一个时区的时间,所以需要把时区偏移去掉,得到真正的UTC时间戳,再设置系统时间
+                                    int64_t real_utc = utc_timestamp - (timezone * 3600);
+
+                                    set_system_time_int_from_utc(real_utc,timezone);
+
+                                }
+                               
                                 cJSON* pSerialNumber = cJSON_GetObjectItem(pData,"serialNumber");
                                 //get the value
                                 if(pSerialNumber != NULL && cJSON_IsString(pSerialNumber))
                                 {
+                                    // char *str_serialNumber = "PXN13BA1IJ7MB9";
                                     char* str_serialNumber = pSerialNumber->valuestring;
                                     ESP_LOGI(HTTP_TAG, "serialNumber: %s\n", str_serialNumber);
 
@@ -498,7 +615,6 @@ static void Http_Get_Url_Task_Cb(void *pvParameters)
         ESP_LOGI(HTTP_TAG, "\nH.GET serialNumber=deviceID..%d %" PRIu32 " bytes",result,esp_get_free_heap_size());
         network_request_replay(NETWORK_HTTPS_GET_SERIALNUMBER_FAILED);
         vTaskDelay(500);
-        User_Erase_NotReset();//清除配网信息
         vTaskDelete(NULL);
         return;
     }
@@ -522,11 +638,7 @@ static void Http_Get_Url_Task_Cb(void *pvParameters)
     {
         result = 0;
         
-        #if ENABLE_CHECK_BLE_STATUS
-        if(common_setting.net_pairing_info.http_url_flag == 0 || common_setting.net_pairing_info.http_token_flag == 0 || common_setting.ble_status.ble_state == 0)
-        #else
         if(common_setting.net_pairing_info.http_url_flag == 0 || common_setting.net_pairing_info.http_token_flag == 0 || common_setting.net_pairing_info.serial_number_flag == 0)
-        #endif
         {
             result = 3;
             break;
@@ -578,7 +690,7 @@ static void Http_Get_Url_Task_Cb(void *pvParameters)
             continue; 
         }
         // ESP_LOGI(HTTP_TAG, "put data:%s\n", post_data);
-        ESP_LOGI(HTTP_TAG, "http_config.url = %s", http_config.url);
+        ESP_LOGI(HTTP_TAG, "post_data = %s", post_data);
         
         http_client = esp_http_client_init(&http_config);
         if(http_client == NULL)
@@ -643,7 +755,6 @@ static void Http_Get_Url_Task_Cb(void *pvParameters)
         
         network_request_replay(NETWORK_HTTPS_PUT_DEVICE_INFO_FAILED);
         vTaskDelay(500);
-        User_Erase_NotReset();//清除配网信息
         vTaskDelete(NULL);
         return;
     }
@@ -656,20 +767,11 @@ static void Http_Get_Url_Task_Cb(void *pvParameters)
     {
         result = 0;
         http_client = NULL;
-        #if ENABLE_CHECK_BLE_STATUS
-        if(common_setting.net_pairing_info.http_url_flag == 0 || common_setting.net_pairing_info.http_token_flag == 0 || \
-            common_setting.net_pairing_info.serial_number_flag == 0 || common_setting.ble_status.ble_state == 0)
-        {
-            result = 3;
-            break;
-        }
-        #else
         if(common_setting.net_pairing_info.http_url_flag == 0 || common_setting.net_pairing_info.http_token_flag == 0 || common_setting.net_pairing_info.serial_number_flag == 0)
         {
             result = 3;
             break;
         }
-        #endif
         
         char url[HTTP_REQUEST_RUL_LEN] = {0};
         const char path[] = "/iot/device/getDeviceBySerialNumber/";
@@ -855,28 +957,19 @@ static void Http_Get_Url_Task_Cb(void *pvParameters)
     if(result != 1)
     {
         // 失败
-        ESP_LOGI(HTTP_TAG, "\n.GET MQTT CER......FAILED..%d %" PRIu32 " bytes",result,esp_get_free_heap_size());
+        ESP_LOGI(HTTP_TAG, "\n.GET CER FAILED..%d %" PRIu32 " bytes",result,esp_get_free_heap_size());
         // ESP_LOGI(HTTP_TAG, "HTTP_TAG1 memory head size: %" PRIu32 " bytes", esp_get_free_heap_size());
         //GET 配置配网服务器下发成功 下发证书 mqtt地址
         network_request_replay(NETWORK_HTTPS_GET_CER_URL_FAILED);
         vTaskDelay(500);
-        User_Erase_NotReset();//清除配网信息
         vTaskDelete(NULL);
         return;
     }
     #endif
-
-    #if ENABLE_CHECK_BLE_STATUS
-    if(common_setting.ble_status.ble_state == 0)
-    {
-        User_Erase_NotReset();//清除配网信息
-        vTaskDelete(NULL);
-    }
-    #endif
     if(pClientCrt != NULL && pClientkey != NULL && pServerCrt != NULL && pMqttSubUrl != NULL && result == 1)
     {
         result = 0;
-        ESP_LOGI(HTTP_TAG, "\nCER.....HTTP%d %" PRIu32 " bytes",result,esp_get_free_heap_size());
+        // ESP_LOGI(HTTP_TAG, "\nCER.....HTTP%d %" PRIu32 " bytes",result,esp_get_free_heap_size());
         xEventGroupSetBits(common_event_group, COMMON_HTTP_DOWNLOAD_BIT);
     }
     else
@@ -887,23 +980,45 @@ static void Http_Get_Url_Task_Cb(void *pvParameters)
     return;
 }
 
+//获取设备信息
 void Http_Get_Url_Task(void){
     xTaskCreate(Http_Get_Url_Task_Cb, "http_get_url_task", HTTP_GET_URL_TASK_STACK, NULL, 2, NULL);
 }
 
-void Http_Download_Task(void){
-    xTaskCreate(Http_Download_Task_Cb, "http_download_task", HTTP_DOWNLOAD_CRT_TASK_STACK, NULL, 2, NULL);
-}
+
+
+/*
+func:http请求状态检查
+*/
 void Http_Download_Status_Check(void)
 {
+    EventBits_t http_bits = xEventGroupWaitBits(common_event_group, COMMON_HTTP_DOWNLOAD_BIT | COMMON_HTTP_BIND_BIT |COMMON_HTTP_GET_URL_BIT, pdTRUE, pdFALSE, 0);
     // ESP_LOGI(HTTP_TAG, "[APP] Free memory http1 on: %" PRIu32 " bytes", esp_get_free_heap_size());
-    if((xEventGroupWaitBits(common_event_group, COMMON_HTTP_DOWNLOAD_BIT, pdFALSE, pdFALSE, 0) & COMMON_HTTP_DOWNLOAD_BIT) != 0)
+    if((http_bits & COMMON_HTTP_DOWNLOAD_BIT) != 0)
     {
         xEventGroupClearBits(common_event_group, COMMON_HTTP_DOWNLOAD_BIT);
         vTaskDelay(50 / portTICK_PERIOD_MS);
         Http_Download_Task();
         ESP_LOGI(HTTP_TAG, "http_download_task %" PRIu32 " bytes", esp_get_free_heap_size());
     }
+    else if((http_bits & COMMON_HTTP_GET_URL_BIT) != 0)
+    {
+        xEventGroupClearBits(common_event_group, COMMON_HTTP_GET_URL_BIT);
+        vTaskDelay(50 / portTICK_PERIOD_MS);
+        Http_Get_Url_Task();
+        
+    }
+
+    else if ((http_bits & COMMON_HTTP_BIND_BIT) != 0)
+    {
+        ESP_LOGI(HTTP_TAG, "http_bind %" PRIu32 " bytes", esp_get_free_heap_size());
+        xEventGroupClearBits(common_event_group, COMMON_HTTP_BIND_BIT);
+        
+        vTaskDelay(50 / portTICK_PERIOD_MS);
+        Http_Get_Bing_Result_Task();
+        
+    }
+
 }
 
 #endif
index 15218d9..296b1ca 100644 (file)
@@ -19,5 +19,6 @@ extern HTTP_GET_CERT_TASK_PARAM_T http_get_cert_task_param;;
 void Http_Download_Status_Check(void);
 void Http_Get_Url_Task(void);
 void Http_Download_Task(void);
+void Http_Get_Bing_Result_Task(void);
 #endif
 #endif
index 9ed16d3..d60e451 100644 (file)
@@ -3,9 +3,13 @@
 #include "user_flash.h"
 #include "cJSON.h"
 #include "esp_chip_info.h"
+#include "user_http.h"
+#include "project_common.h"
+#include "n455_ota.h"
 #if ENABLE_MQTT_FUNC
 static const char *MQTT_TAG = "MQTT";
-
+static esp_mqtt_client_config_t mqtt_cfg = {0};
+static esp_mqtt_client_handle_t mqtt_client_handle = NULL;
 #define REPLY_STATUS_OK 1
 #define REPLY_STATUS_FAIL 0
 // 发送队列静态内存
@@ -32,7 +36,7 @@ static uint8_t mqtt_init_flag = 0;
 static char topic_str[64] = {0};
 static char topic_compare[65]={0}; //最新的服务下发的topic 设备根据这个做topic区分数据上报
 static char cloud_msgID[64]="cloud_0196415f3b1f7e2ab7f72c4e8f91c0a2";  //应答需要用云端下发的msgID
-
+static uint8_t mqtt_check_connect = 0;
 static void log_error_if_nonzero(const char *message, int error_code)
 {
     if (error_code != 0) {
@@ -69,11 +73,17 @@ const char* get_publish_topic(TOPIC_TYPE type)
 
         default: return NULL;
     }
-
-    snprintf(pub_topic, sizeof(pub_topic)-1, "topic/%s/%04X%s",
+    #if PID_A00D
+    snprintf(pub_topic, sizeof(pub_topic)-1, "topic/%s/0x%04X%s",
+        (char *)common_storage.net_info.serial_number,
+        common_setting.mcu_info.pid,
+        suffix);
+    #else
+     snprintf(pub_topic, sizeof(pub_topic)-1, "topic/%s/%04X%s",
         (char *)common_storage.net_info.serial_number,
         common_setting.mcu_info.pid,
         suffix);
+    #endif
     return pub_topic;
 }
 
@@ -82,6 +92,7 @@ const char *property_set_replay="thing.service.property.set.reply";
 const char *property_post = "thing.event.property.post";
 const char *service_invoke = "thing.service.calibration.invoke";
 const char *dev_invoke_replay = "thing.service.calibration.invoke.reply";
+
 //获取方式请求mode
 const char *get_methon(uint8_t methon_mode)
 {
@@ -110,6 +121,9 @@ const char *get_methon(uint8_t methon_mode)
     }
 
 }
+/*
+func:mqtt回调函数
+*/
 #define MQTT_USER_DEFAULT_TOPIC     0
 static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
 {
@@ -119,6 +133,8 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
     int msg_id;
     switch ((esp_mqtt_event_id_t)event_id) {
     case MQTT_EVENT_CONNECTED:
+       
+        mqtt_check_connect=0;
         retry_connect_cnt = 0;
         mqtt_send_data_count=0;
         common_setting.mqtt_user_cfg.mqtt_sub_flag = 0;
@@ -136,15 +152,21 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
         
         
         msg_id = esp_mqtt_client_subscribe(mqtt_client,get_publish_topic(TOPIC_PROPERTY_POST), 0);
-
-
+        ESP_LOGI(MQTT_TAG, "send subscribe msg_id=%d common_setting.mqtt_user_cfg.mqtt_start_flag =%s", msg_id,get_publish_topic(TOPIC_PROPERTY_POST),common_setting.mqtt_user_cfg.mqtt_start_flag);
+        if(common_setting.ble_status.is_bind == 1) // 连接mqtt请求一次http绑定接口做绑定 绑定失败配网失败 绑定成功配网成功
+        {
+            common_setting.ble_status.is_bind = 0;
+            xEventGroupSetBits(common_event_group, (EventBits_t)COMMON_HTTP_BIND_BIT);
+        }
         #endif
-        ESP_LOGI(MQTT_TAG, "send subscribe msg_id=%d get_publish_topic(TOPIC_PROPERTY_POST)=%s", msg_id,get_publish_topic(TOPIC_PROPERTY_POST));
+        
         break;
     case MQTT_EVENT_DISCONNECTED:
         common_setting.mqtt_user_cfg.mqtt_connect_flag = 0;
         common_setting.mqtt_user_cfg.mqtt_sub_flag = 0;
-        Mqtt_Send_Connect_Status();
+       
+        
+        
         ESP_LOGI(MQTT_TAG, "MQTT_EVENT_DISCONNECTED");
         break;
 
@@ -173,12 +195,37 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
     case MQTT_EVENT_ERROR:
         ESP_LOGI(MQTT_TAG, "MQTT_EVENT_ERROR");
         if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
-            log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err);
-            log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err);
-            log_error_if_nonzero("captured as transport's socket errno",  event->error_handle->esp_transport_sock_errno);
-            ESP_LOGI(MQTT_TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
-
+            // log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err);
+            // log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err);
+            // log_error_if_nonzero("captured as transport's socket errno",  event->error_handle->esp_transport_sock_errno);
+            // ESP_LOGI(MQTT_TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
+            int esp_tls_err = event->error_handle->esp_tls_last_esp_err;
+            int tls_stack_err = event->error_handle->esp_tls_stack_err;
+            int sock_errno = event->error_handle->esp_transport_sock_errno;
+            int verify_flags = event->error_handle->esp_tls_cert_verify_flags;
+
+            ESP_LOGI(MQTT_TAG, "  esp-tls err: 0x%04X\n", esp_tls_err);
+            ESP_LOGI(MQTT_TAG, "  tls stack err: 0x%04X\n", tls_stack_err);
+            ESP_LOGI(MQTT_TAG, "  socket errno: %d\n", sock_errno);
+            ESP_LOGI(MQTT_TAG, "  verify_flags errno: %d\n", verify_flags);
+            if(tls_stack_err == 0x2180)
+            {
+                ESP_LOGE(MQTT_TAG, "证书格式非法\n");
+            }
+            if(tls_stack_err == 0x2700)
+            {
+                ESP_LOGE(MQTT_TAG, "证书合法 但不匹配服务器\n");
+            }
+            // ==============================================
+            // 是不是证书错误!!!
+            // ==============================================
+            if (event->error_handle->esp_tls_cert_verify_flags != 0)     // SSL - 证书不匹配
+            {
+                ESP_LOGE(MQTT_TAG, "verify_flags errno\n");
+            }
         }
+        //没意义 有链接才有断开的操作 这个不成立的
+        
         break;
     
     case MQTT_EVENT_BEFORE_CONNECT:
@@ -191,6 +238,37 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
         break;
     }
 }
+//检查mqtt是否连接成功
+void mqtt_check_isconnect(void)
+{
+    #if ENABLE_HTTPS_OTA_FUNC
+    if(Https_Get_Ota_Status())
+    {
+        mqtt_check_connect=0;
+        return;
+    }
+    #endif
+    // if(common_setting.mqtt_user_cfg.mqtt_start_flag == 1 && common_setting.wifi_status.wifi_state == 1) //首次连接mqtt
+    // {
+    //     if(mqtt_check_connect <= 60) //连续五次连不上就不连 重新配网
+    //     { 
+    //         if(mqtt_check_connect == 60)
+    //         {
+    //             common_setting.mqtt_user_cfg.mqtt_start_flag = 0;
+    //             //断开mqtt连接
+    //             //清除配网信息重新开蓝牙
+    //             xEventGroupSetBits(common_event_group, COMMON_MQTT_INIT_BIT);//初始化失败了 或者连不成功
+
+    //         }
+    //         mqtt_check_connect+=1;
+    //     }
+    // }else{
+    //     mqtt_check_connect=0;
+    // }
+}
+/*
+func:mqtt连接状态发给mcu
+*/
 void Mqtt_Send_Connect_Status(void)//包含心跳
 {
     uint8_t heart_beat_data[2] = {0};//数据
@@ -200,9 +278,14 @@ void Mqtt_Send_Connect_Status(void)//包含心跳
     Uart_Reply_Send(COMMON_UART_HEART_CMD, heart_beat_data, sizeof(heart_beat_data), HOST_TYPE_UART);//(cmd, pbuf, len, host_type);
 }
 
+/*
+func:mqtt初始化
 
+*/
 static esp_err_t Mqtt_App_Init(void)
 {
+    
+    memset(&publish_data,0x00,sizeof(publish_data));
     esp_err_t err = ESP_FAIL;
     if(common_setting.wifi_status.wifi_state != 1 || common_setting.ble_status.nimble_flag == 0)
     {
@@ -219,53 +302,55 @@ static esp_err_t Mqtt_App_Init(void)
         ESP_LOGI(MQTT_TAG, "mqtt url error");
         return ESP_FAIL;
     }
-    
-    if(common_storage.net_info.mqtt_url_len==0 && common_setting.mcu_info.pid == 0x0000)
-    {
-        ESP_LOGI(MQTT_TAG, "mqtt_sub_url == 0");
-        return ESP_FAIL;
-    }
     if(mqtt_init_flag)
     {
         //
         ESP_LOGI(MQTT_TAG, "Mqtt initialized.\n");
         return ESP_OK;
     }
-    memset(&common_setting.mqtt_cfg, 0, sizeof(common_setting.mqtt_cfg));
+    mqtt_client_handle=NULL;
+    memset(&mqtt_cfg, 0, sizeof(mqtt_cfg));
     retry_connect_cnt = 0;
     // common_setting.mqtt_cfg.session.keepalive = 60;
-    common_setting.mqtt_cfg.network.disable_auto_reconnect = false;
+    mqtt_cfg.network.disable_auto_reconnect = false;
     // common_setting.mqtt_cfg.broker.address.transport = MQTT_TRANSPORT_OVER_TCP;
     // common_setting.mqtt_cfg.buffer.out_size = 2048;
     // common_setting.mqtt_cfg.buffer.size = 2048;
     
     ESP_LOGI(MQTT_TAG, "URI: %s %s", common_storage.net_info.mqtt_sub_url,common_setting.net_pairing_info.mqtt_sub_url);
-    common_setting.mqtt_cfg.broker.address.uri = (const char *)common_storage.net_info.mqtt_sub_url;
+    mqtt_cfg.broker.address.uri = (const char *)common_storage.net_info.mqtt_sub_url;
+    
     
-    common_setting.mqtt_cfg.broker.verification.certificate = (const char *)common_storage.ssl_cert[SSL_SERVER_CRT].content;
-    common_setting.mqtt_cfg.credentials.authentication.certificate = (const char *)common_storage.ssl_cert[SSL_CLIENT_CRT].content;
-    common_setting.mqtt_cfg.credentials.authentication.key = (const char *)common_storage.ssl_cert[SSL_CLIENT_KEY].content;
+
+    
+
+    mqtt_cfg.broker.verification.certificate =(const char *)common_storage.ssl_cert[SSL_SERVER_CRT].content;
+    mqtt_cfg.credentials.authentication.certificate = (const char *)common_storage.ssl_cert[SSL_CLIENT_CRT].content;
+    mqtt_cfg.credentials.authentication.key = (const char *)common_storage.ssl_cert[SSL_CLIENT_KEY].content;
     char pid_str[10]={0};
+    #if PID_A00D
+    sprintf(pid_str,"0x%04X",common_setting.mcu_info.pid);
+    #else
     sprintf(pid_str,"%04X",common_setting.mcu_info.pid);
+    #endif
     #if MQTT_USER_DEFAULT_TOPIC
     common_setting.mqtt_cfg.credentials.client_id = "basicPubSub";
     #else
-    common_setting.mqtt_cfg.credentials.client_id = (const char *)pid_str;
+    mqtt_cfg.credentials.client_id = (const char *)pid_str;
     #endif
     ESP_LOGI(MQTT_TAG, "Mqtt init %s",pid_str);
-    common_setting.mqtt_cfg.task.priority = 2;
-    common_setting.mqtt_client_handle = esp_mqtt_client_init(&common_setting.mqtt_cfg);
-    if(common_setting.mqtt_client_handle == NULL){
+    mqtt_client_handle = esp_mqtt_client_init(&mqtt_cfg);
+    if(mqtt_client_handle == NULL){
         ESP_LOGI(MQTT_TAG, "client_handle null\n");
         err = ESP_FAIL;
         return err;
     }
     ESP_LOGI(MQTT_TAG, "Mqtt init");
     /* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
-    err = esp_mqtt_client_register_event(common_setting.mqtt_client_handle, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
+    err = esp_mqtt_client_register_event(mqtt_client_handle, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
     if(err == ESP_OK)
     {
-        err = esp_mqtt_client_start(common_setting.mqtt_client_handle);
+        err = esp_mqtt_client_start(mqtt_client_handle);
         if(err == ESP_OK)
         {
             mqtt_init_flag=1;
@@ -274,9 +359,14 @@ static esp_err_t Mqtt_App_Init(void)
     }
     return err;
 }
+/*
+func:获取mqtt的连接状态 
+0:失败 
+1:成功
+*/
 uint8_t Mqtt_Get_Connect_Flag(void)
 {
-    if(common_setting.mqtt_client_handle != NULL &&common_setting.mqtt_user_cfg.mqtt_connect_flag == 1 && \
+    if(mqtt_client_handle != NULL &&common_setting.mqtt_user_cfg.mqtt_connect_flag == 1 && \
         common_setting.mqtt_user_cfg.mqtt_sub_flag == 1 && \
         common_setting.ble_status.ble_state == 0 && common_setting.wifi_status.wifi_state == 1)
     {
@@ -386,6 +476,10 @@ void Mqtt_Send_Mcu_Info(void)
     return;
 }
 void mqtt_get_dev_test(uint16_t *dpid,uint8_t num);
+/*
+mcu信息
+
+*/
 void Mqtt_Send_Data(void)
 {
     // return;
@@ -403,9 +497,9 @@ void Mqtt_Send_Data(void)
     }
     if(mqtt_send_data_count % 7 == 0)
     {
-        uint16_t test_dpid[25]={335,336,336,337,338,339,340,341,400,401,745,746,747,271,272,273,274,275,745,746,275,276,277,278,279};
+        // uint16_t test_dpid[25]={335,336,336,337,338,339,340,341,400,401,745,746,747,271,272,273,274,275,745,746,275,276,277,278,279};
     
-        mqtt_get_dev_test(test_dpid,25);
+        // mqtt_get_dev_test(test_dpid,25);
         // mqtt_parse_recv_data(NULL,0);
     }
     else if(mqtt_send_data_count % 15 == 0)
@@ -417,7 +511,9 @@ void Mqtt_Send_Data(void)
 
     mqtt_send_data_count++;
 }
-// 接收mqtt发过来的数据
+/*
+原始数据传给队列
+*/
 void Mqtt_Recv_Data(char *topic, int topic_len, char *data, int data_len)
 {
     // 1. 长度判断
@@ -440,27 +536,49 @@ void Mqtt_Recv_Data(char *topic, int topic_len, char *data, int data_len)
     msg.data_len = data_len;
     if(mqtt_recv_queue_handle){
         if (xQueueSend(mqtt_recv_queue_handle, &msg, 0) != pdPASS) {
-            ESP_LOGW(MQTT_TAG, "QUEUE is full\n");
+            ESP_LOGW(MQTT_TAG, "mcuerr\n");
         }
     }else{
-        ESP_LOGI(MQTT_TAG,"QUEUE is NULL");
+        ESP_LOGI(MQTT_TAG,"mcusok");
     }
 }
+
+/*
+func:mqtt各个状态检查
+
+*/
 void Mqtt_Connect_Status_Check(void)
 {
+    static uint8_t mqtt_init = 0;
     if((xEventGroupWaitBits(common_event_group, COMMON_MQTT_CONNECT_BIT, pdFALSE, pdFALSE, 0) & COMMON_MQTT_CONNECT_BIT) != 0 && common_setting.ble_status.ble_state == 0\
-    && common_setting.wifi_status.wifi_state == 1 && common_setting.https_ota_cfg.https_ota_start_flag == 0)
+    &&(Https_Get_Ota_Status() == OTA_STATUS_IDLE 
+    #if ENABLE_HTTP_N455_OTA_FUNC
+    || N455_Get_Ota_Status() == N455_OTA_STATUS_IDLE))
+    #else
+    ))
+    #endif
     {
         xEventGroupClearBits(common_event_group, COMMON_MQTT_CONNECT_BIT);
         vTaskDelay(50 / portTICK_PERIOD_MS);
-        if(Mqtt_App_Init() == ESP_OK)
-        {
-            ESP_LOGI(MQTT_TAG, "Mqtt_Init_Task");
-            Mqtt_Init_Task();
-        }
-        else
+        if(common_setting.wifi_status.wifi_state == 1)
         {
-            ESP_LOGI(MQTT_TAG, "Mqtt init fail");
+            int ret = Mqtt_App_Init();
+            if(ret == ESP_OK)
+            {
+                common_setting.mqtt_user_cfg.mqtt_start_flag=0;
+                mqtt_init = 0;
+                ESP_LOGI(MQTT_TAG, "Mqtt_Init_Task");
+                Mqtt_Init_Task();
+            }
+            else
+            {
+                if(mqtt_init <= 5) //连续多次初始化都失败就不初始化了
+                {
+                    xEventGroupSetBits(common_event_group, COMMON_MQTT_CONNECT_BIT);
+                    mqtt_init+=1;
+                }
+                ESP_LOGI(MQTT_TAG, "Mqtt init fail");
+            }
         }
     }
 
@@ -469,8 +587,8 @@ void Mqtt_Connect_Status_Check(void)
         xEventGroupClearBits(common_event_group, COMMON_MQTT_DISCONNECT_BIT);
         vTaskDelay(50 / portTICK_PERIOD_MS);
         
-        if(mqtt_init_flag == 1 && common_setting.mqtt_client_handle != NULL){
-            if(esp_mqtt_client_stop(common_setting.mqtt_client_handle) == ESP_OK)
+        if(mqtt_init_flag == 1 && mqtt_client_handle != NULL){
+            if(esp_mqtt_client_stop(mqtt_client_handle) == ESP_OK)
             {
                 
                 ESP_LOGI(MQTT_TAG, "Mqtt stop OK");
@@ -480,36 +598,55 @@ void Mqtt_Connect_Status_Check(void)
                 ESP_LOGI(MQTT_TAG, "Mqtt stop fail");
             }
             vTaskDelay(50 / portTICK_PERIOD_MS);
-            esp_mqtt_client_destroy(common_setting.mqtt_client_handle);
-            common_setting.mqtt_client_handle=NULL;
+            esp_mqtt_client_destroy(mqtt_client_handle);
+            mqtt_client_handle=NULL;
             retry_connect_cnt = 0;
             mqtt_init_flag=0;
             common_setting.mqtt_user_cfg.mqtt_connect_flag = 0;
             common_setting.mqtt_user_cfg.mqtt_sub_flag = 0;
         }
     }
+
+    //mqtt一直连接不上
+    if((xEventGroupWaitBits(common_event_group, COMMON_MQTT_INIT_BIT, pdFALSE, pdFALSE, 0) & COMMON_MQTT_INIT_BIT) != 0 )
+    {
+        xEventGroupClearBits(common_event_group, COMMON_MQTT_INIT_BIT);
+        vTaskDelay(50 / portTICK_PERIOD_MS);
+        
+        //断开wifi
+        Wifi_Stop();
+        //断开mqtt释放资源
+        Mqtt_Disconnect();
+        vTaskDelay(50 / portTICK_PERIOD_MS);
+        User_Erase_NotReset();
+        xEventGroupSetBits(ble_event_group, BLE_ON_BIT);
+        //http请求绑定结果
+        // 
+    }
     
 }
-//断开wifi连接同时断开mqtt连接 释放mqtt资源
+/*
+func:断开mqtt连接 释放mqtt资源
+*/
 void Mqtt_Disconnect(void)
 {
     if(mqtt_init_flag != 1)
     {
         return;
     }
-    if(common_setting.mqtt_client_handle == NULL)
+    if(mqtt_client_handle == NULL)
     {
         mqtt_init_flag = 0;
         return;
     }
     mqtt_init_flag = 0;
-    esp_mqtt_client_stop(common_setting.mqtt_client_handle);
+    esp_mqtt_client_stop(mqtt_client_handle);
     //
     vTaskDelay(pdMS_TO_TICKS(100));
     //反注册事件+销毁客户端
-    esp_mqtt_client_unregister_event(common_setting.mqtt_client_handle, ESP_EVENT_ANY_ID, mqtt_event_handler);
+    esp_mqtt_client_unregister_event(mqtt_client_handle, ESP_EVENT_ANY_ID, mqtt_event_handler);
     //释放资源
-    esp_mqtt_client_destroy(common_setting.mqtt_client_handle);
+    esp_mqtt_client_destroy(mqtt_client_handle);
     
     // 2. 删掉 MQTT 任务
     if (mqtt_connect_task_handler != NULL) {
@@ -526,16 +663,17 @@ void Mqtt_Disconnect(void)
         vQueueDelete(mqtt_recv_queue_handle);
         mqtt_recv_queue_handle = NULL;
     }
-    common_setting.mqtt_client_handle = NULL;
+    mqtt_init_task_flag=0;
+    mqtt_client_handle = NULL;
     retry_connect_cnt = 0;
     common_setting.mqtt_user_cfg.mqtt_connect_flag = 0;
     common_setting.mqtt_user_cfg.mqtt_sub_flag = 0;
     mqtt_init_flag = 0;
+    memset(&publish_data, 0, sizeof(publish_data));
     ESP_LOGW(MQTT_TAG, "MQTT STOP");
 }
-// 解析 MQTT 下发的 JSON 数据
-// 是否是纯数字
-#define UART_REPLY_MAX_PAYLOAD_MQTT     UART_REPLY_MAX_PAYLOAD-4
+
+// 是否是纯数字 如key value 特殊情况
 bool is_pure_number(const char *str) 
 {
     // 
@@ -553,40 +691,7 @@ bool is_pure_number(const char *str)
     return true;
 }
 
-// 云端 version 转 16 进制版本号(例如 1.03 → 0x0103)
-uint16_t version_str_to_hex(char *version)
-{
-    if(version ==  NULL)
-    {
-        return 0xffff;
-    }
-    if(strlen(version)==0)
-    {
-        ESP_LOGI(MQTT_TAG,"len err%s\n", version);   // 1
-        return 0xffff;
-    }
-    //
-    // // "1.03" → 1
-    char *dot = strchr(version, '.'); 
-    if(dot == NULL) //没有找到.号 不合法
-    {
-        ESP_LOGI(MQTT_TAG,"不合法%s\n", version);   // 1
-        return 0xffff;
-    }
-    int major = atoi(version);       // 转成数字 10.09 = 10 20.1 =20-
-
-
-    // --------------------
-    // 取小数点后面:03
-    // --------------------
-    int minor = atoi(dot + 1);         // dot+1 指向 "03" → 转成 3
-    // 输出结果
-    ESP_LOGI(MQTT_TAG,"主版本:%d\n", major);   // 1
-    ESP_LOGI(MQTT_TAG,"次版本:%d\n", minor);   // 3
-    ESP_LOGI(MQTT_TAG,"总版本:%04x\n", (major << 8) | minor);
-    // 合成 0x0103
-    return (major << 8) | minor;
-}
+
 
 
 char *set_test_json(void)
@@ -598,8 +703,8 @@ char *set_test_json(void)
 
     // ================== 生成时间戳 ==================
     time_t Time_Sec = Get_Time_Stamp();
-    static char time_str[16] = {0};
-    snprintf(time_str, sizeof(time_str)-1, "%lld", Time_Sec);
+    static char time_str[24] = {0};
+    int64_to_str((int64_t)Time_Sec,time_str,sizeof(time_str)-1);
 
     // ================== 1. 创建 data 对象 ==================
     cJSON *data = cJSON_CreateObject();
@@ -720,8 +825,8 @@ char *get_test_json(void)
 
     // ================== 生成时间戳 ==================
     time_t Time_Sec = Get_Time_Stamp();
-    static char time_str[16] = {0};
-    snprintf(time_str, sizeof(time_str)-1, "%lld", Time_Sec);
+    static char time_str[24] = {0};
+    int64_to_str(Time_Sec,time_str,sizeof(time_str)-1);
 
     // ================== 1. 创建 data 对象 ==================
     cJSON *data = cJSON_CreateObject();
@@ -830,8 +935,12 @@ char *get_test_json(void)
     cJSON_Delete(root);
     return out;
 }
-
-void mqtt_parse_recv_data(char *buf, int data_len)
+/*
+func:解析mqtt服务下发的原始数据
+data:数据
+data_len:数据长度
+*/
+void mqtt_parse_recv_data(char *data, int data_len)
 {
     
     // // 安全判断
@@ -839,33 +948,22 @@ void mqtt_parse_recv_data(char *buf, int data_len)
     //     ESP_LOGW(MQTT_TAG, "parese too len:%d\n",data_len);
     //     return;
     // }
-    
-    if(buf == NULL)return;
+    if(data == NULL)return;
     // ========== cJSON 解析(安全版)==========
-    cJSON *root = cJSON_Parse(buf);
+    cJSON *root = cJSON_Parse(data);
     if (root == NULL) {
         ESP_LOGW(MQTT_TAG, "JSON error");
 
         return;
     }
-
-    cJSON *payload_root  = cJSON_GetObjectItem(root, "data");//
-    if (payload_root  == NULL && !cJSON_IsObject(payload_root )) {
-        
-        cJSON_Delete(root);
-        return;
-    }
-
     //请求方式
     
-    // 示例 1:解析字符串类型
     //===========清除配网指令=========================//
-    cJSON *reset = cJSON_GetObjectItem(payload_root , "otareset");//清除配网标识字符串 int
+    cJSON *reset = cJSON_GetObjectItem(root , "otareset");//清除配网标识字符串 int
     if (reset != NULL && cJSON_IsNumber(reset)) {
         ESP_LOGI(MQTT_TAG, "otareset: %d", reset->valueint);
         if(reset->valueint)
         {
-            //1.清除flash
             //2.重启设备
             User_Erase_Nimble_NetWork_Infor();
             vTaskDelay(pdMS_TO_TICKS(100));
@@ -874,11 +972,42 @@ void mqtt_parse_recv_data(char *buf, int data_len)
                 cJSON_Delete(root);
                 root=NULL;
             }
-           
             esp_restart();//重启模组
             return;
         }
     }
+    if (1) {
+        //OTA升级
+        cJSON *filePath = cJSON_GetObjectItem(root , "filePath");
+        if (filePath != NULL && cJSON_IsString(filePath) && filePath->valuestring != NULL) {
+            cJSON *version = cJSON_GetObjectItem(root , "version");
+            if ((version != NULL && cJSON_IsString(version) && version->valuestring != NULL) ) 
+            {
+                Https_Ota_Version_Check(version->valuestring, filePath->valuestring);
+                if(root != NULL)
+                {
+                    cJSON_Delete(root);
+                    root=NULL;
+                }
+                return;
+                
+            }else{
+            }
+            
+            
+
+        }
+    }
+
+    
+    cJSON *payload_root  = cJSON_GetObjectItem(root, "data");//
+    if (payload_root  == NULL && !cJSON_IsObject(payload_root )) {
+        
+        cJSON_Delete(root);
+        return;
+    }
+
+    
 
     // 示例 2:
     //ota
@@ -905,82 +1034,7 @@ void mqtt_parse_recv_data(char *buf, int data_len)
     //     }
     // }
     // cJSON *payload = cJSON_GetObjectItem(root, "payload");//
-    if (1) {
-        //OTA升级
-        cJSON *filePath = cJSON_GetObjectItem(payload_root , "filePath");
-        if (filePath != NULL && cJSON_IsString(filePath) && filePath->valuestring != NULL) {
-            cJSON *version = cJSON_GetObjectItem(payload_root , "version");
-            if ((version != NULL && cJSON_IsString(version) && version->valuestring != NULL) ) 
-            {
-                // version->valuestring = "10.165";
-                // const char* version = "10.165";
-                uint16_t new_version = version_str_to_hex(version->valuestring);
-                // 核心:把 0x0A15 转成浮点数 10.21
-                ESP_LOGI(MQTT_TAG, "ver: %s %04x FW_VERSION:%04x", version->valuestring,new_version,FW_VERSION);
-                if(new_version != FW_VERSION && new_version != 0xffff)
-                {
-                    //开启ota线程
-                    #if ENABLE_HTTPS_OTA_FUNC
-                    // const char *ota_url = filePath->valuestring;
-                    // static const char *filePath="https://pxn-iot.s3.us-east-2.amazonaws.com/iot01/2026/04/27/69ef076479113dba3ec8e375.bin";//https://pxn-iot.s3.us-east-2.amazonaws.com/iot01/2026/04/20/69e589eb7a67c1057c3d452e.bin";
-                    uint8_t url_len = strlen(filePath->valuestring);
-                    if (url_len > 0 && url_len < sizeof(https_ota_url)-1) {
-                        strncpy(https_ota_url, filePath->valuestring, url_len);
-                        https_ota_url[url_len] = '\0';
-                        ESP_LOGI(MQTT_TAG, "OTA URL: %s", https_ota_url);
-                        cJSON_Delete(root);
-                        root=NULL;
-                        
-                        Https_Ota_Start();
-                        return;
-                    }
-                    // uint8_t filePath_Len = strlen(ota_url);
-                    // if(filePath_Len > sizeof(https_ota_url)-1)
-                    // {   
-                    //     filePath_Len = sizeof(https_ota_url)-1;
-                    // }
-                    
-                    // memcpy(https_ota_url,ota_url,filePath_Len);
-                    // https_ota_url[filePath_Len] = '\0';
-                    // ESP_LOGI(MQTT_TAG, "ota_url:%s", https_ota_url);
-                    // cJSON_Delete(root);
-                    // root=NULL;
-                    // Https_Ota_Start();
-                    return;
-                    #endif
-                }else{
-
-
-                }
-                
-            }else{
-                #if 0
-                const char *ota_url = filePath->valuestring;
-                // static const char *filePath="https://pxn-iot.s3.us-east-2.amazonaws.com/iot01/2026/04/27/69ef076479113dba3ec8e375.bin";//https://pxn-iot.s3.us-east-2.amazonaws.com/iot01/2026/04/20/69e589eb7a67c1057c3d452e.bin";
-                uint8_t filePath_Len = strlen(ota_url);
-                if(filePath_Len > sizeof(https_ota_url)-1)
-                {   
-                    filePath_Len = sizeof(https_ota_url)-1;
-                }
-                
-                memcpy(https_ota_url,ota_url,filePath_Len);
-                https_ota_url[filePath_Len] = '\0';
-                ESP_LOGI(MQTT_TAG, "ota_url:%s", https_ota_url);
-                if(root != NULL)
-                {
-                    cJSON_Delete(root);
-                    root=NULL;
-                }
-                Https_Ota_Start();
-                return;
-                #endif
-            }
-            
-            
-
-        }
-    }
-
+   
     //
     //灯光
     //{"productId":"A00B","productName":"WGTL方向盘","prot":[{"736":"50"},{"737":"89"},{"738":"90"}]}
@@ -1100,6 +1154,22 @@ void mqtt_parse_recv_data(char *buf, int data_len)
                     return;
                 }
                 // mqtt_get_dev_property(params);
+                // {
+                //     "msgId": "cloud_0196415f3b1f7e2ab7f72c4e8f91c0a1",
+                //     "method": "thing.service.property.set.reply",
+                //     "time": 1777517821,
+                //     "serialNumber": "PXN1LJ1QUR078E",
+                //     "productId": "A00B",
+                //     "code": 0,
+                //     "message": "ok",
+                    
+                // }
+                cJSON *replay_root = create_publish_ack_json(publish_data.msgid,NULL,get_methon(METHON_SERVICE_PROPERTY_SET_REPLAY));
+                if(replay_root)
+                {
+                    cJSON_Delete(replay_root);
+                    replay_root = NULL;
+                }
                 mqtt_set_dev_property(params);
             }
         }
@@ -1116,6 +1186,7 @@ void mqtt_parse_recv_data(char *buf, int data_len)
     //         "timeoutSec": 30
     //     }
     // }
+
     //"thing.service.calibration.invoke", //服务下发 设备应答
     else if(strcmp(get_publish_topic(TOPIC_SERVICE_POST),topic->valuestring) == 0)
     {
@@ -1170,7 +1241,10 @@ void mqtt_parse_recv_data(char *buf, int data_len)
     
 }
 
-//云端下发设置设备属性值
+/*
+func:云端下发设置设备属性值
+array:数组 [{"key":value},{"key":value},{"key":value}.............]
+*/
 void mqtt_set_dev_property(const cJSON *array)
 {
 
@@ -1307,6 +1381,11 @@ void mqtt_set_dev_property(const cJSON *array)
         ESP_LOGI(MQTT_TAG,"send end\n");
     }
 }
+
+
+/*云端下发获取设备属性值
+array:数组 ["key","key","key",.............]
+*/
 void mqtt_get_dev_property(const cJSON *array)
 {
 
@@ -1371,7 +1450,7 @@ void mqtt_get_dev_property(const cJSON *array)
 }
 
 
-//云端获取设备属性上报
+//测试函数
 // data 是一个数组 ["dpid1","dpid2","dpid3"...........]
 void mqtt_get_dev_test(uint16_t *dpid,uint8_t num)
 {
@@ -1412,7 +1491,11 @@ void mqtt_get_dev_test(uint16_t *dpid,uint8_t num)
 }
 
 
-// 发送一帧完整JSON 带topic root需要发送的json对象 内部转成josn字符串立即发送
+/*
+func:统一发送mqtt数据函数
+topic_type:是哪个topic
+root:需要发送的json对象
+*/
 uint8_t mqtt_send_publish_json(TOPIC_TYPE topic_type,cJSON *root)
 {
     if (!Mqtt_Get_Connect_Flag() || root == NULL) return 0;
@@ -1448,7 +1531,9 @@ uint8_t mqtt_send_publish_json(TOPIC_TYPE topic_type,cJSON *root)
     
 }
     
-//获取json大小
+/*
+func:获取实际的json大小
+*/
 static uint32_t get_json_size(cJSON *root)
 {
     if (!root) return 0;
@@ -1464,9 +1549,12 @@ static uint32_t get_json_size(cJSON *root)
 
 
 
-//设备应答云端公共函数
-// service_id: 传入服务ID 如 "calibration"
-// method: 传入方法名 如 "thing.service.calibration.invoke.reply"
+/*
+func:设备应答云端公共函数
+msgId:需要区分是cloud_msg 还是dev_msgid 
+service_id: 传入服务ID 如 "calibration"
+method: 传入方法名 如 "thing.service.calibration.invoke.reply"
+*/
 cJSON* create_publish_ack_json(const char* msgId,const char* service_id, const char* method)
 {
     cJSON *root = cJSON_CreateObject();
@@ -1480,9 +1568,9 @@ cJSON* create_publish_ack_json(const char* msgId,const char* service_id, const c
     snprintf(pid_str, sizeof(pid_str)-1, "%04X", common_setting.mcu_info.pid);
 
     // 
-    time_t Time_Sec=Get_Time_Stamp();
-    static char time_str[16]={0};
-    snprintf(time_str,sizeof(time_str)-1,"%lld",Time_Sec);
+    time_t Time_Sec = Get_Time_Stamp();
+    static char time_str[24] = {0};
+    int64_to_str((int64_t)Time_Sec,time_str,sizeof(time_str)-1);
 
     cJSON_AddStringToObject(root, "msgId", msgId);
     cJSON_AddStringToObject(root, "method", method);
@@ -1504,7 +1592,9 @@ cJSON* create_publish_ack_json(const char* msgId,const char* service_id, const c
     cJSON_AddStringToObject(root, "message", "ok");
     return root;
 }
-//不带code message 的回复
+/*
+func:不带code message 的回复 有些需要code 有些不要
+*/
 cJSON* create_publish_post_json(const char* msgId,const char* service_id, const char* method)
 {
     cJSON *root = cJSON_CreateObject();
@@ -1523,9 +1613,9 @@ cJSON* create_publish_post_json(const char* msgId,const char* service_id, const
     snprintf(pid_str, sizeof(pid_str)-1, "%04X", common_setting.mcu_info.pid);
 
     // 
-    time_t Time_Sec=Get_Time_Stamp();
-    static char time_str[16]={0};
-    snprintf(time_str,sizeof(time_str)-1,"%lld",Time_Sec);
+    time_t Time_Sec = Get_Time_Stamp();
+    static char time_str[24] = {0};
+    int64_to_str((int64_t)Time_Sec,time_str,sizeof(time_str)-1);
 
     cJSON_AddStringToObject(root, "msgId", msgId);
     cJSON_AddStringToObject(root, "method", method);
@@ -1544,7 +1634,9 @@ cJSON* create_publish_post_json(const char* msgId,const char* service_id, const
     return root;
 }
 
-//pid serialcNumber 不一致应答
+/*
+pid serialcNumber和本地不一致 应答服务器
+*/
 cJSON* pid_serialNumber_replay_json(const char* msgId,const char* service_id, const char* method,uint16_t code)
 {
     cJSON *root = cJSON_CreateObject();
@@ -1564,9 +1656,10 @@ cJSON* pid_serialNumber_replay_json(const char* msgId,const char* service_id, co
     snprintf(pid_str, sizeof(pid_str)-1, "%04X", common_setting.mcu_info.pid);
 
     // 
-    time_t Time_Sec=Get_Time_Stamp();
-    static char time_str[16]={0};
-    snprintf(time_str,sizeof(time_str)-1,"%lld",Time_Sec);
+    time_t Time_Sec = Get_Time_Stamp();
+    static char time_str[24] = {0};
+    int64_to_str((int64_t)Time_Sec,time_str,sizeof(time_str)-1);
+
     cJSON_AddStringToObject(root, "msgId", msgId);
     cJSON_AddStringToObject(root, "method", method);
     cJSON_AddStringToObject(root, "time", time_str);
@@ -1590,12 +1683,10 @@ typedef enum{
     MODE_REPORT, //主动上报
 
 }ACK_POST;
-//设备属性主动上报 收到0x09之后串口返回的数据通过0x07接收到 发给mqtt服务器
-//cmd 预留
-//data 真实数据 
-//len 数据实际大小
-//格式 dpid type len 数据 type可以不解析预留
-//格式 dpid(2) type(1) len(2) data type==5是字符串需要换成字符串发送给mqtt
+
+/*
+func:设备生成MSGID规则 dev_设备MAC后四位_时间戳
+*/
 char *get_devMsgId(void)
 {
     static char msgId[64]={0};
@@ -1603,12 +1694,20 @@ char *get_devMsgId(void)
     esp_read_mac(mac, ESP_MAC_BT);//获取mac地址
     snprintf(&msgId[0], sizeof(msgId)-1,"dev_");
     uint8_t dev_str_len = strlen("dev_");
-    snprintf(&msgId[4], (sizeof(msgId)-1)-dev_str_len,"%02X%02X-", mac[4], mac[5]);
+    snprintf(&msgId[4], (sizeof(msgId)-1)-dev_str_len,"%02X%02X_", mac[4], mac[5]);
     time_t Time_Sec = Get_Time_Stamp();
-    snprintf(&msgId[9],(sizeof(msgId)-1)-dev_str_len-4,"%lld",Time_Sec);
+    int64_to_str((int64_t)Time_Sec,&msgId[9],sizeof(msgId)-10);
+    
     return msgId;
 }
-uint8_t dev_report_property(uint8_t cmd,uint8_t *data,uint8_t len)
+
+/*
+设备属性主动上报 收到0x09之后串口返回的数据通过0x07接收到 发给mqtt服务器
+cmd:预留 上报不需要
+data:真实数据 
+len:数据实际大小
+*/
+uint8_t dev_report_property(uint8_t cmd,uint8_t *data,uint16_t len)
 {
     strncpy(publish_data.msgid,cloud_msgID,strlen(cloud_msgID));
     uint8_t mode = 0; //0是使用云端生成下发的 属于应答 1 是使用设备端生成的 属于设备主动上报的
@@ -1706,7 +1805,7 @@ uint8_t dev_report_property(uint8_t cmd,uint8_t *data,uint8_t len)
             {
                 case MODE_ACK:
                     mqtt_send_publish_json(TOPIC_PROPERTY_REPLY,root);
-                    /* code */
+                    
                     break;
                 case MODE_REPORT:
                     mqtt_send_publish_json(TOPIC_PROPERTY_REPORT,root);
@@ -1801,8 +1900,13 @@ uint8_t dev_report_property(uint8_t cmd,uint8_t *data,uint8_t len)
 
 
 
-
-uint8_t uart_send_iot_data(uint8_t cmd,uint8_t *data,uint8_t len)
+/*
+func:uart发送queue给mqtt进行数据解析
+cmd: 命令保留
+data:包含key value 
+len:总长度
+*/
+uint8_t uart_send_iot_data(uint8_t cmd,uint8_t *data,uint16_t len)
 {
     if(data == NULL || len == 0 || mqtt_dev_report_queue_handle == NULL)
     {
@@ -1814,26 +1918,30 @@ uint8_t uart_send_iot_data(uint8_t cmd,uint8_t *data,uint8_t len)
     send_msg.cmd = cmd;
     
     if (xQueueSend(mqtt_dev_report_queue_handle, &send_msg, 0) != pdTRUE) {
-        ESP_LOGW(MQTT_TAG, "rev_dev_data if full\n");
+        ESP_LOGW(MQTT_TAG, "cmd send :%d err\n",cmd);
         return 0;
     }
     return 1;
 }
 
 
-
+/*
+func:用户封装mqtt发送函数
+*/
 int user_esp_mqtt_client_publish(char *data,uint16_t data_len,char *topic)
 {
-    if(data == NULL || topic == NULL || data_len == 0 || common_setting.mqtt_client_handle == NULL)
+    if(data == NULL || topic == NULL || data_len == 0 || mqtt_client_handle == NULL)
     {
         return -1;
     }
-    int ret = esp_mqtt_client_publish(common_setting.mqtt_client_handle,topic,\
+    int ret = esp_mqtt_client_publish(mqtt_client_handle,topic,\
     data,data_len,0, 0 );
     return ret;
 
 }
-
+/*
+func:任务cb
+*/
 static void Mqtt_Init_Task_Cb(void *p)
 {
     static mqtt_recv_msg_t recv_msg;
@@ -1841,7 +1949,7 @@ static void Mqtt_Init_Task_Cb(void *p)
     while (1)
     {
         if(mqtt_recv_queue_handle != NULL){
-            if(xQueueReceive(mqtt_recv_queue_handle, &recv_msg, 0) == pdTRUE)
+            if(xQueueReceive(mqtt_recv_queue_handle, &recv_msg, portMAX_DELAY) == pdTRUE)
             {
                 ESP_LOGI(MQTT_TAG, "mqtt recv data");
                 ESP_LOGI(MQTT_TAG, "主题:%d", recv_msg.topic_len);
@@ -1854,7 +1962,7 @@ static void Mqtt_Init_Task_Cb(void *p)
         }
         //设备上报
         if(mqtt_dev_report_queue_handle != NULL){
-            if (xQueueReceive(mqtt_dev_report_queue_handle, &send_msg, 0) == pdTRUE) {
+            if (xQueueReceive(mqtt_dev_report_queue_handle, &send_msg, portMAX_DELAY) == pdTRUE) {
                 if (Mqtt_Get_Connect_Flag()) 
                 {
                     switch (send_msg.cmd)
@@ -1868,34 +1976,26 @@ static void Mqtt_Init_Task_Cb(void *p)
                     }
                     
                 }
-                // if (common_setting.mqtt_user_cfg.mqtt_connect_flag == 1 && common_setting.wifi_status.wifi_state == 1) {
-                //     ESP_LOGI(MQTT_TAG, "queue: msg_id=%s %s", send_msg.topic,send_msg.data);
-                //     esp_mqtt_client_publish(common_setting.mqtt_client_handle,send_msg.topic,
-                //         send_msg.data,strlen(send_msg.data),
-                //         0, 0
-                //     );
-                    
-                // }
             }
         }
         vTaskDelay(10 / portTICK_PERIOD_MS);
     }
 }
 
+/*
+func:mqtt初始化队列
+*/
 void Mqtt_Init_Task(void)
 {
     if(mqtt_init_task_flag){
+        ESP_LOGI(MQTT_TAG, "Mqtt_Init_Task inited");
         return;
     }
     mqtt_init_task_flag=1;
-
     mqtt_recv_queue_handle = xQueueCreateStatic(MQTT_RECV_QUEUE_LENGTH, MQTT_RECV_QUEUE_ITEM_SIZE, mqtt_recv_queue_storage, &mqtt_recv_queue_buffer);
     mqtt_dev_report_queue_handle = xQueueCreateStatic(MQTT_SEND_QUEUE_LENGTH, MQTT_SEND_QUEUE_ITEM_SIZE, mqtt_dev_report_queue_storage, &mqtt_dev_report_queue_buffer);
     
-
-    
     mqtt_connect_task_handler = xTaskCreateStatic(Mqtt_Init_Task_Cb, "mqtt_task", MQTT_CONNECT_TASK_STACK, NULL, 1, mqtt_connect_task_stack, &mqtt_connect_task_tcb);
-     
 }
 
 
index 291e391..6505a93 100644 (file)
@@ -3,7 +3,7 @@
 #include "project_common.h"
 #define ENABLE_MQTT_FUNC 1
 #if ENABLE_MQTT_FUNC
-
+#define UART_REPLY_MAX_PAYLOAD_MQTT     UART_REPLY_MAX_PAYLOAD-4
 typedef enum{
     METHON_SERVICE_PROPERTY_SET=0,//服务属性设置下发methon
     METHON_SERVICE_PROPERTY_SET_REPLAY, //设备属性设置应答
@@ -66,7 +66,7 @@ typedef struct {
 } mqtt_send_msg_t;
 
 typedef struct {
-    uint8_t len;
+    uint16_t len;
     uint8_t data[MQTT_SEND_RECV_DATA_BUF_SIZE];
     uint8_t cmd;
 } mqtt_dev_report_msg_t;
@@ -98,12 +98,13 @@ uint8_t Mqtt_Get_Connect_Flag(void);
 void Mqtt_Send_Connect_Status(void);//发送mqtt连接状态给主控
 void mqtt_set_dev_property(const cJSON *array);
 void mqtt_get_dev_property(const cJSON *array);
-uint8_t dev_report_property(uint8_t cmd,uint8_t *data,uint8_t len);
-uint8_t uart_send_iot_data(uint8_t cmd,uint8_t *data,uint8_t len);
+uint8_t dev_report_property(uint8_t cmd,uint8_t *data,uint16_t len);
+uint8_t uart_send_iot_data(uint8_t cmd,uint8_t *data,uint16_t len);
 cJSON* create_publish_ack_json(const char* msgId,const char* service_id, const char* method);
 cJSON* create_publish_post_json(const char* msgId,const char* service_id, const char* method);
 cJSON* pid_serialNumber_replay_json(const char* msgId,const char* service_id, const char* method,uint16_t code);
 uint8_t mqtt_send_publish_json(TOPIC_TYPE topic_type,cJSON *root);
-void mqtt_parse_recv_data(char *buf, int data_len);
+void mqtt_parse_recv_data(char *data, int data_len);
+void mqtt_check_isconnect(void);
 #endif
 #endif
\ No newline at end of file
index 6c78dad..f0a11c3 100644 (file)
@@ -721,7 +721,8 @@ void Wifi_Enable_Status_Check(void)
                     ESP_LOGI(WIFI_TAG, "http_get_url_task start\n");
                     // http_get_url_task_handler = xTaskCreateStatic(http_get_url_task, "http_get_url_task", HTTP_GET_URL_TASK_STACK, NULL, 2, http_get_url_task_stack, &http_get_url_task_tcb);
                     #if ENABLE_HTTP_FUNC
-                    Http_Get_Url_Task();
+                    // Http_Get_Url_Task();
+                    xEventGroupSetBits(common_event_group, COMMON_HTTP_GET_URL_BIT);
                     #endif
                     // ESP_LOGI(WIFI_TAG, "[APP] Free memory http1 on: %" PRIu32 " bytes", esp_get_free_heap_size());