/******************************************************************************
* Copyright(c) 2019-2024 TP-Link Systems Inc.
*
* Filename: hub_manage.c
* Note: hub_manage模块注册,主要对外接口
*
* Author Jiang Changfu <jiangchangfu@tp-link.com.hk>
* Date: 2023-08-19
* Version: v0.1 Create file
******************************************************************************/
#include <netinet/if_ether.h>
#include <linux/filter.h>
#include <linux/if_packet.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "nsd_common.h"
#include "hub_manage.h"
#include "hub_manage_login.h"
#include "hub_manage_http_client.h"
#include "hub_manage_request_handle.h"
#include "hub_man_debug.h"
#include "libdms.h"
#include "libds.h"
#include "ai_enhance.h"
/**************************************************************************************************/
/* DEFINES */
/**************************************************************************************************/
SYSTEM_SYS g_sys_info = {{0}};
LOCAL S32 g_resync_timer_id = -1;
LOCAL S32 resync_delay_sec = 0;
LOCAL FLIP_TYPE g_last_flip_type = FLIP_OFF;
HUB_PWD_UNIT g_hub_sto_passwd_list[HUB_PASSWD_LIST_NUM] = {{0}};
HUB_PWD_UNIT g_hub_wifi_passwd_list[HUB_PASSWD_LIST_NUM] = {{0}};
hub_keepalive_client_ctx hub_client = {0};
/* 和AI_ENHANCE_TYPE顺序保持一致 */
LOCAL char *g_detect_list[] = {
"detection", "personDetection", "petDetection", "vehicleDetection", NULL, "packageDetection", "tamperDetection",
"babyCryDetection", "intrusionDetection", "linecrossingDetection", "glassDetection", "alarmDetection", "meowDetection", "barkDetection"
};
LOCAL U32 g_detect_support = 0;
extern int g_hub_force_port;
extern char g_hub_force_ip[20];
extern int camera_force_hub_configuration_synchronization_flag;
/**************************************************************************************************/
/* LOCAL_FUNCTIONS */
/**************************************************************************************************/
LOCAL void detect_support_load()
{
JSON_OBJPTR res_array = NULL, recv = NULL;
int i = 0, j = 0, comp_arry_len = 0;
int arraylen = ARRAY_SIZE(g_detect_list);
HUB_MANAGE_AI_ENHANCE_DYN ai_enhence_info = {0};
if(NULL == (res_array = jso_new_array()))
{
return;
}
if(get_app_component_list(res_array, "name", "version"))
{
jso_free_obj(res_array);
return;
}
comp_arry_len = json_object_array_length(res_array);
for(j = 0; j < arraylen; j++)
{
if (NULL == g_detect_list[j])
{
continue;
}
for(i = 0; i < comp_arry_len; i++)
{
recv = json_object_array_get_idx(res_array, i);
if(strstr(jso_obj_get_string_origin(recv, "name"), g_detect_list[j]))
{
g_detect_support |= (1 << j);
HUB_MANAGE_INFO("support %s", g_detect_list[j]);
break;
}
}
}
jso_free_obj(res_array);
if (ds_read(HUB_MANAGE_AI_ENHANCE_DYN_PATH, (U8 *)&ai_enhence_info, sizeof(HUB_MANAGE_AI_ENHANCE_DYN)) == 0)
{
HUB_MANAGE_ERROR("read ai_enhence_info fail.");
return;
}
ai_enhence_info.ai_camera_support = g_detect_support;
if (ds_write(HUB_MANAGE_AI_ENHANCE_DYN_PATH, &ai_enhence_info, sizeof(HUB_MANAGE_AI_ENHANCE_DYN)) == 0)
{
HUB_MANAGE_ERROR("write [ai_enhence_info] error");
return;
}
}
U32 get_detect_support()
{
return g_detect_support;
}
LOCAL S32 hub_config_check()
{
int write_flag = 0, ret = 0;
HUB_MANAGE_STORAGE_INFO hub_info = {0};
HUB_MANAGE_WIFI_BACKUP wifi_backup = {0};
BIND_HUB_REPORT bind_report = {0};
HUB_MANAGE_CFG_ASYNC_RECORD async_record = {0}; /* 初始化异步记录结构体 */
if (ds_read(HUB_MANAGE_STORAGE_INFO_PATH, (U8 *)&hub_info, sizeof(HUB_MANAGE_STORAGE_INFO)) == 0)
{
HUB_MANAGE_ERROR("read hub_info fail.");
return SLP_ESYSTEM;
}
/* 从配置文件读取当前的wifi_backup配置 */
if (0 == ds_read(HUB_MANAGE_WIFI_BACKUP_PATH, &wifi_backup, sizeof(HUB_MANAGE_WIFI_BACKUP)))
{
HUB_MANAGE_ERROR("hub_info Parameter could not be NULL.");
return SLP_ESYSTEM;
}
if (0 == ds_read(HUB_MANAGE_CFG_ASYNC_RECORD_PATH, (U8 *)&async_record, sizeof(HUB_MANAGE_CFG_ASYNC_RECORD)))
{
HUB_MANAGE_ERROR("read async cfg info fail.");
return SLP_ESYSTEM;
}
if (0 == ds_read(CLOUD_CONFIG_BIND_HUB_REPORT_PATH, &bind_report, sizeof(BIND_HUB_REPORT)))
{
HUB_MANAGE_ERROR("read device status fail!");
return SLP_ESYSTEM;
}
if (hub_info.enabled && 0 >= strlen(hub_info.hub_mac))
{
HUB_MANAGE_ERROR("missing key parameters,hub_mac");
clear_hub_storage_info();
write_flag = 0;
goto end;
}
if (('\0' == hub_info.asyncMac[0] || '\0' == hub_info.asyncIp[0] || '\0' == hub_info.asyncPsw[0])
&& 0 != (async_record.async_cfg & (1 << HUB_MAN_ASYNC_TYPE_UNBIND_CONFIG)))
{
async_record.async_cfg &= ~(1 << HUB_MAN_ASYNC_TYPE_UNBIND_CONFIG);
ds_advanced_write(HUB_MANAGE_CFG_ASYNC_RECORD_PATH, (U8 *)&async_record, sizeof(HUB_MANAGE_CFG_ASYNC_RECORD), DS_FLAG_SAVE_FLASH);
}
end:
if (!write_flag)
{
return ret;
}
if (ds_advanced_write(HUB_MANAGE_STORAGE_INFO_PATH, (U8 *)&hub_info, sizeof(HUB_MANAGE_STORAGE_INFO), DS_FLAG_SAVE_FLASH) == 0)
{
HUB_MANAGE_ERROR("ds_write hub_storage error.");
ret = SLP_ESYSTEM;
}
if (ds_advanced_write(HUB_MANAGE_WIFI_BACKUP_PATH, (U8 *)&wifi_backup, sizeof(HUB_MANAGE_WIFI_BACKUP), DS_FLAG_SAVE_FLASH) == 0)
{
HUB_MANAGE_ERROR("wifi_backup write fail.");
ret = SLP_ESYSTEM;
}
return ret;
}
LOCAL S32 hub_manage_sync_retry(int retry_time)
{
S32 new_retry_time = 0;
srand(time(0));
if (0 == retry_time)
{
new_retry_time = rand() % (RANDOM_RETRY_TIME_SEC - 1) + 2; //2s~8s
}
else
{
new_retry_time = 2 * retry_time;
if (new_retry_time > MAX_TIMEOUT_RETRY_SEC)
new_retry_time = MAX_TIMEOUT_RETRY_SEC;
}
HUB_MANAGE_INFO("connect retry time update to %ds", new_retry_time);
return new_retry_time; //sec
}
/* 广播与hub间长连接状态的消息 */
void broadcast_hub_connect_status(int status)
{
HUB_CLIENT_CONNECT_MSG conn_msg = {0};
conn_msg.long_connection_sta = (status?1:0);
NSD_SEND(HUB_CLIENT_CONNECT_MSG_ID, (U8 *)&conn_msg, sizeof(HUB_CLIENT_CONNECT_MSG));
return;
}
S32 token_update_timer_handler()
{
HUB_MANAGE_STORAGE_INFO hub_storage = {0};
if (ds_read(HUB_MANAGE_STORAGE_INFO_PATH, (U8 *)&hub_storage, sizeof(HUB_MANAGE_STORAGE_INFO)) == 0)
{
HUB_MANAGE_ERROR("read hub_info fail.");
return ERROR;
}
if (ERROR != hub_client.token_update_timer)
{
inet_del_timer(hub_client.token_update_timer);
hub_client.token_update_timer = ERROR;
}
if (!hub_client.http_ctx)
{
HUB_MANAGE_ERROR("keepalive connection not alive");
return ERROR;
}
hub_client_msg_send(hub_client.http_ctx, HUB_MAN_REQ_TYPE_LOGIN);
hub_client.token_update_timer = inet_add_timer(token_update_timer_handler, 0, TOKEN_UPDATE_PERIOD, EXECUTE_SINGLE);
return SLP_ENONE;
}
S32 set_login_timer()
{
if (ERROR != hub_client.token_update_timer)
{
inet_del_timer(hub_client.token_update_timer);
hub_client.token_update_timer = ERROR;
}
hub_client.token_update_timer = inet_add_timer(token_update_timer_handler, 0, TOKEN_UPDATE_PERIOD, EXECUTE_SINGLE);
return SLP_ENONE;
}
/****************************************************************************
* Function : hub_manage_set_offline
* Description:
* Input : N/A
* Output : N/A
* Return : 0(OK)/-1(ERROR)
****************************************************************************/
void hub_manage_set_offline()
{
STORAGE_TMP_INFO storage_tmp = {0};
if (ds_read(HUB_MANAGE_STORAGE_TMP_PATH, &storage_tmp, sizeof(STORAGE_TMP_INFO)) == 0)
{
HUB_MANAGE_ERROR("read hub storage info fail.");
return;
}
if (TURN_OFFLINE_BOUND_TIMES > storage_tmp.offline)
{
storage_tmp.offline = TURN_OFFLINE_BOUND_TIMES;
ds_write(HUB_MANAGE_STORAGE_TMP_PATH, &storage_tmp, sizeof(STORAGE_TMP_INFO));
}
return;
}
LOCAL S32 dev_dyn_info_init()
{
BACKUP_TMP_INFO backup_tmp = {0};
HUB_MANAGE_WIFI_BACKUP wifi_info = {0};
HUB_MANAGE_STORAGE_INFO hub_storage = {0};
STORAGE_TMP_INFO storage_tmp = {0};
IMAGE_SWITCH image_switch = {0};
if (ds_read(HUB_MANAGE_WIFI_BACKUP_PATH, (U8 *)&wifi_info, sizeof(HUB_MANAGE_WIFI_BACKUP)) == 0)
{
HUB_MANAGE_ERROR("tdpd read factory info fail.");
return ERROR;
}
if (wifi_info.enabled && 0 < strlen(wifi_info.ipaddr))
{
backup_tmp.backup_tmp_enabled = wifi_info.enabled;
strncpy(backup_tmp.backup, wifi_info.backup, BACKUP_STR_MAX_LEN);
ds_write(HUB_MANAGE_BACKUP_TMP_PATH, &backup_tmp, sizeof(BACKUP_TMP_INFO));
}
if (0 == ds_read(HUB_MANAGE_STORAGE_INFO_PATH, &hub_storage, sizeof(HUB_MANAGE_STORAGE_INFO)))
{
HUB_MANAGE_ERROR("hub_storage Parameter could not be NULL.");
return ERROR;
}
if (hub_storage.enabled && 0 < strlen(hub_storage.ipaddr))
{
storage_tmp.storage_tmp_enabled = hub_storage.enabled;
ds_write(HUB_MANAGE_STORAGE_TMP_PATH, &storage_tmp, sizeof(STORAGE_TMP_INFO));
}
if (0 == ds_read(SYSTEM_SYS_PATH, &g_sys_info, sizeof(SYSTEM_SYS)))
{
HUB_MANAGE_ERROR("g_sys_info Parameter could not be NULL.");
return ERROR;
}
if (0 == ds_read(IMAGE_SWITCH_PATH, &image_switch, sizeof(IMAGE_SWITCH)))
{
HUB_MANAGE_ERROR("g_sys_info Parameter could not be NULL.");
return ERROR;
}
g_last_flip_type = image_switch.flip_type;
return OK;
}
/**
* 设置hub存储功能函数
*
* 此函数用于根据输入参数设置hub存储功能的状态,并在必要时更新存储IP地址。同时,它还会根据用户登录状态及密码信息,
* 通过HTTP客户端发送请求以更新hub存储的相关配置。
*
* @param storage_enable 字符串指针,表示存储是否启用。如果为"on"则启用存储,若为"off"则禁用存储。
* @param loginSta 登录状态枚举值,用于指示当前用户的登录情况。
* @param is_first_login 布尔型变量,标识用户是否首次登录。
* @param loginPwd 指向包含登录密码信息结构体的指针。
* @param storage_ipaddr 字符串指针,用于存储或更新hub的存储IP地址。
* @return 返回整型数值,OK表示操作成功,ERROR表示操作失败。
*/
LOCAL S32 set_hub_storage(S32 storage_enable, const char *storage_mac, LOGIN_STATUS loginSta, U8 is_first_login, HUB_PWD_UNIT *loginPwd, char *storage_ipaddr)
{
S32 ret = OK;
STORAGE_TMP_INFO storage_tmp = {0};
HUB_MANAGE_STORAGE_INFO hub_storage_info = {0};
ds_read(HUB_MANAGE_STORAGE_TMP_PATH, &storage_tmp, sizeof(STORAGE_TMP_INFO));
/* 从指定路径读取hub_storage */
if (0 == ds_read(HUB_MANAGE_STORAGE_INFO_PATH, &hub_storage_info, sizeof(HUB_MANAGE_STORAGE_INFO)))
{
HUB_MANAGE_ERROR("hub_info should not be null");
return SLP_ESYSTEM;
}
/* 处理存储使能状态 */
if (storage_enable)
{
storage_tmp.storage_tmp_enabled = TRUE;
storage_tmp.sync_hub_state = SYNC_HUB_SYNCING;
strncpy(storage_tmp.storage_mac, storage_mac, HUB_MAC_STR_LEN);
}
else if (!storage_enable)
{
storage_tmp.storage_tmp_enabled = FALSE;
storage_tmp.sync_hub_state = SYNC_HUB_SUCCESS;
hub_storage_info.enabled = FALSE;
report_cloud_msg_check((U8)storage_tmp.storage_tmp_enabled, &hub_storage_info);
ds_advanced_write(HUB_MANAGE_STORAGE_INFO_PATH, &hub_storage_info, sizeof(HUB_MANAGE_STORAGE_INFO), DS_FLAG_NOTIFY | DS_FLAG_SAVE_FLASH);
/* 当存储关闭时,检查并复制已配置的存储IP地址 */
if (0 >= strlen(hub_storage_info.ipaddr))
{
ret = ERROR;
goto out;
}
strncpy(storage_ipaddr, hub_storage_info.ipaddr, IP_STR_MAX_LEN);
}
else
{
HUB_MANAGE_ERROR("The parameter [storage_enable] error");
ret = ERROR;
goto ERR;
}
out:
/* 将临时存储配置写回指定路径 */
if (ds_write(HUB_MANAGE_STORAGE_TMP_PATH, &storage_tmp, sizeof(STORAGE_TMP_INFO)) == 0)
{
HUB_MANAGE_ERROR("The parameter [hub_storage] error");
ret = ERROR;
goto ERR;
}
/* 向hub同步配置 */
if (!hub_client.http_ctx)
{
hub_client.http_ctx = http_client_request_hub(is_first_login, CONN_WANT_KEEPALIVE, loginSta, loginPwd, TRUE,
storage_ipaddr, HUB_POST_PORT, HUB_MAN_REQ_TYPE_HUB_STORAGE, hub_http_message_handler);
}
else
{
if (0 != strcmp(hub_client.http_ctx->host, storage_ipaddr))
{
/* 先断开长链接是否会有隐患? */
// hub_client.http_ctx = NULL;
hub_client_session_free(hub_client.http_ctx);
hub_client.http_ctx = http_client_request_hub(is_first_login, CONN_WANT_KEEPALIVE, loginSta, loginPwd, TRUE,
storage_ipaddr, HUB_POST_PORT, HUB_MAN_REQ_TYPE_HUB_STORAGE, hub_http_message_handler);
}
else
{
hub_client_msg_send(hub_client.http_ctx, HUB_MAN_REQ_TYPE_HUB_STORAGE);
}
}
ERR:
if (OK != ret)
{
storage_tmp.sync_hub_state = SYNC_HUB_OTHER_ERR;
}
/* 返回执行结果 */
return ret;
}
/****************************************************************************
* 函数名称 : set_wifi_backup
* 功能描述 : 此函数用于设置wifi_backup配置,包括读取当前功能配置信息、处理wifi_backup使能状态,
* 并根据使能状态启动与hub的连接以及保存临时配置到内存ds模型中。
* 输入参数 :
* backup_enable - 字符串指针,表示wifi_backup使能状态,接受"on"(启用)和"off"(关闭)。
* backup - 字符串指针,表示备份类型,可为"hub"、"router"或"auto"。
* loginSta - 登录状态枚举变量。
* is_first_login - 布尔型变量,标识是否为首次登录。
* loginPwd - 登录密码单元结构体指针。
* backup_ipaddr - 字符串指针,用于存储备份连接的IP地址。
* 输出参数 : 无
* 返回值 :
* OK - 表示设置成功。
* ERROR - 表示在处理过程中发生错误。
* note : 该函数会根据备份使能状态进行一系列的操作,并在退出前将临时配置保存至内存ds模型中。
****************************************************************************/
LOCAL S32 set_wifi_backup(S32 backup_enable, const char *backup, LOGIN_STATUS loginSta, U8 is_first_login,
HUB_PWD_UNIT *loginPwd, char *backup_ipaddr)
{
S32 ret = OK;
BACKUP_TMP_INFO backup_tmp = {0};
HUB_MANAGE_WIFI_BACKUP wifi_backup = {0};
memset(&wifi_backup, 0, sizeof(HUB_MANAGE_WIFI_BACKUP));
/* 从配置文件读取当前的wifi_backup配置 */
if (0 == ds_read(HUB_MANAGE_WIFI_BACKUP_PATH, &wifi_backup, sizeof(HUB_MANAGE_WIFI_BACKUP)))
{
HUB_MANAGE_ERROR("hub_info Parameter could not be NULL.");
return SLP_ESYSTEM;
}
/* 处理wifi_backup使能状态 */
if (backup_enable)
{
backup_tmp.backup_tmp_enabled = TRUE;
if (!backup || (0 != strcmp(backup,"hub") && 0 != strcmp(backup,"router") && 0 != strcmp(backup,"auto")))
{
HUB_MANAGE_ERROR("The parameter [backup] error,%s,%s",backup,backup_enable?"on":"off");
ret = ERROR;
goto ERR;
}
strncpy(backup_tmp.backup, backup, BACKUP_STR_MAX_LEN);
strncpy(wifi_backup.backup, backup, BACKUP_STR_MAX_LEN);
}
else if (!backup_enable)
{
backup_tmp.backup_tmp_enabled = FALSE;
wifi_backup.enabled = FALSE;
if (0 >= strlen(wifi_backup.ipaddr))
{
ret = ERROR;
goto out;
}
strncpy(backup_ipaddr, wifi_backup.ipaddr, IP_STR_MAX_LEN);
}
out:
/* 将临时配置保存至内存ds模型 */
ds_write(HUB_MANAGE_BACKUP_TMP_PATH, &backup_tmp, sizeof(BACKUP_TMP_INFO));
ds_advanced_write(HUB_MANAGE_WIFI_BACKUP_PATH, &wifi_backup, sizeof(HUB_MANAGE_WIFI_BACKUP), DS_FLAG_SAVE_FLASH | DS_FLAG_NOTIFY);
if (OK != ret)
{
goto ERR;
}
/* 向hub同步配置 */
if (!hub_client.http_ctx || 0 != strcmp(backup_ipaddr,hub_client.http_ctx->host))
{
http_client_request_hub(is_first_login, CONN_NOT_KEEPALIVE, loginSta, loginPwd, TRUE,
backup_ipaddr, HUB_POST_PORT, HUB_MAN_REQ_TYPE_WIFI_BACKUP, hub_http_message_handler);
}
else
{
hub_client_msg_send(hub_client.http_ctx, HUB_MAN_REQ_TYPE_WIFI_BACKUP);
}
ERR:
return ret;
}
/****************************************************************************
* Function : get_passwd_list
* Description:
* Input :
* Output : N/A
* Return : OK/ERROR
****************************************************************************/
LOCAL S32 get_passwd_list(JSON_OBJPTR param, HUB_PWD_UNIT *pwd_list)
{
S32 ret = OK;
S32 index = 0;
S32 array_len = 0;
S32 encrypt_type = 0;
const char *pwd = NULL;
JSON_OBJPTR pwd_arr = NULL;
JSON_OBJPTR pwd_list_obj = NULL;
/* 检查param中hub_password_list是否存在 */
if (NULL == (pwd_list_obj = jso_obj_get(param, "hub_password_list")))
{
ret = SLP_EENTRYNOTEXIST;
goto out;
}
array_len = jso_array_length(pwd_list_obj);
/* 防止数组访问越界 */
if (array_len > HUB_PASSWD_LIST_NUM)
{
array_len = HUB_PASSWD_LIST_NUM;
}
for(index = 0; index < array_len; index++)
{
pwd_arr = jso_array_get_idx(pwd_list_obj, index);
if (NULL ==(pwd = jso_obj_get_string_origin(pwd_arr,"password")))
{
ret = SLP_EINVARG;
goto out;
}
strncpy(pwd_list[index].passwd, pwd, SHA256_BLOCK_SIZE);
if (-1 == jso_obj_get_int(pwd_arr, "encrypt_type", &encrypt_type))
{
ret = SLP_EINVARG;
goto out;
}
pwd_list[index].encrypt_type = encrypt_type;
HUB_MANAGE_WARNING("get passwd:%s, encrypt_type: %d", pwd_list[index].passwd, pwd_list[index].encrypt_type);
}
out:
return ret;
}
/****************************************************************************
* Function : search_scan_list
* Description:
* Input :
* Output : N/A
* Return : OK/ERROR
****************************************************************************/
LOCAL S32 search_scan_list(const char *hub_mac, char *ipaddr)
{
S32 ret = 0;
S32 hub_count = 0;
S32 index_hs = 0;
char item_path_hs[HUB_TDP_SCAN_LIST_PATH_SIZE] = {0};
TDP_SCAN_LIST_INFO scan_list = {{0}};
if (!ipaddr)
{
HUB_MANAGE_ERROR("ipaddr ptr is null");
ret = ERROR;
goto out;
}
if (0 == (hub_count = ds_section_list_count(HUB_TDP_SCAN_LIST_PATH)))
{
HUB_MANAGE_ERROR("section num of %s cann't be 0", HUB_TDP_SCAN_LIST_PATH);
ret = ERROR;
goto out;
}
/* 遍历所有scan list参数 */
for (index_hs = 0; index_hs < hub_count; index_hs++)
{
snprintf(item_path_hs, HUB_TDP_SCAN_LIST_PATH_SIZE, "%s%d", HUB_TDP_SCAN_LIST_PATH_PREFIX, index_hs + 1);
HUB_MANAGE_ERROR("path is %s, path size is %d.", item_path_hs, HUB_TDP_SCAN_LIST_PATH_SIZE);
if (0 != ds_read(item_path_hs, &scan_list, sizeof(TDP_SCAN_LIST_INFO)))
{
if (!scan_list.mac[0] || HUB_MAC_STR_LEN != strlen(scan_list.mac))
{
HUB_MANAGE_ERROR("hub scan mac is null");
ret = ERROR;
goto out;
}
if (0 == strcmp(scan_list.mac, hub_mac) && '\0' != scan_list.ipaddr[0])
{
strncpy(ipaddr, scan_list.ipaddr, IP_STR_MAX_LEN);
break;
}
}
}
if (0 == strlen(ipaddr))
{
HUB_MANAGE_ERROR("don't find corresponding scan info!");
ret = ERROR;
}
out:
return ret;
}
/****************************************************************************
* Function : tdp_scan_timer_handle
* Description:
* Input :
* Output : N/A
* Return : OK/ERROR
****************************************************************************/
LOCAL S32 wifi_backup_info_parse(JSON_OBJPTR wifi_backup_obj)
{
S32 ret = OK;
S32 index = OK;
U8 is_first_login = 0;
S32 is_backup_enable = 0;
const char *backup_enable = NULL;
const char *wifi_mac = NULL;
const char *backup = NULL;
const char *ip_supply = NULL;
char backup_ipaddr[IP_STR_MAX_LEN + 1] = {0};
LOGIN_STATUS loginSta = STATUS_NOT_LOGIN;
HUB_MANAGE_WIFI_BACKUP wifi_backup;
HUB_PWD_UNIT hub_wifi_passwd_list[HUB_PASSWD_LIST_NUM] = {{0}};
memset(&wifi_backup, 0, sizeof(HUB_MANAGE_WIFI_BACKUP));
if (0 == ds_read(HUB_MANAGE_WIFI_BACKUP_PATH, &wifi_backup, sizeof(HUB_MANAGE_WIFI_BACKUP)))
{
HUB_MANAGE_ERROR("hub_info Parameter could not be NULL.");
return SLP_ESYSTEM;
}
backup_enable = jso_obj_get_string_origin(wifi_backup_obj, "backup_enabled");
if (!backup_enable)
{
HUB_MANAGE_ERROR("The parameter [backup_enabled] error");
ret = ERROR;
goto ERR;
}
else if (0 == strcmp(backup_enable, "on"))
{
is_backup_enable = 1;
}
else if (0 == strcmp(backup_enable, "off"))
{
is_backup_enable = 0;
}
else
{
HUB_MANAGE_ERROR("The value of [backup_enable] is unexpected");
ret = ERROR;
goto ERR;
}
if (is_backup_enable)
{
wifi_mac = jso_obj_get_string_origin(wifi_backup_obj, "wifi_mac");
if (!wifi_mac || HUB_MAC_STR_LEN != strlen(wifi_mac))
{
HUB_MANAGE_ERROR("The parameter [wifi_mac] error");
ret = ERROR;
goto ERR;
}
backup = jso_obj_get_string_origin(wifi_backup_obj, "backup");
if (!backup)
{
HUB_MANAGE_ERROR("The parameter [backup] error");
ret = ERROR;
goto ERR;
}
if (0 > get_passwd_list(wifi_backup_obj, hub_wifi_passwd_list))
{
HUB_MANAGE_ERROR("get hub passwd error");
ret = ERROR;
goto ERR;
}
if (hub_wifi_passwd_list[0].passwd[0] == '\0')
{
if (g_hub_wifi_passwd_list[0].passwd[0] != '\0')
{
for(index = 0; index < HUB_PASSWD_LIST_NUM && g_hub_wifi_passwd_list[0].passwd[0] != '\0'; index++)
{
//添加hub password信息
strncpy(hub_wifi_passwd_list[0].passwd, g_hub_wifi_passwd_list[0].passwd, SHA256_BLOCK_SIZE);
}
}
}
is_first_login = 1;
ip_supply = jso_obj_get_string_origin(wifi_backup_obj, "ipaddr");
if (NULL == ip_supply)
{
/* 当app传入ip为空时,搜索扫描列表,获取存储设备IP */
ret = search_scan_list(wifi_mac, backup_ipaddr);
if (OK != ret)
{
HUB_MANAGE_ERROR("parse ipaddr err and search scan list err");
ret = SLP_ELACKARG;
goto ERR;
}
}
else
{
strncpy(backup_ipaddr, ip_supply, IP_STR_MAX_LEN);
}
}
set_wifi_backup(is_backup_enable, backup, loginSta, is_first_login, hub_wifi_passwd_list, backup_ipaddr);
ERR:
return ret;
}
/****************************************************************************
* 函数名称 : hub_storage_info_parse
* 功能描述 : 解析hubhub_storage
* 输入参数 : hub_storage_obj - 存储配置的JSON对象指针
* 输出参数 : 无
* 返回值 : OK表示成功,ERROR表示失败
****************************************************************************/
LOCAL S32 hub_storage_info_parse(JSON_OBJPTR hub_storage_obj)
{
S32 ret = OK;
S32 index = OK;
S32 is_first_login = 0;
S32 is_storage_enable = 0;
LOGIN_STATUS loginSta = STATUS_NOT_LOGIN;
const char *storage_enable = NULL; /* 存储是否启用 */
const char *storage_mac = NULL; /* 存储设备的MAC地址 */
const char *ip_supply = NULL;
char storage_ipaddr[IP_STR_MAX_LEN + 1] = {0}; /* 存储设备的IP地址 */
HUB_PWD_UNIT hub_sto_passwd_list[HUB_PASSWD_LIST_NUM] = {{0}}; /* 存储设备的密码列表 */
/* 获取并校验"storage_enabled"参数 */
storage_enable = jso_obj_get_string_origin(hub_storage_obj, "storage_enabled");
if (!storage_enable)
{
HUB_MANAGE_ERROR("The parameter [storage_enabled] null");
ret = ERROR;
goto ERR;
}
else if (0 == strcmp(storage_enable, "on"))
{
is_storage_enable = 1;
}
else if (0 == strcmp(storage_enable, "off"))
{
is_storage_enable = 0;
}
else
{
HUB_MANAGE_ERROR("The value of [storage_enabled] is unexpected");
ret = ERROR;
goto ERR;
}
/* 当存储启用时,进一步解析配置 */
if (is_storage_enable)
{
/* 获取并校验hub_storage mac合法性 */
storage_mac = jso_obj_get_string_origin(hub_storage_obj, "storage_mac");
if (!storage_mac || HUB_MAC_STR_LEN != strlen(storage_mac))
{
HUB_MANAGE_ERROR("The parameter [storage_mac] error");
ret = ERROR;
goto ERR;
}
/* 获取密码列表 */
if (0 > get_passwd_list(hub_storage_obj, hub_sto_passwd_list))
{
HUB_MANAGE_ERROR("get hub passwd error");
ret = ERROR;
goto ERR;
}
/* 用于Debug接口,手动设置hub login秘钥 */
if (hub_sto_passwd_list[0].passwd[0] == '\0')
{
if (g_hub_sto_passwd_list[0].passwd[0] != '\0')
{
for(index = 0; index < HUB_PASSWD_LIST_NUM && g_hub_sto_passwd_list[0].passwd[0] != '\0'; index++)
{
/* 添加hub password信息 */
strncpy(hub_sto_passwd_list[0].passwd, g_hub_sto_passwd_list[0].passwd, SHA256_BLOCK_SIZE);
}
}
}
is_first_login = 1; /* 标记为首次登录 */
ip_supply = jso_obj_get_string_origin(hub_storage_obj, "ipaddr");
if (NULL == ip_supply || !ip_supply[0])
{
/* 当app传入ip为空时,搜索扫描列表,获取存储设备IP */
ret = search_scan_list(storage_mac, storage_ipaddr);
if (OK != ret)
{
HUB_MANAGE_ERROR("parse ipaddr err and get scan list err");
ret = SLP_ELACKARG;
goto ERR;
}
}
else
{
strncpy(storage_ipaddr, ip_supply, IP_STR_MAX_LEN);
}
}
/* 设置hub存储配置 */
set_hub_storage(is_storage_enable, storage_mac, loginSta, is_first_login, hub_sto_passwd_list, storage_ipaddr);
ERR:
return ret;
}
/*****************************************************************************
* 函数名称 : hub_config_resync_handle
* 功能描述 :处理异常情况的重新同步流程
* 输入参数 : 无
* 输出参数 : 无
* 返回值 : OK - 表示成功执行,ERROR - 表示执行失败
****************************************************************************/
S32 hub_config_resync_handle(S32 resetSync)
{
HUB_MANAGE_STORAGE_INFO hub_info = {0}; /* 初始化hub_storage结构体 */
HUB_MANAGE_CFG_ASYNC_RECORD async_record = {0}; /* 初始化未同步信息结构体 */
/* 若存在未完成的重新同步定时器,则删除并重置其ID */
if (ERROR != g_resync_timer_id)
{
inet_del_timer(g_resync_timer_id);
g_resync_timer_id = ERROR;
}
if (ds_read(HUB_MANAGE_CFG_ASYNC_RECORD_PATH, (U8 *)&async_record, sizeof(HUB_MANAGE_CFG_ASYNC_RECORD)) == 0)
{
HUB_MANAGE_ERROR("read async cfg info fail.");
return ERROR;
}
if (0 == async_record.async_cfg)
{
HUB_MANAGE_INFO("none config is async.");
return OK;
}
if (ds_read(HUB_MANAGE_STORAGE_INFO_PATH, (U8 *)&hub_info, sizeof(HUB_MANAGE_STORAGE_INFO)) == 0)
{
HUB_MANAGE_ERROR("read hub_info fail.");
return ERROR;
}
/* 如果存在未处理的异步配置请求,如解绑失败,则进行同步 */
if (0 != (async_record.async_cfg & (1 << HUB_MAN_ASYNC_TYPE_SYNC_CONFIG)))
{
HUB_MANAGE_INFO("read async cfg: %d", async_record.async_cfg);
/* 检查并处理待同步的配置请求 */
if (hub_client.http_ctx)
{
hub_client_msg_send(hub_client.http_ctx, HUB_MAN_REQ_TYPE_SYNC_CONFIG);
}
else if ('\0' != hub_info.ipaddr[0] && hub_info.enabled)
{
hub_client.http_ctx = http_client_request_hub(0, CONN_WANT_KEEPALIVE, STATUS_NOT_LOGIN, NULL, TRUE,
hub_info.ipaddr, HUB_POST_PORT, HUB_MAN_REQ_TYPE_SYNC_CONFIG, hub_http_message_handler);
}
else if ('\0' != hub_info.ipaddr[0] && !hub_info.enabled)
{
http_client_request_hub(0, CONN_NOT_KEEPALIVE, STATUS_NOT_LOGIN, NULL, TRUE,
hub_info.ipaddr, HUB_POST_PORT, HUB_MAN_REQ_TYPE_SYNC_CONFIG, hub_http_message_handler);
}
}
else if (0 != (async_record.async_cfg & (1 << HUB_MAN_ASYNC_TYPE_UNBIND_CONFIG))
&& 0 == (async_record.async_cfg & (1 << HUB_MAN_ASYNC_TYPE_SYNC_CONFIG)))
{
/* 当存在已换绑但未同步的配置时,进行配置同步 */
sync_info_to_unbind_hub();
}
return OK;
}
LOCAL S32 http_client_resync_hub_handle()
{
HUB_MANAGE_CFG_ASYNC_RECORD async_record = {0}; /* 初始化异步记录结构体 */
if (ds_read(HUB_MANAGE_CFG_ASYNC_RECORD_PATH, (U8 *)&async_record, sizeof(HUB_MANAGE_CFG_ASYNC_RECORD)) == 0)
{
HUB_MANAGE_ERROR("read async cfg info fail.");
return ERROR;
}
if (0 == (async_record.async_cfg & (1 << HUB_MAN_ASYNC_TYPE_SYNC_CONFIG)))
{
async_record.async_cfg |= (1 << HUB_MAN_ASYNC_TYPE_SYNC_CONFIG);
if (ds_advanced_write(HUB_MANAGE_CFG_ASYNC_RECORD_PATH, &async_record, sizeof(HUB_MANAGE_CFG_ASYNC_RECORD), DS_FLAG_SAVE_FLASH) == 0)
{
HUB_MANAGE_ERROR("write async_record fail.");
return ERROR;
}
}
hub_resync_prepare(FALSE);
return OK; /* 函数执行结束,返回结果状态 */
}
void hub_resync_param_reset()
{
HUB_MANAGE_CFG_ASYNC_RECORD async_record = {0}; /* 初始化未同步信息结构体 */
/* 若存在未完成的重新同步定时器,则删除并重置其ID */
resync_delay_sec = 0;
hub_client.recon_delay = 0;
if (ERROR != g_resync_timer_id)
{
inet_del_timer(g_resync_timer_id);
g_resync_timer_id = ERROR;
}
if (ds_read(HUB_MANAGE_CFG_ASYNC_RECORD_PATH, (U8 *)&async_record, sizeof(HUB_MANAGE_CFG_ASYNC_RECORD)) == 0)
{
HUB_MANAGE_ERROR("read async cfg info fail.");
return;
}
if (0 != (async_record.async_cfg))
{
/* 设置新的同步定时器 */
resync_delay_sec = hub_manage_sync_retry(resync_delay_sec);
g_resync_timer_id = inet_add_timer(hub_config_resync_handle, 0, resync_delay_sec, EXECUTE_SINGLE);
}
return;
}
void hub_resync_prepare(S32 refresh)
{
if (refresh || ERROR != g_resync_timer_id)
{
inet_del_timer(g_resync_timer_id);
g_resync_timer_id = ERROR;
}
/* 设置新的同步定时器 */
resync_delay_sec = hub_manage_sync_retry(resync_delay_sec);
g_resync_timer_id = inet_add_timer(hub_config_resync_handle, 0, resync_delay_sec, EXECUTE_SINGLE);
return;
}
/*------------------------------------------------------------------------------------------------*/
/* ds注册接口回调 */
/*------------------------------------------------------------------------------------------------*/
/****************************************************************************
* 函数名称:tdp_scan_timer_handle
* 功能描述:处理扫描列表的定时器事件,读取并组装扫描到的设备信息
* 输入参数:
* context - 上下文结构体指针,包含相关资源对象
* params - 参数JSON对象指针
* 输出参数:无
* 返回值:OK表示成功,ERROR表示失败
****************************************************************************/
LOCAL S32 hub_list_handle(DS_HANDLE_CONTEXT *context, JSON_OBJPTR params)
{
S32 ret = 0;
S32 hub_count = 0;
S32 index_hs = 0;
JSON_OBJPTR hub_list = NULL;
JSON_OBJPTR hub_scan_info = NULL;
char item_path_hs[HUB_TDP_SCAN_LIST_PATH_SIZE] = {0};
TDP_SCAN_LIST_INFO scan_list = {{0}};
TDPC_SRCH_STATUS srch_sta = {0};
/* 检查输入参数是否有效 */
if (NULL == context || NULL == context->res_obj || NULL == params)
{
HUB_MANAGE_ERROR("ipaddr ptr is null");
ret = ERROR;
goto out;
}
/* 创建并初始化hub_list数组,用于存储扫描结果 */
if (NULL == (hub_list = jso_new_array()))
{
ret = SLP_ENOMEMORY;
goto out;
}
jso_obj_add(context->res_obj, "hub_list", hub_list);
/* 获取待扫描的设备数量 */
hub_count = ds_section_list_count(HUB_TDP_SCAN_LIST_PATH);
HUB_MANAGE_DEBUG("section num of %s is %d", HUB_TDP_SCAN_LIST_PATH, hub_count);
/* 遍历所有待扫描设备,并将其信息添加至hub_list数组 */
for (index_hs = 0; index_hs < hub_count; index_hs++)
{
snprintf(item_path_hs, HUB_TDP_SCAN_LIST_PATH_SIZE, "%s%d", HUB_TDP_SCAN_LIST_PATH_PREFIX, index_hs + 1);
HUB_MANAGE_DEBUG("path is %s, path size is %d.", item_path_hs, HUB_TDP_SCAN_LIST_PATH_SIZE);
/* 读取单个设备扫描信息 */
if (0 != ds_read(item_path_hs, &scan_list, sizeof(TDP_SCAN_LIST_INFO)))
{
/* 如果MAC地址无效,则跳过该设备 */
if (!scan_list.mac[0] || HUB_MAC_STR_LEN != strlen(scan_list.mac))
{
HUB_MANAGE_ERROR("hub scan mac error");
continue;
}
/* 创建并初始化一个用于存储设备详细扫描信息的对象 */
if (NULL == (hub_scan_info = jso_new_obj()))
{
HUB_MANAGE_ERROR("[Error] failed to create hub_scan_info");
ret = SLP_ENOMEMORY;
break;
}
/* 将扫描信息对象添加至hub_list数组 */
jso_array_add(hub_list, hub_scan_info);
/* 添加设备的基本信息至扫描信息对象 */
jso_add_string(hub_scan_info, "mac", scan_list.mac);
jso_add_string(hub_scan_info, "type", scan_list.type);
jso_add_string(hub_scan_info, "model", scan_list.model);
jso_add_string(hub_scan_info, "alias", scan_list.alias);
jso_add_int(hub_scan_info, "ai_hub_support", scan_list.ai_hub_support);
jso_add_int(hub_scan_info, "current_bound", scan_list.current_bound);
jso_add_int(hub_scan_info, "max_bound", scan_list.max_bound);
}
}
/* 读取搜索状态并添加至响应对象 */
if (0 == ds_read(TDPC_SRCH_STATUS_PATH, &srch_sta, sizeof(TDPC_SRCH_STATUS)))
{
HUB_MANAGE_ERROR("read srch_sta fail.");
ret = ERROR;
}
else
{
jso_add_string(context->res_obj, "scan_status", srch_sta.scan_status?"scanning":"idle");
}
out:
return ret;
}
/*****************************************************************************
* 函数名称 : set_hub_config_handle
* 功能描述 : 处理设置Hub配置的请求
* 输入参数 :
* context - DS_HANDLE_CONTEXT类型的指针,用于传递执行上下文信息
* params - JSON_OBJPTR类型的指针,指向包含配置参数的JSON对象
* 输出参数 : 无
* 返回值 : OK表示处理成功,ERROR表示处理失败
****************************************************************************/
LOCAL S32 set_hub_config_handle(DS_HANDLE_CONTEXT *context, JSON_OBJPTR params)
{
S32 ret = ERROR;
JSON_OBJPTR wifi_backup_obj = NULL; /* 用于存储Wi-Fi备份信息的JSON对象指针 */
JSON_OBJPTR hub_storage_obj = NULL; /* 用于存储Hub存储配置的JSON对象指针 */
/* 检查输入参数是否有效 */
if (NULL == context || NULL == params)
{
HUB_MANAGE_ERROR("No params in request.");
ret = ERROR;
goto ERR; /* 参数无效跳过解析 */
}
/* 解析Wi-Fi备份信息 */
wifi_backup_obj = jso_obj_get(params, "wifi_backup");
if (NULL != wifi_backup_obj)
{
ret = wifi_backup_info_parse(wifi_backup_obj);
if (OK != ret)
{
HUB_MANAGE_ERROR("wrong params in wifi_backup request.");
}
}
/* 解析Hub存储配置 */
hub_storage_obj = jso_obj_get(params, "hub_storage");
if (NULL != hub_storage_obj)
{
ret = hub_storage_info_parse(hub_storage_obj);
if (OK != ret)
{
HUB_MANAGE_ERROR("wrong params in hub_storage request.");
}
}
ERR:
return ret;
}
LOCAL S32 hub_reset_sync_handle(DS_HANDLE_CONTEXT *context, JSON_OBJPTR params)
{
S32 ret = 0;
const char *hub_mac = NULL;
HUB_MANAGE_WIFI_BACKUP wifi_info = {0};
/* 检查输入参数是否有效 */
if (NULL == context || NULL == params)
{
HUB_MANAGE_ERROR("No params in request.");
ret = ERROR;
goto END; /* 遇到错误时直接返回 */
}
HUB_MANAGE_INFO(" recv hub reset sync msg.");
hub_mac = jso_obj_get_string_origin(params, "hub_mac");
if (!hub_mac)
{
HUB_MANAGE_ERROR("The parameter [hub_mac] error");
ret = ERROR;
goto END;
}
hub_client_stop();
clear_hub_storage_info();
if (0 == ds_read(HUB_MANAGE_WIFI_BACKUP_PATH, &wifi_info, sizeof(HUB_MANAGE_WIFI_BACKUP)))
{
HUB_MANAGE_ERROR("read wifi info error.");
return ERROR;
}
if (0 == strcmp(wifi_info.hubMac, hub_mac))
{
memset(&wifi_info, 0, sizeof(HUB_MANAGE_WIFI_BACKUP));
ds_advanced_write(HUB_MANAGE_WIFI_BACKUP_PATH, &wifi_info, sizeof(HUB_MANAGE_WIFI_BACKUP), DS_FLAG_SAVE_FLASH | DS_FLAG_NOTIFY);
}
END:
return ret;
}
/*------------------------------------------------wifi_backup---------------------------------------------------*/
LOCAL S32 get_wifi_backup_info(DS_HANDLE_CONTEXT *context, JSON_OBJPTR section_obj)
{
HUB_MANAGE_WIFI_BACKUP wifi_info = {0};
HUB_MANAGE_STORAGE_INFO hub_storage_info = {0};
STORAGE_TMP_INFO storage_tmp = {0};
if (0 == ds_read(HUB_MANAGE_WIFI_BACKUP_PATH, &wifi_info, sizeof(HUB_MANAGE_WIFI_BACKUP)))
{
HUB_MANAGE_ERROR("hub_info Parameter could not be NULL.");
return ERROR;
}
if (0 == ds_read(HUB_MANAGE_STORAGE_INFO_PATH, &hub_storage_info, sizeof(HUB_MANAGE_STORAGE_INFO)))
{
HUB_MANAGE_ERROR("hub_storage Parameter could not be NULL.");
return ERROR;
}
if (0 == ds_read(HUB_MANAGE_STORAGE_TMP_PATH, &storage_tmp, sizeof(STORAGE_TMP_INFO)))
{
HUB_MANAGE_ERROR("storage_tmp Parameter could not be NULL.");
return ERROR;
}
jso_add_string(section_obj, "enabled", wifi_info.enabled?"on":"off");
jso_add_string(section_obj, "backup", wifi_info.backup);
if (0 < strlen(wifi_info.hubMac) && wifi_info.enabled)
{
jso_add_string(section_obj, "wifi_mac", wifi_info.hubMac);
if (!strcmp(wifi_info.hubMac, hub_storage_info.hub_mac))
{
jso_add_string(section_obj, "status", (storage_tmp.offline >= TURN_OFFLINE_BOUND_TIMES)?"offline":"online");
}
else
{
jso_add_string(section_obj, "status", "online");
}
}
HUB_MANAGE_DEBUG("\n"
"**************************************************\n"
"backup wifi info:\n"
"ipaddr:%s\n"
"ssid:%s\n"
"bssid:%s\n"
"asyncIp:%s\n"
"asyncMac:%s\n"
"**************************************************\n",
wifi_info.ipaddr, wifi_info.ssid, wifi_info.bssid, wifi_info.asyncIp, wifi_info.asyncMac);
return SLP_ENONE;
}
/*----------------------------------------------hub_storage--------------------------------------------------*/
LOCAL S32 get_storage_info(DS_HANDLE_CONTEXT *context, JSON_OBJPTR section_obj)
{
HUB_MANAGE_STORAGE_INFO hub_storage_info = {0};
STORAGE_TMP_INFO storage_tmp = {0};
int offline = 0;
if (0 == ds_read(HUB_MANAGE_STORAGE_TMP_PATH, &storage_tmp, sizeof(STORAGE_TMP_INFO)))
{
HUB_MANAGE_ERROR("read storage tmp info fail.");
return ERROR;
}
if (0 == ds_read(HUB_MANAGE_STORAGE_INFO_PATH, &hub_storage_info, sizeof(HUB_MANAGE_STORAGE_INFO)))
{
HUB_MANAGE_ERROR("hub_storage Parameter could not be NULL.");
return ERROR;
}
jso_add_string(section_obj, "enabled", hub_storage_info.enabled?"on":"off");
jso_add_int(section_obj, "storage_media_status", hub_storage_info.storage_media_status);
jso_add_string(section_obj, "last_stored_mac", storage_tmp.last_stored_mac);
if (TURN_OFFLINE_BOUND_TIMES <= storage_tmp.offline)
{
offline = 1;
}
if (0 < strlen(hub_storage_info.ipaddr) && hub_storage_info.enabled)
{
jso_add_string(section_obj, "storage_mac", hub_storage_info.hub_mac);
jso_add_string(section_obj, "status", offline?"offline":"online");
}
HUB_MANAGE_DEBUG("\n"
"**************************************************\n"
"storage info:\n"
"dev_id:%s\n"
"ipaddr:%s\n"
"model:%s\n"
"type:%s\n"
"auth_type:%s\n"
"asyncIp:%s\n"
"asyncMac:%s\n"
"max_bound:%d\n"
"**************************************************\n",
hub_storage_info.dev_id, hub_storage_info.ipaddr, hub_storage_info.model, hub_storage_info.type, hub_storage_info.auth_type,
hub_storage_info.asyncIp, hub_storage_info.asyncMac, hub_storage_info.max_bound);
return SLP_ENONE;
}
LOCAL S32 sync_hub_state_handle(DS_HANDLE_CONTEXT *context, JSON_OBJPTR params)
{
STORAGE_TMP_INFO storage_tmp = {0};
/* 检查输入参数是否有效 */
if (NULL == context || NULL == context->res_obj)
{
HUB_MANAGE_ERROR("context is null");
return ERROR;
}
if (0 == ds_read(HUB_MANAGE_STORAGE_TMP_PATH, &storage_tmp, sizeof(STORAGE_TMP_INFO)))
{
HUB_MANAGE_ERROR("storage tmp could not be NULL.");
return ERROR;
}
switch (storage_tmp.sync_hub_state)
{
case SYNC_HUB_IDLE:
jso_add_string(context->res_obj, "sync_hub_state", "idle");
break;
case SYNC_HUB_SYNCING:
jso_add_string(context->res_obj, "sync_hub_state", "syncing");
break;
case SYNC_HUB_UNLOCAL:
jso_add_string(context->res_obj, "sync_hub_state", "unlocalErr");
break;
case SYNC_HUB_OTHER_ERR:
jso_add_string(context->res_obj, "sync_hub_state", "otherErr");
break;
case SYNC_HUB_SUCCESS:
jso_add_string(context->res_obj, "sync_hub_state", "success");
break;
default:
/* 对未知类型的消息不进行处理 */
HUB_MANAGE_ERROR("unknown state:%d.",storage_tmp.sync_hub_state);
return SLP_ESYSTEM;
}
HUB_MANAGE_DEBUG("sync_hub_state:%d.",storage_tmp.sync_hub_state);
return SLP_ENONE;
}
/*------------------------------------------------------------------------------------------------*/
/* ubus回调函数 */
/*------------------------------------------------------------------------------------------------*/
/*****************************************************************************
* 函数名称:hub_manage_reset_msg_handle
* 功能描述:处理与HUB管理相关的重置消息,reset时需要发送HTTP请求通知hub
* 输入参数:
* handler - dms_handler_t类型的指针(未在示例中使用,推测为句柄)
* mbuf - 消息缓冲区指针
* mlen - 消息长度
* sender_dms_id - 发送者DMS ID
* 输出参数:无
* 返回值:OK表示成功,ERROR表示失败
*****************************************************************************/
LOCAL S32 hub_manage_reset_msg_handle(dms_handler_t *handler, U8 *mbuf, U32 mlen, U32 sender_dms_id)
{
S32 ret = OK;
HUB_MANAGE_STORAGE_INFO hub_storage = {0};
HUB_MANAGE_WIFI_BACKUP wifi_backup = {0};
STORAGE_TMP_INFO storage_tmp = {0};
BACKUP_TMP_INFO wifi_backup_tmp = {0};
/* 从指定路径读取wifi_backup信息,若读取失败则输出错误信息并返回错误码 */
if (0 == ds_read(HUB_MANAGE_WIFI_BACKUP_PATH, &wifi_backup, sizeof(HUB_MANAGE_WIFI_BACKUP)))
{
HUB_MANAGE_ERROR("hub_info Parameter could not be NULL.");
return SLP_ESYSTEM;
}
/* 若wifi_backup已启用且IP地址非空,则禁用wifi_backup功能 */
if (TRUE == wifi_backup.enabled && '\0' != wifi_backup.ipaddr[0])
{
wifi_backup.enabled = FALSE;
wifi_backup_tmp.backup_tmp_enabled = FALSE;
}
/* 从指定路径读取hub_storage,若读取失败则报错 */
if (ds_read(HUB_MANAGE_STORAGE_INFO_PATH, (U8 *)&hub_storage, sizeof(HUB_MANAGE_STORAGE_INFO)) == 0)
{
HUB_MANAGE_ERROR("read hub_info fail.");
ret = ERROR;
goto END;
}
/* 若存储功能已启用且IP地址非空,则禁用存储功能 */
if (TRUE == hub_storage.enabled && '\0' != hub_storage.ipaddr[0])
{
hub_storage.enabled = FALSE;
storage_tmp.storage_tmp_enabled = FALSE;
}
/* 将更新后的hub_storage写入指定路径,若写入失败则输出错误信息并将ret设为错误 */
if (ds_write(HUB_MANAGE_STORAGE_TMP_PATH, &storage_tmp, sizeof(STORAGE_TMP_INFO)) == 0)
{
HUB_MANAGE_ERROR("The parameter [hub_storage] error");
ret = ERROR;
goto END;
}
if (ds_write(HUB_MANAGE_STORAGE_INFO_PATH, &hub_storage, sizeof(HUB_MANAGE_STORAGE_INFO)) == 0)
{
HUB_MANAGE_ERROR("ds_write hub_storage error.");
ret = ERROR;
goto END;
}
/* 将更新后的wifi_backup信息写入指定路径,若写入失败则输出错误信息并将ret设为错误 */
if (ds_write(HUB_MANAGE_BACKUP_TMP_PATH, &wifi_backup_tmp, sizeof(BACKUP_TMP_INFO)) == 0)
{
HUB_MANAGE_ERROR("The parameter [wifi_backup] error");
ret = ERROR;
goto END;
}
if (0 == ds_write(HUB_MANAGE_WIFI_BACKUP_PATH, &wifi_backup, sizeof(HUB_MANAGE_WIFI_BACKUP)))
{
HUB_MANAGE_ERROR("ds_write wifi_backup error.");
goto END;
}
/* 使用新的hub_storage发起HTTP请求到Hub设备 */
if (!hub_client.http_ctx)
{
http_client_request_hub(0, CONN_NOT_KEEPALIVE, STATUS_LOGIN_FINISH, NULL, TRUE,
hub_storage.ipaddr, HUB_POST_PORT, HUB_MAN_REQ_TYPE_SYNC_CONFIG, hub_http_message_handler);
}
else
{
hub_client_msg_send(hub_client.http_ctx, HUB_MAN_REQ_TYPE_SYNC_CONFIG);
}
END:
/* 返回执行结果状态 */
return ret;
}
/****************************************************************************
* Function : hub_storage_reset_cb
* Description: 当需要重置Hubhub_storage时调用的回调函数。
* Input : *handler - 指向dms_handler_t结构体的指针,用于处理存储管理相关的操作。
* *mbuf - 指向包含消息体的缓冲区的指针。
* mlen - 消息体长度。
* sender_dms_id - 发送请求的DMS的ID。
* Output : N/A
* Return : OK/ERROR - 函数执行成功返回SLP_ENONE(通常表示无错误)。
****************************************************************************/
LOCAL S32 hub_storage_reset_cb(dms_handler_t *handler, U8 *mbuf, U32 mlen, U32 sender_dms_id)
{
HUB_MANAGE_STORAGE_INFO hub_storage_info = {0};
HUB_MANAGE_WIFI_BACKUP wifi_info = {0};
ds_read(HUB_MANAGE_STORAGE_INFO_PATH, &hub_storage_info, sizeof(HUB_MANAGE_STORAGE_INFO));
clear_hub_storage_info();
HUB_MANAGE_ERROR("hub storage reset success ");
if (0 == strcmp(wifi_info.hubMac, hub_storage_info.hub_mac))
{
memset(&wifi_info, 0, sizeof(HUB_MANAGE_WIFI_BACKUP));
ds_advanced_write(HUB_MANAGE_WIFI_BACKUP_PATH, &wifi_info, sizeof(HUB_MANAGE_WIFI_BACKUP), DS_FLAG_SAVE_FLASH | DS_FLAG_NOTIFY);
}
return SLP_ENONE;
}
/****************************************************************************
* 函数名称 : tdp_client_out_msg_handle
* 功能描述 : 处理TDP客户端发出的消息
* 输入参数 :
* handler - 处理器句柄,用于标识消息处理的上下文
* mbuf - 指向消息缓冲区的指针
* mlen - 消息缓冲区的长度
* sender_dms_id - 发送消息的DMS ID
* 输出参数 : 无
* 返回值 : OK - 消息处理成功,ERROR - 消息处理失败
****************************************************************************/
LOCAL S32 tdp_client_out_msg_handle(dms_handler_t *handler, U8 *mbuf, U32 mlen, U32 sender_dms_id)
{
TDP_CLIENT_OUT_MSG *msg = (TDP_CLIENT_OUT_MSG *)mbuf;
if ((NULL == mbuf) || (mlen != sizeof(TDP_CLIENT_OUT_MSG)))
{
return ERROR;
}
/* 根据消息类型处理消息 */
switch (msg->type)
{
case TC_TYPE_OUT_RESYNC_CONFIG:
/* 处理重同步配置消息 */
http_client_resync_hub_handle();
break;
default:
/* 对未知类型的消息不进行处理 */
break;
}
return OK;
}
LOCAL S32 hub_info_update_cb(dms_handler_t *handler, U8 *mbuf, U32 mlen, U32 sender_dms_id)
{
HUB_INFO_UPDATE_MSG *msg = (HUB_INFO_UPDATE_MSG *)mbuf;
if ((NULL == mbuf) || (mlen != sizeof(HUB_INFO_UPDATE_MSG)))
{
return ERROR;
}
/* 根据消息类型处理消息 */
HUB_MANAGE_STORAGE_INFO hub_storage_info = {0};
if (0 == ds_read(HUB_MANAGE_STORAGE_INFO_PATH, &hub_storage_info, sizeof(HUB_MANAGE_STORAGE_INFO)))
{
HUB_MANAGE_ERROR("hub_storage Parameter could not be NULL.");
return ERROR;
}
if (hub_storage_info.storage_media_status != msg->media_sta)
{
hub_storage_info.storage_media_status = msg->media_sta;
ds_advanced_write(HUB_MANAGE_STORAGE_INFO_PATH, &hub_storage_info, sizeof(HUB_MANAGE_STORAGE_INFO), DS_FLAG_NOTIFY | DS_FLAG_SAVE_FLASH);
}
return OK;
}
/****************************************************************************
* Function : hub_client_timer_handler
* Description:
* Input : N/A
* Output : N/A
* Return : 0(OK)/-1(ERROR)
****************************************************************************/
void hub_client_timer_handler()
{
HUB_MANAGE_STORAGE_INFO hub_storage_info = {0};
HUB_AUTH_USER_MANAGEMENT hub_auth_mgt = {{0}};
HUB_PWD_UNIT hub_passwd_list[HUB_PASSWD_LIST_NUM] = {{0}};
if (hub_client.resync_timer != ERROR)
{
inet_del_timer(hub_client.resync_timer);
hub_client.resync_timer = ERROR;
}
if (hub_client.http_ctx)
{
HUB_MANAGE_INFO("hub client already connect");
return;
}
if (0 == ds_read(HUB_MANAGE_STORAGE_INFO_PATH, &hub_storage_info, sizeof(HUB_MANAGE_STORAGE_INFO)))
{
HUB_MANAGE_ERROR("hub_storage Parameter could not be NULL.");
return;
}
if (0 == ds_read(HUB_AUTH_PATH, &hub_auth_mgt, sizeof(HUB_AUTH_USER_MANAGEMENT)))
{
HUB_MANAGE_ERROR("read hub_auth info error");
return;
}
if(hub_auth_mgt.passwd[0] != '\0')
{
strncpy(hub_passwd_list[0].passwd, hub_auth_mgt.passwd, SHA256_BLOCK_SIZE);
}
if(camera_force_hub_configuration_synchronization_flag != 0)
{
HUB_MANAGE_ERROR("camera_force_hub_configuration_synchronization");
hub_client.http_ctx = http_client_request_hub(FALSE, CONN_WANT_KEEPALIVE, STATUS_NOT_LOGIN, hub_passwd_list, FALSE,
g_hub_force_ip, g_hub_force_port, HUB_MAN_REQ_TYPE_SYNC_CONFIG, hub_http_message_handler);
}else
{
hub_client.http_ctx = http_client_request_hub(FALSE, CONN_WANT_KEEPALIVE, STATUS_NOT_LOGIN, hub_passwd_list, TRUE,
hub_storage_info.ipaddr, HUB_POST_PORT, HUB_MAN_REQ_TYPE_SYNC_CONFIG, hub_http_message_handler);
}
// hub_client.http_ctx = http_client_request_hub(FALSE, CONN_WANT_KEEPALIVE, STATUS_NOT_LOGIN, hub_passwd_list, TRUE,
// hub_storage_info.ipaddr, HUB_POST_PORT, HUB_MAN_REQ_TYPE_SYNC_CONFIG, hub_http_message_handler);
if (!hub_client.http_ctx)
{
HUB_MANAGE_ERROR("hub client creat failed.");
hub_client.recon_delay = hub_manage_sync_retry(hub_client.recon_delay);
hub_keepalive_client_start(hub_client.recon_delay);
return;
}
return;
}
/****************************************************************************
* Function : hub_keepalive_client_start
* Description:
* Input : delay_ms
* Output : N/A
* Return : 0(OK)/-1(ERROR)
****************************************************************************/
void hub_keepalive_client_start(int delay_sec)
{
HUB_MANAGE_STORAGE_INFO hub_storage = {0};
if (hub_client.resync_timer != ERROR)
{
inet_del_timer(hub_client.resync_timer);
hub_client.resync_timer = ERROR;
}
if (ds_read(HUB_MANAGE_STORAGE_INFO_PATH, (U8 *)&hub_storage, sizeof(HUB_MANAGE_STORAGE_INFO)) == 0)
{
HUB_MANAGE_ERROR("read hub_info fail.");
return;
}
if (!hub_storage.enabled)
{
HUB_MANAGE_INFO("hub_storage off,no need to link");
return;
}
if (delay_sec == 0)
{
hub_client_timer_handler();
return;
}
HUB_MANAGE_INFO("hub_client delay_sec %d.", delay_sec);
hub_client.resync_timer = inet_add_timer(hub_client_timer_handler, 0, delay_sec, EXECUTE_SINGLE);
return;
}
/****************************************************************************
* Function : hub_client_stop
* Description:
* Input : N/A
* Output : N/A
* Return : 0(OK)/-1(ERROR)
****************************************************************************/
void hub_client_stop()
{
if (!hub_client.http_ctx)
{
return;
}
hub_client.recon_delay = 0;
if (ERROR != hub_client.resync_timer)
{
inet_del_timer(hub_client.resync_timer);
hub_client.resync_timer = ERROR;
}
if (hub_client.http_ctx)
{
hub_client.http_ctx = NULL;
hub_client_session_free(hub_client.http_ctx);
}
return;
}
/****************************************************************************
* Function : hub_client_restart
* Description:
* Input : N/A
* Output : N/A
* Return : 0(OK)/-1(ERROR)
****************************************************************************/
void hub_client_restart()
{
hub_client.recon_delay = hub_manage_sync_retry(hub_client.recon_delay);
hub_keepalive_client_start(hub_client.recon_delay);
return;
}
/*------------------------------------------------------------------------------------------------*/
/* 模块初始化注册 */
/*------------------------------------------------------------------------------------------------*/
LOCAL S32 hub_manage_deinit()
{
msg_detach_handler(SYSTEM_RESET_MSG_ID, hub_manage_reset_msg_handle);
msg_detach_handler(HUB_STORAGE_RESET_MSG_ID, hub_storage_reset_cb);
msg_detach_handler(TDP_CLIENT_OUT_MSG_ID, tdp_client_out_msg_handle);
msg_attach_handler(HUB_INFO_UPDATE_MSG_ID, hub_info_update_cb);
return OK;
}
LOCAL S32 hub_manage_init()
{
ds_register_action("hub_manage", "get_scan_hub_list", hub_list_handle);/* app获取当前缓存的扫描结果 */
ds_register_action("hub_manage", "hub_config_set", set_hub_config_handle);/* onboarding后配置(app调用) */
ds_register_action("hub_manage", "ai_enhance_info", get_ai_enhance_handle);/* app获取AI增強配置接口 */
ds_register_action("hub_manage", "sync_ai_enhance", sync_ai_enhance_handle);/* hub设置AI增強接口 */
ds_register_action("hub_manage", "hub_reset_sync", hub_reset_sync_handle);/* hub reset事件通知 */
ds_register_action("hub_manage", "sync_hub_state", sync_hub_state_handle);/* 获取配置开关的同步状态 */
/* 注册获取设备配置信息的 action */
ds_register_get_json("hub_manage", "wifi_backup", "wifi_backup", get_wifi_backup_info);
ds_register_get_json("hub_manage", "hub_storage_info", "hub_storage_info", get_storage_info);
msg_attach_handler(SYSTEM_RESET_MSG_ID, hub_manage_reset_msg_handle);
msg_attach_handler(HUB_STORAGE_RESET_MSG_ID, hub_storage_reset_cb);
msg_attach_handler(TDP_CLIENT_OUT_MSG_ID, tdp_client_out_msg_handle);
msg_attach_handler(HUB_INFO_UPDATE_MSG_ID, hub_info_update_cb);
ai_enhance_obj_init();
HUB_MANAGE_DEBUG("hub_manage init over.");
return OK;
}
LOCAL S32 hub_manage_start()
{
hub_config_check();
dev_dyn_info_init();
hub_man_debug_start();
detect_support_load();
HUB_MANAGE_INFO("hub_manage start over.");
return OK;
}
LOCAL S32 hub_manage_reload(DS_MSG *msg)
{
if (ds_path_id_exist(msg->id, msg->num, SYSTEM_SYS_PATH))
{
SYSTEM_SYS sysInfo = {{0}};
HUB_MANAGE_STORAGE_INFO hub_info = {0};
if (ds_read(HUB_MANAGE_STORAGE_INFO_PATH, (U8 *)&hub_info, sizeof(HUB_MANAGE_STORAGE_INFO)) == 0)
{
HUB_MANAGE_ERROR("read hub_info fail.");
return ERROR;
}
if (ds_read(SYSTEM_SYS_PATH, &sysInfo, sizeof(SYSTEM_SYS)) == 0)
{
HUB_MANAGE_ERROR("read hub_info fail.");
return ERROR;
}
if (hub_info.ipaddr[0] == '\0')
{
return OK;
}
if (hub_client.http_ctx && (strcmp(sysInfo.avatar, g_sys_info.avatar) || strcmp(sysInfo.dev_alias, g_sys_info.dev_alias)))
{
hub_client_msg_send(hub_client.http_ctx, HUB_MAN_REQ_TYPE_SYNC_CONFIG);
}
}
/* 网络连接状态发生变化 */
if (ds_path_id_exist(msg->id, msg->num, LINK_STATUS_PATH))
{
LINK_STATUS link_status = {0};
ds_read(LINK_STATUS_PATH, &link_status, sizeof(LINK_STATUS));
if (LINK_UP == link_status.link_status)
{
HUB_MANAGE_ERROR("link status change,reload connect");
hub_keepalive_client_start(0);
}
}
/* 图像翻转 */
if (ds_path_id_exist(msg->id, msg->num, IMAGE_SWITCH_PATH))
{
FLIP_TYPE flip_type = FLIP_OFF;
IMAGE_SWITCH image_switch = {0};
ds_read(IMAGE_SWITCH_PATH, &image_switch, sizeof(IMAGE_SWITCH));
flip_type = image_switch.flip_type;
if (flip_type != g_last_flip_type)
{
g_last_flip_type = flip_type;
if (hub_client.http_ctx)
{
hub_client_msg_send(hub_client.http_ctx, HUB_MAN_REQ_TYPE_SYNC_CONFIG);
}
}
}
return OK;
}
LOCAL S32 hub_manage_stop()
{
hub_manage_deinit();
ai_enhance_obj_deinit();
hub_man_debug_stop();
return OK;
}
LOCAL void hub_manage_main()
{
DS_DAT_MON_DESC hub_manage_data_monitor[] =
{
DS_DAT_MON(SYSTEM_SYS_PATH, DATA_ATTRI_NOTIFY),
DS_DAT_MON(LINK_STATUS_PATH, DATA_ATTRI_NOTIFY),
DS_DAT_MON(REC_PLAN_ENABLE_PATH, DATA_ATTRI_NOTIFY),
DS_DAT_MON(HUB_MANAGE_STORAGE_INFO_PATH, DATA_ATTRI_NOTIFY),
DS_DAT_MON(HUB_MANAGE_AI_ENHANCE_DYN_PATH, DATA_ATTRI_NOTIFY),
DS_DAT_MON(IMAGE_SWITCH_PATH, DATA_ATTRI_NOTIFY),
};
DS_MOD_DESC hub_manage_module =
DS_STRUCT_MOD("hub_manage", hub_manage_init, NULL, hub_manage_reload, hub_manage_start, hub_manage_stop,
NULL, hub_manage_data_monitor);
MODULE *module_node = ds_register_module("hub_manage", &hub_manage_module);
SDM_ASSERT(NULL != module_node);
}
NSD_INIT(hub_manage_main);