Commit 8c3bbd07 authored by chen.weican's avatar chen.weican

【修改内容】1,增加gateway的配置文件;2,去掉kk_sub_tsl.c,同一改用kk_device_manage里的接口

【提交人】陈伟灿
parent a615faf9
......@@ -291,7 +291,6 @@ APPLICATION_FILES= \
./ZB/kk_plat_ota.c\
./ZB/kk_rgb_hsl_convert.c\
./kk_test.c\
./kk_sub_tsl.c\
./rpc_api/src/rpc_common.c\
./rpc_api/src/rpc_onoff.c\
./rpc_api/src/rpc_global_cmd.c\
......
{
"productCode":"2",
"config":[
{
"identity":"NetChannelState",
"endpoint":1,
"cluster":"0x0000",
"attribute":"0x0000",
"reportFunc":"",
"controlFunc":"kk_permit_join"
}
]
}
\ No newline at end of file
......@@ -771,7 +771,6 @@ void kk_rpc_report_attribute(EmberEUI64 eui64,
{
int i,j,num,status;
char macString[19] = {0};
sub_dev_node_t *node = NULL;
char * pCode;
......@@ -788,8 +787,11 @@ void kk_rpc_report_attribute(EmberEUI64 eui64,
}
void kk_device_gateway_add(EmberEUI64 eui64)
{
kk_device_config_map_add("2");
kk_device_table_add(eui64,0,"2",0);
}
#ifndef __KK_DEVICE_MANAGER_H
#define __KK_DEVICE_MANAGER_H
#include "kk_test.h"
#include "kk_sub_tsl.h"
#include "kk_product_code.h"
#include "kk_zb_com.h"
......
......@@ -138,8 +138,6 @@ void kk_device_table_add(EmberEUI64 mac,EmberNodeId nodeId,const char *productCo
emberAfDebugPrint("mac:");
emberAfPrintBigEndianEui64(mac);
kk_sub_tsl_add(mac,productCode);
if(kk_device_find_by_node(nodeId)!=NULL){
emberAfDebugPrintln(" is already in device table!!!");
kk_print_device_table();
......
......@@ -6,20 +6,19 @@ static void kk_msg_report(cJSON *data,char *msgtype,char *method,EmberEUI64 mac)
static uint16_t msgid;
char msgIdString[10]= {0};
char macString[19] = {0};
sub_dev_node_t *node = NULL;
int res = 0;
kk_device_table_s *dev =NULL;
rpc_eui64ToString(mac,macString);
res = kk_sub_tsl_get_device_by_mac(macString, &node);
if (res != SUCCESS_RETURN) {
printf("[%s][%d]kk_rpc_send_message error!!!\n",__FUNCTION__,__LINE__);
dev = kk_device_find_by_mac(mac);
if (dev == NULL) {
printf("[%s][%d]kk_msg_report error!!!\n",__FUNCTION__,__LINE__);
return;
}
cJSON *info = rpc_cJSON_CreateObject();
if(info != NULL){
rpc_cJSON_AddStringToObject(info, "msgType",msgtype);
rpc_cJSON_AddStringToObject(info, "productCode",node->productCode);
rpc_cJSON_AddStringToObject(info, "productCode",dev->productCode);
rpc_cJSON_AddStringToObject(info, "deviceCode",macString);
}
cJSON *payload = rpc_cJSON_CreateObject();
......@@ -73,7 +72,6 @@ void kk_msg_report_dev_joined(EmberEUI64 mac,const char* productCode)
rpc_cJSON_AddStringToObject(devicesJson, "deviceCode",macString);
rpc_cJSON_AddStringToObject(devicesJson, "mac",macString);
kk_sub_tsl_add(mac,productCode);
emberAfGetEui64(localEui64);
kk_msg_report_joined(devicesJson,localEui64);
}
......@@ -82,22 +80,20 @@ void kk_msg_report_dev_leave(EmberEUI64 mac)
{
int res = 0;
cJSON* devicesJson;
sub_dev_node_t *node = NULL;
EmberEUI64 localEui64 = {0};
char macString[KK_EUI64_STRING_LENGTH];
kk_device_table_s *dev =NULL;
rpc_eui64ToString(mac,macString);
res = kk_sub_tsl_get_device_by_mac(macString, &node);
if (res != SUCCESS_RETURN) {
emberAfDebugPrintln("[%s][%d]kk msg send error!!!\n",__FUNCTION__,__LINE__);
dev = kk_device_find_by_mac(mac);
if (dev == NULL) {
emberAfDebugPrintln("[%s][%d]kk_msg_report_dev_leave error!!!\n",__FUNCTION__,__LINE__);
return;
}
devicesJson = rpc_cJSON_CreateObject();
rpc_cJSON_AddStringToObject(devicesJson, "productCode",node->productCode);
rpc_cJSON_AddStringToObject(devicesJson, "productCode",dev->productCode);
rpc_cJSON_AddStringToObject(devicesJson, "deviceCode",macString);
emberAfGetEui64(localEui64);
kk_msg_report_leave(devicesJson,localEui64);
kk_sub_tsl_delete(mac);
kk_device_table_delete(mac);
kk_device_db_delete(mac);
}
......
......@@ -7,7 +7,6 @@
#include ".././jsonrpc/rpccJSON.h"
#include "com_api.h"
#include "kk_zb_com.h"
#include "kk_sub_tsl.h"
#define KK_IPC_VERSION "1.0"
......
......@@ -111,7 +111,6 @@ void kk_tsl_report_attribute(EmberEUI64 eui64,
uint8_t *data)
{
int i,j,num,status;
sub_dev_node_t *node = NULL;
int res = 0;
char macString[RPC_EUI64_STRING_LENGTH];
kk_device_table_s *dev;
......
......@@ -35,15 +35,13 @@ cJSON *kk_topo_change_operation(jrpc_context * ctx, cJSON *params, cJSON *id,cJS
}
}
}
return rpc_cJSON_CreateNumber(res);
error_return:
return rpc_cJSON_CreateNull();
}
int kk_tsl_utils_memtok(_IN_ char *input, _IN_ char *delimiter, _IN_ int index, _OU_ int *offset)
int kk_tsl_utils_memtok( char *input, char *delimiter, int index, int *offset)
{
int item_index = 0;
int count = 0;
......@@ -103,7 +101,6 @@ cJSON *kk_tsl_property_operation(jrpc_context * ctx, cJSON *params, cJSON *id,cJ
}
item = &dev_info->item;
while(item!=NULL){
rev = kk_tsl_utils_memtok(item->identity,'.',2,&startIdx2);
if(!rev){
kk_tsl_utils_memtok(item->identity,'.',1,&startIdx1);
......
......@@ -24,7 +24,8 @@ void kk_rpc_test(void);
{"kk_tsl_set_colorlight_RGB_red",kk_tsl_set_colorlight_RGB_red},\
{"kk_tsl_set_colorlight_RGB_green",kk_tsl_set_colorlight_RGB_green},\
{"kk_tsl_set_colorlight_RGB_blue",kk_tsl_set_colorlight_RGB_blue},\
{"kk_tsl_set_colorlight_Brightness",kk_tsl_set_colorlight_Brightness},\
{"kk_tsl_set_colorlight_Brightness",kk_tsl_set_colorlight_Brightness},\
{"kk_permit_join",kk_permit_join},\
}
#define KK_RPC_REPORT_FUNCTION_TABLE {\
......
#include "kk_sub_tsl.h"
typedef unsigned char EmberEUI64[8];
typedef struct {
void *mutex;
int sub_devid;
struct list_head dev_list;
} kk_sub_dev_ctx_t;
static kk_sub_dev_ctx_t g_sub_dev_mgr = {0};
static kk_sub_dev_ctx_t * _sub_dev_get_ctx(void)
{
return &g_sub_dev_mgr;
}
static void _sub_dev_mutex_lock(void)
{
kk_sub_dev_ctx_t *ctx = _sub_dev_get_ctx();
if (ctx->mutex) {
HAL_MutexLock(ctx->mutex);
}
}
static void _sub_dev_mutex_unlock(void)
{
kk_sub_dev_ctx_t *ctx = _sub_dev_get_ctx();
if (ctx->mutex) {
HAL_MutexUnlock(ctx->mutex);
}
}
int kk_tsl_init(EmberEUI64 mac)
{
int res = 0;
kk_sub_dev_ctx_t *ctx = _sub_dev_get_ctx();
ctx->mutex = HAL_MutexCreate();
if (ctx->mutex == NULL) {
return FAIL_RETURN;
}
ctx->sub_devid = 1;
INIT_LIST_HEAD(&ctx->dev_list);
kk_sub_tsl_add(mac,"2");
//usleep(1000000);
//kk_test();
return SUCCESS_RETURN;
}
static int _kk_tsl_check_exist(const char *deviceCode)
{
sub_dev_node_t *search_node = NULL;
kk_sub_dev_ctx_t *ctx = _sub_dev_get_ctx();
if(deviceCode == NULL){
return INVALID_PARAMETER;
}
list_for_each_entry(search_node, &ctx->dev_list, linked_list, sub_dev_node_t) {
if ( (strlen(search_node->deviceCode) == strlen(deviceCode)) &&
(memcmp(search_node->deviceCode, deviceCode, strlen(deviceCode)) == 0)) {
/* dm_log_debug("Device Found, Product Key: %s, Device Name: %s", product_key, device_name); */
return SUCCESS_RETURN;
}
}
return FAIL_RETURN;
}
int kk_sub_tsl_add(EmberEUI64 device_mac,const char *productCode)
{
sub_dev_node_t *node = NULL;
kk_sub_dev_ctx_t *ctx = _sub_dev_get_ctx();
char *tsl_str = NULL;
int res = 0;
char macString[19] = {0};
if(productCode == NULL)
{
return INVALID_PARAMETER;
}
rpc_eui64ToString(device_mac,macString);
if(_kk_tsl_check_exist(device_mac) == SUCCESS_RETURN){
return SUCCESS_RETURN;
}
node = malloc(sizeof(sub_dev_node_t));
if (node == NULL) {
return MEMORY_NOT_ENOUGH;
}
_sub_dev_mutex_lock();
memset(node,0,sizeof(sub_dev_node_t) );
memcpy(node->deviceCode, macString, strlen(macString));
memcpy(node->productCode, productCode, strlen(productCode));
INIT_LIST_HEAD(&node->linked_list);
list_add_tail(&node->linked_list, &ctx->dev_list);
_sub_dev_mutex_unlock();
return SUCCESS_RETURN;
}
int kk_sub_tsl_delete(EmberEUI64 device_mac)
{
sub_dev_node_t *node = NULL;
kk_sub_dev_ctx_t *ctx = _sub_dev_get_ctx();
char *tsl_str = NULL;
int res = 0;
char macString[19] = {0};
rpc_eui64ToString(device_mac,macString);
_sub_dev_mutex_lock();
res = kk_sub_tsl_get_device_by_mac(macString, &node);
if (res != SUCCESS_RETURN) {
_sub_dev_mutex_unlock();
return FAIL_RETURN;
}
list_del(&node->linked_list);
free(node);
node = NULL;
_sub_dev_mutex_unlock();
return SUCCESS_RETURN;
}
int kk_sub_tsl_get_device_by_mac(_IN_ const char *deviceCode , _OU_ sub_dev_node_t **node)
{
kk_sub_dev_ctx_t *ctx = _sub_dev_get_ctx();
sub_dev_node_t *search_node = NULL;
list_for_each_entry(search_node, &ctx->dev_list, linked_list, sub_dev_node_t) {
if ((strlen(search_node->deviceCode) == strlen(deviceCode)) &&
(memcmp(search_node->deviceCode, deviceCode, strlen(deviceCode)) == 0)) {
if (node) {
*node = search_node;
}
return SUCCESS_RETURN;
}
}
printf("Device Not Found, device_mac: %s\n", deviceCode);
return FAIL_RETURN;
}
#ifndef _KK_SUB_TSL_H_
#define _KK_SUB_TSL_H_
#include "kk_tsl_common.h"
#include "klist.h"
typedef struct {
char productCode[PRODUCT_TYPE_MAXLEN];
char deviceCode[DEVICE_CODE_MAXLEN];
struct list_head linked_list;
} sub_dev_node_t;
#endif
#include "kk_test.h"
#include "kk_sub_tsl.h"
static void kk_rpc_send_message(cJSON *data,char *msgtype,char *method,EmberEUI64 mac)
{
static uint16_t msgid;
char msgIdString[10]= {0};
char macString[19] = {0};
sub_dev_node_t *node = NULL;
int res = 0;
kk_device_table_s *dev =NULL;
rpc_eui64ToString(mac,macString);
res = kk_sub_tsl_get_device_by_mac(macString, &node);
if (res != SUCCESS_RETURN) {
dev = kk_device_find_by_mac(mac);
if (dev == NULL) {
printf("[%s][%d]kk_rpc_send_message error!!!\n",__FUNCTION__,__LINE__);
return;
}
......@@ -19,7 +18,7 @@ static void kk_rpc_send_message(cJSON *data,char *msgtype,char *method,EmberEUI6
cJSON *info = rpc_cJSON_CreateObject();
if(info != NULL){
rpc_cJSON_AddStringToObject(info, "msgType",msgtype);
rpc_cJSON_AddStringToObject(info, "productCode",node->productCode);
rpc_cJSON_AddStringToObject(info, "productCode",dev->productCode);
rpc_cJSON_AddStringToObject(info, "deviceCode",macString);
}
cJSON *payload = rpc_cJSON_CreateObject();
......@@ -70,22 +69,21 @@ void kk_rpc_reportLeftDevices(EmberEUI64 mac)
{
cJSON* devicesJson;
char macString[RPC_EUI64_STRING_LENGTH];
sub_dev_node_t *node = NULL;
int res = 0;
EmberEUI64 gw_eui64 = {0};
kk_device_table_s *dev =NULL;
rpc_eui64ToString(mac,macString);
res = kk_sub_tsl_get_device_by_mac(macString, &node);
if (res != SUCCESS_RETURN) {
printf("[%s][%d]kk_rpc_send_message error!!!\n",__FUNCTION__,__LINE__);
dev = kk_device_find_by_mac(mac);
if (dev == NULL) {
printf("[%s][%d]kk_rpc_reportLeftDevices error!!!\n",__FUNCTION__,__LINE__);
return;
}
devicesJson = rpc_cJSON_CreateObject();
rpc_cJSON_AddStringToObject(devicesJson, "productCode",node->productCode);
rpc_cJSON_AddStringToObject(devicesJson, "productCode",dev->productCode);
rpc_cJSON_AddStringToObject(devicesJson, "deviceCode",macString);
emberAfGetEui64(gw_eui64);
kk_rpc_report_left_devices(devicesJson,gw_eui64);
kk_sub_tsl_delete(mac);
kk_device_table_delete(mac);
......@@ -109,7 +107,6 @@ void kk_rpc_reportDevices(EmberEUI64 mac,const char* productCode)
rpc_cJSON_AddStringToObject(devicesJson, "deviceCode",macString);
rpc_cJSON_AddStringToObject(devicesJson, "mac",macString);
//
kk_sub_tsl_add(mac,productCode);
emberAfGetEui64(eui64);
kk_rpc_report_devices(devicesJson,eui64);
}
......
// Copyright 2016 Silicon Laboratories, Inc. *80*
#include PLATFORM_HEADER
#ifdef EZSP_HOST
// Includes needed for functions related to the EZSP host
#include "stack/include/error.h"
#include "stack/include/ember-types.h"
#include "app/util/ezsp/ezsp-protocol.h"
#include "app/util/ezsp/ezsp.h"
#include "app/util/ezsp/serial-interface.h"
#include "app/util/zigbee-framework/zigbee-device-common.h"
#else
#include "stack/include/ember.h"
#endif
#include "af.h"
#include "af-main.h"
#include "attribute-storage.h"
#include "common.h"
#include "hal/hal.h"
#include "app/util/serial/command-interpreter2.h"
#include "stack/include/event.h"
#include "app/framework/plugin/concentrator/source-route-host.h"
#include "app/framework/plugin/device-table/device-table.h"
#include "app/framework/plugin/device-table/device-table-internal.h"
#include "app/framework/util/util.h"
#include <stdlib.h>
#include <kk_test.h>
void emAfDeviceTableSave(void);
void emAfDeviceTableLoad(void);
// Framework message send global data
extern uint8_t appZclBuffer[];
extern uint16_t appZclBufferLen;
extern bool zclCmdIsBuilt;
extern EmberApsFrame globalApsFrame;
extern void emAfApsFrameEndpointSetup(uint8_t srcEndpoint,
uint8_t dstEndpoint);
static EmberAfPluginDeviceTableEntry deviceTable[EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE];
EmberStatus emberAfGetChildData(uint8_t index,
EmberChildData *childData);
// Device discovery global declarations
void emAfDeviceTableInitiateRouteRepair(EmberNodeId nodeId);
static void clearDeviceTableIndex(uint16_t index);
EmberAfPluginDeviceTableEntry* emberAfDeviceTablePointer(void)
{
return deviceTable;
}
uint16_t emberAfDeviceTableGetNodeIdFromIndex(uint16_t index)
{
EmberAfPluginDeviceTableEntry *deviceTable = emberAfDeviceTablePointer();
assert(index < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE);
return deviceTable[index].nodeId;
}
uint8_t emAfDeviceTableGetFirstEndpointFromIndex(uint16_t index)
{
assert(index < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE);
return deviceTable[index].endpoint;
}
static void matchReverseEui64(EmberEUI64 eui64a, EmberEUI64 eui64b)
{
uint8_t i;
for (i = 0; i < EUI64_SIZE; i++) {
if (eui64a[i] != eui64b[(EUI64_SIZE - 1) - i]) {
return;
}
}
emberAfCorePrintln("MATCH_EUI: EUI matches backwards");
emberAfCorePrint("A:");
emAfDeviceTablePrintEUI64(eui64a);
emberAfCorePrint(" B:");
emAfDeviceTablePrintEUI64(eui64b);
emberAfCorePrintln("");
}
static void checkNullEui64(EmberEUI64 eui64a, EmberEUI64 eui64b)
{
uint8_t i;
for (i = 0; i < EUI64_SIZE; i++) {
if (eui64a[i] != 0xff
|| eui64b[i] != 0xff) {
return;
}
}
emberAfCorePrintln("MatchEUI: two null EUI");
}
static bool matchEui64(EmberEUI64 a, EmberEUI64 b)
{
checkNullEui64(a, b);
if (MEMCOMPARE(a, b, EUI64_SIZE) == 0) {
return true;
} else {
// Test to see if the EUI64 is backwards
matchReverseEui64(a, b);
return false;
}
}
bool emberAfDeviceTableMatchEui64(EmberEUI64 eui64a, EmberEUI64 eui64b)
{
return matchEui64(eui64a, eui64b);
}
static void unsetEui64(EmberEUI64 eui64)
{
uint8_t i;
for (i = 0; i < 8; i++) {
eui64[i] = 0xff;
}
}
static void clearDeviceTableIndex(uint16_t index)
{
uint8_t i;
assert(index < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE);
deviceTable[index].nodeId = EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_NODE_ID;
unsetEui64(deviceTable[index].eui64);
deviceTable[index].state = EMBER_AF_PLUGIN_DEVICE_TABLE_STATE_NULL;
deviceTable[index].endpoint = 0;
for (i = 0; i < EMBER_AF_PLUGIN_DEVICE_TABLE_CLUSTER_SIZE; i++) {
deviceTable[index].clusterIds[i] = ZCL_NULL_CLUSTER_ID;
}
deviceTable[index].clusterOutStartPosition = 0;
}
void emAfPluginDeviceTableDeleteEntry(uint16_t index)
{
uint16_t currentIndex;
while (index != EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_INDEX) {
currentIndex = index;
// Need to compute the next index before deleting the current one. Or else
// the call to next endpoint will yield a bogus result.
index = emAfDeviceTableFindNextEndpoint(index);
clearDeviceTableIndex(currentIndex);
emberAfPluginDeviceTableIndexRemovedCallback(currentIndex);
}
}
void emAfDeviceTableInit(void)
{
uint16_t i;
for (i = 0; i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE; i++) {
clearDeviceTableIndex(i);
}
}
void emberAfDeviceTableClear(void)
{
emAfDeviceTableInit();
emAfDeviceTableSave();
//emberAfPluginDeviceTableClearedCallback();
}
uint16_t emberAfDeviceTableGetIndexFromEui64AndEndpoint(EmberEUI64 eui64,
uint8_t endpoint)
{
uint16_t i;
for (i = 0; i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE; i++) {
if (matchEui64(deviceTable[i].eui64, eui64)
&& deviceTable[i].endpoint == endpoint) {
return i;
}
}
return EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_INDEX;
}
uint16_t emberAfDeviceTableGetNodeIdFromEui64(EmberEUI64 eui64)
{
uint16_t i;
for (i = 0; i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE; i++) {
if (matchEui64(deviceTable[i].eui64, eui64) ) {
return deviceTable[i].nodeId;
}
}
return EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_NODE_ID;
}
bool emberAfDeviceTableGetEui64FromNodeId(EmberNodeId emberNodeId, EmberEUI64 eui64)
{
uint16_t i;
for (i = 0; i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE; i++) {
if (deviceTable[i].nodeId == emberNodeId) {
MEMCOPY(eui64, deviceTable[i].eui64, EUI64_SIZE);
return true;
}
}
return false;
}
uint16_t emberAfDeviceTableGetIndexFromNodeId(EmberNodeId emberNodeId)
{
uint16_t i;
for (i = 0; i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE; i++) {
if (deviceTable[i].nodeId == emberNodeId) {
return i;
}
}
return EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_INDEX;
}
uint16_t emAfDeviceTableFindFreeDeviceTableIndex(void)
{
uint16_t i;
for (i = 0; i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE; i++) {
if (deviceTable[i].nodeId == EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_NODE_ID) {
return i;
}
}
return EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_INDEX;
}
uint16_t emberAfDeviceTableGetEndpointFromNodeIdAndEndpoint(EmberNodeId emberNodeId,
uint8_t endpoint)
{
uint16_t i;
for (i = 0; i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE; i++) {
if (deviceTable[i].nodeId == emberNodeId
&& deviceTable[i].endpoint == endpoint) {
return i;
}
}
return EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_INDEX;
}
void emAfDeviceTableCopyDeviceTableEntry(uint16_t fromIndex, uint16_t toIndex)
{
EmberAfPluginDeviceTableEntry* from = &(deviceTable[fromIndex]);
EmberAfPluginDeviceTableEntry* to = &(deviceTable[toIndex]);
// make sure the fromIndex is in the valud range.
assert(fromIndex < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE);
// make sure the fromIndex has a valid entry
assert(deviceTable[fromIndex].nodeId
!= EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_NODE_ID);
// make sure the toIndex is in the valud range.
assert(toIndex < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE);
MEMCOPY(to, from, sizeof(EmberAfPluginDeviceTableEntry));
}
uint8_t emAfDeviceTableNumberOfEndpointsFromIndex(uint16_t index)
{
uint8_t count = 0;
uint16_t currentNodeId = emberAfDeviceTableGetNodeIdFromIndex(index);
uint16_t i;
for (i = 0; i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE; i++) {
if (deviceTable[i].nodeId == currentNodeId) {
count++;
}
}
return count;
}
static uint16_t findIndexFromNodeIdAndIndex(uint16_t nodeId, uint16_t index)
{
uint16_t i;
for (i = index; i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE; i++) {
if (nodeId == emberAfDeviceTableGetNodeIdFromIndex(i)) {
return i;
}
}
return EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_INDEX;
}
static uint16_t findIndexFromEui64AndIndex(EmberEUI64 eui64, uint16_t index)
{
uint16_t i;
for (i = index; i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE; i++) {
if (matchEui64(eui64, deviceTable[i].eui64)) {
return i;
}
}
return EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_INDEX;
}
uint16_t emAfDeviceTableFindFirstEndpointNodeId(uint16_t nodeId)
{
return findIndexFromNodeIdAndIndex(nodeId, 0);
}
uint16_t emAfDeviceTableFindNextEndpoint(uint16_t index)
{
return findIndexFromEui64AndIndex(deviceTable[index].eui64,
index + 1);
}
uint16_t emAfDeviceTableFindFirstEndpointIeee(EmberEUI64 eui64)
{
return findIndexFromEui64AndIndex(eui64, 0);
}
uint16_t emberAfDeviceTableGetFirstIndexFromEui64(EmberEUI64 eui64)
{
return emAfDeviceTableFindFirstEndpointIeee(eui64);
}
EmberAfStatus emAfDeviceTableAddNewEndpoint(uint16_t index, uint8_t newEndpoint)
{
uint16_t newIndex = emAfDeviceTableFindFreeDeviceTableIndex();
if (newIndex == EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_INDEX) {
return EMBER_ZCL_STATUS_FAILURE;
}
emAfDeviceTableCopyDeviceTableEntry(index, newIndex);
deviceTable[newIndex].endpoint = newEndpoint;
return EMBER_ZCL_STATUS_SUCCESS;
}
uint16_t emAfDeviceTableFindIndexNodeIdEndpoint(uint16_t nodeId,
uint8_t endpoint)
{
uint16_t i;
for (i = 0; i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE; i++) {
if (deviceTable[i].nodeId == nodeId
&& deviceTable[i].endpoint == endpoint) {
return i;
}
}
return EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_INDEX;
}
EmberAfPluginDeviceTableEntry *emberAfDeviceTableFindDeviceTableEntry(uint16_t index)
{
assert(index < EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_NODE_ID);
return &(deviceTable[index]);
}
void emAfDeviceTableUpdateNodeId(uint16_t currentNodeId, uint16_t newNodeId)
{
uint16_t index = emAfDeviceTableFindFirstEndpointNodeId(currentNodeId);
while (index != EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_INDEX) {
deviceTable[index].nodeId = newNodeId;
index = emAfDeviceTableFindNextEndpoint(index);
}
}
void emAfDeviceTableUpdateDeviceState(uint16_t index, uint8_t newState)
{
while (index != EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_INDEX) {
deviceTable[index].state = newState;
index = emAfDeviceTableFindNextEndpoint(index);
}
}
uint32_t emberAfDeviceTableTimeSinceLastMessage(uint16_t index)
{
uint32_t timeSinceLastMessage = halCommonGetInt32uMillisecondTick();
timeSinceLastMessage -= deviceTable[index].lastMsgTimestamp;
timeSinceLastMessage /= MILLISECOND_TICKS_PER_SECOND;
return timeSinceLastMessage;
}
// AF Framework callbacks. This is where the plugin implements the callbacks.
void emberAfPluginDeviceTableInitCallback(void)
{
emAfDeviceTableInit();
// Load on Init
emAfDeviceTableLoad();
emberAfPluginDeviceTableInitialized();
}
void emberAfPluginDeviceTableStackStatusCallback(EmberStatus status)
{
// If we leave the network, this plugin needs to clear out all of its device
// state.
emberAfCorePrintln("%d %d", status, emberNetworkState());
if (status == EMBER_NETWORK_DOWN
&& emberNetworkState() == EMBER_NO_NETWORK) {
emberAfCorePrintln("DeviceTable: Clear State");
emberAfDeviceTableClear();
//kk_device_table_clear();
}
}
// --------------------------------
// Save/Load the devices
void emAfDeviceTableSave(void)
{
#if defined(EZSP_HOST) && !defined(EMBER_TEST)
FILE *fp;
EmberAfPluginDeviceTableEntry *deviceTable = emberAfDeviceTablePointer();
uint8_t i;
uint8_t j;
// Save device table
fp = fopen("devices.txt", "w");
for (i = 0;
i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE;
i++) {
if (deviceTable[i].nodeId != EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_NODE_ID) {
fprintf(fp,
"%x %x %x ",
deviceTable[i].nodeId,
deviceTable[i].endpoint,
deviceTable[i].deviceId);
for (j = 0; j < 8; j++) {
fprintf(fp, "%x ", deviceTable[i].eui64[j]);
}
for (j = 0; j < EMBER_AF_PLUGIN_DEVICE_TABLE_CLUSTER_SIZE; j++) {
fprintf(fp, "%x ", deviceTable[i].clusterIds[j]);
}
fprintf(fp, "%d ", deviceTable[i].clusterOutStartPosition);
}
}
// Write ffffffff to mark the end
fprintf(fp, "\r\nffffffff\r\n");
fclose(fp);
#endif // defined(EZSP_HOST) && !defined(EMBER_TEST)
}
void emAfDeviceTableLoad(void)
{
#if defined(EZSP_HOST) && !defined(EMBER_TEST)
uint16_t i;
uint16_t j;
FILE *fp;
unsigned int data, data2, data3;
EmberAfPluginDeviceTableEntry *deviceTable = emberAfDeviceTablePointer();
fp = fopen("devices.txt", "r");
if (!fp) {
return;
}
for (i = 0;
i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE && feof(fp) == false;
i++) {
fscanf(fp, "%x %x %x", &data2, &data, &data3);
deviceTable[i].endpoint = (uint8_t) data;
deviceTable[i].nodeId = (uint16_t) data2;
deviceTable[i].deviceId = (uint16_t) data3;
if (deviceTable[i].nodeId != EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_NODE_ID) {
for (j = 0; j < 8; j++) {
fscanf(fp, "%x", &data);
deviceTable[i].eui64[j] = (uint8_t) data;
}
for (j = 0; j < EMBER_AF_PLUGIN_DEVICE_TABLE_CLUSTER_SIZE; j++) {
fscanf(fp, "%x", &data);
deviceTable[i].clusterIds[j] = (uint16_t) data;
}
fscanf(fp, "%d", &data);
deviceTable[i].clusterOutStartPosition = (uint16_t) data;
deviceTable[i].state = EMBER_AF_PLUGIN_DEVICE_TABLE_STATE_JOINED;
//kk_sub_tsl_add(deviceTable[i].eui64,TEST_PRODUCT_CODE);
}
deviceTable[i].lastMsgTimestamp = halCommonGetInt32uMillisecondTick();
}
fclose(fp);
// Set the rest of the device table to null.
for (; i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE; i++) {
deviceTable[i].nodeId = EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_NODE_ID;
}
#endif // #if defined(EZSP_HOST) && !defined(EMBER_TEST)
}
// --------------------------------
// Message send section
// Command to send the CIE IEEE address to the IAS Zone cluster
void emAfDeviceTableSendCieAddressWrite(EmberNodeId nodeId, uint8_t endpoint)
{
EmberEUI64 eui64;
uint8_t outgoingBuffer[15];
uint32_t i;
emberAfGetEui64(eui64);
globalApsFrame.options = EMBER_AF_DEFAULT_APS_OPTIONS;
globalApsFrame.clusterId = ZCL_IAS_ZONE_CLUSTER_ID;
globalApsFrame.sourceEndpoint = 0x01;
globalApsFrame.destinationEndpoint = endpoint;
outgoingBuffer[0] = 0x00;
outgoingBuffer[1] = emberAfNextSequence();
outgoingBuffer[2] = ZCL_WRITE_ATTRIBUTES_COMMAND_ID;
outgoingBuffer[3] = LOW_BYTE(ZCL_IAS_CIE_ADDRESS_ATTRIBUTE_ID);
outgoingBuffer[4] = HIGH_BYTE(ZCL_IAS_CIE_ADDRESS_ATTRIBUTE_ID);
outgoingBuffer[5] = ZCL_IEEE_ADDRESS_ATTRIBUTE_TYPE;
for (i = 0; i < 8; i++) {
outgoingBuffer[6 + i] = eui64[i];
}
emberAfSendUnicast(EMBER_OUTGOING_DIRECT,
nodeId,
&globalApsFrame,
14,
outgoingBuffer);
}
void emberAfDeviceTableCliIndexSendWithEndpoint(uint16_t index,
uint8_t endpoint)
{
EmberNodeId nodeId;
EmberStatus status;
nodeId = emberAfDeviceTableGetNodeIdFromIndex(index);
emAfApsFrameEndpointSetup(emberAfPrimaryEndpoint(), endpoint);
status = emberAfSendUnicast(EMBER_OUTGOING_DIRECT,
nodeId,
&globalApsFrame,
appZclBufferLen,
appZclBuffer);
zclCmdIsBuilt = false;
}
void emberAfDeviceTableCliIndexSend(uint16_t index)
{
uint8_t endpoint = emAfDeviceTableGetFirstEndpointFromIndex(index);
emberAfDeviceTableCliIndexSendWithEndpoint(index, endpoint);
}
void emberAfDeviceTableSend(EmberEUI64 eui64, uint8_t endpoint)
{
uint16_t index = emberAfDeviceTableGetFirstIndexFromEui64(eui64);
if (index != EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_INDEX) {
emberAfDeviceTableCliIndexSendWithEndpoint(index, endpoint);
}
}
void emberAfDeviceTableCommandIndexSendWithEndpoint(uint16_t index,
uint8_t endpoint)
{
EmberNodeId nodeId;
EmberStatus status;
nodeId = emberAfDeviceTableGetNodeIdFromIndex(index);
if (emberAfCurrentCommand() == NULL) {
emAfCommandApsFrame->sourceEndpoint = emberAfPrimaryEndpoint();
} else {
emAfCommandApsFrame->sourceEndpoint = emberAfCurrentEndpoint();
}
emAfCommandApsFrame->destinationEndpoint = endpoint;
emberAfCorePrintln("device table send with ep: 0x%2X, %d",
nodeId,
endpoint);
status = emberAfSendCommandUnicast(EMBER_OUTGOING_DIRECT, nodeId);
zclCmdIsBuilt = false;
}
void emberAfDeviceTableCommandIndexSend(uint16_t index)
{
uint8_t endpoint = emAfDeviceTableGetFirstEndpointFromIndex(index);
emberAfDeviceTableCommandIndexSendWithEndpoint(index, endpoint);
}
void emberAfDeviceTableCommandSendWithEndpoint(EmberEUI64 eui64,
uint8_t endpoint)
{
uint16_t index = emberAfDeviceTableGetFirstIndexFromEui64(eui64);
emberAfDeviceTableCommandIndexSendWithEndpoint(index, endpoint);
}
// Copyright 2016 Silicon Laboratories, Inc. *80*
#include PLATFORM_HEADER
#ifdef EZSP_HOST
// Includes needed for functions related to the EZSP host
#include "stack/include/error.h"
#include "stack/include/ember-types.h"
#include "app/util/ezsp/ezsp-protocol.h"
#include "app/util/ezsp/ezsp.h"
#include "app/util/ezsp/serial-interface.h"
#include "app/util/zigbee-framework/zigbee-device-common.h"
#else
#include "stack/include/ember.h"
#endif
#include "af.h"
#include "af-main.h"
#include "attribute-storage.h"
#include "common.h"
#include "hal/hal.h"
#include "app/util/serial/command-interpreter2.h"
#include "stack/include/event.h"
#include "app/framework/plugin/concentrator/source-route-host.h"
#include "app/framework/plugin/device-table/device-table.h"
#include "app/framework/plugin/device-table/device-table-internal.h"
#include "app/framework/util/util.h"
#include <stdlib.h>
#include <kk_test.h>
void emAfDeviceTableSave(void);
void emAfDeviceTableLoad(void);
// Framework message send global data
extern uint8_t appZclBuffer[];
extern uint16_t appZclBufferLen;
extern bool zclCmdIsBuilt;
extern EmberApsFrame globalApsFrame;
extern void emAfApsFrameEndpointSetup(uint8_t srcEndpoint,
uint8_t dstEndpoint);
static EmberAfPluginDeviceTableEntry deviceTable[EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE];
EmberStatus emberAfGetChildData(uint8_t index,
EmberChildData *childData);
// Device discovery global declarations
void emAfDeviceTableInitiateRouteRepair(EmberNodeId nodeId);
static void clearDeviceTableIndex(uint16_t index);
EmberAfPluginDeviceTableEntry* emberAfDeviceTablePointer(void)
{
return deviceTable;
}
uint16_t emberAfDeviceTableGetNodeIdFromIndex(uint16_t index)
{
EmberAfPluginDeviceTableEntry *deviceTable = emberAfDeviceTablePointer();
assert(index < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE);
return deviceTable[index].nodeId;
}
uint8_t emAfDeviceTableGetFirstEndpointFromIndex(uint16_t index)
{
assert(index < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE);
return deviceTable[index].endpoint;
}
static void matchReverseEui64(EmberEUI64 eui64a, EmberEUI64 eui64b)
{
uint8_t i;
for (i = 0; i < EUI64_SIZE; i++) {
if (eui64a[i] != eui64b[(EUI64_SIZE - 1) - i]) {
return;
}
}
emberAfCorePrintln("MATCH_EUI: EUI matches backwards");
emberAfCorePrint("A:");
emAfDeviceTablePrintEUI64(eui64a);
emberAfCorePrint(" B:");
emAfDeviceTablePrintEUI64(eui64b);
emberAfCorePrintln("");
}
static void checkNullEui64(EmberEUI64 eui64a, EmberEUI64 eui64b)
{
uint8_t i;
for (i = 0; i < EUI64_SIZE; i++) {
if (eui64a[i] != 0xff
|| eui64b[i] != 0xff) {
return;
}
}
emberAfCorePrintln("MatchEUI: two null EUI");
}
static bool matchEui64(EmberEUI64 a, EmberEUI64 b)
{
checkNullEui64(a, b);
if (MEMCOMPARE(a, b, EUI64_SIZE) == 0) {
return true;
} else {
// Test to see if the EUI64 is backwards
matchReverseEui64(a, b);
return false;
}
}
bool emberAfDeviceTableMatchEui64(EmberEUI64 eui64a, EmberEUI64 eui64b)
{
return matchEui64(eui64a, eui64b);
}
static void unsetEui64(EmberEUI64 eui64)
{
uint8_t i;
for (i = 0; i < 8; i++) {
eui64[i] = 0xff;
}
}
static void clearDeviceTableIndex(uint16_t index)
{
uint8_t i;
assert(index < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE);
deviceTable[index].nodeId = EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_NODE_ID;
unsetEui64(deviceTable[index].eui64);
deviceTable[index].state = EMBER_AF_PLUGIN_DEVICE_TABLE_STATE_NULL;
deviceTable[index].endpoint = 0;
for (i = 0; i < EMBER_AF_PLUGIN_DEVICE_TABLE_CLUSTER_SIZE; i++) {
deviceTable[index].clusterIds[i] = ZCL_NULL_CLUSTER_ID;
}
deviceTable[index].clusterOutStartPosition = 0;
}
void emAfPluginDeviceTableDeleteEntry(uint16_t index)
{
uint16_t currentIndex;
while (index != EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_INDEX) {
currentIndex = index;
// Need to compute the next index before deleting the current one. Or else
// the call to next endpoint will yield a bogus result.
index = emAfDeviceTableFindNextEndpoint(index);
clearDeviceTableIndex(currentIndex);
emberAfPluginDeviceTableIndexRemovedCallback(currentIndex);
}
}
void emAfDeviceTableInit(void)
{
uint16_t i;
for (i = 0; i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE; i++) {
clearDeviceTableIndex(i);
}
}
void emberAfDeviceTableClear(void)
{
emAfDeviceTableInit();
emAfDeviceTableSave();
//emberAfPluginDeviceTableClearedCallback();
}
uint16_t emberAfDeviceTableGetIndexFromEui64AndEndpoint(EmberEUI64 eui64,
uint8_t endpoint)
{
uint16_t i;
for (i = 0; i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE; i++) {
if (matchEui64(deviceTable[i].eui64, eui64)
&& deviceTable[i].endpoint == endpoint) {
return i;
}
}
return EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_INDEX;
}
uint16_t emberAfDeviceTableGetNodeIdFromEui64(EmberEUI64 eui64)
{
uint16_t i;
for (i = 0; i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE; i++) {
if (matchEui64(deviceTable[i].eui64, eui64) ) {
return deviceTable[i].nodeId;
}
}
return EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_NODE_ID;
}
bool emberAfDeviceTableGetEui64FromNodeId(EmberNodeId emberNodeId, EmberEUI64 eui64)
{
uint16_t i;
for (i = 0; i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE; i++) {
if (deviceTable[i].nodeId == emberNodeId) {
MEMCOPY(eui64, deviceTable[i].eui64, EUI64_SIZE);
return true;
}
}
return false;
}
uint16_t emberAfDeviceTableGetIndexFromNodeId(EmberNodeId emberNodeId)
{
uint16_t i;
for (i = 0; i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE; i++) {
if (deviceTable[i].nodeId == emberNodeId) {
return i;
}
}
return EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_INDEX;
}
uint16_t emAfDeviceTableFindFreeDeviceTableIndex(void)
{
uint16_t i;
for (i = 0; i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE; i++) {
if (deviceTable[i].nodeId == EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_NODE_ID) {
return i;
}
}
return EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_INDEX;
}
uint16_t emberAfDeviceTableGetEndpointFromNodeIdAndEndpoint(EmberNodeId emberNodeId,
uint8_t endpoint)
{
uint16_t i;
for (i = 0; i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE; i++) {
if (deviceTable[i].nodeId == emberNodeId
&& deviceTable[i].endpoint == endpoint) {
return i;
}
}
return EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_INDEX;
}
void emAfDeviceTableCopyDeviceTableEntry(uint16_t fromIndex, uint16_t toIndex)
{
EmberAfPluginDeviceTableEntry* from = &(deviceTable[fromIndex]);
EmberAfPluginDeviceTableEntry* to = &(deviceTable[toIndex]);
// make sure the fromIndex is in the valud range.
assert(fromIndex < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE);
// make sure the fromIndex has a valid entry
assert(deviceTable[fromIndex].nodeId
!= EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_NODE_ID);
// make sure the toIndex is in the valud range.
assert(toIndex < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE);
MEMCOPY(to, from, sizeof(EmberAfPluginDeviceTableEntry));
}
uint8_t emAfDeviceTableNumberOfEndpointsFromIndex(uint16_t index)
{
uint8_t count = 0;
uint16_t currentNodeId = emberAfDeviceTableGetNodeIdFromIndex(index);
uint16_t i;
for (i = 0; i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE; i++) {
if (deviceTable[i].nodeId == currentNodeId) {
count++;
}
}
return count;
}
static uint16_t findIndexFromNodeIdAndIndex(uint16_t nodeId, uint16_t index)
{
uint16_t i;
for (i = index; i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE; i++) {
if (nodeId == emberAfDeviceTableGetNodeIdFromIndex(i)) {
return i;
}
}
return EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_INDEX;
}
static uint16_t findIndexFromEui64AndIndex(EmberEUI64 eui64, uint16_t index)
{
uint16_t i;
for (i = index; i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE; i++) {
if (matchEui64(eui64, deviceTable[i].eui64)) {
return i;
}
}
return EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_INDEX;
}
uint16_t emAfDeviceTableFindFirstEndpointNodeId(uint16_t nodeId)
{
return findIndexFromNodeIdAndIndex(nodeId, 0);
}
uint16_t emAfDeviceTableFindNextEndpoint(uint16_t index)
{
return findIndexFromEui64AndIndex(deviceTable[index].eui64,
index + 1);
}
uint16_t emAfDeviceTableFindFirstEndpointIeee(EmberEUI64 eui64)
{
return findIndexFromEui64AndIndex(eui64, 0);
}
uint16_t emberAfDeviceTableGetFirstIndexFromEui64(EmberEUI64 eui64)
{
return emAfDeviceTableFindFirstEndpointIeee(eui64);
}
EmberAfStatus emAfDeviceTableAddNewEndpoint(uint16_t index, uint8_t newEndpoint)
{
uint16_t newIndex = emAfDeviceTableFindFreeDeviceTableIndex();
if (newIndex == EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_INDEX) {
return EMBER_ZCL_STATUS_FAILURE;
}
emAfDeviceTableCopyDeviceTableEntry(index, newIndex);
deviceTable[newIndex].endpoint = newEndpoint;
return EMBER_ZCL_STATUS_SUCCESS;
}
uint16_t emAfDeviceTableFindIndexNodeIdEndpoint(uint16_t nodeId,
uint8_t endpoint)
{
uint16_t i;
for (i = 0; i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE; i++) {
if (deviceTable[i].nodeId == nodeId
&& deviceTable[i].endpoint == endpoint) {
return i;
}
}
return EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_INDEX;
}
EmberAfPluginDeviceTableEntry *emberAfDeviceTableFindDeviceTableEntry(uint16_t index)
{
assert(index < EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_NODE_ID);
return &(deviceTable[index]);
}
void emAfDeviceTableUpdateNodeId(uint16_t currentNodeId, uint16_t newNodeId)
{
uint16_t index = emAfDeviceTableFindFirstEndpointNodeId(currentNodeId);
while (index != EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_INDEX) {
deviceTable[index].nodeId = newNodeId;
index = emAfDeviceTableFindNextEndpoint(index);
}
}
void emAfDeviceTableUpdateDeviceState(uint16_t index, uint8_t newState)
{
while (index != EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_INDEX) {
deviceTable[index].state = newState;
index = emAfDeviceTableFindNextEndpoint(index);
}
}
uint32_t emberAfDeviceTableTimeSinceLastMessage(uint16_t index)
{
uint32_t timeSinceLastMessage = halCommonGetInt32uMillisecondTick();
timeSinceLastMessage -= deviceTable[index].lastMsgTimestamp;
timeSinceLastMessage /= MILLISECOND_TICKS_PER_SECOND;
return timeSinceLastMessage;
}
// AF Framework callbacks. This is where the plugin implements the callbacks.
void emberAfPluginDeviceTableInitCallback(void)
{
emAfDeviceTableInit();
// Load on Init
emAfDeviceTableLoad();
emberAfPluginDeviceTableInitialized();
}
void emberAfPluginDeviceTableStackStatusCallback(EmberStatus status)
{
// If we leave the network, this plugin needs to clear out all of its device
// state.
emberAfCorePrintln("%d %d", status, emberNetworkState());
if (status == EMBER_NETWORK_DOWN
&& emberNetworkState() == EMBER_NO_NETWORK) {
emberAfCorePrintln("DeviceTable: Clear State");
emberAfDeviceTableClear();
//kk_device_table_clear();
}
}
// --------------------------------
// Save/Load the devices
void emAfDeviceTableSave(void)
{
#if defined(EZSP_HOST) && !defined(EMBER_TEST)
FILE *fp;
EmberAfPluginDeviceTableEntry *deviceTable = emberAfDeviceTablePointer();
uint8_t i;
uint8_t j;
// Save device table
fp = fopen("devices.txt", "w");
for (i = 0;
i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE;
i++) {
if (deviceTable[i].nodeId != EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_NODE_ID) {
fprintf(fp,
"%x %x %x ",
deviceTable[i].nodeId,
deviceTable[i].endpoint,
deviceTable[i].deviceId);
for (j = 0; j < 8; j++) {
fprintf(fp, "%x ", deviceTable[i].eui64[j]);
}
for (j = 0; j < EMBER_AF_PLUGIN_DEVICE_TABLE_CLUSTER_SIZE; j++) {
fprintf(fp, "%x ", deviceTable[i].clusterIds[j]);
}
fprintf(fp, "%d ", deviceTable[i].clusterOutStartPosition);
}
}
// Write ffffffff to mark the end
fprintf(fp, "\r\nffffffff\r\n");
fclose(fp);
#endif // defined(EZSP_HOST) && !defined(EMBER_TEST)
}
void emAfDeviceTableLoad(void)
{
#if defined(EZSP_HOST) && !defined(EMBER_TEST)
uint16_t i;
uint16_t j;
FILE *fp;
unsigned int data, data2, data3;
EmberAfPluginDeviceTableEntry *deviceTable = emberAfDeviceTablePointer();
fp = fopen("devices.txt", "r");
if (!fp) {
return;
}
for (i = 0;
i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE && feof(fp) == false;
i++) {
fscanf(fp, "%x %x %x", &data2, &data, &data3);
deviceTable[i].endpoint = (uint8_t) data;
deviceTable[i].nodeId = (uint16_t) data2;
deviceTable[i].deviceId = (uint16_t) data3;
if (deviceTable[i].nodeId != EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_NODE_ID) {
for (j = 0; j < 8; j++) {
fscanf(fp, "%x", &data);
deviceTable[i].eui64[j] = (uint8_t) data;
}
for (j = 0; j < EMBER_AF_PLUGIN_DEVICE_TABLE_CLUSTER_SIZE; j++) {
fscanf(fp, "%x", &data);
deviceTable[i].clusterIds[j] = (uint16_t) data;
}
fscanf(fp, "%d", &data);
deviceTable[i].clusterOutStartPosition = (uint16_t) data;
deviceTable[i].state = EMBER_AF_PLUGIN_DEVICE_TABLE_STATE_JOINED;
}
deviceTable[i].lastMsgTimestamp = halCommonGetInt32uMillisecondTick();
}
fclose(fp);
// Set the rest of the device table to null.
for (; i < EMBER_AF_PLUGIN_DEVICE_TABLE_DEVICE_TABLE_SIZE; i++) {
deviceTable[i].nodeId = EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_NODE_ID;
}
#endif // #if defined(EZSP_HOST) && !defined(EMBER_TEST)
}
// --------------------------------
// Message send section
// Command to send the CIE IEEE address to the IAS Zone cluster
void emAfDeviceTableSendCieAddressWrite(EmberNodeId nodeId, uint8_t endpoint)
{
EmberEUI64 eui64;
uint8_t outgoingBuffer[15];
uint32_t i;
emberAfGetEui64(eui64);
globalApsFrame.options = EMBER_AF_DEFAULT_APS_OPTIONS;
globalApsFrame.clusterId = ZCL_IAS_ZONE_CLUSTER_ID;
globalApsFrame.sourceEndpoint = 0x01;
globalApsFrame.destinationEndpoint = endpoint;
outgoingBuffer[0] = 0x00;
outgoingBuffer[1] = emberAfNextSequence();
outgoingBuffer[2] = ZCL_WRITE_ATTRIBUTES_COMMAND_ID;
outgoingBuffer[3] = LOW_BYTE(ZCL_IAS_CIE_ADDRESS_ATTRIBUTE_ID);
outgoingBuffer[4] = HIGH_BYTE(ZCL_IAS_CIE_ADDRESS_ATTRIBUTE_ID);
outgoingBuffer[5] = ZCL_IEEE_ADDRESS_ATTRIBUTE_TYPE;
for (i = 0; i < 8; i++) {
outgoingBuffer[6 + i] = eui64[i];
}
emberAfSendUnicast(EMBER_OUTGOING_DIRECT,
nodeId,
&globalApsFrame,
14,
outgoingBuffer);
}
void emberAfDeviceTableCliIndexSendWithEndpoint(uint16_t index,
uint8_t endpoint)
{
EmberNodeId nodeId;
EmberStatus status;
nodeId = emberAfDeviceTableGetNodeIdFromIndex(index);
emAfApsFrameEndpointSetup(emberAfPrimaryEndpoint(), endpoint);
status = emberAfSendUnicast(EMBER_OUTGOING_DIRECT,
nodeId,
&globalApsFrame,
appZclBufferLen,
appZclBuffer);
zclCmdIsBuilt = false;
}
void emberAfDeviceTableCliIndexSend(uint16_t index)
{
uint8_t endpoint = emAfDeviceTableGetFirstEndpointFromIndex(index);
emberAfDeviceTableCliIndexSendWithEndpoint(index, endpoint);
}
void emberAfDeviceTableSend(EmberEUI64 eui64, uint8_t endpoint)
{
uint16_t index = emberAfDeviceTableGetFirstIndexFromEui64(eui64);
if (index != EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_INDEX) {
emberAfDeviceTableCliIndexSendWithEndpoint(index, endpoint);
}
}
void emberAfDeviceTableCommandIndexSendWithEndpoint(uint16_t index,
uint8_t endpoint)
{
EmberNodeId nodeId;
EmberStatus status;
nodeId = emberAfDeviceTableGetNodeIdFromIndex(index);
if (emberAfCurrentCommand() == NULL) {
emAfCommandApsFrame->sourceEndpoint = emberAfPrimaryEndpoint();
} else {
emAfCommandApsFrame->sourceEndpoint = emberAfCurrentEndpoint();
}
emAfCommandApsFrame->destinationEndpoint = endpoint;
emberAfCorePrintln("device table send with ep: 0x%2X, %d",
nodeId,
endpoint);
status = emberAfSendCommandUnicast(EMBER_OUTGOING_DIRECT, nodeId);
zclCmdIsBuilt = false;
}
void emberAfDeviceTableCommandIndexSend(uint16_t index)
{
uint8_t endpoint = emAfDeviceTableGetFirstEndpointFromIndex(index);
emberAfDeviceTableCommandIndexSendWithEndpoint(index, endpoint);
}
void emberAfDeviceTableCommandSendWithEndpoint(EmberEUI64 eui64,
uint8_t endpoint)
{
uint16_t index = emberAfDeviceTableGetFirstIndexFromEui64(eui64);
emberAfDeviceTableCommandIndexSendWithEndpoint(index, endpoint);
}
// *******************************************************************
// * af-main-host.c
// *
// *
// * Copyright 2007 by Ember Corporation. All rights reserved. *80*
// *******************************************************************
#include "app/framework/include/af.h"
// ZCL - ZigBee Cluster Library
#include "app/framework/util/attribute-storage.h"
#include "app/framework/util/util.h"
#include "app/framework/util/af-event.h"
// ZDO - ZigBee Device Object
#include "app/util/zigbee-framework/zigbee-device-common.h"
#include "app/util/zigbee-framework/zigbee-device-host.h"
// Service discovery library
#include "service-discovery.h"
// Fragmentation
#ifdef EMBER_AF_PLUGIN_FRAGMENTATION
#include "app/framework/plugin/fragmentation/fragmentation.h"
#endif
#include "app/framework/plugin/concentrator/source-route-host.h"
// determines the number of in-clusters and out-clusters based on defines
// in config.h
#include "app/framework/util/af-main.h"
// Needed for zaTrustCenterSecurityPolicyInit()
#include "app/framework/security/af-security.h"
#ifdef GATEWAY_APP
#define COMMAND_INTERPRETER_SUPPORT
#include "app/util/gateway/gateway.h"
#endif
#include "app/util/security/security.h" // Trust Center Address Cache
#include "app/util/common/form-and-join.h"
#include "app/framework/plugin/partner-link-key-exchange/partner-link-key-exchange.h"
#include "app/util/common/library.h"
#include "app/framework/security/crypto-state.h"
#include "afv2-bookkeeping.h"
#include "yjq_ezsp.h"
#include "./rpc_api/inc/rpc_interface_parse.h"
#include <pthread.h>
pthread_mutex_t g_mutex_lock;
//#include <stdio.h>
// This is used to store the local EUI of the NCP when using
// fake certificates.
// Fake certificates are constructed by setting the data to all F's
// but using the device's real IEEE in the cert. The Key establishment
// code requires access to the local IEEE to do this.
EmberEUI64 emLocalEui64;
// APP_SERIAL is set in the project files
uint8_t serialPort = APP_SERIAL;
typedef struct {
EmberNodeId nodeId;
EmberPanId panId;
EmberNetworkStatus networkState;
uint8_t radioChannel;
} NetworkCache;
static NetworkCache networkCache[EMBER_SUPPORTED_NETWORKS];
#define UNKNOWN_NETWORK_STATE 0xFF
// the stack version that the NCP is running
static uint16_t ncpStackVer;
#if defined(EMBER_TEST)
#define EMBER_TEST_ASSERT(x) assert(x)
#else
#define EMBER_TEST_ASSERT(x)
#endif
#if defined(EMBER_AF_PLUGIN_CONCENTRATOR)
#define SOURCE_ROUTE_TABLE_SIZE EMBER_SOURCE_ROUTE_TABLE_SIZE
#else
// Define a small size that will not consume much memory on NCP
#define SOURCE_ROUTE_TABLE_SIZE 2
#endif
// ******************************************************************
// Globals
// when this is set to true it means the NCP has reported a serious error
// and the host needs to reset and re-init the NCP
static bool ncpNeedsResetAndInit = false;
// Declarations related to idling
#ifndef EMBER_TASK_COUNT
#define EMBER_TASK_COUNT (3)
#endif
EmberTaskControl emTasks[EMBER_TASK_COUNT];
PGM uint8_t emTaskCount = EMBER_TASK_COUNT;
#if defined (GATEWAY_APP)
// Baud rate on the gateway application is meaningless, but we must
// define it satisfy compilation.
#define BAUD_RATE BAUD_115200
// Port 1 on the gateway application is used for CLI, while port 0
// is used for "raw" binary. We ignore what was set via App. Builder
// since only port 1 is used by the application.
#undef APP_SERIAL
#define APP_SERIAL 1
#elif (EMBER_AF_BAUD_RATE == 300)
#define BAUD_RATE BAUD_300
#elif (EMBER_AF_BAUD_RATE == 600)
#define BAUD_RATE BAUD_600
#elif (EMBER_AF_BAUD_RATE == 900)
#define BAUD_RATE BAUD_900
#elif (EMBER_AF_BAUD_RATE == 1200)
#define BAUD_RATE BAUD_1200
#elif (EMBER_AF_BAUD_RATE == 2400)
#define BAUD_RATE BAUD_2400
#elif (EMBER_AF_BAUD_RATE == 4800)
#define BAUD_RATE BAUD_4800
#elif (EMBER_AF_BAUD_RATE == 9600)
#define BAUD_RATE BAUD_9600
#elif (EMBER_AF_BAUD_RATE == 14400)
#define BAUD_RATE BAUD_14400
#elif (EMBER_AF_BAUD_RATE == 19200)
#define BAUD_RATE BAUD_19200
#elif (EMBER_AF_BAUD_RATE == 28800)
#define BAUD_RATE BAUD_28800
#elif (EMBER_AF_BAUD_RATE == 38400)
#define BAUD_RATE BAUD_38400
#elif (EMBER_AF_BAUD_RATE == 50000)
#define BAUD_RATE BAUD_50000
#elif (EMBER_AF_BAUD_RATE == 57600)
#define BAUD_RATE BAUD_57600
#elif (EMBER_AF_BAUD_RATE == 76800)
#define BAUD_RATE BAUD_76800
#elif (EMBER_AF_BAUD_RATE == 100000)
#define BAUD_RATE BAUD_100000
#elif (EMBER_AF_BAUD_RATE == 115200)
#define BAUD_RATE BAUD_115200
#elif (EMBER_AF_BAUD_RATE == 230400)
#define BAUD_RATE BAUD_230400
#elif (EMBER_AF_BAUD_RATE == 460800)
#define BAUD_RATE BAUD_460800
#else
#error EMBER_AF_BAUD_RATE set to an invalid baud rate
#endif
#define MAX_CLUSTER 58
// We only get the sender EUI callback when the sender EUI is in the incoming
// message. This keeps track of if the value in the variable is valid or not.
// This is set to VALID (true) when the callback happens and set to INVALID
// (false) at the end of IncomingMessageHandler.
static bool currentSenderEui64IsValid;
static EmberEUI64 currentSenderEui64;
static EmberNodeId currentSender = EMBER_NULL_NODE_ID;
static uint8_t currentBindingIndex = EMBER_NULL_BINDING;
static uint8_t currentAddressIndex = EMBER_NULL_ADDRESS_TABLE_INDEX;
#if defined(EMBER_TEST) && defined(EMBER_AF_PLUGIN_OTA_STORAGE_SIMPLE_EEPROM)
void emAfSetupFakeEepromForSimulation(void);
#define SETUP_FAKE_EEPROM_FOR_SIMULATION() emAfSetupFakeEepromForSimulation()
#else
#define SETUP_FAKE_EEPROM_FOR_SIMULATION()
#endif
#if defined(ZA_CLI_FULL)
#define COMMAND_READER_INIT() emberCommandReaderInit()
#else
#define COMMAND_READER_INIT()
#endif
#if defined(MAIN_FUNCTION_HAS_STANDARD_ARGUMENTS)
#define APP_FRAMEWORK_MAIN_ARGUMENTS argc, argv
#else
#define APP_FRAMEWORK_MAIN_ARGUMENTS 0, NULL
#endif
static uint16_t cachedConfigIdValues[EZSP_CONFIG_ID_MAX + 1];
static bool cacheConfigIdValuesAllowed = false;
static uint8_t ezspSequenceNumber = 0;
//------------------------------------------------------------------------------
// Forward declarations
#ifdef EMBER_AF_GENERATED_PLUGIN_NCP_INIT_FUNCTION_DECLARATIONS
EMBER_AF_GENERATED_PLUGIN_NCP_INIT_FUNCTION_DECLARATIONS
#endif
static void createEndpoint(uint8_t endpointIndex);
static uint8_t ezspNextSequence(void);
//------------------------------------------------------------------------------
// Functions
bool emberAfMemoryByteCompare(const uint8_t* pointer, uint8_t count, uint8_t byteValue)
{
uint8_t i;
for (i = 0; i < count; i++, pointer++) {
if (*pointer != byteValue) {
return false;
}
}
return true;
}
static uint8_t ezspNextSequence(void)
{
return ((++ezspSequenceNumber) & EMBER_AF_MESSAGE_TAG_MASK);
}
bool emberAfNcpNeedsReset(void)
{
return ncpNeedsResetAndInit;
}
// Because an EZSP call can be expensive in terms of bandwidth,
// we cache the node ID so it can be quickly retrieved by the host.
EmberNodeId emberAfGetNodeId(void)
{
uint8_t networkIndex = emberGetCurrentNetwork();
if (networkCache[networkIndex].nodeId == EMBER_NULL_NODE_ID) {
networkCache[networkIndex].nodeId = emberGetNodeId();//yjq:the function useful
}
return networkCache[networkIndex].nodeId;
}
EmberPanId emberAfGetPanId(void)
{
uint8_t networkIndex = emberGetCurrentNetwork();
if (networkCache[networkIndex].panId == 0xFFFF) {
EmberNodeType nodeType;
EmberNetworkParameters parameters;
emberAfGetNetworkParameters(&nodeType, &parameters);
networkCache[networkIndex].panId = parameters.panId;
}
return networkCache[networkIndex].panId;
}
EmberNetworkStatus emberAfNetworkState(void)
{
uint8_t networkIndex = emberGetCurrentNetwork();
if (networkCache[networkIndex].networkState == UNKNOWN_NETWORK_STATE) {
networkCache[networkIndex].networkState = emberNetworkState();
}
return networkCache[networkIndex].networkState;
}
uint8_t emberAfGetRadioChannel(void)
{
uint8_t networkIndex = emberGetCurrentNetwork();
if (networkCache[networkIndex].radioChannel == 0xFF) {
EmberNodeType nodeType;
EmberNetworkParameters parameters;
emberAfGetNetworkParameters(&nodeType, &parameters);
networkCache[networkIndex].radioChannel = parameters.radioChannel;
}
return networkCache[networkIndex].radioChannel;
}
void emberAfGetMfgString(uint8_t* returnData)
{
static uint8_t mfgString[MFG_STRING_MAX_LENGTH];
static bool mfgStringRetrieved = false;
if (mfgStringRetrieved == false) {
ezspGetMfgToken(EZSP_MFG_STRING, mfgString);
mfgStringRetrieved = true;
}
// NOTE: The MFG string is not NULL terminated.
MEMMOVE(returnData, mfgString, MFG_STRING_MAX_LENGTH);
}
void emAfClearNetworkCache(uint8_t networkIndex)
{
networkCache[networkIndex].nodeId = EMBER_NULL_NODE_ID;
networkCache[networkIndex].panId = 0xFFFF;
networkCache[networkIndex].networkState = UNKNOWN_NETWORK_STATE;
networkCache[networkIndex].radioChannel = 0xFF;
}
// Some NCP's support a 'maximize packet buffer' call. If that doesn't
// work, slowly ratchet up the packet buffer count.
static void setPacketBufferCount(void)
{
uint16_t value;
EzspStatus ezspStatus;
EzspStatus maxOutBufferStatus;
maxOutBufferStatus
= ezspSetConfigurationValue(EZSP_CONFIG_PACKET_BUFFER_COUNT,
EZSP_MAXIMIZE_PACKET_BUFFER_COUNT);
// We start from the default used by the NCP and increase up from there
// rather than use a hard coded default in the code.
// This is more portable to different NCP hardware (i.e. 357 vs. 260).
ezspStatus = ezspGetConfigurationValue(EZSP_CONFIG_PACKET_BUFFER_COUNT,
&value);
if (maxOutBufferStatus == EZSP_SUCCESS) {
emberAfAppPrintln("NCP supports maxing out packet buffers");
goto setPacketBufferCountDone;
}
while (ezspStatus == EZSP_SUCCESS) {
value++;
ezspStatus = ezspSetConfigurationValue(EZSP_CONFIG_PACKET_BUFFER_COUNT,
value);
}
setPacketBufferCountDone:
emberAfAppPrintln("Ezsp Config: set packet buffers to %d",
maxOutBufferStatus == EZSP_SUCCESS
? value
: (value - 1));
emberAfAppFlush();
}
// initialize the network co-processor (NCP)
void emAfResetAndInitNCP(void)
{
uint8_t ep;
EzspStatus ezspStatus;
bool memoryAllocation;
uint16_t seed0, seed1;
emberAfPreNcpResetCallback();
// ezspInit resets the NCP by calling halNcpHardReset on a SPI host or
// ashResetNcp on a UART host
ezspStatus = ezspInit();
if (ezspStatus != EZSP_SUCCESS) {
emberAfCorePrintln("ERROR: ezspForceReset 0x%x", ezspStatus);
emberAfCoreFlush();
//assert(false);
printf("[%s][%d]\n",__FUNCTION__,__LINE__);
return;
}
// send the version command before any other commands
emAfCliVersionCommand();
emSecureEzspInit();
// The random number generator on the host needs to be seeded with some
// random data, which we can get from the NCP.
ezspGetRandomNumber(&seed0);
ezspGetRandomNumber(&seed1);
halStackSeedRandom(((uint32_t)seed1 << 16) | (uint32_t)seed0);
// set the source route table size
emberAfSetEzspConfigValue(EZSP_CONFIG_SOURCE_ROUTE_TABLE_SIZE,
SOURCE_ROUTE_TABLE_SIZE,
"source route table size");
emberAfSetEzspConfigValue(EZSP_CONFIG_SECURITY_LEVEL,
EMBER_SECURITY_LEVEL,
"security level");
// set the address table size
emberAfSetEzspConfigValue(EZSP_CONFIG_ADDRESS_TABLE_SIZE,
EMBER_AF_PLUGIN_ADDRESS_TABLE_SIZE,
"address table size");
// set the trust center address cache size
emberAfSetEzspConfigValue(EZSP_CONFIG_TRUST_CENTER_ADDRESS_CACHE_SIZE,
EMBER_AF_PLUGIN_ADDRESS_TABLE_TRUST_CENTER_CACHE_SIZE,
"TC addr cache");
// the stack profile is defined in the config file
emberAfSetEzspConfigValue(EZSP_CONFIG_STACK_PROFILE,
EMBER_STACK_PROFILE,
"stack profile");
// BUG 14222: If stack profile is 2 (ZigBee Pro), we need to enforce
// the standard stack configuration values for that feature set.
if ( EMBER_STACK_PROFILE == 2 ) {
// MAC indirect timeout should be 7.68 secs
emberAfSetEzspConfigValue(EZSP_CONFIG_INDIRECT_TRANSMISSION_TIMEOUT,
7680,
"MAC indirect TX timeout");
// Max hops should be 2 * nwkMaxDepth, where nwkMaxDepth is 15
emberAfSetEzspConfigValue(EZSP_CONFIG_MAX_HOPS,
30,
"max hops");
}
emberAfSetEzspConfigValue(EZSP_CONFIG_TX_POWER_MODE,
EMBER_AF_TX_POWER_MODE,
"tx power mode");
emberAfSetEzspConfigValue(EZSP_CONFIG_SUPPORTED_NETWORKS,
EMBER_SUPPORTED_NETWORKS,
"supported networks");
// allow other devices to modify the binding table
emberAfSetEzspPolicy(EZSP_BINDING_MODIFICATION_POLICY,
EZSP_CHECK_BINDING_MODIFICATIONS_ARE_VALID_ENDPOINT_CLUSTERS,
"binding modify",
"allow for valid endpoints & clusters only");
// return message tag and message contents in ezspMessageSentHandler()
emberAfSetEzspPolicy(EZSP_MESSAGE_CONTENTS_IN_CALLBACK_POLICY,
EZSP_MESSAGE_TAG_AND_CONTENTS_IN_CALLBACK,
"message content in msgSent",
"return");
{
uint8_t value[2];
value[0] = LOW_BYTE(EMBER_AF_INCOMING_BUFFER_LENGTH);
value[1] = HIGH_BYTE(EMBER_AF_INCOMING_BUFFER_LENGTH);
emberAfSetEzspValue(EZSP_VALUE_MAXIMUM_INCOMING_TRANSFER_SIZE,
2, // value length
value,
"maximum incoming transfer size");
value[0] = LOW_BYTE(EMBER_AF_MAXIMUM_SEND_PAYLOAD_LENGTH);
value[1] = HIGH_BYTE(EMBER_AF_MAXIMUM_SEND_PAYLOAD_LENGTH);
emberAfSetEzspValue(EZSP_VALUE_MAXIMUM_OUTGOING_TRANSFER_SIZE,
2, // value length
value,
"maximum outgoing transfer size");
}
// Set the manufacturing code. This is defined by ZigBee document 053874r10
// Ember's ID is 0x1002 and is the default, but this can be overridden in App Builder.
emberSetManufacturerCode(EMBER_AF_MANUFACTURER_CODE);
// Call the plugin and user-specific NCP inits. This is when configuration
// that affects table sizes should occur, which means it must happen before
// setPacketBufferCount.
memoryAllocation = true;
#ifdef EMBER_AF_GENERATED_PLUGIN_NCP_INIT_FUNCTION_CALLS
EMBER_AF_GENERATED_PLUGIN_NCP_INIT_FUNCTION_CALLS
#endif
emberAfNcpInitCallback(memoryAllocation);
setPacketBufferCount();
// Call the plugin and user-specific NCP inits again. This is where non-
// sizing configuration should occur.
memoryAllocation = false;
#ifdef EMBER_AF_GENERATED_PLUGIN_NCP_INIT_FUNCTION_CALLS
EMBER_AF_GENERATED_PLUGIN_NCP_INIT_FUNCTION_CALLS
#endif
emberAfNcpInitCallback(memoryAllocation);
// create endpoints
for ( ep = 0; ep < emberAfEndpointCount(); ep++ ) {
createEndpoint(ep);
}
EM_AF_NETWORK_INIT();
MEMSET(cachedConfigIdValues, 0xFF, ((EZSP_CONFIG_ID_MAX + 1) * sizeof(uint16_t)));
cacheConfigIdValuesAllowed = true;
// Set the localEui64 global
ezspGetEui64(emLocalEui64);
// Initialize messageSentCallbacks table
emAfInitializeMessageSentCallbackArray();
}
// *******************************************************************
// *******************************************************************
// The main() loop and the application's contribution.
void emberAfMainInit(void)
{
}
int emberAfMain(MAIN_FUNCTION_PARAMETERS)
{
SETUP_FAKE_EEPROM_FOR_SIMULATION();
//Initialize the hal
halInit();
INTERRUPTS_ON(); // Safe to enable interrupts at this point
{
int returnCode;
if (emberAfMainStartCallback(&returnCode,
APP_FRAMEWORK_MAIN_ARGUMENTS)) { //get serial port info
return returnCode;
}
}
kk_print("*******************123****************\r\n");
kk_print_info("\r\n-----hello world![%s:%s]-----\r\n",__DATE__,__TIME__);
kk_print_version();
emberSerialInit(APP_SERIAL, BAUD_RATE, PARITY_NONE, 1); //fock child process
emberAfAppPrintln("Reset info: %d (%p)",
halGetResetInfo(),
halGetResetString());
int ret = pthread_mutex_init(&g_mutex_lock, NULL);
if (ret != 0) {
printf("mutex init failed\n");
return -1;
}
/*int pid=fork();
if(pid==0){
rpcInterfaceParse();
}*/
emberAfCoreFlush();
// This will initialize the stack of networks maintained by the framework,
// including setting the default network.
emAfInitializeNetworkIndexStack();
// We must initialize the endpoint information first so
// that they are correctly added by emAfResetAndInitNCP()
emberAfEndpointConfigure();
// initialize the network co-processor (NCP)
emAfResetAndInitNCP();
printf("[%s][%d]\n",__FUNCTION__,__LINE__);
EmberEUI64 eui64;
emberAfGetEui64(eui64);
emberAfCorePrintln("~~~~~~~~~~~~~~~~~~~~~NCP MAC:");
emberAfPrintBigEndianEui64(eui64);
kk_network_check();
kk_tsl_init(eui64);
pthread_t tid;
//pthread_create(&tid, NULL, rpcInterfaceParse, NULL);
pthread_create(&tid, NULL, ipcHandle, NULL);
// initialize the ZCL framework ,(plug in) ,mqtt init is here
emAfInit();
COMMAND_READER_INIT();
// main loop
while (true) {
halResetWatchdog(); // Periodically reset the watchdog.
// see if the NCP has anything waiting to send us
ezspTick();
while (ezspCallbackPending()) {
ezspCallback();
}
// check if we have hit an EZSP Error and need to reset and init the NCP
if (ncpNeedsResetAndInit) {
ncpNeedsResetAndInit = false;
// re-initialize the NCP
emAfResetAndInitNCP();
}
// Wait until ECC operations are done. Don't allow any of the clusters
// to send messages as the NCP is busy doing ECC
if (emAfIsCryptoOperationInProgress()) {
continue;
}
// let the ZCL Utils run - this should go after ezspTick
emAfTick();
emberSerialBufferTick();
emberAfRunEvents();
#if defined(ZA_CLI_FULL)
if (emberProcessCommandInput(APP_SERIAL))
{
#if !defined GATEWAY_APP
// Gateway app. has its own way of handling the command-line prompt.
emberAfGuaranteedPrint("%p>", ZA_PROMPT);
#endif
}
#endif
#if defined(EMBER_TEST)
if (1) {
// Simulation only
uint32_t timeToNextEventMax = emberMsToNextStackEvent();
timeToNextEventMax = emberAfMsToNextEvent(timeToNextEventMax);
simulatedTimePassesMs(timeToNextEventMax);
}
#endif
// After each interation through the main loop, our network index stack
// should be empty and we should be on the default network index again.
emAfAssertNetworkIndexStackIsEmpty();
}
return 0;
}
// ******************************************************************
// binding
// ******************************************************************
EmberStatus emberAfSendEndDeviceBind(uint8_t endpoint)
{
EmberStatus status;
EmberEUI64 eui;
uint8_t inClusterCount, outClusterCount;
EmberAfClusterId clusterList[MAX_CLUSTER];
EmberAfClusterId *inClusterList;
EmberAfClusterId *outClusterList;
EmberAfProfileId profileId;
EmberApsOption options = ((EMBER_AF_DEFAULT_APS_OPTIONS
| EMBER_APS_OPTION_SOURCE_EUI64)
& ~EMBER_APS_OPTION_RETRY);
uint8_t index = emberAfIndexFromEndpoint(endpoint);
if (index == 0xFF) {
return EMBER_INVALID_ENDPOINT;
}
status = emberAfPushEndpointNetworkIndex(endpoint);
if (status != EMBER_SUCCESS) {
return status;
}
emberAfGetEui64(eui);
emberAfZdoPrintln("send %x %2x ", endpoint, options);
inClusterList = clusterList;
inClusterCount = emberAfGetClustersFromEndpoint(endpoint,
inClusterList,
MAX_CLUSTER,
true); // server?
outClusterList = clusterList + inClusterCount;
outClusterCount = emberAfGetClustersFromEndpoint(endpoint,
outClusterList,
(MAX_CLUSTER
- inClusterCount),
false); // server?
profileId = emberAfProfileIdFromIndex(index);
status = ezspEndDeviceBindRequest(emberAfGetNodeId(),
eui,
endpoint,
profileId,
inClusterCount, // cluster in count
outClusterCount, // cluster out count
inClusterList, // list of input clusters
outClusterList, // list of output clusters
options);
emberAfZdoPrintln("done: %x.", status);
emberAfPopNetworkIndex();
return status;
}
// **********************************************************************
// this function sets an EZSP config value and prints out the results to
// the serial output
// **********************************************************************
EzspStatus emberAfSetEzspConfigValue(EzspConfigId configId,
uint16_t value,
PGM_P configIdName)
{
EzspStatus ezspStatus = ezspSetConfigurationValue(configId, value);
emberAfAppFlush();
emberAfAppPrint("Ezsp Config: set %p to 0x%2x:", configIdName, value);
emberAfAppDebugExec(emAfPrintStatus("set", ezspStatus));
emberAfAppFlush();
emberAfAppPrintln("");
emberAfAppFlush();
// If this fails, odds are the simulated NCP doesn't have enough
// memory allocated to it.
EMBER_TEST_ASSERT(ezspStatus == EZSP_SUCCESS);
return ezspStatus;
}
// **********************************************************************
// this function sets an EZSP policy and prints out the results to
// the serial output
// **********************************************************************
EzspStatus emberAfSetEzspPolicy(EzspPolicyId policyId,
EzspDecisionId decisionId,
PGM_P policyName,
PGM_P decisionName)
{
EzspStatus ezspStatus = ezspSetPolicy(policyId,
decisionId);
emberAfAppPrint("Ezsp Policy: set %p to \"%p\":",
policyName,
decisionName);
emberAfAppDebugExec(emAfPrintStatus("set",
ezspStatus));
emberAfAppPrintln("");
emberAfAppFlush();
return ezspStatus;
}
// **********************************************************************
// this function sets an EZSP value and prints out the results to
// the serial output
// **********************************************************************
EzspStatus emberAfSetEzspValue(EzspValueId valueId,
uint8_t valueLength,
uint8_t *value,
PGM_P valueName)
{
EzspStatus ezspStatus = ezspSetValue(valueId, valueLength, value);
emberAfAppPrint("Ezsp Value : set %p to ", valueName);
// print the value based on the length of the value
// for length 1/2/4 bytes, fetch int of that length and promote to 32 bits for printing
switch (valueLength) {
case 1:
emberAfAppPrint("0x%4x:", (uint32_t)(*value));
break;
case 2:
emberAfAppPrint("0x%4x:", (uint32_t)(*((uint16_t *)value)));
break;
case 4:
emberAfAppPrint("0x%4x:", (uint32_t)(*((uint32_t *)value)));
break;
default:
emberAfAppPrint("{val of len %x}:", valueLength);
break;
}
emberAfAppDebugExec(emAfPrintStatus("set", ezspStatus));
emberAfAppPrintln("");
emberAfAppFlush();
return ezspStatus;
}
// ******************************************************************
// setup endpoints and clusters for responding to ZDO requests
// ******************************************************************
//
// Creates the endpoint for 260 by calling ezspAddEndpoint()
//
static void createEndpoint(uint8_t endpointIndex)
{
uint16_t clusterList[MAX_CLUSTER];
uint16_t *inClusterList;
uint16_t *outClusterList;
uint8_t endpoint = emberAfEndpointFromIndex(endpointIndex);
uint8_t inClusterCount;
uint8_t outClusterCount;
{
EmberStatus status = emberAfPushEndpointNetworkIndex(endpoint);
if (status != EMBER_SUCCESS) {
emberAfAppPrintln("Error in creating endpoint %d: 0x%x", endpoint, status);
return;
}
}
// Lay out clusters in the arrays.
inClusterList = clusterList;
inClusterCount = emberAfGetClustersFromEndpoint(endpoint, inClusterList, MAX_CLUSTER, true);
outClusterList = clusterList + inClusterCount;
outClusterCount = emberAfGetClustersFromEndpoint(endpoint, outClusterList, (MAX_CLUSTER - inClusterCount), false);
// Call EZSP function with data.
{
EzspStatus status = ezspAddEndpoint(endpoint,
emberAfProfileIdFromIndex(endpointIndex),
emberAfDeviceIdFromIndex(endpointIndex),
emberAfDeviceVersionFromIndex(endpointIndex),
inClusterCount,
outClusterCount,
(uint16_t *)inClusterList,
(uint16_t *)outClusterList);
if (status == EZSP_SUCCESS) {
emberAfAppPrintln("Ezsp Endpoint %d added, profile 0x%2x, in clusters: %d, out clusters %d",
endpoint,
emberAfProfileIdFromIndex(endpointIndex),
inClusterCount,
outClusterCount);
} else {
emberAfAppPrintln("Error in creating endpoint %d: 0x%x", endpoint, status);
}
}
emberAfPopNetworkIndex();
}
// *******************************************************************
// Handlers required to use the Ember Stack.
// Called when the stack status changes, usually as a result of an
// attempt to form, join, or leave a network.
void ezspStackStatusHandler(EmberStatus status)
{
emberAfPushCallbackNetworkIndex();
emAfStackStatusHandler(status);
emberAfPopNetworkIndex();
}
EmberNodeId emberGetSender(void)
{
return currentSender;
}
uint8_t emberAfGetBindingIndex(void)
{
return currentBindingIndex;
}
uint8_t emberAfGetAddressIndex(void)
{
return currentAddressIndex;
}
// This is not called if the incoming message did not contain the EUI64 of
// the sender.
void ezspIncomingSenderEui64Handler(EmberEUI64 senderEui64)
{
// current sender is now valid
MEMMOVE(currentSenderEui64, senderEui64, EUI64_SIZE);
currentSenderEui64IsValid = true;
}
EmberStatus emberGetSenderEui64(EmberEUI64 senderEui64)
{
// if the current sender EUI is valid then copy it in and send it back
if (currentSenderEui64IsValid) {
MEMMOVE(senderEui64, currentSenderEui64, EUI64_SIZE);
return EMBER_SUCCESS;
}
// in the not valid case just return error
return EMBER_ERR_FATAL;
}
//
// ******************************************************************
void ezspIncomingMessageHandler(EmberIncomingMessageType type,
EmberApsFrame *apsFrame,
uint8_t lastHopLqi,
int8_t lastHopRssi,
EmberNodeId sender,
uint8_t bindingIndex,
uint8_t addressIndex,
uint8_t messageLength,
uint8_t *messageContents)
{
uint8_t sourceRouteOverhead;
emberAfPushCallbackNetworkIndex();
// The following code caches valid Source Route overheads sent pro actively
// by the NCP and uses it once to calculate the overhead for a target, after
// which it gets cleared.
sourceRouteOverhead = getSourceRouteOverhead(messageLength);
emberAfSetSourceRouteOverheadCallback(sender, sourceRouteOverhead);
currentSender = sender;
currentBindingIndex = bindingIndex;
currentAddressIndex = addressIndex;
emAfIncomingMessageHandler(type,
apsFrame,
lastHopLqi,
lastHopRssi,
messageLength,
messageContents);
currentSenderEui64IsValid = false;
currentSender = EMBER_NULL_NODE_ID;
currentBindingIndex = EMBER_NULL_BINDING;
currentAddressIndex = EMBER_NULL_ADDRESS_TABLE_INDEX;
// Invalidate the sourceRouteOverhead cached at the end of the current incomingMessageHandler
emberAfSetSourceRouteOverheadCallback(sender, EZSP_SOURCE_ROUTE_OVERHEAD_UNKNOWN);
emberAfPopNetworkIndex();
}
// Called when a message we sent is acked by the destination or when an
// ack fails to arrive after several retransmissions.
void ezspMessageSentHandler(EmberOutgoingMessageType type,
uint16_t indexOrDestination,
EmberApsFrame *apsFrame,
uint8_t messageTag,
EmberStatus status,
uint8_t messageLength,
uint8_t *messageContents)
{
emberAfPushCallbackNetworkIndex();
#ifdef EMBER_AF_PLUGIN_FRAGMENTATION
if (emAfFragmentationMessageSent(apsFrame, status)) {
goto kickout;
}
#endif //EMBER_AF_PLUGIN_FRAGMENTATION
emAfMessageSentHandler(type,
indexOrDestination,
apsFrame,
status,
messageLength,
messageContents,
messageTag);
goto kickout; // silence a warning when not using fragmentation
kickout:
emberAfPopNetworkIndex();
}
void emberChildJoinHandler(uint8_t index, bool joining)
{
}
// This is called when an EZSP error is reported
void ezspErrorHandler(EzspStatus status)
{
emberAfCorePrintln("ERROR: ezspErrorHandler 0x%x", status);
emberAfCoreFlush();
// Rather than detect whether or not we can recover from the error,
// we just flag the NCP for reboot.
// Do not reset if this is a decryption failure, as we ignored the packet.
if (status != EZSP_ERROR_SECURITY_PARAMETERS_INVALID) {
ncpNeedsResetAndInit = true;
}
}
EmberStatus emberAfEzspSetSourceRoute(EmberNodeId id)
{
#ifdef EZSP_APPLICATION_HAS_ROUTE_RECORD_HANDLER
uint16_t relayList[ZA_MAX_HOPS];
uint8_t relayCount;
if (emberFindSourceRoute(id, &relayCount, relayList)
&& ezspSetSourceRoute(id, relayCount, relayList) != EMBER_SUCCESS) {
return EMBER_SOURCE_ROUTE_FAILURE;
}
#endif
return EMBER_SUCCESS;
}
EmberStatus emAfSend(EmberOutgoingMessageType type,
uint16_t indexOrDestination,
EmberApsFrame *apsFrame,
uint8_t messageLength,
uint8_t *message,
uint8_t *messageTag,
EmberNodeId alias,
uint8_t sequence)
{
EmberStatus status;
*messageTag = ezspNextSequence();
switch (type) {
case EMBER_OUTGOING_DIRECT:
case EMBER_OUTGOING_VIA_ADDRESS_TABLE:
case EMBER_OUTGOING_VIA_BINDING:
{
status = emberAfEzspSetSourceRoute(indexOrDestination);
if (status == EMBER_SUCCESS) {
status = ezspSendUnicast(type,
indexOrDestination,
apsFrame,
*messageTag,
(uint8_t)messageLength,
message,
&apsFrame->sequence);
}
break;
}
case EMBER_OUTGOING_MULTICAST:
{
status = ezspSendMulticast(apsFrame,
ZA_MAX_HOPS, // hops
ZA_MAX_HOPS, // nonmember radius
*messageTag,
messageLength,
message,
&apsFrame->sequence);
break;
}
case EMBER_OUTGOING_MULTICAST_WITH_ALIAS:
{
status = ezspSendMulticastWithAlias(apsFrame,
apsFrame->radius, //radius
apsFrame->radius, //nonmember radius
alias,
sequence,
*messageTag,
messageLength,
message,
&apsFrame->sequence);
break;
}
case EMBER_OUTGOING_BROADCAST:
{
status = ezspSendBroadcast(indexOrDestination,
apsFrame,
ZA_MAX_HOPS, // radius
*messageTag,
messageLength,
message,
&apsFrame->sequence);
break;
}
case EMBER_OUTGOING_BROADCAST_WITH_ALIAS:
status = ezspProxyBroadcast(alias,
indexOrDestination,
sequence,
apsFrame,
apsFrame->radius, // radius
*messageTag,
messageLength,
message,
&apsFrame->sequence);
break;
default:
status = EMBER_BAD_ARGUMENT;
}
return status;
}
// Platform dependent interface to get various stack parameters.
void emberAfGetEui64(EmberEUI64 returnEui64)
{
MEMCOPY(returnEui64, emLocalEui64, EUI64_SIZE);
}
EmberStatus emberAfGetNetworkParameters(EmberNodeType* nodeType,
EmberNetworkParameters* parameters)
{
return ezspGetNetworkParameters(nodeType, parameters);
}
EmberStatus emberAfGetNodeType(EmberNodeType *nodeType)
{
EmberNetworkParameters parameters;
return ezspGetNetworkParameters(nodeType, &parameters);
}
// This will cache all config items to make sure repeated calls do not
// go all the way to the NCP.
uint8_t emberAfGetNcpConfigItem(EzspConfigId id)
{
// In case we can't cache config items yet, we need a temp
// variable to store the retrieved EZSP config ID.
uint16_t temp = 0xFFFF;
uint16_t *configItemPtr = &temp;
bool cacheValid;
EMBER_TEST_ASSERT(id <= EZSP_CONFIG_ID_MAX);
cacheValid = (cacheConfigIdValuesAllowed
&& id <= EZSP_CONFIG_ID_MAX);
if (cacheValid) {
configItemPtr = &(cachedConfigIdValues[id]);
}
if (*configItemPtr == 0xFFFF
&& EZSP_SUCCESS != ezspGetConfigurationValue(id,
configItemPtr)) {
// We return a 0 size (for tables) on error to prevent code from using the
// invalid value of 0xFFFF. This is particularly necessary for loops that
// iterate over all indexes.
return 0;
}
return (uint8_t)(*configItemPtr);
}
EmberStatus emberAfGetSourceRouteTableEntry(
uint8_t index,
EmberNodeId *destination,
uint8_t *closerIndex)
{
return ezspGetSourceRouteTableEntry(index,
destination,
closerIndex);
}
uint8_t emberAfGetSourceRouteTableFilledSize(void)
{
return ezspGetSourceRouteTableFilledSize();
}
uint8_t emberAfGetSourceRouteTableTotalSize(void)
{
return ezspGetSourceRouteTableTotalSize();
}
EmberStatus emberAfGetChildData(uint8_t index,
EmberChildData *childData)
{
return ezspGetChildData(index,
childData);
}
uint8_t emberAfGetChildTableSize(void)
{
return emberAfGetNcpConfigItem(EZSP_CONFIG_MAX_END_DEVICE_CHILDREN);
}
uint8_t emberAfGetKeyTableSize(void)
{
return emberAfGetNcpConfigItem(EZSP_CONFIG_KEY_TABLE_SIZE);
}
uint8_t emberAfGetAddressTableSize(void)
{
return emberAfGetNcpConfigItem(EZSP_CONFIG_ADDRESS_TABLE_SIZE);
}
uint8_t emberAfGetBindingTableSize(void)
{
return emberAfGetNcpConfigItem(EZSP_CONFIG_BINDING_TABLE_SIZE);
}
uint8_t emberAfGetNeighborTableSize(void)
{
return emberAfGetNcpConfigItem(EZSP_CONFIG_NEIGHBOR_TABLE_SIZE);
}
uint8_t emberAfGetRouteTableSize(void)
{
return emberAfGetNcpConfigItem(EZSP_CONFIG_ROUTE_TABLE_SIZE);
}
uint8_t emberAfGetSecurityLevel(void)
{
return emberAfGetNcpConfigItem(EZSP_CONFIG_SECURITY_LEVEL);
}
uint8_t emberAfGetStackProfile(void)
{
return emberAfGetNcpConfigItem(EZSP_CONFIG_STACK_PROFILE);
}
uint8_t emberAfGetSleepyMulticastConfig(void)
{
return emberAfGetNcpConfigItem(EZSP_CONFIG_SEND_MULTICASTS_TO_SLEEPY_ADDRESS);
}
// On the System-on-a-chip this function is provided by the stack.
// Here is a copy for the host based applications.
void emberReverseMemCopy(uint8_t* dest, const uint8_t* src, uint16_t length)
{
uint16_t i;
uint16_t j = (length - 1);
for ( i = 0; i < length; i++) {
dest[i] = src[j];
j--;
}
}
// ******************************************************************
// Functions called by the Serial Command Line Interface (CLI)
// ******************************************************************
// *****************************
// emAfCliVersionCommand
//
// version <no arguments>
// *****************************
void emAfCliVersionCommand(void)
{
// Note that NCP == Network Co-Processor
EmberVersion versionStruct;
// the EZSP protocol version that the NCP is using
uint8_t ncpEzspProtocolVer;
// the stackType that the NCP is running
uint8_t ncpStackType;
// the EZSP protocol version that the Host is running
// we are the host so we set this value
uint8_t hostEzspProtocolVer = EZSP_PROTOCOL_VERSION;
// send the Host version number to the NCP. The NCP returns the EZSP
// version that the NCP is running along with the stackType and stackVersion
ncpEzspProtocolVer = ezspVersion(hostEzspProtocolVer,
&ncpStackType,
&ncpStackVer);
// verify that the stack type is what is expected
if (ncpStackType != EZSP_STACK_TYPE_MESH) {
emberAfAppPrint("ERROR: stack type 0x%x is not expected!",
ncpStackType);
assert(false);
}
// verify that the NCP EZSP Protocol version is what is expected
if (ncpEzspProtocolVer != EZSP_PROTOCOL_VERSION) {
emberAfAppPrint("ERROR: NCP EZSP protocol version of 0x%x does not match Host version 0x%x\r\n",
ncpEzspProtocolVer,
hostEzspProtocolVer);
assert(false);
}
emberAfAppPrint("ezsp ver 0x%x stack type 0x%x ",
ncpEzspProtocolVer, ncpStackType);
if (EZSP_SUCCESS != ezspGetVersionStruct(&versionStruct)) {
// NCP has Old style version number
emberAfAppPrintln("stack ver [0x%2x]", ncpStackVer);
kk_set_ezsp_version_info(hostEzspProtocolVer,ncpEzspProtocolVer,ncpStackType,ncpStackVer,NULL);
} else {
// NCP has new style version number
emAfParseAndPrintVersion(versionStruct);
kk_set_ezsp_version_info(hostEzspProtocolVer,ncpEzspProtocolVer,ncpStackType,ncpStackVer,&versionStruct);
}
emberAfAppFlush();
}
uint8_t emAfGetPacketBufferFreeCount(void)
{
uint8_t freeCount;
uint8_t valueLength = 1;
ezspGetValue(EZSP_VALUE_FREE_BUFFERS,
&valueLength,
&freeCount);
return freeCount;
}
uint8_t emAfGetPacketBufferTotalCount(void)
{
uint16_t value;
ezspGetConfigurationValue(EZSP_CONFIG_PACKET_BUFFER_COUNT,
&value);
return (uint8_t)value;
}
// WARNING: This function executes in ISR context
void halNcpIsAwakeIsr(bool isAwake)
{
if (isAwake) {
emberAfNcpIsAwakeIsrCallback();
} else {
// If we got indication that the NCP failed to wake up
// there is not much that can be done. We will reset the
// host (which in turn will reset the NCP) and that will
// hopefully bring things back in sync.
assert(0);
}
}
void ezspNetworkFoundHandler(EmberZigbeeNetwork *networkFound,
uint8_t lqi,
int8_t rssi)
{
emberAfPushCallbackNetworkIndex();
#ifdef EMBER_AF_PLUGIN_FORM_AND_JOIN
if (!emberFormAndJoinNetworkFoundHandler(networkFound, lqi, rssi))
#endif
emberAfNetworkFoundCallback(networkFound, lqi, rssi);
emberAfPopNetworkIndex();
}
void ezspScanCompleteHandler(uint8_t channel, EmberStatus status)
{
emberAfPushCallbackNetworkIndex();
#ifdef EMBER_AF_PLUGIN_FORM_AND_JOIN
if (!emberFormAndJoinScanCompleteHandler(channel, status))
#endif
emberAfScanCompleteCallback(channel, status);
emberAfPopNetworkIndex();
}
void ezspEnergyScanResultHandler(uint8_t channel, int8_t rssi)
{
emberAfPushCallbackNetworkIndex();
#ifdef EMBER_AF_PLUGIN_FORM_AND_JOIN
if (!emberFormAndJoinEnergyScanResultHandler(channel, rssi))
#endif
emberAfEnergyScanResultCallback(channel, rssi);
emberAfPopNetworkIndex();
}
void ezspUnusedPanIdFoundHandler(EmberPanId panId, uint8_t channel)
{
emberAfPushCallbackNetworkIndex();
#ifdef EMBER_AF_PLUGIN_FORM_AND_JOIN
if (!emberFormAndJoinUnusedPanIdFoundHandler(panId, channel))
#endif
emberAfUnusedPanIdFoundCallback(panId, channel);
emberAfPopNetworkIndex();
}
void emAfPrintEzspEndpointFlags(uint8_t endpoint)
{
EzspEndpointFlags flags;
EzspStatus status = ezspGetEndpointFlags(endpoint,
&flags);
if (status != EZSP_SUCCESS) {
emberAfCorePrint("Error retrieving EZSP endpoint flags.");
} else {
emberAfCorePrint("- EZSP Endpoint flags: 0x%2X", flags);
}
}
void emSetAddDelay(uint8_t delay)
{
//XXXEZSP
}
void ezspZigbeeKeyEstablishmentHandler(EmberEUI64 partner,
EmberKeyStatus status)
{
// This function is generated.
emAfZigbeeKeyEstablishment(partner, status);
}
// *******************************************************************
// * af-main-host.c
// *
// *
// * Copyright 2007 by Ember Corporation. All rights reserved. *80*
// *******************************************************************
#include "app/framework/include/af.h"
// ZCL - ZigBee Cluster Library
#include "app/framework/util/attribute-storage.h"
#include "app/framework/util/util.h"
#include "app/framework/util/af-event.h"
// ZDO - ZigBee Device Object
#include "app/util/zigbee-framework/zigbee-device-common.h"
#include "app/util/zigbee-framework/zigbee-device-host.h"
// Service discovery library
#include "service-discovery.h"
// Fragmentation
#ifdef EMBER_AF_PLUGIN_FRAGMENTATION
#include "app/framework/plugin/fragmentation/fragmentation.h"
#endif
#include "app/framework/plugin/concentrator/source-route-host.h"
// determines the number of in-clusters and out-clusters based on defines
// in config.h
#include "app/framework/util/af-main.h"
// Needed for zaTrustCenterSecurityPolicyInit()
#include "app/framework/security/af-security.h"
#ifdef GATEWAY_APP
#define COMMAND_INTERPRETER_SUPPORT
#include "app/util/gateway/gateway.h"
#endif
#include "app/util/security/security.h" // Trust Center Address Cache
#include "app/util/common/form-and-join.h"
#include "app/framework/plugin/partner-link-key-exchange/partner-link-key-exchange.h"
#include "app/util/common/library.h"
#include "app/framework/security/crypto-state.h"
#include "afv2-bookkeeping.h"
#include "yjq_ezsp.h"
#include "./rpc_api/inc/rpc_interface_parse.h"
#include <pthread.h>
pthread_mutex_t g_mutex_lock;
//#include <stdio.h>
// This is used to store the local EUI of the NCP when using
// fake certificates.
// Fake certificates are constructed by setting the data to all F's
// but using the device's real IEEE in the cert. The Key establishment
// code requires access to the local IEEE to do this.
EmberEUI64 emLocalEui64;
// APP_SERIAL is set in the project files
uint8_t serialPort = APP_SERIAL;
typedef struct {
EmberNodeId nodeId;
EmberPanId panId;
EmberNetworkStatus networkState;
uint8_t radioChannel;
} NetworkCache;
static NetworkCache networkCache[EMBER_SUPPORTED_NETWORKS];
#define UNKNOWN_NETWORK_STATE 0xFF
// the stack version that the NCP is running
static uint16_t ncpStackVer;
#if defined(EMBER_TEST)
#define EMBER_TEST_ASSERT(x) assert(x)
#else
#define EMBER_TEST_ASSERT(x)
#endif
#if defined(EMBER_AF_PLUGIN_CONCENTRATOR)
#define SOURCE_ROUTE_TABLE_SIZE EMBER_SOURCE_ROUTE_TABLE_SIZE
#else
// Define a small size that will not consume much memory on NCP
#define SOURCE_ROUTE_TABLE_SIZE 2
#endif
// ******************************************************************
// Globals
// when this is set to true it means the NCP has reported a serious error
// and the host needs to reset and re-init the NCP
static bool ncpNeedsResetAndInit = false;
// Declarations related to idling
#ifndef EMBER_TASK_COUNT
#define EMBER_TASK_COUNT (3)
#endif
EmberTaskControl emTasks[EMBER_TASK_COUNT];
PGM uint8_t emTaskCount = EMBER_TASK_COUNT;
#if defined (GATEWAY_APP)
// Baud rate on the gateway application is meaningless, but we must
// define it satisfy compilation.
#define BAUD_RATE BAUD_115200
// Port 1 on the gateway application is used for CLI, while port 0
// is used for "raw" binary. We ignore what was set via App. Builder
// since only port 1 is used by the application.
#undef APP_SERIAL
#define APP_SERIAL 1
#elif (EMBER_AF_BAUD_RATE == 300)
#define BAUD_RATE BAUD_300
#elif (EMBER_AF_BAUD_RATE == 600)
#define BAUD_RATE BAUD_600
#elif (EMBER_AF_BAUD_RATE == 900)
#define BAUD_RATE BAUD_900
#elif (EMBER_AF_BAUD_RATE == 1200)
#define BAUD_RATE BAUD_1200
#elif (EMBER_AF_BAUD_RATE == 2400)
#define BAUD_RATE BAUD_2400
#elif (EMBER_AF_BAUD_RATE == 4800)
#define BAUD_RATE BAUD_4800
#elif (EMBER_AF_BAUD_RATE == 9600)
#define BAUD_RATE BAUD_9600
#elif (EMBER_AF_BAUD_RATE == 14400)
#define BAUD_RATE BAUD_14400
#elif (EMBER_AF_BAUD_RATE == 19200)
#define BAUD_RATE BAUD_19200
#elif (EMBER_AF_BAUD_RATE == 28800)
#define BAUD_RATE BAUD_28800
#elif (EMBER_AF_BAUD_RATE == 38400)
#define BAUD_RATE BAUD_38400
#elif (EMBER_AF_BAUD_RATE == 50000)
#define BAUD_RATE BAUD_50000
#elif (EMBER_AF_BAUD_RATE == 57600)
#define BAUD_RATE BAUD_57600
#elif (EMBER_AF_BAUD_RATE == 76800)
#define BAUD_RATE BAUD_76800
#elif (EMBER_AF_BAUD_RATE == 100000)
#define BAUD_RATE BAUD_100000
#elif (EMBER_AF_BAUD_RATE == 115200)
#define BAUD_RATE BAUD_115200
#elif (EMBER_AF_BAUD_RATE == 230400)
#define BAUD_RATE BAUD_230400
#elif (EMBER_AF_BAUD_RATE == 460800)
#define BAUD_RATE BAUD_460800
#else
#error EMBER_AF_BAUD_RATE set to an invalid baud rate
#endif
#define MAX_CLUSTER 58
// We only get the sender EUI callback when the sender EUI is in the incoming
// message. This keeps track of if the value in the variable is valid or not.
// This is set to VALID (true) when the callback happens and set to INVALID
// (false) at the end of IncomingMessageHandler.
static bool currentSenderEui64IsValid;
static EmberEUI64 currentSenderEui64;
static EmberNodeId currentSender = EMBER_NULL_NODE_ID;
static uint8_t currentBindingIndex = EMBER_NULL_BINDING;
static uint8_t currentAddressIndex = EMBER_NULL_ADDRESS_TABLE_INDEX;
#if defined(EMBER_TEST) && defined(EMBER_AF_PLUGIN_OTA_STORAGE_SIMPLE_EEPROM)
void emAfSetupFakeEepromForSimulation(void);
#define SETUP_FAKE_EEPROM_FOR_SIMULATION() emAfSetupFakeEepromForSimulation()
#else
#define SETUP_FAKE_EEPROM_FOR_SIMULATION()
#endif
#if defined(ZA_CLI_FULL)
#define COMMAND_READER_INIT() emberCommandReaderInit()
#else
#define COMMAND_READER_INIT()
#endif
#if defined(MAIN_FUNCTION_HAS_STANDARD_ARGUMENTS)
#define APP_FRAMEWORK_MAIN_ARGUMENTS argc, argv
#else
#define APP_FRAMEWORK_MAIN_ARGUMENTS 0, NULL
#endif
static uint16_t cachedConfigIdValues[EZSP_CONFIG_ID_MAX + 1];
static bool cacheConfigIdValuesAllowed = false;
static uint8_t ezspSequenceNumber = 0;
//------------------------------------------------------------------------------
// Forward declarations
#ifdef EMBER_AF_GENERATED_PLUGIN_NCP_INIT_FUNCTION_DECLARATIONS
EMBER_AF_GENERATED_PLUGIN_NCP_INIT_FUNCTION_DECLARATIONS
#endif
static void createEndpoint(uint8_t endpointIndex);
static uint8_t ezspNextSequence(void);
//------------------------------------------------------------------------------
// Functions
bool emberAfMemoryByteCompare(const uint8_t* pointer, uint8_t count, uint8_t byteValue)
{
uint8_t i;
for (i = 0; i < count; i++, pointer++) {
if (*pointer != byteValue) {
return false;
}
}
return true;
}
static uint8_t ezspNextSequence(void)
{
return ((++ezspSequenceNumber) & EMBER_AF_MESSAGE_TAG_MASK);
}
bool emberAfNcpNeedsReset(void)
{
return ncpNeedsResetAndInit;
}
// Because an EZSP call can be expensive in terms of bandwidth,
// we cache the node ID so it can be quickly retrieved by the host.
EmberNodeId emberAfGetNodeId(void)
{
uint8_t networkIndex = emberGetCurrentNetwork();
if (networkCache[networkIndex].nodeId == EMBER_NULL_NODE_ID) {
networkCache[networkIndex].nodeId = emberGetNodeId();//yjq:the function useful
}
return networkCache[networkIndex].nodeId;
}
EmberPanId emberAfGetPanId(void)
{
uint8_t networkIndex = emberGetCurrentNetwork();
if (networkCache[networkIndex].panId == 0xFFFF) {
EmberNodeType nodeType;
EmberNetworkParameters parameters;
emberAfGetNetworkParameters(&nodeType, &parameters);
networkCache[networkIndex].panId = parameters.panId;
}
return networkCache[networkIndex].panId;
}
EmberNetworkStatus emberAfNetworkState(void)
{
uint8_t networkIndex = emberGetCurrentNetwork();
if (networkCache[networkIndex].networkState == UNKNOWN_NETWORK_STATE) {
networkCache[networkIndex].networkState = emberNetworkState();
}
return networkCache[networkIndex].networkState;
}
uint8_t emberAfGetRadioChannel(void)
{
uint8_t networkIndex = emberGetCurrentNetwork();
if (networkCache[networkIndex].radioChannel == 0xFF) {
EmberNodeType nodeType;
EmberNetworkParameters parameters;
emberAfGetNetworkParameters(&nodeType, &parameters);
networkCache[networkIndex].radioChannel = parameters.radioChannel;
}
return networkCache[networkIndex].radioChannel;
}
void emberAfGetMfgString(uint8_t* returnData)
{
static uint8_t mfgString[MFG_STRING_MAX_LENGTH];
static bool mfgStringRetrieved = false;
if (mfgStringRetrieved == false) {
ezspGetMfgToken(EZSP_MFG_STRING, mfgString);
mfgStringRetrieved = true;
}
// NOTE: The MFG string is not NULL terminated.
MEMMOVE(returnData, mfgString, MFG_STRING_MAX_LENGTH);
}
void emAfClearNetworkCache(uint8_t networkIndex)
{
networkCache[networkIndex].nodeId = EMBER_NULL_NODE_ID;
networkCache[networkIndex].panId = 0xFFFF;
networkCache[networkIndex].networkState = UNKNOWN_NETWORK_STATE;
networkCache[networkIndex].radioChannel = 0xFF;
}
// Some NCP's support a 'maximize packet buffer' call. If that doesn't
// work, slowly ratchet up the packet buffer count.
static void setPacketBufferCount(void)
{
uint16_t value;
EzspStatus ezspStatus;
EzspStatus maxOutBufferStatus;
maxOutBufferStatus
= ezspSetConfigurationValue(EZSP_CONFIG_PACKET_BUFFER_COUNT,
EZSP_MAXIMIZE_PACKET_BUFFER_COUNT);
// We start from the default used by the NCP and increase up from there
// rather than use a hard coded default in the code.
// This is more portable to different NCP hardware (i.e. 357 vs. 260).
ezspStatus = ezspGetConfigurationValue(EZSP_CONFIG_PACKET_BUFFER_COUNT,
&value);
if (maxOutBufferStatus == EZSP_SUCCESS) {
emberAfAppPrintln("NCP supports maxing out packet buffers");
goto setPacketBufferCountDone;
}
while (ezspStatus == EZSP_SUCCESS) {
value++;
ezspStatus = ezspSetConfigurationValue(EZSP_CONFIG_PACKET_BUFFER_COUNT,
value);
}
setPacketBufferCountDone:
emberAfAppPrintln("Ezsp Config: set packet buffers to %d",
maxOutBufferStatus == EZSP_SUCCESS
? value
: (value - 1));
emberAfAppFlush();
}
// initialize the network co-processor (NCP)
void emAfResetAndInitNCP(void)
{
uint8_t ep;
EzspStatus ezspStatus;
bool memoryAllocation;
uint16_t seed0, seed1;
emberAfPreNcpResetCallback();
// ezspInit resets the NCP by calling halNcpHardReset on a SPI host or
// ashResetNcp on a UART host
ezspStatus = ezspInit();
if (ezspStatus != EZSP_SUCCESS) {
emberAfCorePrintln("ERROR: ezspForceReset 0x%x", ezspStatus);
emberAfCoreFlush();
//assert(false);
printf("[%s][%d]\n",__FUNCTION__,__LINE__);
return;
}
// send the version command before any other commands
emAfCliVersionCommand();
emSecureEzspInit();
// The random number generator on the host needs to be seeded with some
// random data, which we can get from the NCP.
ezspGetRandomNumber(&seed0);
ezspGetRandomNumber(&seed1);
halStackSeedRandom(((uint32_t)seed1 << 16) | (uint32_t)seed0);
// set the source route table size
emberAfSetEzspConfigValue(EZSP_CONFIG_SOURCE_ROUTE_TABLE_SIZE,
SOURCE_ROUTE_TABLE_SIZE,
"source route table size");
emberAfSetEzspConfigValue(EZSP_CONFIG_SECURITY_LEVEL,
EMBER_SECURITY_LEVEL,
"security level");
// set the address table size
emberAfSetEzspConfigValue(EZSP_CONFIG_ADDRESS_TABLE_SIZE,
EMBER_AF_PLUGIN_ADDRESS_TABLE_SIZE,
"address table size");
// set the trust center address cache size
emberAfSetEzspConfigValue(EZSP_CONFIG_TRUST_CENTER_ADDRESS_CACHE_SIZE,
EMBER_AF_PLUGIN_ADDRESS_TABLE_TRUST_CENTER_CACHE_SIZE,
"TC addr cache");
// the stack profile is defined in the config file
emberAfSetEzspConfigValue(EZSP_CONFIG_STACK_PROFILE,
EMBER_STACK_PROFILE,
"stack profile");
// BUG 14222: If stack profile is 2 (ZigBee Pro), we need to enforce
// the standard stack configuration values for that feature set.
if ( EMBER_STACK_PROFILE == 2 ) {
// MAC indirect timeout should be 7.68 secs
emberAfSetEzspConfigValue(EZSP_CONFIG_INDIRECT_TRANSMISSION_TIMEOUT,
7680,
"MAC indirect TX timeout");
// Max hops should be 2 * nwkMaxDepth, where nwkMaxDepth is 15
emberAfSetEzspConfigValue(EZSP_CONFIG_MAX_HOPS,
30,
"max hops");
}
emberAfSetEzspConfigValue(EZSP_CONFIG_TX_POWER_MODE,
EMBER_AF_TX_POWER_MODE,
"tx power mode");
emberAfSetEzspConfigValue(EZSP_CONFIG_SUPPORTED_NETWORKS,
EMBER_SUPPORTED_NETWORKS,
"supported networks");
// allow other devices to modify the binding table
emberAfSetEzspPolicy(EZSP_BINDING_MODIFICATION_POLICY,
EZSP_CHECK_BINDING_MODIFICATIONS_ARE_VALID_ENDPOINT_CLUSTERS,
"binding modify",
"allow for valid endpoints & clusters only");
// return message tag and message contents in ezspMessageSentHandler()
emberAfSetEzspPolicy(EZSP_MESSAGE_CONTENTS_IN_CALLBACK_POLICY,
EZSP_MESSAGE_TAG_AND_CONTENTS_IN_CALLBACK,
"message content in msgSent",
"return");
{
uint8_t value[2];
value[0] = LOW_BYTE(EMBER_AF_INCOMING_BUFFER_LENGTH);
value[1] = HIGH_BYTE(EMBER_AF_INCOMING_BUFFER_LENGTH);
emberAfSetEzspValue(EZSP_VALUE_MAXIMUM_INCOMING_TRANSFER_SIZE,
2, // value length
value,
"maximum incoming transfer size");
value[0] = LOW_BYTE(EMBER_AF_MAXIMUM_SEND_PAYLOAD_LENGTH);
value[1] = HIGH_BYTE(EMBER_AF_MAXIMUM_SEND_PAYLOAD_LENGTH);
emberAfSetEzspValue(EZSP_VALUE_MAXIMUM_OUTGOING_TRANSFER_SIZE,
2, // value length
value,
"maximum outgoing transfer size");
}
// Set the manufacturing code. This is defined by ZigBee document 053874r10
// Ember's ID is 0x1002 and is the default, but this can be overridden in App Builder.
emberSetManufacturerCode(EMBER_AF_MANUFACTURER_CODE);
// Call the plugin and user-specific NCP inits. This is when configuration
// that affects table sizes should occur, which means it must happen before
// setPacketBufferCount.
memoryAllocation = true;
#ifdef EMBER_AF_GENERATED_PLUGIN_NCP_INIT_FUNCTION_CALLS
EMBER_AF_GENERATED_PLUGIN_NCP_INIT_FUNCTION_CALLS
#endif
emberAfNcpInitCallback(memoryAllocation);
setPacketBufferCount();
// Call the plugin and user-specific NCP inits again. This is where non-
// sizing configuration should occur.
memoryAllocation = false;
#ifdef EMBER_AF_GENERATED_PLUGIN_NCP_INIT_FUNCTION_CALLS
EMBER_AF_GENERATED_PLUGIN_NCP_INIT_FUNCTION_CALLS
#endif
emberAfNcpInitCallback(memoryAllocation);
// create endpoints
for ( ep = 0; ep < emberAfEndpointCount(); ep++ ) {
createEndpoint(ep);
}
EM_AF_NETWORK_INIT();
MEMSET(cachedConfigIdValues, 0xFF, ((EZSP_CONFIG_ID_MAX + 1) * sizeof(uint16_t)));
cacheConfigIdValuesAllowed = true;
// Set the localEui64 global
ezspGetEui64(emLocalEui64);
// Initialize messageSentCallbacks table
emAfInitializeMessageSentCallbackArray();
}
// *******************************************************************
// *******************************************************************
// The main() loop and the application's contribution.
void emberAfMainInit(void)
{
}
int emberAfMain(MAIN_FUNCTION_PARAMETERS)
{
SETUP_FAKE_EEPROM_FOR_SIMULATION();
//Initialize the hal
halInit();
INTERRUPTS_ON(); // Safe to enable interrupts at this point
{
int returnCode;
if (emberAfMainStartCallback(&returnCode,
APP_FRAMEWORK_MAIN_ARGUMENTS)) { //get serial port info
return returnCode;
}
}
kk_print("*******************123****************\r\n");
kk_print_info("\r\n-----hello world![%s:%s]-----\r\n",__DATE__,__TIME__);
kk_print_version();
emberSerialInit(APP_SERIAL, BAUD_RATE, PARITY_NONE, 1); //fock child process
emberAfAppPrintln("Reset info: %d (%p)",
halGetResetInfo(),
halGetResetString());
int ret = pthread_mutex_init(&g_mutex_lock, NULL);
if (ret != 0) {
printf("mutex init failed\n");
return -1;
}
/*int pid=fork();
if(pid==0){
rpcInterfaceParse();
}*/
emberAfCoreFlush();
// This will initialize the stack of networks maintained by the framework,
// including setting the default network.
emAfInitializeNetworkIndexStack();
// We must initialize the endpoint information first so
// that they are correctly added by emAfResetAndInitNCP()
emberAfEndpointConfigure();
// initialize the network co-processor (NCP)
emAfResetAndInitNCP();
printf("[%s][%d]\n",__FUNCTION__,__LINE__);
EmberEUI64 eui64;
emberAfGetEui64(eui64);
emberAfCorePrintln("~~~~~~~~~~~~~~~~~~~~~NCP MAC:");
emberAfPrintBigEndianEui64(eui64);
kk_network_check();
kk_device_gateway_add(eui64);
pthread_t tid;
//pthread_create(&tid, NULL, rpcInterfaceParse, NULL);
pthread_create(&tid, NULL, ipcHandle, NULL);
// initialize the ZCL framework ,(plug in) ,mqtt init is here
emAfInit();
COMMAND_READER_INIT();
// main loop
while (true) {
halResetWatchdog(); // Periodically reset the watchdog.
// see if the NCP has anything waiting to send us
ezspTick();
while (ezspCallbackPending()) {
ezspCallback();
}
// check if we have hit an EZSP Error and need to reset and init the NCP
if (ncpNeedsResetAndInit) {
ncpNeedsResetAndInit = false;
// re-initialize the NCP
emAfResetAndInitNCP();
}
// Wait until ECC operations are done. Don't allow any of the clusters
// to send messages as the NCP is busy doing ECC
if (emAfIsCryptoOperationInProgress()) {
continue;
}
// let the ZCL Utils run - this should go after ezspTick
emAfTick();
emberSerialBufferTick();
emberAfRunEvents();
#if defined(ZA_CLI_FULL)
if (emberProcessCommandInput(APP_SERIAL))
{
#if !defined GATEWAY_APP
// Gateway app. has its own way of handling the command-line prompt.
emberAfGuaranteedPrint("%p>", ZA_PROMPT);
#endif
}
#endif
#if defined(EMBER_TEST)
if (1) {
// Simulation only
uint32_t timeToNextEventMax = emberMsToNextStackEvent();
timeToNextEventMax = emberAfMsToNextEvent(timeToNextEventMax);
simulatedTimePassesMs(timeToNextEventMax);
}
#endif
// After each interation through the main loop, our network index stack
// should be empty and we should be on the default network index again.
emAfAssertNetworkIndexStackIsEmpty();
}
return 0;
}
// ******************************************************************
// binding
// ******************************************************************
EmberStatus emberAfSendEndDeviceBind(uint8_t endpoint)
{
EmberStatus status;
EmberEUI64 eui;
uint8_t inClusterCount, outClusterCount;
EmberAfClusterId clusterList[MAX_CLUSTER];
EmberAfClusterId *inClusterList;
EmberAfClusterId *outClusterList;
EmberAfProfileId profileId;
EmberApsOption options = ((EMBER_AF_DEFAULT_APS_OPTIONS
| EMBER_APS_OPTION_SOURCE_EUI64)
& ~EMBER_APS_OPTION_RETRY);
uint8_t index = emberAfIndexFromEndpoint(endpoint);
if (index == 0xFF) {
return EMBER_INVALID_ENDPOINT;
}
status = emberAfPushEndpointNetworkIndex(endpoint);
if (status != EMBER_SUCCESS) {
return status;
}
emberAfGetEui64(eui);
emberAfZdoPrintln("send %x %2x ", endpoint, options);
inClusterList = clusterList;
inClusterCount = emberAfGetClustersFromEndpoint(endpoint,
inClusterList,
MAX_CLUSTER,
true); // server?
outClusterList = clusterList + inClusterCount;
outClusterCount = emberAfGetClustersFromEndpoint(endpoint,
outClusterList,
(MAX_CLUSTER
- inClusterCount),
false); // server?
profileId = emberAfProfileIdFromIndex(index);
status = ezspEndDeviceBindRequest(emberAfGetNodeId(),
eui,
endpoint,
profileId,
inClusterCount, // cluster in count
outClusterCount, // cluster out count
inClusterList, // list of input clusters
outClusterList, // list of output clusters
options);
emberAfZdoPrintln("done: %x.", status);
emberAfPopNetworkIndex();
return status;
}
// **********************************************************************
// this function sets an EZSP config value and prints out the results to
// the serial output
// **********************************************************************
EzspStatus emberAfSetEzspConfigValue(EzspConfigId configId,
uint16_t value,
PGM_P configIdName)
{
EzspStatus ezspStatus = ezspSetConfigurationValue(configId, value);
emberAfAppFlush();
emberAfAppPrint("Ezsp Config: set %p to 0x%2x:", configIdName, value);
emberAfAppDebugExec(emAfPrintStatus("set", ezspStatus));
emberAfAppFlush();
emberAfAppPrintln("");
emberAfAppFlush();
// If this fails, odds are the simulated NCP doesn't have enough
// memory allocated to it.
EMBER_TEST_ASSERT(ezspStatus == EZSP_SUCCESS);
return ezspStatus;
}
// **********************************************************************
// this function sets an EZSP policy and prints out the results to
// the serial output
// **********************************************************************
EzspStatus emberAfSetEzspPolicy(EzspPolicyId policyId,
EzspDecisionId decisionId,
PGM_P policyName,
PGM_P decisionName)
{
EzspStatus ezspStatus = ezspSetPolicy(policyId,
decisionId);
emberAfAppPrint("Ezsp Policy: set %p to \"%p\":",
policyName,
decisionName);
emberAfAppDebugExec(emAfPrintStatus("set",
ezspStatus));
emberAfAppPrintln("");
emberAfAppFlush();
return ezspStatus;
}
// **********************************************************************
// this function sets an EZSP value and prints out the results to
// the serial output
// **********************************************************************
EzspStatus emberAfSetEzspValue(EzspValueId valueId,
uint8_t valueLength,
uint8_t *value,
PGM_P valueName)
{
EzspStatus ezspStatus = ezspSetValue(valueId, valueLength, value);
emberAfAppPrint("Ezsp Value : set %p to ", valueName);
// print the value based on the length of the value
// for length 1/2/4 bytes, fetch int of that length and promote to 32 bits for printing
switch (valueLength) {
case 1:
emberAfAppPrint("0x%4x:", (uint32_t)(*value));
break;
case 2:
emberAfAppPrint("0x%4x:", (uint32_t)(*((uint16_t *)value)));
break;
case 4:
emberAfAppPrint("0x%4x:", (uint32_t)(*((uint32_t *)value)));
break;
default:
emberAfAppPrint("{val of len %x}:", valueLength);
break;
}
emberAfAppDebugExec(emAfPrintStatus("set", ezspStatus));
emberAfAppPrintln("");
emberAfAppFlush();
return ezspStatus;
}
// ******************************************************************
// setup endpoints and clusters for responding to ZDO requests
// ******************************************************************
//
// Creates the endpoint for 260 by calling ezspAddEndpoint()
//
static void createEndpoint(uint8_t endpointIndex)
{
uint16_t clusterList[MAX_CLUSTER];
uint16_t *inClusterList;
uint16_t *outClusterList;
uint8_t endpoint = emberAfEndpointFromIndex(endpointIndex);
uint8_t inClusterCount;
uint8_t outClusterCount;
{
EmberStatus status = emberAfPushEndpointNetworkIndex(endpoint);
if (status != EMBER_SUCCESS) {
emberAfAppPrintln("Error in creating endpoint %d: 0x%x", endpoint, status);
return;
}
}
// Lay out clusters in the arrays.
inClusterList = clusterList;
inClusterCount = emberAfGetClustersFromEndpoint(endpoint, inClusterList, MAX_CLUSTER, true);
outClusterList = clusterList + inClusterCount;
outClusterCount = emberAfGetClustersFromEndpoint(endpoint, outClusterList, (MAX_CLUSTER - inClusterCount), false);
// Call EZSP function with data.
{
EzspStatus status = ezspAddEndpoint(endpoint,
emberAfProfileIdFromIndex(endpointIndex),
emberAfDeviceIdFromIndex(endpointIndex),
emberAfDeviceVersionFromIndex(endpointIndex),
inClusterCount,
outClusterCount,
(uint16_t *)inClusterList,
(uint16_t *)outClusterList);
if (status == EZSP_SUCCESS) {
emberAfAppPrintln("Ezsp Endpoint %d added, profile 0x%2x, in clusters: %d, out clusters %d",
endpoint,
emberAfProfileIdFromIndex(endpointIndex),
inClusterCount,
outClusterCount);
} else {
emberAfAppPrintln("Error in creating endpoint %d: 0x%x", endpoint, status);
}
}
emberAfPopNetworkIndex();
}
// *******************************************************************
// Handlers required to use the Ember Stack.
// Called when the stack status changes, usually as a result of an
// attempt to form, join, or leave a network.
void ezspStackStatusHandler(EmberStatus status)
{
emberAfPushCallbackNetworkIndex();
emAfStackStatusHandler(status);
emberAfPopNetworkIndex();
}
EmberNodeId emberGetSender(void)
{
return currentSender;
}
uint8_t emberAfGetBindingIndex(void)
{
return currentBindingIndex;
}
uint8_t emberAfGetAddressIndex(void)
{
return currentAddressIndex;
}
// This is not called if the incoming message did not contain the EUI64 of
// the sender.
void ezspIncomingSenderEui64Handler(EmberEUI64 senderEui64)
{
// current sender is now valid
MEMMOVE(currentSenderEui64, senderEui64, EUI64_SIZE);
currentSenderEui64IsValid = true;
}
EmberStatus emberGetSenderEui64(EmberEUI64 senderEui64)
{
// if the current sender EUI is valid then copy it in and send it back
if (currentSenderEui64IsValid) {
MEMMOVE(senderEui64, currentSenderEui64, EUI64_SIZE);
return EMBER_SUCCESS;
}
// in the not valid case just return error
return EMBER_ERR_FATAL;
}
//
// ******************************************************************
void ezspIncomingMessageHandler(EmberIncomingMessageType type,
EmberApsFrame *apsFrame,
uint8_t lastHopLqi,
int8_t lastHopRssi,
EmberNodeId sender,
uint8_t bindingIndex,
uint8_t addressIndex,
uint8_t messageLength,
uint8_t *messageContents)
{
uint8_t sourceRouteOverhead;
emberAfPushCallbackNetworkIndex();
// The following code caches valid Source Route overheads sent pro actively
// by the NCP and uses it once to calculate the overhead for a target, after
// which it gets cleared.
sourceRouteOverhead = getSourceRouteOverhead(messageLength);
emberAfSetSourceRouteOverheadCallback(sender, sourceRouteOverhead);
currentSender = sender;
currentBindingIndex = bindingIndex;
currentAddressIndex = addressIndex;
emAfIncomingMessageHandler(type,
apsFrame,
lastHopLqi,
lastHopRssi,
messageLength,
messageContents);
currentSenderEui64IsValid = false;
currentSender = EMBER_NULL_NODE_ID;
currentBindingIndex = EMBER_NULL_BINDING;
currentAddressIndex = EMBER_NULL_ADDRESS_TABLE_INDEX;
// Invalidate the sourceRouteOverhead cached at the end of the current incomingMessageHandler
emberAfSetSourceRouteOverheadCallback(sender, EZSP_SOURCE_ROUTE_OVERHEAD_UNKNOWN);
emberAfPopNetworkIndex();
}
// Called when a message we sent is acked by the destination or when an
// ack fails to arrive after several retransmissions.
void ezspMessageSentHandler(EmberOutgoingMessageType type,
uint16_t indexOrDestination,
EmberApsFrame *apsFrame,
uint8_t messageTag,
EmberStatus status,
uint8_t messageLength,
uint8_t *messageContents)
{
emberAfPushCallbackNetworkIndex();
#ifdef EMBER_AF_PLUGIN_FRAGMENTATION
if (emAfFragmentationMessageSent(apsFrame, status)) {
goto kickout;
}
#endif //EMBER_AF_PLUGIN_FRAGMENTATION
emAfMessageSentHandler(type,
indexOrDestination,
apsFrame,
status,
messageLength,
messageContents,
messageTag);
goto kickout; // silence a warning when not using fragmentation
kickout:
emberAfPopNetworkIndex();
}
void emberChildJoinHandler(uint8_t index, bool joining)
{
}
// This is called when an EZSP error is reported
void ezspErrorHandler(EzspStatus status)
{
emberAfCorePrintln("ERROR: ezspErrorHandler 0x%x", status);
emberAfCoreFlush();
// Rather than detect whether or not we can recover from the error,
// we just flag the NCP for reboot.
// Do not reset if this is a decryption failure, as we ignored the packet.
if (status != EZSP_ERROR_SECURITY_PARAMETERS_INVALID) {
ncpNeedsResetAndInit = true;
}
}
EmberStatus emberAfEzspSetSourceRoute(EmberNodeId id)
{
#ifdef EZSP_APPLICATION_HAS_ROUTE_RECORD_HANDLER
uint16_t relayList[ZA_MAX_HOPS];
uint8_t relayCount;
if (emberFindSourceRoute(id, &relayCount, relayList)
&& ezspSetSourceRoute(id, relayCount, relayList) != EMBER_SUCCESS) {
return EMBER_SOURCE_ROUTE_FAILURE;
}
#endif
return EMBER_SUCCESS;
}
EmberStatus emAfSend(EmberOutgoingMessageType type,
uint16_t indexOrDestination,
EmberApsFrame *apsFrame,
uint8_t messageLength,
uint8_t *message,
uint8_t *messageTag,
EmberNodeId alias,
uint8_t sequence)
{
EmberStatus status;
*messageTag = ezspNextSequence();
switch (type) {
case EMBER_OUTGOING_DIRECT:
case EMBER_OUTGOING_VIA_ADDRESS_TABLE:
case EMBER_OUTGOING_VIA_BINDING:
{
status = emberAfEzspSetSourceRoute(indexOrDestination);
if (status == EMBER_SUCCESS) {
status = ezspSendUnicast(type,
indexOrDestination,
apsFrame,
*messageTag,
(uint8_t)messageLength,
message,
&apsFrame->sequence);
}
break;
}
case EMBER_OUTGOING_MULTICAST:
{
status = ezspSendMulticast(apsFrame,
ZA_MAX_HOPS, // hops
ZA_MAX_HOPS, // nonmember radius
*messageTag,
messageLength,
message,
&apsFrame->sequence);
break;
}
case EMBER_OUTGOING_MULTICAST_WITH_ALIAS:
{
status = ezspSendMulticastWithAlias(apsFrame,
apsFrame->radius, //radius
apsFrame->radius, //nonmember radius
alias,
sequence,
*messageTag,
messageLength,
message,
&apsFrame->sequence);
break;
}
case EMBER_OUTGOING_BROADCAST:
{
status = ezspSendBroadcast(indexOrDestination,
apsFrame,
ZA_MAX_HOPS, // radius
*messageTag,
messageLength,
message,
&apsFrame->sequence);
break;
}
case EMBER_OUTGOING_BROADCAST_WITH_ALIAS:
status = ezspProxyBroadcast(alias,
indexOrDestination,
sequence,
apsFrame,
apsFrame->radius, // radius
*messageTag,
messageLength,
message,
&apsFrame->sequence);
break;
default:
status = EMBER_BAD_ARGUMENT;
}
return status;
}
// Platform dependent interface to get various stack parameters.
void emberAfGetEui64(EmberEUI64 returnEui64)
{
MEMCOPY(returnEui64, emLocalEui64, EUI64_SIZE);
}
EmberStatus emberAfGetNetworkParameters(EmberNodeType* nodeType,
EmberNetworkParameters* parameters)
{
return ezspGetNetworkParameters(nodeType, parameters);
}
EmberStatus emberAfGetNodeType(EmberNodeType *nodeType)
{
EmberNetworkParameters parameters;
return ezspGetNetworkParameters(nodeType, &parameters);
}
// This will cache all config items to make sure repeated calls do not
// go all the way to the NCP.
uint8_t emberAfGetNcpConfigItem(EzspConfigId id)
{
// In case we can't cache config items yet, we need a temp
// variable to store the retrieved EZSP config ID.
uint16_t temp = 0xFFFF;
uint16_t *configItemPtr = &temp;
bool cacheValid;
EMBER_TEST_ASSERT(id <= EZSP_CONFIG_ID_MAX);
cacheValid = (cacheConfigIdValuesAllowed
&& id <= EZSP_CONFIG_ID_MAX);
if (cacheValid) {
configItemPtr = &(cachedConfigIdValues[id]);
}
if (*configItemPtr == 0xFFFF
&& EZSP_SUCCESS != ezspGetConfigurationValue(id,
configItemPtr)) {
// We return a 0 size (for tables) on error to prevent code from using the
// invalid value of 0xFFFF. This is particularly necessary for loops that
// iterate over all indexes.
return 0;
}
return (uint8_t)(*configItemPtr);
}
EmberStatus emberAfGetSourceRouteTableEntry(
uint8_t index,
EmberNodeId *destination,
uint8_t *closerIndex)
{
return ezspGetSourceRouteTableEntry(index,
destination,
closerIndex);
}
uint8_t emberAfGetSourceRouteTableFilledSize(void)
{
return ezspGetSourceRouteTableFilledSize();
}
uint8_t emberAfGetSourceRouteTableTotalSize(void)
{
return ezspGetSourceRouteTableTotalSize();
}
EmberStatus emberAfGetChildData(uint8_t index,
EmberChildData *childData)
{
return ezspGetChildData(index,
childData);
}
uint8_t emberAfGetChildTableSize(void)
{
return emberAfGetNcpConfigItem(EZSP_CONFIG_MAX_END_DEVICE_CHILDREN);
}
uint8_t emberAfGetKeyTableSize(void)
{
return emberAfGetNcpConfigItem(EZSP_CONFIG_KEY_TABLE_SIZE);
}
uint8_t emberAfGetAddressTableSize(void)
{
return emberAfGetNcpConfigItem(EZSP_CONFIG_ADDRESS_TABLE_SIZE);
}
uint8_t emberAfGetBindingTableSize(void)
{
return emberAfGetNcpConfigItem(EZSP_CONFIG_BINDING_TABLE_SIZE);
}
uint8_t emberAfGetNeighborTableSize(void)
{
return emberAfGetNcpConfigItem(EZSP_CONFIG_NEIGHBOR_TABLE_SIZE);
}
uint8_t emberAfGetRouteTableSize(void)
{
return emberAfGetNcpConfigItem(EZSP_CONFIG_ROUTE_TABLE_SIZE);
}
uint8_t emberAfGetSecurityLevel(void)
{
return emberAfGetNcpConfigItem(EZSP_CONFIG_SECURITY_LEVEL);
}
uint8_t emberAfGetStackProfile(void)
{
return emberAfGetNcpConfigItem(EZSP_CONFIG_STACK_PROFILE);
}
uint8_t emberAfGetSleepyMulticastConfig(void)
{
return emberAfGetNcpConfigItem(EZSP_CONFIG_SEND_MULTICASTS_TO_SLEEPY_ADDRESS);
}
// On the System-on-a-chip this function is provided by the stack.
// Here is a copy for the host based applications.
void emberReverseMemCopy(uint8_t* dest, const uint8_t* src, uint16_t length)
{
uint16_t i;
uint16_t j = (length - 1);
for ( i = 0; i < length; i++) {
dest[i] = src[j];
j--;
}
}
// ******************************************************************
// Functions called by the Serial Command Line Interface (CLI)
// ******************************************************************
// *****************************
// emAfCliVersionCommand
//
// version <no arguments>
// *****************************
void emAfCliVersionCommand(void)
{
// Note that NCP == Network Co-Processor
EmberVersion versionStruct;
// the EZSP protocol version that the NCP is using
uint8_t ncpEzspProtocolVer;
// the stackType that the NCP is running
uint8_t ncpStackType;
// the EZSP protocol version that the Host is running
// we are the host so we set this value
uint8_t hostEzspProtocolVer = EZSP_PROTOCOL_VERSION;
// send the Host version number to the NCP. The NCP returns the EZSP
// version that the NCP is running along with the stackType and stackVersion
ncpEzspProtocolVer = ezspVersion(hostEzspProtocolVer,
&ncpStackType,
&ncpStackVer);
// verify that the stack type is what is expected
if (ncpStackType != EZSP_STACK_TYPE_MESH) {
emberAfAppPrint("ERROR: stack type 0x%x is not expected!",
ncpStackType);
assert(false);
}
// verify that the NCP EZSP Protocol version is what is expected
if (ncpEzspProtocolVer != EZSP_PROTOCOL_VERSION) {
emberAfAppPrint("ERROR: NCP EZSP protocol version of 0x%x does not match Host version 0x%x\r\n",
ncpEzspProtocolVer,
hostEzspProtocolVer);
assert(false);
}
emberAfAppPrint("ezsp ver 0x%x stack type 0x%x ",
ncpEzspProtocolVer, ncpStackType);
if (EZSP_SUCCESS != ezspGetVersionStruct(&versionStruct)) {
// NCP has Old style version number
emberAfAppPrintln("stack ver [0x%2x]", ncpStackVer);
kk_set_ezsp_version_info(hostEzspProtocolVer,ncpEzspProtocolVer,ncpStackType,ncpStackVer,NULL);
} else {
// NCP has new style version number
emAfParseAndPrintVersion(versionStruct);
kk_set_ezsp_version_info(hostEzspProtocolVer,ncpEzspProtocolVer,ncpStackType,ncpStackVer,&versionStruct);
}
emberAfAppFlush();
}
uint8_t emAfGetPacketBufferFreeCount(void)
{
uint8_t freeCount;
uint8_t valueLength = 1;
ezspGetValue(EZSP_VALUE_FREE_BUFFERS,
&valueLength,
&freeCount);
return freeCount;
}
uint8_t emAfGetPacketBufferTotalCount(void)
{
uint16_t value;
ezspGetConfigurationValue(EZSP_CONFIG_PACKET_BUFFER_COUNT,
&value);
return (uint8_t)value;
}
// WARNING: This function executes in ISR context
void halNcpIsAwakeIsr(bool isAwake)
{
if (isAwake) {
emberAfNcpIsAwakeIsrCallback();
} else {
// If we got indication that the NCP failed to wake up
// there is not much that can be done. We will reset the
// host (which in turn will reset the NCP) and that will
// hopefully bring things back in sync.
assert(0);
}
}
void ezspNetworkFoundHandler(EmberZigbeeNetwork *networkFound,
uint8_t lqi,
int8_t rssi)
{
emberAfPushCallbackNetworkIndex();
#ifdef EMBER_AF_PLUGIN_FORM_AND_JOIN
if (!emberFormAndJoinNetworkFoundHandler(networkFound, lqi, rssi))
#endif
emberAfNetworkFoundCallback(networkFound, lqi, rssi);
emberAfPopNetworkIndex();
}
void ezspScanCompleteHandler(uint8_t channel, EmberStatus status)
{
emberAfPushCallbackNetworkIndex();
#ifdef EMBER_AF_PLUGIN_FORM_AND_JOIN
if (!emberFormAndJoinScanCompleteHandler(channel, status))
#endif
emberAfScanCompleteCallback(channel, status);
emberAfPopNetworkIndex();
}
void ezspEnergyScanResultHandler(uint8_t channel, int8_t rssi)
{
emberAfPushCallbackNetworkIndex();
#ifdef EMBER_AF_PLUGIN_FORM_AND_JOIN
if (!emberFormAndJoinEnergyScanResultHandler(channel, rssi))
#endif
emberAfEnergyScanResultCallback(channel, rssi);
emberAfPopNetworkIndex();
}
void ezspUnusedPanIdFoundHandler(EmberPanId panId, uint8_t channel)
{
emberAfPushCallbackNetworkIndex();
#ifdef EMBER_AF_PLUGIN_FORM_AND_JOIN
if (!emberFormAndJoinUnusedPanIdFoundHandler(panId, channel))
#endif
emberAfUnusedPanIdFoundCallback(panId, channel);
emberAfPopNetworkIndex();
}
void emAfPrintEzspEndpointFlags(uint8_t endpoint)
{
EzspEndpointFlags flags;
EzspStatus status = ezspGetEndpointFlags(endpoint,
&flags);
if (status != EZSP_SUCCESS) {
emberAfCorePrint("Error retrieving EZSP endpoint flags.");
} else {
emberAfCorePrint("- EZSP Endpoint flags: 0x%2X", flags);
}
}
void emSetAddDelay(uint8_t delay)
{
//XXXEZSP
}
void ezspZigbeeKeyEstablishmentHandler(EmberEUI64 partner,
EmberKeyStatus status)
{
// This function is generated.
emAfZigbeeKeyEstablishment(partner, status);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment