840 lines
27 KiB
C
840 lines
27 KiB
C
|
/*
|
||
|
* @Date: 2024-07-18 16:55:31
|
||
|
* @LastEditors: lzc56 563451665@qq.com
|
||
|
* @LastEditTime: 2025-01-02 13:45:42
|
||
|
* @FilePath: \software\main\src\bsp_upgrade.c
|
||
|
*/
|
||
|
#include "bsp_mqtt.h"
|
||
|
#include "esp_wifi.h"
|
||
|
#include "drv_fatfs.h"
|
||
|
#include "drv_usart.h"
|
||
|
#include "bsp_algCom.h"
|
||
|
#include "bsp_bleNet.h"
|
||
|
#include "bsp_upgrade.h"
|
||
|
#include "crcTable.h"
|
||
|
// #include "ymodem.h"
|
||
|
|
||
|
#define FILE_URL "http://dev.bewatec.com.cn:22223/test/10004/mods/mattress/S1.0.0"
|
||
|
#define FILE_PATH "/spiflash/OTA.bin"
|
||
|
|
||
|
#define PACKET_SIZE 512
|
||
|
|
||
|
CRC32_CTX ota_ctx;
|
||
|
ota_info_t ota_info;
|
||
|
TaskHandle_t upgrade_TaskHandle;
|
||
|
static const char *TAG = "bsp/upgrade";
|
||
|
|
||
|
uint32_t deviceUpgradeNum = 0;
|
||
|
|
||
|
int LastPacketLessSize = 0;
|
||
|
char otaSendBuffer[PACKET_SIZE] = {0};
|
||
|
char LastPacketBuffer[PACKET_SIZE] = {0};
|
||
|
|
||
|
extern const uint8_t server_cert_pem_start[] asm("_binary_ca_cert_pem_start");
|
||
|
extern const uint8_t server_cert_pem_end[] asm("_binary_ca_cert_pem_end");
|
||
|
|
||
|
// extern void dump_hex(const uint8_t *buf, uint32_t size);
|
||
|
extern esp_err_t nvs_write_otaInfo(ota_info_t *pOta_info_t, uint32_t len);
|
||
|
|
||
|
#define OTA_URL_SIZE 256
|
||
|
|
||
|
static void send_GoIntoOTA(void);
|
||
|
static void send_ota_Info(void);
|
||
|
void send_ota_Upgrade(void);
|
||
|
|
||
|
long fsize(FILE *fp);
|
||
|
void Ymodem_Exit(void);
|
||
|
void prepareUpgrade(void);
|
||
|
void protobufSendOta(void);
|
||
|
char Ymodem_checkFile(void);
|
||
|
void list_dir(const char *path);
|
||
|
void CRC32_Init(CRC32_CTX *ctx);
|
||
|
void upgradeTimeOut_Reboot(void);
|
||
|
void dump_hex(const uint8_t *buf, uint32_t size);
|
||
|
void download_file_task(void *pvParameters);
|
||
|
void CRC32_Final(CRC32_CTX *ctx, unsigned char *md);
|
||
|
void CRC32_Update(CRC32_CTX *ctx, const unsigned char *data, size_t len);
|
||
|
static char send_ota_bin(char *data, int len, uint32_t packetNum);
|
||
|
/* Event handler for catching system events */
|
||
|
static void ota_event_handler(void *arg, esp_event_base_t event_base,
|
||
|
int32_t event_id, void *event_data)
|
||
|
{
|
||
|
if (event_base == ESP_HTTPS_OTA_EVENT)
|
||
|
{
|
||
|
switch (event_id)
|
||
|
{
|
||
|
case ESP_HTTPS_OTA_START:
|
||
|
ESP_LOGI(TAG, "OTA started");
|
||
|
break;
|
||
|
case ESP_HTTPS_OTA_CONNECTED:
|
||
|
ESP_LOGI(TAG, "Connected to server");
|
||
|
break;
|
||
|
case ESP_HTTPS_OTA_GET_IMG_DESC:
|
||
|
ESP_LOGI(TAG, "Reading Image Description");
|
||
|
break;
|
||
|
case ESP_HTTPS_OTA_VERIFY_CHIP_ID:
|
||
|
ESP_LOGI(TAG, "Verifying chip id of new image: %d", *(esp_chip_id_t *)event_data);
|
||
|
break;
|
||
|
case ESP_HTTPS_OTA_DECRYPT_CB:
|
||
|
ESP_LOGI(TAG, "Callback to decrypt function");
|
||
|
break;
|
||
|
case ESP_HTTPS_OTA_WRITE_FLASH:
|
||
|
ESP_LOGD(TAG, "Writing to flash: %d written", *(int *)event_data);
|
||
|
break;
|
||
|
case ESP_HTTPS_OTA_UPDATE_BOOT_PARTITION:
|
||
|
ESP_LOGI(TAG, "Boot partition updated. Next Partition: %d", *(esp_partition_subtype_t *)event_data);
|
||
|
break;
|
||
|
case ESP_HTTPS_OTA_FINISH:
|
||
|
ESP_LOGI(TAG, "OTA finish");
|
||
|
break;
|
||
|
case ESP_HTTPS_OTA_ABORT:
|
||
|
ESP_LOGI(TAG, "OTA abort");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static esp_err_t validate_image_header(esp_app_desc_t *new_app_info)
|
||
|
{
|
||
|
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(TAG, "Running firmware version: %s", running_app_info.version);
|
||
|
}
|
||
|
|
||
|
#ifndef CONFIG_EXAMPLE_SKIP_VERSION_CHECK
|
||
|
if (memcmp(new_app_info->version, running_app_info.version, sizeof(new_app_info->version)) == 0)
|
||
|
{
|
||
|
ESP_LOGW(TAG, "Current running version is the same as a new. We will not continue the update.");
|
||
|
// 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;
|
||
|
}
|
||
|
|
||
|
void selfUpgradeTask(void *pvParameter)
|
||
|
{
|
||
|
char url_Buffer[128] = {0};
|
||
|
memcpy(url_Buffer, ota_info.url, sizeof(ota_info.url));
|
||
|
strcat(url_Buffer, "/");
|
||
|
strcat(url_Buffer, ota_info.wifiPath);
|
||
|
ESP_LOGI(TAG, "url : %s", url_Buffer);
|
||
|
ESP_LOGI(TAG, "Starting Advanced OTA example");
|
||
|
|
||
|
esp_err_t ota_finish_err = ESP_OK;
|
||
|
esp_http_client_config_t config = {
|
||
|
.url = url_Buffer,
|
||
|
// .cert_pem = (char *)server_cert_pem_start,
|
||
|
.timeout_ms = 5000,
|
||
|
.keep_alive_enable = true,
|
||
|
};
|
||
|
|
||
|
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
|
||
|
};
|
||
|
|
||
|
esp_https_ota_handle_t https_ota_handle = NULL;
|
||
|
esp_err_t err = esp_https_ota_begin(&ota_config, &https_ota_handle);
|
||
|
int imageSize = esp_https_ota_get_image_size(https_ota_handle);
|
||
|
ESP_LOGI(TAG, "Sum Size is %d", imageSize);
|
||
|
if (err != ESP_OK)
|
||
|
{
|
||
|
ESP_LOGE(TAG, "ESP HTTPS OTA Begin failed");
|
||
|
char temp_Buffer[128] = {0};
|
||
|
// TODO:上报升级失败 再 复位
|
||
|
sprintf(temp_Buffer, "{\"ota\": -1}");
|
||
|
mqtt_UploadOTAInfo(temp_Buffer);
|
||
|
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||
|
esp_restart();
|
||
|
vTaskDelete(NULL);
|
||
|
}
|
||
|
|
||
|
esp_app_desc_t app_desc;
|
||
|
err = esp_https_ota_get_img_desc(https_ota_handle, &app_desc);
|
||
|
if (err != ESP_OK)
|
||
|
{
|
||
|
ESP_LOGE(TAG, "esp_https_ota_read_img_desc failed");
|
||
|
goto ota_end;
|
||
|
}
|
||
|
err = validate_image_header(&app_desc);
|
||
|
if (err != ESP_OK)
|
||
|
{
|
||
|
ESP_LOGE(TAG, "image header verification failed");
|
||
|
goto ota_end;
|
||
|
}
|
||
|
float progress = 0.0f;
|
||
|
char temp_Buffer[64] = {0};
|
||
|
while (1)
|
||
|
{
|
||
|
err = esp_https_ota_perform(https_ota_handle);
|
||
|
if (err != ESP_ERR_HTTPS_OTA_IN_PROGRESS)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
// esp_https_ota_perform returns after every read operation which gives user the ability to
|
||
|
// monitor the status of OTA upgrade by calling esp_https_ota_get_image_len_read, which gives length of image
|
||
|
// data read so far.
|
||
|
int currentSize = esp_https_ota_get_image_len_read(https_ota_handle);
|
||
|
// ESP_LOGI(TAG, "currentSize %d ,imageSize %d", currentSize, imageSize);
|
||
|
progress = ((float)currentSize / (float)imageSize) * 100.0f;
|
||
|
ESP_LOGI(TAG, "%.3f%%", progress);
|
||
|
sprintf(temp_Buffer, "{\"type\":\"COM\",\"ota_progress\":\"%.2f%%\"}", progress);
|
||
|
if (((int)progress % 5) == 0)
|
||
|
mqtt_UploadOTAProgress(temp_Buffer);
|
||
|
// xTimerReset(upgradeTimeOut_timer, 0);
|
||
|
}
|
||
|
|
||
|
if (esp_https_ota_is_complete_data_received(https_ota_handle) != true)
|
||
|
{
|
||
|
// the OTA image was not completely received and user can customise the response to this situation.
|
||
|
ESP_LOGE(TAG, "Complete data was not received.");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ota_finish_err = esp_https_ota_finish(https_ota_handle);
|
||
|
if ((err == ESP_OK) && (ota_finish_err == ESP_OK))
|
||
|
{
|
||
|
char Temp[] = {"{\"ota\":1}"};
|
||
|
send_ota_bin(otaSendBuffer, PACKET_SIZE, deviceUpgradeNum * PACKET_SIZE);
|
||
|
for (int i = 0; i < 5; i++)
|
||
|
{
|
||
|
com_SendData("\xA5\x5A\x01\x00\xFF", 5); // STM32部分的复位指令
|
||
|
vTaskDelay(pdMS_TO_TICKS(50));
|
||
|
}
|
||
|
ESP_LOGI(TAG, "ESP_HTTPS_OTA upgrade successful. Rebooting ...");
|
||
|
mqtt_UploadOTAInfo(Temp);
|
||
|
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||
|
esp_restart();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (ota_finish_err == ESP_ERR_OTA_VALIDATE_FAILED)
|
||
|
{
|
||
|
ESP_LOGE(TAG, "Image validation failed, image is corrupted");
|
||
|
}
|
||
|
ESP_LOGE(TAG, "ESP_HTTPS_OTA upgrade failed 0x%x", ota_finish_err);
|
||
|
vTaskDelete(NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ota_end:
|
||
|
esp_https_ota_abort(https_ota_handle);
|
||
|
ESP_LOGE(TAG, "ESP_HTTPS_OTA upgrade failed");
|
||
|
vTaskDelete(NULL);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @description: selfUpgrade
|
||
|
* @return {*}
|
||
|
*/
|
||
|
int countPkg = 0;
|
||
|
long sumSize = 0;
|
||
|
long algTotalSize = 0;
|
||
|
char upgradeFlag = 0;
|
||
|
unsigned char crcValue[4] = {0};
|
||
|
void selfUpgrade(void)
|
||
|
{
|
||
|
BaseType_t err = xSemaphoreTake(OTA_deviceUpgradeDoneSemaphore, portMAX_DELAY);
|
||
|
|
||
|
ESP_LOGI(TAG, "OTA example app_main start");
|
||
|
|
||
|
ESP_ERROR_CHECK(esp_event_handler_register(ESP_HTTPS_OTA_EVENT, ESP_EVENT_ANY_ID, &ota_event_handler, NULL));
|
||
|
|
||
|
#if defined(CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE)
|
||
|
/**
|
||
|
* We are treating successful WiFi connection as a checkpoint to cancel rollback
|
||
|
* process and mark newly updated firmware image as active. For production cases,
|
||
|
* please tune the checkpoint behavior per end application requirement.
|
||
|
*/
|
||
|
const esp_partition_t *running = esp_ota_get_running_partition();
|
||
|
esp_ota_img_states_t ota_state;
|
||
|
if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK)
|
||
|
{
|
||
|
if (ota_state == ESP_OTA_IMG_PENDING_VERIFY)
|
||
|
{
|
||
|
if (esp_ota_mark_app_valid_cancel_rollback() == ESP_OK)
|
||
|
{
|
||
|
ESP_LOGI(TAG, "App is valid, rollback cancelled successfully");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ESP_LOGE(TAG, "Failed to cancel rollback");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#if CONFIG_BT_ENABLED
|
||
|
/* Ensure to disable any WiFi power save mode, this allows best throughput
|
||
|
* and hence timings for overall OTA operation.
|
||
|
*/
|
||
|
esp_wifi_set_ps(WIFI_PS_NONE);
|
||
|
#else
|
||
|
/* WIFI_PS_MIN_MODEM is the default mode for WiFi Power saving. When both
|
||
|
* WiFi and Bluetooth are running, WiFI modem has to go down, hence we
|
||
|
* need WIFI_PS_MIN_MODEM. And as WiFi modem goes down, OTA download time
|
||
|
* increases.
|
||
|
*/
|
||
|
esp_wifi_set_ps(WIFI_PS_MIN_MODEM);
|
||
|
#endif // CONFIG_BT_ENABLED
|
||
|
|
||
|
xTaskCreate(&selfUpgradeTask, "selfUpgradeTask", 1024 * 12, NULL, 5, NULL);
|
||
|
}
|
||
|
//----------------------------------------------------------------------------
|
||
|
esp_err_t http_event_handler(esp_http_client_event_t *evt)
|
||
|
{
|
||
|
float progress = 0.0f;
|
||
|
char temp_Buffer[64] = {0};
|
||
|
switch (evt->event_id)
|
||
|
{
|
||
|
case HTTP_EVENT_ERROR:
|
||
|
printf("HTTP_EVENT_ERROR\n");
|
||
|
break;
|
||
|
case HTTP_EVENT_REDIRECT:
|
||
|
printf("HTTP_EVENT_REDIRECT\n");
|
||
|
break;
|
||
|
case HTTP_EVENT_ON_CONNECTED:
|
||
|
sumSize = 0;
|
||
|
countPkg = 0;
|
||
|
ota_Fatfs_Init();
|
||
|
printf("HTTP_EVENT_ON_CONNECTED\n");
|
||
|
break;
|
||
|
case HTTP_EVENT_HEADER_SENT:
|
||
|
printf("HTTP_EVENT_HEADER_SENT\n");
|
||
|
break;
|
||
|
case HTTP_EVENT_ON_HEADER:
|
||
|
printf("HTTP_EVENT_ON_HEADER, key=%s, value=%s\n", evt->header_key, evt->header_value);
|
||
|
if (strcmp(evt->header_key, "Content-Length") == 0)
|
||
|
algTotalSize = atoi(evt->header_value);
|
||
|
break;
|
||
|
case HTTP_EVENT_ON_DATA:
|
||
|
countPkg++;
|
||
|
sumSize += evt->data_len;
|
||
|
if (sumSize < algTotalSize)
|
||
|
CRC32_Update(&ota_ctx, evt->data, evt->data_len);
|
||
|
else if (sumSize == algTotalSize)
|
||
|
{
|
||
|
// 获取结尾校验相关
|
||
|
ota_ctx.rec = 0;
|
||
|
ESP_LOGI(TAG, "Last Packet...");
|
||
|
CRC32_Update(&ota_ctx, evt->data, evt->data_len - 4);
|
||
|
memcpy(&ota_ctx.rec, evt->data + (evt->data_len - 4), 4);
|
||
|
ESP_LOGI(TAG, "ota_ctx.rec : %lx", ota_ctx.rec);
|
||
|
}
|
||
|
// printf("HTTP_EVENT_ON_DATA, len=%d count %d sumSize %ld \r\n",
|
||
|
// evt->data_len, countPkg, sumSize);
|
||
|
if (!esp_http_client_is_chunked_response(evt->client))
|
||
|
{
|
||
|
// Write received data to a file
|
||
|
FILE *f = fopen(FILE_PATH, "a");
|
||
|
if (f == NULL)
|
||
|
{
|
||
|
printf("Failed to open file for writing\n");
|
||
|
return ESP_FAIL;
|
||
|
}
|
||
|
fwrite(evt->data, 1, evt->data_len, f);
|
||
|
fclose(f);
|
||
|
}
|
||
|
progress = ((float)sumSize / (float)algTotalSize) * 100.0f;
|
||
|
ESP_LOGI(TAG, "%.3f%%", progress);
|
||
|
sprintf(temp_Buffer, "{\"type\":\"DL\",\"ota_progress\":\"%.2f%%\"}", progress);
|
||
|
if (((int)progress % 5) == 0)
|
||
|
mqtt_UploadOTAProgress(temp_Buffer);
|
||
|
break;
|
||
|
case HTTP_EVENT_ON_FINISH:
|
||
|
printf("HTTP_EVENT_ON_FINISH\n");
|
||
|
CRC32_Final(&ota_ctx, crcValue);
|
||
|
printf(" ota_ctx : %lx\n", ota_ctx.crc);
|
||
|
// if (ota_ctx.crc == ota_ctx.rec)
|
||
|
if (1)
|
||
|
{
|
||
|
upgradeFlag = 1; // 需要进行升级算法
|
||
|
ESP_LOGI(TAG, "File Check Success");
|
||
|
FILE *f = fopen(FILE_PATH, "rb");
|
||
|
printf("Done Size :%ld\n", fsize(f));
|
||
|
fclose(f);
|
||
|
ota_Fatfs_deinit();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
upgradeFlag = 0; // 不需要进行升级算法
|
||
|
ESP_LOGE(TAG, "File Check Fail");
|
||
|
// TODO:上报升级失败 再 复位
|
||
|
sprintf(temp_Buffer, "{\"ota\": -1}");
|
||
|
mqtt_UploadOTAInfo(temp_Buffer);
|
||
|
esp_restart();
|
||
|
}
|
||
|
break;
|
||
|
case HTTP_EVENT_DISCONNECTED:
|
||
|
printf("HTTP_EVENT_DISCONNECTED\n");
|
||
|
break;
|
||
|
}
|
||
|
return ESP_OK;
|
||
|
}
|
||
|
|
||
|
void download_file_task(void *pvParameters)
|
||
|
{
|
||
|
char temp_Buffer[128] = {0};
|
||
|
|
||
|
// TODO: 如果之前就有文件则不进行下载 判断升级正常之后 重新进行升级流程
|
||
|
if (Ymodem_checkFile() == 1)
|
||
|
goto file_exist;
|
||
|
#if 1
|
||
|
char url_Buffer[128] = {0};
|
||
|
memcpy(url_Buffer, ota_info.url, sizeof(ota_info.url));
|
||
|
strcat(url_Buffer, "/");
|
||
|
strcat(url_Buffer, ota_info.mattressPath);
|
||
|
ESP_LOGI(TAG, "url : %s", url_Buffer);
|
||
|
esp_http_client_config_t config = {
|
||
|
.url = url_Buffer,
|
||
|
.event_handler = http_event_handler,
|
||
|
};
|
||
|
esp_http_client_handle_t client = esp_http_client_init(&config);
|
||
|
// Set up file to store the downloaded data
|
||
|
ota_Fatfs_Init();
|
||
|
FILE *f = fopen(FILE_PATH, "w+");
|
||
|
printf("Empty Size :%ld\n", fsize(f));
|
||
|
if (f == NULL)
|
||
|
{
|
||
|
printf("Failed to create file for writing\n");
|
||
|
remove(FILE_PATH); // 移除文件
|
||
|
return;
|
||
|
}
|
||
|
fclose(f);
|
||
|
ota_Fatfs_deinit();
|
||
|
esp_err_t err = esp_http_client_perform(client);
|
||
|
if (err == ESP_OK && upgradeFlag == 1)
|
||
|
{
|
||
|
printf("File downloaded successfully\n");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
printf("File download failed\n");
|
||
|
char temp_Buffer[128] = {0};
|
||
|
// TODO:上报升级失败 再 复位
|
||
|
sprintf(temp_Buffer, "{\"ota\": -1}");
|
||
|
mqtt_UploadOTAInfo(temp_Buffer);
|
||
|
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||
|
esp_restart();
|
||
|
}
|
||
|
esp_http_client_close(client);
|
||
|
esp_http_client_cleanup(client);
|
||
|
#else
|
||
|
upgradeFlag = 1;
|
||
|
algTotalSize = 214796;
|
||
|
#endif
|
||
|
file_exist:
|
||
|
printf("File DL Done\r\n");
|
||
|
while (1)
|
||
|
{
|
||
|
const TickType_t xFrequency = 200;
|
||
|
if (upgradeFlag)
|
||
|
{
|
||
|
printf("Ready Ymodem Upgrade\n");
|
||
|
// xTimerStart(upgradeTimeOut_timer, 0);
|
||
|
// TODO: 增加文件大小的存储 NVS
|
||
|
ota_info.mattressBinSize = algTotalSize;
|
||
|
ESP_LOGI(TAG, "mattressBinSize :%ld ", ota_info.mattressBinSize);
|
||
|
// nvs_write_otaInfo(&ota_info, sizeof(ota_info));
|
||
|
// TODO: 升级增加 准备工序
|
||
|
send_GoIntoOTA();
|
||
|
send_ota_Info();
|
||
|
// 发送
|
||
|
send_ota_Upgrade();
|
||
|
// xTimerStop(upgradeTimeOut_timer, 0);
|
||
|
// 发生设备升级完成状态指示二值信号量
|
||
|
xSemaphoreGive(OTA_deviceUpgradeDoneSemaphore);
|
||
|
vTaskDelete(NULL);
|
||
|
}
|
||
|
// vTaskDelay(pdMS_TO_TICKS(25));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deviceUpgrade(void)
|
||
|
{
|
||
|
CRC32_Init(&ota_ctx);
|
||
|
xTaskCreate(&download_file_task, "download_file_task", 4096, NULL, 5, NULL);
|
||
|
}
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
void upgrade_task(void *arg)
|
||
|
{
|
||
|
uint32_t KeepAlive = 0;
|
||
|
while (1)
|
||
|
{
|
||
|
KeepAlive++;
|
||
|
BaseType_t err = xSemaphoreTake(OTA_startSemaphore, 50);
|
||
|
if (err == pdPASS)
|
||
|
{
|
||
|
ESP_LOGI(TAG, "---------------OTA Start---------------\r\n");
|
||
|
// 如果刚上电就升级
|
||
|
if (xTimerIsTimerActive(NetConfig_timer) == pdTRUE)
|
||
|
{
|
||
|
xTimerStop(NetConfig_timer, 0);
|
||
|
vTaskDelete(BLE_NetTasks_TaskHandle); // 关闭配网线程
|
||
|
vTaskDelete(ParseTaskHandle); // 关闭解析线程
|
||
|
}
|
||
|
// 长时间运行的线程
|
||
|
if (esp_task_wdt_status(Alg_TaskHandle) == ESP_OK)
|
||
|
esp_task_wdt_delete(Alg_TaskHandle);
|
||
|
vTaskSuspend(MQTT_TaskHandle);
|
||
|
// vTaskDelete(Alg_TaskHandle);
|
||
|
// 其他设备升级 OTA
|
||
|
deviceUpgrade();
|
||
|
|
||
|
// Test: xSemaphoreGive(OTA_deviceUpgradeDoneSemaphore);
|
||
|
// 自身 OTA
|
||
|
selfUpgrade();
|
||
|
}
|
||
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||
|
ESP_LOGI(TAG, "KeepAlive = %ld, arg = %s", KeepAlive, (char *)arg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CRC32_Init(CRC32_CTX *ctx)
|
||
|
{
|
||
|
ctx->crc = 0xFFFFFFFFL;
|
||
|
}
|
||
|
|
||
|
void CRC32_Update(CRC32_CTX *ctx, const unsigned char *data, size_t len)
|
||
|
{
|
||
|
for (size_t i = 0; i < len; i++)
|
||
|
{
|
||
|
ctx->crc = (ctx->crc >> 8) ^ crc32_table[(ctx->crc & 0xFF) ^ *data++];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CRC32_Final(CRC32_CTX *ctx, unsigned char *md)
|
||
|
{
|
||
|
ctx->crc ^= 0xFFFFFFFFUL;
|
||
|
*md++ = (ctx->crc & 0xFF000000UL) >> 24;
|
||
|
*md++ = (ctx->crc & 0x00FF0000UL) >> 16;
|
||
|
*md++ = (ctx->crc & 0x0000FF00UL) >> 8;
|
||
|
*md++ = (ctx->crc & 0x000000FFUL);
|
||
|
}
|
||
|
|
||
|
long fsize(FILE *fp)
|
||
|
{
|
||
|
long n;
|
||
|
fpos_t fpos; // 当前位置
|
||
|
fgetpos(fp, &fpos); // 获取当前位置
|
||
|
fseek(fp, 0, SEEK_END);
|
||
|
n = ftell(fp);
|
||
|
fsetpos(fp, &fpos); // 恢复之前的位置
|
||
|
return n;
|
||
|
}
|
||
|
|
||
|
void list_dir(const char *path)
|
||
|
{
|
||
|
DIR *dir;
|
||
|
struct dirent *entry;
|
||
|
printf(" ------------------------ \n");
|
||
|
if ((dir = opendir(path)) == NULL)
|
||
|
{
|
||
|
perror("opendir() error\n");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
puts("contents of directory:");
|
||
|
while ((entry = readdir(dir)) != NULL)
|
||
|
{
|
||
|
printf(" %s\n", entry->d_name);
|
||
|
}
|
||
|
closedir(dir);
|
||
|
}
|
||
|
printf(" ------------------------ \n");
|
||
|
}
|
||
|
|
||
|
char Ymodem_checkFile(void)
|
||
|
{
|
||
|
ota_Fatfs_Init();
|
||
|
list_dir("/spiflash");
|
||
|
// --------------------------------------------------------
|
||
|
// TODO :先读取有没有文件 大小是否满足要求
|
||
|
uint32_t fileSize = 0;
|
||
|
FILE *fp = fopen(FILE_PATH, "a");
|
||
|
fileSize = fsize(fp);
|
||
|
printf("File Size :%ld\n", fileSize);
|
||
|
fclose(fp);
|
||
|
ota_Fatfs_deinit();
|
||
|
if (fileSize == ota_info.mattressBinSize && fileSize >= 200000)
|
||
|
{
|
||
|
// 检测文件大小是否满足要求
|
||
|
upgradeFlag = 1;
|
||
|
algTotalSize = fileSize;
|
||
|
// 是 :跳过下载文件流程
|
||
|
return 1;
|
||
|
// 否 :擦除文件 继续下载
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ota_Fatfs_Init();
|
||
|
remove(FILE_PATH); // 升级完成 移除文件
|
||
|
ota_Fatfs_deinit();
|
||
|
}
|
||
|
return 0;
|
||
|
// --------------------------------------------------------
|
||
|
}
|
||
|
|
||
|
#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
|
||
|
void dump_hex(const uint8_t *buf, uint32_t size)
|
||
|
{
|
||
|
int i, j;
|
||
|
|
||
|
for (i = 0; i < size; i += 16)
|
||
|
{
|
||
|
printf("%08X: ", i);
|
||
|
|
||
|
for (j = 0; j < 16; j++)
|
||
|
{
|
||
|
if (i + j < size)
|
||
|
{
|
||
|
printf("%02X ", buf[i + j]);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
printf(" ");
|
||
|
}
|
||
|
}
|
||
|
printf(" ");
|
||
|
|
||
|
for (j = 0; j < 16; j++)
|
||
|
{
|
||
|
if (i + j < size)
|
||
|
{
|
||
|
printf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
|
||
|
}
|
||
|
}
|
||
|
printf("\n");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void send_GoIntoOTA(void)
|
||
|
{
|
||
|
char buff[9];
|
||
|
uint32_t crc;
|
||
|
EventBits_t Event;
|
||
|
|
||
|
buff[0] = 0xA5;
|
||
|
buff[1] = 0x5A;
|
||
|
buff[2] = 0x05;
|
||
|
buff[3] = 0x00;
|
||
|
buff[4] = 0x10; // 控制字
|
||
|
|
||
|
crc = My_crc32((unsigned char *)buff, 5);
|
||
|
buff[5] = (uint8_t)crc;
|
||
|
buff[6] = (uint8_t)(crc >> 8);
|
||
|
buff[7] = (uint8_t)(crc >> 16);
|
||
|
buff[8] = (uint8_t)(crc >> 24);
|
||
|
|
||
|
for (int i = 0; i < 30; i++)
|
||
|
{
|
||
|
com_SendData("\xA5\x5A\x01\x00\x10", 5);
|
||
|
Event = xEventGroupWaitBits(xComEventGroup, COM_OTA_MSG_OK | COM_OTA_MSG_DONE | COM_OTA_MSG_RESEND,
|
||
|
pdTRUE, pdFALSE, (150 / portTICK_PERIOD_MS));
|
||
|
if (Event & COM_OTA_MSG_OK)
|
||
|
{
|
||
|
ESP_LOGI(TAG, "GO INTO OTA COM_OTA_MSG_OK resend: %d", i);
|
||
|
return;
|
||
|
}
|
||
|
else if (Event & COM_OTA_MSG_RESEND)
|
||
|
ESP_LOGI(TAG, "GO INTO OTA COM_OTA_MSG_RESEND resend: %d", i);
|
||
|
else
|
||
|
ESP_LOGI(TAG, "GO INTO OTA COM_OTA_MSG_DONE resend: %d", i);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void send_ota_Info(void)
|
||
|
{
|
||
|
uint32_t crc;
|
||
|
char buff[17], i;
|
||
|
EventBits_t Event;
|
||
|
|
||
|
buff[0] = 0xA5;
|
||
|
buff[1] = 0x5A;
|
||
|
buff[2] = 0x0D;
|
||
|
buff[3] = 0x00;
|
||
|
buff[4] = 0x11; // 控制字
|
||
|
|
||
|
buff[5] = ota_info.version[0];
|
||
|
buff[6] = ota_info.version[1];
|
||
|
buff[7] = ota_info.version[2];
|
||
|
buff[8] = ota_info.version[3];
|
||
|
|
||
|
buff[9] = (uint8_t)ota_info.mattressBinSize;
|
||
|
buff[10] = (uint8_t)(ota_info.mattressBinSize >> 8);
|
||
|
buff[11] = (uint8_t)(ota_info.mattressBinSize >> 16);
|
||
|
buff[12] = (uint8_t)(ota_info.mattressBinSize >> 24);
|
||
|
|
||
|
crc = My_crc32((unsigned char *)buff, 13);
|
||
|
buff[13] = (uint8_t)crc;
|
||
|
buff[14] = (uint8_t)(crc >> 8);
|
||
|
buff[15] = (uint8_t)(crc >> 16);
|
||
|
buff[16] = (uint8_t)(crc >> 24);
|
||
|
|
||
|
for (i = 0; i < 25; i++)
|
||
|
{
|
||
|
com_SendData((const char *)buff, 17);
|
||
|
Event = xEventGroupWaitBits(xComEventGroup, COM_OTA_MSG_OK | COM_OTA_MSG_DONE | COM_OTA_MSG_RESEND,
|
||
|
pdTRUE, pdFALSE, (150 / portTICK_PERIOD_MS));
|
||
|
if (Event & COM_OTA_MSG_OK)
|
||
|
{
|
||
|
ESP_LOGI(TAG, "GO INTO OTA COM_OTA_MSG_OK resend: %d", i);
|
||
|
return;
|
||
|
}
|
||
|
else if (Event & COM_OTA_MSG_RESEND)
|
||
|
ESP_LOGI(TAG, "GO INTO OTA COM_OTA_MSG_RESEND resend: %d", i);
|
||
|
else
|
||
|
ESP_LOGI(TAG, "GO INTO OTA COM_OTA_MSG_DONE resend: %d", i);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static char send_ota_bin(char *data, int len, uint32_t packetNum) // 数据的长度(不是一帧的长度)
|
||
|
{
|
||
|
char buff[len + 13];
|
||
|
EventBits_t Event;
|
||
|
uint32_t crc;
|
||
|
int i;
|
||
|
|
||
|
memset(buff, 0, sizeof(buff));
|
||
|
|
||
|
buff[0] = 0xA5;
|
||
|
buff[1] = 0x5A;
|
||
|
buff[2] = (uint8_t)(len + 9);
|
||
|
buff[3] = (uint8_t)((len + 9) >> 8);
|
||
|
buff[4] = 0x12; // 控制字
|
||
|
/*第几包*/
|
||
|
buff[5] = (uint8_t)(packetNum);
|
||
|
buff[6] = (uint8_t)(packetNum >> 8);
|
||
|
buff[7] = (uint8_t)(packetNum >> 16);
|
||
|
buff[8] = (uint8_t)(packetNum >> 24);
|
||
|
for (i = 0; i < len; i++)
|
||
|
buff[9 + i] = data[i];
|
||
|
|
||
|
crc = My_crc32((unsigned char *)buff, len + 9);
|
||
|
buff[9 + len] = (uint8_t)crc;
|
||
|
buff[9 + len + 1] = (uint8_t)(crc >> 8);
|
||
|
buff[9 + len + 2] = (uint8_t)(crc >> 16);
|
||
|
buff[9 + len + 3] = (uint8_t)(crc >> 24);
|
||
|
|
||
|
ESP_LOGD(TAG, " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! BinCurrentNo: %ld !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", packetNum);
|
||
|
for (i = 0; i < 5; i++)
|
||
|
{
|
||
|
com_SendData(buff, len + 13);
|
||
|
ESP_LOGI(TAG, " packetNum: %ld", packetNum);
|
||
|
Event = xEventGroupWaitBits(xComEventGroup, COM_OTA_MSG_OK | COM_OTA_MSG_DONE | COM_OTA_MSG_RESEND,
|
||
|
pdTRUE, pdFALSE, (100 / portTICK_PERIOD_MS));
|
||
|
if (Event & COM_OTA_MSG_OK)
|
||
|
{
|
||
|
ESP_LOGI(TAG, "COM_OTA_MSG_OK,OTAInfo BinCurrentByte: %ld", packetNum);
|
||
|
return 1;
|
||
|
}
|
||
|
else if (Event & COM_OTA_MSG_RESEND)
|
||
|
{
|
||
|
ESP_LOGI(TAG, "COM_OTA_MSG_RESEND,OTAInfo resend: %d", i);
|
||
|
return 0;
|
||
|
}
|
||
|
else if (Event & COM_OTA_MSG_DONE)
|
||
|
{
|
||
|
ESP_LOGI(TAG, "COM_OTA_MSG_DONE,OTAInfo resend: %d", i);
|
||
|
ESP_LOGI(TAG, "OTA bin sent over BinCurrentByte: %ld", packetNum);
|
||
|
return 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ESP_LOGI(TAG, "OTAflag=0,OTAInfo resend: %d", i);
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
void send_ota_Upgrade(void)
|
||
|
{
|
||
|
FILE *f = NULL;
|
||
|
char comStatus = 0;
|
||
|
float progress = 0.0f;
|
||
|
char temp_Buffer[128] = {0};
|
||
|
|
||
|
uint32_t lessSize = 0;
|
||
|
uint32_t packet_num = 0;
|
||
|
uint32_t currentSendSize = 0;
|
||
|
lessSize = ota_info.mattressBinSize % PACKET_SIZE;
|
||
|
packet_num = ota_info.mattressBinSize / PACKET_SIZE;
|
||
|
ESP_LOGI(TAG, "packet_num %ld\r\n", packet_num);
|
||
|
ESP_LOGI(TAG, "lessSize %ld\r\n", lessSize);
|
||
|
LastPacketLessSize = lessSize;
|
||
|
ota_Fatfs_Init();
|
||
|
ESP_LOGI(TAG, "------------------------- Start -------------------------");
|
||
|
for (int i = 0; i < packet_num; i++)
|
||
|
{
|
||
|
memset(otaSendBuffer, 0, sizeof(otaSendBuffer));
|
||
|
ESP_LOGI(TAG, "------packet_num %ld\r\n", packet_num);
|
||
|
ESP_LOGI(TAG, "------lessSize %ld\r\n", lessSize);
|
||
|
// xTimerReset(upgradeTimeOut_timer, 0);
|
||
|
// TODO:读取文件
|
||
|
f = fopen(FILE_PATH, "r");
|
||
|
if (f == NULL)
|
||
|
{
|
||
|
i = 0;
|
||
|
continue;
|
||
|
}
|
||
|
ESP_LOGI(TAG, "Write pack : %d ", i);
|
||
|
fseek(f, i * PACKET_SIZE, SEEK_SET);
|
||
|
fread(otaSendBuffer, 1, PACKET_SIZE, f);
|
||
|
// dump_hex((uint8_t *)otaSendBuffer, PACKET_SIZE);
|
||
|
vTaskDelay(pdMS_TO_TICKS(250));
|
||
|
// comStatus = 1;
|
||
|
comStatus = send_ota_bin(otaSendBuffer, PACKET_SIZE, i * PACKET_SIZE);
|
||
|
fclose(f);
|
||
|
if (comStatus != 1)
|
||
|
{
|
||
|
i--;
|
||
|
continue;
|
||
|
}
|
||
|
currentSendSize = (i + 1) * PACKET_SIZE;
|
||
|
progress = ((float)currentSendSize / (float)ota_info.mattressBinSize) * 100.0f;
|
||
|
ESP_LOGI(TAG, "%.3f%%", progress);
|
||
|
sprintf(temp_Buffer, "{\"type\":\"ALG\",\"ota_progress\":\"%.2f%%\"}", progress);
|
||
|
if (((int)progress % 5) == 0)
|
||
|
mqtt_UploadOTAProgress(temp_Buffer);
|
||
|
}
|
||
|
// TODO:读取文件
|
||
|
f = fopen(FILE_PATH, "r");
|
||
|
// 最后一包
|
||
|
fseek(f, packet_num * PACKET_SIZE, SEEK_SET);
|
||
|
fread(otaSendBuffer, 1, lessSize, f);
|
||
|
vTaskDelay(pdMS_TO_TICKS(500));
|
||
|
fclose(f);
|
||
|
deviceUpgradeNum = packet_num;
|
||
|
memcpy(LastPacketBuffer, otaSendBuffer, LastPacketLessSize);
|
||
|
//--------------------------------------------------------------- 测试
|
||
|
// send_ota_bin(otaSendBuffer, PACKET_SIZE, packet_num * PACKET_SIZE);
|
||
|
// for (int i = 0; i < 5; i++)
|
||
|
// {
|
||
|
// com_SendData("\xA5\x5A\x01\x00\xFF", 5); // STM32部分的复位指令
|
||
|
// vTaskDelay(pdMS_TO_TICKS(50));
|
||
|
// }
|
||
|
//---------------------------------------------------------------
|
||
|
sprintf(temp_Buffer, "{\"type\":\"ALG\",\"ota_progress\":\"100%%\"}");
|
||
|
mqtt_UploadOTAProgress(temp_Buffer);
|
||
|
ESP_LOGI(TAG, "------------------------- End -------------------------");
|
||
|
vTaskDelay(50);
|
||
|
remove(FILE_PATH); // 升级完成 移除文件
|
||
|
ota_Fatfs_deinit();
|
||
|
}
|