update qcloud sdk

1. iot-hub sdk update to 3.2.0
2. iot-explorer update to 3.1.1
This commit is contained in:
daishengdong
2020-05-07 11:11:04 +08:00
parent c8e39739d3
commit 3e631cd96a
594 changed files with 47287 additions and 44165 deletions

View File

@@ -0,0 +1,430 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "qcloud_iot_export.h"
#include "qcloud_iot_import.h"
#include "utils_getopt.h"
/*
* This sample test multi MQTT clients in multi-thread runtime.
* 3 MQTT clients run in each own thread
* psk/cert_device_info1/2/3.json for each device info are required
* data topic forward configuration is required
*/
#define MAX_MQTT_THREAD_COUNT 3
// record the status of all the threadss
static unsigned int sg_thread_status[MAX_MQTT_THREAD_COUNT];
#ifdef WIN32
#define OS_PATH ".\\"
#else
#define OS_PATH "./"
#endif
#ifdef AUTH_MODE_CERT
char *device_info_file[MAX_MQTT_THREAD_COUNT] = {OS_PATH "cert_device_info1.json", OS_PATH "cert_device_info2.json",
OS_PATH "cert_device_info3.json"};
#else
char *device_info_file[MAX_MQTT_THREAD_COUNT] = {OS_PATH "psk_device_info1.json", OS_PATH "psk_device_info2.json",
OS_PATH "psk_device_info3.json"};
#endif
// sample data structures
typedef struct AppThreadData {
int thread_id;
char * device_info_file;
bool sub_ready;
uint32_t msg_recv_cnt;
} AppThreadData;
static int sg_loop_cnt = 10;
// MQTT event callback
static void _mqtt_event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg)
{
MQTTMessage * mqtt_messge = (MQTTMessage *)msg->msg;
uintptr_t packet_id = (uintptr_t)msg->msg;
AppThreadData *app_data = (AppThreadData *)handle_context;
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_PUBLISH_RECVEIVED:
Log_i("topic message arrived but without any related handle: topic=%.*s, topic_msg=%.*s",
mqtt_messge->topic_len, mqtt_messge->ptopic, mqtt_messge->payload_len, mqtt_messge->payload);
break;
case MQTT_EVENT_SUBCRIBE_SUCCESS:
Log_d("mqtt topic subscribe success");
app_data->sub_ready = true;
break;
case MQTT_EVENT_SUBCRIBE_TIMEOUT:
Log_i("mqtt topic subscribe timeout");
app_data->sub_ready = false;
break;
case MQTT_EVENT_SUBCRIBE_NACK:
Log_i("mqtt topic subscribe NACK");
app_data->sub_ready = false;
break;
case MQTT_EVENT_UNSUBCRIBE_SUCCESS:
Log_i("unsubscribe success, packet-id=%u", (unsigned int)packet_id);
app_data->sub_ready = false;
break;
case MQTT_EVENT_UNSUBCRIBE_TIMEOUT:
Log_i("unsubscribe timeout, packet-id=%u", (unsigned int)packet_id);
break;
case MQTT_EVENT_UNSUBCRIBE_NACK:
Log_i("unsubscribe 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;
}
}
// Setup MQTT construct parameters
static int _setup_connect_init_params(MQTTInitParams *initParams, DeviceInfo *device_info, AppThreadData *app_data)
{
initParams->product_id = device_info->product_id;
initParams->device_name = device_info->device_name;
#ifdef AUTH_MODE_CERT
char certs_dir[16] = "certs";
char current_path[128];
char *cwd = getcwd(current_path, sizeof(current_path));
if (cwd == NULL) {
Log_e("getcwd return NULL");
return QCLOUD_ERR_FAILURE;
}
#ifdef WIN32
HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir,
device_info->dev_cert_file_name);
HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir,
device_info->dev_key_file_name);
#else
HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir,
device_info->dev_cert_file_name);
HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir,
device_info->dev_key_file_name);
#endif
#else
initParams->device_secret = device_info->device_secret;
#endif
initParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT;
initParams->keep_alive_interval_ms = QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL;
initParams->auto_connect_enable = 1;
initParams->event_handle.h_fp = _mqtt_event_handler;
initParams->event_handle.context = (void *)app_data;
return QCLOUD_RET_SUCCESS;
}
#define MAX_SIZE_OF_TOPIC_CONTENT 100
// publish MQTT msg
static int _publish_test_msg(void *client, char *topic_keyword, QoS qos, int count, int thread_id)
{
char topic_name[128] = {0};
DeviceInfo *dev_info = IOT_MQTT_GetDeviceInfo(client);
int size = HAL_Snprintf(topic_name, sizeof(topic_name), "%s/%s/%s", dev_info->product_id, dev_info->device_name,
topic_keyword);
if (size < 0 || size > sizeof(topic_name) - 1) {
Log_e("topic content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_name));
return QCLOUD_ERR_FAILURE;
}
PublishParams pub_params = DEFAULT_PUB_PARAMS;
pub_params.qos = qos;
char topic_content[MAX_SIZE_OF_TOPIC_CONTENT + 1] = {0};
size = HAL_Snprintf(topic_content, sizeof(topic_content), "{\"text\": \"thread-%u\", \"count\": \"%d\"}", thread_id,
count);
if (size < 0 || size > sizeof(topic_content) - 1) {
Log_e("payload content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_content));
return -3;
}
pub_params.payload = topic_content;
pub_params.payload_len = strlen(topic_content);
return IOT_MQTT_Publish(client, topic_name, &pub_params);
}
// callback when MQTT msg arrives
static void _on_message_callback(void *pClient, MQTTMessage *message, void *user_data)
{
if (message == NULL) {
return;
}
AppThreadData *app_data = (AppThreadData *)user_data;
app_data->msg_recv_cnt += 1;
Log_i("Thread-%d recv msg topic:%.*s, payload:%.*s", app_data->thread_id, (int)message->topic_len, message->ptopic,
(int)message->payload_len, (char *)message->payload);
}
// subscrib MQTT topic
static int _subscribe_topic_wait_result(void *client, char *topic_keyword, QoS qos, AppThreadData *app_data)
{
static char topic_name[128] = {0};
DeviceInfo *dev_info = IOT_MQTT_GetDeviceInfo(client);
int size = HAL_Snprintf(topic_name, sizeof(topic_name), "%s/%s/%s", dev_info->product_id, dev_info->device_name,
topic_keyword);
if (size < 0 || size > sizeof(topic_name) - 1) {
Log_e("topic content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_name));
return QCLOUD_ERR_FAILURE;
}
SubscribeParams sub_params = DEFAULT_SUB_PARAMS;
sub_params.qos = qos;
sub_params.on_message_handler = _on_message_callback;
sub_params.user_data = (void *)app_data;
int rc = IOT_MQTT_Subscribe(client, topic_name, &sub_params);
if (rc < 0) {
Log_e("MQTT subscribe failed: %d", rc);
return rc;
}
int wait_cnt = 10;
while (!app_data->sub_ready && (wait_cnt > 0)) {
// wait for subscription result
rc = IOT_MQTT_Yield(client, 1000);
if (rc) {
Log_e("MQTT error: %d", rc);
return rc;
}
wait_cnt--;
}
if (wait_cnt > 0) {
return QCLOUD_RET_SUCCESS;
} else {
Log_e("wait for subscribe result timeout!");
return QCLOUD_ERR_FAILURE;
}
}
static uint32_t _get_random_delay(void)
{
srand((unsigned)HAL_GetTimeMs());
/* range: 1000 - 5000 ms, in 10ms unit */
return (rand() % 400 + 100) * 10;
}
static void _mqtt_client_thread_runner(void *ptr)
{
int pub_cnt = 0;
void * client = NULL;
AppThreadData *app_data = (AppThreadData *)ptr;
int thread_id = app_data->thread_id;
DeviceInfo dev_info = {0};
if (HAL_GetDevInfoFromFile(app_data->device_info_file, (void *)&dev_info)) {
Log_e("invalid dev info file: %s", app_data->device_info_file);
goto thread_exit;
}
Log_i("Thread running. ID: %d; device file: %s", thread_id, app_data->device_info_file);
// init connection
MQTTInitParams init_params = DEFAULT_MQTTINIT_PARAMS;
int rc = _setup_connect_init_params(&init_params, &dev_info, app_data);
if (rc != QCLOUD_RET_SUCCESS) {
Log_e("init params error: %d", rc);
goto thread_exit;
}
// create MQTT client and connect with server
client = IOT_MQTT_Construct(&init_params);
if (client != NULL) {
Log_i("Cloud Device Construct Success");
} else {
Log_e("MQTT Construct failed!");
goto thread_exit;
}
#ifdef SYSTEM_COMM
long time = 0;
// get system timestamp from server
rc = IOT_Get_SysTime(client, &time);
if (QCLOUD_RET_SUCCESS == rc) {
Log_i("system time is %ld", time);
} else {
Log_e("get system time failed!");
}
#endif
// subscribe topic first
rc = _subscribe_topic_wait_result(client, "data", QOS1, app_data);
if (rc < 0) {
Log_e("Client Subscribe Topic Failed: %d", rc);
goto thread_exit;
}
int test_count = 0;
do {
rc = _publish_test_msg(client, "data", QOS1, test_count, thread_id);
if (rc < 0) {
Log_e("client publish topic failed :%d.", rc);
} else {
pub_cnt++;
}
rc = IOT_MQTT_Yield(client, 1000);
if (rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT) {
HAL_SleepMs(1000);
continue;
} else if (rc != QCLOUD_RET_SUCCESS && rc != QCLOUD_RET_MQTT_RECONNECTED) {
Log_e("exit with error: %d", rc);
break;
}
test_count++;
if (test_count < sg_loop_cnt)
HAL_SleepMs(_get_random_delay());
#ifdef SYSTEM_COMM
long time = 0;
// get system timestamp from server
rc = IOT_Get_SysTime(client, &time);
if (QCLOUD_RET_SUCCESS == rc) {
Log_i("system time is %ld", time);
} else {
Log_e("get system time failed!");
}
#endif
} while (test_count < sg_loop_cnt);
thread_exit:
if (client != NULL)
IOT_MQTT_Destroy(&client);
Log_i(">>>>>>>>>>Thread-%d totally pub %d msg and recv %d msg", thread_id, pub_cnt, app_data->msg_recv_cnt);
sg_thread_status[thread_id] = 1;
}
static int parse_arguments(int argc, char **argv)
{
int c;
while ((c = utils_getopt(argc, argv, "l:")) != EOF) switch (c) {
case 'l':
sg_loop_cnt = atoi(utils_optarg);
break;
default:
HAL_Printf(
"usage: %s [options]\n"
" [-l n] test loop count\n",
argv[0]);
return -1;
}
return 0;
}
int main(int argc, char **argv)
{
// init log level
IOT_Log_Set_Level(eLOG_DEBUG);
parse_arguments(argc, argv);
AppThreadData app_data[MAX_MQTT_THREAD_COUNT];
int i;
// init thread app data
for (i = 0; i < MAX_MQTT_THREAD_COUNT; i++) {
sg_thread_status[i] = 0; // init thread status flag
app_data[i].device_info_file = device_info_file[i];
app_data[i].thread_id = i;
app_data[i].sub_ready = false;
app_data[i].msg_recv_cnt = 0;
}
int created_thread_cnt = 0;
/* create multi threads for multi mqtt client test */
for (i = 0; i < MAX_MQTT_THREAD_COUNT; i++) {
sg_thread_status[i] = 0; // init thread status flag
ThreadParams thread_params = {0};
thread_params.thread_func = _mqtt_client_thread_runner;
thread_params.user_arg = &app_data[i];
int rc = HAL_ThreadCreate(&thread_params);
if (rc) {
Log_e("create mqtt thread fail: %d", rc);
} else {
created_thread_cnt++;
}
HAL_SleepMs(300);
}
Log_i("created %d mqtt threads", created_thread_cnt);
/* wait for all threads to finish their jobs */
int finished_created_thread_cnt;
do {
finished_created_thread_cnt = 0;
for (i = 0; i < MAX_MQTT_THREAD_COUNT; i++) {
finished_created_thread_cnt += sg_thread_status[i];
}
Log_i(">>>>>>>>Finished thread count : %d", finished_created_thread_cnt);
HAL_SleepMs(1000);
} while (finished_created_thread_cnt < created_thread_cnt);
return 0;
}

View File

@@ -0,0 +1,304 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "qcloud_iot_export.h"
#include "qcloud_iot_import.h"
#include "utils_getopt.h"
/*
* This sample test multi shadow clients in multi-thread runtime.
* 3 shadow clients run in each own thread
* psk/cert_device_info1/2/3.json for each device info are required
*/
#define MAX_MQTT_THREAD_COUNT 3
// record the status of all the threadss
static unsigned int sg_thread_status[MAX_MQTT_THREAD_COUNT];
#ifdef WIN32
#ifdef AUTH_MODE_CERT
char *device_info_file[MAX_MQTT_THREAD_COUNT] = {".\\cert_device_info1.json", ".\\cert_device_info2.json",
".\\cert_device_info3.json"};
#else
char *device_info_file[MAX_MQTT_THREAD_COUNT] = {".\\psk_device_info1.json", ".\\psk_device_info2.json",
".\\psk_device_info3.json"};
#endif
#else
#ifdef AUTH_MODE_CERT
char *device_info_file[MAX_MQTT_THREAD_COUNT] = {"./cert_device_info1.json", "./cert_device_info2.json",
"./cert_device_info3.json"};
#else
char *device_info_file[MAX_MQTT_THREAD_COUNT] = {"./psk_device_info1.json", "./psk_device_info2.json",
"./psk_device_info3.json"};
#endif
#endif
// sample data structures
typedef struct SampleThreadData {
int thread_id;
char *device_info_file;
char *property_key;
} SampleThreadData;
static int sg_loop_cnt = 10;
void OnDeltaCallback(void *pClient, const char *pJsonValueBuffer, uint32_t valueLength, DeviceProperty *pProperty)
{
Log_i("Thread recv delta str: %s", pJsonValueBuffer);
pProperty->delta_arrived = true;
}
void OnShadowUpdateCallback(void *pClient, Method method, RequestAck requestAck, const char *pJsonDocument,
void *pUserdata)
{
Log_i("Thread recv shadow update response ack: %d", requestAck);
}
static int _report_desire_null(void *handle, char *jsonBuffer, size_t sizeOfBuffer)
{
/* device data updated, desire should be set null */
int rc = IOT_Shadow_JSON_ConstructDesireAllNull(handle, jsonBuffer, sizeOfBuffer);
if (rc == QCLOUD_RET_SUCCESS) {
rc = IOT_Shadow_Update(handle, jsonBuffer, sizeOfBuffer, OnShadowUpdateCallback, "desire_null",
QCLOUD_IOT_MQTT_COMMAND_TIMEOUT);
if (rc == QCLOUD_RET_SUCCESS) {
Log_d("shadow update(desired) success");
} else {
Log_e("shadow update(desired) failed, err: %d", rc);
}
} else {
Log_e("construct desire failed, err: %d", rc);
}
return rc;
}
static int _setup_connect_init_params(ShadowInitParams *initParams, DeviceInfo *device_info)
{
initParams->product_id = device_info->product_id;
initParams->device_name = device_info->device_name;
#ifdef AUTH_MODE_CERT
char certs_dir[16] = "certs";
char current_path[128];
char *cwd = getcwd(current_path, sizeof(current_path));
if (cwd == NULL) {
Log_e("getcwd return NULL");
return QCLOUD_ERR_FAILURE;
}
#ifdef WIN32
HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir,
device_info->dev_cert_file_name);
HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir,
device_info->dev_key_file_name);
#else
HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir,
device_info->dev_cert_file_name);
HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir,
device_info->dev_key_file_name);
#endif
#else
initParams->device_secret = device_info->device_secret;
#endif
initParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT;
initParams->keep_alive_interval_ms = QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL;
initParams->auto_connect_enable = 1;
return QCLOUD_RET_SUCCESS;
}
static uint32_t _get_random_delay(void)
{
srand((unsigned)HAL_GetTimeMs());
/* range: 1000 - 5000 ms, in 10ms unit */
return (rand() % 400 + 100) * 10;
}
static void _shadow_client_thread_runner(void *ptr)
{
int rc = QCLOUD_ERR_FAILURE;
void *shadow_client = NULL;
SampleThreadData *thread_data = (SampleThreadData *)ptr;
int thread_id = thread_data->thread_id;
DeviceInfo dev_info = {0};
if (HAL_GetDevInfoFromFile(thread_data->device_info_file, (void *)&dev_info)) {
Log_e("invalid dev info file: %s", thread_data->device_info_file);
goto thread_exit;
}
Log_i("Thread running. ID: %d; device: %s", thread_id, thread_data->device_info_file);
char shadow_json_buffer[200];
size_t shadow_json_buf_size = sizeof(shadow_json_buffer) / sizeof(shadow_json_buffer[0]);
DeviceProperty shadow_property;
int current_update_count = 0;
// init connection
ShadowInitParams init_params = DEFAULT_SHAWDOW_INIT_PARAMS;
rc = _setup_connect_init_params(&init_params, &dev_info);
if (rc != QCLOUD_RET_SUCCESS) {
Log_e("init params err,rc=%d", rc);
goto thread_exit;
}
shadow_client = IOT_Shadow_Construct(&init_params);
if (shadow_client == NULL) {
Log_e("shadow client constructed failed.");
goto thread_exit;
}
// register delta property
shadow_property.key = thread_data->property_key;
shadow_property.data = &current_update_count;
shadow_property.type = JINT32;
rc = IOT_Shadow_Register_Property(shadow_client, &shadow_property, OnDeltaCallback);
if (rc != QCLOUD_RET_SUCCESS) {
rc = IOT_Shadow_Destroy(shadow_client);
Log_e("register device shadow property failed, err: %d", rc);
goto thread_exit;
}
// do get and sync operation before update
rc = IOT_Shadow_Get_Sync(shadow_client, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT);
if (rc != QCLOUD_RET_SUCCESS) {
Log_e("get device shadow failed, err: %d", rc);
goto thread_exit;
}
int loop_cnt = 0;
while (IOT_Shadow_IsConnected(shadow_client) || QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT == rc ||
QCLOUD_RET_MQTT_RECONNECTED == rc || QCLOUD_RET_SUCCESS == rc) {
rc = IOT_Shadow_Yield(shadow_client, 500);
if (QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT == rc) {
HAL_SleepMs(1000);
continue;
} else if (rc != QCLOUD_RET_SUCCESS && rc != QCLOUD_RET_MQTT_RECONNECTED) {
Log_e("exit with error: %d", rc);
break;
}
if (shadow_property.delta_arrived) {
_report_desire_null(shadow_client, shadow_json_buffer, shadow_json_buf_size);
shadow_property.delta_arrived = false;
}
IOT_Shadow_JSON_ConstructReport(shadow_client, shadow_json_buffer, shadow_json_buf_size, 1, &shadow_property);
rc = IOT_Shadow_Update(shadow_client, shadow_json_buffer, shadow_json_buf_size, OnShadowUpdateCallback, NULL,
QCLOUD_IOT_MQTT_COMMAND_TIMEOUT);
current_update_count++;
if (loop_cnt++ >= sg_loop_cnt)
break;
// sleep for some time
HAL_SleepMs(_get_random_delay());
}
thread_exit:
if (shadow_client != NULL) {
IOT_Shadow_Destroy(shadow_client);
shadow_client = NULL;
}
sg_thread_status[thread_id] = 1;
}
static int parse_arguments(int argc, char **argv)
{
int c;
while ((c = utils_getopt(argc, argv, "l:")) != EOF) switch (c) {
case 'l':
sg_loop_cnt = atoi(utils_optarg);
break;
default:
HAL_Printf(
"usage: %s [options]\n"
" [-l n] test loop count\n",
argv[0]);
return -1;
}
return 0;
}
int main(int argc, char **argv)
{
// init log level
IOT_Log_Set_Level(eLOG_DEBUG);
parse_arguments(argc, argv);
SampleThreadData thread_data[MAX_MQTT_THREAD_COUNT];
char *property_key[MAX_MQTT_THREAD_COUNT] = {"update_count_1", "update_count_2", "update_count_3"};
int i;
for (i = 0; i < MAX_MQTT_THREAD_COUNT; i++) {
sg_thread_status[i] = 0; // init thread status flag
thread_data[i].property_key = property_key[i];
thread_data[i].device_info_file = device_info_file[i];
thread_data[i].thread_id = i;
}
int created_thread_cnt = 0;
/* create multi threads for multi mqtt client test */
for (i = 0; i < MAX_MQTT_THREAD_COUNT; i++) {
sg_thread_status[i] = 0; // init thread status flag
ThreadParams thread_params = {0};
thread_params.thread_func = _shadow_client_thread_runner;
thread_params.user_arg = &thread_data[i];
int rc = HAL_ThreadCreate(&thread_params);
if (rc) {
Log_e("create mqtt thread fail: %d", rc);
} else {
created_thread_cnt++;
}
HAL_SleepMs(300);
}
Log_i("created %d shadow threads", created_thread_cnt);
/* wait for all threads to finish their jobs */
int finished_created_thread_cnt;
do {
finished_created_thread_cnt = 0;
for (i = 0; i < MAX_MQTT_THREAD_COUNT; i++) {
finished_created_thread_cnt += sg_thread_status[i];
}
Log_i(">>>>>>>>Finished thread count : %d", finished_created_thread_cnt);
HAL_SleepMs(1000);
} while (finished_created_thread_cnt < created_thread_cnt);
return 0;
}