TypeList 之 DerivedToFront 把类型链表中类型按继承层次排序(子类 -> 基类)

本文介绍了一种使用C++模板元编程实现类型列表的操作方法,包括获取长度、查找索引、追加删除类型等实用功能,并展示了如何对类型进行排序,特别针对继承关系的处理。

#include <cstdlib>
#include <iostream>

using namespace std;

template<bool flag,typename T,typename U>
struct Select
{
  typedef T Result;
};
template<typename T,typename U>
struct Select<false,T,U>
{
  typedef U Result;
};
template<class T,class U>
class Conversion
{
  typedef char small;
  class Big{char dummy[2];};
  static small Test(T);
  static Big Test(...);
  static T MakeT();
  static U MakeU();
public:
  enum{exists = sizeof(Test(MakeU())) == sizeof(small)};
  enum{exist2ways = exists && Conversion<U,T>::exists};
  enum{sametype = false};
};
template<class T>
class Conversion<T,T>
{public:enum{exists = 1,exist2ways = 1,sametype = 1};};
#define SUPPERSUBCLASS(T,U)/
        (Conversion<const T*,const U*>::exists)&&/
        !(Conversion<const T*,const void*>::sametype)//防止 T* 是void*类型
#define SUPPERSUBCLASS_STRICT(T,U)/
        (Conversion<const T,const U>::exists)&&/
        !(Conversion<const T,const void>::sametype)//防止 T* 是void*类型
class NullType;
namespace TL
{
  template<class T,class U>
  struct TypeList
  {
    typedef T head;
    typedef U tail;
  };
  #define TYPELIST_1(T1) TypeList<T1,NullType>
  #define TYPELIST_2(T1,T2) TypeList<T1,TYPELIST_1(T2)>
  #define TYPELIST_3(T1,T2,T3) TypeList<T1,TYPELIST_2(T2,T3)>
  #define TYPELIST_4(T1,T2,T3,T4) TypeList<T1,TYPELIST_3(T2,T3,T4)>
  //-----------------------------------------------------------------
  //Length
  template<class Tlist>struct Length;
  template<>struct Length<NullType>
  {
    enum{value = 0};
  };
  template<class T,class U>
  struct Length<TypeList<T,U> >
  {
    enum{value = 1 + Length<U>::value};
  };
  //---------------------------------------------------------------
  //利用索引查找对象
  template<class T,int U>struct TypeAt;
  template<class head,class tail>
  struct TypeAt<TypeList<head,tail>,0>
  {
    typedef head Result;
  };
  template<class head,class tail,int i>
  struct TypeAt<TypeList<head,tail>,i>
  {
    typedef typename TypeAt<tail,i - 1>::Result Result;
  };
  //---------------------------------------------------------------
  //indexof
  template<class TList,class T>struct IndexOf;
  template<class T>
  struct IndexOf<NullType,T>
  {
    enum{value = -1};
  };
  template<class Tail,class T>
  struct IndexOf<TypeList<T,Tail>,T>
  {
    enum{value = 0};
  };
  template<class Head,class Tail,class T>
  struct IndexOf<TypeList<Head,Tail>,T>
  {
  private:
    enum{temp = IndexOf<Tail,T>::value};
  public:
    enum{value = temp == -1 ? -1 : 1 + temp};
  };
  //---------------------------------------------------------------
  //Append
  template<class TList,class T>struct Append;
  template<>
  struct Append<NullType,NullType>
  {
    typedef NullType Result;
  };
  template<class T>
  struct Append<NullType,T>
  {
    typedef TYPELIST_1(T) Result;
  };
  template<class head,class Tail>
  struct Append<NullType,TypeList<head,Tail> >
  {
    typedef TypeList<head,Tail> Result;
  };
  template<class head,class Tail,class T>
  struct Append<TypeList<head,Tail>,T>
  {
    typedef TypeList<head,typename Append<Tail,T>::Result> Result;
  };
  //---------------------------------------------------------------
  //Erase
  template<class TList,class T>struct Erase;
  template<class T>
  struct Erase<NullType,T>
  {
    typedef NullType Result;
  };
  template<class T,class tail>
  struct Erase<TypeList<T,tail>,T>
  {
    typedef tail Result;
  };
  template<class head,class tail,class T>
  struct Erase<TypeList<head,tail>,T>
  {
    typedef TypeList<head,typename Erase<tail,T>::Result> Result;
  };
  //---------------------------------------------------------------
  //NoDuplicate
  template<class TList>struct NoDuplicate;
  template<>struct NoDuplicate<NullType>
  {
    typedef NullType Result;
  };
  template<class head,class tail>
  struct NoDuplicate<TypeList<head,tail> >
  {
  private:
    typedef typename NoDuplicate<tail>::Result L1;
    typedef typename Erase<L1,head>::Result L2;
  public:
    typedef TypeList<head,L2> Result;
  };
  //---------------------------------------------------------------
  //TypeList 之 Replace,把类型列表中的 T 类型换成 U 类型
  template<class TList,class T,class U>struct Replace;
  template<class T,class U>
  struct Replace<NullType,T,U>
  {
    typedef NullType Result;
  };
  template<class T,class U,class tail>
  struct Replace<TypeList<T,tail>,T,U>
  {
    typedef TypeList<U,tail> Result;
  };
  template<class head,class tail,class T,class U>
  struct Replace<TypeList<head,tail>,T,U>
  {
    typedef TypeList<head,typename Replace<tail,T,U>::Result> Result;
  };
  //---------------------------------------------------------------
  //TypeList 之 MostDerived
  template<class TList,class T>struct MostDerived;
  template<class T>
  struct MostDerived<NullType,T>
  {
    typedef T Result;
  };
  template<class head,class tail,class T>
  struct MostDerived<TypeList<head,tail>,T>
  {
  private:
    typedef typename MostDerived<tail,T>::Result Candidate;
  public:
    typedef typename Select<SUPPERSUBCLASS(Candidate,head),head,Candidate>::Result Result;
  };
  //---------------------------------------------------------------
  //TypeList 之 DerivedToFront 把类型链表中类型按继承层次排序(子类 -> 基类)
  template<class TList>struct DerivedToFront;
  template<>
  struct DerivedToFront<NullType>
  {
    typedef NullType Result;
  };
  template<class head,class tail>
  struct DerivedToFront<TypeList<head,tail> >
  {
  private:
    typedef typename MostDerived<TypeList<head,tail>,head>::Result TheMostDerivedType;
    typedef typename Replace<tail,TheMostDerivedType,head>::Result L;
  public:
    typedef TypeList<TheMostDerivedType,L> Result;
  };
}
using namespace TL;
class Widget
{};
class ScrollBar:public Widget
{};
class Button:public Widget
{};
class GraphicButton:public Button
{};
int main(int argc, char *argv[])
{
    typedef TYPELIST_4(Button,ScrollBar,GraphicButton,Widget) MyList;
    cout<<"排序前----------------------------------------"<<endl;
    cout<<"GraphicButton的索引:/t"<<IndexOf<MyList,GraphicButton>::value<<endl;
    cout<<"Button的索引:/t/t"<<IndexOf<MyList,Button>::value<<endl;
    cout<<"ScrollBar的索引:/t"<<IndexOf<MyList,ScrollBar>::value<<endl;
    cout<<"Widget的索引:/t/t"<<IndexOf<MyList,Widget>::value<<endl;
    typedef DerivedToFront<MyList>::Result MyList2;
    cout<<"排序后----------------------------------------"<<endl;
    cout<<"GraphicButton的索引:/t"<<IndexOf<MyList2,GraphicButton>::value<<endl;
    cout<<"Button的索引:/t/t"<<IndexOf<MyList2,Button>::value<<endl;
    cout<<"ScrollBar的索引:/t"<<IndexOf<MyList2,ScrollBar>::value<<endl;
    cout<<"Widget的索引:/t/t"<<IndexOf<MyList2,Widget>::value<<endl;
    cout<<"----------------------------------------------"<<endl;
    system("PAUSE");
    return EXIT_SUCCESS;
}

参考下面代码,我要将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);
09-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值