Initial commit: CCU621_M firmware project with BLE debug link support.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-08 17:28:36 +08:00
commit 9ceb218f80
1597 changed files with 724159 additions and 0 deletions
+1120
View File
File diff suppressed because it is too large Load Diff
+48
View File
@@ -0,0 +1,48 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __IOTX_OTA_H__
#define __IOTX_OTA_H__
#include "ota_api.h"
typedef struct
{
const char *product_key; /* point to product key */
const char *device_name; /* point to device name */
uint32_t id; /* message id */
IOT_OTA_State_t state; /* OTA state */
IOT_OTA_Type_t type; /* OTA Type */
uint32_t size_last_fetched; /* size of last downloaded */
uint32_t size_fetched; /* size of already downloaded */
uint32_t size_file; /* size of file */
uint32_t size_fetched_per_time; /*request size of per time */
char *purl; /* point to URL */
char *version; /* point to string */
char *module; /* point to module string */
char md5sum[33]; /* MD5 string */
void *md5; /* MD5 handle */
void *sha256; /* Sha256 handle */
void *ch_signal; /* channel handle of signal exchanged with OTA server */
void *ch_fetch; /* channel handle of download */
/* cota */
char *configId;
uint32_t configSize;
char *sign;
char *signMethod;
char *cota_url;
char *getType;
int err; /* last error code */
ota_event_fpt ota_event_cb;
} OTA_Struct_t, *OTA_Struct_pt;
int iotx_ota_get_config(void *handle, const char *configScope, const char *getType,
const char *attributeKeys);
int iotx_req_image(void *handle, const char *version);
#endif /* #ifndef __IOTX_OTA_H__ */
+14
View File
@@ -0,0 +1,14 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __IOTX_OTA_CONFIG_H__
#define __IOTX_OTA_CONFIG_H__
#ifndef OTA_SIGNAL_CHANNEL
#define OTA_SIGNAL_CHANNEL (1)
#endif
#endif /* __IOTX_OTA_CONFIG_H__ */
+96
View File
@@ -0,0 +1,96 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef _IOTX_OTA_INTERNAL_H_
#define _IOTX_OTA_INTERNAL_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "infra_httpc.h"
#include "infra_string.h"
#include "infra_md5.h"
#include "infra_sha256.h"
#include "infra_json_parser.h"
#include "iotx_ota.h"
#include "ota_api.h"
#include "iotx_ota_config.h"
#include "wrappers.h"
#ifdef INFRA_MEM_STATS
#include "infra_mem_stats.h"
#define OTA_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "ota")
#define OTA_FREE(ptr) LITE_free(ptr)
#define OTA_API_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "ota.api")
#define OTA_API_FREE(ptr) LITE_free(ptr)
#else
#define OTA_MALLOC(size) HAL_Malloc(size)
#define OTA_FREE(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
#define OTA_API_MALLOC(size) HAL_Malloc(size)
#define OTA_API_FREE(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
#endif
#define OTA_SNPRINTF HAL_Snprintf
#ifdef INFRA_LOG
#include "infra_log.h"
#define OTA_LOG_CRIT(...) log_crit("ota", __VA_ARGS__)
#define OTA_LOG_ERROR(...) log_err("ota", __VA_ARGS__)
#define OTA_LOG_WRN(...) log_warning("ota", __VA_ARGS__)
#define OTA_LOG_INFO(...) log_info("ota", __VA_ARGS__)
#define OTA_LOG_DEBUG(...) log_debug("ota", __VA_ARGS__)
#else
#define OTA_LOG_CRIT(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#define OTA_LOG_ERROR(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#define OTA_LOG_WRN(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#define OTA_LOG_INFO(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#define OTA_LOG_DEBUG(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#endif
typedef enum {
IOTX_OTA_TOPIC_TYPE_DEVICE_REQUEST = 1,
IOTX_OTA_TOPIC_TYPE_DEVICE_UPGRATE = 2,
IOTX_OTA_TOPIC_TYPE_CONFIG_GET = 3,
IOTX_OTA_TOPIC_TYPE_CONFIG_PUSH = 4,
IOTX_OTA_TOPIC_TYPE_MAX
} iotx_ota_topic_types_t;
typedef int (*ota_cb_fpt)(void *pcontext, const char *msg, uint32_t msg_len, iotx_ota_topic_types_t type);
/* is_fetch = 0; start fetch */
/* is_fetch = 1; stop fetch */
const char *otalib_JsonValueOf(const char *json, uint32_t json_len, const char *key, uint32_t *val_len);
void *otalib_MD5Init(void);
void otalib_MD5Update(void *md5, const char *buf, size_t buf_len);
void otalib_MD5Finalize(void *md5, char *output_str);
void otalib_MD5Deinit(void *md5);
void *otalib_Sha256Init(void);
void otalib_Sha256Update(void *sha256, const char *buf, size_t buf_len);
void otalib_Sha256Finalize(void *sha256, char *output_str);
void otalib_Sha256Deinit(void *sha256);
int otalib_GetFirmwareFixlenPara(const char *json_doc,
size_t json_doc_len,
const char *key,
char *dest,
size_t dest_len);
int otalib_GetFirmwareVarlenPara(const char *json_doc,
size_t json_doc_len,
const char *key,
char **dest);
int otalib_GetParams(const char *json_doc, uint32_t json_len, char **url, char **version, char *md5,
uint32_t *file_size, char **module);
int otalib_GetConfigParams(const char *json_doc, uint32_t json_len, char **configId, uint32_t *configSize, char **sign,
char **signMethod, char **url, char **getType);
int otalib_GenInfoMsg(char *buf, size_t buf_len, uint32_t id, const char *version);
int otalib_GenReportMsg(char *buf, size_t buf_len, uint32_t id, int progress, const char *msg_detail);
void *ofc_Init(char *url, int offset);
void *ofc_Init_new(void *handle);
int32_t ofc_Fetch(void *handle, char *buf, uint32_t buf_len, uint32_t timeout_s);
int ofc_Deinit(void **handle);
#endif /* _IOTX_OTA_INTERNAL_H_ */
+255
View File
@@ -0,0 +1,255 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __OTA_EXPORT_H__
#define __OTA_EXPORT_H__
#include "infra_types.h"
#include "infra_defs.h"
#if defined(__cplusplus)
extern "C" {
#endif
#define OTA_CH_SIGNAL_MQTT (0)
#define OTA_CH_SIGNAL_COAP (1)
#define OTA_CH_FETCH_HTTP (1)
typedef enum {
IOT_OTAE_GENERAL = -1,
IOT_OTAE_INVALID_PARAM = -2,
IOT_OTAE_INVALID_STATE = -3,
IOT_OTAE_STR_TOO_LONG = -4,
IOT_OTAE_FETCH_FAILED = -5,
IOT_OTAE_NOMEM = -6,
IOT_OTAE_OSC_FAILED = -7,
IOT_OTAE_NONE = 0,
} IOT_OTA_Err_t;
/* State of OTA */
typedef enum {
IOT_OTAS_UNINITED = 0, /* Uninitialized State */
IOT_OTAS_INITED, /* Initialized State */
IOT_OTAS_PUSHED, /* The mission has been pushed down */
IOT_OTAS_FETCHING, /* Fetching firmware */
IOT_OTAS_FETCHED /* Fetching firmware finish */
} IOT_OTA_State_t;
typedef enum {
IOT_OTAT_NONE,
IOT_OTAT_COTA,
IOT_OTAT_FOTA
} IOT_OTA_Type_t;
/* Progress of OTA */
typedef enum {
/* Burn firmware file failed */
IOT_OTAP_BURN_FAILED = -4,
/* Check firmware file failed */
IOT_OTAP_CHECK_FALIED = -3,
/* Fetch firmware file failed */
IOT_OTAP_FETCH_FAILED = -2,
/* Initialized failed */
IOT_OTAP_GENERAL_FAILED = -1,
/* [0, 100], percentage of fetch progress */
/* The minimum percentage of fetch progress */
IOT_OTAP_FETCH_PERCENTAGE_MIN = 0,
/* The maximum percentage of fetch progress */
IOT_OTAP_FETCH_PERCENTAGE_MAX = 100
} IOT_OTA_Progress_t;
typedef enum {
IOT_OTAG_COTA_CONFIG_ID,
IOT_OTAG_COTA_CONFIG_SIZE,
IOT_OTAG_COTA_SIGN,
IOT_OTAG_COTA_SIGN_METHOD,
IOT_OTAG_COTA_URL,
IOT_OTAG_COTA_GETTYPE,
IOT_OTAG_OTA_TYPE,
IOT_OTAG_FETCHED_SIZE, /* option for get already fetched size */
IOT_OTAG_FILE_SIZE, /* size of file */
IOT_OTAG_MD5SUM, /* md5 in string format */
IOT_OTAG_VERSION, /* version in string format */
IOT_OTAG_MODULE, /* version in string format */
IOT_OTAG_CHECK_FIRMWARE, /* Check firmware is valid or not */
IOT_OTAG_CHECK_CONFIG, /* Check config file is valid or not */
IOT_OTAG_RESET_FETCHED_SIZE,/* reset the size_fetched parameter to be 0 */
IOT_OTAG_RESET_STATE /* reset the ota state to inited */
} IOT_OTA_CmdType_t;
typedef int (* ota_event_fpt)(void *);
/** @defgroup group_api api
* @{
*/
/** @defgroup group_api_ota ota
* @{
*/
/**
* @brief Initialize OTA module, and return handle.
* The MQTT client must be construct before calling this interface.
*
* @param [in] product_key: specify the product key.
* @param [in] device_name: specify the device name.
* @param [in] ch_signal: specify the signal channel.
*
* @retval 0 : Successful.
* @retval -1 : Failed.
* @see None.
*/
void *IOT_OTA_Init(const char *product_key, const char *device_name, void *ch_signal);
/**
* @brief Deinitialize OTA module specified by the 'handle', and release the related resource.
* You must call this interface to release resource if reboot is not invoked after downloading.
*
* @param [in] handle: specify the OTA module.
*
* @retval 0 : Successful.
* @retval < 0 : Failed, the value is error code.
* @see None.
*/
int IOT_OTA_Deinit(void *handle);
/**
* @brief Report firmware version information to OTA server (optional).
* NOTE: please
*
* @param [in] handle: specify the OTA module.
* @param [in] version: specify the firmware version in string format.
*
* @retval 0 : Successful.
* @retval < 0 : Failed, the value is error code.
* @see None.
*/
int IOT_OTA_ReportVersion(void *handle, const char *version);
/**
* @brief Report detail progress to OTA server (optional).
* NOTE: please
*
* @param [in] handle: specify the OTA module.
* @param [in] progress: specify the progress defined by 'IOT_OTA_Progress_t'.
* @param [in] msg: detail progress information in string.
*
* @retval 0 : Successful.
* @retval < 0 : Failed, the value is error code.
* @see None.
*/
int IOT_OTA_ReportProgress(void *handle, IOT_OTA_Progress_t progress, const char *msg);
/**
* @brief Check whether is on fetching state
*
* @param [in] handle: specify the OTA module.
*
* @retval 1 : Yes.
* @retval 0 : No.
* @see None.
*/
int IOT_OTA_IsFetching(void *handle);
/**
* @brief Check whether is on end-of-fetch state.
*
* @param [in] handle: specify the OTA module.
*
* @retval 1 : Yes.
* @retval 0 : False.
* @see None.
*/
int IOT_OTA_IsFetchFinish(void *handle);
/**
* @brief fetch firmware from remote server with specific timeout value.
* NOTE: If you want to download more faster, the bigger 'buf' should be given.
*
* @param [in] handle: specify the OTA module.
* @param [out] buf: specify the space for storing firmware data.
* @param [in] buf_len: specify the length of 'buf' in bytes.
* @param [in] timeout_s: specify the timeout value in second.
*
* @retval < 0 : Error occur..
* @retval 0 : No any data be downloaded in 'timeout_s' timeout period.
* @retval (0, len] : The length of data be downloaded in 'timeout_s' timeout period in bytes.
* @see None.
*/
int IOT_OTA_FetchYield(void *handle, char *buf, uint32_t buf_len, uint32_t timeout_s);
/**
* @brief Get OTA information specified by 'type'.
* By this interface, you can get information like state, size of file, md5 of file, etc.
*
* @param [in] handle: handle of the specific OTA
* @param [in] type: specify what information you want, see detail 'IOT_OTA_CmdType_t'
* @param [out] buf: specify buffer for data exchange
* @param [in] buf_len: specify the length of 'buf' in byte.
* @return
@verbatim
NOTE:
1) When type is IOT_OTAG_FETCHED_SIZE, 'buf' should be pointer of uint32_t, and 'buf_len' should be 4.
2) When type is IOT_OTAG_FILE_SIZE, 'buf' should be pointer of uint32_t, and 'buf_len' should be 4.
3) When type is IOT_OTAG_MD5SUM, 'buf' should be a buffer, and 'buf_len' should be 33.
4) When type is IOT_OTAG_VERSION, 'buf' should be a buffer, and 'buf_len' should be OTA_VERSION_LEN_MAX.
5) When type is IOT_OTAG_CHECK_FIRMWARE, 'buf' should be pointer of uint32_t, and 'buf_len' should be 4.
0, firmware is invalid; 1, firmware is valid.
@endverbatim
*
* @retval 0 : Successful.
* @retval < 0 : Failed, the value is error code.
* @see None.
*/
int IOT_OTA_Ioctl(void *handle, IOT_OTA_CmdType_t type, void *buf, int buf_len);
/**
* @brief Get last error code.
*
* @param [in] handle: specify the OTA module.
*
* @return The error code.
* @see None.
*/
int IOT_OTA_GetLastError(void *handle);
/**
* @brief set ota event callback.
*
* @param [in] handle: specify the OTA module.
*
* @param [in] cb: user callback.
*
* @return The error code.
* @see None.
*/
int IOT_OTA_SetOnPushedCallback(void *handle, int (*cb)(void *context));
/** @} */ /* end of api_ota */
/** @} */ /* end of api */
#if defined(__cplusplus)
}
#endif
#endif /* __OTA_EXPORT_H__ */
+160
View File
@@ -0,0 +1,160 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __OTA_COAP_C_H__
#define __OTA_COAP_C_H__
#if (OTA_SIGNAL_CHANNEL) == 2
#include "iotx_ota_internal.h"
/* OSC, OTA signal channel */
/* Specify the maximum characters of version */
#define OSC_COAP_URI_MAX_LEN (135) /* IoTx CoAP uri maximal length */
typedef struct {
void *coap;
const char *product_key;
const char *device_name;
ota_cb_fpt cb;
void *context;
} otacoap_Struct_t, *otacoap_Struct_pt;
static otacoap_Struct_pt h_osc_coap = NULL;
static void otacoap_response_handler(void *arg, void *p_response)
{
int len = 0;
unsigned char *p_payload = NULL;
iotx_coap_resp_code_t resp_code;
IOT_CoAP_GetMessageCode(p_response, &resp_code);
IOT_CoAP_GetMessagePayload(p_response, &p_payload, &len);
OTA_LOG_DEBUG("CoAP response code = %d", resp_code);
OTA_LOG_DEBUG("[CoAP msg_len=%d, msg=%s\r\n", len, p_payload);
if ((NULL != h_osc_coap) && (NULL != p_payload)) {
h_osc_coap->cb(h_osc_coap->context, (const char *)p_payload, (uint32_t)len);
}
}
/* Generate topic name according to @ota_topic_type, @product_key, @device_name */
/* and then copy to @buf. */
/* 0, successful; -1, failed */
static int otacoap_GenTopicName(char *buf, size_t buf_len, const char *ota_topic_type, const char *product_key,
const char *device_name)
{
int ret;
ret = OTA_SNPRINTF(buf,
buf_len,
"/topic/ota/device/%s/%s/%s",
ota_topic_type,
product_key,
device_name);
if (ret >= buf_len) {
return -1;
}
if (ret < 0) {
OTA_LOG_ERROR("snprintf failed");
return -1;
}
return 0;
}
/* report progress of OTA */
static int otacoap_Publish(otacoap_Struct_pt handle, const char *topic_type, const char *msg)
{
int ret;
char uri[IOTX_URI_MAX_LEN + 1] = {0};
iotx_message_t message;
message.p_payload = (unsigned char *)msg;
message.payload_len = (unsigned short)strlen(msg);
message.resp_callback = otacoap_response_handler;
message.msg_type = IOTX_MESSAGE_CON;
message.content_type = IOTX_CONTENT_TYPE_JSON;
/* topic name: /topic/ota/device/${topic_type}/${productKey}/${deviceName} */
ret = otacoap_GenTopicName(uri, OSC_COAP_URI_MAX_LEN, topic_type, handle->product_key, handle->device_name);
if (ret < 0) {
OTA_LOG_ERROR("generate topic name failed");
return -1;
}
if (IOTX_SUCCESS != (ret = IOT_CoAP_SendMessage(handle->coap, (char *)uri, &message))) {
OTA_LOG_ERROR("send CoAP msg failed%d", ret);
return -1;
}
return 0;
}
void *osc_Init(const char *product_key, const char *device_name, void *ch_signal, ota_cb_fpt cb, void *context)
{
otacoap_Struct_pt h_osc = NULL;
if (NULL == (h_osc = OTA_MALLOC(sizeof(otacoap_Struct_t)))) {
OTA_LOG_ERROR("allocate for h_osc failed");
return NULL;
}
memset(h_osc, 0, sizeof(otacoap_Struct_t));
h_osc->coap = ch_signal;
h_osc->product_key = product_key;
h_osc->device_name = device_name;
h_osc->cb = cb;
h_osc->context = context;
h_osc_coap = h_osc;
return h_osc;
}
int osc_Deinit(void *handle)
{
if (NULL != handle) {
OTA_FREE(handle);
}
return 0;
}
/* report progress of OTA */
int osc_ReportProgress(void *handle, const char *msg)
{
return otacoap_Publish(handle, "progress", msg);
}
/* report version of OTA firmware */
int osc_ReportVersion(void *handle, const char *msg)
{
static int state = 0;
int ret;
if (0 == state) { /* report version in initial state */
ret = otacoap_Publish(handle, "inform", msg);
if (0 != ret) {
return ret;
}
state = 1;
}
/* request new firmware after initial state */
return otacoap_Publish(handle, "request", msg);
}
#endif /* #if (OTA_SIGNAL_CHANNEL) == 2 */
#endif
+273
View File
@@ -0,0 +1,273 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "iotx_ota_internal.h"
/* ofc, OTA fetch channel */
#define OFC_HTTP_HEADER_MAXLEN (512)
typedef struct
{
char *payload;
int alread_download;
int payload_len;
} ota_http_response_t;
typedef struct
{
const char *url;
void *http_handle;
int fetch_size;
unsigned int file_size;
} otahttp_Struct_t, *otahttp_Struct_pt;
void *ofc_Init(char *url, int offset)
{
otahttp_Struct_pt h_odc;
char *pub_key = NULL;
int port = 0;
char header[OFC_HTTP_HEADER_MAXLEN] = {0};
char *header_fmt = "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
"Accept-Encoding: gzip, deflate\r\n"
"Range: bytes=%d-\r\n";
char *protocol_end = NULL, *port_start = NULL, *port_end = NULL;
int protocol_len = 0;
iotx_http_method_t method = IOTX_HTTP_GET;
/* protocol end location */
protocol_end = strstr(url, "://");
if (protocol_end != NULL)
{
protocol_len = strlen(url) - strlen(protocol_end);
/* check protocol, http or https, and assign default port*/
if ((strlen("http") == protocol_len) && (memcmp("http", url, protocol_len) == 0))
{
OTA_LOG_INFO("protocol: http");
port = 11889; // 80;
}
else if ((strlen("https") == protocol_len) && (memcmp("https", url, protocol_len) == 0))
{
OTA_LOG_INFO("protocol: https");
#ifdef SUPPORT_TLS
{
extern const char *iotx_ca_crt;
pub_key = (char *)iotx_ca_crt;
}
port = 443;
#else
port = 80;
#endif
}
else
{
OTA_LOG_ERROR("Invalid URL");
return NULL;
}
}
else
{
OTA_LOG_INFO("protocol: http");
protocol_end = url;
port = 11889; // 80;
}
/* check port, if exist, override port */
port_start = strstr(protocol_end + 1, ":");
if (port_start != NULL)
{
port_end = strstr(port_start + 1, "/");
if (port_end != NULL)
{
OTA_LOG_INFO("port exist: %.*s", (int)(port_end - port_start - 1), port_start + 1);
infra_str2int((const char *)(port_start + 1), &port);
}
}
if (offset == 0)
HAL_Snprintf(header, OFC_HTTP_HEADER_MAXLEN, header_fmt, offset);
if (NULL == (h_odc = OTA_MALLOC(sizeof(otahttp_Struct_t))))
{
OTA_LOG_ERROR("allocate for h_odc failed");
return NULL;
}
memset(h_odc, 0, sizeof(otahttp_Struct_t));
h_odc->http_handle = wrapper_http_init();
if (h_odc->http_handle == NULL)
{
OTA_FREE(h_odc);
return NULL;
}
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_URL, (void *)url);
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_PORT, (void *)&port);
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_METHOD, (void *)&method);
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_HEADER, (void *)header);
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_CERT, (void *)pub_key);
return h_odc;
}
void *ofc_Init_new(void *handle)
{
OTA_Struct_pt h_ota = (OTA_Struct_pt)handle;
otahttp_Struct_pt h_odc = (otahttp_Struct_pt)h_ota->ch_fetch;
char *pub_key = NULL;
int port = 0;
char header[OFC_HTTP_HEADER_MAXLEN] = {0};
char *header_fmt = "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
"Accept-Encoding: gzip, deflate\r\n"
"Range: bytes=%d-%d\r\n";
char *header_fmt_1 = "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
"Accept-Encoding: gzip, deflate\r\n"
"Range: bytes=%d-\r\n";
char *protocol_end = NULL, *port_start = NULL, *port_end = NULL;
int protocol_len = 0;
iotx_http_method_t method = IOTX_HTTP_GET;
protocol_end = strstr(h_ota->purl, "://");
if (protocol_end != NULL)
{
protocol_len = strlen(h_ota->purl) - strlen(protocol_end);
if ((strlen("http") == protocol_len) && (memcmp("http", h_ota->purl, protocol_len) == 0))
{
OTA_LOG_INFO("protocol: http");
port = 11889; // 80;
}
else if ((strlen("https") == protocol_len) && (memcmp("https", h_ota->purl, protocol_len) == 0))
{
OTA_LOG_INFO("protocol: https");
#ifdef SUPPORT_TLS
{
extern const char *iotx_ca_crt;
pub_key = (char *)iotx_ca_crt;
}
port = 443;
#else
port = 80;
#endif
}
else
{
OTA_LOG_ERROR("Invalid URL");
return NULL;
}
}
else
{
OTA_LOG_INFO("protocol: http");
protocol_end = h_ota->purl;
port = 11889; // 80;
}
port_start = strstr(protocol_end + 1, ":");
if (port_start != NULL)
{
port_end = strstr(port_start + 1, "/");
if (port_end != NULL)
{
OTA_LOG_INFO("port exist: %.*s", (int)(port_end - port_start - 1), port_start + 1);
infra_str2int((const char *)(port_start + 1), &port);
}
}
HAL_Printf("size_file = %d, size_fetched = %d, fetched_per_time = %d\n", h_ota->size_file, h_ota->size_fetched, h_ota->size_fetched_per_time);
if ((h_ota->size_file - h_ota->size_fetched) < h_ota->size_fetched_per_time)
{
HAL_Snprintf(header, OFC_HTTP_HEADER_MAXLEN, header_fmt_1, h_ota->size_fetched);
HAL_Printf("------header_fmt_1-----\n");
}
else
{
HAL_Snprintf(header, OFC_HTTP_HEADER_MAXLEN, header_fmt, h_ota->size_fetched, h_ota->size_fetched + h_ota->size_fetched_per_time - 1);
HAL_Printf("------header_fmt-----\n");
}
if (h_odc == NULL)
{
if (NULL == (h_odc = OTA_MALLOC(sizeof(otahttp_Struct_t))))
{
OTA_LOG_ERROR("allocate for h_odc failed");
return NULL;
}
memset(h_odc, 0, sizeof(otahttp_Struct_t));
h_odc->http_handle = wrapper_http_init();
if (h_odc->http_handle == NULL)
{
OTA_FREE(h_odc);
return NULL;
}
}
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_URL, (void *)h_ota->purl);
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_PORT, (void *)&port);
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_METHOD, (void *)&method);
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_HEADER, (void *)header);
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_CERT, (void *)pub_key);
return h_odc;
}
static int _ota_fetch_callback(char *ptr, int length, int total_length, void *userdata)
{
ota_http_response_t *response = (ota_http_response_t *)userdata;
if (response->alread_download + length > response->payload_len)
{
return FAIL_RETURN;
}
memcpy(response->payload + response->alread_download, ptr, length);
response->alread_download += length;
return length;
}
int32_t ofc_Fetch(void *handle, char *buf, uint32_t buf_len, uint32_t timeout_s)
{
int current_fetch_size = 0;
int http_timeout_s = timeout_s * 1000;
int http_recv_maxlen = buf_len;
otahttp_Struct_pt h_odc = (otahttp_Struct_pt)handle;
ota_http_response_t response;
memset(&response, 0, sizeof(ota_http_response_t));
memset(buf, 0, buf_len);
response.payload = buf;
response.payload_len = buf_len;
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_TIMEOUT, (void *)&http_timeout_s);
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_RECVCALLBACK, (void *)_ota_fetch_callback);
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_RECVMAXLEN, (void *)&http_recv_maxlen);
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_RECVCONTEXT, (void *)&response);
current_fetch_size = wrapper_http_perform(h_odc->http_handle, NULL, 0);
if (current_fetch_size < 0)
{
OTA_LOG_ERROR("fetch firmware failed");
return current_fetch_size;
}
h_odc->fetch_size += current_fetch_size;
/* OTA_LOG_ERROR("Download This Time: %d",current_fetch_size);
OTA_LOG_ERROR("Download Total : %d",h_odc->fetch_size); */
return current_fetch_size;
}
int ofc_Deinit(void **handle)
{
otahttp_Struct_t *h_odc = NULL;
if (handle == NULL || *handle == NULL)
{
return FAIL_RETURN;
}
h_odc = *(otahttp_Struct_t **)handle;
wrapper_http_deinit(&h_odc->http_handle);
OTA_FREE(h_odc);
*handle = NULL;
return 0;
}
+346
View File
@@ -0,0 +1,346 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "iotx_ota_internal.h"
#include "infra_compat.h"
const char *otalib_JsonValueOf(const char *json, uint32_t json_len, const char *key, uint32_t *val_len)
{
int length;
const char *val;
val = json_get_value_by_name((char *)json, json_len, (char *)key, &length, NULL);
if (NULL != val)
{
*val_len = (uint32_t)length;
}
return val;
}
void *otalib_MD5Init(void)
{
iot_md5_context *ctx = OTA_MALLOC(sizeof(iot_md5_context));
if (NULL == ctx)
{
return NULL;
}
utils_md5_init(ctx);
utils_md5_starts(ctx);
return ctx;
}
void otalib_MD5Update(void *md5, const char *buf, size_t buf_len)
{
utils_md5_update(md5, (unsigned char *)buf, buf_len);
}
void otalib_MD5Finalize(void *md5, char *output_str)
{
int i;
unsigned char buf_out[16];
utils_md5_finish(md5, buf_out);
for (i = 0; i < 16; ++i)
{
output_str[i * 2] = infra_hex2char(buf_out[i] >> 4);
output_str[i * 2 + 1] = infra_hex2char(buf_out[i]);
}
output_str[32] = '\0';
}
void otalib_MD5Deinit(void *md5)
{
if (NULL != md5)
{
OTA_FREE(md5);
}
}
void *otalib_Sha256Init(void)
{
iot_sha256_context *ctx = OTA_MALLOC(sizeof(iot_sha256_context));
if (NULL == ctx)
{
return NULL;
}
utils_sha256_init(ctx);
utils_sha256_starts(ctx);
return ctx;
}
void otalib_Sha256Update(void *sha256, const char *buf, size_t buf_len)
{
utils_sha256_update(sha256, (unsigned char *)buf, buf_len);
}
void otalib_Sha256Finalize(void *sha256, char *output_str)
{
int i;
unsigned char buf_out[32];
utils_sha256_finish(sha256, buf_out);
for (i = 0; i < 32; ++i)
{
output_str[i * 2] = infra_hex2char(buf_out[i] >> 4);
output_str[i * 2 + 1] = infra_hex2char(buf_out[i]);
}
output_str[64] = '\0';
}
void otalib_Sha256Deinit(void *sha256)
{
utils_sha256_free(sha256);
if (NULL != sha256)
{
OTA_FREE(sha256);
}
}
/* Get the specific @key value, and copy to @dest */
/* 0, successful; -1, failed */
int otalib_GetFirmwareFixlenPara(const char *json_doc,
size_t json_doc_len,
const char *key,
char *dest,
size_t dest_len)
{
const char *pvalue;
uint32_t val_len;
if (NULL == (pvalue = otalib_JsonValueOf(json_doc, json_doc_len, key, &val_len)))
{
OTA_LOG_ERROR("Not '%s' key in json doc of OTA", key);
return -1;
}
if (val_len > dest_len)
{
OTA_LOG_ERROR("value length of the key is too long");
return -1;
}
memcpy(dest, pvalue, val_len);
return 0;
}
/* Get variant length parameter of firmware, and copy to @dest */
/* 0, successful; -1, failed */
int otalib_GetFirmwareVarlenPara(const char *json_doc,
size_t json_doc_len,
const char *key,
char **dest)
{
const char *pvalue;
uint32_t val_len;
if (NULL == (pvalue = otalib_JsonValueOf(json_doc, json_doc_len, key, &val_len)))
{
if (0 != strcmp(key, "module"))
{
OTA_LOG_ERROR("Not %s key in json doc of OTA", key);
}
return -1;
}
if (NULL == (*dest = OTA_MALLOC(val_len + 1)))
{
OTA_LOG_ERROR("allocate for dest failed");
return -1;
}
memcpy(*dest, pvalue, val_len);
(*dest)[val_len] = '\0';
return 0;
}
int otalib_GetParams(const char *json_doc, uint32_t json_len, char **url, char **version, char *md5,
uint32_t *file_size, char **module)
{
#define OTA_FILESIZE_STR_LEN (16)
char file_size_str[OTA_FILESIZE_STR_LEN + 1] = {0};
/* get version */
if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "version", version))
{
OTA_LOG_ERROR("get value of version key failed");
return -1;
}
/* get module*/
if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "module", module))
{
OTA_LOG_INFO("normal OTA");
}
/* get URL */
if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "url", url))
{
OTA_LOG_ERROR("get value of url key failed");
return -1;
}
/* get md5 */
if (0 != otalib_GetFirmwareFixlenPara(json_doc, json_len, "md5", md5, 32))
{
OTA_LOG_ERROR("get value of md5 key failed");
return -1;
}
/* get file size */
if (0 != otalib_GetFirmwareFixlenPara(json_doc, json_len, "size", file_size_str, OTA_FILESIZE_STR_LEN))
{
OTA_LOG_ERROR("get value of size key failed");
return -1;
}
file_size_str[OTA_FILESIZE_STR_LEN] = '\0';
*file_size = atoi(file_size_str);
return 0;
#undef OTA_FILESIZE_STR_LEN
}
int otalib_GetConfigParams(const char *json_doc, uint32_t json_len, char **configId, uint32_t *configSize, char **sign,
char **signMethod, char **url, char **getType)
{
#define OTA_FILESIZE_STR_LEN (16)
char file_size_str[OTA_FILESIZE_STR_LEN + 1];
/* get configId */
if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "configId", configId))
{
OTA_LOG_ERROR("get value of configId key failed");
return -1;
}
/* get configSize */
if (0 != otalib_GetFirmwareFixlenPara(json_doc, json_len, "configSize", file_size_str, OTA_FILESIZE_STR_LEN))
{
OTA_LOG_ERROR("get value of size key failed");
return -1;
}
file_size_str[OTA_FILESIZE_STR_LEN] = '\0';
*configSize = atoi(file_size_str);
/* get sign */
if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "sign", sign))
{
OTA_LOG_ERROR("get value of sign key failed");
return -1;
}
/* get signMethod */
if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "signMethod", signMethod))
{
OTA_LOG_ERROR("get value of signMethod key failed");
return -1;
}
/* get url */
if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "url", url))
{
OTA_LOG_ERROR("get value of url key failed");
return -1;
}
/* get getType */
if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "getType", getType))
{
OTA_LOG_ERROR("get value of getType key failed");
return -1;
}
return 0;
#undef OTA_FILESIZE_STR_LEN
}
/* Generate firmware information according to @id, @version */
/* and then copy to @buf. */
/* 0, successful; -1, failed */
int otalib_GenInfoMsg(char *buf, size_t buf_len, uint32_t id, const char *version)
{
int ret;
ret = HAL_Snprintf(buf,
buf_len,
"{\"id\":%d,\"params\":{\"version\":\"%s\"}}",
id,
version);
if (ret < 0)
{
OTA_LOG_ERROR("HAL_Snprintf failed");
return -1;
}
return 0;
}
/* Generate report information according to @id, @msg */
/* and then copy to @buf. */
/* 0, successful; -1, failed */
int otalib_GenReportMsg(char *buf, size_t buf_len, uint32_t id, int progress, const char *msg_detail)
{
int ret;
char module[IOTX_MODULE_LEN] = {0};
IOT_Ioctl(IOTX_IOCTL_GET_MODULE, module);
if (NULL == msg_detail)
{
if (strlen(module) == 0)
{
ret = HAL_Snprintf(buf,
buf_len,
"{\"id\":%d,\"params\":{\"step\":\"%d\",\"desc\":\"\"}}",
id,
progress);
}
else
{
ret = HAL_Snprintf(buf,
buf_len,
"{\"id\":%d,\"params\":{\"step\":\"%d\",\"desc\":\"\", \"module\":\"%s\"}}",
id,
progress,
module);
}
}
else
{
if (strlen(module) == 0)
{
ret = HAL_Snprintf(buf,
buf_len,
"{\"id\":%d,\"params\":{\"step\":\"%d\",\"desc\":\"%s\"}}",
id,
progress,
msg_detail);
}
else
{
ret = HAL_Snprintf(buf,
buf_len,
"{\"id\":%d,\"params\":{\"step\":\"%d\",\"desc\":\"%s\", \"module\":\"%s\"}}",
id,
progress,
msg_detail,
module);
}
}
if (ret < 0)
{
OTA_LOG_ERROR("HAL_Snprintf failed");
return -1;
}
else if (ret >= buf_len)
{
OTA_LOG_ERROR("msg is too long");
return IOT_OTAE_STR_TOO_LONG;
}
return 0;
}
+331
View File
@@ -0,0 +1,331 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __OTA_MQTT_C_H__
#define __OTA_MQTT_C_H__
#if (OTA_SIGNAL_CHANNEL) == 1
#include "mqtt_api.h"
#include "ota_api.h"
#include "iotx_ota_internal.h"
/* OSC, OTA signal channel */
/* Specify the maximum characters of version */
#define OTA_MQTT_TOPIC_LEN (128)
typedef struct
{
void *mqtt;
const char *product_key;
const char *device_name;
char topic_upgrade[OTA_MQTT_TOPIC_LEN];
char topic_request[OTA_MQTT_TOPIC_LEN];
char topic_config_get[OTA_MQTT_TOPIC_LEN];
char topic_config_push[OTA_MQTT_TOPIC_LEN];
ota_cb_fpt cb;
void *context;
} otamqtt_Struct_t, *otamqtt_Struct_pt;
/* Generate topic name according to @ota_topic_type, @product_key, @device_name */
/* and then copy to @buf. */
/* 0, successful; -1, failed */
static int otamqtt_GenTopicName(char *buf, size_t buf_len, const char *ota_topic_type, const char *product_key,
const char *device_name)
{
int ret;
ret = HAL_Snprintf(buf,
buf_len,
"/ota/device/%s/%s/%s",
ota_topic_type,
product_key,
device_name);
if (ret >= buf_len)
{
return -1;
}
if (ret < 0)
{
OTA_LOG_ERROR("HAL_Snprintf failed");
return -1;
}
return 0;
}
/* report progress of OTA */
static int otamqtt_Publish(otamqtt_Struct_pt handle, const char *topic_type, int qos, const char *msg)
{
int ret;
char topic_name[OTA_MQTT_TOPIC_LEN];
iotx_mqtt_topic_info_t topic_info;
memset(&topic_info, 0, sizeof(iotx_mqtt_topic_info_t));
if (0 == qos)
{
topic_info.qos = IOTX_MQTT_QOS0;
}
else
{
topic_info.qos = IOTX_MQTT_QOS1;
}
topic_info.payload = (void *)msg;
topic_info.payload_len = strlen(msg);
/* inform OTA to topic: "/ota/device/progress/$(product_key)/$(device_name)" */
ret = otamqtt_GenTopicName(topic_name, OTA_MQTT_TOPIC_LEN, topic_type, handle->product_key, handle->device_name);
if (ret < 0)
{
OTA_LOG_ERROR("generate topic name of info failed");
return -1;
}
ret = IOT_MQTT_Publish(handle->mqtt, topic_name, &topic_info);
if (ret < 0)
{
OTA_LOG_ERROR("publish failed");
return IOT_OTAE_OSC_FAILED;
}
return 0;
}
static int otamqtt_publish_full_topic(otamqtt_Struct_pt handle, const char *topic_name,
iotx_mqtt_topic_info_pt topic_msg)
{
if (IOT_MQTT_Publish(handle->mqtt, topic_name, topic_msg) < 0)
{
OTA_LOG_ERROR("publish failed");
return IOT_OTAE_OSC_FAILED;
}
return 0;
}
/* decode JSON string to get firmware information, like firmware version, URL, file size, MD5. */
/* return NONE */
static void otamqtt_UpgrageCb(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
{
otamqtt_Struct_pt handle = (otamqtt_Struct_pt)pcontext;
iotx_mqtt_topic_info_pt topic_info = (iotx_mqtt_topic_info_pt)msg->msg;
OTA_LOG_DEBUG("topic=%.*s", topic_info->topic_len, topic_info->ptopic);
OTA_LOG_DEBUG("len=%u, topic_msg=%.*s", topic_info->payload_len, topic_info->payload_len, (char *)topic_info->payload);
if (IOTX_MQTT_EVENT_PUBLISH_RECEIVED != msg->event_type)
{
return;
}
if (NULL != strstr(topic_info->ptopic, "/ota/device/request"))
{
OTA_LOG_DEBUG("receive device request");
/*if(NULL != HAL_strnstr(topic_info->payload, topic_info->payload_len,
"url", strlen("url")))*/
if (NULL != strstr(topic_info->payload, "url"))
{
OTA_LOG_INFO("get request reply for new version image");
if (NULL != handle->cb)
{
handle->cb(handle->context, topic_info->payload, topic_info->payload_len, IOTX_OTA_TOPIC_TYPE_DEVICE_REQUEST);
}
}
}
else if (NULL != strstr(topic_info->ptopic, "/ota/device/upgrade"))
{
OTA_LOG_DEBUG("receive device upgrade");
if (NULL != handle->cb)
{
handle->cb(handle->context, topic_info->payload, topic_info->payload_len, IOTX_OTA_TOPIC_TYPE_DEVICE_UPGRATE);
}
}
else if (NULL != strstr(topic_info->ptopic, "/thing/config/get_reply"))
{
OTA_LOG_DEBUG("receive config get_reply");
if (NULL != handle->cb)
{
handle->cb(handle->context, topic_info->payload, topic_info->payload_len, IOTX_OTA_TOPIC_TYPE_CONFIG_GET);
}
}
else if (NULL != strstr(topic_info->ptopic, "/thing/config/push"))
{
OTA_LOG_DEBUG("receive config push");
if (NULL != handle->cb)
{
if (0 != handle->cb(handle->context, topic_info->payload, topic_info->payload_len, IOTX_OTA_TOPIC_TYPE_CONFIG_PUSH))
{
/* fail, send fail response code:400 */
const char *pvalue;
uint32_t val_len;
char topic[OTA_MQTT_TOPIC_LEN] = {0};
char message[OTA_MQTT_TOPIC_LEN] = {0};
iotx_mqtt_topic_info_t message_info;
memset(&message_info, 0, sizeof(iotx_mqtt_topic_info_t));
pvalue = otalib_JsonValueOf(topic_info->payload, topic_info->payload_len, "id", &val_len);
HAL_Snprintf(topic,
OTA_MQTT_TOPIC_LEN,
"/sys/%s/%s/thing/config/push_reply",
handle->product_key,
handle->device_name);
HAL_Snprintf(message,
OTA_MQTT_TOPIC_LEN,
"\"id\":%.*s,\"code\":\"%d\",\"data\":{}",
val_len,
pvalue,
400);
message_info.qos = IOTX_MQTT_QOS0;
message_info.payload = (void *)message;
message_info.payload_len = strlen(message);
if (IOT_MQTT_Publish(handle->mqtt, topic, &message_info) < 0)
{
OTA_LOG_ERROR("publish failed");
}
}
}
}
}
void *osc_Init(const char *product_key, const char *device_name, void *ch_signal, ota_cb_fpt cb, void *context)
{
int ret;
otamqtt_Struct_pt h_osc = NULL;
if (NULL == (h_osc = OTA_MALLOC(sizeof(otamqtt_Struct_t))))
{
OTA_LOG_ERROR("allocate for h_osc failed");
return NULL;
}
memset(h_osc, 0, sizeof(otamqtt_Struct_t));
/* subscribe the OTA topic: "/ota/device/request/$(product_key)/$(device_name)" */
ret = otamqtt_GenTopicName(h_osc->topic_request, OTA_MQTT_TOPIC_LEN, "request", product_key, device_name);
if (ret < 0)
{
OTA_LOG_ERROR("generate topic name of request failed");
goto do_exit;
}
ret = IOT_MQTT_Subscribe(ch_signal, h_osc->topic_request, IOTX_MQTT_QOS1, otamqtt_UpgrageCb, h_osc);
if (ret < 0)
{
OTA_LOG_ERROR("mqtt subscribe failed");
goto do_exit;
}
/* subscribe the OTA topic: "/ota/device/upgrade/$(product_key)/$(device_name)" */
ret = otamqtt_GenTopicName(h_osc->topic_upgrade, OTA_MQTT_TOPIC_LEN, "upgrade", product_key, device_name);
if (ret < 0)
{
OTA_LOG_ERROR("generate topic name of upgrade failed");
goto do_exit;
}
ret = IOT_MQTT_Subscribe(ch_signal, h_osc->topic_upgrade, IOTX_MQTT_QOS1, otamqtt_UpgrageCb, h_osc);
if (ret < 0)
{
OTA_LOG_ERROR("mqtt subscribe failed");
goto do_exit;
}
/* subscribe the OTA topic: "/sys/{productKey}/{deviceName}/thing/config/get_reply" */
ret = HAL_Snprintf(h_osc->topic_config_get,
OTA_MQTT_TOPIC_LEN,
"/sys/%s/%s/thing/config/get_reply",
product_key,
device_name);
if (ret < 0)
{
OTA_LOG_ERROR("generate topic name of config get failed");
goto do_exit;
}
ret = IOT_MQTT_Subscribe(ch_signal, h_osc->topic_config_get, IOTX_MQTT_QOS0, otamqtt_UpgrageCb, h_osc);
if (ret < 0)
{
OTA_LOG_ERROR("mqtt subscribe failed");
goto do_exit;
}
/* subscribe the OTA topic: "/sys/{productKey}/{deviceName}/thing/config/push" */
ret = HAL_Snprintf(h_osc->topic_config_push,
OTA_MQTT_TOPIC_LEN,
"/sys/%s/%s/thing/config/push",
product_key,
device_name);
if (ret < 0)
{
OTA_LOG_ERROR("generate topic name of config get failed");
goto do_exit;
}
ret = IOT_MQTT_Subscribe(ch_signal, h_osc->topic_config_push, IOTX_MQTT_QOS0, otamqtt_UpgrageCb, h_osc);
if (ret < 0)
{
OTA_LOG_ERROR("mqtt subscribe failed");
goto do_exit;
}
h_osc->mqtt = ch_signal;
h_osc->product_key = product_key;
h_osc->device_name = device_name;
h_osc->cb = cb;
h_osc->context = context;
return h_osc;
do_exit:
if (NULL != h_osc)
{
OTA_FREE(h_osc);
}
return NULL;
}
int osc_Deinit(void *handle)
{
if (NULL != handle)
{
OTA_FREE(handle);
}
return 0;
}
/* report progress of OTA */
int osc_ReportProgress(void *handle, const char *msg)
{
return otamqtt_Publish(handle, "progress", 0, msg);
}
/* report version of OTA firmware */
int osc_ReportVersion(void *handle, const char *msg)
{
return otamqtt_Publish(handle, "inform", 1, msg);
}
/* request the OTA firmware pushed by user*/
int osc_RequestImage(void *handle, const char *msg)
{
return otamqtt_Publish(handle, "request", 1, msg);
}
/* request the config */
int osc_RequestConfig(void *handle, const char *topic_name, iotx_mqtt_topic_info_pt topic_msg)
{
return otamqtt_publish_full_topic(handle, topic_name, topic_msg);
}
#endif /* #if (OTA_SIGNAL_CHANNEL) == 1 */
#endif /* #ifndef __OTA_MQTT_C_H__ */