EC600U_esp32_iap_uart/qcloud-iot/samples/gateway/sub_dev001.c

684 lines
23 KiB
C
Raw Permalink Normal View History

2024-02-05 17:39:56 +08:00
/*
* Tencent is pleased to support the open source community by making IoT Hub
available.
* Copyright (C) 2016 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.
*
*/
#include "lite-utils.h"
#include "qcloud_iot_export.h"
#include "qcloud_iot_import.h"
#include "utils_timer.h"
#include "qcloud_iot_export_data_template.h"
/* anis color control codes */
#define ANSI_COLOR_RED "\x1b[31m"
#define ANSI_COLOR_GREEN "\x1b[32m"
#define ANSI_COLOR_YELLOW "\x1b[33m"
#define ANSI_COLOR_BLUE "\x1b[34m"
#define ANSI_COLOR_RESET "\x1b[0m"
static DeviceInfo sg_devInfo;
static Timer sg_reportTimer;
static MQTTEventType sg_subscribe_event_result = MQTT_EVENT_UNDEF;
static bool sg_control_msg_arrived = false;
static char sg_data_report_buffer[2048];
size_t sg_data_report_buffersize = sizeof(sg_data_report_buffer) / sizeof(sg_data_report_buffer[0]);
/*data_config.c can be generated by tools/codegen.py -c xx/product.json*/
/*-----------------data config start -------------------*/
#define TOTAL_PROPERTY_COUNT 4
#define MAX_STR_NAME_LEN (64)
static sDataPoint sg_DataTemplate[TOTAL_PROPERTY_COUNT];
typedef enum {
eCOLOR_RED = 0,
eCOLOR_GREEN = 1,
eCOLOR_BLUE = 2,
} eColor;
typedef struct _ProductDataDefine {
TYPE_DEF_TEMPLATE_BOOL m_light_switch;
TYPE_DEF_TEMPLATE_ENUM m_color;
TYPE_DEF_TEMPLATE_INT m_brightness;
TYPE_DEF_TEMPLATE_STRING m_name[MAX_STR_NAME_LEN + 1];
} ProductDataDefine;
static ProductDataDefine sg_ProductData;
static void _init_data_template(void)
{
memset((void *)&sg_ProductData, 0, sizeof(ProductDataDefine));
sg_ProductData.m_light_switch = 0;
sg_DataTemplate[0].data_property.key = "power_switch";
sg_DataTemplate[0].data_property.data = &sg_ProductData.m_light_switch;
sg_DataTemplate[0].data_property.type = TYPE_TEMPLATE_BOOL;
sg_ProductData.m_color = eCOLOR_RED;
sg_DataTemplate[1].data_property.key = "color";
sg_DataTemplate[1].data_property.data = &sg_ProductData.m_color;
sg_DataTemplate[1].data_property.type = TYPE_TEMPLATE_ENUM;
sg_ProductData.m_brightness = 0;
sg_DataTemplate[2].data_property.key = "brightness";
sg_DataTemplate[2].data_property.data = &sg_ProductData.m_brightness;
sg_DataTemplate[2].data_property.type = TYPE_TEMPLATE_INT;
strncpy(sg_ProductData.m_name, sg_devInfo.device_name, MAX_STR_NAME_LEN);
sg_ProductData.m_name[strlen(sg_devInfo.device_name)] = '\0';
sg_DataTemplate[3].data_property.key = "name";
sg_DataTemplate[3].data_property.data = sg_ProductData.m_name;
sg_DataTemplate[3].data_property.data_buff_len = MAX_STR_NAME_LEN;
sg_DataTemplate[3].data_property.type = TYPE_TEMPLATE_STRING;
};
/*-----------------data config end -------------------*/
/*event_config.c can be generated by tools/codegen.py -c xx/product.json*/
/*-----------------event config start -------------------*/
#ifdef EVENT_POST_ENABLED
#define EVENT_COUNTS (3)
#define MAX_EVENT_STR_MESSAGE_LEN (64)
#define MAX_EVENT_STR_NAME_LEN (64)
static TYPE_DEF_TEMPLATE_BOOL sg_status;
static TYPE_DEF_TEMPLATE_STRING sg_message[MAX_EVENT_STR_MESSAGE_LEN + 1];
static DeviceProperty g_propertyEvent_status_report[] = {
{.key = "status", .data = &sg_status, .type = TYPE_TEMPLATE_BOOL},
{.key = "message", .data = sg_message, .type = TYPE_TEMPLATE_STRING},
};
static TYPE_DEF_TEMPLATE_FLOAT sg_voltage;
static DeviceProperty g_propertyEvent_low_voltage[] = {
{.key = "voltage", .data = &sg_voltage, .type = TYPE_TEMPLATE_FLOAT},
};
static TYPE_DEF_TEMPLATE_STRING sg_name[MAX_EVENT_STR_NAME_LEN + 1];
static TYPE_DEF_TEMPLATE_INT sg_error_code;
static DeviceProperty g_propertyEvent_hardware_fault[] = {
{.key = "name", .data = sg_name, .type = TYPE_TEMPLATE_STRING},
{.key = "error_code", .data = &sg_error_code, .type = TYPE_TEMPLATE_INT},
};
static sEvent g_events[] = {
{
.event_name = "status_report",
.type = "info",
.timestamp = 0,
.eventDataNum = sizeof(g_propertyEvent_status_report) / sizeof(g_propertyEvent_status_report[0]),
.pEventData = g_propertyEvent_status_report,
},
{
.event_name = "low_voltage",
.type = "alert",
.timestamp = 0,
.eventDataNum = sizeof(g_propertyEvent_low_voltage) / sizeof(g_propertyEvent_low_voltage[0]),
.pEventData = g_propertyEvent_low_voltage,
},
{
.event_name = "hardware_fault",
.type = "fault",
.timestamp = 0,
.eventDataNum = sizeof(g_propertyEvent_hardware_fault) / sizeof(g_propertyEvent_hardware_fault[0]),
.pEventData = g_propertyEvent_hardware_fault,
},
};
/*-----------------event config end -------------------*/
static void update_events_timestamp(sEvent *pEvents, int count)
{
int i;
for (i = 0; i < count; i++) {
if (NULL == (&pEvents[i])) {
Log_e("null event pointer");
return;
}
#ifdef EVENT_TIMESTAMP_USED
pEvents[i].timestamp = HAL_Timer_current_sec(); // should be UTC and
// accurate
#else
pEvents[i].timestamp = 0;
#endif
}
}
static void event_post_cb(void *pClient, MQTTMessage *msg)
{
Log_d("recv event reply, clear event");
IOT_Event_clearFlag(pClient, FLAG_EVENT0);
}
// event check and post
static void eventPostCheck(void *client)
{
int i;
int rc;
uint32_t eflag;
uint8_t EventCont;
sEvent * pEventList[EVENT_COUNTS];
eflag = IOT_Event_getFlag(client);
if ((EVENT_COUNTS > 0) && (eflag > 0)) {
EventCont = 0;
for (i = 0; i < EVENT_COUNTS; i++) {
if ((eflag & (1 << i)) & ALL_EVENTS_MASK) {
pEventList[EventCont++] = &(g_events[i]);
update_events_timestamp(&g_events[i], 1);
}
}
rc = IOT_Post_Event(client, sg_data_report_buffer, sg_data_report_buffersize, EventCont, pEventList,
event_post_cb);
if (rc < 0) {
Log_e("event post failed: %d", rc);
}
}
}
#endif
/*action_config.c can be generated by tools/codegen.py -c xx/product.json*/
/*-----------------action config start -------------------*/
#ifdef ACTION_ENABLED
#define TOTAL_ACTION_COUNTS (1)
static TYPE_DEF_TEMPLATE_INT sg_blink_in_period = 5;
static DeviceProperty g_actionInput_blink[] = {
{.key = "period", .data = &sg_blink_in_period, .type = TYPE_TEMPLATE_INT}};
static TYPE_DEF_TEMPLATE_BOOL sg_blink_out_result = 0;
static DeviceProperty g_actionOutput_blink[] = {
{.key = "result", .data = &sg_blink_out_result, .type = TYPE_TEMPLATE_BOOL},
};
static DeviceAction g_actions[] = {
{
.pActionId = "blink",
.timestamp = 0,
.input_num = sizeof(g_actionInput_blink) / sizeof(g_actionInput_blink[0]),
.output_num = sizeof(g_actionOutput_blink) / sizeof(g_actionOutput_blink[0]),
.pInput = g_actionInput_blink,
.pOutput = g_actionOutput_blink,
},
};
/*-----------------action config end -------------------*/
static void OnActionCallback(void *pClient, const char *pClientToken, DeviceAction *pAction)
{
int i;
sReplyPara replyPara;
// control light blink
int period = 0;
DeviceProperty *pActionInput = pAction->pInput;
for (i = 0; i < pAction->input_num; i++) {
if (!strcmp(pActionInput[i].key, "period")) {
period = *((int *)pActionInput[i].data);
} else {
Log_e("no such input[%s]!", pActionInput[i].key);
}
}
// do blink
HAL_Printf("%s[lighting blink][****]" ANSI_COLOR_RESET, ANSI_COLOR_RED);
HAL_SleepMs(period * 1000);
HAL_Printf("\r%s[lighting blink][****]" ANSI_COLOR_RESET, ANSI_COLOR_GREEN);
HAL_SleepMs(period * 1000);
HAL_Printf("\r%s[lighting blink][****]\n" ANSI_COLOR_RESET, ANSI_COLOR_RED);
// construct output
memset((char *)&replyPara, 0, sizeof(sReplyPara));
replyPara.code = eDEAL_SUCCESS;
replyPara.timeout_ms = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT;
strcpy(replyPara.status_msg,
"action execute success!"); // add the message about the action resault
DeviceProperty *pActionOutnput = pAction->pOutput;
*(int *)(pActionOutnput[0].data) = 0; // set result
IOT_ACTION_REPLY(pClient, pClientToken, sg_data_report_buffer, sg_data_report_buffersize, pAction, &replyPara);
}
static int _register_data_template_action(void *pTemplate_client)
{
int i, rc;
for (i = 0; i < TOTAL_ACTION_COUNTS; i++) {
rc = IOT_Template_Register_Action(pTemplate_client, &g_actions[i], OnActionCallback);
if (rc != QCLOUD_RET_SUCCESS) {
rc = IOT_Template_Destroy(pTemplate_client);
Log_e("register device data template action failed, err: %d", rc);
return rc;
} else {
Log_i("data template action=%s registered.", g_actions[i].pActionId);
}
}
return QCLOUD_RET_SUCCESS;
}
#endif
static void event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg)
{
uintptr_t packet_id = (uintptr_t)msg->msg;
switch (msg->event_type) {
case MQTT_EVENT_UNDEF:
Log_i("undefined event occur.");
break;
case MQTT_EVENT_DISCONNECT:
Log_i("MQTT disconnect.");
break;
case MQTT_EVENT_RECONNECT:
Log_i("MQTT reconnect.");
break;
case MQTT_EVENT_SUBCRIBE_SUCCESS:
sg_subscribe_event_result = msg->event_type;
Log_i("subscribe success, packet-id=%u", (unsigned int)packet_id);
break;
case MQTT_EVENT_SUBCRIBE_TIMEOUT:
sg_subscribe_event_result = msg->event_type;
Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id);
break;
case MQTT_EVENT_SUBCRIBE_NACK:
sg_subscribe_event_result = msg->event_type;
Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id);
break;
case MQTT_EVENT_PUBLISH_SUCCESS:
Log_i("publish success, packet-id=%u", (unsigned int)packet_id);
break;
case MQTT_EVENT_PUBLISH_TIMEOUT:
Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id);
break;
case MQTT_EVENT_PUBLISH_NACK:
Log_i("publish nack, packet-id=%u", (unsigned int)packet_id);
break;
default:
Log_i("Should NOT arrive here.");
break;
}
}
/*add user init code, like sensor init*/
static void _usr_init(void)
{
Log_d("add your init code here");
}
/*control msg from server will trigger this callback*/
static void OnControlMsgCallback(void *pClient, const char *pJsonValueBuffer, uint32_t valueLength,
DeviceProperty *pProperty)
{
int i = 0;
for (i = 0; i < TOTAL_PROPERTY_COUNT; i++) {
/* handle self defined string/json here. Other properties are dealed in
* _handle_delta()*/
if (strcmp(sg_DataTemplate[i].data_property.key, pProperty->key) == 0) {
sg_DataTemplate[i].state = eCHANGED;
Log_i("Property=%s changed", pProperty->key);
sg_control_msg_arrived = true;
return;
}
}
Log_e("Property=%s changed no match", pProperty->key);
}
static void OnReportReplyCallback(void *pClient, Method method, ReplyAck replyAck, const char *pJsonDocument,
void *pUserdata)
{
Log_i("recv report_reply(ack=%d): %s", replyAck, pJsonDocument);
}
// register data template properties
static int _register_data_template_property(void *pTemplate_client)
{
int i, rc;
for (i = 0; i < TOTAL_PROPERTY_COUNT; i++) {
rc = IOT_Template_Register_Property(pTemplate_client, &sg_DataTemplate[i].data_property, OnControlMsgCallback);
if (rc != QCLOUD_RET_SUCCESS) {
rc = IOT_Template_Destroy(pTemplate_client);
Log_e("register device data template property failed, err: %d", rc);
return rc;
} else {
Log_i("data template property=%s registered.", sg_DataTemplate[i].data_property.key);
}
}
return QCLOUD_RET_SUCCESS;
}
/*get property state, changed or not*/
static eDataState get_property_state(void *pProperyData)
{
int i;
for (i = 0; i < TOTAL_PROPERTY_COUNT; i++) {
if (sg_DataTemplate[i].data_property.data == pProperyData) {
return sg_DataTemplate[i].state;
}
}
Log_e("no property matched");
return eNOCHANGE;
}
/*set property state, changed or no change*/
static void set_propery_state(void *pProperyData, eDataState state)
{
int i;
for (i = 0; i < TOTAL_PROPERTY_COUNT; i++) {
if (sg_DataTemplate[i].data_property.data == pProperyData) {
sg_DataTemplate[i].state = state;
break;
}
}
}
/* demo for light logic deal */
static void deal_down_stream_user_logic(void *client, ProductDataDefine *light)
{
int i;
const char *ansi_color = NULL;
const char *ansi_color_name = NULL;
char brightness_bar[] = "||||||||||||||||||||";
int brightness_bar_len = strlen(brightness_bar);
/* light color */
switch (light->m_color) {
case eCOLOR_RED:
ansi_color = ANSI_COLOR_RED;
ansi_color_name = " RED ";
break;
case eCOLOR_GREEN:
ansi_color = ANSI_COLOR_GREEN;
ansi_color_name = "GREEN";
break;
case eCOLOR_BLUE:
ansi_color = ANSI_COLOR_BLUE;
ansi_color_name = " BLUE";
break;
default:
ansi_color = ANSI_COLOR_YELLOW;
ansi_color_name = "UNKNOWN";
break;
}
/* light brightness bar */
brightness_bar_len =
(light->m_brightness >= 100) ? brightness_bar_len : (int)((light->m_brightness * brightness_bar_len) / 100);
for (i = brightness_bar_len; i < strlen(brightness_bar); i++) {
brightness_bar[i] = '-';
}
if (light->m_light_switch) {
/* light is on , show with the properties*/
HAL_Printf("%s[ lighting ]|[color:%s]|[brightness:%s]|[%s]\n" ANSI_COLOR_RESET, ansi_color, ansi_color_name,
brightness_bar, light->m_name);
} else {
/* light is off */
HAL_Printf(ANSI_COLOR_YELLOW "[ light is off ]|[color:%s]|[brightness:%s]|[%s]\n" ANSI_COLOR_RESET,
ansi_color_name, brightness_bar, light->m_name);
}
if (eCHANGED == get_property_state(&light->m_light_switch)) {
#ifdef EVENT_POST_ENABLED
if (light->m_light_switch) {
*(TYPE_DEF_TEMPLATE_BOOL *)g_events[0].pEventData[0].data = 1;
memset((TYPE_DEF_TEMPLATE_STRING *)g_events[0].pEventData[1].data, 0, MAX_EVENT_STR_MESSAGE_LEN);
strcpy((TYPE_DEF_TEMPLATE_STRING *)g_events[0].pEventData[1].data, "light on");
} else {
*(TYPE_DEF_TEMPLATE_BOOL *)g_events[0].pEventData[0].data = 0;
memset((TYPE_DEF_TEMPLATE_STRING *)g_events[0].pEventData[1].data, 0, MAX_EVENT_STR_MESSAGE_LEN);
strcpy((TYPE_DEF_TEMPLATE_STRING *)g_events[0].pEventData[1].data, "light off");
}
// switch state changed set EVENT0 flag, the events will be posted by
// eventPostCheck
IOT_Event_setFlag(client, FLAG_EVENT0);
#else
Log_d("light switch state changed");
#endif
}
}
/*example for cycle report, you can delete this for your needs*/
static void cycle_report(Timer *reportTimer)
{
int i;
if (expired(reportTimer)) {
for (i = 0; i < TOTAL_PROPERTY_COUNT; i++) {
set_propery_state(sg_DataTemplate[i].data_property.data, eCHANGED);
countdown_ms(reportTimer, 5000);
}
}
}
/*get local property data, like sensor data*/
static void _refresh_local_property(void)
{
// add your local property refresh logic, cycle report for example
cycle_report(&sg_reportTimer);
}
static int find_wait_report_property(DeviceProperty *pReportDataList[])
{
int i, j;
for (i = 0, j = 0; i < TOTAL_PROPERTY_COUNT; i++) {
if (eCHANGED == sg_DataTemplate[i].state) {
pReportDataList[j++] = &(sg_DataTemplate[i].data_property);
sg_DataTemplate[i].state = eNOCHANGE;
}
}
return j;
}
/* demo for up-stream code */
static int deal_up_stream_user_logic(DeviceProperty *pReportDataList[], int *pCount)
{
// refresh local property
_refresh_local_property();
/*find propery need report*/
*pCount = find_wait_report_property(pReportDataList);
return (*pCount > 0) ? QCLOUD_RET_SUCCESS : QCLOUD_ERR_FAILURE;
}
/*You should get the real info for your device, here just for example*/
static int _get_sys_info(void *handle, char *pJsonDoc, size_t sizeOfBuffer)
{
/*platform info has at least one of module_hardinfo/module_softinfo/fw_ver
* property*/
DeviceProperty plat_info[] = {
{.key = "module_hardinfo", .type = TYPE_TEMPLATE_STRING, .data = "ESP8266"},
{.key = "module_softinfo", .type = TYPE_TEMPLATE_STRING, .data = "V1.0"},
{.key = "fw_ver", .type = TYPE_TEMPLATE_STRING, .data = QCLOUD_IOT_DEVICE_SDK_VERSION},
{.key = "imei", .type = TYPE_TEMPLATE_STRING, .data = "11-22-33-44"},
{.key = "lat", .type = TYPE_TEMPLATE_STRING, .data = "22.546015"},
{.key = "lon", .type = TYPE_TEMPLATE_STRING, .data = "113.941125"},
{NULL, NULL, 0} // end
};
/*self define info*/
DeviceProperty self_info[] = {
{.key = "append_info", .type = TYPE_TEMPLATE_STRING, .data = "your self define info"}, {NULL, NULL, 0} // end
};
return IOT_Template_JSON_ConstructSysInfo(handle, pJsonDoc, sizeOfBuffer, plat_info, self_info);
}
void *sub_dev1_thread(void *user_arg, char *product_id, char *device_name)
{
DeviceProperty *pReportDataList[TOTAL_PROPERTY_COUNT];
sReplyPara replyPara;
int ReportCont;
int rc;
void * pGateWayClient = user_arg;
Log_d("sub_dev1_thread ...");
// init connection
TemplateInitParams init_params = DEFAULT_TEMPLATE_INIT_PARAMS;
init_params.product_id = product_id;
init_params.device_name = device_name;
init_params.event_handle.h_fp = event_handler;
void *client = IOT_Template_Construct(&init_params, IOT_Gateway_Get_Mqtt_Client(pGateWayClient));
if (client != NULL) {
Log_i("Cloud Device Construct Success");
} else {
Log_e("Cloud Device Construct Failed");
return NULL;
}
#ifdef MULTITHREAD_ENABLED
/*only gateway yield thread read mqtt packet*/
int code;
bool state = IOT_Gateway_Get_Yield_Status(pGateWayClient, &code);
IOT_Template_Set_Yield_Status(client, state, code);
#endif
// usr init
_usr_init();
// init data template
_init_data_template();
// register data template propertys here
rc = _register_data_template_property(client);
if (rc == QCLOUD_RET_SUCCESS) {
Log_i("Register data template propertys Success");
} else {
Log_e("Register data template propertys Failed: %d", rc);
return NULL;
}
// register data template actions here
#ifdef ACTION_ENABLED
rc = _register_data_template_action(client);
if (rc == QCLOUD_RET_SUCCESS) {
Log_i("Register data template actions Success");
} else {
Log_e("Register data template actions Failed: %d", rc);
return NULL;
}
#endif
HAL_SleepMs(1000); // wait subcrible ack
// report device info, then you can manager your product by these info, like
// position
rc = _get_sys_info(client, sg_data_report_buffer, sg_data_report_buffersize);
if (QCLOUD_RET_SUCCESS == rc) {
rc = IOT_Template_Report_SysInfo_Sync(client, sg_data_report_buffer, sg_data_report_buffersize,
QCLOUD_IOT_MQTT_COMMAND_TIMEOUT);
if (rc != QCLOUD_RET_SUCCESS) {
Log_e("Report system info fail, err: %d", rc);
return NULL;
}
} else {
Log_e("Get system info fail, err: %d", rc);
}
// get the property changed during offline
rc = IOT_Template_GetStatus_sync(client, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT);
if (rc != QCLOUD_RET_SUCCESS) {
Log_e("Get data status fail, err: %d", rc);
return NULL;
} else {
Log_d("Get data status success");
}
// init a timer for cycle report, you could delete it or not for your needs
InitTimer(&sg_reportTimer);
while (IOT_Template_IsConnected(client) || QCLOUD_RET_SUCCESS == rc) {
rc = IOT_Template_Yield(client, 200);
if (QCLOUD_RET_SUCCESS != rc) {
Log_d("Template Yield without mqtt err, rc:%d", rc);
}
/* handle control msg from server */
if (sg_control_msg_arrived) {
deal_down_stream_user_logic(client, &sg_ProductData);
/* control msg should reply, otherwise server treat device didn't receive
* and retain the msg which would be get by get status*/
memset((char *)&replyPara, 0, sizeof(sReplyPara));
replyPara.code = eDEAL_SUCCESS;
replyPara.timeout_ms = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT;
replyPara.status_msg[0] = '\0'; // add extra info to replyPara.status_msg when error occured
rc = IOT_Template_ControlReply(client, sg_data_report_buffer, sg_data_report_buffersize, &replyPara);
if (rc == QCLOUD_RET_SUCCESS) {
Log_d("Contol msg reply success");
sg_control_msg_arrived = false;
} else {
Log_e("Contol msg reply failed, err: %d", rc);
}
}
/*report msg to server*/
/*report the lastest properties's status*/
if (QCLOUD_RET_SUCCESS == deal_up_stream_user_logic(pReportDataList, &ReportCont)) {
rc = IOT_Template_JSON_ConstructReportArray(client, sg_data_report_buffer, sg_data_report_buffersize,
ReportCont, pReportDataList);
if (rc == QCLOUD_RET_SUCCESS) {
rc = IOT_Template_Report(client, sg_data_report_buffer, sg_data_report_buffersize,
OnReportReplyCallback, NULL, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT);
if (rc == QCLOUD_RET_SUCCESS) {
Log_i("data template reporte success");
} else {
Log_e("data template reporte failed, err: %d", rc);
}
} else {
Log_e("construct reporte data failed, err: %d", rc);
}
}
#ifdef EVENT_POST_ENABLED
eventPostCheck(client);
#endif
HAL_SleepMs(1000);
}
#ifdef MULTITHREAD_ENABLED
rc = IOT_Template_Destroy_Except_MQTT(client);
#endif
return NULL;
}