From 4b1572fd6117da630161b48c11c6a8457c194836 Mon Sep 17 00:00:00 2001 From: "ethan.du" Date: Tue, 11 Aug 2020 16:32:36 +0800 Subject: [PATCH] support dev model ex and ota module --- ports/rtthread/HAL_Flash_Platform.h | 51 ++ ports/rtthread/HAL_Flash_rtthread.c | 71 ++ samples/dev_model/dev_model_sample.c | 10 +- samples/ota/ota_sample.c | 4 +- .../rt_ota_packaging_tool.exe.config | 2 +- uiot/dev_model/include/dm_config.h | 6 +- uiot/dev_model/include/dm_internal.h | 6 + uiot/dev_model/src/dm_client.c | 60 ++ uiot/dev_model/src/dm_mqtt.c | 629 ++++++++++++++++-- uiot/ota/include/ota_config.h | 12 +- uiot/ota/include/ota_internal.h | 63 +- uiot/ota/src/ota_client.c | 289 +++++--- uiot/ota/src/ota_fetch.c | 9 - uiot/ota/src/ota_lib.c | 42 +- uiot/ota/src/ota_mqtt.c | 19 +- uiot/sdk-impl/uiot_defs.h | 14 +- uiot/sdk-impl/uiot_export_dm.h | 119 +++- uiot/sdk-impl/uiot_export_ota.h | 60 +- uiot/sdk-impl/uiot_import.h | 98 ++- 19 files changed, 1312 insertions(+), 252 deletions(-) create mode 100644 ports/rtthread/HAL_Flash_Platform.h create mode 100644 ports/rtthread/HAL_Flash_rtthread.c diff --git a/ports/rtthread/HAL_Flash_Platform.h b/ports/rtthread/HAL_Flash_Platform.h new file mode 100644 index 0000000..d5c9674 --- /dev/null +++ b/ports/rtthread/HAL_Flash_Platform.h @@ -0,0 +1,51 @@ +#ifndef _HAL_FLASH_H_ +#define _HAL_FLASH_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +#include "uiot_import.h" + +/** + * @brief 设置相应name + * + * @param handle 指向download_name的指针 + * @return 指向download_name的指针 + */ +void * HAL_Download_Name_Set(void * handle); + +/** + * @brief 分区结构体初始化以及擦除FLASH等操作 + * + * @param name 分区名 + * @return 指向分区结构体的指针 + */ +void * HAL_Download_Init(_IN_ void * name); + +/** +* @brief 将长度为length的buffer_read的数据写入到FLASH中 + * + * @param handle 指向分区结构体的指针 + * @param total_length 数据包总长度 + * @param buffer_read 数据的指针 + * @param length 数据的长度,单位为字节 + * @return -1失败 0成功 + */ +int HAL_Download_Write(_IN_ void * handle,_IN_ uint32_t total_length,_IN_ uint8_t *buffer_read,_IN_ uint32_t length); + +/** + * @brief STM32F767 FLASH的information分区的下载标志置位成功 + * + * @param 指向分区结构体的指针 + * @return -1失败 0成功 + */ +int HAL_Download_End(_IN_ void * handle); + + +#if defined(__cplusplus) +} +#endif +#endif /* _HAL_FLASH_H_ */ + + diff --git a/ports/rtthread/HAL_Flash_rtthread.c b/ports/rtthread/HAL_Flash_rtthread.c new file mode 100644 index 0000000..7cf7185 --- /dev/null +++ b/ports/rtthread/HAL_Flash_rtthread.c @@ -0,0 +1,71 @@ +/* +* Copyright (C) 2012-2019 UCloud. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"). +* You may not use this file except in compliance with the License. +* A copy of the License is located at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* or in the "license" file accompanying this file. This file 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. +*/ + +#include "HAL_Flash_Platform.h" +#include + +#define DOWNLOAD_PARTITION "download" + +void * HAL_Download_Name_Set(void * handle) +{ + return (void *)DOWNLOAD_PARTITION; +} + + +void * HAL_Download_Init(_IN_ void * name) +{ + char * file_name =(char *)name; + const struct fal_partition * dl_part = RT_NULL; + if ((dl_part = fal_partition_find(file_name)) == RT_NULL) + { + LOG_ERROR("Firmware download failed! Partition (%s) find error!", file_name); + return NULL; + } + + LOG_INFO("Start erase flash (%s) partition!", dl_part->name); + + if (fal_partition_erase_all(dl_part) < 0) + { + LOG_ERROR("Firmware download failed! Partition (%s) erase error!", dl_part->name); + return NULL; + } + LOG_INFO("Erase flash (%s) partition success!", dl_part->name); + + return (void *)dl_part; +} + +int HAL_Download_Write(_IN_ void * handle,_IN_ uint32_t total_length,_IN_ uint8_t *buffer_read,_IN_ uint32_t length) +{ + const struct fal_partition * dl_part = (struct fal_partition *) handle; + if(dl_part==NULL) + return FAILURE_RET; + if (fal_partition_write(dl_part, total_length, buffer_read, length) < 0){ + LOG_ERROR("Firmware download failed! Partition (%s) write data error!", dl_part->name); + return FAILURE_RET; + } + return SUCCESS_RET; +} + +int HAL_Download_End(_IN_ void * handle) +{ + LOG_INFO("System now will restart..."); + rt_thread_delay(rt_tick_from_millisecond(5)); + /* Reset the device, Start new firmware */ + extern void rt_hw_cpu_reset(void); + rt_hw_cpu_reset(); + return SUCCESS_RET; +} + + diff --git a/samples/dev_model/dev_model_sample.c b/samples/dev_model/dev_model_sample.c index e164904..9e9664b 100644 --- a/samples/dev_model/dev_model_sample.c +++ b/samples/dev_model/dev_model_sample.c @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -80,10 +81,9 @@ int property_post_cb(const char *request_id, const int ret_code){ return SUCCESS_RET; } -int command_cb(const char *request_id, const char *identifier, const char *input, char **output){ +int command_cb(const char *request_id, const char *identifier, const char *input, char *output){ LOG_INFO("command_cb; request_id: %s; identifier: %s; input: %s", request_id, identifier, input); - *output = (char *)HAL_Malloc(100); - HAL_Snprintf(*output, 1000, "{\"result\":%d}", 1); + HAL_Snprintf(output, 1000, "{\"result\":%d}", 1); return SUCCESS_RET; } @@ -140,8 +140,8 @@ static void mqtt_devmodel_thread(void) IOT_DM_Yield(h_dm, 200); for (i = 0; i < 10; i++) { - IOT_DM_Property_Report(h_dm, PROPERTY_POST, i * 2, "{\"volume\": {\"Value\":50}}"); - IOT_DM_TriggerEvent(h_dm, i * 2 + 1, "low_power_alert", "{\"power\": 5}"); + IOT_DM_Property_Report(h_dm, PROPERTY_POST, i * 2, "\"volume\": {\"Value\":50}"); + IOT_DM_TriggerEvent(h_dm, i * 2 + 1, "low_power_alert", "\"power\": 5"); IOT_DM_Yield(h_dm, 200); HAL_SleepMs(2000); diff --git a/samples/ota/ota_sample.c b/samples/ota/ota_sample.c index cf7a487..6cdabaa 100644 --- a/samples/ota/ota_sample.c +++ b/samples/ota/ota_sample.c @@ -110,12 +110,12 @@ static void ota_test_thread(void) } /* Must report version first */ - if (IOT_OTA_ReportVersion(h_ota, "1.0.0") < 0) { + if (IOT_OTA_ReportVersion(h_ota, "default", "1.0.0") < 0) { LOG_ERROR("report OTA version failed"); return; } - if (IOT_OTA_RequestFirmware(h_ota, "1.0.0") < 0) { + if (IOT_OTA_RequestFirmware(h_ota, "default", "1.0.0") < 0) { LOG_ERROR("Request firmware failed"); return; } diff --git a/tools/ota_packager/rt_ota_packaging_tool.exe.config b/tools/ota_packager/rt_ota_packaging_tool.exe.config index 1384560..2cd85d3 100644 --- a/tools/ota_packager/rt_ota_packaging_tool.exe.config +++ b/tools/ota_packager/rt_ota_packaging_tool.exe.config @@ -6,5 +6,5 @@ - + \ No newline at end of file diff --git a/uiot/dev_model/include/dm_config.h b/uiot/dev_model/include/dm_config.h index 4992a8e..0d57c15 100644 --- a/uiot/dev_model/include/dm_config.h +++ b/uiot/dev_model/include/dm_config.h @@ -22,9 +22,9 @@ extern "C" { #define DM_TOPIC_BUF_LEN (128) #define DM_MSG_REPLY_BUF_LEN (128) -#define DM_MSG_REPORT_BUF_LEN (256) -#define DM_EVENT_POST_BUF_LEN (256) -#define DM_CMD_REPLY_BUF_LEN (256) +#define DM_MSG_REPORT_BUF_LEN (2048) +#define DM_EVENT_POST_BUF_LEN (2048) +#define DM_CMD_REPLY_BUF_LEN (2048) //pub #define PROPERTY_RESTORE_TOPIC_TEMPLATE "/$system/%s/%s/tmodel/property/restore" diff --git a/uiot/dev_model/include/dm_internal.h b/uiot/dev_model/include/dm_internal.h index d4466f1..c3eebb0 100644 --- a/uiot/dev_model/include/dm_internal.h +++ b/uiot/dev_model/include/dm_internal.h @@ -67,10 +67,16 @@ void *dsc_init(const char *product_sn, const char *device_sn, void *channel, voi int dsc_deinit(void *handle); +int dm_gen_properties_payload(DM_Property_t *property, int property_num, DM_Type type, bool value_key, char *properties_payload); + int dm_mqtt_property_report_publish(DM_MQTT_Struct_t *handle, DM_Type type, int request_id, const char *payload); +int dm_mqtt_property_report_publish_Ex(DM_MQTT_Struct_t *handle, DM_Type type, int request_id, DM_Property_t *property, int property_num); + int dm_mqtt_event_publish(DM_MQTT_Struct_t *handle, int request_id, const char *identifier, const char *payload); +int dm_mqtt_event_publish_Ex(DM_MQTT_Struct_t *handle, int request_id, DM_Event_t *event); + #ifdef __cplusplus } #endif diff --git a/uiot/dev_model/src/dm_client.c b/uiot/dev_model/src/dm_client.c index e30c4ad..dc9888c 100644 --- a/uiot/dev_model/src/dm_client.c +++ b/uiot/dev_model/src/dm_client.c @@ -63,6 +63,32 @@ int IOT_DM_Property_Report(void *handle, DM_Type type, int request_id, const cha return dm_mqtt_property_report_publish(h_dm->ch_signal, type, request_id, payload); } +int IOT_DM_Property_ReportEx(void *handle, DM_Type type, int request_id, int property_num, ...) +{ + POINTER_VALID_CHECK(handle, FAILURE_RET); + int loop = 0; + int ret = 0; + DM_Struct_t *h_dm = (DM_Struct_t*) handle; + + va_list pArgs; + va_start(pArgs, property_num); + + DM_Property_t *property = (DM_Property_t *)HAL_Malloc(property_num * sizeof(DM_Property_t)); + + for(loop = 0; loop < property_num; loop++) + { + DM_Property_t *property_node; + property_node = va_arg(pArgs, DM_Property_t *); + property[loop] = *property_node; + } + + va_end(pArgs); + + ret = dm_mqtt_property_report_publish_Ex(h_dm->ch_signal, type, request_id, property, property_num); + HAL_Free(property); + return ret; +} + int IOT_DM_TriggerEvent(void *handle, int request_id, const char *identifier, const char *payload) { POINTER_VALID_CHECK(handle, FAILURE_RET); @@ -72,6 +98,40 @@ int IOT_DM_TriggerEvent(void *handle, int request_id, const char *identifier, co return dm_mqtt_event_publish(h_dm->ch_signal, request_id, identifier, payload); } +int IOT_DM_TriggerEventEx(void *handle, int request_id, DM_Event_t *event) +{ + POINTER_VALID_CHECK(handle, FAILURE_RET); + + DM_Struct_t *h_dm = (DM_Struct_t*) handle; + + return dm_mqtt_event_publish_Ex(h_dm->ch_signal, request_id, event); +} + +int IOT_DM_GenCommandOutput(char *output, int property_num, ...) +{ + POINTER_VALID_CHECK(output, FAILURE_RET); + int ret = 0; + int loop = 0; + + va_list pArgs; + va_start(pArgs, property_num); + + DM_Property_t *property = (DM_Property_t *)HAL_Malloc(property_num * sizeof(DM_Property_t)); + + for(loop = 0; loop < property_num; loop++) + { + DM_Property_t *property_node; + property_node = va_arg(pArgs, DM_Property_t *); + property[loop] = *property_node; + } + + va_end(pArgs); + + ret = dm_gen_properties_payload(property, property_num, PROPERTY_POST, false, output); + HAL_Free(property); + return ret; +} + int IOT_DM_Yield(void *handle, uint32_t timeout_ms) { POINTER_VALID_CHECK(handle, FAILURE_RET); diff --git a/uiot/dev_model/src/dm_mqtt.c b/uiot/dev_model/src/dm_mqtt.c index 8ad7dec..00d1627 100644 --- a/uiot/dev_model/src/dm_mqtt.c +++ b/uiot/dev_model/src/dm_mqtt.c @@ -39,7 +39,7 @@ static int _dm_mqtt_gen_topic_name(char *buf, size_t buf_len, const char *topic_ ret = HAL_Snprintf(buf, buf_len, topic_template, product_sn, device_sn); if (ret < 0 || ret >= buf_len) { - LOG_ERROR("HAL_Snprintf failed"); + LOG_ERROR("HAL_Snprintf failed\r\n"); FUNC_EXIT_RC(FAILURE_RET); } @@ -55,18 +55,18 @@ static int _dm_mqtt_gen_property_payload(char *buf, size_t buf_len, DM_Type type ret = HAL_Snprintf(buf, buf_len, "{\"RequestID\": \"%d\"}", request_id); break; case PROPERTY_POST: - ret = HAL_Snprintf(buf, buf_len, "{\"RequestID\": \"%d\", \"Property\": %s}", request_id, payload); + ret = HAL_Snprintf(buf, buf_len, "{\"RequestID\": \"%d\", \"Property\": {%s}}", request_id, payload); break; case PROPERTY_DESIRED_GET: - ret = HAL_Snprintf(buf, buf_len, "{\"RequestID\": \"%d\", \"Require\": %s}", request_id, payload); + ret = HAL_Snprintf(buf, buf_len, "{\"RequestID\": \"%d\", \"Require\": [%s]}", request_id, payload); break; case PROPERTY_DESIRED_DELETE: - ret = HAL_Snprintf(buf, buf_len, "{\"RequestID\": \"%d\", \"Delete\": %s}", request_id, payload); + ret = HAL_Snprintf(buf, buf_len, "{\"RequestID\": \"%d\", \"Delete\": {%s}}", request_id, payload); break; default: FUNC_EXIT_RC(FAILURE_RET); } if (ret < 0 || ret >= buf_len) { - LOG_ERROR("generate property payload failed"); + LOG_ERROR("generate property payload failed\r\n"); FUNC_EXIT_RC(FAILURE_RET); } @@ -77,11 +77,11 @@ static int _dm_mqtt_gen_event_payload(char *buf, size_t buf_len, int request_id, FUNC_ENTRY; int ret; - ret = HAL_Snprintf(buf, buf_len, "{\"RequestID\": \"%d\", \"Identifier\": \"%s\", \"Output\": %s}", request_id, + ret = HAL_Snprintf(buf, buf_len, "{\"RequestID\": \"%d\", \"Identifier\": \"%s\", \"Output\": {%s}}", request_id, identifier, payload); if (ret < 0 || ret >= buf_len) { - LOG_ERROR("generate event payload failed"); + LOG_ERROR("generate event payload failed\r\n"); FUNC_EXIT_RC(FAILURE_RET); } @@ -105,7 +105,7 @@ static int _dm_mqtt_publish(DM_MQTT_Struct_t *handle, char *topic_name, int qos, ret = IOT_MQTT_Publish(handle->mqtt, topic_name, &pub_params); if (ret < 0) { - LOG_ERROR("publish to topic: %s failed", topic_name); + LOG_ERROR("publish to topic: %s failed\r\n", topic_name); FUNC_EXIT_RC(FAILURE_RET); } @@ -121,22 +121,22 @@ static void _dm_mqtt_common_reply_cb(MQTTMessage *message, CommonReplyCB cb) { char *msg = NULL; if (NULL == (msg = HAL_Malloc(message->payload_len + 1))) { - LOG_ERROR("allocate for message failed"); + LOG_ERROR("allocate for message failed\r\n"); FUNC_EXIT; } HAL_Snprintf(msg, message->payload_len + 1, "%s", message->payload); if (NULL == (ret_code_char = LITE_json_value_of((char *) "RetCode", msg))) { - LOG_ERROR("allocate for ret_code_char failed"); + LOG_ERROR("allocate for ret_code_char failed\r\n"); goto do_exit; } if (SUCCESS_RET != LITE_get_int8(&ret_code, ret_code_char)) { - LOG_ERROR("get ret_code failed"); + LOG_ERROR("get ret_code failed\r\n"); goto do_exit; } if (NULL == (request_id = LITE_json_value_of((char *) "RequestID", msg))) { - LOG_ERROR("allocate for request_id failed"); + LOG_ERROR("allocate for request_id failed\r\n"); goto do_exit; } @@ -169,26 +169,26 @@ void dm_mqtt_property_restore_cb(void *pClient, MQTTMessage *message, void *pCon char *msg = NULL; if (NULL == (msg = HAL_Malloc(message->payload_len + 1))) { - LOG_ERROR("allocate for message failed"); + LOG_ERROR("allocate for message failed\r\n"); FUNC_EXIT; } HAL_Snprintf(msg, message->payload_len + 1, "%s", message->payload); if (NULL == (ret_code_char = LITE_json_value_of((char *) "RetCode", msg))) { - LOG_ERROR("allocate for ret_code_char failed"); + LOG_ERROR("allocate for ret_code_char failed\r\n"); goto do_exit; } if (SUCCESS_RET != LITE_get_int8(&ret_code, ret_code_char)) { - LOG_ERROR("get for ret_code failed"); + LOG_ERROR("get for ret_code failed\r\n"); goto do_exit; } if (NULL == (request_id = LITE_json_value_of((char *) "RequestID", msg))) { - LOG_ERROR("allocate for request_id failed"); + LOG_ERROR("allocate for request_id failed\r\n"); goto do_exit; } if (NULL == (property = LITE_json_value_of((char *) "Property", msg))) { - LOG_ERROR("allocate for property failed"); + LOG_ERROR("allocate for property failed\r\n"); goto do_exit; } @@ -241,18 +241,18 @@ void dm_mqtt_property_set_cb(void *pClient, MQTTMessage *message, void *pContext char *msg = NULL; if (NULL == (msg = HAL_Malloc(message->payload_len + 1))) { - LOG_ERROR("allocate for message failed"); + LOG_ERROR("allocate for message failed\r\n"); FUNC_EXIT; } HAL_Snprintf(msg, message->payload_len + 1, "%s", message->payload); if (NULL == (request_id = LITE_json_value_of((char *) "RequestID", msg))) { - LOG_ERROR("allocate for request_id failed"); + LOG_ERROR("allocate for request_id failed\r\n"); goto do_exit; } if (NULL == (property = LITE_json_value_of((char *) "Property", msg))) { - LOG_ERROR("allocate for property failed"); + LOG_ERROR("allocate for property failed\r\n"); goto do_exit; } @@ -260,26 +260,26 @@ void dm_mqtt_property_set_cb(void *pClient, MQTTMessage *message, void *pContext cb_ret = cb(request_id, property); if (NULL == (msg_reply = HAL_Malloc(DM_MSG_REPLY_BUF_LEN))) { - LOG_ERROR("allocate for msg_reply failed"); + LOG_ERROR("allocate for msg_reply failed\r\n"); goto do_exit; } if (NULL == (topic = HAL_Malloc(DM_TOPIC_BUF_LEN))) { - LOG_ERROR("allocate for topic failed"); + LOG_ERROR("allocate for topic failed\r\n"); goto do_exit; } if (SUCCESS_RET != _dm_mqtt_gen_topic_name(topic, DM_TOPIC_BUF_LEN, handle->upstream_topic_templates[PROPERTY_SET], handle->product_sn, handle->device_sn)) { - LOG_ERROR("generate topic name failed"); + LOG_ERROR("generate topic name failed\r\n"); goto do_exit; } ret = HAL_Snprintf(msg_reply, DM_MSG_REPLY_BUF_LEN, "{\"RequestID\": \"%s\", \"RetCode\": %d}", request_id, cb_ret); if (ret < 0 || ret >= DM_MSG_REPLY_BUF_LEN) { - LOG_ERROR("HAL_Snprintf msg_reply failed"); + LOG_ERROR("HAL_Snprintf msg_reply failed\r\n"); goto do_exit; } ret = _dm_mqtt_publish(handle, topic, 1, msg_reply); if (ret < 0) { - LOG_ERROR("mqtt publish msg failed"); + LOG_ERROR("mqtt publish msg failed\r\n"); goto do_exit; } @@ -312,26 +312,26 @@ void dm_mqtt_property_desired_get_cb(void *pClient, MQTTMessage *message, void * char *msg = NULL; if (NULL == (msg = HAL_Malloc(message->payload_len + 1))) { - LOG_ERROR("allocate for message failed"); + LOG_ERROR("allocate for message failed\r\n"); goto do_exit; } HAL_Snprintf(msg, message->payload_len + 1, "%s", message->payload); if (NULL == (ret_code_char = LITE_json_value_of((char *) "RetCode", msg))) { - LOG_ERROR("allocate for ret_code_char failed"); + LOG_ERROR("allocate for ret_code_char failed\r\n"); goto do_exit; } if (SUCCESS_RET != LITE_get_int8(&ret_code, ret_code_char)) { - LOG_ERROR("get ret_code failed"); + LOG_ERROR("get ret_code failed\r\n"); goto do_exit; } if (NULL == (request_id = LITE_json_value_of((char *) "RequestID", msg))) { - LOG_ERROR("allocate for request_id failed"); + LOG_ERROR("allocate for request_id failed\r\n"); goto do_exit; } if (NULL == (desired = LITE_json_value_of((char *) "Desired", msg))) { - LOG_ERROR("allocate for desired failed"); + LOG_ERROR("allocate for desired failed\r\n"); goto do_exit; } @@ -401,58 +401,65 @@ void dm_mqtt_command_cb(void *pClient, MQTTMessage *message, void *pContext) { char *msg = NULL; if (NULL == (msg = HAL_Malloc(message->payload_len + 1))) { - LOG_ERROR("allocate for message failed"); + LOG_ERROR("allocate for message failed\r\n"); FUNC_EXIT; } HAL_Snprintf(msg, message->payload_len + 1, "%s", message->payload); if (NULL == (request_id = LITE_json_value_of((char *) "RequestID", msg))) { - LOG_ERROR("allocate for request_id failed"); + LOG_ERROR("allocate for request_id failed\r\n"); goto do_exit; } if (NULL == (identifier = LITE_json_value_of((char *) "Identifier", msg))) { - LOG_ERROR("allocate for identifier failed"); + LOG_ERROR("allocate for identifier failed\r\n"); goto do_exit; } if (NULL == (input = LITE_json_value_of((char *) "Input", msg))) { - LOG_ERROR("allocate for input failed"); + LOG_ERROR("allocate for input failed\r\n"); + goto do_exit; + } + + output = HAL_Malloc(DM_MSG_REPORT_BUF_LEN); + + if (NULL == output) { + LOG_ERROR("allocate for output failed\r\n"); goto do_exit; } cb = (CommandCB) handle->callbacks[COMMAND]; - cb_ret = cb(request_id, identifier, input, &output); + cb_ret = cb(request_id, identifier, input, output); if (NULL == output) { - LOG_ERROR("output error"); + LOG_ERROR("output error\r\n"); goto do_exit; } if (NULL == (cmd_reply = HAL_Malloc(DM_CMD_REPLY_BUF_LEN))) { - LOG_ERROR("allocate for cmd_reply failed"); + LOG_ERROR("allocate for cmd_reply failed\r\n"); goto do_exit; } if (NULL == (topic = HAL_Malloc(DM_TOPIC_BUF_LEN))) { - LOG_ERROR("allocate for topic failed"); + LOG_ERROR("allocate for topic failed\r\n"); goto do_exit; } int ret = HAL_Snprintf(topic, DM_TOPIC_BUF_LEN, handle->upstream_topic_templates[COMMAND], handle->product_sn, handle->device_sn, request_id); if (ret < 0 || ret > DM_TOPIC_BUF_LEN) { - LOG_ERROR("topic error"); + LOG_ERROR("topic error\r\n"); goto do_exit; } ret = HAL_Snprintf(cmd_reply, DM_CMD_REPLY_BUF_LEN, - "{\"RequestID\": \"%s\", \"RetCode\": %d, \"Identifier\": \"%s\", \"Output\": %s}", + "{\"RequestID\": \"%s\", \"RetCode\": %d, \"Identifier\": \"%s\", \"Output\": {%s}}", request_id, cb_ret, identifier, output); if (ret < 0 || ret > DM_CMD_REPLY_BUF_LEN) { - LOG_ERROR("generate cmd_reply msg failed"); + LOG_ERROR("generate cmd_reply msg failed\r\n"); goto do_exit; } ret = _dm_mqtt_publish(handle, topic, 1, cmd_reply); if (ret < 0) { - LOG_ERROR("mqtt publish msg failed"); + LOG_ERROR("mqtt publish msg failed\r\n"); goto do_exit; } @@ -473,7 +480,7 @@ int _dsc_mqtt_register_callback(DM_MQTT_Struct_t *handle, DM_Type dm_type, void int ret; if (NULL == handle || callback == NULL) { - LOG_ERROR("params error!"); + LOG_ERROR("params error!\r\n"); FUNC_EXIT_RC(FAILURE_RET); } handle->callbacks[dm_type] = callback; @@ -484,7 +491,7 @@ int _dsc_mqtt_register_callback(DM_MQTT_Struct_t *handle, DM_Type dm_type, void ret = _dm_mqtt_gen_topic_name(topic, DM_TOPIC_BUF_LEN, handle->downstream_topic_templates[dm_type], handle->product_sn, handle->device_sn); if (ret < 0) { - LOG_ERROR("generate topic name failed"); + LOG_ERROR("generate topic name failed\r\n"); FUNC_EXIT_RC(FAILURE_RET); } @@ -495,7 +502,7 @@ int _dsc_mqtt_register_callback(DM_MQTT_Struct_t *handle, DM_Type dm_type, void ret = IOT_MQTT_Subscribe(handle->mqtt, topic, &sub_params); if (ret < 0) { - LOG_ERROR("mqtt subscribe failed!"); + LOG_ERROR("mqtt subscribe failed!\r\n"); FUNC_EXIT_RC(FAILURE_RET); } @@ -503,19 +510,19 @@ int _dsc_mqtt_register_callback(DM_MQTT_Struct_t *handle, DM_Type dm_type, void } -DEFINE_DM_CALLBACK(PROPERTY_RESTORE, PropertyRestoreCB) +DEFINE_DM_CALLBACK(PROPERTY_RESTORE, PropertyRestoreCB); -DEFINE_DM_CALLBACK(PROPERTY_POST, CommonReplyCB) +DEFINE_DM_CALLBACK(PROPERTY_POST, CommonReplyCB); -DEFINE_DM_CALLBACK(PROPERTY_SET, PropertySetCB) +DEFINE_DM_CALLBACK(PROPERTY_SET, PropertySetCB); -DEFINE_DM_CALLBACK(PROPERTY_DESIRED_GET, PropertyDesiredGetCB) +DEFINE_DM_CALLBACK(PROPERTY_DESIRED_GET, PropertyDesiredGetCB); -DEFINE_DM_CALLBACK(PROPERTY_DESIRED_DELETE, CommonReplyCB) +DEFINE_DM_CALLBACK(PROPERTY_DESIRED_DELETE, CommonReplyCB); -DEFINE_DM_CALLBACK(EVENT_POST, CommonReplyCB) +DEFINE_DM_CALLBACK(EVENT_POST, CommonReplyCB); -DEFINE_DM_CALLBACK(COMMAND, CommandCB) +DEFINE_DM_CALLBACK(COMMAND, CommandCB); void *dsc_init(const char *product_sn, const char *device_sn, void *channel, void *context) { FUNC_ENTRY; @@ -523,7 +530,7 @@ void *dsc_init(const char *product_sn, const char *device_sn, void *channel, voi DM_MQTT_Struct_t *h_dsc = NULL; if (NULL == (h_dsc = HAL_Malloc(sizeof(DM_MQTT_Struct_t)))) { - LOG_ERROR("allocate for h_dsc failed"); + LOG_ERROR("allocate for h_dsc failed\r\n"); FUNC_EXIT_RC(NULL); } @@ -547,6 +554,433 @@ int dsc_deinit(void *handle) { FUNC_EXIT_RC(SUCCESS_RET); } +static int dm_gen_node_payload(DM_Node_t *dm_node, bool value_key, char *node_payload) +{ + int ret = 0; + + switch(dm_node->base_type) + { + case TYPE_INT: + if(NULL != dm_node->key) + ret = HAL_Snprintf(node_payload, DM_MSG_REPORT_BUF_LEN, value_key?"\"%s\": {\"Value\": %d}":"\"%s\": %d", dm_node->key, dm_node->value.int32_value); + else + ret = HAL_Snprintf(node_payload, DM_MSG_REPORT_BUF_LEN, "%d", dm_node->value.int32_value); + break; + case TYPE_BOOL: + if(NULL != dm_node->key) + ret = HAL_Snprintf(node_payload, DM_MSG_REPORT_BUF_LEN, value_key?"\"%s\": {\"Value\": %d}":"\"%s\": %d", dm_node->key, dm_node->value.bool_value); + else + ret = HAL_Snprintf(node_payload, DM_MSG_REPORT_BUF_LEN, "%d", dm_node->value.bool_value); + break; + case TYPE_ENUM: + if(NULL != dm_node->key) + ret = HAL_Snprintf(node_payload, DM_MSG_REPORT_BUF_LEN, value_key?"\"%s\": {\"Value\": %d}":"\"%s\": %d", dm_node->key, dm_node->value.enum_value); + else + ret = HAL_Snprintf(node_payload, DM_MSG_REPORT_BUF_LEN, "%d", dm_node->value.enum_value); + break; + case TYPE_FLOAT: + if(NULL != dm_node->key) + ret = HAL_Snprintf(node_payload, DM_MSG_REPORT_BUF_LEN, value_key?"\"%s\": {\"Value\": %f}":"\"%s\": %f", dm_node->key, dm_node->value.float32_value); + else + ret = HAL_Snprintf(node_payload, DM_MSG_REPORT_BUF_LEN, "%f", dm_node->value.float32_value); + break; + case TYPE_DOUBLE: + if(NULL != dm_node->key) + ret = HAL_Snprintf(node_payload, DM_MSG_REPORT_BUF_LEN, value_key?"\"%s\": {\"Value\": %lf}":"\"%s\": %lf", dm_node->key, dm_node->value.float64_value); + else + ret = HAL_Snprintf(node_payload, DM_MSG_REPORT_BUF_LEN, "%lf", dm_node->value.float64_value); + break; + case TYPE_STRING: + if(NULL != dm_node->key) + ret = HAL_Snprintf(node_payload, DM_MSG_REPORT_BUF_LEN, value_key?"\"%s\": {\"Value\": \"%s\"}":"\"%s\": \"%s\"", dm_node->key, dm_node->value.string_value); + else + ret = HAL_Snprintf(node_payload, DM_MSG_REPORT_BUF_LEN, "\"%s\"", dm_node->value.string_value); + break; + case TYPE_DATE: + if(NULL != dm_node->key) + ret = HAL_Snprintf(node_payload, DM_MSG_REPORT_BUF_LEN, value_key?"\"%s\": {\"Value\": %ld}":"\"%s\": %ld", dm_node->key, dm_node->value.date_value); + else + ret = HAL_Snprintf(node_payload, DM_MSG_REPORT_BUF_LEN, "%ld", dm_node->value.date_value); + break; + default: + LOG_ERROR("illegal node type\r\n"); + return FAILURE_RET; + } + if (ret < 0 || ret >= DM_MSG_REPORT_BUF_LEN) { + LOG_ERROR("generate node payload failed\r\n"); + return FAILURE_RET; + } + return SUCCESS_RET; +} + +static int dm_gen_struct_payload(DM_Type_Struct_t *dm_struct, bool value_key, char *struct_payload) +{ + int remain_size = 0; + int write_size = 0; + int loop = 0; + int ret = 0; + + DM_Node_t *p_node = dm_struct->value; + + char *node_payload = HAL_Malloc(DM_MSG_REPORT_BUF_LEN); + + if (NULL == node_payload) { + LOG_ERROR("allocate for node_payload failed\r\n"); + return FAILURE_RET; + } + + //结构体中只有一个成员 + if(1 == dm_struct->num) + { + ret = dm_gen_node_payload(p_node, false, node_payload); + if (SUCCESS_RET != ret) { + LOG_ERROR("dm_gen_node_payload failed\r\n"); + HAL_Free(node_payload); + return ret; + } + + if(NULL != dm_struct->key) + { + write_size = HAL_Snprintf(struct_payload, DM_MSG_REPORT_BUF_LEN, value_key?"\"%s\": {\"Value\": {%s}}":"\"%s\": {%s}", dm_struct->key, node_payload); + } + else + { + write_size = HAL_Snprintf(struct_payload, DM_MSG_REPORT_BUF_LEN, "{%s}", node_payload); + } + } + else + { + for(loop = 0; loop < dm_struct->num; loop++) + { + ret = dm_gen_node_payload(&p_node[loop], false, node_payload); + if (SUCCESS_RET != ret) { + LOG_ERROR("dm_gen_node_payload failed\r\n"); + HAL_Free(node_payload); + return ret; + } + + if(0 == loop) + { + if(NULL != dm_struct->key) + { + write_size = HAL_Snprintf(struct_payload, DM_MSG_REPORT_BUF_LEN, value_key?"\"%s\": {\"Value\": {%s":"\"%s\": {%s", dm_struct->key, node_payload); + remain_size = DM_MSG_REPORT_BUF_LEN - write_size; + } + else + { + write_size = HAL_Snprintf(struct_payload, DM_MSG_REPORT_BUF_LEN, "{%s", node_payload); + remain_size = DM_MSG_REPORT_BUF_LEN - write_size; + } + } + else if(loop == dm_struct->num - 1) + { + if(NULL != dm_struct->key) + { + write_size = HAL_Snprintf(struct_payload + strlen(struct_payload), remain_size, value_key?", %s}}":", %s}", node_payload); + remain_size = remain_size - write_size; + } + else + { + write_size = HAL_Snprintf(struct_payload + strlen(struct_payload), remain_size, ", %s}", node_payload); + remain_size = remain_size - write_size; + } + } + else + { + write_size = HAL_Snprintf(struct_payload + strlen(struct_payload), remain_size, ", %s", node_payload); + remain_size = remain_size - write_size; + } + } + } + HAL_Free(node_payload); + if (write_size < 0 || remain_size < 0) { + LOG_ERROR("generate struct payload failed\r\n"); + return FAILURE_RET; + } + return SUCCESS_RET; +} + +static int dm_gen_array_base_payload(DM_Array_Base_t *dm_array_base, bool value_key, char *array_base_payload) +{ + int remain_size = 0; + int write_size = 0; + int loop = 0; + int ret = 0; + + DM_Node_t *p_node = dm_array_base->value; + + char *node_payload = HAL_Malloc(DM_MSG_REPORT_BUF_LEN); + + if (NULL == node_payload) { + LOG_ERROR("allocate for node_payload failed\r\n"); + return FAILURE_RET; + } + + //数组只有一个成员 + if(1 == dm_array_base->num) + { + ret = dm_gen_node_payload(p_node, false, node_payload); + if (SUCCESS_RET != ret) { + LOG_ERROR("dm_gen_node_payload failed\r\n"); + HAL_Free(node_payload); + return ret; + } + write_size = HAL_Snprintf(array_base_payload, DM_MSG_REPORT_BUF_LEN, value_key?"\"%s\": {\"Value\": [%s]}":"\"%s\": [%s]", dm_array_base->key, node_payload); + } + else + { + for(loop = 0; loop < dm_array_base->num; loop++) + { + ret = dm_gen_node_payload(&p_node[loop], false, node_payload); + if (SUCCESS_RET != ret) { + LOG_ERROR("dm_gen_node_payload failed\r\n"); + HAL_Free(node_payload); + return ret; + } + + if(0 == loop) + { + write_size = HAL_Snprintf(array_base_payload, DM_MSG_REPORT_BUF_LEN, value_key?"\"%s\": {\"Value\": [%s":"\"%s\": [%s", dm_array_base->key, node_payload); + remain_size = DM_MSG_REPORT_BUF_LEN - write_size; + } + else if(loop == dm_array_base->num - 1) + { + write_size = HAL_Snprintf(array_base_payload + strlen(array_base_payload), remain_size, value_key?", %s]}":", %s]", node_payload); + remain_size = remain_size - write_size; + } + else + { + write_size = HAL_Snprintf(array_base_payload + strlen(array_base_payload), remain_size, ", %s", node_payload); + remain_size = remain_size - write_size; + } + } + } + HAL_Free(node_payload); + if (write_size < 0 || remain_size < 0) { + LOG_ERROR("generate struct payload failed\r\n"); + return FAILURE_RET; + } + return SUCCESS_RET; +} + +static int dm_gen_array_struct_payload(DM_Array_Struct_t *dm_array_struct, bool value_key, char *array_struct_payload) +{ + int remain_size = 0; + int write_size = 0; + int loop = 0; + int ret = 0; + + DM_Type_Struct_t *p_struct = dm_array_struct->value; + + char *struct_payload = HAL_Malloc(DM_MSG_REPORT_BUF_LEN); + + if (NULL == struct_payload) { + LOG_ERROR("allocate for struct_payload failed\r\n"); + return FAILURE_RET; + } + + //数组只有一个结构体成员 + if(1 == dm_array_struct->num) + { + ret = dm_gen_struct_payload(p_struct, false, struct_payload); + if (SUCCESS_RET != ret) { + LOG_ERROR("dm_gen_struct_payload failed\r\n"); + HAL_Free(struct_payload); + return ret; + } + write_size = HAL_Snprintf(array_struct_payload, DM_MSG_REPORT_BUF_LEN, value_key?"\"%s\": {\"Value\": [%s]}":"\"%s\": [%s]", dm_array_struct->key, struct_payload); + } + else + { + for(loop = 0; loop < dm_array_struct->num; loop++) + { + ret = dm_gen_struct_payload(&p_struct[loop], false, struct_payload); + if (SUCCESS_RET != ret) { + LOG_ERROR("dm_gen_struct_payload failed\r\n"); + HAL_Free(struct_payload); + return ret; + } + if(0 == loop) + { + write_size = HAL_Snprintf(array_struct_payload, DM_MSG_REPORT_BUF_LEN, value_key?"\"%s\": {\"Value\": [%s":"\"%s\": [%s", dm_array_struct->key, struct_payload); + remain_size = DM_MSG_REPORT_BUF_LEN - write_size; + } + else if(loop == dm_array_struct->num - 1) + { + write_size = HAL_Snprintf(array_struct_payload + strlen(array_struct_payload), remain_size, value_key?", %s]}":", %s]", struct_payload); + remain_size = remain_size - write_size; + } + else + { + write_size = HAL_Snprintf(array_struct_payload + strlen(array_struct_payload), remain_size, ", %s", struct_payload); + remain_size = remain_size - write_size; + } + } + } + HAL_Free(struct_payload); + if (write_size < 0 || remain_size < 0) { + LOG_ERROR("generate array struct payload failed\r\n"); + return FAILURE_RET; + } + return SUCCESS_RET; +} + +static int dm_gen_property_post_payload(DM_Property_t *property, bool value_key, char *property_payload) +{ + int ret = 0; + + switch(property->parse_type) + { + case TYPE_NODE: + ret = dm_gen_node_payload(property->value.dm_node, value_key, property_payload); + break; + case TYPE_STRUCT: + ret = dm_gen_struct_payload(property->value.dm_struct, value_key, property_payload); + break; + case TYPE_ARRAY_BASE: + ret = dm_gen_array_base_payload(property->value.dm_array_base, value_key, property_payload); + break; + case TYPE_ARRAY_STRUCT: + ret = dm_gen_array_struct_payload(property->value.dm_array_struct, value_key, property_payload); + break; + default: + LOG_ERROR("illegal property type\r\n"); + return FAILURE_RET; + } + + return ret; +} + +static int dm_gen_property_desired_payload(DM_Property_t *property, char *desired_payload) +{ + int write_size = 0; + + switch(property->parse_type) + { + case TYPE_NODE: + write_size = HAL_Snprintf(desired_payload, DM_MSG_REPORT_BUF_LEN, "\"%s\"", property->value.dm_node->key); + break; + case TYPE_STRUCT: + write_size = HAL_Snprintf(desired_payload, DM_MSG_REPORT_BUF_LEN, "\"%s\"", property->value.dm_struct->key); + break; + case TYPE_ARRAY_BASE: + write_size = HAL_Snprintf(desired_payload, DM_MSG_REPORT_BUF_LEN, "\"%s\"", property->value.dm_array_base->key); + break; + case TYPE_ARRAY_STRUCT: + write_size = HAL_Snprintf(desired_payload, DM_MSG_REPORT_BUF_LEN, "\"%s\"", property->value.dm_array_struct->key); + break; + default: + LOG_ERROR("illegal property type\r\n"); + return FAILURE_RET; + } + + if (write_size < 0) { + LOG_ERROR("generate property desired payload failed\r\n"); + return FAILURE_RET; + } + return SUCCESS_RET; +} + +static int dm_gen_property_delete_payload(DM_Property_t *property, char *delete_payload) +{ + int write_size = 0; + + switch(property->parse_type) + { + case TYPE_NODE: + write_size = HAL_Snprintf(delete_payload, DM_MSG_REPORT_BUF_LEN, "\"%s\": {\"version\": %d}", property->value.dm_node->key, property->desired_ver); + break; + case TYPE_STRUCT: + write_size = HAL_Snprintf(delete_payload, DM_MSG_REPORT_BUF_LEN, "\"%s\": {\"version\": %d}", property->value.dm_struct->key, property->desired_ver); + break; + case TYPE_ARRAY_BASE: + write_size = HAL_Snprintf(delete_payload, DM_MSG_REPORT_BUF_LEN, "\"%s\": {\"version\": %d}", property->value.dm_array_base->key, property->desired_ver); + break; + case TYPE_ARRAY_STRUCT: + write_size = HAL_Snprintf(delete_payload, DM_MSG_REPORT_BUF_LEN, "\"%s\": {\"version\": %d}", property->value.dm_array_struct->key, property->desired_ver); + break; + default: + LOG_ERROR("illegal property type\r\n"); + return FAILURE_RET; + } + + if (write_size < 0) { + LOG_ERROR("generate property delete payload failed\r\n"); + return FAILURE_RET; + } + return SUCCESS_RET; +} + +int dm_gen_properties_payload(DM_Property_t *property, int property_num, DM_Type type, bool value_key, char *properties_payload) +{ + int remain_size = 0; + int write_size = 0; + int loop = 0; + int ret = 0; + + if (NULL == property || NULL == properties_payload) { + LOG_ERROR("params error!\r\n"); + FUNC_EXIT_RC(FAILURE_RET); + } + + char *payload = HAL_Malloc(DM_MSG_REPORT_BUF_LEN); + + if (NULL == payload) { + LOG_ERROR("allocate for payload failed\r\n"); + return FAILURE_RET; + } + for(loop = 0; loop < property_num; loop++) + { + switch(type) + { + case PROPERTY_POST: + ret = dm_gen_property_post_payload(&(property[loop]), value_key, payload); + if (SUCCESS_RET != ret) { + LOG_ERROR("dm_gen_property_post_payload failed\r\n"); + HAL_Free(payload); + return ret; + } + break; + case PROPERTY_DESIRED_GET: + ret = dm_gen_property_desired_payload(&(property[loop]), payload); + if (SUCCESS_RET != ret) { + LOG_ERROR("dm_gen_property_post_payload failed\r\n"); + HAL_Free(payload); + return ret; + } + break; + case PROPERTY_DESIRED_DELETE: + ret = dm_gen_property_delete_payload(&(property[loop]), payload); + if (SUCCESS_RET != ret) { + LOG_ERROR("dm_gen_property_post_payload failed\r\n"); + HAL_Free(payload); + return ret; + } + break; + default: + LOG_ERROR("illegal dm type\r\n"); + break; + } + if(0 == loop) + { + write_size = HAL_Snprintf(properties_payload, DM_MSG_REPORT_BUF_LEN, "%s", payload); + remain_size = DM_MSG_REPORT_BUF_LEN - write_size; + } + else + { + write_size = HAL_Snprintf(properties_payload + strlen(properties_payload), remain_size, ", %s", payload); + remain_size = remain_size - write_size; + } + } + + HAL_Free(payload); + if (write_size < 0 || remain_size < 0) { + LOG_ERROR("dm_gen_properties_payload failed\r\n"); + return FAILURE_RET; + } + return SUCCESS_RET; +} + int dm_mqtt_property_report_publish(DM_MQTT_Struct_t *handle, DM_Type type, int request_id, const char *payload) { FUNC_ENTRY; @@ -555,29 +989,30 @@ int dm_mqtt_property_report_publish(DM_MQTT_Struct_t *handle, DM_Type type, int char *topic = NULL; if (NULL == (msg_report = HAL_Malloc(DM_MSG_REPORT_BUF_LEN))) { - LOG_ERROR("allocate for msg_report failed"); - goto do_exit; + LOG_ERROR("allocate for msg_report failed\r\n"); + return FAILURE_RET; } if (NULL == (topic = HAL_Malloc(DM_TOPIC_BUF_LEN))) { - LOG_ERROR("allocate for topic failed"); - goto do_exit; + LOG_ERROR("allocate for topic failed\r\n"); + HAL_Free(msg_report); + return FAILURE_RET; } if (SUCCESS_RET != _dm_mqtt_gen_topic_name(topic, DM_TOPIC_BUF_LEN, handle->upstream_topic_templates[type], handle->product_sn, handle->device_sn)) { - LOG_ERROR("generate topic failed"); + LOG_ERROR("generate topic failed\r\n"); goto do_exit; } ret = _dm_mqtt_gen_property_payload(msg_report, DM_MSG_REPORT_BUF_LEN, type, request_id, payload); if (ret < 0) { - LOG_ERROR("generate msg_report failed"); + LOG_ERROR("generate msg_report failed\r\n"); ret = FAILURE_RET; goto do_exit; } ret = _dm_mqtt_publish(handle, topic, 1, msg_report); if (ret < 0) { - LOG_ERROR("mqtt publish msg failed"); + LOG_ERROR("mqtt publish msg failed\r\n"); } do_exit: @@ -587,6 +1022,37 @@ do_exit: FUNC_EXIT_RC(ret); } +int dm_mqtt_property_report_publish_Ex(DM_MQTT_Struct_t *handle, DM_Type type, int request_id, DM_Property_t *property, int property_num) { + FUNC_ENTRY; + int ret = 0; + char *payload = HAL_Malloc(DM_MSG_REPORT_BUF_LEN); + + if (NULL == payload) { + LOG_ERROR("allocate for payload failed\r\n"); + return FAILURE_RET; + } + + ret = dm_gen_properties_payload(property, property_num, type, true, payload); + if(FAILURE_RET == ret) + { + LOG_ERROR("dm_gen_properties_payload failed\r\n"); + HAL_Free(payload); + return FAILURE_RET; + } + + ret = dm_mqtt_property_report_publish(handle, type, request_id, payload); + if(FAILURE_RET == ret) + { + LOG_ERROR("dm_mqtt_property_report_publish failed\r\n"); + HAL_Free(payload); + return FAILURE_RET; + } + + HAL_Free(payload); + return ret; +} + + int dm_mqtt_event_publish(DM_MQTT_Struct_t *handle, int request_id, const char *identifier, const char *payload) { FUNC_ENTRY; @@ -595,28 +1061,28 @@ int dm_mqtt_event_publish(DM_MQTT_Struct_t *handle, int request_id, const char * char *topic = NULL; if (NULL == (msg_report = HAL_Malloc(DM_EVENT_POST_BUF_LEN))) { - LOG_ERROR("allocate for msg_report failed"); + LOG_ERROR("allocate for msg_report failed\r\n"); goto do_exit; } if (NULL == (topic = HAL_Malloc(DM_TOPIC_BUF_LEN))) { - LOG_ERROR("allocate for topic failed"); + LOG_ERROR("allocate for topic failed\r\n"); goto do_exit; } if (SUCCESS_RET != _dm_mqtt_gen_topic_name(topic, DM_TOPIC_BUF_LEN, handle->upstream_topic_templates[EVENT_POST], handle->product_sn, handle->device_sn)) { - LOG_ERROR("generate topic failed"); + LOG_ERROR("generate topic failed\r\n"); goto do_exit; } ret = _dm_mqtt_gen_event_payload(msg_report, DM_EVENT_POST_BUF_LEN, request_id, identifier, payload); if (ret < 0) { - LOG_ERROR("generate msg_report failed"); + LOG_ERROR("generate msg_report failed\r\n"); goto do_exit; } ret = _dm_mqtt_publish(handle, topic, 1, msg_report); if (ret < 0) { - LOG_ERROR("mqtt publish msg failed"); + LOG_ERROR("mqtt publish msg failed\r\n"); } do_exit: @@ -625,3 +1091,36 @@ do_exit: FUNC_EXIT_RC(ret); } + +int dm_mqtt_event_publish_Ex(DM_MQTT_Struct_t *handle, int request_id, DM_Event_t *event) { + FUNC_ENTRY; + + int ret = 0; + DM_Property_t *p_property = event->dm_property; + + char *properties_payload = HAL_Malloc(DM_MSG_REPORT_BUF_LEN); + + if (NULL == properties_payload) { + LOG_ERROR("allocate for properties_payload failed\r\n"); + return FAILURE_RET; + } + + ret = dm_gen_properties_payload(p_property, event->property_num, PROPERTY_POST, false, properties_payload); + if (FAILURE_RET == ret) { + LOG_ERROR("dm_gen_properties_payload failed\r\n"); + HAL_Free(properties_payload); + return FAILURE_RET; + } + + ret = dm_mqtt_event_publish(handle, request_id, event->event_identy, properties_payload); + if(FAILURE_RET == ret) + { + LOG_ERROR("dm_mqtt_property_report_publish failed\r\n"); + HAL_Free(properties_payload); + return FAILURE_RET; + } + + HAL_Free(properties_payload); + return ret; +} + diff --git a/uiot/ota/include/ota_config.h b/uiot/ota/include/ota_config.h index 3bfead6..0c8b13d 100644 --- a/uiot/ota/include/ota_config.h +++ b/uiot/ota/include/ota_config.h @@ -22,16 +22,18 @@ extern "C" { #define TYPE_FIELD "Method" #define MD5_FIELD "Payload.MD5" +#define MODULE_FIELD "Payload.Module" #define VERSION_FIELD "Payload.Version" #define URL_FIELD "Payload.URL" #define SIZE_FIELD "Payload.Size" #define UPDATE_FIRMWARE_METHOD "update_firmware" +#define CANCEL_UPDATE_METHOD "cancel_update" -#define REPORT_PROGRESS_MSG_TEMPLATE "{\"Method\": \"report_progress\", \"Payload\": {\"State\":\"%s\", \"Percent\":%d}}" -#define REPORT_SUCCESS_MSG_TEMPLATE "{\"Method\": \"report_success\", \"Payload\":{\"Version\":\"%s\"}}" -#define REPORT_FAIL_MSG_TEMPLATE "{\"Method\": \"report_fail\", \"Payload\": {\"ErrCode\": %d}}" -#define REPORT_VERSION_MSG_TEMPLATE "{\"Method\": \"report_version\", \"Payload\":{\"Version\":\"%s\"}}" -#define REQUEST_FIRMWARE_MSG_TEMPLATE "{\"Method\": \"request_firmware\", \"Payload\":{\"Version\":\"%s\"}}" +#define REPORT_PROGRESS_MSG_TEMPLATE "{\"Method\": \"report_progress\", \"Payload\": {\"State\":\"%s\", \"Percent\":%d, \"Module\":\"%s\", \"Version\":\"%s\" }}" +#define REPORT_SUCCESS_MSG_TEMPLATE "{\"Method\": \"report_success\", \"Payload\":{\"Module\":\"%s\", \"Version\":\"%s\"}}" +#define REPORT_FAIL_MSG_TEMPLATE "{\"Method\": \"report_fail\", \"Payload\": {\"ErrCode\": %d, \"Module\":\"%s\", \"Version\":\"%s\"}}" +#define REPORT_VERSION_MSG_TEMPLATE "{\"Method\": \"report_version\", \"Payload\":{\"Module\":\"%s\", \"Version\":\"%s\"}}" +#define REQUEST_FIRMWARE_MSG_TEMPLATE "{\"Method\": \"request_firmware\", \"Payload\":{\"Module\":\"%s\", \"Version\":\"%s\"}}" #define OTA_VERSION_STR_LEN_MIN (1) #define OTA_VERSION_STR_LEN_MAX (32) diff --git a/uiot/ota/include/ota_internal.h b/uiot/ota/include/ota_internal.h index b045552..e26bbd7 100644 --- a/uiot/ota/include/ota_internal.h +++ b/uiot/ota/include/ota_internal.h @@ -21,43 +21,42 @@ extern "C" { #endif #include - +#include "ota_config.h" #include "uiot_export_ota.h" - -typedef enum { - - OTA_REPORT_UNDEFINED_ERROR = -6, - OTA_REPORT_FIRMWARE_BURN_FAILED = -5, - OTA_REPORT_MD5_MISMATCH = -4, - OTA_REPORT_DOWNLOAD_TIMEOUT = -3, - OTA_REPORT_SIGNATURE_EXPIRED = -2, - OTA_REPORT_FIRMWARE_NOT_EXIST = -1, - OTA_REPORT_NONE = 0, - OTA_REPORT_DOWNLOADING = 1, - OTA_REPORT_BURNING = 2, - OTA_REPORT_SUCCESS = 3, - OTA_REQUEST_FIRMWARE = 4, - OTA_REPORT_VERSION = 5, - -} IOT_OTA_UpstreamMsgType; - -/* OTA状态 */ -typedef enum { - - OTA_STATE_UNINITED = 0, /* 未初始化 */ - OTA_STATE_INITED, /* 初始化完成 */ - OTA_STATE_FETCHING, /* 正在下载固件 */ - OTA_STATE_FETCHED, /* 固件下载完成 */ - OTA_STATE_DISCONNECTED /* 连接已经断开 */ - -} IOT_OTA_State; +#include "utils_httpc.h" +#include "utils_list.h" // OTA Signal Channel typedef void (*OnOTAMessageCallback)(void *pContext, const char *msg, uint32_t msgLen); +typedef struct{ + char *payload; // MQTT 消息负载 + size_t payload_len; // MQTT 消息负载长度 +}OTA_UPLOAD_Msg; + +typedef struct { + + const char *url; + http_client_t http; /* http client */ + http_client_data_t http_data; /* http client data */ + +} OTA_Http_Client; + void *osc_init(const char *product_sn, const char *device_sn, void *channel, OnOTAMessageCallback callback, void *context); +/* OSC, OTA signal channel */ +typedef struct { + void *mqtt; + const char *product_sn; + const char *device_sn; + char topic_upgrade[OTA_TOPIC_BUF_LEN]; + OnOTAMessageCallback msg_callback; + List *msg_list; /* recv update msg */ + void *msg_mutex; /* mutex for msg list */ + void *context; +} OTA_MQTT_Struct_t; + int osc_deinit(void *handle); int osc_report_progress(void *handle, const char *msg); @@ -84,10 +83,12 @@ void ota_lib_md5_deinit(void *md5); int ota_lib_get_msg_type(char *json, char **type); -int ota_lib_get_params(char *json, char **url, char **version, char **md5, +int ota_lib_get_msg_module_ver(char *json, char **module, char **ver); + +int ota_lib_get_params(char *json, char **url, char **module, char **download_name, char **version, char **md5, uint32_t *fileSize); -int ota_lib_gen_upstream_msg(char *buf, size_t bufLen, const char *version, int progress, +int ota_lib_gen_upstream_msg(char *buf, size_t bufLen, const char *module, const char *version, int progress, IOT_OTA_UpstreamMsgType reportType); #ifdef __cplusplus diff --git a/uiot/ota/src/ota_client.c b/uiot/ota/src/ota_client.c index d2a6723..93ee8a5 100644 --- a/uiot/ota/src/ota_client.c +++ b/uiot/ota/src/ota_client.c @@ -61,33 +61,65 @@ static void print_progress(uint32_t percent) progress_sign[sizeof(progress_sign) - 1] = '\0'; - HAL_Printf("Download: [%s] %d%%\r\n", progress_sign, percent); + LOG_INFO("Download: [%s] %d%%\r\n", progress_sign, percent); } -typedef struct { - uint32_t id; /* message id */ - IOT_OTA_State 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 */ +static void _ota_push_upload_msg(void *handle, const char *msg, uint32_t msg_len) +{ + OTA_Struct_t *h_ota = (OTA_Struct_t *) handle; + OTA_MQTT_Struct_t *h_osc = h_ota->ch_signal; - char *url; /* point to URL */ - char *version; /* point to version */ - char *md5sum; /* MD5 string */ + OTA_UPLOAD_Msg *push_msg = (OTA_UPLOAD_Msg *)HAL_Malloc(sizeof(OTA_UPLOAD_Msg)); + if (NULL == (push_msg->payload = HAL_Malloc(msg_len + 1))) { + LOG_ERROR("HAL_Malloc failed!"); + return; + } + + HAL_Snprintf(push_msg->payload, msg_len + 1, "%s", msg); + push_msg->payload_len = msg_len; + + ListNode *node = list_node_new((void *)push_msg); + if (NULL == node) + { + LOG_ERROR("run list_node_new is error!\n"); + HAL_Free(push_msg->payload); + HAL_Free(push_msg); + return; + } + + HAL_MutexLock(h_osc->msg_mutex); + list_rpush(h_osc->msg_list, node); + HAL_MutexUnlock(h_osc->msg_mutex); + return; +} - void *md5; /* MD5 handle */ - void *ch_signal; /* channel handle of signal exchanged with OTA server */ - void *ch_fetch; /* channel handle of download */ +static void _ota_pop_upload_msg(void *handle) +{ + OTA_Struct_t *h_ota = (OTA_Struct_t *) handle; + OTA_MQTT_Struct_t *h_osc = h_ota->ch_signal; - int err; /* last error code */ + if(h_osc->msg_list->len > 0) + { + HAL_MutexLock(h_osc->msg_mutex); + ListNode *node = list_lpop(h_osc->msg_list); + HAL_MutexUnlock(h_osc->msg_mutex); + OTA_UPLOAD_Msg *pop_msg = node->val; + h_osc->msg_callback(h_ota, pop_msg->payload, pop_msg->payload_len); + HAL_Free(pop_msg->payload); + HAL_Free(pop_msg); + HAL_Free(node); + return; + } + return; +} - Timer report_timer; -} OTA_Struct_t; - -static void _ota_callback(void *pContext, const char *msg, uint32_t msg_len) { +static void _ota_callback(void *pContext, const char *msg, uint32_t msg_len) +{ char *msg_method = NULL; char *msg_str = NULL; - + char *msg_module = NULL; + char *msg_ver = NULL; + OTA_Struct_t *h_ota = (OTA_Struct_t *) pContext; if (h_ota == NULL || msg == NULL) { @@ -95,11 +127,6 @@ static void _ota_callback(void *pContext, const char *msg, uint32_t msg_len) { return; } - if (h_ota->state == OTA_STATE_FETCHING) { - LOG_INFO("In OTA_STATE_FETCHING state"); - return; - } - if (NULL == (msg_str = HAL_Malloc(msg_len + 1))) { LOG_ERROR("HAL_Malloc failed!"); return; @@ -112,32 +139,66 @@ static void _ota_callback(void *pContext, const char *msg, uint32_t msg_len) { goto do_exit; } - if (strcmp(msg_method, UPDATE_FIRMWARE_METHOD) != 0) { - LOG_ERROR("Message type error! type: %s", msg_method); + if((NULL == h_ota->ch_fetch) && (0 == strcmp(msg_method, CANCEL_UPDATE_METHOD))) + { + LOG_ERROR("download is canceled!"); goto do_exit; } - if (SUCCESS_RET != ota_lib_get_params(msg_str, &h_ota->url, &h_ota->version, - &h_ota->md5sum, &h_ota->size_file)) { - LOG_ERROR("Get firmware parameter failed"); - goto do_exit; + if (0 == strcmp(msg_method, UPDATE_FIRMWARE_METHOD)) + { + /* downloading, push update msg to list */ + if (h_ota->state == OTA_STATE_FETCHING) { + LOG_INFO("In OTA_STATE_FETCHING state"); + _ota_push_upload_msg(h_ota, msg_str, msg_len); + goto do_exit; + } + + if (SUCCESS_RET != ota_lib_get_params(msg_str, &h_ota->url, &h_ota->module, &h_ota->download_name, &h_ota->version, &h_ota->md5sum, &h_ota->size_file)) { + LOG_ERROR("Get firmware parameter failed"); + goto do_exit; + } + + if (NULL == (h_ota->ch_fetch = ofc_init(h_ota->url))) { + LOG_ERROR("Initialize fetch module failed"); + goto do_exit; + } + + if (SUCCESS_RET != ofc_connect(h_ota->ch_fetch)) { + LOG_ERROR("Connect fetch module failed"); + h_ota->state = OTA_STATE_DISCONNECTED; + goto do_exit; + } + + h_ota->state = OTA_STATE_FETCHING; + + if(SUCCESS_RET != IOT_OTA_fw_download(h_ota)) { + LOG_ERROR("download file failed"); + h_ota->state = OTA_STATE_DISCONNECTED; + } + + /* download over, pop first pushed msg to download */ + _ota_pop_upload_msg(h_ota); + } + else if(0 == strcmp(msg_method, CANCEL_UPDATE_METHOD)) + { + if (SUCCESS_RET != ota_lib_get_msg_module_ver(msg_str, &msg_module, &msg_ver)) { + LOG_ERROR("Get message module failed!"); + HAL_Free(msg_module); + HAL_Free(msg_ver); + goto do_exit; + } - if (NULL == (h_ota->ch_fetch = ofc_init(h_ota->url))) { - LOG_ERROR("Initialize fetch module failed"); - goto do_exit; + if((0 == strcmp(msg_module, h_ota->module)) && (0 == strcmp(msg_ver, h_ota->version))) + { + OTA_Http_Client *h_ofc = (OTA_Http_Client *)h_ota->ch_fetch; + http_client_close(&h_ofc->http); + h_ota->state = OTA_STATE_DISCONNECTED; + } + HAL_Free(msg_module); + HAL_Free(msg_ver); } - - if (SUCCESS_RET != ofc_connect(h_ota->ch_fetch)) { - LOG_ERROR("Connect fetch module failed"); - h_ota->state = OTA_STATE_DISCONNECTED; - goto do_exit; - } - - h_ota->state = OTA_STATE_FETCHING; - - IOT_OTA_fw_download(h_ota); - do_exit: HAL_Free(msg_str); HAL_Free(msg_method); @@ -171,7 +232,7 @@ int IOT_OTA_ReportProgress(void *handle, int progress, IOT_OTA_ProgressState sta return ERR_OTA_NO_MEMORY; } - ret = ota_lib_gen_upstream_msg(msg_report, OTA_UPSTREAM_MSG_BUF_LEN, h_ota->version, progress, (IOT_OTA_UpstreamMsgType)state); + ret = ota_lib_gen_upstream_msg(msg_report, OTA_UPSTREAM_MSG_BUF_LEN, h_ota->module, h_ota->version, progress, (IOT_OTA_UpstreamMsgType)state); if (SUCCESS_RET != ret) { LOG_ERROR("generate reported message failed"); h_ota->err = ret; @@ -193,7 +254,7 @@ do_exit: } -static int send_upstream_msg_with_version(void *handle, const char *version, IOT_OTA_UpstreamMsgType reportType) +static int send_upstream_msg_with_version(void *handle, const char *module, const char *version, IOT_OTA_UpstreamMsgType reportType) { POINTER_VALID_CHECK(handle, ERR_OTA_INVALID_PARAM); POINTER_VALID_CHECK(version, ERR_OTA_INVALID_PARAM); @@ -221,7 +282,7 @@ static int send_upstream_msg_with_version(void *handle, const char *version, IOT return ERR_OTA_NO_MEMORY; } - ret = ota_lib_gen_upstream_msg(msg_upstream, OTA_UPSTREAM_MSG_BUF_LEN, version, 0, reportType); + ret = ota_lib_gen_upstream_msg(msg_upstream, OTA_UPSTREAM_MSG_BUF_LEN, module, version, 0, reportType); if (SUCCESS_RET != ret) { LOG_ERROR("generate upstream message failed"); h_ota->err = ret; @@ -242,7 +303,6 @@ do_exit: return ret; } - void *IOT_OTA_Init(const char *product_sn, const char *device_sn, void *ch_signal) { POINTER_VALID_CHECK(product_sn, NULL); @@ -263,7 +323,7 @@ void *IOT_OTA_Init(const char *product_sn, const char *device_sn, void *ch_signa LOG_ERROR("initialize signal channel failed"); goto do_exit; } - + h_ota->md5 = ota_lib_md5_init(); if (NULL == h_ota->md5) { LOG_ERROR("initialize md5 failed"); @@ -301,7 +361,7 @@ int IOT_OTA_Destroy(void *handle) return FAILURE_RET; } - osc_deinit(h_ota->ch_signal); + osc_deinit(h_ota->ch_signal); ofc_deinit(h_ota->ch_fetch); ota_lib_md5_deinit(h_ota->md5); @@ -309,6 +369,10 @@ int IOT_OTA_Destroy(void *handle) HAL_Free(h_ota->url); } + if (NULL != h_ota->module) { + HAL_Free(h_ota->module); + } + if (NULL != h_ota->version) { HAL_Free(h_ota->version); } @@ -317,6 +381,10 @@ int IOT_OTA_Destroy(void *handle) HAL_Free(h_ota->md5sum); } + if (NULL != h_ota->download_name) { + HAL_Free(h_ota->download_name); + } + HAL_Free(h_ota); return SUCCESS_RET; } @@ -324,35 +392,60 @@ int IOT_OTA_Destroy(void *handle) void IOT_OTA_Clear(void *handle) { OTA_Struct_t *h_ota = (OTA_Struct_t *)handle; - memset(h_ota->url, 0, strlen(h_ota->url)); - memset(h_ota->version, 0, strlen(h_ota->version)); - memset(h_ota->md5sum, 0, strlen(h_ota->md5sum)); + + ofc_deinit(h_ota->ch_fetch); + + if (NULL != h_ota->url) { + memset(h_ota->url, 0, strlen(h_ota->url)); + } + + if (NULL != h_ota->module) { + memset(h_ota->module, 0, strlen(h_ota->module)); + } + + if(NULL != h_ota->download_name){ + memset(h_ota->download_name, 0, strlen(h_ota->download_name)); + } + + if (NULL != h_ota->version) { + memset(h_ota->version, 0, strlen(h_ota->version)); + } + + if (NULL != h_ota->md5sum) { + memset(h_ota->md5sum, 0, strlen(h_ota->md5sum)); + } + h_ota->size_last_fetched = 0; h_ota->size_fetched = 0; h_ota->size_file = 0; - ota_lib_md5_deinit(h_ota->md5); + ota_lib_md5_deinit(h_ota->md5); h_ota->md5 = ota_lib_md5_init(); h_ota->state = OTA_STATE_INITED; return; } -int IOT_OTA_ReportVersion(void *handle, const char *version) +int IOT_OTA_ReportVersion(void *handle, const char *module, const char *version) { - return send_upstream_msg_with_version(handle, version, OTA_REPORT_VERSION); + return send_upstream_msg_with_version(handle, module, version, OTA_REPORT_VERSION); } -int IOT_OTA_RequestFirmware(void *handle, const char *version) +int IOT_OTA_RequestFirmware(void *handle, const char *module, const char *version) { - return send_upstream_msg_with_version(handle, version, OTA_REQUEST_FIRMWARE); + return send_upstream_msg_with_version(handle, module, version, OTA_REQUEST_FIRMWARE); } int IOT_OTA_ReportSuccess(void *handle, const char *version) -{ - return send_upstream_msg_with_version(handle, version, OTA_REPORT_SUCCESS); +{ + OTA_Struct_t *h_ota = (OTA_Struct_t *)handle; + + if(h_ota->fetch_callback_func != NULL) + { + h_ota->fetch_callback_func(handle, OTA_REPORT_SUCCESS); + } + return send_upstream_msg_with_version(handle, h_ota->module, version, OTA_REPORT_SUCCESS); } - int IOT_OTA_ReportFail(void *handle, IOT_OTA_ReportErrCode err_code) { POINTER_VALID_CHECK(handle, ERR_OTA_INVALID_PARAM); @@ -373,7 +466,7 @@ int IOT_OTA_ReportFail(void *handle, IOT_OTA_ReportErrCode err_code) return ERR_OTA_NO_MEMORY; } - ret = ota_lib_gen_upstream_msg(msg_upstream, OTA_UPSTREAM_MSG_BUF_LEN, "", 0, (IOT_OTA_UpstreamMsgType)err_code); + ret = ota_lib_gen_upstream_msg(msg_upstream, OTA_UPSTREAM_MSG_BUF_LEN, h_ota->module, "", 0, (IOT_OTA_UpstreamMsgType)err_code); if (SUCCESS_RET != ret) { LOG_ERROR("generate upstream message failed"); h_ota->err = ret; @@ -387,6 +480,9 @@ int IOT_OTA_ReportFail(void *handle, IOT_OTA_ReportErrCode err_code) goto do_exit; } + if(h_ota->fetch_callback_func != NULL) + h_ota->fetch_callback_func(handle, (IOT_OTA_UpstreamMsgType)err_code); + do_exit: if (NULL != msg_upstream) { HAL_Free(msg_upstream); @@ -432,6 +528,14 @@ int IOT_OTA_IsFetchFinish(void *handle) return (OTA_STATE_FETCHED == h_ota->state); } +int IOT_OTA_Yield(void *handle, uint32_t timeout_ms) +{ + POINTER_VALID_CHECK(handle, FAILURE_RET); + + OTA_Struct_t *h_ota = (OTA_Struct_t*) handle; + + return IOT_MQTT_Yield(((OTA_MQTT_Struct_t *)h_ota->ch_signal)->mqtt, timeout_ms); +} int IOT_OTA_FetchYield(void *handle, char *buf, size_t buf_len, size_t range_len, uint32_t timeout_s) { @@ -453,7 +557,7 @@ int IOT_OTA_FetchYield(void *handle, char *buf, size_t buf_len, size_t range_len /* fetch fail,try again utill 5 time */ ret = ofc_fetch(h_ota->ch_fetch, h_ota->size_fetched ,buf, buf_len, range_len, timeout_s); /* range download send request too often maybe cutdown by server, need reconnect and continue to download. */ - if(ret == ERR_HTTP_CONN_ERROR) { + if((ret == ERR_HTTP_CONN_ERROR) && (h_ota->state != OTA_STATE_DISCONNECTED)) { ofc_deinit(h_ota->ch_fetch); h_ota->ch_fetch = ofc_init(h_ota->url); ofc_connect(h_ota->ch_fetch); @@ -610,37 +714,26 @@ int IOT_OTA_fw_download(void *handle) { int ret = 0; int file_size = 0, length, firmware_valid, total_length = 0; - uint8_t *buffer_read = RT_NULL; - const struct fal_partition * dl_part = RT_NULL; + char *buffer_read = NULL; OTA_Struct_t * h_ota = (OTA_Struct_t *) handle; + void * download_handle = NULL; // 用于存放云端下发的固件版本 char msg_version[33]; IOT_OTA_Ioctl(h_ota, OTA_IOCTL_FILE_SIZE, &file_size, 4); - - /* Get download partition information and erase download partition data */ - if ((dl_part = fal_partition_find("download")) == RT_NULL) + + download_handle = HAL_Download_Init(h_ota->download_name); + if(download_handle == NULL) { - LOG_ERROR("Firmware download failed! Partition (%s) find error!", "download"); - ret = -RT_ERROR; + ret = FAILURE_RET; goto __exit; } - LOG_INFO("Start erase flash (%s) partition!", dl_part->name); - - if (fal_partition_erase(dl_part, 0, file_size) < 0) - { - LOG_ERROR("Firmware download failed! Partition (%s) erase error!", dl_part->name); - ret = -RT_ERROR; - goto __exit; - } - LOG_INFO("Erase flash (%s) partition success!", dl_part->name); - - buffer_read = (uint8_t *)HAL_Malloc(HTTP_OTA_BUFF_LEN); - if (buffer_read == RT_NULL) + buffer_read = (char *)HAL_Malloc(HTTP_OTA_BUFF_LEN); + if (buffer_read == NULL) { LOG_ERROR("No memory for http ota!"); - ret = -RT_ERROR; + ret = FAILURE_RET; goto __exit; } memset(buffer_read, 0x00, HTTP_OTA_BUFF_LEN); @@ -652,25 +745,26 @@ int IOT_OTA_fw_download(void *handle) if (length > 0) { /* Write the data to the corresponding partition address */ - if (fal_partition_write(dl_part, total_length, buffer_read, length) < 0) - { - LOG_ERROR("Firmware download failed! Partition (%s) write data error!", dl_part->name); - ret = -RT_ERROR; + if(HAL_Download_Write(download_handle, total_length, buffer_read, length) == FAILURE_RET){ + ret = FAILURE_RET; goto __exit; } + total_length += length; + //wait cancel cmd + IOT_OTA_Yield(handle, 100); } else { LOG_ERROR("Exit: server return err (%d)!", length); - ret = -RT_ERROR; + ret = ERR_OTA_FETCH_FAILED; goto __exit; } } while (!IOT_OTA_IsFetchFinish(h_ota)); if (total_length == file_size) { - ret = RT_EOK; + ret = SUCCESS_RET; IOT_OTA_Ioctl(h_ota, OTA_IOCTL_CHECK_FIRMWARE, &firmware_valid, 4); if (0 == firmware_valid) { LOG_ERROR("The firmware is invalid"); @@ -681,23 +775,18 @@ int IOT_OTA_fw_download(void *handle) IOT_OTA_Ioctl(h_ota, OTA_IOCTL_VERSION, msg_version, 33); IOT_OTA_ReportSuccess(h_ota, msg_version); } + + if(HAL_Download_End(download_handle)) + ret = FAILURE_RET; LOG_INFO("Download firmware to flash success."); - LOG_INFO("System now will restart..."); - - rt_thread_delay(rt_tick_from_millisecond(5)); - - /* Reset the device, Start new firmware */ - extern void rt_hw_cpu_reset(void); - rt_hw_cpu_reset(); } __exit: - if (buffer_read != RT_NULL) - HAL_Free(buffer_read); - + if (buffer_read != NULL) + HAL_Free(buffer_read); IOT_OTA_Clear(h_ota); - + return ret; } diff --git a/uiot/ota/src/ota_fetch.c b/uiot/ota/src/ota_fetch.c index edccd53..eb8f908 100644 --- a/uiot/ota/src/ota_fetch.c +++ b/uiot/ota/src/ota_fetch.c @@ -21,15 +21,6 @@ #include "ca.h" #include "utils_httpc.h" -typedef struct { - - const char *url; - http_client_t http; /* http client */ - http_client_data_t http_data; /* http client data */ - -} OTA_Http_Client; - - void *ofc_init(const char *url) { FUNC_ENTRY; diff --git a/uiot/ota/src/ota_lib.c b/uiot/ota/src/ota_lib.c index 45c1095..499b2a6 100644 --- a/uiot/ota/src/ota_lib.c +++ b/uiot/ota/src/ota_lib.c @@ -64,16 +64,42 @@ int ota_lib_get_msg_type(char *json, char **type) { FUNC_EXIT_RC(SUCCESS_RET); } +int ota_lib_get_msg_module_ver(char *json, char **module, char **ver) { + FUNC_ENTRY; -int ota_lib_get_params(char *json, char **url, char **version, char **md5, + if (NULL == (*module = LITE_json_value_of(MODULE_FIELD, json))) { + LOG_ERROR("get value of module key failed"); + FUNC_EXIT_RC(ERR_OTA_GENERAL_FAILURE); + } + + if (NULL == (*ver = LITE_json_value_of(VERSION_FIELD, json))) { + LOG_ERROR("get value of ver key failed"); + FUNC_EXIT_RC(ERR_OTA_GENERAL_FAILURE); + } + + FUNC_EXIT_RC(SUCCESS_RET); +} + +int ota_lib_get_params(char *json, char **url, char **module, char **download_name, char **version, char **md5, uint32_t *fileSize) { FUNC_ENTRY; + char *module_str; char *file_size_str; char *version_str; char *url_str; char *md5_str; + /* get module */ + if (NULL == (module_str = LITE_json_value_of(MODULE_FIELD, json))) { + LOG_ERROR("get value of module key failed"); + FUNC_EXIT_RC(ERR_OTA_GENERAL_FAILURE); + } + if (NULL != *module) { + HAL_Free(*module); + } + *module = module_str; + /* get version */ if (NULL == (version_str = LITE_json_value_of(VERSION_FIELD, json))) { LOG_ERROR("get value of version key failed"); @@ -94,6 +120,8 @@ int ota_lib_get_params(char *json, char **url, char **version, char **md5, } *url = url_str; + *download_name = HAL_Download_Name_Set((void*)url_str); + /* get md5 */ if (NULL == (md5_str = LITE_json_value_of(MD5_FIELD, json))) { LOG_ERROR("get value of md5 failed"); @@ -119,7 +147,7 @@ int ota_lib_get_params(char *json, char **url, char **version, char **md5, FUNC_EXIT_RC(SUCCESS_RET); } -int ota_lib_gen_upstream_msg(char *buf, size_t bufLen, const char *version, int progress, +int ota_lib_gen_upstream_msg(char *buf, size_t bufLen, const char *module, const char *version, int progress, IOT_OTA_UpstreamMsgType reportType) { FUNC_ENTRY; @@ -136,23 +164,23 @@ int ota_lib_gen_upstream_msg(char *buf, size_t bufLen, const char *version, int break; case OTA_REPORT_DOWNLOADING: - ret = HAL_Snprintf(buf, bufLen, REPORT_PROGRESS_MSG_TEMPLATE, "downloading", progress); + ret = HAL_Snprintf(buf, bufLen, REPORT_PROGRESS_MSG_TEMPLATE, "downloading", progress, module, version); break; case OTA_REPORT_BURNING: - ret = HAL_Snprintf(buf, bufLen, REPORT_PROGRESS_MSG_TEMPLATE, "burning", progress); + ret = HAL_Snprintf(buf, bufLen, REPORT_PROGRESS_MSG_TEMPLATE, "burning", progress, module, version); break; case OTA_REPORT_SUCCESS: - ret = HAL_Snprintf(buf, bufLen, REPORT_SUCCESS_MSG_TEMPLATE, version); + ret = HAL_Snprintf(buf, bufLen, REPORT_SUCCESS_MSG_TEMPLATE, module, version); break; case OTA_REQUEST_FIRMWARE: - ret = HAL_Snprintf(buf, bufLen, REQUEST_FIRMWARE_MSG_TEMPLATE, version); + ret = HAL_Snprintf(buf, bufLen, REQUEST_FIRMWARE_MSG_TEMPLATE, module, version); break; case OTA_REPORT_VERSION: - ret = HAL_Snprintf(buf, bufLen, REPORT_VERSION_MSG_TEMPLATE, version); + ret = HAL_Snprintf(buf, bufLen, REPORT_VERSION_MSG_TEMPLATE, module, version); break; default: FUNC_EXIT_RC(ERR_OTA_GENERAL_FAILURE); diff --git a/uiot/ota/src/ota_mqtt.c b/uiot/ota/src/ota_mqtt.c index 7d14ed3..479a4ad 100644 --- a/uiot/ota/src/ota_mqtt.c +++ b/uiot/ota/src/ota_mqtt.c @@ -23,16 +23,6 @@ #include "ota_config.h" #include "ota_internal.h" -/* OSC, OTA signal channel */ -typedef struct { - void *mqtt; - const char *product_sn; - const char *device_sn; - char topic_upgrade[OTA_TOPIC_BUF_LEN]; - OnOTAMessageCallback msg_callback; - void *context; -} OTA_MQTT_Struct_t; - static int _ota_mqtt_gen_topic_name(char *buf, size_t buf_len, const char *ota_topic_type, const char *product_sn, const char *device_sn) { @@ -119,6 +109,10 @@ void *osc_init(const char *product_sn, const char *device_sn, void *channel, OnO h_osc->device_sn = device_sn; h_osc->msg_callback = callback; h_osc->context = context; + h_osc->msg_list = list_new(); + h_osc->msg_mutex = HAL_MutexCreate(); + if (h_osc->msg_mutex == NULL) + goto do_exit; /* subscribe the OTA topic: "/$system/$(product_sn)/$(device_sn)/ota/downstream" */ ret = _ota_mqtt_gen_topic_name(h_osc->topic_upgrade, OTA_TOPIC_BUF_LEN, OTA_DOWNSTREAM_TOPIC_TYPE, product_sn, @@ -153,6 +147,11 @@ int osc_deinit(void *handle) { FUNC_ENTRY; + OTA_MQTT_Struct_t *h_osc = handle; + + list_destroy(h_osc->msg_list); + HAL_MutexDestroy(h_osc->msg_mutex); + if (NULL != handle) { HAL_Free(handle); } diff --git a/uiot/sdk-impl/uiot_defs.h b/uiot/sdk-impl/uiot_defs.h index 307d3de..84b5dc4 100644 --- a/uiot/sdk-impl/uiot_defs.h +++ b/uiot/sdk-impl/uiot_defs.h @@ -134,7 +134,7 @@ typedef enum { {\ HAL_Printf("DEBUG: %s L#%d ", __func__, __LINE__); \ HAL_Printf(__VA_ARGS__); \ - HAL_Printf("\n"); \ + HAL_Printf("\r\n"); \ } #else #define LOG_DEBUG(...) @@ -149,7 +149,7 @@ typedef enum { #define LOG_INFO(...) \ {\ HAL_Printf(__VA_ARGS__); \ - HAL_Printf("\n"); \ + HAL_Printf("\r\n"); \ } #else #define LOG_INFO(...) @@ -165,7 +165,7 @@ typedef enum { { \ HAL_Printf("WARN: %s L#%d ", __func__, __LINE__); \ HAL_Printf(__VA_ARGS__); \ - HAL_Printf("\n"); \ + HAL_Printf("\r\n"); \ } #else #define LOG_WARN(...) @@ -181,7 +181,7 @@ typedef enum { { \ HAL_Printf("ERROR: %s L#%d ", __func__, __LINE__); \ HAL_Printf(__VA_ARGS__); \ - HAL_Printf("\n"); \ + HAL_Printf("\r\n"); \ } #else #define LOG_ERROR(...) @@ -190,16 +190,16 @@ typedef enum { #ifdef ENABLE_IOT_TRACE #define FUNC_ENTRY \ {\ - HAL_Printf("FUNC_ENTRY: %s L#%d \n", __func__, __LINE__); \ + HAL_Printf("FUNC_ENTRY: %s L#%d \r\n", __func__, __LINE__); \ } #define FUNC_EXIT \ {\ - HAL_Printf("FUNC_EXIT: %s L#%d \n", __func__, __LINE__); \ + HAL_Printf("FUNC_EXIT: %s L#%d \r\n", __func__, __LINE__); \ return; \ } #define FUNC_EXIT_RC(x) \ {\ - HAL_Printf("FUNC_EXIT: %s L#%d Return Code : %d \n", __func__, __LINE__, x); \ + HAL_Printf("FUNC_EXIT: %s L#%d Return Code : %d \r\n", __func__, __LINE__, x); \ return x; \ } #else diff --git a/uiot/sdk-impl/uiot_export_dm.h b/uiot/sdk-impl/uiot_export_dm.h index 89ad88b..e8472b2 100644 --- a/uiot/sdk-impl/uiot_export_dm.h +++ b/uiot/sdk-impl/uiot_export_dm.h @@ -34,11 +34,87 @@ typedef enum _dm_type { DM_TYPE_MAX }DM_Type; +typedef enum{ + TYPE_INT, + TYPE_FLOAT, + TYPE_DOUBLE, + TYPE_BOOL, + TYPE_ENUM, + TYPE_STRING, + TYPE_DATE, +} DM_Base_Type; + +typedef enum{ + TYPE_NODE, + TYPE_STRUCT, + TYPE_ARRAY_BASE, + TYPE_ARRAY_STRUCT, +} DM_Parse_Type; + +typedef union{ + int int32_value; + float float32_value; + double float64_value; + bool bool_value; + int enum_value; + char *string_value; + long date_value; +}DM_Base_Value_U; + +typedef struct{ + DM_Base_Type base_type; + char *key; + DM_Base_Value_U value; +} DM_Node_t; + +typedef struct{ + char *key; + DM_Node_t *value; + int num; +} DM_Type_Struct_t; + +typedef struct{ + char *key; + DM_Node_t *value; + int num; +} DM_Array_Base_t; + +typedef struct{ + char *key; + DM_Type_Struct_t *value; + int num; +} DM_Array_Struct_t; + +typedef union{ + DM_Node_t *dm_node; + DM_Type_Struct_t *dm_struct; + DM_Array_Base_t *dm_array_base; + DM_Array_Struct_t *dm_array_struct; +}DM_Property_Value_U; + +typedef struct{ + DM_Parse_Type parse_type; + DM_Property_Value_U value; + int desired_ver; +} DM_Property_t; + +typedef struct{ + char *event_identy; + DM_Property_t *dm_property; + int property_num; +} DM_Event_t; + +typedef struct{ + DM_Property_t *input; + int input_num; + DM_Property_t *output; + int output_num; +} DM_Command_t; typedef int (* PropertyRestoreCB)(const char *request_id, const int ret_code, const char *property); typedef int (* PropertySetCB)(const char *request_id, const char *property); typedef int (* PropertyDesiredGetCB)(const char *request_id, const int ret_code, const char *desired); -typedef int (* CommandCB)(const char *request_id, const char *identifier, const char *input, char **output); +typedef int (* CommandCB)(const char *request_id, const char *identifier, const char *input, char *output); typedef int (* CommonReplyCB)(const char *request_id, const int ret_code); #define DECLARE_DM_CALLBACK(type, cb) int uiot_register_for_##type(void*, cb); @@ -105,6 +181,24 @@ int IOT_DM_Destroy(void *handle); */ int IOT_DM_Property_Report(void *handle, DM_Type type, int request_id, const char *payload); +/** + * @brief 属性有关的消息上报,拓展接口 + * + * @param handle: IOT_DM_Init返回的句柄 + * @param type: 消息类型,此处为 + PROPERTY_RESTORE, + PROPERTY_POST, + PROPERTY_DESIRED_GET, + PROPERTY_DESIRED_DELETE + 四种消息类型之一 + * @param request_id: 消息的request_id + * @param property_num: 属性个数 + * @param ...: 属性 + * + * @retval 0 : 成功 + * @retval < 0 : 失败,返回具体错误码 + */ +int IOT_DM_Property_ReportEx(void *handle, DM_Type type, int request_id, int property_num, ...); /** * @brief 事件消息上报 @@ -119,6 +213,29 @@ int IOT_DM_Property_Report(void *handle, DM_Type type, int request_id, const cha */ int IOT_DM_TriggerEvent(void *handle, int request_id, const char *identifier, const char *payload); +/** + * @brief 事件消息上报,拓展接口 + * + * @param handle: IOT_DM_Init返回的句柄 + * @param request_id: 消息的request_id + * @param event: 事件的句柄 + * + * @retval 0 : 成功 + * @retval < 0 : 失败,返回具体错误码 + */ +int IOT_DM_TriggerEventEx(void *handle, int request_id, DM_Event_t *event); + +/** + * @brief 命令消息输出参数键值对生成 + * + * @param output: 生成的输出参数键值对 + * @param property_num: 属性个数 + * @param ...: 属性 + * + * @retval 0 : 成功 + * @retval < 0 : 失败,返回具体错误码 + */ +int IOT_DM_GenCommandOutput(char *output, int property_num, ...); /** * @brief 在当前线程为底层MQTT客户端让出一定CPU执行时间,让其接收网络报文并将消息分发到用户的回调函数中 diff --git a/uiot/sdk-impl/uiot_export_ota.h b/uiot/sdk-impl/uiot_export_ota.h index 5455825..63f4527 100644 --- a/uiot/sdk-impl/uiot_export_ota.h +++ b/uiot/sdk-impl/uiot_export_ota.h @@ -50,6 +50,58 @@ typedef enum { } IOT_OTA_ReportErrCode; +typedef enum { + + OTA_REPORT_UNDEFINED_ERROR = -6, + OTA_REPORT_FIRMWARE_BURN_FAILED = -5, + OTA_REPORT_MD5_MISMATCH = -4, + OTA_REPORT_DOWNLOAD_TIMEOUT = -3, + OTA_REPORT_SIGNATURE_EXPIRED = -2, + OTA_REPORT_FIRMWARE_NOT_EXIST = -1, + OTA_REPORT_NONE = 0, + OTA_REPORT_DOWNLOADING = 1, + OTA_REPORT_BURNING = 2, + OTA_REPORT_SUCCESS = 3, + OTA_REQUEST_FIRMWARE = 4, + OTA_REPORT_VERSION = 5, + +} IOT_OTA_UpstreamMsgType; + +typedef int (*IOT_OTA_FetchCallback)(void *handle, IOT_OTA_UpstreamMsgType state); + +/* OTA状态 */ +typedef enum { + + OTA_STATE_UNINITED = 0, /* 未初始化 */ + OTA_STATE_INITED, /* 初始化完成 */ + OTA_STATE_FETCHING, /* 正在下载固件 */ + OTA_STATE_FETCHED, /* 固件下载完成 */ + OTA_STATE_DISCONNECTED /* 连接已经断开 */ + +} IOT_OTA_State; + +typedef struct { + uint32_t id; /* message id */ + IOT_OTA_State 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 *url; /* point to URL */ + char *download_name; /* download partition name */ + char *module; /* download module name */ + char *version; /* point to version */ + char *md5sum; /* 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 */ + + Timer report_timer; + IOT_OTA_FetchCallback fetch_callback_func; +} OTA_Struct_t; /** * @brief 初始化OTA模块和返回句柄 @@ -81,12 +133,13 @@ int IOT_OTA_Destroy(void *handle); * NOTE: 进行OTA前请保证先上报一次本地固件的版本信息,以便服务器获取到设备目前的固件信息 * * @param handle: 指定OTA模块 + * @param module: 版本所属类型 * @param version: 以字符串格式指定固件版本 * * @retval > 0 : 对应publish的packet id * @retval < 0 : 失败,返回具体错误码 */ -int IOT_OTA_ReportVersion(void *handle, const char *version); +int IOT_OTA_ReportVersion(void *handle, const char *module, const char *version); /** @@ -101,7 +154,6 @@ int IOT_OTA_ReportVersion(void *handle, const char *version); */ int IOT_OTA_ReportProgress(void *handle, int progress, IOT_OTA_ProgressState state); - /** * @brief 向OTA服务器上报升级成功 * @@ -113,7 +165,6 @@ int IOT_OTA_ReportProgress(void *handle, int progress, IOT_OTA_ProgressState sta */ int IOT_OTA_ReportSuccess(void *handle, const char *version); - /** * @brief 向OTA服务器上报失败信息 * @@ -189,12 +240,13 @@ int IOT_OTA_GetLastError(void *handle); * @brief 请求固件更新消息。设备离线时,不能接收服务端推送的升级消息。通过MQTT协议接入物联网平台的设备再次上线后,主动请求固件更新消息 * * @param handle: 指定OTA模块 + * @param module: 版本所属类型 * @param version: 当前固件版本号 * * @retval > 0 : 对应publish的packet id * @retval < 0 : 失败,返回具体错误码 */ -int IOT_OTA_RequestFirmware(void *handle, const char *version); +int IOT_OTA_RequestFirmware(void *handle, const char *module, const char *version); /** * @brief 下载固件,下载结束后重启设备 diff --git a/uiot/sdk-impl/uiot_import.h b/uiot/sdk-impl/uiot_import.h index e5d2dc5..2beeb02 100644 --- a/uiot/sdk-impl/uiot_import.h +++ b/uiot/sdk-impl/uiot_import.h @@ -29,7 +29,10 @@ extern "C" { #include "uiot_defs.h" #include "HAL_Timer_Platform.h" +#include "HAL_Flash_Platform.h" #include "utils_net.h" +#include "lite-utils.h" +#include "json_parser.h" /** * @brief 创建互斥量 @@ -316,17 +319,108 @@ int32_t HAL_TCP_Write(_IN_ uintptr_t fd, _IN_ unsigned char *buf, _IN_ size_t le */ int32_t HAL_TCP_Read(_IN_ uintptr_t fd, _OU_ unsigned char *buf, _IN_ size_t len, _IN_ uint32_t timeout_ms); +/** + * @brief 设置相应name + * + * @param handle 指向download_name的指针 + * @return 指向download_name的指针 + */ +void * HAL_Download_Name_Set(void * handle); + +/** + * @brief 下载的准备工作 + * + * @param name 文件名 + * @return 文件描述符 + */ +void * HAL_Download_Init(_IN_ void * name); + +/** +* @brief 将长度为length的buffer_read的数据写入到FLASH中 + * + * @param handle 文件描述符 + * @param total_length 未用到 + * @param buffer_read 数据的指针 + * @param length 数据的长度,单位为字节 + * @return + */ +int HAL_Download_Write(_IN_ void * handle,_IN_ uint32_t total_length,_IN_ uint8_t *buffer_read,_IN_ uint32_t length); + +/** + * @brief STM32F767 FLASH的information分区的下载标志置位成功 + * + * @param handle 文件描述符 + * @return -1失败 0成功 + */ +int HAL_Download_End(_IN_ void * handle); + +#ifdef SUPPORT_AT_CMD + +/** + * @brief 通讯模组初始化。 + * + * @param 无 + * @return 无 + */ +void HAL_AT_Init(); + +/** + * @brief 向指定的通讯模组读AT命令执行结果。 + * + * @param pNetwork 网络句柄 + * @param buf 指向数据接收缓冲区的指针 + * @param len 数据接收缓冲区的字节大小 + * @return <0: TCP读取错误; =0: TCP读超时, 且没有读取任何数据; >0: TCP成功读取的字节数 + */ int HAL_AT_Read(_IN_ utils_network_pt pNetwork, _OU_ unsigned char *buffer, _IN_ size_t len); +/** + * @brief 向指定的通讯模组写AT命令。 + * + * @param buf 指向数据发送缓冲区的指针 + * @param len 数据发送缓冲区的字节大小 + * @return <0: TCP写入错误; =0: TCP写超时, 且没有写入任何数据; >0: TCP成功写入的字节数 + */ int HAL_AT_Write(_IN_ unsigned char *buffer, _IN_ size_t len); -int HAL_AT_TCP_Disconnect(void); +/** + * @brief 断开TCP连接, 并释放相关对象资源。 + * + * @param pNetwork 网络句柄 + * @return 成功返回SUCCESS,失败返回FAILURE + */ +int HAL_AT_TCP_Disconnect(utils_network_pt pNetwork); -int HAL_AT_TCP_Connect(_IN_ void * pNetwork, _IN_ const char *host, _IN_ uint16_t port); +/** + * @brief 建立TCP连接。根据指定的HOST地址, 服务器端口号建立TCP连接, 返回对应的连接句柄。 + * + * @param pNetwork 网络句柄 + * @param host 指定的TCP服务器网络地址 + * @param port 指定的TCP服务器端口 + * @return 连接成功, 返回TCP连接句柄,连接失败,返回NULL + */ +int HAL_AT_TCP_Connect(_IN_ utils_network_pt pNetwork, _IN_ const char *host, _IN_ uint16_t port); +/** + * @brief 向指定的TCP连接写入数据。 + * + * @param pNetwork 网络句柄 + * @param buf 指向数据发送缓冲区的指针 + * @param len 数据发送缓冲区的字节大小 + * @return <0: TCP写入错误; =0: TCP写超时, 且没有写入任何数据; >0: TCP成功写入的字节数 + */ int HAL_AT_Write_Tcp(_IN_ utils_network_pt pNetwork, _IN_ unsigned char *buffer, _IN_ size_t len); +/** + * @brief 从指定的TCP连接读取数据。 + * + * @param pNetwork 网络句柄 + * @param buf 指向数据接收缓冲区的指针 + * @param len 数据接收缓冲区的字节大小 + * @return <0: TCP读取错误; =0: TCP读超时, 且没有读取任何数据; >0: TCP成功读取的字节数 + */ int HAL_AT_Read_Tcp(_IN_ utils_network_pt pNetwork, _IN_ unsigned char *buffer, _IN_ size_t len); +#endif #if defined(__cplusplus) }