doubao_chat/lib/net/dui/dui_iot_manager.c

457 lines
13 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <string.h>
#include "os/os_api.h"
#include "iot.h"
#include "iot_ota.h"
#include "iot_parse.h"
#ifdef DUI_MEMHEAP_DEBUG
#include "mem_leak_test.h"
#endif
#define xerror printf
#define xinfo printf
#define xdebug printf
#define MQTT_MAX_RECONNECT_DLY_MS 16000
#define MQTT_DEFAULT_RECONNECT_DLY_MS 500
#define MQTT_HEART_SEND_WND (100000 / OS_TICKS_PER_SEC)
#define MQTT_VERSION_SEND_WND (36000000 / OS_TICKS_PER_SEC)
static iot_proc_t *g_iot_proc = NULL;
static char *g_iot_mqtt_apikey = NULL;
static void iot_msg_callback(void *param, void *payload, int payloadlen)
{
iot_proc_t *iot_proc = (iot_proc_t *)param;
msg_queue_item_t *item;
if (NULL == payload || 0 == payloadlen) {
xerror("Input parameters are invalid !\n");
return;
}
xinfo("iot recv msg : %s\n", (char *)payload);
item = (msg_queue_item_t *)malloc(sizeof(msg_queue_item_t) + payloadlen + 1);
if (NULL == item) {
return;
}
item->payload = sizeof(msg_queue_item_t) + (char *)item;
item->payload_len = payloadlen;
strcpy(item->payload, payload);
if (os_q_post(&g_iot_proc->recv_queue, item)) {
xerror("xQueueSend mqtt recv msg failed !\n");
free(item);
}
}
static void iot_ota_msg_callback(void *param, void *payload, int payloadlen)
{
iot_proc_t *iot_proc = (iot_proc_t *)param;
msg_queue_item_t *item;
if (NULL == payload || 0 == payloadlen) {
xerror("Input parameters are invalid !\n");
return;
}
xinfo("ota msg : %s\n", (char *)payload);
item = (msg_queue_item_t *)malloc(sizeof(msg_queue_item_t) + payloadlen + 1);
if (NULL == item) {
return;
}
item->payload = sizeof(msg_queue_item_t) + (char *)item;
item->payload_len = payloadlen;
strcpy(item->payload, payload);
if (os_q_post(&g_iot_proc->recv_queue, item)) {
xerror("xQueueSend mqtt recv msg failed !\n");
free(item);
}
}
int iot_send(char *buf)
{
msg_queue_item_t *send_item;
if ((NULL == buf)) {
return -1;
}
if (IOT_STA_CONNECTED != g_iot_proc->status) {
xerror("iot_proc not connected !\n");
return -1;
}
send_item = (msg_queue_item_t *)malloc(sizeof(msg_queue_item_t) + strlen(buf) + 1);
if (NULL == send_item) {
return -1;
}
send_item->payload = sizeof(msg_queue_item_t) + (char *)send_item;
send_item->payload_len = strlen(buf);
strcpy(send_item->payload, buf);
xinfo("iot send msg : %s\n", buf);
if (os_q_post(&g_iot_proc->send_queue, send_item)) {
xerror("xQueueSend failed !\n");
free(send_item);
return -1;
}
return 0;
}
int iot_ota_send(char *buf, int size)
{
return dui_iot_ota_mqtt_send(&g_iot_proc->ota_mqtt, buf, size);
}
static void iot_poll_and_online_loop(void *param)
{
iot_proc_t *iot_proc = (iot_proc_t *)param;
uint32_t heart_send_tick = os_time_get();
while (IOT_STA_CONNECTED == iot_proc->status && 0 == iot_proc->exit_flag) {
if (iot_proc->iot_send_failed > 0) {
break;
}
if ((os_time_get() - heart_send_tick) > MQTT_HEART_SEND_WND) {
heart_send_tick = os_time_get();
iot_ctl_online();
}
if (0 != dui_iot_mqtt_yield(&iot_proc->mqtt)) {
break;
}
//vTaskDelay(2000/portTICK_RATE_MS);
}
iot_proc->iot_send_failed++;
xdebug("=== iot_poll_and_online_loop exit ====\n");
}
static void iot_send_queue_clear(iot_proc_t *iot_proc)
{
msg_queue_item_t *item;
while (1) {
if (os_q_pend(&iot_proc->send_queue, -1, &item)) {
return;
}
free(item);
}
}
static void iot_ctl_proc(iot_proc_t *iot_proc)
{
msg_queue_item_t *item;
while (0 == iot_proc->exit_flag) {
if (iot_proc->iot_send_failed > 0) {
iot_proc->status = IOT_STA_INIT;
break;
}
if (os_q_pend(&iot_proc->send_queue, 100, &item)) {
continue;
}
if (0 != dui_iot_mqtt_send(&iot_proc->mqtt, item->payload, item->payload_len)) {
iot_proc->iot_send_failed++;
}
free(item);
}
}
static void iot_ctl_proc_loop(void *param)
{
int iot_status = 0;
iot_proc_t *iot_proc = (iot_proc_t *)param;
int send_cfg_netword_cnt = 0;
int iot_loop_pid = 0;
u32 dly_cnt = 0;
u32 delay_ms = MQTT_DEFAULT_RECONNECT_DLY_MS;
while (0 == iot_proc->exit_flag) {
iot_status = iot_proc->status;
switch (iot_status) {
case IOT_STA_INIT:
/* xdebug("==>IOT_STA_INIT\n"); */
iot_proc->iot_send_failed = 0;
dui_iot_mqtt_disconnect(&iot_proc->mqtt);
thread_kill(&iot_loop_pid, KILL_WAIT);
iot_loop_pid = 0;
if (0 == dly_cnt) {
iot_proc->status++;
break;
}
--dly_cnt;
os_time_dly(10);
break;
case IOT_STA_CONNECTING:
xdebug("==>IOT_STA_CONNECTING\n");
if (0 != dui_iot_mqtt_connect(&iot_proc->mqtt)) {
iot_proc->status = IOT_STA_INIT;
delay_ms = (delay_ms << 1) > MQTT_MAX_RECONNECT_DLY_MS ? MQTT_MAX_RECONNECT_DLY_MS : delay_ms << 1;
dly_cnt = delay_ms / 100;
break;
}
delay_ms = MQTT_DEFAULT_RECONNECT_DLY_MS;
dly_cnt = delay_ms / 100;
iot_proc->status++;
if (IOT_STA_CONNECTED == iot_proc->status) {
iot_ctl_first_online();
}
break;
case IOT_STA_CONNECTED:
xdebug("==>IOT_STA_CONNECTED\n");
if (iot_proc->conn_cb) {
iot_proc->conn_cb();
}
if (0 == send_cfg_netword_cnt) {
if (0 != iot_ctl_network_config()) {
iot_proc->status = IOT_STA_INIT;
break;
}
++send_cfg_netword_cnt;
}
thread_fork("dui_iot_poll_online", 21, 1024, 0, &iot_loop_pid, iot_poll_and_online_loop, iot_proc);
iot_ctl_proc(iot_proc);
break;
default:
break;
}
}
dui_iot_mqtt_disconnect(&iot_proc->mqtt);
thread_kill(&iot_loop_pid, KILL_WAIT);
}
static void iot_parse_proc_loop(void *param)
{
iot_proc_t *iot_proc = (iot_proc_t *)param;
msg_queue_item_t *recv_item;
while (1) {
if (os_q_pend(&iot_proc->recv_queue, 0, &recv_item)) {
xerror("Get queue item failed !\n");
continue;
}
if (recv_item == (msg_queue_item_t *) - 1) {
break;
}
if (!iot_proc->exit_flag) {
dui_iot_parse_process((const char *)recv_item->payload);
}
free(recv_item);
}
}
static void iot_ota_proc(iot_proc_t *iot_proc)
{
uint32_t heart_send_tick = os_time_get();
uint32_t version_check_tick = 0;
bool version_first_send = false;
while (0 == iot_proc->exit_flag) {
if (iot_proc->ota_send_failed > 0) {
iot_proc->ota_status = IOT_STA_INIT;
break;
}
if ((os_time_get() - heart_send_tick) > MQTT_HEART_SEND_WND) {
heart_send_tick = os_time_get();
if (0 != iot_ctl_ota_online()) {
iot_proc->ota_send_failed++;
continue;
}
}
if (version_first_send != true || (os_time_get() - version_check_tick) > MQTT_VERSION_SEND_WND) {
if (version_first_send != true) {
version_first_send = true;
}
version_check_tick = os_time_get();
if (0 != iot_ctl_ota_query()) {
iot_proc->ota_send_failed++;
continue;
}
}
if (0 != dui_iot_ota_mqtt_yield(&iot_proc->ota_mqtt)) {
iot_proc->ota_send_failed++;
continue;
}
}
}
static void iot_ota_proc_loop(void *param)
{
int iot_ota_status = 0;
iot_proc_t *iot_proc = (iot_proc_t *)param;
u32 dly_cnt = 0;
u32 delay_ms = MQTT_DEFAULT_RECONNECT_DLY_MS;
while (0 == iot_proc->exit_flag) {
iot_ota_status = iot_proc->ota_status;
switch (iot_ota_status) {
case IOT_STA_INIT:
/* xdebug("==>IOT_OTA_INIT\n"); */
iot_proc->ota_send_failed = 0;
dui_iot_ota_mqtt_disconnect(&iot_proc->ota_mqtt);
if (0 == dly_cnt) {
iot_proc->ota_status++;
break;
}
--dly_cnt;
os_time_dly(10);
break;
case IOT_STA_CONNECTING:
xdebug("==>IOT_OTA_CONNECTING\n");
if (0 != dui_iot_ota_mqtt_connect(&iot_proc->ota_mqtt)) {
iot_proc->ota_status = IOT_STA_INIT;
delay_ms = (delay_ms << 1) > MQTT_MAX_RECONNECT_DLY_MS ? MQTT_MAX_RECONNECT_DLY_MS : delay_ms << 1;
dly_cnt = delay_ms / 100;
break;
}
delay_ms = MQTT_DEFAULT_RECONNECT_DLY_MS;
dly_cnt = delay_ms / 100;
iot_proc->ota_status++;
if (IOT_STA_CONNECTED == iot_proc->ota_status) {
iot_ctl_ota_first_online();
}
break;
case IOT_STA_CONNECTED:
xdebug("==>IOT_OTA_CONNECTED\n");
iot_ota_proc(iot_proc);
break;
default:
break;
}
}
dui_iot_ota_mqtt_disconnect(&iot_proc->ota_mqtt);
}
static int iot_proc_init(const iot_config_para_t *cfg, iot_on_connected cb)
{
if (!cfg->device_id
|| !cfg->iot_mqtt_srv
|| !cfg->iot_mqtt_topic
|| !cfg->iot_mqtt_apikey
|| !cfg->ota_mqtt_srv
|| !cfg->ota_mqtt_topic) {
return -1;
}
g_iot_proc = (iot_proc_t *)malloc(sizeof(iot_proc_t));
if (g_iot_proc == NULL) {
return -1;
}
g_iot_mqtt_apikey = (char *)calloc(strlen(cfg->iot_mqtt_apikey) + 1, sizeof(char));
if (!g_iot_mqtt_apikey) {
free(g_iot_proc);
g_iot_proc = NULL;
return -1;
}
strcpy(g_iot_mqtt_apikey, cfg->iot_mqtt_apikey);
memset(g_iot_proc, 0, sizeof(iot_proc_t));
g_iot_proc->conn_cb = cb;
g_iot_proc->status = IOT_STA_INIT;
dui_iot_mqtt_init(&g_iot_proc->mqtt,
cfg->iot_mqtt_srv,
cfg->iot_mqtt_port,
cfg->iot_mqtt_topic,
cfg->device_id);
dui_iot_register_callback(&g_iot_proc->mqtt, iot_msg_callback, g_iot_proc);
g_iot_proc->ota_status = IOT_STA_INIT;
dui_iot_ota_mqtt_init(&g_iot_proc->ota_mqtt,
cfg->ota_mqtt_srv,
cfg->ota_mqtt_port,
cfg->ota_mqtt_topic,
cfg->device_id);
dui_iot_ota_register_callback(&g_iot_proc->ota_mqtt, iot_ota_msg_callback, g_iot_proc);
os_q_create(&g_iot_proc->send_queue, IOT_MSG_QUEUE_LENGTH);
os_q_create(&g_iot_proc->recv_queue, IOT_MSG_QUEUE_LENGTH);
thread_fork("dui_iot_ctl_proc", 20, 1024, 0, &g_iot_proc->iot_ctl_proc_pid, iot_ctl_proc_loop, g_iot_proc);
/* thread_fork("dui_iot_ota_proc", 21, 1024, 0, &g_iot_proc->iot_ota_proc_pid, iot_ota_proc_loop, g_iot_proc); */ //暂不启用OTA,需要时,开启该线程,实现相关逻辑
thread_fork("dui_iot_parse_proc", 22, 768, 0, &g_iot_proc->iot_parse_proc_pid, iot_parse_proc_loop, g_iot_proc);
return 0;
}
int iot_mgr_init(const char *device_id)
{
iot_config_para_t cfg = {0};
cfg.device_id = device_id;
cfg.iot_mqtt_srv = "iot-hub.duiopen.com";
/* cfg.iot_mqtt_topic = "2a9e40accda84cada7791c19ebec81ee"; */
cfg.iot_mqtt_topic = "6752919c7c8745339b385bc9cc16f79a";
cfg.iot_mqtt_apikey = "59676e4d6fa54c5b94b69d5ff1ff426a";
cfg.iot_mqtt_port = 1883;
cfg.ota_mqtt_srv = "mqtt.iot.aispeech.com";
cfg.ota_mqtt_topic = "2a9e40accda84cada7791c19ebec81ee";
cfg.ota_mqtt_port = 1883;
return iot_proc_init(&cfg, NULL);
}
void iot_mgr_deinit(void)
{
if (g_iot_proc) {
g_iot_proc->exit_flag = 1;
g_iot_proc->ota_mqtt.exit_flag = 1;
g_iot_proc->mqtt.exit_flag = 1;
thread_kill(&g_iot_proc->iot_ota_proc_pid, KILL_WAIT);
thread_kill(&g_iot_proc->iot_ctl_proc_pid, KILL_WAIT);
if (os_q_post(&g_iot_proc->recv_queue, (void *) - 1)) {
xerror("iot_mgr_deinit post err full \n");
}
thread_kill(&g_iot_proc->iot_parse_proc_pid, KILL_WAIT);
iot_send_queue_clear(g_iot_proc);
dui_iot_mqtt_deinit(&g_iot_proc->mqtt);
dui_iot_ota_mqtt_deinit(&g_iot_proc->ota_mqtt);
dui_free_media_item();
os_q_del(&g_iot_proc->send_queue, 1);
os_q_del(&g_iot_proc->recv_queue, 1);
free(g_iot_mqtt_apikey);
g_iot_mqtt_apikey = NULL;
free(g_iot_proc);
g_iot_proc = NULL;
}
}
const char *iot_mgr_get_mqtt_apikey(void)
{
return g_iot_mqtt_apikey ? g_iot_mqtt_apikey : "";
}