参考下面代码,我要将chime设备换成Camera设备,请问该怎么修改相应的代码实现门铃和Camera的发现、配对、以及门铃给Camera设备发送响铃事件
/*******************************************************************************
* Copyright (C), 2022-2023, TP-Link Systems Inc.
* File name : wlan_chime_ctrl.c
* Version : 1.0
* Description : doorbell无线控制模块
* 包含无线控制chime响铃、支持chime快配功能
* Author : zhou bingjie<zhoubingjie@tp-link.com.hk>
* Create Date : 2022-11-30
* History :
* ------------------------------
* 01, 2022-11-30, zhou bingjie, create file.
*******************************************************************************/
#include "wlan_chime_ctrl.h"
LOCAL int recv_local_ctrl_fd = INVALID_SOCKET;
LOCAL int recv_wpa_fd = INVALID_SOCKET;
LOCAL S32 listen_local_ctrl_inet_idx = -1;
LOCAL S32 listen_wpa_inet_idx = -1;
LOCAL S32 chime_list_aging_inet_idx = -1;
LOCAL S32 bindtoken_aging_inet_idx = -1;
LOCAL CHIME_INFO *l_chime_list = NULL;
LOCAL SEND_PARAM_LIST *l_send_param_list = NULL;
LOCAL SEND_PARAM_LIST *l_action_send_param_list = NULL;
LOCAL S64 l_ring_time = 0;
LOCAL S64 l_reply_chime_time = 0;
LOCAL PAIRED_CHIME l_paired_chime_list;
LOCAL CHIME_CTRL_UNPAIR_LIST l_unpair_list;
LOCAL BLACKLIST_CHIME l_chime_blacklist;
char g_bindToken[BINDTOKEN_NUM][BINDTOKEN_LENGTH + 1] = {0};
U32 g_bindToken_add_time[BINDTOKEN_NUM] = {0};
LOCAL S8 l_request_bindtoken = 0;
LOCAL S8 l_request_bindtoken_num = 10;
/* 创建接收udp套接字 */
LOCAL int create_udp_recv_socket(U32 addr, U16 port)
{
int sock = -1;
struct sockaddr_in sock_addr;
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
WLAN_CHIME_CTRL_ERROR("create socket error, %s", strerror(errno));
return -1;
}
int on = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0)
{
WLAN_CHIME_CTRL_ERROR("setsockopt(SO_REUSEADDR) failed");
return -1;
}
memset(&sock_addr, 0, sizeof(sock_addr));
sock_addr.sin_family = AF_INET;
sock_addr.sin_addr.s_addr = htonl(addr);
sock_addr.sin_port = htons(port);
if (bind(sock, (struct sockaddr *)&sock_addr, sizeof(struct sockaddr_in)) < 0)
{
close(sock);
WLAN_CHIME_CTRL_ERROR("bind socket error, %s", strerror(errno));
return -1;
}
return sock;
}
/* 初始化本地控制套接字 */
LOCAL S32 chime_ctrl_socket_init()
{
S32 buf_size = 0;
recv_local_ctrl_fd = create_udp_recv_socket(INADDR_ANY, BROADCAST_PORT);
if (INVALID_SOCKET == recv_local_ctrl_fd)
{
WLAN_CHIME_CTRL_ERROR("Create chime_ctrl socket error.");
return ERROR;
}
/* 设置成非阻塞模式,开启广播标记 */
if ((ERROR == sock_non_block(recv_local_ctrl_fd)) || (ERROR == sock_broad_cast(recv_local_ctrl_fd)))
{
WLAN_CHIME_CTRL_ERROR("Config chime_ctrl socket error.");
goto error;
}
/* 设置缓存大小 */
buf_size = SOCKET_RECV_BUF_SIZE;
if (ERROR == setsockopt(recv_local_ctrl_fd, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof(buf_size)))
{
WLAN_CHIME_CTRL_ERROR("Set sock recv buf error.");
goto error;
}
return OK;
error:
close(recv_local_ctrl_fd);
recv_local_ctrl_fd = INVALID_SOCKET;
return ERROR;
}
/* doorbell无线控制响铃 */
LOCAL S32 wlan_doorbell_control(struct doorbell_control_param *param)
{
S32 ret = OK;
int socket_fd;
if (param->send_num > 0)
{
param->send_num--;/* 调用一次函数,发送次数自减1 */
}
else
{
inet_del_timer(param->timer_id);
free(param);
return ret;
}
ret = init_socket_fd(&socket_fd);
if (ret != 0)
{
WLAN_CHIME_CTRL_ERROR("wlan_doorbell_control: socket init failed.\n");
return -1;
}
doorbell_control_chime(socket_fd, param->recv_buf, param->send_len);
close(socket_fd);
return ret;
}
/* chime无线控制回调 */
LOCAL S32 chime_ctrl_handle(S32 sock)
{
struct sockaddr_in server_addr;
S32 length = 0;
S32 addr_len = sizeof(struct sockaddr_in);
U8 recv_buf[PKT_MAX_SIZE] = {0};
U16 encrypt_len;
S32 front_encrypt_len = HDR_MAX_LEN + sizeof(char) + MD5_HASH_SIZE * 2;
S32 ret = OK;
S32 send_len = 0;
S64 now_time = 0;
struct doorbell_control_param *control_param;
LINK_STATUS link_status = {0};
struct timeval tv;
memset(&server_addr, 0, sizeof(server_addr));
/* 接收本地控制消息 */
length = recvfrom(sock, recv_buf, PKT_MAX_SIZE,
0, (struct sockaddr *)&server_addr, (socklen_t *)&addr_len);
if (length < front_encrypt_len + sizeof(encrypt_len))
{
WLAN_CHIME_CTRL_ERROR("recv buf 'chime ctrl data' length is %d, too short.\n", length);
return -1;
}
gettimeofday(&tv, NULL);
now_time = (S64)tv.tv_sec * 1000 + tv.tv_usec / 1000;
if (now_time - l_ring_time < RING_INTERVAL_TIME)/* 短时间只执行一次回调 */
{
return -1;
}
l_ring_time = now_time;
memset(&link_status, 0, sizeof(link_status));
if (0 == ds_read(LINK_STATUS_PATH, &link_status, sizeof(LINK_STATUS_PATH)))
{
WLAN_CHIME_CTRL_ERROR("read LINK_STATUS_PATH failed\n");
return ERROR;
}
if (link_status.ipaddr != server_addr.sin_addr.s_addr) /* 非本机ip直接退出 */
{
WLAN_CHIME_CTRL_ERROR("source ip is not local\n");
return ERROR;
}
encrypt_len = ((U16)recv_buf[front_encrypt_len] << 8) + (U16)recv_buf[front_encrypt_len + 1];
recv_buf[HDR_MAX_LEN] = 0x01; /* data_num固定为1 */
send_len = front_encrypt_len + sizeof(encrypt_len) + encrypt_len;
/* 发送chime响铃无线控制帧 */
control_param = malloc(sizeof(struct doorbell_control_param));
memset(control_param, 0, sizeof(struct doorbell_control_param));
memcpy(control_param->recv_buf, recv_buf, PKT_MAX_SIZE);
control_param->send_len = send_len;
control_param->send_num = 20;
control_param->timer_id = inet_add_high_precision_timer(wlan_doorbell_control,
(S32)control_param, 100, EXECUTE_FOREVER);
return ret;
}
LOCAL S32 chime_ctrl_socket_start()
{
if (INVALID_SOCKET == chime_ctrl_socket_init())
{
WLAN_CHIME_CTRL_ERROR("chime_ctrl socket init error.");
return ERROR;
}
/* 向网络服务进程注册监听套接字 */
listen_local_ctrl_inet_idx = inet_add_socket((S32)recv_local_ctrl_fd,
(void *)chime_ctrl_handle, NULL, NULL);
if (listen_local_ctrl_inet_idx == -1)
{
WLAN_CHIME_CTRL_ERROR("Regist chime_ctrl socket error.");
close(recv_local_ctrl_fd);
recv_local_ctrl_fd = INVALID_SOCKET;
return ERROR;
}
return OK;
}
/* 快配chime配对列表、黑名单、远程移除列表更新:添加或删除 */
LOCAL void updata_paired_chime_list(U8 *chime_mac, S8 updata_flag)
{
int i = 0;
char chime_mac_str[MAC_STR_SIMPLIFY_LEN + 1] = "";
char *addr = NULL;
sprintf(chime_mac_str, "%02X%02X%02X%02X%02X%02X", chime_mac[0], \
chime_mac[1], chime_mac[2], chime_mac[3], chime_mac[4], chime_mac[5]);
if (0 == ds_read(PAIRED_CHIME_PATH, &l_paired_chime_list, sizeof(PAIRED_CHIME)))
{
WLAN_CHIME_CTRL_ERROR("read PAIRED_CHIME_PATH failed\n");
}
if (0 == ds_read(CHIME_CTRL_UNPAIR_LIST_PATH, &l_unpair_list, sizeof(CHIME_CTRL_UNPAIR_LIST)))
{
WLAN_CHIME_CTRL_ERROR("read CHIME_CTRL_UNPAIR_LIST_PATH failed\n");
}
if (0 == ds_read(BLACKLIST_CHIME_PATH, &l_chime_blacklist, sizeof(BLACKLIST_CHIME)))
{
WLAN_CHIME_CTRL_ERROR("read BLACKLIST_CHIME_PATH failed\n");
}
/* 更新配对列表 */
for (i = 0; i < PAIRED_MAX_NUM; i++)
{
/* 已存在配对列表,若不是删除操作,直接退出 */
if (strcmp(l_paired_chime_list.mac_addr[i], chime_mac_str) == 0)
{
if (updata_flag == DEL_PAIRED_CHIME)
{
memset(l_paired_chime_list.mac_addr[i], 0, sizeof(l_paired_chime_list.mac_addr[i]));
WLAN_CHIME_CTRL_INFO("del paired chime from list. mac : %s\n", chime_mac_str);
}
else
{
return;
}
}
}
for (i = 0; i < PAIRED_MAX_NUM; i++)
{
if (strlen(l_paired_chime_list.mac_addr[i]) == 0)
{
if (updata_flag == ADD_PAIRED_CHIME)
{
strcpy(l_paired_chime_list.mac_addr[i], chime_mac_str);
WLAN_CHIME_CTRL_INFO("add paired chime into list. mac : %s\n", chime_mac_str);
break;
}
}
}
if (i == PAIRED_MAX_NUM)
{
WLAN_CHIME_CTRL_INFO("paired chime list full, can't add chime %s\n", chime_mac_str);
}
/* 更新黑名单 */
for (i = 0; i < BLACKLIST_MAX_NUM; i++)
{
if (strcmp(l_chime_blacklist.mac_addr[i], chime_mac_str) == 0 && updata_flag == ADD_PAIRED_CHIME)
{
memset(l_chime_blacklist.mac_addr[i], 0, sizeof(l_chime_blacklist.mac_addr[i]));
l_chime_blacklist.timestamp[i] = 0;
}
}
/* 更新远程移除列表 */
addr = strstr(l_unpair_list.list, chime_mac_str);
if (addr != NULL && updata_flag == ADD_PAIRED_CHIME)
{
strcpy(addr, addr + CHIME_CTRL_UNPAIR_MAC_LEN);
l_unpair_list.num--;
}
ds_advanced_write(PAIRED_CHIME_PATH, &l_paired_chime_list, sizeof(PAIRED_CHIME), DS_FLAG_NOTIFY | DS_FLAG_SAVE_FLASH);
ds_advanced_write(BLACKLIST_CHIME_PATH, &l_chime_blacklist, sizeof(BLACKLIST_CHIME), DS_FLAG_NOTIFY | DS_FLAG_SAVE_FLASH);
ds_advanced_write(CHIME_CTRL_UNPAIR_LIST_PATH, &l_unpair_list, sizeof(CHIME_CTRL_UNPAIR_LIST), DS_FLAG_NOTIFY | DS_FLAG_SAVE_FLASH);
}
LOCAL S32 is_bindtoken_list_empty()
{
int i;
for (i = 0; i < BINDTOKEN_NUM; i++)
{
if (strlen(g_bindToken[i]) != 0)
{
return -1;
}
}
return 1;
}
LOCAL void bindtoken_timeout()
{
if (is_bindtoken_list_empty() == 1)
{
if (l_request_bindtoken_num > 0)
{
msg_send(BINDTOKEN_REQUEST_MSG_MID, NULL, 0);
inet_add_timer(bindtoken_timeout, 0, 10, EXECUTE_SINGLE);
l_request_bindtoken_num--;
}
else
{
WLAN_CHIME_CTRL_INFO("get bindtoken timeout\n");
l_request_bindtoken = 0;
l_request_bindtoken_num = 10;
}
}
else if (l_request_bindtoken == 1)
{
l_request_bindtoken = 0;
l_request_bindtoken_num = 10;
}
}
/* wpa_supplicant 上报probe request */
LOCAL void wpa_supplicant_report_probereq(int sock)
{
S32 res, pos, reply_len = 0;
U8 reply[1024] = {0};
char rsa_pub_key[512] = "";
U32 rsa_pub_key_len = 0;
U8 sa_mac[MAC_LEN] = {0};
U8 dataID;
U8 frametype;
res = recv(sock, reply, sizeof(reply), 0);
if (res < 0){
WLAN_CHIME_CTRL_ERROR("recv wpa_supplicant report failed.\n");
return;
}
reply_len = res;
memcpy(sa_mac, reply, MAC_LEN);
res = verify_probereq_if_from_chime(reply + MAC_LEN, reply_len - MAC_LEN);
if (res < 0)
return;
pos = MAC_LEN + res;
frametype = reply[pos++];
dataID = reply[pos++];
switch (frametype)
{
case CHIME_CONNECT_REQUEST:/* 接收的是chime发送的RSA公钥 */
if (dataID == DATA_ID_RSA_PUBKEY)
{
U8 rsa_pub_key_der[512] = {0};/* rsa公钥der格式 */
U8 deviceID_MD5[MD5_16 + 1] = {0};
U8 rsa_pub_key_der_len = reply[pos];
struct _aes_key aes_key;
SEND_PARAM *send_param;
S64 now_time;
struct timeval tv;
CHIME_INFO *list_pos;
gettimeofday(&tv, NULL);
now_time = (S64)tv.tv_sec * 1000 + tv.tv_usec / 1000;
list_pos = find_chime(l_chime_list, sa_mac);
/* 同一chime设备,短时间只执行一次回复 */
if (list_pos != NULL && list_pos->request_num >= FLOW_CTRL_NUM_LIMIT
&& now_time - l_reply_chime_time < REPLY_CHIME_TIME)
{
return ;
}
WLAN_CHIME_CTRL_INFO("chime discovery. mac[*:*:*:*:%2X:%2X]",sa_mac[MAC_LEN - 2], sa_mac[MAC_LEN - 1]);
/* bindtoken列表为空,向cloud申请一个bindtoken,保证列表至少有一个bindtoken, l_request_bindtoken用于避免多次请求 */
if (is_bindtoken_list_empty() == 1 && l_request_bindtoken == 0)
{
msg_send(BINDTOKEN_REQUEST_MSG_MID, NULL, 0);
l_request_bindtoken = 1;
inet_add_timer(bindtoken_timeout, 0, 10, EXECUTE_SINGLE);
}
l_reply_chime_time = now_time;
/* 获取rsa公钥 */
memcpy(rsa_pub_key_der, reply + pos + 1, rsa_pub_key_der_len);
/* DER格式转PEM格式 */
mbedtls_pem_write_buffer(PUB_RSA_KEY_HEAD, PUB_RSA_KEY_TAIL, rsa_pub_key_der,
rsa_pub_key_der_len, (U8*)rsa_pub_key, sizeof(rsa_pub_key), &rsa_pub_key_len);
/* 获取deviceID */
pos += rsa_pub_key_der_len + 1;
memcpy(deviceID_MD5, reply + pos + 2, MD5_16);
/* 添加设备到链表 */
if (add_chime_list(l_chime_list, sa_mac, rsa_pub_key, deviceID_MD5, &aes_key) != 0)
{
WLAN_CHIME_CTRL_ERROR("add or update chime list fail.");
return;
}
/* 设置发送信息内容 */
send_param = malloc(sizeof(SEND_PARAM));
memset(send_param, 0, sizeof(SEND_PARAM));
send_param->send_type = SEND_AES_KEY;
memcpy(send_param->rsa_pub_key, rsa_pub_key, strlen(rsa_pub_key));
memcpy(send_param->dst_mac, sa_mac, MAC_LEN);
memcpy(&send_param->aes_key, &aes_key, sizeof(struct _aes_key));
wlan_ctrl_sendto_chime(send_param);/* 向chime发送AES key */
if (send_param != NULL)
{
free(send_param);
send_param = NULL;
}
}
break;
case CHIME_RESPONSE:/* 接收的是chime发送的应答 */
WLAN_CHIME_CTRL_INFO("recieve chime response. mac= [*:*:*:*:%2X:%2X], dataID= %d, result= %d",
sa_mac[MAC_LEN - 2], sa_mac[MAC_LEN - 1], dataID, reply[pos + 1]);
if (dataID == DATA_ID_RECV_NET_INFO_RESULT)
{
U8 recv_net_info_result = reply[pos + 1];
SEND_PARAM_LIST *tmp = l_send_param_list->next;
if (tmp != NULL && tmp->send_param->send_num != 0 &&
memcmp(tmp->send_param->dst_mac, sa_mac, MAC_LEN) == 0)
{
tmp->send_param->send_num = 0;/* 发送次数置0 */
}
if (recv_net_info_result == RECV_NET_INFO_SUCCESS)
{
updata_paired_chime_list(sa_mac, ADD_PAIRED_CHIME);
}
}
else if (dataID == DATA_ID_ONBOARDING_RESULT)
{
U8 onboarding_result = reply[pos + 1];
if (onboarding_result == CHIME_ONBOARDING_SUCCESS)
{
del_chime_list(l_chime_list, sa_mac);
updata_paired_chime_list(sa_mac, ADD_PAIRED_CHIME);
}
else if (onboarding_result == CHIME_ONBOARDING_FAILED)
{
updata_paired_chime_list(sa_mac, DEL_PAIRED_CHIME);
}
}
break;
default:
break;
}
}
/* 监听chime发送的probe request帧 */
LOCAL S32 register_recv_frame_handle()
{
if(init_recv_socket_fd(&recv_wpa_fd) == 0)
{
listen_wpa_inet_idx = inet_add_socket((S32)recv_wpa_fd,
(void *)wpa_supplicant_report_probereq, NULL, NULL);
if (listen_wpa_inet_idx == -1)
{
WLAN_CHIME_CTRL_ERROR("Regist chime_ctrl socket error.");
close(recv_wpa_fd);
recv_wpa_fd = INVALID_SOCKET;
return ERROR;
}
WLAN_CHIME_CTRL_INFO("recv_wpa_fd = %d, listen_wpa_inet_idx = %d", recv_wpa_fd, listen_wpa_inet_idx);
}
return OK;
}
/* 获得chime设备列表 */
LOCAL S32 get_fast_onboarding_list(DS_HANDLE_CONTEXT *context, JSON_OBJPTR param)
{
JSON_OBJPTR mac_addr_list_obj = NULL;
CHIME_INFO *chime_list = l_chime_list;
char chime_mac[MAC_STR_SIMPLIFY_LEN + 1];
mac_addr_list_obj = jso_new_array();
if (NULL == mac_addr_list_obj)
{
return -1;
}
while (NULL != chime_list->next)
{
chime_list = chime_list->next;
sprintf(chime_mac, "%02X%02X%02X%02X%02X%02X", chime_list->mac_addr[0], chime_list->mac_addr[1],\
chime_list->mac_addr[2], chime_list->mac_addr[3], chime_list->mac_addr[4], chime_list->mac_addr[5]);
json_object_array_add(mac_addr_list_obj, jso_new_string(chime_mac));
}
jso_obj_add(context->res_obj, "mac_addr_list", mac_addr_list_obj);
return OK;
}
/* 依次对每个chime发送入网信息 */
LOCAL void select_chime_send_cb(void *param)
{
SEND_PROCESS *send_process = (SEND_PROCESS *)param;
SEND_PARAM_LIST *send_param_list = send_process->send_param_list;
SEND_PARAM_LIST *pos;
try_again:
if (send_param_list->next == NULL)
{
send_param_list->stop_send = 0;
inet_del_timer(send_process->timer_id);
free(send_process);
return;
}
pos = send_process->send_param_list;
if (pos->next != NULL)
{
SEND_PARAM_LIST *tmp = pos->next;
if (tmp->send_param->send_num > 0 && send_param_list->stop_send == 0)
{
wlan_ctrl_sendto_chime(tmp->send_param);
}
else
{
pos->next = tmp->next;
free(tmp->send_param);
free(tmp);
goto try_again;
}
}
}
/* 用户app选择chime配网进行动作:响铃or亮灯 */
LOCAL S32 select_device_action(struct _DS_HANDLE_CONTEXT *context, JSON_OBJPTR param)
{
JSON_OBJPTR sub_obj = NULL;
unsigned char action_flag = FLAG_NONE;
const char *mac_addr = NULL;
int array_len = 0;
int action_array_len = 0;
int i = 0, j = 0;
CHIME_INFO *pos = NULL;
SEND_PROCESS *send_action_process = NULL;
if ((NULL == param) || !jso_is_array(param))
{
WLAN_CHIME_CTRL_ERROR("param err");
return SLP_EINVARG;
}
array_len = jso_array_length(param);
for (i = 0; i < array_len; i++)
{
SEND_PARAM *send_param;
U8 ta_mac[MAC_LEN] = {0};
JSON_OBJPTR action;
const char *action_string;
sub_obj = jso_array_get_idx(param, i);
if (NULL == sub_obj)
{
WLAN_CHIME_CTRL_ERROR("get sub_obj err.\n");
continue;
}
mac_addr = jso_obj_get_string_origin(sub_obj, "mac_addr");
if (strlen(mac_addr) != MAC_STR_SIMPLIFY_LEN)
{
WLAN_CHIME_CTRL_ERROR("invalid mac_addr");
continue;
}
action = jso_get_obj_from_obj(sub_obj, "action");
if ((NULL == action) || !jso_is_array(action))
{
WLAN_CHIME_CTRL_ERROR("action err");
return SLP_EINVARG;
}
action_array_len = jso_array_length(action);
for (j = 0; j < action_array_len; j++)
{
action_string = jso_get_string_origin(jso_array_get_idx(action, j));
if (strcmp(action_string, ACTION_RING) == 0)
{
action_flag |= FLAG_RING;
}
else if (strcmp(action_string, ACTION_LED_BLINK) == 0)
{
action_flag |= FLAG_LED_BLINK;
}
else
{
WLAN_CHIME_CTRL_ERROR("invalid action_string, only support ring and led_blink");
continue;
}
}
mac_to_hex(mac_addr, ta_mac);/* mac字符串转数组形式 */
pos = find_chime(l_chime_list, ta_mac);/* 在设备链表中找到mac对应的chime */
if (pos == NULL)
{
continue;
}
WLAN_CHIME_CTRL_INFO("set chime[*:*:*:*:%2X:%2X] network configuration. receive [%d] from app, current No.[%d]",
ta_mac[MAC_LEN - 2], ta_mac[MAC_LEN - 1], array_len, i);
/* 设置发送信息内容 */
send_param = malloc(sizeof(SEND_PARAM));
memset(send_param, 0, sizeof(SEND_PARAM));
send_param->send_type = RING_OR_LED;/* 发包类型为发送响铃or亮灯 */
send_param->ring_or_led_flag = action_flag;
memcpy(send_param->rsa_pub_key, pos->pub_rsa_key, strlen(pos->pub_rsa_key));
memcpy(&send_param->aes_key, &pos->aes_key, sizeof(struct _aes_key));
memcpy(send_param->dst_mac, ta_mac, MAC_LEN);
send_param->send_num = SEND_RING_OR_LED_NUM;
insert_send_param_list(l_action_send_param_list, send_param);/* 加入到发送链表中 */
}
if (pos == NULL)
{
WLAN_CHIME_CTRL_ERROR("list find chime failed\n");
return ERROR;
}
/* 初始化SEND_PROCESS结构体,便于传参 */
send_action_process = (SEND_PROCESS *)malloc(sizeof(SEND_PROCESS));
memset(send_action_process, 0, sizeof(SEND_PROCESS));
send_action_process->send_param_list = l_action_send_param_list;
send_action_process->timer_id = inet_add_high_precision_timer(select_chime_send_cb,
(S32)send_action_process, 100, EXECUTE_FOREVER);/* 定时器间隔发包 */
return OK;
}
/* 用户app选择chime配网 */
LOCAL S32 select_device(struct _DS_HANDLE_CONTEXT *context, JSON_OBJPTR param)
{
JSON_OBJPTR sub_obj = NULL;
const char *mac_addr = NULL;
int array_len = 0;
int i = 0;
CHIME_INFO *pos = NULL;
SEND_PROCESS *send_process = NULL;
int device_num = 0;
struct timeval tv;
if ((NULL == param) || !jso_is_array(param))
{
WLAN_CHIME_CTRL_ERROR("param err");
return SLP_EINVARG;
}
if (l_action_send_param_list != NULL)
{
l_action_send_param_list->stop_send = 1;
}
array_len = jso_array_length(param);
for (i = 0; i < array_len; i++)
{
SEND_PARAM *send_param;
U8 ta_mac[MAC_LEN] = {0};
sub_obj = jso_array_get_idx(param, i);
if (NULL == sub_obj)
{
WLAN_CHIME_CTRL_ERROR("get sub_obj err.\n");
continue;
}
mac_addr = jso_obj_get_string_origin(sub_obj, "mac_addr");
if (strlen(mac_addr) != MAC_STR_SIMPLIFY_LEN)
{
WLAN_CHIME_CTRL_ERROR("invalid mac_addr");
continue;
}
mac_to_hex(mac_addr, ta_mac);/* mac字符串转数组形式 */
pos = find_chime(l_chime_list, ta_mac);/* 在设备链表中找到mac对应的chime */
if (pos == NULL)
{
continue;
}
WLAN_CHIME_CTRL_INFO("configure [*:*:*:*:%2X:%2X] network. receive [%d] from app, current No.[%d]",
ta_mac[MAC_LEN - 2], ta_mac[MAC_LEN - 1], array_len, i);
/* 设置发送信息内容 */
send_param = malloc(sizeof(SEND_PARAM));
memset(send_param, 0, sizeof(SEND_PARAM));
send_param->send_type = SEND_NET_INFO;
memcpy(send_param->rsa_pub_key, pos->pub_rsa_key, strlen(pos->pub_rsa_key));
memcpy(&send_param->aes_key, &pos->aes_key, sizeof(struct _aes_key));
memcpy(send_param->dst_mac, ta_mac, MAC_LEN);
send_param->send_num = SEND_NET_INFO_NUM;
insert_send_param_list(l_send_param_list, send_param);/* 加入到发送链表中 */
gettimeofday(&tv, NULL);
send_param->request_bindtoken_time = (U64)tv.tv_sec * 1000 + tv.tv_usec / 1000;
device_num++;
}
if (pos == NULL)
{
WLAN_CHIME_CTRL_ERROR("list find chime failed\n");
return ERROR;
}
/* 初始化SEND_PROCESS结构体,便于传参 */
send_process = (SEND_PROCESS *)malloc(sizeof(SEND_PROCESS));
memset(send_process, 0, sizeof(SEND_PROCESS));
send_process->send_param_list = l_send_param_list;
send_process->timer_id = inet_add_high_precision_timer(select_chime_send_cb,
(S32)send_process, 100, EXECUTE_FOREVER);/* 定时器间隔发包 */
/* 申请额外的bindtoken,用于多个chime快配 */
for (i = 0; i < device_num - 1; i++)
{
msg_send(BINDTOKEN_REQUEST_MSG_MID, NULL, 0);
}
return OK;
}
LOCAL S32 wlan_ctrl_variable_init()
{
memset(&g_chime_ctrl_aeskey, 0, sizeof(g_chime_ctrl_aeskey));
memset(&l_paired_chime_list, 0, sizeof(l_paired_chime_list));
memset(&l_unpair_list, 0, sizeof(l_unpair_list));
memset(&l_chime_blacklist, 0, sizeof(l_chime_blacklist));
l_send_param_list = send_param_list_init();
l_action_send_param_list = send_param_list_init();
l_chime_list = chimelist_init();
return OK;
}
LOCAL S32 add_bindtoken(void *handler, U8 *mbuf, U32 mlen, U32 sender_id)
{
int i = 0;
BINDTOKEN_MSG *msg = (BINDTOKEN_MSG *)mbuf;
if (mbuf == NULL)
{
WLAN_CHIME_CTRL_ERROR("mbuf is NULL.\n");
return ERROR;
}
if (mlen != sizeof(BINDTOKEN_MSG))
{
WLAN_CHIME_CTRL_ERROR("mlen is wrong\n");
return ERROR;
}
if (strlen(msg->bindtoken) != 0)
{
for (i = 0; i < BINDTOKEN_NUM; i++)
{
if (strlen(g_bindToken[i]) == 0)
{
strcpy(g_bindToken[i], msg->bindtoken);
g_bindToken_add_time[i] = time(NULL);
l_request_bindtoken = 0;
WLAN_CHIME_CTRL_INFO("get bindtoken[%d] from cloud.\n", i);
break;
}
}
}
else
{
WLAN_CHIME_CTRL_ERROR("bindtoken error\n");
return ERROR;
}
return OK;
}
LOCAL void bindtoken_aging()
{
int i = 0;
for (i = 0; i < BINDTOKEN_NUM; i++)
{
if (strlen(g_bindToken[i]) != 0 && (time(NULL) - g_bindToken_add_time[i]) > BINDTOKEN_AGING_TIME)
{
WLAN_CHIME_CTRL_INFO("aging bindToken[%d].\n", i);
memset(g_bindToken[i], 0, sizeof(g_bindToken[i]));
g_bindToken_add_time[i] = 0;
}
}
}
LOCAL S32 wlan_chime_init()
{
wlan_ctrl_variable_init();
/* 定时维护chime设备链表 */
chime_list_aging_inet_idx = inet_add_high_precision_timer(equip_aging, (S32)l_chime_list, 1000, EXECUTE_FOREVER);
/* 获取chime设备链表 */
ds_register_action("wlan_chime_ctrl", "get_fast_onboarding_list", get_fast_onboarding_list);
/* 选择设备,响铃or亮灯 */
ds_register_action("wlan_chime_ctrl", "select_device_action", select_device_action);
/* 选择设备,发送入网信息 */
ds_register_action("wlan_chime_ctrl", "select_device", select_device);
/* 监听本地控制响铃消息 */
chime_ctrl_socket_start();
/* 监听chime发送的probe request帧 */
register_recv_frame_handle();
return OK;
}
LOCAL S32 wlan_chime_start()
{
msg_attach_handler(BINDTOKEN_RESPOND_MSG_MID, add_bindtoken);
bindtoken_aging_inet_idx = inet_add_timer(bindtoken_aging, 0, BINDTOKEN_AGING_INTERVAL_TIME, EXECUTE_FOREVER);
return OK;
}
LOCAL S32 wlan_chime_stop()
{
if (recv_local_ctrl_fd != INVALID_SOCKET)
{
inet_del_socket(listen_local_ctrl_inet_idx);
close(recv_local_ctrl_fd);
recv_local_ctrl_fd = INVALID_SOCKET;
}
if (recv_wpa_fd != INVALID_SOCKET)
{
inet_del_socket(listen_wpa_inet_idx);
close(recv_wpa_fd);
recv_wpa_fd = INVALID_SOCKET;
}
if (chime_list_aging_inet_idx != -1)
{
inet_del_timer(chime_list_aging_inet_idx);
chime_list_aging_inet_idx = -1;
}
if (bindtoken_aging_inet_idx != -1)
{
inet_del_timer(bindtoken_aging_inet_idx);
bindtoken_aging_inet_idx = -1;
}
free_send_param_list(l_send_param_list);
free_send_param_list(l_action_send_param_list);
free_chime_list(l_chime_list);
msg_detach_handler(BINDTOKEN_RESPOND_MSG_MID, add_bindtoken);
return OK;
}
LOCAL void wlan_chime_ctrl_main()
{
DS_MOD_DESC wlan_chime_ctrl_module =
DS_STRUCT_MOD("wlan_chime_ctrl", wlan_chime_init, NULL, NULL,
wlan_chime_start, wlan_chime_stop, NULL, NULL);
MODULE *module_node = ds_register_subsystem("wlan_chime_ctrl", &wlan_chime_ctrl_module, FALSE);
WLAN_ASSERT(NULL != module_node);
}
WLAN_INIT(wlan_chime_ctrl_main);