)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
-project(mqtt_ssl_mutual_auth)
\ No newline at end of file
+project(mqtt_ssl_mutual_auth)
+
+add_custom_command(
+ TARGET app
+ POST_BUILD
+ COMMAND if exist "${CMAKE_SOURCE_DIR}/rename_fw.bat" (cmd /c "${CMAKE_SOURCE_DIR}/rename_fw.bat")
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ COMMENT "自动重命名固件文件(如果存在脚本)..."
+)
\ No newline at end of file
for(;;)
{
+
#if ENABLE_BLE_FUNC
Ble_Enable_Status_Check();
#endif
}
}
+ if((xEventGroupWaitBits(common_event_group, COMMON_FACTORY_SET_BIT, pdFALSE, pdFALSE, 0) & COMMON_FACTORY_SET_BIT) != 0)
+ {
+ xEventGroupClearBits(common_event_group, COMMON_FACTORY_SET_BIT);
+ Esp32_Factory_Reset();
+ }
if((xEventGroupWaitBits(common_event_group, COMMON_RESET_BIT, pdFALSE, pdFALSE, 0) & COMMON_RESET_BIT) != 0)
{
ESP_LOGI(MAIN_TAG, "[APP] IDF version: %s", esp_get_idf_version());
ESP_LOGI(MAIN_TAG, "[DEVICE] Version: %04x %04x", FW_VERSION, BUILD_VERSION);
- // esp_log_level_set("*", ESP_LOG_INFO);
- // esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE);
- // esp_log_level_set("transport_base", ESP_LOG_VERBOSE);
- // esp_log_level_set("transport", ESP_LOG_VERBOSE);
- // esp_log_level_set("outbox", ESP_LOG_VERBOSE);
ESP_LOGI(MAIN_TAG, "[APP] Free memory start: %" PRIu32 " bytes", esp_get_free_heap_size());
// Uart_Initialize();
// uart_task_handler = xTaskCreateStatic(Uart_Task, "Uart_Task", UART_TASK_STACK, NULL, 7, uart_task_stack, &uart_task_tcb);
Uart_Initialize();
uart_task_handler = xTaskCreateStatic(Uart_Task, "Uart_Task", UART_TASK_STACK, NULL, 7, uart_task_stack, &uart_task_tcb);
- // uart_send_task_handler = xTaskCreateStatic(Uart_Send_Task, "Uart_Send_Task", UART_SEND_TASK_STACK, NULL, 5, uart_send_task_stack, &uart_send_task_tcb);
-
- // ESP_LOGI(MAIN_TAG, "[APP] Free memory after Uart_Initialize: %" PRIu32 " bytes", esp_get_free_heap_size());
#if (1)//#if (IOT_ENABLE)
// LWIP
ESP_ERROR_CHECK(esp_netif_init());
// WIFI
#if ENABLE_WIFI_FUNC
Wifi_Sta_Init();
- vTaskDelay(1000);
+ vTaskDelay(500);
#endif
Https_Ota_Handler_Init();
#endif
-
-
- // ESP_LOGI(MAIN_TAG, "chip_id:%s chip_version:%d\n",chip_info.model,chip_info.res);
- //等待wifi稳定再去连接wifi
- // ESP_LOGI(MAIN_TAG, "[APP] Free memory after wifi: %" PRIu32 " bytes", esp_get_free_heap_size());
#endif
main_loop_task_handler = xTaskCreateStatic(Main_Loop_Task, "Main_Loop_Task", MAIN_LOOP_TASK_STACK, NULL, 4, main_loop_task_stack, &main_loop_task_tcb);
- // ESP_LOGI(MAIN_TAG, "[APP] Free memory after Main_Loop: %" PRIu32 " bytes", esp_get_free_heap_size());
- #if (!USER_TEST_ENABLE)
-
- #endif
}
volatile uint16_t ota_faile_count;//失败计数器
uint8_t https_update_ota_flag;//根据版本号是否需要升级
uint8_t https_ota_init;//ota升级task初始化
- esp_https_ota_handle_t https_ota_handle; //ota句柄
+
}__attribute__((packed)) https_ota_ctx_t;
static https_ota_ctx_t s_ota_ctx = { 0 };
+
#define HTTPS_OTA_RETRY_NUM 3
#define OTA_URL_SIZE 128
/*
*函数功能:sdk原生自动版本校验 未使用
*/
+#define HTTPS_OTA_IS_RETRY_FUNC
+// #define HTTPS_OTA_USER_CILENT
+#ifdef HTTPS_OTA_USER_CILENT
+//===== 自研OTA工具函数(直接复制即可)=====
+#include "esp_ota_ops.h"
+#include "esp_app_format.h" // ESP_APP_DESC_MAGIC_WORD
+
+static esp_err_t self_ota_get_target_part(const esp_partition_t **out_ota_part)
+{
+ const esp_partition_t *running = esp_ota_get_running_partition();
+ const esp_partition_t *ota_part = esp_ota_get_next_update_partition(running);
+ if (!ota_part) {
+ ESP_LOGE(HTTPS_OTA, "get ota partition failed");
+ return ESP_FAIL;
+ }
+ *out_ota_part = ota_part;
+ return ESP_OK;
+}
+
+static esp_err_t self_ota_check_firmware_header(const uint8_t *data, size_t len)
+{
+ // 至少要读到 app_desc 大小
+ if (len < sizeof(esp_app_desc_t) + 32) {
+ return ESP_ERR_INVALID_SIZE;
+ }
+
+ // 偏移 24 字节后才是 esp_app_desc_t
+ const esp_app_desc_t *app_desc = (const esp_app_desc_t *)(data + 32);
+
+ // 1. 校验魔数(正确写法!!!)
+ uint32_t magic = ESP_APP_DESC_MAGIC_WORD;
+ if (app_desc->magic_word != magic) {
+ ESP_LOGE(HTTPS_OTA, "firmware magic word error");
+ return ESP_ERR_INVALID_ARG;
+ }
+ return ESP_OK;
+ // 2. 获取当前运行固件版本
+ const esp_partition_t *running_part = esp_ota_get_running_partition();
+ esp_app_desc_t running_desc;
+ if (esp_ota_get_partition_description(running_part, &running_desc) != ESP_OK) {
+ return ESP_FAIL;
+ }
+
+ // 3. 打印版本、判断是否相同
+ ESP_LOGI(HTTPS_OTA, "run ver:%s, new ver:%s",
+ running_desc.version, app_desc->version);
+
+ // 版本相同则不升级
+ if (strcmp((const char*)running_desc.version, (const char*)app_desc->version) == 0) {
+ ESP_LOGW(HTTPS_OTA, "same version, skip");
+ return ESP_ERR_NOT_SUPPORTED;
+ }
+
+ return ESP_OK;
+}
+
+//会占用ram
+// OTA 分片大小,建议 4KB / 8KB,兼顾效率与栈/内存
+#define OTA_DOWNLOAD_BUF_SIZE (4096)
+// HTTP 单次超时(毫秒),核心防阻塞
+#define OTA_HTTP_TIMEOUT_MS (6000)
+// 连续无数据最大次数(判定网络卡死)
+#define OTA_STUCK_MAX_CNT (8)
+// OTA 最大重试次数
+#define OTA_SELF_MAX_RETRY (3)
+
+// 下载缓冲区
+static uint8_t ota_download_buf[OTA_DOWNLOAD_BUF_SIZE];
+static esp_err_t self_ota_download_and_write(const char *url)
+{
+ esp_err_t ret = ESP_FAIL;
+ esp_http_client_handle_t http_client = NULL;
+ const esp_partition_t *ota_part = NULL;
+ esp_ota_handle_t ota_handle = 0;
+
+ uint32_t total_read = 0;
+ // 卡死计数
+ bool header_checked = false;// 固件头只校验一次
+
+ // 1. 获取OTA分区
+ ret = self_ota_get_target_part(&ota_part);
+ if (ret != ESP_OK) goto clean_exit;
+
+ // 2. 初始化HTTP客户端
+ esp_http_client_config_t http_cfg = {
+ .url = url,
+ .timeout_ms = OTA_HTTP_TIMEOUT_MS,
+ .keep_alive_enable = false,
+ .crt_bundle_attach = esp_crt_bundle_attach, // HTTPS证书
+ };
+ http_client = esp_http_client_init(&http_cfg);
+ if (!http_client) {
+ ESP_LOGE(HTTPS_OTA, "http client init fail");
+ ret = ESP_FAIL;
+ goto clean_exit;
+ }
+
+ // 3. 发起连接
+ ret = esp_http_client_open(http_client, 0);
+ if (ret != ESP_OK) {
+ ESP_LOGE(HTTPS_OTA, "http open fail");
+ goto clean_exit;
+ }
+ ret = esp_http_client_fetch_headers(http_client);
+ int code = esp_http_client_get_status_code(http_client);
+ if (code != 200 || ret < 0) {
+ ESP_LOGI(HTTPS_OTA, "HTTP code error");
+ goto clean_exit;
+ }
+ int content_len = esp_http_client_get_content_length(http_client);
+ ESP_LOGI(HTTPS_OTA, "Firmware total len: %d", content_len);
+
+ // 4. 初始化OTA写入句柄
+ ret = esp_ota_begin(ota_part, OTA_SIZE_UNKNOWN, &ota_handle);
+ if (ret != ESP_OK) {
+ ESP_LOGE(HTTPS_OTA, "esp_ota_begin fail");
+ goto clean_exit;
+ }
+
+ // s_self_ota_state = SELF_OTA_DOWNLOADING;
+ ESP_LOGI(HTTPS_OTA, "Start self ota download");
+
+ // 5. 循环分片读取 + 写入 Flash(核心防阻塞循环)
+ while (1)
+ {
+ // 上层主动停止标记(对应你原来的 ota_timeout_req)
+ if (s_ota_ctx.ota_timeout_req) {
+ ESP_LOGW(HTTPS_OTA, "OTA user stop");
+ ret = ESP_ERR_TIMEOUT;
+ break;
+ }
+
+ // 单次读取分片数据
+ int read_len = esp_http_client_read(http_client, (char *)ota_download_buf, OTA_DOWNLOAD_BUF_SIZE);
+ if (read_len < 0) {
+ ESP_LOGE(HTTPS_OTA, "http read error");
+ ret = ESP_FAIL;
+ break;
+ }
+ // 读到末尾,正常结束
+ if (read_len == 0) {
+ ESP_LOGI(HTTPS_OTA, "Download complete, total read: %lu", total_read);
+
+ if(total_read != content_len)
+ {
+ ret = ESP_FAIL;
+ } else {
+ ret = ESP_OK;
+ }
+ break;
+ }
+ total_read += read_len;
+
+ // 第一次读到数据,校验固件头部
+ if (!header_checked) {
+ ret = self_ota_check_firmware_header(ota_download_buf, read_len);
+ if (ret != ESP_OK) break;
+ header_checked = true;
+ }
+
+ // 写入OTA分区
+ ret = esp_ota_write(ota_handle, ota_download_buf, read_len);
+ if (ret != ESP_OK) {
+ ESP_LOGE(HTTPS_OTA, "esp_ota_write fail");
+ break;
+ }
+
+ // 打印进度(可选)
+ ESP_LOGI(HTTPS_OTA, "Download progress: %lu / %d", total_read, content_len);
+ }
+
+ // 6. 下载完成,收尾校验
+ if (ret == ESP_OK) {
+ // s_self_ota_state = SELF_OTA_VERIFY;
+ ret = esp_ota_end(ota_handle);
+ if (ret != ESP_OK) {
+ ESP_LOGE(HTTPS_OTA, "esp_ota_end verify fail");
+ goto clean_exit;
+ } else {
+ // 切换启动分区
+ ret = esp_ota_set_boot_partition(ota_part);
+ if (ret != ESP_OK) {
+ // s_self_ota_state = SELF_OTA_SUCCESS;
+ ESP_LOGI(HTTPS_OTA, "OTA set boot partition ok");
+ goto clean_exit;
+ }
+ ota_handle=0;
+ }
+ }else{
+ //失败需要关闭
+ goto clean_exit;
+ }
+
+clean_exit:
+ // 统一资源释放(重中之重,防止内存/句柄泄漏)
+ if (http_client) {
+ esp_http_client_close(http_client);
+ esp_http_client_cleanup(http_client);
+ }
+ // 失败则终止OTA,标记分区无效
+ if (ret != ESP_OK && ota_handle != 0) {
+ esp_ota_abort(ota_handle);
+ // s_self_ota_state = SELF_OTA_FAILED;
+ }
+ return ret;
+}
+//用户自定义的OTA任务回调函数,主要用于处理OTA升级流程 https
+static void Https_Ota_Task_Cb(void *pvParameter)
+{
+ Mqtt_Disconnect();
+ vTaskDelay(200 / portTICK_PERIOD_MS);
+
+ ESP_LOGI(HTTPS_OTA, "Self OTA start, url: %s", https_ota_url);
+ g_ota_status = HTTPS_OTA_STATUS_UPGRADING;
+ Https_Ota_Report_Status(HTTPS_OTA_STATUS_UPGRADING);
+
+ esp_err_t ota_ret = ESP_FAIL;
+ uint8_t try_idx = 0;
+ bool ota_success = false;
+
+ s_ota_ctx.ota_timeout_count = HTTPS_OTA_TIMEOUT_TIME;
+ // 多层重试
+ for (try_idx = 0; try_idx < HTTPS_OTA_MAX_RETRY_CNT; try_idx++)
+ {
+ ESP_LOGI(HTTPS_OTA, "==== Self OTA retry %d/%d ====", try_idx+1, HTTPS_OTA_MAX_RETRY_CNT);
+ if (s_ota_ctx.ota_timeout_req) {
+ ota_success = false;
+ break;;
+ }
+ // 调用自研下载函数
+ ota_ret = self_ota_download_and_write(https_ota_url);
+ if (ota_ret == ESP_OK) {
+ ota_success = true;
+ break;
+ }
+ vTaskDelay(pdMS_TO_TICKS(HTTPS_OTA_RETRY_TIMES));
+ }
+
+ // ========== 分支处理:成功 / 失败 ==========
+ if (ota_success)
+ {
+ g_ota_status = HTTPS_OTA_STATUS_SUCCESS;
+ #if (!ENABLE_HTTP_N455_OTA_FUNC)
+ Https_Ota_Report_Status(HTTPS_OTA_STATUS_SUCCESS);
+ Https_Ota_Clear_Upgrade_Flag();
+ esp_restart(); // 正常重启
+ #else
+ // 保留你原有 N455 联动逻辑
+ if(N455_Ota_Get_Update_Flag())
+ {
+ if(N455_Ota_Task() == 1)
+ {
+ esp_ota_mark_app_invalid_rollback();
+ Https_Ota_Report_Status(HTTPS_OTA_STATUS_FAILED);
+ N455_Ota_Clear_Upgrade_Flag();
+ Https_Ota_Clear_Upgrade_Flag();
+ xEventGroupSetBits(common_event_group, COMMON_MQTT_CONNECT_BIT);
+ }
+ }else{
+ Https_Ota_Report_Status(HTTPS_OTA_STATUS_SUCCESS);
+ Https_Ota_Clear_Upgrade_Flag();
+ esp_restart();
+ }
+ #endif
+ vTaskDelete(NULL);
+ return;
+ }
+ else
+ {
+ // 升级失败分支
+ ESP_LOGE(HTTPS_OTA, "Self OTA all retry failed");
+ g_ota_status = HTTPS_OTA_STATUS_FAILED;
+ Https_Ota_Report_Status(HTTPS_OTA_STATUS_FAILED);
+ Https_Ota_Clear_Upgrade_Flag();
+ xEventGroupSetBits(common_event_group, COMMON_MQTT_CONNECT_BIT);
+ vTaskDelete(NULL);
+ }
+}
+#endif
+#ifndef HTTPS_OTA_USER_CILENT
+#ifndef HTTPS_OTA_IS_RETRY_FUNC
static esp_err_t validate_image_header(esp_app_desc_t *new_app_info)
{
return ESP_OK;
// err = esp_http_client_set_header(http_client, "Custom-Header", "Value");
return err;
}
-
-#if 0
/*
func:OTA升级回调函数
*/
static void Https_Ota_Task_Cb(void *pvParameter)
{
+ esp_https_ota_handle_t https_ota_handle = NULL;
ota_timeout_count = HTTPS_OTA_TIMEOUT_TIME;
Mqtt_Disconnect(); // 关闭MQTTs
// 2. 延迟一下确保资源释放
// 删除
vTaskDelete(NULL);
}
-#else
+#endif
+#ifdef HTTPS_OTA_IS_RETRY_FUNC
+static esp_err_t validate_image_header(esp_app_desc_t *new_app_info)
+{
+ return ESP_OK;
+ if (new_app_info == NULL) {
+ return ESP_ERR_INVALID_ARG;
+ }
+
+ const esp_partition_t *running = esp_ota_get_running_partition();
+ esp_app_desc_t running_app_info;
+ if (esp_ota_get_partition_description(running, &running_app_info) == ESP_OK) {
+ ESP_LOGI(HTTPS_OTA, "Running firmware version: %s", running_app_info.version);
+ }
+ ESP_LOGI(HTTPS_OTA, "Running firmware version: %s new_app_info->version:%s", running_app_info.version,new_app_info->version);
+#if 1
+ if (memcmp(new_app_info->version, running_app_info.version, sizeof(new_app_info->version)) == 0) {
+ ESP_LOGW(HTTPS_OTA, "Current running version is the same as a new. We will not continue the update.");
+ return ESP_FAIL;
+ }
+#endif
+
+#ifdef CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
+ /**
+ * Secure version check from firmware image header prevents subsequent download and flash write of
+ * entire firmware image. However this is optional because it is also taken care in API
+ * esp_https_ota_finish at the end of OTA update procedure.
+ */
+ const uint32_t hw_sec_version = esp_efuse_read_secure_version();
+ if (new_app_info->secure_version < hw_sec_version) {
+ ESP_LOGW(HTTPS_OTA, "New firmware security version is less than eFuse programmed, %"PRIu32" < %"PRIu32, new_app_info->secure_version, hw_sec_version);
+ return ESP_FAIL;
+ }
+#endif
+
+ return ESP_OK;
+}
+
+static esp_err_t _http_client_init_cb(esp_http_client_handle_t http_client)
+{
+ esp_err_t err = ESP_OK;
+ /* Uncomment to add custom headers to HTTP request */
+ // err = esp_http_client_set_header(http_client, "Custom-Header", "Value");
+ return err;
+}
static void Https_Ota_Task_Cb(void *pvParameter)
{
-
+ esp_https_ota_handle_t https_ota_handle = NULL;
Mqtt_Disconnect(); // 关闭MQTTs
- vTaskDelay(200 / portTICK_PERIOD_MS);
+ vTaskDelay(50 / portTICK_PERIOD_MS);
- s_ota_ctx.https_ota_handle=NULL;
+ https_ota_handle=NULL;
ESP_LOGI(HTTPS_OTA, "Starting Advanced OTA example:%s\n",https_ota_url);
g_ota_status = HTTPS_OTA_STATUS_UPGRADING;
Https_Ota_Report_Status(HTTPS_OTA_STATUS_UPGRADING);
- vTaskDelay(100 / portTICK_PERIOD_MS);
+ vTaskDelay(50 / portTICK_PERIOD_MS);
esp_err_t ota_finish_err = ESP_OK;
bool ota_success = false;
ESP_LOGI(HTTPS_OTA,"==== OTA try %d/%d ====",try_idx+1,HTTPS_OTA_MAX_RETRY_CNT);
esp_http_client_config_t config = {
.url = https_ota_url,
- .timeout_ms = 5000,
+ .timeout_ms = 3000,
.keep_alive_enable = false,
};
config.crt_bundle_attach = esp_crt_bundle_attach;
esp_err_t err = ESP_FAIL;
// 先释放上一轮句柄
- if (s_ota_ctx.https_ota_handle != NULL)
+ if (https_ota_handle != NULL)
{
- esp_https_ota_abort(s_ota_ctx.https_ota_handle);
- s_ota_ctx.https_ota_handle = NULL;
+ esp_https_ota_abort(https_ota_handle);
+ https_ota_handle = NULL;
}
- s_ota_ctx.https_ota_handle = NULL;
- err = esp_https_ota_begin(&ota_config, &s_ota_ctx.https_ota_handle);
+ https_ota_handle = NULL;
+ err = esp_https_ota_begin(&ota_config, &https_ota_handle);
if(err != ESP_OK)
{
ESP_LOGI(HTTPS_OTA, "esp_https_ota_begin failed, try:%d", try_idx+1);
err = ESP_FAIL;
esp_app_desc_t app_desc;
- err = esp_https_ota_get_img_desc(s_ota_ctx.https_ota_handle, &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");
vTaskDelay(pdMS_TO_TICKS(HTTPS_OTA_RETRY_TIMES));
download_abort = true;
break;
}
- if(s_ota_ctx.https_ota_handle == NULL)
+ if(https_ota_handle == NULL)
{
download_abort = true;
break;
}
- err = esp_https_ota_perform(s_ota_ctx.https_ota_handle);
+ err = esp_https_ota_perform(https_ota_handle);
if (err == ESP_ERR_HTTPS_OTA_IN_PROGRESS) {
- ESP_LOGI(HTTPS_OTA, "Image bytes read: %d ota_timeout_req:%d", esp_https_ota_get_image_len_read(s_ota_ctx.https_ota_handle),s_ota_ctx.ota_timeout_req);
+ ESP_LOGI(HTTPS_OTA, "Image bytes read: %d ota_timeout_req:%d", esp_https_ota_get_image_len_read(https_ota_handle),s_ota_ctx.ota_timeout_req);
if(s_ota_ctx.ota_timeout_req){
ESP_LOGI(HTTPS_OTA, "user stop!!!!timeout!!!!");
}
// 数据没收全
- if (esp_https_ota_is_complete_data_received(s_ota_ctx.https_ota_handle) != true) {
+ if (esp_https_ota_is_complete_data_received(https_ota_handle) != true) {
ESP_LOGI(HTTPS_OTA, "Complete data was not received. continue ota %d",common_setting.wifi_status.wifi_state);
vTaskDelay(pdMS_TO_TICKS(HTTPS_OTA_RETRY_TIMES));
continue;
}
// 执行finish
- ota_finish_err = esp_https_ota_finish(s_ota_ctx.https_ota_handle);
+ ota_finish_err = esp_https_ota_finish(https_ota_handle);
if ((err == ESP_OK) && (ota_finish_err == ESP_OK)) {
ESP_LOGI(HTTPS_OTA, "ESP_HTTPS_OTA upgrade successful. Rebooting ...");
g_ota_status = HTTPS_OTA_STATUS_SUCCESS;
s_ota_ctx.ota_timeout_count=0;
- s_ota_ctx.https_ota_handle = NULL;
+ https_ota_handle = NULL;
ota_success = true;
break; //升级成功跳出for,不再重试
} else {
vTaskDelete(NULL);
return;
}else{
- if(s_ota_ctx.https_ota_handle != NULL && g_ota_status != HTTPS_OTA_STATUS_SUCCESS){
- esp_https_ota_abort(s_ota_ctx.https_ota_handle);
- s_ota_ctx.https_ota_handle = NULL;
+ if(https_ota_handle != NULL && g_ota_status != HTTPS_OTA_STATUS_SUCCESS){
+ esp_https_ota_abort(https_ota_handle);
+ https_ota_handle = NULL;
}
s_ota_ctx.ota_timeout_req=0;
ESP_LOGI(HTTPS_OTA, "ESP_HTTPS_OTA upgrade failed after 3 retry");
}
}
#endif
+#endif
//清空升级标识
void Https_Ota_Clear_Upgrade_Flag(void)
{
// 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表示收到但失败
-
-// //task 标识
-// static uint8_t n455_ota_init = 0;
-// static volatile uint8_t n455_ota_stop_flag = 0;
-// static volatile uint16_t n455_ota_timeout_cnt = 0;
-// static uint8_t n455_ota_update_flag = 0; //ota是否需要升级 根据版本号比对
typedef struct{
volatile bool uart_ack_received; //收到回复串口的应答 1收到应答
.crt_bundle_attach = esp_crt_bundle_attach,
.event_handler = _http_ota_event_handler,
.timeout_ms = 5000,
- .keep_alive_enable = false,
+ .keep_alive_enable = false, //true 会占用很多内存建议是false 不需要保持连接
};
/*
*模组不需要升级的时候需要上报状态 模组升级了不需要再次上报升级中的状态
if(!Https_Ota_Get_Update_Flag())
{
Mqtt_Disconnect(); // 关闭MQTTs
- vTaskDelay(200 / portTICK_PERIOD_MS);
+ vTaskDelay(50 / portTICK_PERIOD_MS);
n455_g_ota_status = N455_OTA_STATUS_UPGRADING;
Https_Ota_Report_Status(N455_OTA_STATUS_UPGRADING);
}
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;
memset(buf, 0, sizeof(buf));
real_write_len = 0;
CRC32_Init(&crc_ctx);
- offset_size = 0;
memset(write_data, 0, sizeof(write_data));
// memset(header_buf,0,sizeof(header_buf));
wlen = 0;
CRC32_Update(&crc_ctx, buf, r);
- 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;
+ write_data[wlen++] = real_write_len & 0xFF;
+ write_data[wlen++] = (real_write_len >> 8) & 0xFF;
+ write_data[wlen++] = (real_write_len >> 16) & 0xFF;
+ write_data[wlen++] = (real_write_len >> 24) & 0xFF;
write_data[wlen++] = r & 0xFF;
write_data[wlen++] = (r >> 8) & 0xFF;
memcpy(&write_data[wlen], buf, r);
break;
}
- offset_size += r;
+ // offset_size += r;
real_write_len += r;
+ ESP_LOGE(N455_OTA, "W:%d",real_write_len);
}
ESP_LOGE(N455_OTA, "WRITE END:%d",real_write_len);
//超时退出不再继续ota升级
*chip_len=len;
memcpy(chip_id,chip_name,strlen(chip_name));
// 最终清晰打印
- ESP_LOGI(CHIP_LOG, "chip_name: %s chip_info.revision %d", chip_name,chip_info.revision);
+ // ESP_LOGI(CHIP_LOG, "chip_name: %s chip_info.revision %d", chip_name,chip_info.revision);
}
void print_chip_info(void)
#define FW_VERSION_B VERSION_MAX_HEX
#endif
+#define DEFAULT_MAGRIC_MCU 0xBAD0C0FFEE00CAFE
+
// 最终对外版本
-#define FW_VERSION (FW_VERSION_B > VERSION_MAX_HEX ? VERSION_MAX_HEX:FW_VERSION_B) // 固件版本 //10.22 // 固件版本 //10.22 // 固件版本 //10.22 // 固件版本 //0A00 10.00 10.21
+#define FW_VERSION (0x0101) // 固件版本 //10.22 // 固件版本 //10.22 // 固件版本 //10.22 // 固件版本 //0A00 10.00 10.21
#define BUILD_VERSION (0x000C) // 编译测试版本
#define DEVICE_VID (0x36E6) // 设备厂商代码
#define DEVICE_PID (0xEC01) // 设备型号代码
COMMON_HTTP_GET_URL_BIT = BIT6,
COMMON_HTTP_BIND_BIT = BIT7,
COMMON_HTTPS_N455_OTA_BIT = BIT8,
+ COMMON_FACTORY_SET_BIT = BIT9,
}COMMON_EVENT_GROUP_BIT_E;
typedef enum
uint8_t reserved:4;
int tz_offset_min;
+
// UNIVERSAL
uint32_t heart_beat_interval; // ms
MCU_INFO_T mcu_info;
void int64_to_str(uint64_t ts, char *out,size_t out_len);
void Get_Time(struct tm *time_out);
void set_system_time_int_from_utc(int64_t utc_timestamp_sec,const char *zone);
-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);
//
case COMMON_UART_FACTORY_RESET:
{
- Esp32_Factory_Reset();
+
+ xEventGroupSetBits(common_event_group, COMMON_FACTORY_SET_BIT);
uart_pairing_reply.send_flag=1;
uart_pairing_reply.len = 0;
}
//清除信息
User_Erase_Nimble_NetWork_Infor();
//read wifi 信息
- User_Flash_Check();
+
memset(&common_storage, 0, sizeof(common_storage));
memset(&common_setting.net_pairing_info,0x00,sizeof(common_setting.net_pairing_info));
memset(&common_setting.mqtt_user_cfg,0x00,sizeof(common_setting.mqtt_user_cfg));
memset(&common_setting.https_ota_cfg,0x00,sizeof(common_setting.https_ota_cfg));
-
+ User_Flash_Check();
}
esp_err_t User_Flash_Erase(size_t offset, size_t size)
}
-// ===================== MQTT 事件拆分(原大函数拆分为子函数) =====================
+// ===================== MQTT 事件连接函数 =====================
static void mqtt_event_on_connected(esp_mqtt_event_handle_t event)
{
esp_mqtt_client_handle_t mqtt_client = event->client;
}
#endif
}
-
+/************mqtt****断开事件函数******************************* */
static void mqtt_event_on_disconnected(void)
{
mqtt_ctx.sub_flag = 0;
ESP_LOGI(MQTT_TAG, "MQTT_EVENT_DISCONNECTED");
}
-
+/****************mqtt**********订阅成功事件*********************** */
static void mqtt_event_on_subscribed(void)
{
mqtt_ctx.sub_flag = 1;
ESP_LOGI(MQTT_TAG, "MQTT_EVENT_SUBSCRIBED");
}
+/***************mqtt*******服务下发数据事件***************************************** */
static void mqtt_event_on_data(esp_mqtt_event_handle_t event)
{
Mqtt_Recv_Data(event->topic, event->topic_len, event->data, event->data_len);
}
-
+/*****************mqtt*****事件错误回调******************************************************** */
static void mqtt_event_on_error(esp_mqtt_event_handle_t event)
{
ESP_LOGI(MQTT_TAG, "MQTT_EVENT_ERROR");
case MQTT_EVENT_DATA:
// ESP_LOGI(MQTT_TAG, "TOPIC=%.*s\r\n", event->topic_len, event->topic);
- ESP_LOGI(MQTT_TAG, "DATA=%.*s\r\n", event->data_len, event->data);
-
+ // ESP_LOGI(MQTT_TAG, "DATA=%.*s\r\n", event->data_len, event->data);
+ ESP_LOGI(MQTT_TAG, "DATA=%d %d\r\n", event->data_len,event->topic_len);
mqtt_event_on_data(event);
break;
{
// 1. 长度判断
+
if (topic_len > MQTT_TOPIC_LEN || data_len > MQTT_DATA_BUF_SIZE || data_len <= 0 || topic_len <= 0) {
ESP_LOGI(MQTT_TAG, "len large :%d\n",data_len);
return;
}
-
+ if (topic_len == strlen(get_publish_topic(TOPIC_FIRMWARE_OTA_UPGRADE)) &&
+ strcmp(get_publish_topic(TOPIC_FIRMWARE_OTA_UPGRADE), topic) == 0)
+ {
+ ESP_LOGI(MQTT_TAG, "ota json");
+ mqtt_parse_recv_data(topic, topic_len, data, data_len);
+ return;
+ }
+
// 2. 构建消息
mqtt_recv_msg_t msg;
memset(&msg, 0, sizeof(mqtt_recv_msg_t));
*函数功能:开机连上mqtt订阅成功之后发送主控信息
*/
-void Mqtt_Send_Mcu_Info(void)
+uint8_t Mqtt_Send_Mcu_Info(void)
{
if(mqtt_ctx.mqtt_send_mcu_info_flag)
{
- return;
+ return 0;
}
if(!Mqtt_Get_Connect_Flag())
{
- return;
+ return 0;
}
char pid_str[10] = {0};
char vid_str[10] = {0};
char wifi_soc[16] = {"Unknown"};
+ esp_chip_info_t chip_info;
+ esp_chip_info(&chip_info);
// 获取芯片型号
- uint8_t chip_len = 0;
- get_chip_info(wifi_soc, &chip_len);
- if (chip_len == 0) {
- strcpy(wifi_soc, "Unknown");
+ // uint8_t chip_len = 0;
+ // get_chip_info(wifi_soc, &chip_len);
+
+ if (chip_info.model == CHIP_ESP32C2) {
+ strcpy(wifi_soc, "ESP32-C2");
+ }else{
+ strcpy(wifi_soc, "Unknown");
}
// PID、VID 大写十六进制格式
snprintf(pid_str, sizeof(pid_str), "%04X", common_setting.mcu_info.pid);
// ===================== 构建正确的 JSON =====================
cJSON *root = cJSON_CreateObject();
- if (root == NULL) return;
+ if (root == NULL) return 0;
// 把设备信息加到里面
char *post_data = cJSON_PrintUnformatted(root);
cJSON_Delete(root);
root=NULL;
- if (post_data == NULL) return;
+ if (post_data == NULL) return 0;
if(strlen(post_data) >= MQTT_SEND_RECV_DATA_BUF_SIZE)
ESP_LOGI(MQTT_TAG, "len large %d", strlen(post_data));
free(post_data);
post_data=NULL;
- return;
+ return 0 ;
}
if(strlen(post_data) == 0 || strlen(get_publish_topic(TOPIC_PROPERTY_ACK_POST)) == 0)
{
ESP_LOGI(MQTT_TAG, "len no %d", strlen(get_publish_topic(TOPIC_PROPERTY_ACK_POST)),strlen(post_data));
free(post_data);
post_data=NULL;
- return;
+ return 0;
}
// static char data_buf[64] = {0};
// static mqtt_send_msg_t send_msg={0};
// memcpy(data_buf,post_data,strlen(post_data));
- ESP_LOGI(MQTT_TAG, "CJSON:%s", post_data);
+ ESP_LOGI(MQTT_TAG, "mcu info:%d", strlen(post_data));
// memcpy(send_msg.topic,get_publish_topic(TOPIC_PROPERTY_ACK_POST),strlen(get_publish_topic(TOPIC_PROPERTY_ACK_POST)));
if(mqtt_dev_report_queue_handle==NULL)
{
ESP_LOGI(MQTT_TAG, "Mqtt_Send_Mcu_Info is null\n");
- return;
+ return 0;
}
- user_esp_mqtt_client_publish(post_data,strlen(post_data),get_publish_topic(TOPIC_PROPERTY_ACK_POST));
+ int ret = user_esp_mqtt_client_publish(post_data,strlen(post_data),get_publish_topic(TOPIC_PROPERTY_ACK_POST));
free(post_data);
post_data = NULL;
mqtt_ctx.mqtt_send_mcu_info_flag=0;
- return;
+ return 1;
}
void mqtt_get_dev_test(uint16_t *dpid,uint8_t num);
/*
// mqtt_get_dev_test(test_dpid,49);
}
- if(mqtt_ctx.mqtt_send_data_count >= 30)
+ ESP_LOGI(MQTT_TAG,"%d %d",mqtt_ctx.sub_flag,mqtt_ctx.connect_flag);
+ if(mqtt_ctx.sub_flag == 1 && mqtt_ctx.connect_flag == 1)
{
+ static uint8_t send_flag_first = 0;
+ if(send_flag_first == 0 && mqtt_ctx.mqtt_send_data_count >= 2)
+ {
+ if(Mqtt_Send_Mcu_Info())
+ {
+ send_flag_first=1;
+ }
+ }
+ if(mqtt_ctx.mqtt_send_data_count >= 30)
+ {
+ mqtt_ctx.mqtt_send_data_count = 0;
+ Mqtt_Send_Mcu_Info();
+ }
+ }else{
mqtt_ctx.mqtt_send_data_count = 0;
- Mqtt_Send_Mcu_Info();
}
mqtt_ctx.mqtt_send_data_count++;
}
-
+//用户自定义的json生成函数测试数据
+#if 0
char *set_test_json(void)
{
// 1. 创建根对象
cJSON_Delete(root);
return out;
}
+#endif
+
/*
*函数功能: ota报文解析
*参数array:数组[{},{}]
if(reset->valueint)
{
//2.重启设备
+ Wifi_Stop();
+ vTaskDelay(pdMS_TO_TICKS(50));
+ Mqtt_Disconnect();
+ vTaskDelay(pdMS_TO_TICKS(50));
User_Erase_Nimble_NetWork_Infor();
- vTaskDelay(pdMS_TO_TICKS(100));
if(root != NULL)
{
cJSON_Delete(root);
{
ret = Uart_Reply_Send(COMMON_UART_PROPERTY_BATCH_REPORT_CMD,send_data, send_len,HOST_TYPE_UART);
- ESP_LOGI(MQTT_TAG,"end ret %d\n",ret);
+ ESP_LOGI(MQTT_TAG,"send=%d\n",ret);
return ret;
}
else{
#define MQTT_TOPIC_LEN 64
#define MQTT_MAX_TRY_CONNECT_TIME 10
#define MQTT_DATA_BUF_SIZE MQTT_SEND_RECV_DATA_BUF_SIZE
-#define MQTT_RECV_QUEUE_LENGTH 8
+#define MQTT_RECV_QUEUE_LENGTH 10
-#define MQTT_SEND_QUEUE_LENGTH 4
+#define MQTT_SEND_QUEUE_LENGTH 8
#define MQTT_SEND_MSG_MAX_LEN MQTT_SEND_RECV_DATA_BUF_SIZE
void Mqtt_Recv_Data(char *topic,int topic_len,char *data,int data_len);
void Mqtt_Init_Task(void);
void Mqtt_Disconnect(void);
-void Mqtt_Send_Mcu_Info(void);
+
uint8_t Mqtt_Get_Connect_Flag(void);
void Mqtt_Send_Connect_Status(void);//发送mqtt连接状态给主控
int mqtt_set_dev_property(const cJSON *array);
void mqtt_check_isconnect(void);
void mqtt_ota_data_parse(const cJSON *array);
uint8_t get_mqtt_init_flag(void);
+uint8_t Mqtt_Send_Mcu_Info(void);
#endif
#endif
\ No newline at end of file
static esp_timer_handle_t wifi_one_timer_handle;//创建定时器handle
static uint8_t wifi_one_timer_flag = 0;//0:未创建 1:已创建
-void Wifi_Connect_Set_Flag(void)
-{
- if(common_setting.wifi_status.connect_mode != 2)//只有用户配网才开启定时器
- {
- return;
- }
- #if (1)
-
-
- #endif
-}
+
void Wifi_Connect_Timerout_Stop(void)
{
if(wifi_one_timer_flag)
s_retry_num = 0;
if(common_setting.wifi_status.connect_mode == 2)
{
- // Create and start one-time timer for 80 ms
+ // Create and start one-time timer for 80s
if(common_setting.ble_status.ble_adv_flag > 0) //蓝牙开启说明在配网状态 如果在设定的时间内没有连上就发送超时蓝牙指令
{
wifi_connect_timeout_flag = 1;
--- /dev/null
+@echo off
+chcp 65001 >nul 2>&1
+setlocal enabledelayedexpansion
+
+set "BAT_PATH=%~dp0"
+set "BAT_PATH=!BAT_PATH:~0,-1!"
+
+set "PROJ_DIR=!BAT_PATH!"
+set "H_FILE=!PROJ_DIR!\main\project_common.h"
+set "SRC_BIN=!PROJ_DIR!\build\mqtt_ssl_mutual_auth.bin"
+set "DST_DIR=!PROJ_DIR!\update_bin"
+set "PREFIX=ESP32_C2_IOT_Update_"
+
+if not exist "!SRC_BIN!" (
+ echo ERROR: Source bin not found: !SRC_BIN!
+ pause
+ exit /b 1
+)
+
+set "LINE="
+for /f "delims=" %%a in ('findstr /r /C:"#define[ \t]*FW_VERSION" "!H_FILE!"') do (
+ set "LINE=%%a"
+)
+if "!LINE!"=="" (
+ echo ERROR: FW_VERSION not found in header
+ pause
+ exit /b 1
+)
+
+:: ======================
+:: 修复:支持 (0x0101) 括号
+:: ======================
+for /f "tokens=3 delims=() " %%b in ("!LINE!") do set "RAW=%%b"
+set "RAW=!RAW:;=!"
+set "RAW=!RAW: =!"
+
+set "HEX=!RAW:~2,4!"
+set "HIB_HEX=!HEX:~0,2!"
+set "LOB_HEX=!HEX:~2,2!"
+if "!LOB_HEX!"=="" set "LOB_HEX=00"
+if "!HIB_HEX!"=="" set "HIB_HEX=00"
+
+call :hex2dec !HIB_HEX! HIB
+call :hex2dec !LOB_HEX! LOB
+
+if !LOB! lss 10 set "LOB=0!LOB!"
+set "VER=V!HIB!.!LOB!"
+
+for /f "tokens=2-4 delims=/-. " %%a in ("%date%") do (
+ set "YYYY=%%a"
+ set "MM=%%b"
+ set "DD=%%c"
+)
+set "HH=%time:~0,2%"
+set "MI=%time:~3,2%"
+set "HH=!HH: =0!"
+set "MI=!MI: =0!"
+set "DATETIME=!YYYY!!MM!!DD!!HH!!MI!"
+
+set "DST_BIN=!DST_DIR!\!PREFIX!!VER!_!DATETIME!.bin"
+if not exist "!DST_DIR!" md "!DST_DIR!"
+
+copy /y "!SRC_BIN!" "!DST_BIN!" >nul
+if !errorlevel! equ 0 (
+ echo SUCCESS: !DST_BIN!
+) else (
+ echo ERROR: Copy failed
+)
+
+pause
+exit /b
+
+:hex2dec
+setlocal
+set "hex=%1"
+set "hex=!hex:a=A!"
+set "hex=!hex:b=B!"
+set "hex=!hex:c=C!"
+set "hex=!hex:d=D!"
+set "hex=!hex:e=E!"
+set "hex=!hex:f=F!"
+set "c1=!hex:~0,1!"
+set "c2=!hex:~1,1!"
+call :char2dec !c1! v1
+call :char2dec !c2! v2
+set /a dec=v1*16+v2
+endlocal & set "%2=%dec%"
+goto :eof
+
+:char2dec
+setlocal
+set "c=%1"
+set "val=0"
+if /i "!c!"=="0" set val=0
+if /i "!c!"=="1" set val=1
+if /i "!c!"=="2" set val=2
+if /i "!c!"=="3" set val=3
+if /i "!c!"=="4" set val=4
+if /i "!c!"=="5" set val=5
+if /i "!c!"=="6" set val=6
+if /i "!c!"=="7" set val=7
+if /i "!c!"=="8" set val=8
+if /i "!c!"=="9" set val=9
+if /i "!c!"=="A" set val=10
+if /i "!c!"=="B" set val=11
+if /i "!c!"=="C" set val=12
+if /i "!c!"=="D" set val=13
+if /i "!c!"=="E" set val=14
+if /i "!c!"=="F" set val=15
+endlocal & set "%2=%val%"
+goto :eof
\ No newline at end of file