4G_module/examples/fota/src/cm_demo_fota.c

761 lines
28 KiB
C
Raw Normal View History

2024-09-02 17:54:29 +08:00
/*********************************************************
* @file cm_demo_fota.c
* @brief OpenCPU FOTA示例
* Copyright (c) 2022 China Mobile IOT.
* All rights reserved.
* created by WangPeng 2022/8/29
********************************************************/
#include "stdio.h"
#include "string.h"
#include "cm_fota.h"
#include "cm_sys.h"
#include "cm_os.h"
#include "cm_fs.h"
#include "cm_http.h"
#include "cm_rtc.h"
#include "md.h"
#include "base64.h"
#include "cJSON.h"
#include "cm_fs.h"
#include "cm_demo_uart.h"
/* 产品ID平台创建产品后由平台分配的IDhttps://open.iot.10086.cn/console/product/own。此处为示例数据实际使用须据实修改 */
static char OneNET_pid[16] = "07av4iD9CC";
/* 用户ID平台网页中用户中心-账户信息https://open.iot.10086.cn/account/profile中查询到的用户ID。此处为示例数据实际使用须据实修改 */
static char OneNET_userid[16] = "148865";
/* 设备名称平台添加设备时添加设备的设备名称https://open.iot.10086.cn/console/device/manage/devs。此处为示例数据实际使用须据实修改 */
static char OneNET_devname[16] = "ML307A-DSLN";
/* 用户Accesskey平台网页中用户中心-访问权限https://open.iot.10086.cn/account/access中查询到的用户Accesskey。此处为示例数据实际使用须据实修改 */
static char OneNET_userkey[128] = "xxxxxxx9acyjz4upifwnvbwuETqplZ0DEJ+9jTj2jWD0GzrDSrLu7/oqLmKIZk18SUPu6vQZDsaOrwtPethioA==";
/* 模组OneNET软件版本号平台添加差分升级包时填写的待升级版本。此处为示例数据实际使用须据实修改 */
static char OneNET_version[16] = "1.0";
static void __cm_fota_cb(cm_fota_error_e error)
{
cm_demo_printf("[FOTA] error code is %d\n", error);
}
/**
* @brief OneNET版本号
*
* @return
* = 0 - \n
* = -1 -
*
* @details 使OneNET接口地址为http://ota.heclouds.com/fuse-ota/{pro_id}/{dev_name}/version \n
* https://open.iot.10086.cn/doc/v5/fuse/detail/1454 \n
* 使使https://open.iot.10086.cn/doc/v5/fuse/detail/1464 \n
* OneNET平台会持续迭代demo示例在2023年6月5日可以正常使用OneNET FOTA功能OneNET平台版本迭代后还可使用 \n
*
*/
static int32_t __cm_onenet_fota_report_ver(void)
{
int32_t ret = -1;
cm_httpclient_handle_t client = NULL;
ret = cm_httpclient_create((const uint8_t *)"http://ota.heclouds.com", NULL, &client);
if (CM_HTTP_RET_CODE_OK != ret || NULL == client)
{
cm_log_printf(0, "[OneNET] cm_httpclient_create() error!\r\n");
return -1;
}
cm_httpclient_cfg_t client_cfg;
client_cfg.ssl_enable = false;
client_cfg.ssl_id = 0;
client_cfg.cid = 0;
client_cfg.conn_timeout = HTTPCLIENT_CONNECT_TIMEOUT_DEFAULT;
client_cfg.rsp_timeout = HTTPCLIENT_WAITRSP_TIMEOUT_DEFAULT;
client_cfg.dns_priority = 0;
ret = cm_httpclient_set_cfg(client, client_cfg);
char path[128] = {0};
char header[256] = {0};
char message[128] = {0};
char content[64] = {0};
unsigned char base64_tmp[128] = {0};
int32_t et = cm_rtc_get_current_time() + 2 * 24 * 60 * 60;
sprintf(path, "/fuse-ota");
sprintf(path + strlen((char*)path), "/%s/%s/version", OneNET_pid, OneNET_devname);
/* 新接口必须要上报MCU版本号OpenCPU开发通常不涉及MCU故s_version传入任意值 */
sprintf(content, "{\"s_version\": \"%s\",\"f_version\": \"%s\"}", "MCU1.0", OneNET_version);
sprintf(header, "%ld\nsha1\nuserid/%s\n2022-05-01", et, OneNET_userid);
int base64_len = 0;
mbedtls_base64_decode((unsigned char*)base64_tmp, 128, (unsigned int*)&base64_len, (const unsigned char*)OneNET_userkey, strlen(OneNET_userkey));
mbedtls_md_context_t ctx = {0};
const mbedtls_md_info_t *info = NULL;
mbedtls_md_init(&ctx);
info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
mbedtls_md_setup(&ctx, info, 1);
mbedtls_md_hmac_starts(&ctx, (void *)base64_tmp, base64_len);
mbedtls_md_hmac_update(&ctx, (void *)header, strlen(header));
mbedtls_md_hmac_finish(&ctx, (void *)message);
mbedtls_md_free(&ctx);
mbedtls_base64_encode((unsigned char*)base64_tmp, 128, (unsigned int*)&base64_len, (const unsigned char*)message, 20);//SHA-1 算法输出为20字节
sprintf(header, "Authorization: version=2022-05-01&res=userid%s%s&et=%ld&method=sha1&sign=", "%2F", OneNET_userid, et);
for(int i = 0; i < base64_len; i++)
{
if((base64_tmp[i] == '+') || (base64_tmp[i] == '/') || (base64_tmp[i] == '='))
{
sprintf(header+strlen(header), "%s", (base64_tmp[i] == '+')?("%2B"):((base64_tmp[i] == '/')?("%2F"):("%3D")));
}
else
{
sprintf(header+strlen(header), "%c", base64_tmp[i]);
}
}
sprintf(header + strlen(header), "\r\nContent-Type:%s\r\n", "application/json");
cm_httpclient_sync_response_t response = {};
cm_httpclient_sync_param_t param = {HTTPCLIENT_REQUEST_POST, (const uint8_t *)path, strlen(content), (uint8_t *)content};
cm_httpclient_specific_header_set(client, (uint8_t *)header, strlen(header));
ret = cm_httpclient_sync_request(client, param, &response);
if (CM_HTTP_RET_CODE_OK != ret || NULL == client)
{
cm_log_printf(0, "[OneNET] cm_httpclient_sync_request() error! ret is %d\r\n", ret);
cm_httpclient_specific_header_free(client);
cm_httpclient_terminate(client);
cm_httpclient_delete(client);
client = NULL;
return -1;
}
else
{
cm_log_printf(0, "%s\r\n", response.response_content);
}
cJSON *root = cJSON_Parse((const char *)response.response_content);
cJSON *code = cJSON_GetObjectItem(root, "code");
if(code == NULL)
{
cJSON_Delete(root);
cm_log_printf(0, "[OneNET] HTTP GET DATA ERROR\r\n");
cm_httpclient_specific_header_free(client);
cm_httpclient_terminate(client);
cm_httpclient_delete(client);
client = NULL;
return -1;
}
if(0 == code->valueint)
{
cJSON_Delete(root);
cm_httpclient_specific_header_free(client);
cm_httpclient_terminate(client);
cm_httpclient_delete(client);
client = NULL;
return 0;
}
else
{
cm_log_printf(0, "[OneNET] REPORT VERSION ERROR [%d]\r\n", code->valueint);
cJSON_Delete(root);
cm_httpclient_specific_header_free(client);
cm_httpclient_terminate(client);
cm_httpclient_delete(client);
client = NULL;
return -1;
}
}
/**
* @brief
*
* @return
* = 0 - \n
* = -1 -
*
* @details 使OneNET接口地址为http://ota.heclouds.com/fuse-ota/{pro_id}/{dev_name}/check \n
* https://open.iot.10086.cn/doc/v5/fuse/detail/1447 \n
* 使使https://open.iot.10086.cn/doc/v5/fuse/detail/1464 \n
* OneNET平台会持续迭代demo示例在2023年6月5日可以正常使用OneNET FOTA功能OneNET平台版本迭代后还可使用 \n
*
*/
static int32_t __cm_onenet_fota_check_upgrade_task(void)
{
int32_t ret = -1;
cm_httpclient_handle_t client = NULL;
ret = cm_httpclient_create((const uint8_t *)"http://ota.heclouds.com", NULL, &client);
if (CM_HTTP_RET_CODE_OK != ret || NULL == client)
{
cm_log_printf(0, "[OneNET] cm_httpclient_create() error!\r\n");
return -1;
}
cm_httpclient_cfg_t client_cfg;
client_cfg.ssl_enable = false;
client_cfg.ssl_id = 0;
client_cfg.cid = 0;
client_cfg.conn_timeout = HTTPCLIENT_CONNECT_TIMEOUT_DEFAULT;
client_cfg.rsp_timeout = HTTPCLIENT_WAITRSP_TIMEOUT_DEFAULT;
client_cfg.dns_priority = 0;
ret = cm_httpclient_set_cfg(client, client_cfg);
char path[128] = {0};
char header[256] = {0};
char message[128] = {0};
unsigned char base64_tmp[128] = {0};
int32_t et = cm_rtc_get_current_time() + 2 * 24 * 60 * 60;
sprintf(path, "/fuse-ota");
sprintf(path + strlen((char*)path), "/%s/%s/check?type=1&version=%s", OneNET_pid, OneNET_devname, OneNET_version);
sprintf(header, "%ld\nsha1\nuserid/%s\n2022-05-01", et, OneNET_userid);
int base64_len = 0;
mbedtls_base64_decode((unsigned char*)base64_tmp, 128, (unsigned int*)&base64_len, (const unsigned char*)OneNET_userkey, strlen(OneNET_userkey));
mbedtls_md_context_t ctx = {0};
const mbedtls_md_info_t *info = NULL;
mbedtls_md_init(&ctx);
info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
mbedtls_md_setup(&ctx, info, 1);
mbedtls_md_hmac_starts(&ctx, (void *)base64_tmp, base64_len);
mbedtls_md_hmac_update(&ctx, (void *)header, strlen(header));
mbedtls_md_hmac_finish(&ctx, (void *)message);
mbedtls_md_free(&ctx);
mbedtls_base64_encode((unsigned char*)base64_tmp, 128, (unsigned int*)&base64_len, (const unsigned char*)message, 20);//SHA-1 算法输出为20字节
sprintf(header, "Authorization: version=2022-05-01&res=userid%s%s&et=%ld&method=sha1&sign=", "%2F", OneNET_userid, et);
for(int i = 0; i < base64_len; i++)
{
if((base64_tmp[i] == '+') || (base64_tmp[i] == '/') || (base64_tmp[i] == '='))
{
sprintf(header+strlen(header), "%s", (base64_tmp[i] == '+')?("%2B"):((base64_tmp[i] == '/')?("%2F"):("%3D")));
}
else
{
sprintf(header+strlen(header), "%c", base64_tmp[i]);
}
}
sprintf(header + strlen(header), "\r\nContent-Type:%s\r\n", "application/json");
cm_httpclient_sync_response_t response = {};
cm_httpclient_sync_param_t param = {HTTPCLIENT_REQUEST_GET, (const uint8_t *)path, 0, NULL};
cm_httpclient_specific_header_set(client, (uint8_t *)header, strlen(header));
ret = cm_httpclient_sync_request(client, param, &response);
if (CM_HTTP_RET_CODE_OK != ret || NULL == client)
{
cm_log_printf(0, "[OneNET] cm_httpclient_sync_request() error! ret is %d\r\n", ret);
cm_httpclient_specific_header_free(client);
cm_httpclient_terminate(client);
cm_httpclient_delete(client);
client = NULL;
return -1;
}
else
{
cm_log_printf(0, "%s\r\n", response.response_content);
}
cJSON *root = cJSON_Parse((const char *)response.response_content);
cJSON *code = cJSON_GetObjectItem(root, "code");
if(code == NULL)
{
cJSON_Delete(root);
cm_log_printf(0, "[OneNET] HTTP GET DATA ERROR\r\n");
cm_httpclient_specific_header_free(client);
cm_httpclient_terminate(client);
cm_httpclient_delete(client);
client = NULL;
return -1;
}
if(0 == code->valueint)
{
cJSON *data = cJSON_GetObjectItem(root, "data");
if(data == NULL)
{
cm_log_printf(0, "[OneNET] HTTP GET data ERROR\r\n");
cJSON_Delete(root);
cm_httpclient_specific_header_free(client);
cm_httpclient_terminate(client);
cm_httpclient_delete(client);
client = NULL;
return -1;
}
cJSON *tid = cJSON_GetObjectItem(data, "tid");
if(tid == NULL)
{
cm_log_printf(0, "[OneNET] HTTP GET tid ERROR\r\n");
cJSON_Delete(root);
cm_httpclient_specific_header_free(client);
cm_httpclient_terminate(client);
cm_httpclient_delete(client);
client = NULL;
return -1;
}
char c_tid[16] = {0};
sprintf(c_tid, "%d", tid->valueint);
/* 将tid写入文件系统用于记录 */
if (true == cm_fs_exist("onenet_tid.txt"))
{
cm_fs_delete("onenet_tid.txt");
}
int32_t fd = cm_fs_open("onenet_tid.txt", CM_FS_WB);
int32_t f_len = cm_fs_write(fd, c_tid, strlen(c_tid));
if (f_len != strlen(c_tid))
{
cm_log_printf(0, "[OneNET] FS WRITE tid ERROR\r\n");
}
cm_fs_close(fd);
cJSON_Delete(root);
cm_httpclient_specific_header_free(client);
cm_httpclient_terminate(client);
cm_httpclient_delete(client);
client = NULL;
return 0;
}
else
{
cm_log_printf(0, "[OneNET] REPORT VERSION ERROR [%d]\r\n", code->valueint);
cJSON_Delete(root);
cm_httpclient_specific_header_free(client);
cm_httpclient_terminate(client);
cm_httpclient_delete(client);
client = NULL;
return -1;
}
}
/**
* @brief url地址cm_fota_set_url()
*
* @return
* = 0 - \n
* < 0 -
*
* @details 使使https://open.iot.10086.cn/doc/v5/fuse/detail/1464 \n
* OneNET平台会持续迭代demo示例在2023年6月5日可以正常使用OneNET FOTA功能OneNET平台版本迭代后还可使用 \n
* header中数据使header配置header数据以参数形式添加进url中OneNET平台支持该方式 \n
*
*/
static int32_t __cm_onenet_fota_set_url(void)
{
char download_url[256] = {0};
char c_tid[16] = {0};
int32_t fd = cm_fs_open("onenet_tid.txt", CM_FS_RB);
int32_t f_len = cm_fs_read(fd, c_tid, 32);
cm_fs_close(fd);
if (0 == f_len)
{
cm_log_printf(0, "[OneNET] no tid\r\n");
return -1;
}
int32_t et = cm_rtc_get_current_time() + 2 * 24 * 60 * 60;
sprintf(download_url, "http://ota.heclouds.com");
sprintf(download_url + strlen((char*)download_url), "/fuse-ota/%s/%s/%s/download", OneNET_pid, OneNET_devname, c_tid);
/* 鉴权数据原为header中数据因本模组平台仅可使用最小系统升级方案不支持header配置故需将header数据以参数形式添加进url中OneNET平台支持该方式 */
char header[128] = {0};
unsigned char base64_tmp[128] = {0};
char message[128] = {0};
int base64_len = 0;
sprintf(header, "%ld\nsha1\nuserid/%s\n2022-05-01", et, OneNET_userid);
mbedtls_base64_decode((unsigned char*)base64_tmp, 128, (unsigned int*)&base64_len, (const unsigned char*)OneNET_userkey, strlen(OneNET_userkey));
mbedtls_md_context_t ctx = {0};
const mbedtls_md_info_t *info = NULL;
mbedtls_md_init(&ctx);
info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
mbedtls_md_setup(&ctx, info, 1);
mbedtls_md_hmac_starts(&ctx, (void *)base64_tmp, base64_len);
mbedtls_md_hmac_update(&ctx, (void *)header, strlen(header));
mbedtls_md_hmac_finish(&ctx, (void *)message);
mbedtls_md_free(&ctx);
mbedtls_base64_encode((unsigned char*)base64_tmp, 128, (unsigned int*)&base64_len, (const unsigned char*)message, 20);//SHA-1 算法输出为20字节
/* 鉴权数据原为header中数据因本模组平台仅可使用最小系统升级方案不支持header配置故需将header数据以参数形式添加进url中OneNET平台支持该方式 */
sprintf(download_url + strlen((char*)download_url), "?res=userid%s%s&et=%ld&method=sha1&sign=", "%2F", OneNET_userid, et);
for(int i = 0; i < base64_len; i++)
{
if((base64_tmp[i] == '+') || (base64_tmp[i] == '/') || (base64_tmp[i] == '='))
{
sprintf(download_url+strlen(download_url), "%s", (base64_tmp[i] == '+')?("%2B"):((base64_tmp[i] == '/')?("%2F"):("%3D")));
}
else
{
sprintf(download_url+strlen(download_url), "%c", base64_tmp[i]);
}
}
cm_log_printf(0, "[OneNET] download_url:%s\r\n", download_url);
cm_demo_printf("[OneNET] download_url:%s\r\n", download_url);
cm_fota_set_ota_plan(CM_FOTA_ASR_PLAN_MINI_INTEGRATE);
cm_fota_res_callback_register((cm_fota_result_callback)__cm_fota_cb);
return cm_fota_set_url(download_url);
}
/**
* @brief
*
* @return
* = 0 - \n
* = -1 -
*
* @details 使OneNET接口地址为http://ota.heclouds.com/fuse-ota/{pro_id}/{dev_name}/{tid}/status \n
* https://open.iot.10086.cn/doc/v5/fuse/detail/1449 \n
* \n
* 使使https://open.iot.10086.cn/doc/v5/fuse/detail/1464 \n
* OneNET平台会持续迭代demo示例在2023年6月5日可以正常使用OneNET FOTA功能OneNET平台版本迭代后还可使用 \n
*
*/
static int32_t __cm_onenet_fota_report_progress(void)
{
int32_t ret = -1;
char c_tid[16] = {0};
int32_t fd = cm_fs_open("onenet_tid.txt", CM_FS_RB);
int32_t f_len = cm_fs_read(fd, c_tid, 32);
cm_fs_close(fd);
if (0 == f_len)
{
cm_log_printf(0, "[OneNET] no tid\r\n");
return -1;
}
cm_httpclient_handle_t client = NULL;
ret = cm_httpclient_create((const uint8_t *)"http://ota.heclouds.com", NULL, &client);
if (CM_HTTP_RET_CODE_OK != ret || NULL == client)
{
cm_log_printf(0, "[OneNET] cm_httpclient_create() error!\r\n");
return -1;
}
cm_httpclient_cfg_t client_cfg;
client_cfg.ssl_enable = false;
client_cfg.ssl_id = 0;
client_cfg.cid = 0;
client_cfg.conn_timeout = HTTPCLIENT_CONNECT_TIMEOUT_DEFAULT;
client_cfg.rsp_timeout = HTTPCLIENT_WAITRSP_TIMEOUT_DEFAULT;
client_cfg.dns_priority = 0;
ret = cm_httpclient_set_cfg(client, client_cfg);
char path[128] = {0};
char header[256] = {0};
char message[128] = {0};
char content[64] = "{\"step\":201}"; //升级成功,此时平台会把设备的版本号修改为任务的目标版本(设备状态变成:升级完成)
unsigned char base64_tmp[128] = {0};
int32_t et = cm_rtc_get_current_time() + 2 * 24 * 60 * 60;
sprintf(path, "/fuse-ota");
sprintf(path + strlen((char*)path), "/%s/%s/%s/status", OneNET_pid, OneNET_devname, c_tid);
sprintf(header, "%ld\nsha1\nuserid/%s\n2022-05-01", et, OneNET_userid);
int base64_len = 0;
mbedtls_base64_decode((unsigned char*)base64_tmp, 128, (unsigned int*)&base64_len, (const unsigned char*)OneNET_userkey, strlen(OneNET_userkey));
mbedtls_md_context_t ctx = {0};
const mbedtls_md_info_t *info = NULL;
mbedtls_md_init(&ctx);
info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
mbedtls_md_setup(&ctx, info, 1);
mbedtls_md_hmac_starts(&ctx, (void *)base64_tmp, base64_len);
mbedtls_md_hmac_update(&ctx, (void *)header, strlen(header));
mbedtls_md_hmac_finish(&ctx, (void *)message);
mbedtls_md_free(&ctx);
mbedtls_base64_encode((unsigned char*)base64_tmp, 128, (unsigned int*)&base64_len, (const unsigned char*)message, 20);//SHA-1 算法输出为20字节
sprintf(header, "Authorization: version=2022-05-01&res=userid%s%s&et=%ld&method=sha1&sign=", "%2F", OneNET_userid, et);
for(int i = 0; i < base64_len; i++)
{
if((base64_tmp[i] == '+') || (base64_tmp[i] == '/') || (base64_tmp[i] == '='))
{
sprintf(header+strlen(header), "%s", (base64_tmp[i] == '+')?("%2B"):((base64_tmp[i] == '/')?("%2F"):("%3D")));
}
else
{
sprintf(header+strlen(header), "%c", base64_tmp[i]);
}
}
sprintf(header + strlen(header), "\r\nContent-Type:%s\r\n", "application/json");
cm_httpclient_sync_response_t response = {};
cm_httpclient_sync_param_t param = {HTTPCLIENT_REQUEST_POST, (const uint8_t *)path, strlen(content), (uint8_t *)content};
cm_httpclient_specific_header_set(client, (uint8_t *)header, strlen(header));
ret = cm_httpclient_sync_request(client, param, &response); //发送请求,同步接口
if (CM_HTTP_RET_CODE_OK != ret || NULL == client)
{
cm_log_printf(0, "[OneNET] cm_httpclient_sync_request() error! ret is %d\r\n", ret);
cm_httpclient_specific_header_free(client);
cm_httpclient_terminate(client);
cm_httpclient_delete(client);
client = NULL;
return -1;
}
else
{
cm_log_printf(0, "%s\r\n", response.response_content);
}
cJSON *root = cJSON_Parse((const char *)response.response_content);
cJSON *code = cJSON_GetObjectItem(root, "code");
if(code == NULL)
{
cJSON_Delete(root);
cm_log_printf(0, "[OneNET] HTTP GET DATA ERROR\r\n");
cm_httpclient_specific_header_free(client);
cm_httpclient_terminate(client);
cm_httpclient_delete(client);
client = NULL;
return -1;
}
if(0 == code->valueint)
{
cJSON_Delete(root);
cm_httpclient_specific_header_free(client);
cm_httpclient_terminate(client);
cm_httpclient_delete(client);
client = NULL;
return 0;
}
else
{
cm_log_printf(0, "[OneNET] REPORT VERSION ERROR [%d]\r\n", code->valueint);
cJSON_Delete(root);
cm_httpclient_specific_header_free(client);
cm_httpclient_terminate(client);
cm_httpclient_delete(client);
client = NULL;
return -1;
}
}
/**
* UART口FOTA功能调试使用示例
* CM:FOTA:FULLPACKAGE_HTTP //HTTP FOTA完整包升级方式配置HTTP服务器信息仅为示例配置的url不可使用
* CM:FOTA:FULLPACKAGE_FTP //FTP FOTA完整包升级方式配置FTP服务器信息仅为示例配置的url不可使用
* CM:FOTA:ONENET:operation //从OneNET平台获取和配置下载升级包的urloperation为操作参数详见下方代码
* CM:FOTA:UPGRADE //升级,须在完成配置后使用
*/
void cm_test_fota(unsigned char **cmd,int len)
{
unsigned char operation[20] = {0};
sprintf((char *)operation, "%s", cmd[2]);
int ret = 0;
if (0 == strcmp((const char *)operation, "FULLPACKAGE_HTTP")) //HTTP FOTA完整包升级方式配置FOTA信息
{
cm_fota_set_ota_plan(CM_FOTA_ASR_PLAN_MINI_INTEGRATE);
cm_fota_res_callback_register((cm_fota_result_callback)__cm_fota_cb);
ret = cm_fota_set_url("http://xxx.com:8080/system_patch.bin"); //仅作为示例url不可使用
if (0 != ret){
cm_log_printf(0, "cm_fota_set_url() error");
}
}
else if (0 == strcmp((const char *)operation, "FULLPACKAGE_FTP")) //FTP FOTA完整包升级方式配置FOTA信息
{
cm_fota_set_ota_plan(CM_FOTA_ASR_PLAN_MINI_INTEGRATE);
cm_fota_res_callback_register((cm_fota_result_callback)__cm_fota_cb);
ret = cm_fota_set_url("ftp://xxx.com:23/system_patch.bin"); //仅作为示例url不可使用
if (0 != ret){
cm_log_printf(0, "cm_fota_set_url() error");
}
ret = cm_fota_set_auth("user", "password");
if (0 != ret){
cm_log_printf(0, "cm_fota_set_auth() error");
}
}
else if (0 == strcmp((const char *)operation, "UPGRADE")) //启动升级
{
cm_fs_system_info_t fs_info = {0, 0};
cm_fs_getinfo(&fs_info);
/* 文件系统剩余空间为0时不建议执行升级关键文件系统操作可能会失败 */
if (0 == fs_info.free_size)
{
cm_log_printf(0, "insufficient space left in the file system");
return;
}
cm_fota_info_t info = {0};
cm_fota_read_config(&info);
if (CM_FOTA_TYPE_HTTP_HTTPS == info.fixed_info.fota_mode)
{
cm_log_printf(0, "HTTP server [%s]", info.fixed_info.url);
}
else if (CM_FOTA_TYPE_FTP == info.fixed_info.fota_mode)
{
cm_log_printf(0, "FTP server [%s] [%s] [%s]", info.fixed_info.url, info.fixed_info.username, info.fixed_info.passwd);
}
else
{
cm_log_printf(0, "HTTP server error");
return;
}
osDelay(200);
cm_fota_exec_upgrade();
}
else if (0 == strcmp((const char *)operation, "ONENET")) //使用OneNET FOTA服务程序示例
{
/* 使用本示例需要用户将OneNET_pid、OneNET_userid、OneNET_devname、OneNET_userkey、OneNET_version填写为用户账号及产品的真实内容 */
/* OneNET HTTP升级必要步骤参考链接https://open.iot.10086.cn/doc/v5/fuse/detail/1204 */
/* 与平台交互过程中使用鉴权信息会过期开发使用过程中须保证在时间过期前完成升级。安全鉴权参考https://open.iot.10086.cn/doc/v5/fuse/detail/1464 */
/* OneNET FOTA必须使用整包 mini FOTA方案服务步骤如下 */
/* 步骤1上报当前版本号测试指令CM:FOTA:ONENET:VERSION */
/* 步骤2增值服务-OTA升级https://open.iot.10086.cn/console/valueAdded/ota/package页面添加升级包差分包批量升级跳过验证。该步骤在平台侧网页完成https://open.iot.10086.cn/doc/v5/fuse/detail/1068 */
/* 步骤3检测升级任务并调用cm_fota_set_url()接口配置升级url测试指令CM:FOTA:ONENET:CHECK */
/* 步骤4下载升级包并升级固件此步由最小系统完成测试指令CM:FOTA:UPGRADE */
/* 步骤5待模组升级完成并重启后上报升级完成状态测试指令CM:FOTA:ONENET:PROGRESS */
/* 因为OneNET平台会持续迭代本demo示例在2023年6月5日可以正常使用OneNET FOTA功能但不能保证后续OneNET平台版本迭代后还可使用 */
unsigned char onenet_operation[20] = {0};
sprintf((char *)onenet_operation, "%s", cmd[3]);
if (0 == strcmp((const char *)onenet_operation, "VERSION"))
{
ret = __cm_onenet_fota_report_ver();
if (0 == ret)
{
cm_demo_printf("[OneNET] REPORT VERSION SUCC\r\n");
}
else
{
cm_demo_printf("[OneNET] REPORT VERSION ERROR\r\n");
}
}
else if (0 == strcmp((const char *)onenet_operation, "CHECK"))
{
ret = __cm_onenet_fota_check_upgrade_task();
if (0 == ret)
{
cm_demo_printf("[OneNET] UPGRADE TASK IS EXIST\r\n");
ret = __cm_onenet_fota_set_url();
if (0 == ret)
{
cm_demo_printf("[OneNET] __cm_onenet_fota_set_url SUCC\r\n");
}
else
{
cm_demo_printf("[OneNET] __cm_onenet_fota_set_url ERROR\r\n");
}
}
else
{
cm_demo_printf("[OneNET] CHEAK ERROR OR UPGRADE TASK IS NOT EXIST\r\n");
}
}
else if (0 == strcmp((const char *)onenet_operation, "PROGRESS"))
{
ret = __cm_onenet_fota_report_progress();
if (0 == ret)
{
cm_demo_printf("[OneNET] REPORT PROGRESS SUCC\r\n");
}
else
{
cm_demo_printf("[OneNET] REPORT PROGRESS ERROR\r\n");
}
}
}
else
{
cm_demo_printf("[FOTA] Illegal operation\n");
}
return;
}