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:
daishengdong
2020-05-07 11:11:04 +08:00
parent c8e39739d3
commit 3e631cd96a
594 changed files with 47287 additions and 44165 deletions

View 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

View 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

View 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

View 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

View 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