update qcloud sdk
1. iot-hub sdk update to 3.2.0 2. iot-explorer update to 3.1.1
This commit is contained in:
661
components/connectivity/qcloud-iot-hub-sdk/3rdparty/sdk_src/services/ota/ota_client.c
vendored
Normal file
661
components/connectivity/qcloud-iot-hub-sdk/3rdparty/sdk_src/services/ota/ota_client.c
vendored
Normal file
@@ -0,0 +1,661 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making IoT Hub available.
|
||||
* Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is
|
||||
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ota_client.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ota_fetch.h"
|
||||
#include "ota_lib.h"
|
||||
#include "qcloud_iot_export.h"
|
||||
#include "utils_param_check.h"
|
||||
#include "utils_timer.h"
|
||||
|
||||
#define OTA_VERSION_STR_LEN_MIN (1)
|
||||
#define OTA_VERSION_STR_LEN_MAX (32)
|
||||
|
||||
typedef struct {
|
||||
const char *product_id; /* point to product id */
|
||||
const char *device_name; /* point to device name */
|
||||
|
||||
uint32_t id; /* message id */
|
||||
IOT_OTA_State_Code state; /* OTA state */
|
||||
uint32_t size_last_fetched; /* size of last downloaded */
|
||||
uint32_t size_fetched; /* size of already downloaded */
|
||||
uint32_t size_file; /* size of file */
|
||||
|
||||
char *purl; /* point to URL */
|
||||
char *version; /* point to string */
|
||||
char md5sum[33]; /* MD5 string */
|
||||
|
||||
void *md5; /* MD5 handle */
|
||||
void *ch_signal; /* channel handle of signal exchanged with OTA server */
|
||||
void *ch_fetch; /* channel handle of download */
|
||||
|
||||
int err; /* last error code */
|
||||
|
||||
short current_signal_type;
|
||||
|
||||
Timer report_timer;
|
||||
|
||||
} OTA_Struct_t;
|
||||
|
||||
/* check ota progress */
|
||||
/* return: true, valid progress state; false, invalid progress state. */
|
||||
static int _ota_check_progress(IOT_OTA_Progress_Code progress)
|
||||
{
|
||||
return ((progress >= IOT_OTAP_BURN_FAILED) && (progress <= IOT_OTAP_FETCH_PERCENTAGE_MAX));
|
||||
}
|
||||
|
||||
/* callback when OTA topic msg is received */
|
||||
static void _ota_callback(void *pcontext, const char *msg, uint32_t msg_len)
|
||||
{
|
||||
#define OTA_JSON_TYPE_VALUE_LENGTH 64
|
||||
|
||||
char *json_type = NULL;
|
||||
|
||||
OTA_Struct_t *h_ota = (OTA_Struct_t *)pcontext;
|
||||
|
||||
if (h_ota->state >= IOT_OTAS_FETCHING) {
|
||||
Log_i("In downloading or downloaded state");
|
||||
goto End;
|
||||
}
|
||||
|
||||
if (msg == NULL || msg_len == 0) {
|
||||
Log_e("OTA response message is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
if (qcloud_otalib_get_firmware_type(msg, &json_type) != QCLOUD_RET_SUCCESS) {
|
||||
Log_e("Get firmware type failed!");
|
||||
goto End;
|
||||
}
|
||||
|
||||
if (!strcmp(json_type, REPORT_VERSION_RSP)) {
|
||||
if (qcloud_otalib_get_report_version_result(msg) < QCLOUD_RET_SUCCESS) {
|
||||
Log_e("Report version failed!");
|
||||
h_ota->err = IOT_OTA_ERR_REPORT_VERSION;
|
||||
h_ota->state = IOT_OTAS_FETCHED;
|
||||
} else {
|
||||
Log_i("Report version success!");
|
||||
}
|
||||
goto End;
|
||||
} else {
|
||||
if (strcmp(json_type, UPDATE_FIRMWARE) != 0) {
|
||||
Log_e("Netheir Report version result nor update firmware! type: %s", json_type);
|
||||
goto End;
|
||||
}
|
||||
|
||||
if (NULL != json_type) {
|
||||
HAL_Free(json_type);
|
||||
json_type = NULL;
|
||||
}
|
||||
|
||||
if (0 != qcloud_otalib_get_params(msg, &json_type, &h_ota->purl, &h_ota->version, h_ota->md5sum,
|
||||
&h_ota->size_file)) {
|
||||
Log_e("Get firmware parameter failed");
|
||||
goto End;
|
||||
}
|
||||
|
||||
h_ota->state = IOT_OTAS_FETCHING;
|
||||
}
|
||||
|
||||
End:
|
||||
if (json_type != NULL)
|
||||
HAL_Free(json_type);
|
||||
|
||||
#undef OTA_JSON_TYPE_VALUE_LENGTH
|
||||
}
|
||||
|
||||
static void IOT_OTA_ResetStatus(void *handle)
|
||||
{
|
||||
OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
|
||||
h_ota->state = IOT_OTAS_INITED;
|
||||
}
|
||||
|
||||
static int IOT_OTA_ReportProgress(void *handle, IOT_OTA_Progress_Code progress, IOT_OTAReportType reportType)
|
||||
{
|
||||
#define MSG_REPORT_LEN (256)
|
||||
|
||||
int ret = QCLOUD_ERR_FAILURE;
|
||||
char * msg_reported;
|
||||
OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
|
||||
|
||||
if (NULL == handle) {
|
||||
Log_e("handle is NULL");
|
||||
return IOT_OTA_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (IOT_OTAS_UNINITED == h_ota->state) {
|
||||
Log_e("handle is uninitialized");
|
||||
h_ota->err = IOT_OTA_ERR_INVALID_STATE;
|
||||
return QCLOUD_ERR_FAILURE;
|
||||
}
|
||||
|
||||
if (!_ota_check_progress(progress)) {
|
||||
Log_e("progress is a invalid parameter: %d", progress);
|
||||
h_ota->err = IOT_OTA_ERR_INVALID_PARAM;
|
||||
return QCLOUD_ERR_FAILURE;
|
||||
}
|
||||
|
||||
if (NULL == (msg_reported = HAL_Malloc(MSG_REPORT_LEN))) {
|
||||
Log_e("allocate for msg_reported failed");
|
||||
h_ota->err = IOT_OTA_ERR_NOMEM;
|
||||
return QCLOUD_ERR_FAILURE;
|
||||
}
|
||||
|
||||
ret = qcloud_otalib_gen_report_msg(msg_reported, MSG_REPORT_LEN, h_ota->id, h_ota->version, progress, reportType);
|
||||
if (0 != ret) {
|
||||
Log_e("generate reported message failed");
|
||||
h_ota->err = ret;
|
||||
goto do_exit;
|
||||
}
|
||||
|
||||
ret = qcloud_osc_report_progress(h_ota->ch_signal, msg_reported);
|
||||
if (QCLOUD_RET_SUCCESS != ret) {
|
||||
Log_e("Report progress failed");
|
||||
h_ota->err = ret;
|
||||
goto do_exit;
|
||||
}
|
||||
|
||||
ret = QCLOUD_RET_SUCCESS;
|
||||
|
||||
do_exit:
|
||||
if (NULL != msg_reported) {
|
||||
HAL_Free(msg_reported);
|
||||
}
|
||||
return ret;
|
||||
|
||||
#undef MSG_REPORT_LEN
|
||||
}
|
||||
|
||||
static int IOT_OTA_ReportUpgradeResult(void *handle, const char *version, IOT_OTAReportType reportType)
|
||||
{
|
||||
#define MSG_UPGPGRADE_LEN (256)
|
||||
|
||||
POINTER_SANITY_CHECK(handle, IOT_OTA_ERR_INVALID_PARAM);
|
||||
POINTER_SANITY_CHECK(version, IOT_OTA_ERR_INVALID_PARAM);
|
||||
|
||||
int ret, len;
|
||||
char * msg_upgrade;
|
||||
OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
|
||||
|
||||
if (IOT_OTAS_UNINITED == h_ota->state) {
|
||||
Log_e("handle is uninitialized");
|
||||
h_ota->err = IOT_OTA_ERR_INVALID_STATE;
|
||||
return QCLOUD_ERR_FAILURE;
|
||||
}
|
||||
|
||||
len = strlen(version);
|
||||
if ((len < OTA_VERSION_STR_LEN_MIN) || (len > OTA_VERSION_STR_LEN_MAX)) {
|
||||
Log_e("version string is invalid: must be [1, 32] chars");
|
||||
h_ota->err = IOT_OTA_ERR_INVALID_PARAM;
|
||||
return QCLOUD_ERR_FAILURE;
|
||||
}
|
||||
|
||||
if (NULL == (msg_upgrade = HAL_Malloc(MSG_UPGPGRADE_LEN))) {
|
||||
Log_e("allocate for msg_informed failed");
|
||||
h_ota->err = IOT_OTA_ERR_NOMEM;
|
||||
return QCLOUD_ERR_FAILURE;
|
||||
}
|
||||
|
||||
ret = qcloud_otalib_gen_report_msg(msg_upgrade, MSG_UPGPGRADE_LEN, 1, version, 1, reportType);
|
||||
if (ret != 0) {
|
||||
Log_e("generate inform message failed");
|
||||
h_ota->err = ret;
|
||||
ret = QCLOUD_ERR_FAILURE;
|
||||
goto do_exit;
|
||||
}
|
||||
|
||||
ret = qcloud_osc_report_upgrade_result(h_ota->ch_signal, msg_upgrade);
|
||||
if (0 > ret) {
|
||||
Log_e("Report version failed");
|
||||
h_ota->err = ret;
|
||||
ret = QCLOUD_ERR_FAILURE;
|
||||
goto do_exit;
|
||||
}
|
||||
|
||||
IOT_OTA_ResetStatus(h_ota);
|
||||
|
||||
do_exit:
|
||||
if (NULL != msg_upgrade) {
|
||||
HAL_Free(msg_upgrade);
|
||||
}
|
||||
return ret;
|
||||
|
||||
#undef MSG_UPGPGRADE_LEN
|
||||
}
|
||||
|
||||
/* Init OTA handle */
|
||||
void *IOT_OTA_Init(const char *product_id, const char *device_name, void *ch_signal)
|
||||
{
|
||||
POINTER_SANITY_CHECK(product_id, NULL);
|
||||
POINTER_SANITY_CHECK(device_name, NULL);
|
||||
POINTER_SANITY_CHECK(ch_signal, NULL);
|
||||
|
||||
OTA_Struct_t *h_ota = NULL;
|
||||
|
||||
if (NULL == (h_ota = HAL_Malloc(sizeof(OTA_Struct_t)))) {
|
||||
Log_e("allocate failed");
|
||||
return NULL;
|
||||
}
|
||||
memset(h_ota, 0, sizeof(OTA_Struct_t));
|
||||
h_ota->state = IOT_OTAS_UNINITED;
|
||||
|
||||
h_ota->ch_signal = qcloud_osc_init(product_id, device_name, ch_signal, _ota_callback, h_ota);
|
||||
if (NULL == h_ota->ch_signal) {
|
||||
Log_e("initialize signal channel failed");
|
||||
goto do_exit;
|
||||
}
|
||||
|
||||
h_ota->md5 = qcloud_otalib_md5_init();
|
||||
if (NULL == h_ota->md5) {
|
||||
Log_e("initialize md5 failed");
|
||||
goto do_exit;
|
||||
}
|
||||
|
||||
h_ota->product_id = product_id;
|
||||
h_ota->device_name = device_name;
|
||||
h_ota->state = IOT_OTAS_INITED;
|
||||
#ifdef OTA_MQTT_CHANNEL
|
||||
h_ota->current_signal_type = MQTT_CHANNEL;
|
||||
#else
|
||||
h_ota->current_signal_type = COAP_CHANNEL;
|
||||
#endif
|
||||
return h_ota;
|
||||
|
||||
do_exit:
|
||||
|
||||
if (NULL != h_ota->ch_signal) {
|
||||
qcloud_osc_deinit(h_ota->ch_signal);
|
||||
}
|
||||
|
||||
if (NULL != h_ota->md5) {
|
||||
qcloud_otalib_md5_deinit(h_ota->md5);
|
||||
}
|
||||
|
||||
if (NULL != h_ota) {
|
||||
HAL_Free(h_ota);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
#undef AOM_INFO_MSG_LEN
|
||||
}
|
||||
|
||||
/* Destroy OTA handle and resource */
|
||||
int IOT_OTA_Destroy(void *handle)
|
||||
{
|
||||
OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
|
||||
|
||||
if (NULL == h_ota) {
|
||||
Log_e("handle is NULL");
|
||||
return IOT_OTA_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (IOT_OTAS_UNINITED == h_ota->state) {
|
||||
Log_e("handle is uninitialized");
|
||||
h_ota->err = IOT_OTA_ERR_INVALID_STATE;
|
||||
return QCLOUD_ERR_FAILURE;
|
||||
}
|
||||
|
||||
qcloud_osc_deinit(h_ota->ch_signal);
|
||||
qcloud_ofc_deinit(h_ota->ch_fetch);
|
||||
qcloud_otalib_md5_deinit(h_ota->md5);
|
||||
|
||||
if (NULL != h_ota->purl) {
|
||||
HAL_Free(h_ota->purl);
|
||||
}
|
||||
|
||||
if (NULL != h_ota->version) {
|
||||
HAL_Free(h_ota->version);
|
||||
}
|
||||
|
||||
HAL_Free(h_ota);
|
||||
return QCLOUD_RET_SUCCESS;
|
||||
}
|
||||
|
||||
/*support continuous transmission of breakpoints*/
|
||||
int IOT_OTA_StartDownload(void *handle, uint32_t offset, uint32_t size)
|
||||
{
|
||||
OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
|
||||
int Ret;
|
||||
|
||||
Log_d("to download FW from offset: %u, size: %u", offset, size);
|
||||
h_ota->size_fetched = offset;
|
||||
h_ota->ch_fetch = ofc_Init(h_ota->purl, offset, size);
|
||||
if (NULL == h_ota->ch_fetch) {
|
||||
Log_e("Initialize fetch module failed");
|
||||
return QCLOUD_ERR_FAILURE;
|
||||
}
|
||||
|
||||
Ret = qcloud_ofc_connect(h_ota->ch_fetch);
|
||||
if (QCLOUD_RET_SUCCESS != Ret) {
|
||||
Log_e("Connect fetch module failed");
|
||||
h_ota->state = IOT_OTAS_DISCONNECTED;
|
||||
}
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
/*support continuous transmission of breakpoints*/
|
||||
void IOT_OTA_UpdateClientMd5(void *handle, char *buff, uint32_t size)
|
||||
{
|
||||
OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
|
||||
|
||||
qcloud_otalib_md5_update(h_ota->md5, buff, size);
|
||||
}
|
||||
|
||||
/*support continuous transmission of breakpoints*/
|
||||
int IOT_OTA_ResetClientMD5(void *handle)
|
||||
{
|
||||
OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
|
||||
|
||||
qcloud_otalib_md5_deinit(h_ota->md5);
|
||||
h_ota->md5 = qcloud_otalib_md5_init();
|
||||
if (NULL == h_ota->md5) {
|
||||
return QCLOUD_ERR_FAILURE;
|
||||
}
|
||||
|
||||
return QCLOUD_RET_SUCCESS;
|
||||
}
|
||||
|
||||
int IOT_OTA_ReportVersion(void *handle, const char *version)
|
||||
{
|
||||
#define MSG_INFORM_LEN (128)
|
||||
|
||||
int ret, len;
|
||||
char * msg_informed;
|
||||
OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
|
||||
|
||||
POINTER_SANITY_CHECK(handle, IOT_OTA_ERR_INVALID_PARAM);
|
||||
POINTER_SANITY_CHECK(version, IOT_OTA_ERR_INVALID_PARAM);
|
||||
|
||||
len = strlen(version);
|
||||
if ((len < OTA_VERSION_STR_LEN_MIN) || (len > OTA_VERSION_STR_LEN_MAX)) {
|
||||
Log_e("version string is invalid: must be [1, 32] chars");
|
||||
h_ota->err = IOT_OTA_ERR_INVALID_PARAM;
|
||||
return QCLOUD_ERR_FAILURE;
|
||||
}
|
||||
|
||||
if (IOT_OTAS_UNINITED == h_ota->state) {
|
||||
Log_e("handle is uninitialized");
|
||||
h_ota->err = IOT_OTA_ERR_INVALID_STATE;
|
||||
return QCLOUD_ERR_FAILURE;
|
||||
}
|
||||
|
||||
IOT_OTA_ResetStatus(h_ota);
|
||||
|
||||
if (NULL == (msg_informed = HAL_Malloc(MSG_INFORM_LEN))) {
|
||||
Log_e("allocate for msg_informed failed");
|
||||
h_ota->err = IOT_OTA_ERR_NOMEM;
|
||||
return QCLOUD_ERR_FAILURE;
|
||||
}
|
||||
|
||||
ret = qcloud_otalib_gen_info_msg(msg_informed, MSG_INFORM_LEN, h_ota->id, version);
|
||||
if (ret != 0) {
|
||||
Log_e("generate inform message failed");
|
||||
h_ota->err = ret;
|
||||
ret = QCLOUD_ERR_FAILURE;
|
||||
goto do_exit;
|
||||
}
|
||||
|
||||
ret = qcloud_osc_report_version(h_ota->ch_signal, msg_informed);
|
||||
if (0 > ret) {
|
||||
Log_e("Report version failed");
|
||||
h_ota->err = ret;
|
||||
ret = QCLOUD_ERR_FAILURE;
|
||||
goto do_exit;
|
||||
}
|
||||
|
||||
do_exit:
|
||||
if (NULL != msg_informed) {
|
||||
HAL_Free(msg_informed);
|
||||
}
|
||||
return ret;
|
||||
|
||||
#undef MSG_INFORM_LEN
|
||||
}
|
||||
|
||||
int IOT_OTA_ReportUpgradeBegin(void *handle)
|
||||
{
|
||||
OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
|
||||
return IOT_OTA_ReportUpgradeResult(handle, h_ota->version, IOT_OTAR_UPGRADE_BEGIN);
|
||||
}
|
||||
|
||||
int IOT_OTA_ReportUpgradeSuccess(void *handle, const char *version)
|
||||
{
|
||||
OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
|
||||
int ret;
|
||||
|
||||
if (NULL == version) {
|
||||
ret = IOT_OTA_ReportUpgradeResult(handle, h_ota->version, IOT_OTAR_UPGRADE_SUCCESS);
|
||||
} else {
|
||||
ret = IOT_OTA_ReportUpgradeResult(handle, version, IOT_OTAR_UPGRADE_SUCCESS);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int IOT_OTA_ReportUpgradeFail(void *handle, const char *version)
|
||||
{
|
||||
OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
|
||||
int ret;
|
||||
|
||||
if (NULL == version) {
|
||||
ret = IOT_OTA_ReportUpgradeResult(handle, h_ota->version, IOT_OTAR_UPGRADE_FAIL);
|
||||
} else {
|
||||
ret = IOT_OTA_ReportUpgradeResult(handle, version, IOT_OTAR_UPGRADE_FAIL);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* check whether is downloading */
|
||||
int IOT_OTA_IsFetching(void *handle)
|
||||
{
|
||||
OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
|
||||
|
||||
if (NULL == handle) {
|
||||
Log_e("handle is NULL");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (IOT_OTAS_UNINITED == h_ota->state) {
|
||||
Log_e("handle is uninitialized");
|
||||
h_ota->err = IOT_OTA_ERR_INVALID_STATE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (IOT_OTAS_FETCHING == h_ota->state);
|
||||
}
|
||||
|
||||
/* check whether fetch over */
|
||||
int IOT_OTA_IsFetchFinish(void *handle)
|
||||
{
|
||||
OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
|
||||
|
||||
if (NULL == handle) {
|
||||
Log_e("handle is NULL");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (IOT_OTAS_UNINITED == h_ota->state) {
|
||||
Log_e("handle is uninitialized");
|
||||
h_ota->err = IOT_OTA_ERR_INVALID_STATE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (IOT_OTAS_FETCHED == h_ota->state);
|
||||
}
|
||||
|
||||
int IOT_OTA_FetchYield(void *handle, char *buf, uint32_t buf_len, uint32_t timeout_ms)
|
||||
{
|
||||
int ret;
|
||||
OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
|
||||
|
||||
POINTER_SANITY_CHECK(handle, IOT_OTA_ERR_INVALID_PARAM);
|
||||
POINTER_SANITY_CHECK(buf, IOT_OTA_ERR_INVALID_PARAM);
|
||||
NUMBERIC_SANITY_CHECK(buf_len, IOT_OTA_ERR_INVALID_PARAM);
|
||||
|
||||
if (IOT_OTAS_FETCHING != h_ota->state) {
|
||||
h_ota->err = IOT_OTA_ERR_INVALID_STATE;
|
||||
return IOT_OTA_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
ret = qcloud_ofc_fetch(h_ota->ch_fetch, buf, buf_len, timeout_ms);
|
||||
if (ret < 0) {
|
||||
h_ota->state = IOT_OTAS_FETCHED;
|
||||
h_ota->err = IOT_OTA_ERR_FETCH_FAILED;
|
||||
|
||||
if (ret == IOT_OTA_ERR_FETCH_AUTH_FAIL) { // OTA auth failed
|
||||
IOT_OTA_ReportUpgradeResult(h_ota, h_ota->version, IOT_OTAR_AUTH_FAIL);
|
||||
h_ota->err = ret;
|
||||
} else if (ret == IOT_OTA_ERR_FETCH_NOT_EXIST) { // fetch not existed
|
||||
IOT_OTA_ReportUpgradeResult(h_ota, h_ota->version, IOT_OTAR_FILE_NOT_EXIST);
|
||||
h_ota->err = ret;
|
||||
} else if (ret == IOT_OTA_ERR_FETCH_TIMEOUT) { // fetch timeout
|
||||
IOT_OTA_ReportUpgradeResult(h_ota, h_ota->version, IOT_OTAR_DOWNLOAD_TIMEOUT);
|
||||
h_ota->err = ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
} else if (0 == h_ota->size_fetched) {
|
||||
/* force report status in the first */
|
||||
IOT_OTA_ReportProgress(h_ota, IOT_OTAP_FETCH_PERCENTAGE_MIN, IOT_OTAR_DOWNLOAD_BEGIN);
|
||||
|
||||
InitTimer(&h_ota->report_timer);
|
||||
countdown(&h_ota->report_timer, 1);
|
||||
}
|
||||
|
||||
h_ota->size_last_fetched = ret;
|
||||
h_ota->size_fetched += ret;
|
||||
|
||||
/* report percent every second. */
|
||||
uint32_t percent = (h_ota->size_fetched * 100) / h_ota->size_file;
|
||||
if (percent == 100) {
|
||||
IOT_OTA_ReportProgress(h_ota, percent, IOT_OTAR_DOWNLOADING);
|
||||
} else if (h_ota->size_last_fetched > 0 && expired(&h_ota->report_timer)) {
|
||||
IOT_OTA_ReportProgress(h_ota, percent, IOT_OTAR_DOWNLOADING);
|
||||
countdown(&h_ota->report_timer, 1);
|
||||
}
|
||||
|
||||
if (h_ota->size_fetched >= h_ota->size_file) {
|
||||
h_ota->state = IOT_OTAS_FETCHED;
|
||||
}
|
||||
|
||||
qcloud_otalib_md5_update(h_ota->md5, buf, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int IOT_OTA_Ioctl(void *handle, IOT_OTA_CmdType type, void *buf, size_t buf_len)
|
||||
{
|
||||
OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
|
||||
|
||||
POINTER_SANITY_CHECK(handle, IOT_OTA_ERR_INVALID_PARAM);
|
||||
POINTER_SANITY_CHECK(buf, IOT_OTA_ERR_INVALID_PARAM);
|
||||
NUMBERIC_SANITY_CHECK(buf_len, IOT_OTA_ERR_INVALID_PARAM);
|
||||
|
||||
if (h_ota->state < IOT_OTAS_FETCHING) {
|
||||
h_ota->err = IOT_OTA_ERR_INVALID_STATE;
|
||||
return IOT_OTA_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case IOT_OTAG_FETCHED_SIZE:
|
||||
if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
|
||||
Log_e("Invalid parameter");
|
||||
h_ota->err = IOT_OTA_ERR_INVALID_PARAM;
|
||||
return QCLOUD_ERR_FAILURE;
|
||||
} else {
|
||||
*((uint32_t *)buf) = h_ota->size_fetched;
|
||||
return 0;
|
||||
}
|
||||
|
||||
case IOT_OTAG_FILE_SIZE:
|
||||
if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
|
||||
Log_e("Invalid parameter");
|
||||
h_ota->err = IOT_OTA_ERR_INVALID_PARAM;
|
||||
return QCLOUD_ERR_FAILURE;
|
||||
} else {
|
||||
*((uint32_t *)buf) = h_ota->size_file;
|
||||
return 0;
|
||||
}
|
||||
|
||||
case IOT_OTAG_VERSION:
|
||||
strncpy(buf, h_ota->version, buf_len);
|
||||
((char *)buf)[buf_len - 1] = '\0';
|
||||
break;
|
||||
|
||||
case IOT_OTAG_MD5SUM:
|
||||
strncpy(buf, h_ota->md5sum, buf_len);
|
||||
((char *)buf)[buf_len - 1] = '\0';
|
||||
break;
|
||||
|
||||
case IOT_OTAG_CHECK_FIRMWARE:
|
||||
if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
|
||||
Log_e("Invalid parameter");
|
||||
h_ota->err = IOT_OTA_ERR_INVALID_PARAM;
|
||||
return QCLOUD_ERR_FAILURE;
|
||||
} else if (h_ota->state != IOT_OTAS_FETCHED) {
|
||||
h_ota->err = IOT_OTA_ERR_INVALID_STATE;
|
||||
Log_e("Firmware can be checked in IOT_OTAS_FETCHED state only");
|
||||
return QCLOUD_ERR_FAILURE;
|
||||
} else {
|
||||
char md5_str[33];
|
||||
qcloud_otalib_md5_finalize(h_ota->md5, md5_str);
|
||||
Log_i("FW MD5 check: origin=%s, now=%s", h_ota->md5sum, md5_str);
|
||||
if (0 == strcmp(h_ota->md5sum, md5_str)) {
|
||||
*((uint32_t *)buf) = 1;
|
||||
} else {
|
||||
*((uint32_t *)buf) = 0;
|
||||
// report MD5 inconsistent
|
||||
IOT_OTA_ReportUpgradeResult(h_ota, h_ota->version, IOT_OTAR_MD5_NOT_MATCH);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
default:
|
||||
Log_e("invalid cmd type");
|
||||
h_ota->err = IOT_OTA_ERR_INVALID_PARAM;
|
||||
return QCLOUD_ERR_FAILURE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get last error code */
|
||||
int IOT_OTA_GetLastError(void *handle)
|
||||
{
|
||||
OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
|
||||
|
||||
if (NULL == handle) {
|
||||
Log_e("handle is NULL");
|
||||
return IOT_OTA_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
return h_ota->err;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
201
components/connectivity/qcloud-iot-hub-sdk/3rdparty/sdk_src/services/ota/ota_coap.c
vendored
Normal file
201
components/connectivity/qcloud-iot-hub-sdk/3rdparty/sdk_src/services/ota/ota_coap.c
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making IoT Hub available.
|
||||
* Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is
|
||||
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "qcloud_iot_export.h"
|
||||
#include "qcloud_iot_import.h"
|
||||
|
||||
#ifndef OTA_MQTT_CHANNEL
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ota_client.h"
|
||||
|
||||
typedef struct {
|
||||
void *coap;
|
||||
|
||||
const char *product_id;
|
||||
const char *device_name;
|
||||
|
||||
char topic_upgrade[OTA_MAX_TOPIC_LEN];
|
||||
|
||||
OnOTAMessageCallback msg_callback;
|
||||
|
||||
void *context;
|
||||
} OTA_CoAP_Struct_t;
|
||||
|
||||
static void _otacoap_upgrage_cb(void *coap_message, void *pcontext)
|
||||
{
|
||||
int ret_code = IOT_COAP_GetMessageCode(coap_message);
|
||||
|
||||
switch (ret_code) {
|
||||
case COAP_EVENT_RECEIVE_ACK:
|
||||
Log_i("received OTA message ACK, msgid: %d", IOT_COAP_GetMessageId(coap_message));
|
||||
break;
|
||||
case COAP_EVENT_RECEIVE_RESPCONTENT: {
|
||||
Log_i("received OTA message respconetent.");
|
||||
char *payload = NULL;
|
||||
int payload_len = 0;
|
||||
int ret = -1;
|
||||
ret = IOT_COAP_GetMessagePayload(coap_message, &payload, &payload_len);
|
||||
if (ret == QCLOUD_RET_SUCCESS) {
|
||||
OTA_CoAP_Struct_t *handle = (OTA_CoAP_Struct_t *)pcontext;
|
||||
if (NULL != handle->msg_callback) {
|
||||
handle->msg_callback(handle->context, payload, payload_len);
|
||||
}
|
||||
} else {
|
||||
Log_e("message received response, content error.");
|
||||
}
|
||||
} break;
|
||||
case COAP_EVENT_UNAUTHORIZED:
|
||||
Log_e("coap client auth token expired or invalid, msgid: %d", IOT_COAP_GetMessageId(coap_message));
|
||||
break;
|
||||
case COAP_EVENT_FORBIDDEN:
|
||||
Log_e("coap URI is invalid for this device, msgid: %d", IOT_COAP_GetMessageId(coap_message));
|
||||
break;
|
||||
case COAP_EVENT_INTERNAL_SERVER_ERROR:
|
||||
Log_e("coap server internal error, msgid: %d", IOT_COAP_GetMessageId(coap_message));
|
||||
break;
|
||||
case COAP_EVENT_ACK_TIMEOUT:
|
||||
Log_e("message receive ACK timeout, msgid: %d", IOT_COAP_GetMessageId(coap_message));
|
||||
break;
|
||||
case COAP_EVENT_SEPRESP_TIMEOUT:
|
||||
Log_i("message received ACK but receive response timeout, msgid: %d", IOT_COAP_GetMessageId(coap_message));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate topic name according to @OTATopicType, @productId, @deviceName */
|
||||
/* and then copy to @buf. */
|
||||
/* 0, successful; -1, failed */
|
||||
static int _otacoap_gen_topic_name(char *buf, size_t bufLen, const char *OTATopicType, const char *productId,
|
||||
const char *deviceName)
|
||||
{
|
||||
IOT_FUNC_ENTRY;
|
||||
|
||||
int ret;
|
||||
|
||||
ret = HAL_Snprintf(buf, bufLen, "$ota/%s/%s/%s", OTATopicType, productId, deviceName);
|
||||
|
||||
if (ret >= bufLen)
|
||||
IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL);
|
||||
|
||||
if (ret < 0) {
|
||||
Log_e("HAL_Snprintf failed");
|
||||
IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL);
|
||||
}
|
||||
|
||||
IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS);
|
||||
}
|
||||
|
||||
/* report progress of OTA */
|
||||
static int _otacoap_publish(OTA_CoAP_Struct_t *handle, const char *topicType, const char *msg, bool needResp)
|
||||
{
|
||||
IOT_FUNC_ENTRY;
|
||||
|
||||
int ret;
|
||||
char topic_name[OTA_MAX_TOPIC_LEN];
|
||||
|
||||
SendMsgParams send_params = DEFAULT_SENDMSG_PARAMS;
|
||||
send_params.pay_load = (void *)msg;
|
||||
send_params.pay_load_len = strlen(msg);
|
||||
send_params.resp_callback = _otacoap_upgrage_cb;
|
||||
send_params.need_resp = needResp;
|
||||
send_params.user_context = handle;
|
||||
|
||||
/* inform OTA to topic: "/ota/device/progress/$(product_id)/$(device_name)" */
|
||||
ret = _otacoap_gen_topic_name(topic_name, OTA_MAX_TOPIC_LEN, topicType, handle->product_id, handle->device_name);
|
||||
if (ret < 0) {
|
||||
Log_e("generate topic name of info failed");
|
||||
IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL);
|
||||
}
|
||||
|
||||
ret = IOT_COAP_SendMessage(handle->coap, topic_name, &send_params);
|
||||
if (ret < 0) {
|
||||
Log_e("publish failed");
|
||||
IOT_FUNC_EXIT_RC(IOT_OTA_ERR_OSC_FAILED);
|
||||
}
|
||||
|
||||
IOT_FUNC_EXIT_RC(ret);
|
||||
}
|
||||
|
||||
void *qcloud_osc_init(const char *productId, const char *deviceName, void *channel, OnOTAMessageCallback callback,
|
||||
void *context)
|
||||
{
|
||||
OTA_CoAP_Struct_t *h_osc = NULL;
|
||||
|
||||
if (NULL == (h_osc = HAL_Malloc(sizeof(OTA_CoAP_Struct_t)))) {
|
||||
Log_e("allocate for h_osc failed");
|
||||
goto do_exit;
|
||||
}
|
||||
|
||||
memset(h_osc, 0, sizeof(OTA_CoAP_Struct_t));
|
||||
|
||||
h_osc->coap = channel;
|
||||
h_osc->product_id = productId;
|
||||
h_osc->device_name = deviceName;
|
||||
h_osc->msg_callback = callback;
|
||||
h_osc->context = context;
|
||||
|
||||
return h_osc;
|
||||
|
||||
do_exit:
|
||||
if (NULL != h_osc) {
|
||||
HAL_Free(h_osc);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int qcloud_osc_deinit(void *handle)
|
||||
{
|
||||
IOT_FUNC_ENTRY;
|
||||
|
||||
if (NULL != handle) {
|
||||
HAL_Free(handle);
|
||||
}
|
||||
|
||||
IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS);
|
||||
}
|
||||
|
||||
/* report progress of OTA */
|
||||
int qcloud_osc_report_progress(void *handle, const char *msg)
|
||||
{
|
||||
return _otacoap_publish(handle, "report", msg, false);
|
||||
}
|
||||
|
||||
/* report version of OTA firmware */
|
||||
int qcloud_osc_report_version(void *handle, const char *msg)
|
||||
{
|
||||
return _otacoap_publish(handle, "report", msg, true);
|
||||
}
|
||||
|
||||
/* report upgrade begin of OTA firmware */
|
||||
int qcloud_osc_report_upgrade_result(void *handle, const char *msg)
|
||||
{
|
||||
return _otacoap_publish(handle, "report", msg, false);
|
||||
}
|
||||
|
||||
/* OSC, OTA signal channel */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
148
components/connectivity/qcloud-iot-hub-sdk/3rdparty/sdk_src/services/ota/ota_fetch.c
vendored
Normal file
148
components/connectivity/qcloud-iot-hub-sdk/3rdparty/sdk_src/services/ota/ota_fetch.c
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making IoT Hub available.
|
||||
* Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is
|
||||
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ota_fetch.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "qcloud_iot_ca.h"
|
||||
#include "qcloud_iot_export.h"
|
||||
#include "qcloud_iot_import.h"
|
||||
#include "utils_httpc.h"
|
||||
|
||||
#define OTA_HTTP_HEAD_CONTENT_LEN 256
|
||||
|
||||
/* ofc, OTA fetch channel */
|
||||
|
||||
typedef struct {
|
||||
const char * url;
|
||||
HTTPClient http; /* http client */
|
||||
HTTPClientData http_data; /* http client data */
|
||||
|
||||
} OTAHTTPStruct;
|
||||
|
||||
#ifdef OTA_USE_HTTPS
|
||||
static int is_begin_with(const char *str1, char *str2)
|
||||
{
|
||||
if (str1 == NULL || str2 == NULL)
|
||||
return -1;
|
||||
int len1 = strlen(str1);
|
||||
int len2 = strlen(str2);
|
||||
if ((len1 < len2) || (len1 == 0 || len2 == 0))
|
||||
return -1;
|
||||
char *p = str2;
|
||||
int i = 0;
|
||||
while (*p != '\0') {
|
||||
if (*p != str1[i])
|
||||
return 0;
|
||||
p++;
|
||||
i++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static char sg_head_content[OTA_HTTP_HEAD_CONTENT_LEN];
|
||||
void * ofc_Init(const char *url, uint32_t offset, uint32_t size)
|
||||
{
|
||||
OTAHTTPStruct *h_odc;
|
||||
|
||||
if (NULL == (h_odc = HAL_Malloc(sizeof(OTAHTTPStruct)))) {
|
||||
Log_e("allocate for h_odc failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(h_odc, 0, sizeof(OTAHTTPStruct));
|
||||
memset(sg_head_content, 0, OTA_HTTP_HEAD_CONTENT_LEN);
|
||||
HAL_Snprintf(sg_head_content, OTA_HTTP_HEAD_CONTENT_LEN,
|
||||
"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",
|
||||
offset, size);
|
||||
|
||||
Log_d("head_content:%s", sg_head_content);
|
||||
/* set http request-header parameter */
|
||||
h_odc->http.header = sg_head_content;
|
||||
h_odc->url = url;
|
||||
|
||||
return h_odc;
|
||||
}
|
||||
|
||||
int32_t qcloud_ofc_connect(void *handle)
|
||||
{
|
||||
IOT_FUNC_ENTRY;
|
||||
|
||||
OTAHTTPStruct *h_odc = (OTAHTTPStruct *)handle;
|
||||
|
||||
int port = 80;
|
||||
const char *ca_crt = NULL;
|
||||
|
||||
#ifdef OTA_USE_HTTPS
|
||||
if (is_begin_with(h_odc->url, "https")) {
|
||||
port = 443;
|
||||
ca_crt = iot_https_ca_get();
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t rc = qcloud_http_client_common(&h_odc->http, h_odc->url, port, ca_crt, HTTP_GET, &h_odc->http_data);
|
||||
|
||||
IOT_FUNC_EXIT_RC(rc);
|
||||
}
|
||||
|
||||
int32_t qcloud_ofc_fetch(void *handle, char *buf, uint32_t bufLen, uint32_t timeout_s)
|
||||
{
|
||||
IOT_FUNC_ENTRY;
|
||||
|
||||
int diff;
|
||||
OTAHTTPStruct *h_odc = (OTAHTTPStruct *)handle;
|
||||
|
||||
h_odc->http_data.response_buf = buf;
|
||||
h_odc->http_data.response_buf_len = bufLen;
|
||||
diff = h_odc->http_data.response_content_len - h_odc->http_data.retrieve_len;
|
||||
|
||||
int rc = qcloud_http_recv_data(&h_odc->http, timeout_s * 1000, &h_odc->http_data);
|
||||
if (QCLOUD_RET_SUCCESS != rc) {
|
||||
if (rc == QCLOUD_ERR_HTTP_NOT_FOUND)
|
||||
IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FETCH_NOT_EXIST);
|
||||
|
||||
if (rc == QCLOUD_ERR_HTTP_AUTH)
|
||||
IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FETCH_AUTH_FAIL);
|
||||
|
||||
if (rc == QCLOUD_ERR_HTTP_TIMEOUT)
|
||||
IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FETCH_TIMEOUT);
|
||||
|
||||
IOT_FUNC_EXIT_RC(rc);
|
||||
}
|
||||
|
||||
IOT_FUNC_EXIT_RC(h_odc->http_data.response_content_len - h_odc->http_data.retrieve_len - diff);
|
||||
}
|
||||
|
||||
int qcloud_ofc_deinit(void *handle)
|
||||
{
|
||||
IOT_FUNC_ENTRY;
|
||||
if (NULL != handle) {
|
||||
HAL_Free(handle);
|
||||
}
|
||||
|
||||
IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
318
components/connectivity/qcloud-iot-hub-sdk/3rdparty/sdk_src/services/ota/ota_lib.c
vendored
Normal file
318
components/connectivity/qcloud-iot-hub-sdk/3rdparty/sdk_src/services/ota/ota_lib.c
vendored
Normal file
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making IoT Hub available.
|
||||
* Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is
|
||||
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ota_lib.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lite-utils.h"
|
||||
#include "ota_client.h"
|
||||
#include "qcloud_iot_export.h"
|
||||
#include "qcloud_iot_import.h"
|
||||
#include "utils_md5.h"
|
||||
|
||||
/* Get the specific @key value, and copy to @dest */
|
||||
/* 0, successful; -1, failed */
|
||||
static int _qcloud_otalib_get_firmware_fixlen_para(const char *json_doc, const char *key, char *dest, size_t dest_len)
|
||||
{
|
||||
IOT_FUNC_ENTRY;
|
||||
|
||||
int ret = QCLOUD_RET_SUCCESS;
|
||||
|
||||
char *key_bak = HAL_Malloc(strlen(key) + 1);
|
||||
if (key_bak == NULL) {
|
||||
Log_e("not enough memory for malloc key");
|
||||
ret = IOT_OTA_ERR_FAIL;
|
||||
IOT_FUNC_EXIT_RC(ret);
|
||||
}
|
||||
|
||||
char *json_doc_bak = HAL_Malloc(strlen(json_doc) + 1);
|
||||
if (json_doc_bak == NULL) {
|
||||
Log_e("not enough memory for malloc json");
|
||||
HAL_Free(key_bak);
|
||||
ret = IOT_OTA_ERR_FAIL;
|
||||
IOT_FUNC_EXIT_RC(ret);
|
||||
}
|
||||
|
||||
strcpy(key_bak, key);
|
||||
strcpy(json_doc_bak, json_doc);
|
||||
|
||||
char *value = LITE_json_value_of(key_bak, json_doc_bak);
|
||||
if (value == NULL) {
|
||||
Log_e("Not '%s' key in json doc of OTA", key);
|
||||
ret = IOT_OTA_ERR_FAIL;
|
||||
} else {
|
||||
uint32_t val_len = strlen(value);
|
||||
if (val_len > dest_len) {
|
||||
Log_e("value length of the key is too long");
|
||||
ret = IOT_OTA_ERR_FAIL;
|
||||
} else {
|
||||
memcpy(dest, value, val_len);
|
||||
ret = QCLOUD_RET_SUCCESS;
|
||||
}
|
||||
|
||||
HAL_Free(value);
|
||||
}
|
||||
|
||||
if (key_bak != NULL) {
|
||||
HAL_Free(key_bak);
|
||||
}
|
||||
if (json_doc_bak != NULL) {
|
||||
HAL_Free(json_doc_bak);
|
||||
}
|
||||
|
||||
IOT_FUNC_EXIT_RC(ret);
|
||||
}
|
||||
|
||||
/* Get variant length parameter of firmware, and copy to @dest */
|
||||
/* 0, successful; -1, failed */
|
||||
static int _qcloud_otalib_get_firmware_varlen_para(const char *json_doc, const char *key, char **dest)
|
||||
{
|
||||
#define OTA_FIRMWARE_JSON_VALUE_MAX_LENGTH (64)
|
||||
|
||||
IOT_FUNC_ENTRY;
|
||||
|
||||
int ret = QCLOUD_RET_SUCCESS;
|
||||
|
||||
char *key_bak = HAL_Malloc(strlen(key) + 1);
|
||||
if (key_bak == NULL) {
|
||||
Log_e("not enough memory for malloc key");
|
||||
ret = IOT_OTA_ERR_FAIL;
|
||||
IOT_FUNC_EXIT_RC(ret);
|
||||
}
|
||||
|
||||
char *json_doc_bak = HAL_Malloc(strlen(json_doc) + 1);
|
||||
if (json_doc_bak == NULL) {
|
||||
Log_e("not enough memory for malloc json");
|
||||
HAL_Free(key_bak);
|
||||
ret = IOT_OTA_ERR_FAIL;
|
||||
IOT_FUNC_EXIT_RC(ret);
|
||||
}
|
||||
|
||||
strcpy(key_bak, key);
|
||||
strcpy(json_doc_bak, json_doc);
|
||||
|
||||
*dest = LITE_json_value_of(key_bak, json_doc_bak);
|
||||
if (*dest == NULL) {
|
||||
Log_e("Not '%s' key in json '%s' doc of OTA", key_bak, json_doc_bak);
|
||||
ret = IOT_OTA_ERR_FAIL;
|
||||
}
|
||||
|
||||
if (key_bak != NULL) {
|
||||
HAL_Free(key_bak);
|
||||
}
|
||||
if (json_doc_bak != NULL) {
|
||||
HAL_Free(json_doc_bak);
|
||||
}
|
||||
|
||||
IOT_FUNC_EXIT_RC(ret);
|
||||
|
||||
#undef OTA_FIRMWARE_JSON_VALUE_MAX_LENGTH
|
||||
}
|
||||
|
||||
void *qcloud_otalib_md5_init(void)
|
||||
{
|
||||
iot_md5_context *ctx = HAL_Malloc(sizeof(iot_md5_context));
|
||||
if (NULL == ctx) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
utils_md5_init(ctx);
|
||||
utils_md5_starts(ctx);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void qcloud_otalib_md5_update(void *md5, const char *buf, size_t buf_len)
|
||||
{
|
||||
utils_md5_update(md5, (unsigned char *)buf, buf_len);
|
||||
}
|
||||
|
||||
void qcloud_otalib_md5_finalize(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] = utils_hb2hex(buf_out[i] >> 4);
|
||||
output_str[i * 2 + 1] = utils_hb2hex(buf_out[i]);
|
||||
}
|
||||
output_str[32] = '\0';
|
||||
}
|
||||
|
||||
void qcloud_otalib_md5_deinit(void *md5)
|
||||
{
|
||||
if (NULL != md5) {
|
||||
HAL_Free(md5);
|
||||
}
|
||||
}
|
||||
|
||||
int qcloud_otalib_get_firmware_type(const char *json, char **type)
|
||||
{
|
||||
return _qcloud_otalib_get_firmware_varlen_para(json, TYPE_FIELD, type);
|
||||
}
|
||||
|
||||
int qcloud_otalib_get_report_version_result(const char *json)
|
||||
{
|
||||
IOT_FUNC_ENTRY;
|
||||
|
||||
char *result_code = NULL;
|
||||
|
||||
int rc = _qcloud_otalib_get_firmware_varlen_para(json, RESULT_FIELD, &result_code);
|
||||
if (rc != QCLOUD_RET_SUCCESS || strcmp(result_code, "0") != 0) {
|
||||
if (NULL != result_code)
|
||||
HAL_Free(result_code);
|
||||
IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL);
|
||||
}
|
||||
|
||||
if (NULL != result_code)
|
||||
HAL_Free(result_code);
|
||||
IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS);
|
||||
}
|
||||
|
||||
int qcloud_otalib_get_params(const char *json, char **type, char **url, char **version, char *md5, uint32_t *fileSize)
|
||||
{
|
||||
#define OTA_FILESIZE_STR_LEN (16)
|
||||
|
||||
IOT_FUNC_ENTRY;
|
||||
|
||||
char file_size_str[OTA_FILESIZE_STR_LEN + 1] = {0};
|
||||
|
||||
/* get type */
|
||||
if (0 != _qcloud_otalib_get_firmware_varlen_para(json, TYPE_FIELD, type)) {
|
||||
Log_e("get value of type key failed");
|
||||
IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL);
|
||||
}
|
||||
|
||||
/* get version */
|
||||
if (0 != _qcloud_otalib_get_firmware_varlen_para(json, VERSION_FIELD, version)) {
|
||||
Log_e("get value of version key failed");
|
||||
IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL);
|
||||
}
|
||||
|
||||
/* get URL */
|
||||
if (0 != _qcloud_otalib_get_firmware_varlen_para(json, URL_FIELD, url)) {
|
||||
Log_e("get value of url key failed");
|
||||
IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL);
|
||||
}
|
||||
|
||||
/* get md5 */
|
||||
if (0 != _qcloud_otalib_get_firmware_fixlen_para(json, MD5_FIELD, md5, 32)) {
|
||||
Log_e("get value of md5 key failed");
|
||||
IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL);
|
||||
}
|
||||
|
||||
/* get file size */
|
||||
if (0 != _qcloud_otalib_get_firmware_fixlen_para(json, FILESIZE_FIELD, file_size_str, OTA_FILESIZE_STR_LEN)) {
|
||||
Log_e("get value of size key failed");
|
||||
IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL);
|
||||
}
|
||||
|
||||
file_size_str[OTA_FILESIZE_STR_LEN] = '\0';
|
||||
*fileSize = atoi(file_size_str);
|
||||
|
||||
IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS);
|
||||
|
||||
#undef OTA_FILESIZE_STR_LEN
|
||||
}
|
||||
|
||||
int qcloud_otalib_gen_info_msg(char *buf, size_t bufLen, uint32_t id, const char *version)
|
||||
{
|
||||
IOT_FUNC_ENTRY;
|
||||
|
||||
int ret;
|
||||
ret = HAL_Snprintf(buf, bufLen, "{\"type\": \"report_version\", \"report\":{\"version\":\"%s\"}}", version);
|
||||
|
||||
if (ret < 0) {
|
||||
Log_e("HAL_Snprintf failed");
|
||||
IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
|
||||
}
|
||||
|
||||
IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS);
|
||||
}
|
||||
|
||||
int qcloud_otalib_gen_report_msg(char *buf, size_t bufLen, uint32_t id, const char *version, int progress,
|
||||
IOT_OTAReportType reportType)
|
||||
{
|
||||
IOT_FUNC_ENTRY;
|
||||
|
||||
int ret;
|
||||
|
||||
switch (reportType) {
|
||||
/* report OTA download begin */
|
||||
case IOT_OTAR_DOWNLOAD_BEGIN:
|
||||
ret = HAL_Snprintf(buf, bufLen,
|
||||
"{\"type\": \"report_progress\", \"report\": {\"progress\": {\"state\":\"downloading\", "
|
||||
"\"percent\":\"0\", \"result_code\":\"0\", \"result_msg\":\"\"}, \"version\": \"%s\"}}",
|
||||
version);
|
||||
break;
|
||||
/* report OTA download progress */
|
||||
case IOT_OTAR_DOWNLOADING:
|
||||
ret = HAL_Snprintf(buf, bufLen,
|
||||
"{\"type\": \"report_progress\", \"report\": {\"progress\": {\"state\":\"downloading\", "
|
||||
"\"percent\":\"%d\", \"result_code\":\"0\", \"result_msg\":\"\"}, \"version\": \"%s\"}}",
|
||||
progress, version);
|
||||
break;
|
||||
case IOT_OTAR_DOWNLOAD_TIMEOUT:
|
||||
case IOT_OTAR_FILE_NOT_EXIST:
|
||||
case IOT_OTAR_MD5_NOT_MATCH:
|
||||
case IOT_OTAR_AUTH_FAIL:
|
||||
case IOT_OTAR_UPGRADE_FAIL:
|
||||
ret = HAL_Snprintf(buf, bufLen,
|
||||
"{\"type\": \"report_progress\", \"report\": {\"progress\": {\"state\":\"fail\", "
|
||||
"\"result_code\":\"%d\", \"result_msg\":\"time_out\"}, \"version\": \"%s\"}}",
|
||||
reportType, version);
|
||||
break;
|
||||
/* report OTA upgrade begin */
|
||||
case IOT_OTAR_UPGRADE_BEGIN:
|
||||
ret = HAL_Snprintf(buf, bufLen,
|
||||
"{\"type\": \"report_progress\", \"report\":{\"progress\":{\"state\":\"burning\", "
|
||||
"\"result_code\":\"0\", \"result_msg\":\"\"}, \"version\":\"%s\"}}",
|
||||
version);
|
||||
break;
|
||||
|
||||
/* report OTA upgrade finish */
|
||||
case IOT_OTAR_UPGRADE_SUCCESS:
|
||||
ret = HAL_Snprintf(buf, bufLen,
|
||||
"{\"type\": \"report_progress\", \"report\":{\"progress\":{\"state\":\"done\", "
|
||||
"\"result_code\":\"0\", \"result_msg\":\"\"}, \"version\":\"%s\"}}",
|
||||
version);
|
||||
break;
|
||||
|
||||
default:
|
||||
IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
Log_e("HAL_Snprintf failed");
|
||||
IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL);
|
||||
} else if (ret >= bufLen) {
|
||||
Log_e("msg is too long");
|
||||
IOT_FUNC_EXIT_RC(IOT_OTA_ERR_STR_TOO_LONG);
|
||||
}
|
||||
|
||||
IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
242
components/connectivity/qcloud-iot-hub-sdk/3rdparty/sdk_src/services/ota/ota_mqtt.c
vendored
Normal file
242
components/connectivity/qcloud-iot-hub-sdk/3rdparty/sdk_src/services/ota/ota_mqtt.c
vendored
Normal file
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making IoT Hub available.
|
||||
* Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is
|
||||
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "qcloud_iot_export.h"
|
||||
#include "qcloud_iot_import.h"
|
||||
|
||||
#ifdef OTA_MQTT_CHANNEL
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ota_client.h"
|
||||
|
||||
/* OSC, OTA signal channel */
|
||||
typedef struct {
|
||||
void *mqtt; // MQTT cient
|
||||
|
||||
const char *product_id;
|
||||
const char *device_name;
|
||||
|
||||
char topic_upgrade[OTA_MAX_TOPIC_LEN]; // OTA MQTT Topic
|
||||
OnOTAMessageCallback msg_callback;
|
||||
|
||||
void *context;
|
||||
bool topic_ready;
|
||||
} OTA_MQTT_Struct_t;
|
||||
|
||||
/* Generate topic name according to @OTATopicType, @productId, @deviceName */
|
||||
/* and then copy to @buf. */
|
||||
/* 0, successful; -1, failed */
|
||||
static int _otamqtt_gen_topic_name(char *buf, size_t bufLen, const char *OTATopicType, const char *productId,
|
||||
const char *deviceName)
|
||||
{
|
||||
IOT_FUNC_ENTRY;
|
||||
|
||||
int ret;
|
||||
|
||||
ret = HAL_Snprintf(buf, bufLen, "$ota/%s/%s/%s", OTATopicType, productId, deviceName);
|
||||
|
||||
if (ret >= bufLen)
|
||||
IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL);
|
||||
|
||||
if (ret < 0) {
|
||||
Log_e("HAL_Snprintf failed");
|
||||
IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL);
|
||||
}
|
||||
|
||||
IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS);
|
||||
}
|
||||
|
||||
/* report progress of OTA */
|
||||
static int _otamqtt_publish(OTA_MQTT_Struct_t *handle, const char *topicType, int qos, const char *msg)
|
||||
{
|
||||
IOT_FUNC_ENTRY;
|
||||
|
||||
int ret;
|
||||
char topic_name[OTA_MAX_TOPIC_LEN];
|
||||
PublishParams pub_params = DEFAULT_PUB_PARAMS;
|
||||
|
||||
if (0 == qos) {
|
||||
pub_params.qos = QOS0;
|
||||
} else {
|
||||
pub_params.qos = QOS1;
|
||||
}
|
||||
pub_params.payload = (void *)msg;
|
||||
pub_params.payload_len = strlen(msg);
|
||||
|
||||
/* inform OTA to topic: "/ota/device/progress/$(product_id)/$(device_name)" */
|
||||
ret = _otamqtt_gen_topic_name(topic_name, OTA_MAX_TOPIC_LEN, topicType, handle->product_id, handle->device_name);
|
||||
if (ret < 0) {
|
||||
Log_e("generate topic name of info failed");
|
||||
IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL);
|
||||
}
|
||||
|
||||
ret = IOT_MQTT_Publish(handle->mqtt, topic_name, &pub_params);
|
||||
if (ret < 0) {
|
||||
Log_e("publish to topic: %s failed", topic_name);
|
||||
IOT_FUNC_EXIT_RC(IOT_OTA_ERR_OSC_FAILED);
|
||||
}
|
||||
|
||||
IOT_FUNC_EXIT_RC(ret);
|
||||
}
|
||||
|
||||
/* callback after OTA topic is subscribed */
|
||||
/* Parse firmware info (version/URL/file size/MD5) from JSON text */
|
||||
static void _otamqtt_upgrage_cb(void *pClient, MQTTMessage *message, void *pcontext)
|
||||
{
|
||||
OTA_MQTT_Struct_t *handle = (OTA_MQTT_Struct_t *)pcontext;
|
||||
|
||||
Log_d("topic=%.*s", message->topic_len, message->ptopic);
|
||||
Log_i("len=%u, topic_msg=%.*s", message->payload_len, message->payload_len, (char *)message->payload);
|
||||
|
||||
if (NULL != handle->msg_callback) {
|
||||
handle->msg_callback(handle->context, message->payload, message->payload_len);
|
||||
}
|
||||
}
|
||||
|
||||
static void _otamqtt_event_callback(void *pclient, MQTTEventType event_type, void *user_data)
|
||||
{
|
||||
OTA_MQTT_Struct_t *h_osc = (OTA_MQTT_Struct_t *)user_data;
|
||||
|
||||
switch (event_type) {
|
||||
case MQTT_EVENT_SUBCRIBE_SUCCESS:
|
||||
Log_d("OTA topic subscribe success");
|
||||
h_osc->topic_ready = true;
|
||||
break;
|
||||
|
||||
case MQTT_EVENT_SUBCRIBE_TIMEOUT:
|
||||
Log_i("OTA topic subscribe timeout");
|
||||
h_osc->topic_ready = false;
|
||||
break;
|
||||
|
||||
case MQTT_EVENT_SUBCRIBE_NACK:
|
||||
Log_i("OTA topic subscribe NACK");
|
||||
h_osc->topic_ready = false;
|
||||
break;
|
||||
case MQTT_EVENT_UNSUBSCRIBE:
|
||||
Log_i("OTA topic has been unsubscribed");
|
||||
h_osc->topic_ready = false;
|
||||
;
|
||||
break;
|
||||
case MQTT_EVENT_CLIENT_DESTROY:
|
||||
Log_i("mqtt client has been destroyed");
|
||||
h_osc->topic_ready = false;
|
||||
;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void *qcloud_osc_init(const char *productId, const char *deviceName, void *channel, OnOTAMessageCallback callback,
|
||||
void *context)
|
||||
{
|
||||
int ret;
|
||||
OTA_MQTT_Struct_t *h_osc = NULL;
|
||||
|
||||
if (NULL == (h_osc = HAL_Malloc(sizeof(OTA_MQTT_Struct_t)))) {
|
||||
Log_e("allocate for h_osc failed");
|
||||
goto do_exit;
|
||||
}
|
||||
|
||||
memset(h_osc, 0, sizeof(OTA_MQTT_Struct_t));
|
||||
|
||||
/* subscribe the OTA topic: "$ota/update/$(product_id)/$(device_name)" */
|
||||
ret = _otamqtt_gen_topic_name(h_osc->topic_upgrade, OTA_MAX_TOPIC_LEN, "update", productId, deviceName);
|
||||
if (ret < 0) {
|
||||
Log_e("generate topic name of upgrade failed");
|
||||
goto do_exit;
|
||||
}
|
||||
|
||||
SubscribeParams sub_params = DEFAULT_SUB_PARAMS;
|
||||
sub_params.on_message_handler = _otamqtt_upgrage_cb;
|
||||
sub_params.on_sub_event_handler = _otamqtt_event_callback;
|
||||
sub_params.qos = QOS1;
|
||||
sub_params.user_data = h_osc;
|
||||
|
||||
ret = IOT_MQTT_Subscribe(channel, h_osc->topic_upgrade, &sub_params);
|
||||
if (ret < 0) {
|
||||
Log_e("ota mqtt subscribe failed!");
|
||||
goto do_exit;
|
||||
}
|
||||
|
||||
int wait_cnt = 10;
|
||||
while (!h_osc->topic_ready && (wait_cnt > 0)) {
|
||||
// wait for subscription result
|
||||
IOT_MQTT_Yield(channel, 200);
|
||||
wait_cnt--;
|
||||
}
|
||||
|
||||
if (wait_cnt == 0) {
|
||||
Log_e("ota mqtt subscribe timeout!");
|
||||
goto do_exit;
|
||||
}
|
||||
|
||||
h_osc->mqtt = channel;
|
||||
h_osc->product_id = productId;
|
||||
h_osc->device_name = deviceName;
|
||||
h_osc->msg_callback = callback;
|
||||
h_osc->context = context;
|
||||
|
||||
return h_osc;
|
||||
|
||||
do_exit:
|
||||
if (NULL != h_osc) {
|
||||
HAL_Free(h_osc);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int qcloud_osc_deinit(void *handle)
|
||||
{
|
||||
IOT_FUNC_ENTRY;
|
||||
|
||||
if (NULL != handle) {
|
||||
OTA_MQTT_Struct_t *h_osc = (OTA_MQTT_Struct_t *)handle;
|
||||
IOT_MQTT_Unsubscribe(h_osc->mqtt, h_osc->topic_upgrade);
|
||||
HAL_Free(handle);
|
||||
}
|
||||
|
||||
IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS);
|
||||
}
|
||||
|
||||
/* report progress of OTA */
|
||||
int qcloud_osc_report_progress(void *handle, const char *msg)
|
||||
{
|
||||
return _otamqtt_publish(handle, "report", QOS0, msg);
|
||||
}
|
||||
|
||||
/* report version of OTA firmware */
|
||||
int qcloud_osc_report_version(void *handle, const char *msg)
|
||||
{
|
||||
return _otamqtt_publish(handle, "report", QOS1, msg);
|
||||
}
|
||||
|
||||
/* report upgrade begin of OTA firmware */
|
||||
int qcloud_osc_report_upgrade_result(void *handle, const char *msg)
|
||||
{
|
||||
return _otamqtt_publish(handle, "report", QOS1, msg);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
Reference in New Issue
Block a user