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

761 lines
28 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*********************************************************
* @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;
}