rel_1.6.0 init

This commit is contained in:
guocheng.kgc 2020-06-18 20:06:52 +08:00 committed by shengdong.dsd
commit 27b3e2883d
19359 changed files with 8093121 additions and 0 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,196 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef __DEVMGR__H
#define __DEVMGR__H
#include <stdint.h>
#include <unistd.h>
#include "aos/aos.h"
#include "service.h"
#include "devmgr_common.h"
#include "alink_export_internal.h"
//#define __DEVMGR_UT__ 1
#ifdef __DEVMGR_UT__
#include "devmgr_ut.h"
#endif
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
#define STR_SIGN_LEN (16)
#define STR_DEVID_LEN (17)
#define STR_TOKEN_LEN (6)
#define STR_UUID_LEN (32)
#define ETHER_ADDR_BYTES (6)
// add by wukong 2017-4-17
#define STR_MODEL_LEN (80 + 1)
#ifndef STR_NAME_LEN
#define STR_NAME_LEN (32 + 1)
#endif
// add by wukong end 2017-4-17
#define MODULE_NAME_DEVMGR "devmgr"
/*
*
*/
typedef enum {
DEV_TYPE_GATEWAY = 0,
DEV_TYPE_WIFI = 1,
DEV_TYPE_ZIGBEE = 2,
DEV_TYPE_BLE = 3,
DEV_TYPE_WIFI_SUB = 4,
DEV_TYPE_MAX
}
devtype_t;
/*
*
*/
typedef enum {
LINK_STATE_OFFLINE = 0,
LINK_STATE_ONLINE = 1,
} link_state_t;
/*
*
*/
typedef enum {
NETWORK_EVENT_UP = 0,
NETWORK_EVENT_DOWN = 1,
LINK_EVENT_ONLINE = 2,
LINK_EVENT_OFFLINE = 3,
LINK_EVENT_LEAVE = 4
} network_event_t;
/*
*
*/
typedef enum {
DEVICE_STATE_INITIAL = 0,
DEVICE_STATE_AUTHORISED = 1,
DEVICE_STATE_REGISTERED = 2,
DEVICE_STATE_LOGINED = 3,
DEVICE_STATE_LOGOUTED = 4
} device_state_t;
// add by wukong 2017-4-17 for router sub devices
typedef struct router_base_s {
char name[STR_NAME_LEN]; // hostname, for example, my iphone's hostname is "wujy"
char ostype[STR_NAME_LEN]; // router's sub device type, e.g "Android"
char category[STR_NAME_LEN]; // e.g "unknown"
char manufacturer[STR_NAME_LEN]; // e.g "HUAWEI","HTC", "unknown"
char model[STR_MODEL_LEN]; // e.g "PANDORABOX_NETWORKING_ROUTER_NEWIFI_PB1", "alink", "unknown"
} router_base_t;
// add by wukong end 2017-4-17
typedef struct dev_base_s {
uint8_t dev_type;
uint32_t model_id;
union {
char ether_mac[ETHER_ADDR_BYTES];
char ieee_addr[IEEE_ADDR_BYTES];
} u;
char rand[SUBDEV_RAND_BYTES];
char sign[STR_SIGN_LEN + 1];
char dev_id[STR_DEVID_LEN + 1];
char uuid[STR_UUID_LEN + 1];
char token[STR_TOKEN_LEN + 1];
uint16_t crc;
} dev_base_t;
typedef struct dev_info_s {
dlist_t list_node;
dlist_t attr_head;
dev_base_t dev_base;
// add by wukong 2017-4-17
router_base_t router_base;
// add by wukong end 2017-4-17
uint8_t device_idx; //0xff为无效值
uint8_t cloud_state;
uint8_t link_state;
void *dev_mutex;
uint8_t ref_cnt;
} dev_info_t;
typedef int32_t (*zigbee_remove_device_cb_t)(uint8_t ieee_addr[IEEE_ADDR_BYTES]);
int devmgr_get_dev_type(const char *devid_or_uuid, uint8_t *dev_type);
dev_info_t *devmgr_get_devinfo(const char *devid_or_uuid_or_mac);
#ifdef GATEWAY_SDK
//dev_info_t *devmgr_get_devinfo(const char *devid_or_uuid);
dev_info_t *devmgr_get_unknown_devinfo(const char *devid_or_uuid);
dev_info_t *devmgr_get_devinfo_by_ieeeaddr(unsigned char
ieee_addr[IEEE_ADDR_BYTES]);
int devmgr_sync_device_profile(uint8_t dev_type, unsigned int model_id);
int devmgr_authorise_device(char *devid);
/*获取全部设备model_id,提供给文件下载管理模块使用*/
int devmgr_get_all_device_modelid(uint32_t model_id[], int *num);
/*释放devinfo对象引用计数*/
void devmgr_put_devinfo_ref(dev_info_t *devinfo);
int devmgr_update_device_online_status(const char *devid, link_state_t state);
int devmgr_update_zigbee_device_online_status(uint8_t
ieee_addr[IEEE_ADDR_BYTES], uint8_t online);
int devmgr_relogin_device(const char *devid);
int devmgr_join_zigbee_device(unsigned char ieee_addr[IEEE_ADDR_BYTES],
uint32_t model_id, const char rand[SUBDEV_RAND_BYTES], const char *sign);
int devmgr_leave_zigbee_device(unsigned char ieee_addr[IEEE_ADDR_BYTES]);
void __dump_devinfo(dev_info_t *devinfo);
int devmgr_delete_device_by_devinfo(dev_info_t *devinfo);
void __dump_device_list();
//lmns依赖接口
//device -> gw,wifi设备上下线接口
//payload:{"uuid":"","mac":"","modelId":"","model":"","name":""}
int devmgr_update_wifi_device_online_status(const char *devid, uint8_t online,
const char *payload);
//app -> gw,扫码添加和删除设备
int devmgr_delete_device(const char *devid);
//payload:{"mac":"","ieeeAddr":"","modelId":"","dev_type":""}
int devmgr_add_device(const char *devid, const char *payload);
void devmgr_free_unknown_devlist(void);
//主动从设备端获取设备静态信息
int devmgr_zbnet_get_devinfo(unsigned char ieee_addr[IEEE_ADDR_BYTES]);
void devmgr_reset_all_device(void);
#endif
// add by wukong 2017-4-17
int get_mac_by_uuid(const char *uuid, char *mac);
int get_uuid_by_mac(const char *mac, char *uuid);
// add by wukong end 2017-17
int devmgr_init();
void devmgr_exit();
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif
#endif

View file

@ -0,0 +1,21 @@
NAME := devmgr
$(NAME)_TYPE := framework
GLOBAL_INCLUDES += .
$(NAME)_SOURCES := devmgr_alink.c devmgr_common.c devmgr.c devmgr_cache.c devmgr_router.c
ifeq ($(COMPILER),)
$(NAME)_CFLAGS += -Wall -Werror -Wno-unused-variable -Wno-unused-parameter -Wno-implicit-function-declaration
$(NAME)_CFLAGS += -Wno-type-limits -Wno-sign-compare -Wno-pointer-sign -Wno-uninitialized
$(NAME)_CFLAGS += -Wno-return-type -Wno-unused-function -Wno-unused-but-set-variable
$(NAME)_CFLAGS += -Wno-unused-value -Wno-strict-aliasing
else ifeq ($(COMPILER),gcc)
$(NAME)_CFLAGS += -Wall -Werror -Wno-unused-variable -Wno-unused-parameter -Wno-implicit-function-declaration
$(NAME)_CFLAGS += -Wno-type-limits -Wno-sign-compare -Wno-pointer-sign -Wno-uninitialized
$(NAME)_CFLAGS += -Wno-return-type -Wno-unused-function -Wno-unused-but-set-variable
$(NAME)_CFLAGS += -Wno-unused-value -Wno-strict-aliasing
endif
$(NAME)_CFLAGS += -DGATEWAY_SDK

View file

@ -0,0 +1,742 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <time.h>
#include "aos/aos.h"
#include "json_parser.h"
#include "msdp.h"
#include "devmgr.h"
#include "devmgr_alink.h"
#include "devmgr_cache.h"
#include "service_manager.h"
#include "connectivity_manager.h"
#include "digest_algorithm.h"
#include "alink_protocol.h"
#include "alink_export_internal.h"
#define MODULE_NAME MODULE_NAME_DEVMGR
#define DEVMGR_SERVICE_AUTHORISE_DEVICE_LIST "AuthoriseDeviceList"
#define DEVMGR_SERVICE_REMOVE_DEVICE "RemoveDevice"
#define DEVMGR_ATTRIBUTE_JOINED_DEVICE_LIST "JoinedDeviceList"
#define DEVMGR_SERVICE_PERMITJOIN_DEVICE "PermitJoin"
#define DEMGR_JOINED_DEVINFO_STRING_FMT "{\"sn\":\"%s\",\"shortModel\":\"%08x\"}"
#define DEVMGR_JSON_KEY_IEEE_ADDR "ieeeAddr"
#define DEVMGR_JSON_KEY_MAC "mac"
#define DEVMGR_JSON_KEY_SN "sn"
#define DEVMGR_JSON_KEY_SN_SET "snSet"
#define DEVMGR_JSON_KEY_DURATION "duration"
#define DEVMGR_JSON_KEY_MODEL_ID "modelId"
#define DEVMGR_JSON_KEY_SHORT_MODEL "shortModel"
#define DEVMGR_JSON_KEY_ENABLE "enable"
/* imported from other files to pass compile */
typedef int32_t (*zigbee_permit_join_cb_t)(uint8_t duration);
typedef struct {
bool enable;
uint8_t duration; //permitjoin持续时间
uint32_t short_model; //允许加入的设备shortModel0xffff表示不指定特定shortModel
uint32_t timestamp; //permitjoin起始时间戳
} permitjoin_t;
/*defined in devmgr.c*/
extern void *devlist_lock;
extern dlist_t dev_head;
extern dlist_t unknown_dev_head;
static permitjoin_t g_permitjoin_config;
static void *disablejoin_work = NULL;
void __work_func(void *work)
{
log_trace("disable device join");
g_permitjoin_config.enable = false;
devmgr_free_unknown_devlist();
}
const char *devmgr_get_device_signature(uint32_t short_model,
const char rand[SUBDEV_RAND_BYTES], char *sign_buff, uint32_t buff_size)
{
int i = 0;
char buff[128] = {0};
unsigned char md5_ret[16] = {0};
char secret[41] = {0};
char rand_hexstr[SUBDEV_RAND_BYTES * 2 + 1] = {0};
int ret = SERVICE_RESULT_ERR;
if (buff_size <= STR_SIGN_LEN) {
log_error("buffer size is too small");
return NULL;
}
memcpy(secret, "ISsi2JtDctJf0qW0HUjF7JtJjiiJLMbcZE8wxu4E", sizeof(secret));
int len = SUBDEV_RAND_BYTES;
memcpy(buff, rand, len);
len += snprintf(buff + len, sizeof(buff) - len, "%s", secret);
digest_md5(buff, len, md5_ret);
for (i = 0; i < STR_SIGN_LEN / 2; i++) {
sprintf(sign_buff + i * 2, "%02x", md5_ret[i]);
}
bytes_2_hexstr(rand, SUBDEV_RAND_BYTES, rand_hexstr, sizeof(rand_hexstr));
log_trace("rand hexstr:%s, secret:%s, sign:%s\n", rand_hexstr, secret,
sign_buff);
return sign_buff;
}
static int devmgr_listener(int type, void *data, int dlen, void *result,
int *rlen)
{
//log_trace("DEVMGR recv %s", sm_code2string(type));
if (type == SERVICE_EVENT) {
int st = *((int *)data);
log_trace("DEVMGR recv %s, %s", sm_code2string(type), sm_code2string(st));
if (st == SERVICE_STATE_READY) {
devmgr_network_event_cb(NETWORK_EVENT_UP);
} else if (st == SERVICE_STATE_STOP || st == SERVICE_STATE_INIT) {
devmgr_network_event_cb(NETWORK_EVENT_DOWN);
}
}
return EVENT_IGNORE;
}
int stdd_get_device_service(dev_info_t *devinfo, char *service_buff,
int buff_size)
{
return 0;
}
static int devmgr_register_remote_service(dev_info_t *devinfo)
{
int ret = SERVICE_RESULT_ERR;
uint8_t service[256] = {0};
if (NULL == devinfo) {
log_info("parameter invalid");
return SERVICE_RESULT_ERR;
}
ret = stdd_get_device_service(devinfo, service, sizeof(service));
if (SERVICE_RESULT_OK != ret ||
0 == json_get_array_size(service, strlen(service))) {
log_info("The device %s no service to register\r\n", devinfo->dev_base.uuid);
return SERVICE_RESULT_OK;
} else {
log_trace("The device %s service is %s\r\n", devinfo->dev_base.uuid, service);
return msdp_register_remote_service(devinfo->dev_base.uuid, service);
}
}
int devmgr_login_device(dev_info_t *devinfo)
{
int len, ret;
uint8_t tx_buff[128] = {0};
uint8_t digest[16] = {0};
uint8_t sign[33] = {0};
uint8_t rand_hexstr[SUBDEV_RAND_BYTES * 2 + 1] = {0};
alink_data_t data = {METHOD_DEVICE_LOGIN_SUB, tx_buff};
if (devinfo->dev_base.uuid[0] == '\0') {
return SERVICE_RESULT_ERR;
}
//"sign" : "hmacmd5(sub device's token, rand + sub device's uuid)"
memcpy(tx_buff, devinfo->dev_base.rand, sizeof(devinfo->dev_base.rand));
len = sizeof(devinfo->dev_base.rand);
len += snprintf(tx_buff + len, sizeof(tx_buff) - len, "%s",
devinfo->dev_base.uuid);
digest_hmac(DIGEST_TYPE_MD5, tx_buff, len, devinfo->dev_base.token,
strlen(devinfo->dev_base.token), digest);
bytes_2_hexstr(digest, sizeof(digest), sign, sizeof(sign));
tx_buff[0] = '\0';
bytes_2_hexstr(devinfo->dev_base.rand, sizeof(devinfo->dev_base.rand),
rand_hexstr, sizeof(rand_hexstr));
if (sizeof(tx_buff) == snprintf(tx_buff, sizeof(tx_buff),
PARAMS_DEVICE_LOGIN_SUB_FMT, devinfo->dev_base.uuid, rand_hexstr, sign)) {
return SERVICE_RESULT_ERR;
}
log_debug("send:%s", tx_buff);
ret = ((service_t *)sm_get_service("accs"))->put((void *)&data,
sizeof(data)); //accs_put
//ret = SERVICE_RESULT_OK;
return ret;
}
int devmgr_logout_device(dev_info_t *devinfo)
{
int ret;
char tx_buff[64] = {0};
alink_data_t data = {METHOD_DEVICE_LOGOUT_SUB, tx_buff};
if (devinfo->dev_base.uuid[0] == '\0') {
return SERVICE_RESULT_ERR;
}
if (sizeof(tx_buff) == snprintf(tx_buff, sizeof(tx_buff),
PARAMS_DEVICE_LOGOUT_SUB_FMT, devinfo->dev_base.uuid)) {
return SERVICE_RESULT_ERR;
}
log_debug("send:%s", tx_buff);
ret = ((service_t *)sm_get_service("accs"))->put((void *)&data,
sizeof(data)); //accs_put
// TODO: if need check the return code?
//ret = SERVICE_RESULT_OK;
return ret;
}
int devmgr_register_device(dev_info_t *devinfo)
{
int ret;
char tx_buff[512] = {0};
char features[128] = {0};
char result[128] = {0};
char sign_buff[STR_SIGN_LEN + 1] = {0};
char rand_hexstr[SUBDEV_RAND_BYTES * 2 + 1] = {0};
alink_data_t data = {METHOD_DEVICE_REGISTER_SUB, tx_buff};
if (sizeof(features) == snprintf(features, sizeof(features),
FEATURE_DEVICE_LOGIN_SUB_FMT, PROTOCL_ZIGBEE, "1")) {
return SERVICE_RESULT_ERR;
}
char *sign = devinfo->dev_base.sign;
if (strcmp(get_main_dev()->config->alinkserver,
default_online_server_with_port) != 0 &&
NULL != devmgr_get_device_signature(devinfo->dev_base.model_id,
devinfo->dev_base.rand, sign_buff, sizeof(sign_buff))) {
sign = sign_buff;
}
bytes_2_hexstr(devinfo->dev_base.rand, sizeof(devinfo->dev_base.rand),
rand_hexstr, sizeof(rand_hexstr));
if (sizeof(tx_buff) == snprintf(tx_buff, sizeof(tx_buff),
PARAMS_DEVICE_REGISTER_SUB_FMT,
devinfo->dev_base.model_id, rand_hexstr, sign,
devinfo->dev_base.dev_id, "", "", "",
"", "", "", "", features)) {
return SERVICE_RESULT_ERR;
}
log_debug("send:%s", tx_buff);
ret = ((service_t *)sm_get_service("accs"))->get((void *)&data, sizeof(data),
result, sizeof(result));//accs_put
if (SERVICE_RESULT_OK == ret) {
int len = 0;
char *json_str = json_get_value_by_name(result, strlen(result), "token", &len,
NULL);
if (NULL == json_str) {
log_error("get token fail, result data = %s", result);
return SERVICE_RESULT_ERR;
}
strncpy(devinfo->dev_base.token, json_str,
sizeof(devinfo->dev_base.token) > len ? len : sizeof(devinfo->dev_base.token));
json_str = json_get_value_by_name(result, strlen(result), JSON_KEY_UUID, &len,
NULL);
if (NULL == json_str) {
log_error("get uuid fail, result data = %s", result);
return SERVICE_RESULT_ERR;
}
strncpy(devinfo->dev_base.uuid, json_str,
sizeof(devinfo->dev_base.uuid) > len ? len : sizeof(devinfo->dev_base.uuid));
log_info("register device success, uuid:%s, token:%s", devinfo->dev_base.uuid,
devinfo->dev_base.token);
}
return ret;
}
int devmgr_unregister_device(dev_info_t *devinfo)
{
int len, ret;
uint8_t digest[16] = {0};
uint8_t sign[33] = {0};
uint8_t tx_buff[128] = {0};
uint8_t rand_hexstr[SUBDEV_RAND_BYTES * 2 + 1] = {0};
alink_data_t data = {METHOD_DEVICE_UNREGISTER_SUB, tx_buff};
log_info("unregister device, devid:%s", devinfo->dev_base.dev_id);
if (devinfo->dev_base.uuid[0] == '\0') {
return SERVICE_RESULT_ERR;
}
bytes_2_hexstr(devinfo->dev_base.rand, sizeof(devinfo->dev_base.rand),
rand_hexstr, sizeof(rand_hexstr));
//"sign" : "hmacmd5(sub device's token, rand + sub device's uuid)"
memcpy(tx_buff, devinfo->dev_base.rand, sizeof(devinfo->dev_base.rand));
len = sizeof(devinfo->dev_base.rand);
len += snprintf(tx_buff + len, sizeof(tx_buff) - len, "%s",
devinfo->dev_base.uuid);
digest_hmac(DIGEST_TYPE_MD5, tx_buff, len, devinfo->dev_base.token,
strlen(devinfo->dev_base.token), digest);
bytes_2_hexstr(digest, sizeof(digest), sign, sizeof(sign));
if (sizeof(tx_buff) == snprintf(tx_buff, sizeof(tx_buff),
PARAMS_DEVICE_UNREGISTER_SUB_FMT, devinfo->dev_base.uuid, rand_hexstr, sign)) {
return SERVICE_RESULT_ERR;
}
log_debug("send:%s", tx_buff);
ret = ((service_t *)sm_get_service("accs"))->put((void *)&data,
sizeof(data)); //accs_put
ret = SERVICE_RESULT_OK;
return ret;
}
static int devmgr_authorise_device_cb(char *devid, int str_len, int type)
{
int ret = SERVICE_RESULT_OK;
char devid_str[32] = {0};
strncpy(devid_str, devid, str_len);
ret = devmgr_authorise_device(devid_str);
RET_RETURN(ret, "authorise device fail, devid:%s", devid_str);
return ret;
}
//获取临时入网设备列表
static int devmgr_get_joined_devlist_attribute_cb(char *buf, unsigned int buf_len)
{
int ret = SERVICE_RESULT_OK;
dev_info_t *pos = NULL;
char ieeeAddr[STR_DEVID_LEN + 1] = {0};
int len = 0;
len += snprintf(buf, buf_len - len - 1, "[");
os_mutex_lock(devlist_lock);
dlist_for_each_entry(&unknown_dev_head, pos, dev_info_t, list_node) {
get_ieeeaddr_string_by_extaddr(pos->dev_base.u.ieee_addr, ieeeAddr,
sizeof(ieeeAddr));
len += snprintf(buf + len, buf_len - len - 1, DEMGR_JOINED_DEVINFO_STRING_FMT,
ieeeAddr, (unsigned int)pos->dev_base.model_id);
//buff太小
if (len == buf_len - 1) {
os_mutex_unlock(devlist_lock);
return SERVICE_BUFFER_INSUFFICENT;
}
}
os_mutex_unlock(devlist_lock);
buf[len] = ']';
buf[len + 1] = '\0';
return SERVICE_RESULT_OK;
}
static int devmgr_authorise_devlist_service_cb(char *args, char *buf,
unsigned int buf_len)
{
//args:{"ieeeAddrs":["", ...]}
int ret = SERVICE_RESULT_OK;
char *ieee_addrs = NULL;
int str_len = 0;
ieee_addrs = json_get_value_by_name(args, strlen(args), DEVMGR_JSON_KEY_SN_SET,
&str_len, NULL);
PTR_RETURN(ieee_addrs, ret, "get snSet fail, rpc args:%s", args);
//遍历json数组并执行处理函数
char back_chr = 0;
backup_json_str_last_char(ieee_addrs, str_len, back_chr);
char *str_pos, *entry;
int entry_len, type;
json_array_for_each_entry(ieee_addrs, str_pos, entry, entry_len, type) {
ret = devmgr_authorise_device_cb(entry, entry_len, type);
RET_LOG(ret, "authorise device fail, ieee_addrs:%s", ieee_addrs);
}
restore_json_str_last_char(ieee_addrs, str_len, back_chr);
devmgr_free_unknown_devlist();
return SERVICE_RESULT_OK;
}
static int devmgr_permitjoin_service_cb(char *args, char *buf,
unsigned int buf_len)
{
int str_len, ret = SERVICE_RESULT_ERR;
char buff[32] = {0};
char *str_pos = NULL;
//args:{"enable", "duration":"","shortModel":""}
//enable,获取使能状态
str_pos = json_get_value_by_name(args, strlen(args), DEVMGR_JSON_KEY_ENABLE,
&str_len, NULL);
PTR_RETURN(str_pos, ret, "get enable fail, args:%s", args);
g_permitjoin_config.enable = (*str_pos != '0') ? true : false;
//duration
str_pos = json_get_value_by_name(args, strlen(args), DEVMGR_JSON_KEY_DURATION,
&str_len, NULL);
PTR_RETURN(str_pos, ret, "get duration fail, args:%s", args);
strncpy(buff, str_pos, str_len);
g_permitjoin_config.duration = (uint8_t)atoi(buff);
if (g_permitjoin_config.duration < 1) {
g_permitjoin_config.enable = false;
}
memset(buff, 0, sizeof(buff));
#if 0/*2016.11.15开始modelId参数变更为shortModel*/
str_pos = json_get_value_by_name(args, strlen(args),
DEVMGR_JSON_KEY_SHORT_MODEL, &str_len, NULL);
PTR_RETURN(str_pos, ret, "get short model fail, args:%s", args);
strncpy(buff, str_pos, str_len);
#else/*获取shortModel失败再获取modelId过渡使用*/
str_pos = json_get_value_by_name(args, strlen(args), DEVMGR_JSON_KEY_MODEL_ID,
&str_len, NULL);
if (NULL == str_pos) {
str_pos = json_get_value_by_name(args, strlen(args),
DEVMGR_JSON_KEY_SHORT_MODEL, &str_len, NULL);
PTR_RETURN(str_pos, ret, "get short model fail, args:%s", args);
}
strncpy(buff, str_pos, str_len);
#endif
sscanf(buff, "%08x", (unsigned int *)&g_permitjoin_config.short_model);
//设置时间戳
g_permitjoin_config.timestamp = time(NULL);
if (alink_cb_func[_ALINK_ZIGBEE_PERMIT_JOIN]) {
ret = ((zigbee_permit_join_cb_t)alink_cb_func[_ALINK_ZIGBEE_PERMIT_JOIN])(
g_permitjoin_config.duration);
RET_RETURN(ret, "permit join fail");
} else {
log_error("permit_device callback is NULL");
}
//设置定时器
aos_cancel_work(disablejoin_work, __work_func, NULL);
if (g_permitjoin_config.enable == true &&
g_permitjoin_config.duration > 0) {
log_trace("delay disable device join, duration:%d",
g_permitjoin_config.duration);
disablejoin_work = aos_loop_schedule_work(g_permitjoin_config.duration * 1000,
__work_func, NULL, NULL, NULL);
}
return ret;
}
static int devmgr_remove_device_service_cb(char *args, char *buf,
unsigned int buf_len)
{
int str_len, ret = SERVICE_RESULT_ERR;
char ieee_addr[STR_DEVID_LEN + 1] = {0};
char *str_pos = NULL;
//args:{"ieeeAddr":""}
str_pos = json_get_value_by_name(args, strlen(args), DEVMGR_JSON_KEY_SN,
&str_len, NULL);
PTR_RETURN(str_pos, ret, "get sn fail, args:%s", args);
strncpy(ieee_addr, str_pos,
sizeof(ieee_addr) > str_len ? str_len : sizeof(ieee_addr) - 1);
ret = devmgr_delete_device(ieee_addr);
RET_RETURN(ret, CALL_FUCTION_FAILED, "devmgr_delete_device");
return ret;
}
static int devmgr_network_down_event_handler(dev_info_t *devinfo)
{
int ret = SERVICE_RESULT_OK;
switch (devinfo->cloud_state) {
case DEVICE_STATE_AUTHORISED:
case DEVICE_STATE_LOGOUTED:
//nothing todo
break;
case DEVICE_STATE_REGISTERED:
case DEVICE_STATE_LOGINED:
ret = devmgr_logout_device(devinfo);
if (ret != SERVICE_RESULT_OK) {
break;
}
devinfo->cloud_state = DEVICE_STATE_LOGOUTED;
break;
default:
break;
}
return ret;
}
void devmgr_delay_disable_join(int duration)
{
//permit join nothing todi
if (g_permitjoin_config.enable == true) {
return;
}
log_trace("permit device join, duration:%d", duration);
g_permitjoin_config.short_model = DEVMGR_PERMITJOIN_ANY_MODEL;
g_permitjoin_config.enable = true;
aos_cancel_work(disablejoin_work, __work_func, NULL);
disablejoin_work = aos_loop_schedule_work(duration * 1000, __work_func, NULL, NULL,
NULL);
return;
}
int devmgr_network_leave_event_handler(dev_info_t *devinfo)
{
int ret = SERVICE_RESULT_OK;
switch (devinfo->cloud_state) {
case DEVICE_STATE_AUTHORISED:
//nothing todo
break;
case DEVICE_STATE_REGISTERED:
case DEVICE_STATE_LOGINED:
case DEVICE_STATE_LOGOUTED:
ret = devmgr_unregister_device(devinfo);
if (ret != SERVICE_RESULT_OK) {
break;
}
devinfo->cloud_state = DEVICE_STATE_INITIAL;
break;
default:
break;
}
return ret;
}
int devmgr_network_up_event_handler(dev_info_t *devinfo)
{
int ret = SERVICE_RESULT_OK;
switch (devinfo->cloud_state) {
case DEVICE_STATE_AUTHORISED:
//发起设备注册,注册成功则更新设备信息和状态
ret = devmgr_register_device(devinfo);
if (ret != SERVICE_RESULT_OK) {
break;
}
ret = devmgr_login_device(devinfo);
if (ret != SERVICE_RESULT_OK) {
break;
}
devmgr_register_remote_service(devinfo);
devinfo->cloud_state = DEVICE_STATE_LOGINED;
break;
case DEVICE_STATE_REGISTERED:
case DEVICE_STATE_LOGOUTED:
if (LINK_STATE_ONLINE == devinfo->link_state) {
ret = devmgr_login_device(devinfo);
if (ret != SERVICE_RESULT_OK) {
log_warn("login sub device fail, devid:%s,uuid:%s, ret: %d",
devinfo->dev_base.dev_id, devinfo->dev_base.uuid, ret);
/* ALINK_CODE_ERROR_SUBDEV_NO_RELATIONSHIP:
* sub device relation not exist, delete the device from the gateway
* ALINK_CODE_ERROR_SUBDEV_INVALID_UUID:
* gw or sub device's uuid is invalid, delete the device from the gateway
*/
if (ALINK_CODE_ERROR_SUBDEV_NO_RELATIONSHIP == ret
|| ALINK_CODE_ERROR_SUBDEV_INVALID_UUID == ret) {
devinfo->cloud_state = DEVICE_STATE_AUTHORISED; /*needn't do unregister*/
devmgr_delete_device_by_devinfo(devinfo);
ret = SERVICE_RESULT_OK;
}
break;
}
devmgr_register_remote_service(devinfo);
devinfo->cloud_state = DEVICE_STATE_LOGINED;
}
break;
case DEVICE_STATE_LOGINED:
default:
break;
}
return ret;
}
uint32_t devmgr_get_permitjoin_short_model()
{
//app端触发入网/按键触发入网再超时时间内置直接返回指定short_model
if (g_permitjoin_config.timestamp + g_permitjoin_config.duration > time(NULL)
|| g_permitjoin_config.duration == 0xff) {
return g_permitjoin_config.short_model;
}
//网关按键触发入网
return DEVMGR_PERMITJOIN_ANY_MODEL;
}
static int devmgr_update_status_cb(char *name, int name_len, char *value,
int value_len, int value_type, const char *devid)
{
int str_len, ret = SERVICE_RESULT_ERR;
char attr_name[MAX_ATTR_NAME_LEN] = {0};
char attr_value[128] = {0};
//忽略uuid,attrset参数
if (strcmp(name, JSON_KEY_ATTRSET) == 0 || strcmp(name, JSON_KEY_UUID)) {
return SERVICE_RESULT_OK;
}
strncpy(attr_name, name, sizeof(attr_name) - 1);
char *str_pos = json_get_value_by_name(value, value_len, JSON_KEY_VALUE,
&str_len, NULL);
PTR_RETURN(str_pos, ret, "get value fail, attr_value:%s", value);
strncpy(attr_value, str_pos,
sizeof(attr_value) > str_len ? str_len : sizeof(attr_value) - 1);
log_trace("attr_name:%s, attr_value:%s", attr_name, attr_value);
ret = devmgr_update_attr_cache(devid, attr_name, attr_value);
return ret;
}
/*通告局域网内设备状态变更*/
/*
--> {"uuid":"42E6E69DAEF6483FBBA412A28AF7CD76","attrSet":["OnOff"],"OnOff":{"value":"1","when":"1404443369"}}
*/
int devmgr_annunciate_device_status(const char *devid, char *params)
{
int ret = SERVICE_RESULT_OK;
/* unknonw device */
dev_info_t *devinfo = devmgr_get_devinfo(devid);
PTR_RETURN(devinfo, ret, "get devinfo fail, devid:%s", devid);
devmgr_put_devinfo_ref(devinfo);
//遍历attr
char *pos, *key, *val;
int klen, vlen, vtype;
json_object_for_each_kv(params, pos, key, klen, val, vlen, vtype) {
ret = devmgr_update_status_cb(key, klen, val, vlen, vtype, devid);
RET_LOG(ret, "update device status fail, key:%s, value:%s", key, val);
}
return ret;
}
int devmgr_link_state_event_handler(dev_info_t *devinfo, link_state_t state)
{
int ret = SERVICE_RESULT_ERR;
devinfo->link_state = state;
if (LINK_STATE_ONLINE == state) {
ret = devmgr_network_up_event_handler(devinfo);
RET_LOG(ret, CALL_FUCTION_FAILED, "devmgr_network_up_event_handler");
} else if (LINK_STATE_OFFLINE == state) {
ret = devmgr_network_down_event_handler(devinfo);
RET_LOG(ret, CALL_FUCTION_FAILED, "devmgr_network_down_event_handler");
} else {
log_error("unknown link state, state:%d", state);
}
return ret;
}
int devmgr_network_event_cb(network_event_t event)
{
//遍历设备逐个注册、attatch
int ret = SERVICE_RESULT_OK;
dev_info_t *pos, *next = NULL;
os_mutex_lock(devlist_lock);
dlist_for_each_entry(&unknown_dev_head, pos, dev_info_t, list_node) {
switch (event) {
case NETWORK_EVENT_DOWN: //network disconnected
//ret = devmgr_network_down_event_handler(pos);
pos->cloud_state = DEVICE_STATE_LOGOUTED;
break;
case NETWORK_EVENT_UP: //network connected
ret = devmgr_network_up_event_handler(pos);
break;
default:
break;
}
}
os_mutex_unlock(devlist_lock);
return ret;
}
int devmgr_alink_init()
{
int ret = SERVICE_RESULT_OK;
memset(&g_permitjoin_config, 0, sizeof(g_permitjoin_config));
#if 0
//属性注册
ret = alink_register_attribute(DEVMGR_ATTRIBUTE_JOINED_DEVICE_LIST,
devmgr_get_joined_devlist_attribute_cb, NULL);
//服务注册
ret = alink_register_service(DEVMGR_SERVICE_AUTHORISE_DEVICE_LIST,
devmgr_authorise_devlist_service_cb);
ret = alink_register_service(DEVMGR_SERVICE_REMOVE_DEVICE,
devmgr_remove_device_service_cb);
ret = alink_register_service(DEVMGR_SERVICE_PERMITJOIN_DEVICE,
devmgr_permitjoin_service_cb);
#endif
sm_attach_service("accs", &devmgr_listener);
return ret;
}
void devmgr_alink_exit()
{
sm_detach_service("accs", &devmgr_listener);
aos_cancel_work(disablejoin_work, __work_func, NULL);
alink_unregister_service(DEVMGR_SERVICE_AUTHORISE_DEVICE_LIST);
alink_unregister_service(DEVMGR_SERVICE_REMOVE_DEVICE);
alink_unregister_service(DEVMGR_SERVICE_PERMITJOIN_DEVICE);
}

View file

@ -0,0 +1,64 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef __DEVMGR_ALINK__H__
#define __DEVMGR_ALINK__H__
#include <unistd.h>
#ifdef __cplusplus
extern "C" {
#endif
#define PROTOCL_ZIGBEE "zigbee"
#define PROTOCL_RF433 "rf433"
#define METHOD_DEVICE_REGISTER_SUB "device.registerSub"
#define METHOD_DEVICE_UNREGISTER_SUB "device.unregisterSub"
#define METHOD_DEVICE_LOGIN_SUB "device.loginSub"
#define METHOD_DEVICE_LOGOUT_SUB "device.logoutSub"
#define DEVMGR_PERMITJOIN_ANY_MODEL (0xffffffff)
/*按键触发入网开关,默认超时时间*/
#define DEVMGR_DEFAULT_PERMITJOIN_DURATION 240
//"sign":"hmacmd5(secret, rand+sn)"
#define PARAMS_DEVICE_REGISTER_SUB_FMT ("{\"shortModel\":\"%08x\",\"rand\":\"%s\",\"sign\":\"%s\","\
"\"sn\":\"%s\",\"model\":\"%s\",\"mac\":\"%s\",\"version\":\"%s\",\"name\":\"%s\","\
"\"barcode\":\"%s\",\"cid\":\"%s\",\"description\":\"%s\",\"features\":%s}")
#define PARAMS_DEVICE_UNREGISTER_SUB_FMT ("{\"uuid\":\"%s\",\"rand\":\"%s\",\"sign\":\"%s\"}")
//"sign" : "hmacmd5(sub device's token, rand + sub device's uuid)"
#define PARAMS_DEVICE_LOGIN_SUB_FMT ("{\"uuid\":\"%s\",\"rand\":\"%s\",\"sign\":\"%s\"}")
#define PARAMS_DEVICE_LOGOUT_SUB_FMT ("{\"uuid\":\"%s\"}")
#define FEATURE_DEVICE_LOGIN_SUB_FMT ("{\"linkCapability\":[{\"protocol\":\"%s\",\"profile\":\"%s\"}]}")
#define RESULT_DEVICE_REGISTER_SUB_FMT ("{\"uuid\":\"%s\",\"token\":\"%s\"}")
int devmgr_network_up_event_handler(dev_info_t *devinfo);
uint32_t devmgr_get_permitjoin_short_model();
/*通告局域网内设备状态变更*/
/*
--> {"uuid":"42E6E69DAEF6483FBBA412A28AF7CD76","attrSet":["OnOff"],"OnOff":{"value":"1","when":"1404443369"}}
*/
const char *devmgr_get_device_signature(uint32_t short_model,
const char rand[SUBDEV_RAND_BYTES], char *sign_buff, uint32_t buff_size);
int devmgr_login_device(dev_info_t *devinfo);
int devmgr_logout_device(dev_info_t *devinfo);
int devmgr_register_device(dev_info_t *devinfo);
int devmgr_unregister_device(dev_info_t *devinfo);
int devmgr_annunciate_device_status(const char *devid, char *params);
int devmgr_link_state_event_handler(dev_info_t *devinfo, link_state_t state);
int devmgr_network_leave_event_handler(dev_info_t *devinfo);
int devmgr_network_event_cb(network_event_t event);
void devmgr_delay_disable_join(int duration);
int devmgr_alink_init();
void devmgr_alink_exit();
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,277 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "aos/aos.h"
#include "os.h"
#include "devmgr.h"
#include "devmgr_cache.h"
#define MODULE_NAME MODULE_NAME_DEVMGR
typedef struct attr_cache_s {
dlist_t list_node;
char *attr_name;
char *attr_value;
} attr_cache_t;
static void *__cache_dup_string(const char *src)
{
char *dst;
int n ;
if (!src) {
return NULL;
}
n = strlen(src);
dst = (char *)os_malloc(n + 1);
if (!dst) {
return NULL;
}
memcpy(dst, src, n);
dst[n] = '\0';
return dst;
}
static void *__cache_new_buff(unsigned int buff_size)
{
void *buff = os_malloc(buff_size);
if (NULL != buff) {
memset(buff, 0, buff_size);
}
return buff;
}
static void __cache_free_buff(void *buff)
{
if (buff) {
os_free(buff);
}
}
static void *__cache_renew_buff(char *src, uint32_t new_size)
{
__cache_free_buff(src);
return __cache_new_buff(new_size);
}
static attr_cache_t *__new_attr_node(const char *attr_name,
const char *attr_value)
{
attr_cache_t *attr_node = __cache_new_buff(sizeof(attr_cache_t));
PTR_GOTO(attr_node, err, "pstrdup error");
memset(attr_node, 0, sizeof(attr_cache_t));
attr_node->attr_name = __cache_dup_string(attr_name);
PTR_GOTO(attr_node->attr_name, err, "pstrdup error");
attr_node->attr_value = __cache_dup_string(attr_value);
PTR_GOTO(attr_node->attr_value, err, "pstrdup error");
return attr_node;
err:
if (attr_node != NULL) {
if (attr_node->attr_name) {
__cache_free_buff(attr_node->attr_name);
}
if (attr_node->attr_value) {
__cache_free_buff(attr_node->attr_value);
}
__cache_free_buff((char *)attr_node);
}
return NULL;
}
static void __free_attr_node(attr_cache_t *cache)
{
if (cache != NULL) {
if (cache->attr_name) {
__cache_free_buff(cache->attr_name);
}
if (cache->attr_value) {
__cache_free_buff(cache->attr_value);
}
__cache_free_buff((char *)cache);
}
}
static int __get_attr_cache(dlist_t *attr_head, const char *attr_name,
char *attr_value_buff, int buff_size)
{
attr_cache_t *attr_node = NULL;
char *buff = NULL;
dlist_for_each_entry(attr_head, attr_node, attr_cache_t, list_node) {
if (strcmp(attr_node->attr_name, attr_name) == 0) {
if (buff_size <= strlen(attr_node->attr_value)) {
return SERVICE_BUFFER_INSUFFICENT;
}
strncpy(attr_value_buff, attr_node->attr_value, buff_size);
return SERVICE_RESULT_OK;
}
}
return SERVICE_RESULT_ERR;
}
static int __read_attr_cache(dlist_t *attr_head, const char *attr_name,
char **attr_value)
{
attr_cache_t *attr_node = NULL;
char *buff = NULL;
dlist_for_each_entry(attr_head, attr_node, attr_cache_t, list_node) {
if (strcmp(attr_node->attr_name, attr_name) == 0) {
buff = os_malloc(strlen(attr_node->attr_value) + 1);
PTR_RETURN(buff, SERVICE_RESULT_ERR, "pmalloc failed");
strncpy(buff, attr_node->attr_value, strlen(attr_node->attr_value) + 1);
*attr_value = buff;
return SERVICE_RESULT_OK;
}
}
return SERVICE_RESULT_ERR;
}
static int __update_attr_cache(dlist_t *attr_head, const char *attr_name,
const char *attr_value)
{
attr_cache_t *attr_node = NULL;
char *buff = NULL;
dlist_for_each_entry(attr_head, attr_node, attr_cache_t, list_node) {
if (strcmp(attr_node->attr_name, attr_name) == 0) {
attr_node->attr_value = __cache_renew_buff(attr_node->attr_value,
strlen(attr_value) + 1);
strncpy(attr_node->attr_value, attr_value, strlen(attr_value) + 1);
return SERVICE_RESULT_OK;
}
}
attr_node = __new_attr_node(attr_name, attr_value);
PTR_RETURN(attr_node, SERVICE_RESULT_ERR, CALL_FUCTION_FAILED,
"__new_attr_node")
dlist_add_tail(&attr_node->list_node, attr_head);
return SERVICE_RESULT_OK;
}
static void __free_attr_cache_list(dlist_t *cache_head)
{
attr_cache_t *cache;
dlist_t *next;
dlist_for_each_entry_safe(cache_head, next, cache, attr_cache_t, list_node) {
__free_attr_node(cache);
}
}
void __dump_attr_cache(dlist_t *attr_head)
{
os_printf("\tattr cache:\n");
attr_cache_t *cache;
dlist_for_each_entry(attr_head, cache, attr_cache_t, list_node) {
os_printf("\t\t%s: %s\n", cache->attr_name, cache->attr_value);
}
}
/*读取子设备属性缓存*/
int devmgr_get_attr_cache(const char *devid_or_uuid, const char *attr_name,
char *attr_value_buff, int buff_size)
{
int ret = SERVICE_RESULT_ERR;
dev_info_t *devinfo = devmgr_get_devinfo(devid_or_uuid);
PTR_RETURN(devinfo, SERVICE_RESULT_ERR, CALL_FUCTION_FAILED,
"devmgr_get_devinfo");
os_mutex_lock(devinfo->dev_mutex);
ret = __get_attr_cache(&devinfo->attr_head, attr_name, attr_value_buff,
buff_size);
os_mutex_unlock(devinfo->dev_mutex);
devmgr_put_devinfo_ref(devinfo);
return ret;
}
/*读取子设备属性缓存*/
int devmgr_read_attr_cache(const char *devid_or_uuid, const char *attr_name,
char **attr_value)
{
int ret = SERVICE_RESULT_ERR;
dev_info_t *devinfo = devmgr_get_devinfo(devid_or_uuid);
PTR_RETURN(devinfo, SERVICE_RESULT_ERR, CALL_FUCTION_FAILED,
"devmgr_get_devinfo");
os_mutex_lock(devinfo->dev_mutex);
ret = __read_attr_cache(&devinfo->attr_head, attr_name, attr_value);
os_mutex_unlock(devinfo->dev_mutex);
devmgr_put_devinfo_ref(devinfo);
return ret;
}
/*更新子设备属性缓存*/
int devmgr_update_attr_cache(const char *devid_or_uuid, const char *attr_name,
const char *attr_value)
{
int ret = SERVICE_RESULT_ERR;
dev_info_t *devinfo = devmgr_get_devinfo(devid_or_uuid);
PTR_RETURN(devinfo, ret, CALL_FUCTION_FAILED, "devmgr_get_devinfo")
os_mutex_lock(devinfo->dev_mutex);
ret = __update_attr_cache(&devinfo->attr_head, attr_name, attr_value);
os_mutex_unlock(devinfo->dev_mutex);
devmgr_put_devinfo_ref(devinfo);
return ret;
}
void devmgr_free_device_cache(dev_info_t *devinfo)
{
__free_attr_cache_list(&devinfo->attr_head);
}
int devmgr_cache_init()
{
return SERVICE_RESULT_OK;
}
void devmgr_cache_exit()
{
return;
}

View file

@ -0,0 +1,30 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef __DEVMGR_CACHE__H__
#define __DEVMGR_CACHE__H__
#include "devmgr.h"
#include <unistd.h>
#ifdef __cplusplus
extern "C" {
#endif
void __dump_attr_cache(dlist_t *attr_head);
int devmgr_get_attr_cache(const char *devid_or_uuid, const char *attr_name,
char *attr_value_buff, int buff_size);
int devmgr_read_attr_cache(const char *devid_or_uuid, const char *attr_name,
char **attr_value);
int devmgr_update_attr_cache(const char *devid_or_uuid, const char *attr_name,
const char *attr_value);
void devmgr_free_device_cache(dev_info_t *devinfo);
int devmgr_cache_init();
void devmgr_cache_exit();
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,99 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <aos/errno.h>
#include "devmgr_common.h"
#include "service.h"
#define IEEE_ADDR_STRING_FMT "%02x%02x%02x%02x%02x%02x%02x%02x"
int bytes_2_hexstr(const uint8_t *buf, int buf_len, char *hexstr,
int hex_buf_len)
{
int len = 0;
int index = 0;
if (hex_buf_len <= buf_len * 2) {
return SERVICE_RESULT_ERR;
}
while (index < buf_len) {
len += snprintf(hexstr + len, hex_buf_len - len, "%02x", *(buf + index));
index++;
}
*(hexstr + len) = '\0';
return SERVICE_RESULT_OK;
}
int hexstr_2_bytes(const char *hexstr, uint8_t *buf, int *buf_len)
{
int len = 0;
int index = 0;
unsigned int arr = 0;
if (strlen(hexstr) / 2 > *buf_len + 1) {
return SERVICE_RESULT_ERR;
}
while (len < strlen(hexstr)) {
if (1 != sscanf(hexstr, "%02x", &arr )) {
return SERVICE_RESULT_ERR;
}
*(buf + index) = (uint8_t) * (&arr);
index++;
len += 2;
}
*buf_len = index;
return SERVICE_RESULT_OK;
}
int get_ieeeaddr_by_string(char *ieeeaddr_string,
uint8_t extaddr[IEEE_ADDR_BYTES])
{
int i;
unsigned int arr[8] = {0};
if (NULL == ieeeaddr_string) {
return SERVICE_RESULT_ERR;
}
if (IEEE_ADDR_BYTES != sscanf(ieeeaddr_string, IEEE_ADDR_STRING_FMT,
&arr[0], &arr[1], &arr[2], &arr[3],
&arr[4], &arr[5], &arr[6], &arr[7])) {
return SERVICE_RESULT_ERR;
}
for (i = 0; i < 8; i++) {
extaddr[i] = (uint8_t)arr[i];
}
return SERVICE_RESULT_OK;
}
char *get_ieeeaddr_string_by_extaddr(uint8_t extaddr[IEEE_ADDR_BYTES],
char *ieeeaddr_buf, int buf_len)
{
int len = 0;
len = snprintf(ieeeaddr_buf, buf_len, IEEE_ADDR_STRING_FMT, extaddr[0],
extaddr[1], extaddr[2],
extaddr[3], extaddr[4], extaddr[5], extaddr[6], extaddr[7]);
if (len == buf_len) {
return NULL;
}
return ieeeaddr_buf;
}

View file

@ -0,0 +1,33 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef __DEVMGR_COMMON_UT__
#define __DEVMGR_COMMON_UT__
#include <stdint.h>
#include <unistd.h>
#include "alink_export_zigbee.h"
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
int bytes_2_hexstr(const uint8_t *buf, int buf_len, char *hexstr,
int hex_buf_len);
int hexstr_2_bytes(const char *hexstr, uint8_t *buf, int *buf_len);
int get_ieeeaddr_by_string(char *ieeeaddr_string,
uint8_t extaddr[IEEE_ADDR_BYTES]);
char *get_ieeeaddr_string_by_extaddr(uint8_t extaddr[IEEE_ADDR_BYTES],
char *ieeeaddr_buf, int buf_len);
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif
#endif

View file

@ -0,0 +1,281 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <time.h>
#include "devmgr.h"
#include "devmgr_router.h"
#include "aos/aos.h"
#include "json_parser.h"
#include "msdp.h"
#include "service_manager.h"
#include "connectivity_manager.h"
#include "digest_algorithm.h"
#include "config.h"
#define MODULE_NAME MODULE_NAME_DEVMGR
extern void *devlist_lock;
extern dlist_t dev_head;
static int router_register_device(dev_info_t *devinfo)
{
int ret;
char tx_buff[512] = {0};
char result[128] = {0};
alink_data_t data = {METHOD_DEVICE_REGISTER_SUB_WIFI, tx_buff};
if (sizeof(tx_buff) == snprintf(tx_buff, sizeof(tx_buff),
PARAMS_DEVICE_REGISTER_SUB_WIFI_FMT,
devinfo->router_base.name,
devinfo->router_base.model,
devinfo->router_base.ostype,
devinfo->router_base.category,
devinfo->dev_base.u.ether_mac,
devinfo->router_base.manufacturer)) {
return SERVICE_RESULT_ERR;
}
log_debug("send:%s", tx_buff);
ret = ((service_t *)sm_get_service("accs"))->get((void *)&data, sizeof(data),
result, sizeof(result));
if (SERVICE_RESULT_OK == ret) {
int len = 0;
char *json_str = json_get_value_by_name(result, strlen(result), JSON_KEY_UUID,
&len, NULL);
if (NULL == json_str) {
log_error("get uuid fail, result data = %s", result);
return SERVICE_RESULT_ERR;
}
strncpy(devinfo->dev_base.uuid, json_str,
sizeof(devinfo->dev_base.uuid) > len ? len : sizeof(devinfo->dev_base.uuid));
log_info("register device success, uuid:%s", devinfo->dev_base.uuid);
}
return ret;
}
static int router_login_device(dev_info_t *devinfo)
{
int ret;
char tx_buff[512] = {0};
char result[128] = {0};
alink_data_t data = {METHOD_DEVICE_ATTACH_SUB_WIFI, tx_buff};
if (devinfo->dev_base.uuid[0] == '\0') {
return SERVICE_RESULT_ERR;
}
if (sizeof(tx_buff) == snprintf(tx_buff, sizeof(tx_buff),
PARAMS_DEVICE_ATTACH_SUB_WIFI_FMT,
config_get_main_uuid(),
devinfo->dev_base.uuid)) {
return SERVICE_RESULT_ERR;
}
log_debug("send:%s", tx_buff);
ret = ((service_t *)sm_get_service("accs"))->get((void *)&data, sizeof(data),
result, sizeof(result));
if (SERVICE_RESULT_OK == ret) {
int len = 0;
char *json_str = json_get_value_by_name(result, strlen(result), JSON_KEY_CODE,
&len, NULL);
if (NULL == json_str) {
log_error("get rsp code fail, result data = %s", result);
return SERVICE_RESULT_ERR;
}
log_info("attach wifi device result, code:%s", json_str);
}
return ret;
}
static int router_logout_device(dev_info_t *devinfo)
{
int ret;
char tx_buff[512] = {0};
char result[128] = {0};
alink_data_t data = {METHOD_DEVICE_DETACH_SUB_WIFI, tx_buff};
if (devinfo->dev_base.uuid[0] == '\0') {
return SERVICE_RESULT_ERR;
}
if (sizeof(tx_buff) == snprintf(tx_buff, sizeof(tx_buff),
PARAMS_DEVICE_DETACH_SUB_WIFI_FMT,
config_get_main_uuid(),
devinfo->dev_base.uuid)) {
return SERVICE_RESULT_ERR;
}
log_debug("send:%s", tx_buff);
ret = ((service_t *)sm_get_service("accs"))->get((void *)&data, sizeof(data),
result, sizeof(result));
if (SERVICE_RESULT_OK == ret) {
int len = 0;
char *json_str = json_get_value_by_name(result, strlen(result), JSON_KEY_CODE,
&len, NULL);
if (NULL == json_str) {
log_error("get rsp code fail, result data = %s", result);
return SERVICE_RESULT_ERR;
}
log_info("deattach wifi device result, code:%s", json_str);
}
return ret;
}
int router_network_down_event_handler(dev_info_t *devinfo)
{
int ret = SERVICE_RESULT_OK;
switch (devinfo->cloud_state) {
case DEVICE_STATE_LOGOUTED:
//nothing todo
break;
case DEVICE_STATE_REGISTERED:
case DEVICE_STATE_LOGINED:
ret = router_logout_device(devinfo);
if (ret != SERVICE_RESULT_OK) {
break;
}
devinfo->cloud_state = DEVICE_STATE_LOGOUTED;
break;
default:
break;
}
return ret;
}
int router_network_up_event_handler(dev_info_t *devinfo)
{
int ret = SERVICE_RESULT_OK;
switch (devinfo->cloud_state) {
case DEVICE_STATE_LOGOUTED:
case DEVICE_STATE_INITIAL:
ret = router_register_device(devinfo);
if (ret != SERVICE_RESULT_OK) {
goto ERR;
}
devinfo->cloud_state = DEVICE_STATE_REGISTERED;
case DEVICE_STATE_REGISTERED:
ret = router_login_device(devinfo);
if (ret != SERVICE_RESULT_OK) {
goto ERR;
}
devinfo->cloud_state = DEVICE_STATE_LOGINED;
break;
default:
break;
}
ERR:
log_error("ret = %d.", ret);
return ret;
}
int router_link_state_event_handler(dev_info_t *devinfo, link_state_t state)
{
int ret = SERVICE_RESULT_ERR;
devinfo->link_state = state;
if (LINK_STATE_ONLINE == state) {
ret = router_network_up_event_handler(devinfo);
RET_LOG(ret, CALL_FUCTION_FAILED, "devmgr_network_up_event_handler");
} else if (LINK_STATE_OFFLINE == state) {
ret = router_network_down_event_handler(devinfo);
RET_LOG(ret, CALL_FUCTION_FAILED, "devmgr_network_down_event_handler");
} else {
log_error("unknown link state, state:%d", state);
}
return ret;
}
static int router_network_event_cb(network_event_t event)
{
//±éÀúÉ豸£¬Öð¸ö×¢²á¡¢attatch
int ret = SERVICE_RESULT_OK;
dev_info_t *pos;
dlist_t *next = NULL;
os_mutex_lock(devlist_lock);
dlist_for_each_entry_safe(&dev_head, next, pos, dev_info_t, list_node) {
if (pos->dev_base.dev_type != DEV_TYPE_WIFI) {
continue;
}
switch (event) {
case NETWORK_EVENT_DOWN: //network disconnected
ret = router_network_down_event_handler(pos);
break;
case NETWORK_EVENT_UP: //network connected
ret = router_network_up_event_handler(pos);
break;
default:
break;
}
}
os_mutex_unlock(devlist_lock);
return ret;
}
static int devmgr_listener(int type, void *data, int dlen, void *result,
int *rlen)
{
if (type == SERVICE_EVENT) {
int st = *((int *)data);
log_trace("DEVMGR recv %s, %s", sm_code2string(type), sm_code2string(st));
if (st == SERVICE_STATE_READY) {
router_network_event_cb(NETWORK_EVENT_UP);
} else if (st == SERVICE_STATE_STOP || st == SERVICE_STATE_INIT) {
router_network_event_cb(NETWORK_EVENT_DOWN);
}
}
return EVENT_IGNORE;
}
int devmgr_router_init()
{
log_trace("devmgr_router init success.");
sm_attach_service("accs", &devmgr_listener);
return 0;
}
void devmgr_router_exit()
{
sm_detach_service("accs", &devmgr_listener);
log_trace("devmgr_router exit.");
}

View file

@ -0,0 +1,43 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef __DEVMGR_ROUTER__H__
#define __DEVMGR_ROUTER__H__
#include <unistd.h>
#ifdef __cplusplus
extern "C" {
#endif
#define METHOD_DEVICE_REGISTER_SUB_WIFI "registerSubDevice"
#define METHOD_DEVICE_UNREGISTER_SUB_WIFI "unregisterDevice"
#define METHOD_DEVICE_ATTACH_SUB_WIFI "attachSubDevice"
#define METHOD_DEVICE_DETACH_SUB_WIFI "detachSubDevice"
#define PARAMS_DEVICE_REGISTER_SUB_WIFI_FMT ("{\"name\":\"%s\","\
"\"model\":\"%s\","\
"\"type\":\"%s\","\
"\"category\":\"%s\","\
"\"sn\":\"\","\
"\"mac\":\"%s\","\
"\"manufacturer\":\"%s\","\
"\"version\":\"\"}")
#define PARAMS_DEVICE_ATTACH_SUB_WIFI_FMT "{\"uuid\":\"%s\", \"clients\":[\"%s\"]}"
#define PARAMS_DEVICE_DETACH_SUB_WIFI_FMT "{\"uuid\":\"%s\", \"clients\":[\"%s\"]}"
int router_network_up_event_handler(dev_info_t *devinfo);
int router_network_down_event_handler(dev_info_t *devinfo);
int router_link_state_event_handler(dev_info_t *devinfo, link_state_t state);
int devmgr_router_init();
void devmgr_router_exit();
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,196 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <aos/errno.h>
#include "devmgr.h"
#include "devmgr_alink.h"
#include "devmgr_cache.h"
dev_base_t dev_base1;
dev_base_t dev_base2;
void __dump_device_list();
void *alink_cb_func[ALINK_CB_MAX_NUM] = {NULL};
int alink_unregister_service(const char *name)
{
return 0;
}
int stdd_zbnet_remove_device_cb(uint8_t ieee_addr[8])
{
log_trace("remove device: %02x%02x%02x%02x%02x%02x%02x%02x",
ieee_addr[0], ieee_addr[1], ieee_addr[2], ieee_addr[3],
ieee_addr[4], ieee_addr[5], ieee_addr[6], ieee_addr[7]);
return 0;
}
int stdd_zigbee_permit_join(uint8_t duration)
{
return 0;
}
int stdd_zbnet_supervision_interval_cb(uint8_t ieee_addr[8], uint8_t interval)
{
return 0;
}
int get_device_profile_file(uint8_t dev_type, uint32_t model_id,
char file_name[], int max_name_length)
{
strcpy(file_name, "test_attr_profile.lua");
return 0;
}
int fmgr_get_attr_profile(char file_name[], int max_name_length)
{
sprintf(file_name, "test_device_profile.lua");
return 0;
}
int get_kv(const char *key, void *value_buf, int *buf_len)
{
int ret = 0;
if (strcmp(key, "device_01") == 0) {
memcpy(value_buf, &dev_base1, sizeof(dev_base1));
} else if (strcmp(key, "device_02") == 0) {
memcpy(value_buf, &dev_base2, sizeof(dev_base2));
} else {
ret = -1;
}
return ret;
}
int set_kv_in_flash(const char *key, const void *value_buf, int buf_len,
int flag)
{
return 0;
}
int remove_kv(const char *key)
{
return 0;
}
int alink_register_attribute(const char *name,
void *get_cb,
void *set_cb)
{
return 0;
}
int alink_register_service(const char *name, void *exec_cb)
{
return 0;
}
void stdd_forward_device_status(dev_info_t *devinfo,
const char *attr_name, const char *attr_value)
{
log_trace("forward device state, devid:%s, uuid:%s, attr_name:%s, attr_value:%s",
devinfo->dev_base.dev_id, devinfo->dev_base.uuid, attr_name, attr_value);
}
int32_t stdd_add_device_profile(uint32_t model_id, const char *profile_path)
{
log_trace("add device profile, profile_path:%s", profile_path);
return 0;
}
#define UUID_1 "123412412312312312312sdfsdgdgdew"
#define UUID_2 "5465465465465464865465asdfa12312"
void dev_list_init()
{
memset(&dev_base1, 0, sizeof(dev_base1));
memset(&dev_base2, 0, sizeof(dev_base2));
dev_base1.dev_type = DEV_TYPE_ZIGBEE;
dev_base1.model_id = 0x01010101;
memcpy(dev_base1.u.ieee_addr, "12345678", 8);
strncpy(dev_base1.rand, "rand_01", strlen("rand_01"));
strncpy(dev_base1.sign, "sign_01", strlen("sign_01"));
strcpy(dev_base1.uuid, UUID_1);
bytes_2_hexstr(dev_base1.u.ieee_addr, 8, dev_base1.dev_id,
sizeof(dev_base1.dev_id));
//log_trace("dev_base1.devid:%s", dev_base1.dev_id);
dev_base2.dev_type = DEV_TYPE_ZIGBEE;
dev_base2.model_id = 0x02020202;
memcpy(dev_base2.u.ieee_addr, "87654321", 8);
strncpy(dev_base2.rand, "rand_02", strlen("rand_02"));
strncpy(dev_base2.sign, "sign_02", strlen("sign_02"));
strcpy(dev_base2.uuid, UUID_2);
bytes_2_hexstr(dev_base2.u.ieee_addr, 8, dev_base2.dev_id,
sizeof(dev_base2.dev_id));
//log_trace("dev_base2.devid:%s", dev_base2.dev_id);
}
void dev_list_ut()
{
char ieee_addr[8];
//devmgr_delete_device(UUID_1);
//devmgr_delete_device(UUID_2);
memcpy(ieee_addr, "12345678", 8);
devmgr_leave_zigbee_device(ieee_addr);
__dump_device_list();
}
#define ATTR_NAME_1 "attr_1"
#define ATTR_NAME_2 "attr_2"
#define ATTR_VALUE_1 "value_1"
#define ATTR_VALUE_2 "value_2"
void dev_cache_ut()
{
int ret = SERVICE_RESULT_ERR;
ret = devmgr_update_attr_cache(UUID_1, ATTR_NAME_1, ATTR_VALUE_1);
RET_LOG(ret, "update attr cache fail, uuid:%s, attr_name:%s", UUID_1,
ATTR_NAME_1);
ret = devmgr_update_attr_cache(UUID_1, ATTR_NAME_2, ATTR_VALUE_2);
RET_LOG(ret, "update attr cache fail, uuid:%s, attr_name:%s", UUID_1,
ATTR_NAME_2);
ret = devmgr_update_attr_cache(UUID_2, ATTR_NAME_1, ATTR_VALUE_1);
RET_LOG(ret, "update attr cache fail, uuid:%s, attr_name:%s", UUID_1,
ATTR_NAME_1);
ret = devmgr_update_attr_cache(UUID_2, ATTR_NAME_2, ATTR_VALUE_2);
RET_LOG(ret, "update attr cache fail, uuid:%s, attr_name:%s", UUID_1,
ATTR_NAME_2);
char *attr_value = NULL;
ret = devmgr_read_attr_cache(UUID_1, ATTR_NAME_1, &attr_value);
RET_LOG(ret, "read attr cache fail, uuid:%s, attr_name:%s", UUID_1,
ATTR_NAME_1);
if (attr_value) {
log_trace("attr_name:%s, attr_value:%s", ATTR_NAME_1, attr_value);
}
}
int main(int argc, char *argv[])
{
int ret = SERVICE_RESULT_ERR;
dev_list_init();
ret = devmgr_init();
RET_RETURN(ret, "devmgr_init fail");
dev_cache_ut();
dev_list_ut();
return 0;
}

View file

@ -0,0 +1,188 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef __DEVMGR_UT__H__
#define __DEVMGR_UT__H__
#include <stdint.h>
#include <unistd.h>
#include "alink_export_zigbee.h"
#ifdef __cplusplus
extern "C" {
#endif
#define os_mutex_init() \
((void *)0x010101010)
#define os_mutex_lock(mutex)
#define os_mutex_unlock(mutex)
#define os_mutex_destroy(mutex) (mutex = NULL)
#define CALL_FUCTION_FAILED "Call function \"%s\" failed\n"
#define MAX_UUID_LEN 33
#define MAX_ATTR_NAME_LEN 80
#define MAX_SERVICE_NAME_LEN 80
#define MAX_ALINKGW_ATTR_HANDLER 64
#define MAX_ALINKGW_SERVICE_HANDLER 32
#define ALINKGW_MAX_VENDOR_CALLBACK_REMALLOC_COUNT 4 //回调函数返回buff不够的情况下最多尝试4次分配内存
#define JSON_KEY_UUID "uuid"
#define JSON_KEY_ATTRSET "attrSet"
#define JSON_KEY_SERVICE "service"
#define JSON_KEY_VALUE "value"
#define JSON_KEY_WHEN "when"
#define JSON_KEY_RESULT "result"
#define JSON_KEY_CODE "code"
#define JSON_KEY_ARGS "args"
#define JSON_KEY_SET "set"
#define JSON_KEY_EXTRA "extra"
#define log_print(fmt, args...) \
do { \
printf("[DEVMGR] %s:%4d %20s: " fmt "\n", __FILE__, __LINE__, __func__, ##args); \
} while(0)
#define log_fatal(FMT, args...) log_print(FMT, ##args)
#define log_error(FMT, args...) log_print(FMT, ##args)
#define log_info(FMT, args...) log_print(FMT, ##args)
#define log_dump(FMT, args...) log_print(FMT, ##args)
#define log_debug(FMT, args...) log_print(FMT, ##args)
#define log_trace(FMT, args...) log_print(FMT, ##args)
#define RET_FAILED(ret) (ret != SERVICE_RESULT_OK)
#define RET_GOTO(Ret,gotoTag,strError, args...) \
{\
if ( RET_FAILED(Ret) ) \
{ \
log_trace(strError, ##args); \
goto gotoTag; \
}\
}
#define RET_FALSE(Ret,strError,args...) \
{\
if ( RET_FAILED(Ret) ) \
{ \
log_trace(strError, ##args); \
return false; \
}\
}
#define RET_RETURN(Ret,strError,args...) \
{\
if ( RET_FAILED(Ret) ) \
{ \
log_trace(strError, ##args); \
return Ret; \
}\
}
#define RET_LOG(Ret,strError,args...) \
{\
if ( RET_FAILED(Ret) ) \
{ \
log_error(strError, ##args); \
}\
}
#define PTR_RETURN(Pointer,Ret,strError,args...) \
{\
if ( !Pointer) \
{ \
log_trace(strError, ##args); \
return Ret; \
}\
}
#define PTR_FALSE(Pointer,strError,args...) \
{\
if ( !Pointer) \
{ \
log_trace(strError, ##args); \
return FALSE; \
}\
}
#define PTR_LOG(Pointer,strError,args...) \
{\
if ( !Pointer) \
{ \
log_error(strError, ##args); \
}\
}
#define PTR_GOTO(Pointer, gotoTag, strError, args...) \
{\
if ( !Pointer) \
{ \
log_trace(strError, ##args); \
goto gotoTag; \
}\
}
#define POINTER_RETURN(Pointer,strError,args...) \
{\
if ( !Pointer) \
{ \
log_trace(strError, ##args); \
return Pointer; \
}\
}
enum SERVICE_CODE {
SERVICE_BUFFER_INSUFFICENT = -3,
SERVICE_CODE_UNKNOWN = -2,
SERVICE_RESULT_ERR = -1,
SERVICE_RESULT_OK = 0,
SERVICE_CODE_BEGIN = 0x0100,
SERVICE_EVENT,
SERVICE_DATA,
SERVICE_CONN_INIT,
SERVICE_CONN_READY,
SERVICE_CONN_CLOSE,
SERVICE_ATTACH,
SERVICE_DETACH,
SERVICE_STATE_INIT,
SERVICE_STATE_PREPARE,
SERVICE_STATE_READY,
SERVICE_STATE_BUSY,
SERVICE_STATE_STOP,
SERVICE_CODE_END = 0x01FF,
};
typedef struct alink_data {
char *method;
char *data;
} alink_data_t;
#define ALINK_CODE_ERROR_SIGN (3074)
extern void *alink_cb_func[ALINK_CB_MAX_NUM];
int alink_unregister_service(const char *name);
int get_device_profile_file(uint8_t dev_type, uint32_t model_id,
char file_name[], int max_name_length);
int fmgr_get_global_profile(char file_name[], int max_name_length);
int get_kv(const char *key, void *value_buf, *int buf_len);
int set_kv_in_flash(const char *key, const void *value_buf, int buf_len,
int flag);
int remove_kv(const char *key);
int alink_register_attribute(const char *name,
void *get_cb,
void *set_cb);
int alink_register_service(const char *name, void *exec_cb);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,9 @@
src = Split('''
devmgr_alink.c
devmgr_common.c
devmgr.c
devmgr_cache.c
devmgr_router.c
''')
component = aos_component('devmgr', src)