#include "kk_device_manager.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "kk_product_code.h"
#include "kk_device_table_db.h"
#include "kk_ncp_msg.h"
#include "kk_zigbee_api.h"
#include "zb_device_id.h"


//#include "sub_device_manage.h"



/****************** ******************************************************************
* File Name			: kk_device_manager.c
* Author			: yjq
* data				: 2020/09/01
*************************************************************************************/
#define KK_GP_EP									242




static const char *kk_match_tsl_productCode(const char* modelId)
{
	int i;
	int num = kk_get_product_code_table_size();

	UTIL_LOG_INFO("device model id:%s,%d\n",modelId,strlen(modelId));
	for(i=0;i<num && kk_product_code[i].modelId!=NULL;i++){
		if(strstr(modelId,kk_product_code[i].modelId)!=NULL){
			UTIL_LOG_INFO("match model id:%s\n",kk_product_code[i].modelId);
			UTIL_LOG_INFO("tsl product code:%s\n",kk_product_code[i].code);
			#ifdef KK_PRODUCT_CODE_STRING_ENABLE
			UTIL_LOG_INFO("match product:%s\n",kk_product_code[i].name);
			#endif
			
			return kk_product_code[i].code;
		}
	}
	return NULL;
}

////////////////////////////////////////////////////





static int kk_match_device_id(uint16_t deviceId)
{
	int i;

	if(deviceId==0xffff) return -1;
	for(i=0;zb_device_id[i].deviceId!=0xffff;i++){
		if(zb_device_id[i].deviceId==deviceId){
			emberAfDebugPrint("device:");
			#ifdef ZIGBEE_DEVICE_ID_STRING_ENABLE
				emberAfDebugPrintln("%s",zb_device_id[i].deviceIdString);
			#endif
			return 0;
		}
	}
	return -2;
}





static void kk_device_modle_id_identify(EmberNodeId nodeId,
													uint8_t status,
													uint8_t dataType,
													uint8_t dataSize,
													uint8_t *data)
{
	
	kk_device_table_s *ptr = kk_get_device_table_pointer();
	EmberEUI64 eui64;
	uint8_t modelID[33] = {0};
	char *pCode = NULL;
	while(ptr!=NULL){
		if(ptr->nodeId == nodeId){
			emberAfCorePrintln("[match tsl]node:0x%04X,status:0x%02x,dataType:0x%02x",nodeId,status,dataType);
			if(status==EMBER_ZCL_STATUS_SUCCESS ){//dataType==ZCL_CHAR_STRING_ATTRIBUTE_TYPE
				ptr->identifyCnt = 0;
				if(dataSize>=32){
					dataSize = 32;
					emberAfCorePrintln("[warring]modle id size = %d,max = 32!!!");
				}
				memcpy(modelID,data,dataSize);
				pCode = kk_match_productCode(modelID);
				if(pCode == NULL){
					emberAfCorePrintln("not match pCode!!!");
					return;
				}
				memcpy(ptr->productCode,pCode,strlen(pCode));
				if(ptr->productCode!=NULL){
					if(emberAfDeviceTableGetEui64FromNodeId(ptr->nodeId,eui64)){
						kk_msg_report_dev_joined(eui64,ptr->productCode);
						kk_device_db_update(eui64,ptr->nodeId,ptr->deviceId,ptr->productCode);
						kk_device_config_map_add(ptr->productCode);
					}else{
						UTIL_LOG_WARNING("not find mac from node in device table!!!");
					}
				}else{
					emberAfCorePrintln("not match tsl!!!");
				}
			}else if(status==EMBER_ZCL_STATUS_UNSUPPORTED_ATTRIBUTE){
				ptr->identifyCnt = 0;
				emberAfCorePrintln("nodeId:0x%04X,unsupport model id attr,CNT=%d",nodeId,ptr->identifyCnt);
				//to do :zdo leave ???
			}else{
				emberAfCorePrintln("nodeId:0x%04X,read modle id fail,status=0x%x",nodeId,status);
			}
			return;
		}
		ptr = ptr->next;
	}

}
void kk_read_attr_response(EmberNodeId nodeId,
										uint8_t ep,
										EmberAfClusterId cluster,
										EmberAfAttributeId attribute,
										uint8_t status,
										uint8_t dataType,
										uint8_t dataSize,
										uint8_t *data)
{
	emberAfAppPrintln("ep=%d,cluster=0x%04X,attribute=0x%04X",ep,cluster,attribute);
	if(cluster==ZCL_BASIC_CLUSTER_ID){
		if(attribute==ZCL_MODEL_IDENTIFIER_ATTRIBUTE_ID){
			if(ep==KK_PRIMARY_EP)
				kk_device_modle_id_identify(nodeId,status,dataType,dataSize,data);
		}
	}

	kk_colorlight_attr_read(nodeId,ep,cluster,attribute,status,dataType,dataSize,data);

}
void emberAfPluginDeviceTableNewDeviceCallback(EmberEUI64 nodeEui64)
{
	kk_device_joined(emberAfDeviceTableGetNodeIdFromEui64(nodeEui64));
}
void emberAfPluginDeviceTableRejoinDeviceCallback(EmberEUI64 nodeEui64)
{
	kk_device_joined(emberAfDeviceTableGetNodeIdFromEui64(nodeEui64));
}

void emberAfPluginDeviceTableDeviceLeftCallback(EmberEUI64 nodeEui64)
{
	uint16_t deviceTableIndex = emberAfDeviceTableGetFirstIndexFromEui64(nodeEui64);

	if(deviceTableIndex == EMBER_AF_PLUGIN_DEVICE_TABLE_NULL_INDEX){
		return ;
	}
	EmberAfPluginDeviceTableEntry *deviceTable = emberAfDeviceTablePointer();

	cJSON* nodeJson = rpc_reportDeviceState("left",deviceTable[deviceTableIndex].eui64);
	rpc_printfJSON("left",nodeJson);

	kk_msg_report_dev_leave(deviceTable[deviceTableIndex].eui64);

	kk_device_table_delete(deviceTable[deviceTableIndex].eui64);
	kk_device_db_delete(deviceTable[deviceTableIndex].eui64);
}



void kk_productCode_tick()
{
	kk_device_table_s *ptr = kk_get_device_table_pointer();
	EmberEUI64 eui64;
	EmberStatus status;

	
	while(ptr!=NULL){
		//emberAfCorePrintln("%d",strlen(ptr->productCode));
		if(strlen(ptr->productCode)==0){
			
			if(ptr->nodeId!=0xffff && ptr->identifyCnt!=0){
				status = zclGRead(ptr->nodeId,
									1,
									1,
									false,
									ZCL_BASIC_CLUSTER_ID,
									ZCL_MODEL_IDENTIFIER_ATTRIBUTE_ID,
									true);
				--ptr->identifyCnt;
				emberAfCorePrintln("read model id from node:0x%02x,status=0x%x,cnt=%d",ptr->nodeId,status,ptr->identifyCnt);
			}else{
				emberAfCorePrintln("not find node!");
			}
		}
		ptr = ptr->next;

	}
}


//to do:syn kk device table with ember device table
void kk_add_device_to_table(EmberEUI64 mac,EmberNodeId nodeId,uint16_t deviceId)
{
	UTIL_LOG_INFO("\n------------------------kk add device------------------------\n");
	emberAfAppPrint("mac:");
	emberAfPrintBigEndianEui64(mac);
	emberAfAppPrintln("\nnode:0x%04X,device id:0x%04x",nodeId,deviceId);

	kk_match_device_id(deviceId);
	
	kk_device_table_add(mac,nodeId,NULL,deviceId);
	kk_device_db_insert(mac,nodeId,deviceId,"");
	//kk_msg_report_dev_joined(mac,"85");
	//kk_device_db_update(mac,nodeId,deviceId,"85");
	//kk_device_config_map_add("85");	
}


void kk_network_check(void)
{
	EmberEUI64 eui64;
	EmberPanId panId;
	EmberStatus status;
	if(ezspNetworkState()!= EMBER_JOINED_NETWORK ){
		emberAfGetEui64(eui64);
		panId = HIGH_LOW_TO_INT(eui64[1],eui64[0]);
		status = kk_network_form(true,panId,KK_NETWORK_PARAMETER_TX_POWER,KK_NETWORK_PARAMETER_CHANNEL);
		if(status==EMBER_SUCCESS){
			UTIL_LOG_INFO("network form success~~~~~~");
			kk_print_network_info();
		}else{
			emberAfAppPrintln("network form fail!!!,status=0x%x",status);
		}
	}else{
		kk_print_network_info();
	}
}

//int rpc_nwkPermitJoin(jrpc_context * ctx,const char *mac,unsigned char ep,void* data)
int kk_permit_join(jrpc_context * ctx,EmberNodeId node,unsigned char ep,void* data)
{
	EmberStatus status;
	int isEnable = *(int*)data;

	//kk_network_check();

	if(isEnable == 0){
		status = nwkPermitJoinCMD(FALSE);
		emberAfCorePrintln("Disable Permit join\r\n");
	}else if(isEnable == 1){
		status = nwkPermitJoinCMD(TRUE);
		emberAfCorePrintln("Enable Permit join %ds\r\n",EMBER_AF_PLUGIN_NETWORK_CREATOR_SECURITY_NETWORK_OPEN_TIME_S);
	}else{
		set_json_error_type(ctx,JRPC_INVALID_PARAMS,MSG_INVALID_PARAMS);
		goto error_return;
	}

	return status;

error_return:
	return -1;
}

int kk_wlist_ctrl(jrpc_context * ctx,EmberNodeId node,unsigned char ep,void* data)
{
	EmberStatus status = 0;
	int isEnable = *(int*)data;

	status = kk_wlist_status_open(isEnable);//1: open; 0:close

	return status;


}



#define KK_DEVICE_MAP_TABLE_FILE					"/usr/kk/dev_config_table/dev_map_table.json"
#define KK_DEVICE_MAP_TABLE_ARRAY_IDENTIFY			"mapTable"

#define KK_DEVICE_CONFIG_MAP_TABLE_ARRAY_IDENTIFY			"config"
#define KK_DEVICE_CONFIG_MAP_TABLE_EXTRA_DATA_IDENTIFY		"extra data"

typedef struct kk_dev_map{
	char * modleId;
	char * productCode;
	char * productName;
	struct kk_dev_map * next;
}kk_dev_map;

static kk_dev_map *device_map = NULL;
bool kk_device_map_add(const char *modleId,const char *productCode,const char *productName)
{
	int len;
	kk_dev_map *ptr,*pre;
	
	ptr = pre = device_map;

	if(modleId == NULL &&productCode == NULL) return false;
	
	while(ptr!=NULL){
		pre = ptr;
		ptr = ptr->next;
	}
	ptr = (kk_dev_map*)malloc(sizeof(kk_dev_map));

	memset(ptr,0,sizeof(kk_dev_map));

	len = strlen(modleId);
	ptr->modleId = (char *)malloc(len+1);
	memcpy(ptr->modleId, modleId,len);
	ptr->modleId[len] = '\0';

	len = strlen(productCode);
	ptr->productCode = (char *)malloc(len+1);
	memcpy(ptr->productCode, productCode,len);
	ptr->productCode[len] = '\0';

	if(productName!=NULL){
		len = strlen(productName);
		ptr->productName = (char *)malloc(len+1);
		memcpy(ptr->productName, productName,len);
		ptr->productName[len] = '\0';
	}

	if(device_map==NULL){
		device_map = ptr;
	}else{
		pre->next = ptr;
	}

	return true;
}
void kk_device_map_print(void )
{
	int cnt = 1;
	kk_dev_map *ptr = device_map;
	
	UTIL_LOG_INFO("\n***************device map list print***************\n");
	
	while(ptr!=NULL){
		emberAfCorePrintln("--------------------%d--------------------\n",cnt++);
		emberAfCorePrintln("modleId:%s\n",ptr->modleId);
		emberAfCorePrintln("productCode:%s\n",ptr->productCode);
		if(ptr->productName){
			emberAfCorePrintln("productName:%s\n",ptr->productName);
		}
		ptr = ptr->next;
	}
	
}
void kk_load_dev_map_table(void)
{
	int len;
	int bufferSize;

	int fd = open(KK_DEVICE_MAP_TABLE_FILE,O_RDONLY);
	if(fd<0){
		UTIL_LOG_ERR("can not open %s,fd=%d!!!\n",KK_DEVICE_MAP_TABLE_FILE,fd);
		return ;
	}

	struct stat statbuff;
	stat(KK_DEVICE_MAP_TABLE_FILE, &statbuff);
	bufferSize = statbuff.st_size + 128;

	uint8_t *buffer = (uint8_t *)malloc(bufferSize);

	memset(buffer,0,bufferSize);
;
	
	UTIL_LOG_INFO("\n***************load device map table***************\n");

	len = read(fd,buffer ,bufferSize);
	if(len<0){
		free(buffer);
		close(fd);
		UTIL_LOG_ERR("can not read %s!!!\n",KK_DEVICE_MAP_TABLE_FILE);
		return ;
	}
	

	cJSON * map = rpc_cJSON_Parse(buffer);
	if(map == NULL){
		free(buffer);
		UTIL_LOG_INFO("can not load dev map table!!!\n");
		return ;
	}

	char* p = rpc_cJSON_Print(map);
	if(p!=NULL){
		emberAfCorePrintln("device map table JSON:\n%s\n",p);
		free(p);
	}

	kk_add_dev_map_table_to_list(map);
	free(buffer);
	close(fd);
	
	rpc_cJSON_Delete(map);


}

void kk_add_dev_map_table_to_list(cJSON * root)
{
	int i,len,size;
	cJSON *item,*modelId,*productCode,*productName;
	cJSON * table = rpc_cJSON_GetObjectItem(root,KK_DEVICE_MAP_TABLE_ARRAY_IDENTIFY);

	if(table==NULL){
		UTIL_LOG_INFO("can not add dev map to list!!!\n");
		return ;
	}
	size = rpc_cJSON_GetArraySize(table);

	
	for(i=0;i<size;i++){
		item = rpc_cJSON_GetArrayItem(table,i);
		modelId = cJSON_GetObjectItem(item, "modleId");
		productCode = cJSON_GetObjectItem(item, "productCode");
		productName = cJSON_GetObjectItem(item, "productName");
		kk_device_map_add(modelId->valuestring,productCode->valuestring,productName->valuestring);
	}
}

char *kk_match_productCode(const char* modelId)
{
	kk_dev_map *ptr = device_map;
	UTIL_LOG_INFO("\n***************match productCode***************\n");
	UTIL_LOG_INFO("device model id:%s\n",modelId);

	while(ptr!=NULL){
		if(strstr(modelId,ptr->modleId)!=NULL){
			UTIL_LOG_INFO("match model id:%s\n",ptr->modleId);
			UTIL_LOG_INFO("tsl product code:%s\n",ptr->productCode);
			if(ptr->productName!=NULL){
				UTIL_LOG_INFO("match product:%s\n",ptr->productName);
			}
			return ptr->productCode;
		}
		ptr = ptr->next;
	}

	return NULL;
}


static kk_dev_config_map *dev_config_map = NULL;

#define KK_DEVICE_CONFIG_MAP_TABLE_FILE_PREFIX			"/usr/kk/dev_config_table/device_%s.json"



kk_dev_config_item *kk_device_config_item_find_by_identity(kk_dev_config_map * map,const char* identity)
{
	kk_dev_config_item *item;
	item = &map->item;
	while(item!=NULL){
		if(!strcmp(item->identity,identity)){
			return item;
		}
		item = item->next;
	}
	return NULL;
}

									
									



kk_dev_config_map *kk_device_config_find(const char *productCode)
{
	kk_dev_config_map *ptr,*pre;

	ptr = pre = dev_config_map;
	
	if(productCode==NULL) return NULL;
	
	while(ptr!=NULL){
		if(!memcmp(ptr->productCode,productCode,strlen(productCode))){
			return ptr;
		}
		pre = ptr;
		ptr = ptr->next;
	}
	return NULL;
}
void kk_device_config_item_report(EmberEUI64 eui64,uint8_t EP,EmberAfClusterId clu,EmberAfAttributeId attr,
								uint8_t dataType,uint8_t len,uint8_t *data)
{
	int status;
	kk_dev_config_item *item;
	kk_dev_config_map * cfgMap;
	char *pCode;
	kk_rpc_report func;

	pCode = kk_device_find_productCode(eui64);

	cfgMap = kk_device_config_find(pCode);

	if(cfgMap==NULL) {
		emberAfDebugPrintln("cfgMap==NULL!");
		return ;
	}
	item = &cfgMap->item;
	
	while(item!=NULL){
		if(item->endpoint == EP &&
			item->cluster == clu &&
			item->attribute == attr){
			if(item->reportFunc!=NULL){
				func = item->reportFunc;
				emberAfCorePrintln("[call]:%s\n",item->reportFuncName);
				status = func(eui64,EP,clu,attr,dataType,len,data);
				emberAfDebugPrintln("report status:%d",status);
				break;
			}
		}
		item = item->next;
	}

}

kk_rpc_set kk_find_rpc_set_function_api(const char *name)
{
	int rpcFuncSize = kk_get_rpc_set_api_size();
	for(int i=0;i<rpcFuncSize;i++){
		if(!strcmp(kk_rpc_set_api[i].name,name)){
			return kk_rpc_set_api[i].set;
		}
	}
	return NULL;
}
kk_rpc_report kk_find_rpc_report_function_api(const char *name)
{
	int rpcFuncSize = kk_get_rpc_report_api_size();
	for(int i=0;i<rpcFuncSize;i++){
		if(!strcmp(kk_rpc_report_api[i].name,name)){
			return kk_rpc_report_api[i].report;
		}
	}
	return NULL;
}

bool kk_device_config_exist_check(const char *productCode)
{
	kk_dev_config_map *ptr = dev_config_map;
	
	while(ptr!=NULL){
		if(!strcmp(ptr->productCode,productCode)) return true;
		ptr = ptr->next;
	}
	return false;
}

bool kk_device_config_add(const char *productCode,const char *identity,uint8_t ep,uint16_t clu,uint16_t attr,uint16_t mask,const char *reportFuncName,const char *controlFuncName)
{
	int len;
	kk_dev_config_map *ptr,*pre,*pTemp;
	kk_dev_config_item *item,*itemPre,*newItem;

	ptr = kk_device_config_find(productCode);


	
	if(ptr==NULL){
		ptr = (kk_dev_config_map*)malloc(sizeof(kk_dev_config_map));

		memset(ptr,0,sizeof(kk_dev_config_map));

		len = strlen(productCode);
		ptr->productCode = (char *)malloc(len+1);
		memcpy(ptr->productCode, productCode,len);
		ptr->productCode[len] = '\0';
		
		len = strlen(identity);
		ptr->item.identity = (char *)malloc(len+1);
		memcpy(ptr->item.identity, identity,len);
		ptr->item.identity[len] = '\0';
		
		ptr->item.endpoint = ep;
		ptr->item.cluster = clu;
		ptr->item.attribute = attr;
		ptr->item.iasZoneStatusMask = mask;

		len = strlen(reportFuncName);
		ptr->item.reportFuncName = (char *)malloc(len+1);
		memcpy(ptr->item.reportFuncName, reportFuncName,len);
		ptr->item.reportFuncName[len] = '\0';

		len = strlen(controlFuncName);
		ptr->item.controlFuncName = (char *)malloc(len+1);
		memcpy(ptr->item.controlFuncName, controlFuncName,len);
		ptr->item.controlFuncName[len] = '\0';

		ptr->item.reportFunc = kk_find_rpc_report_function_api(reportFuncName);
		ptr->item.controlFunc = kk_find_rpc_set_function_api(controlFuncName);
		

		if(dev_config_map==NULL){
			dev_config_map = ptr;
			
		}else{
			pTemp = dev_config_map;
			
			while(pTemp!=NULL){
				pre = pTemp;
				pTemp = pTemp->next;
			}
			
			pTemp = pre;
			pTemp->next = ptr;
		}
	}else{
	
		item = &ptr->item;
		while(item!=NULL){
			itemPre = item;
			item = item->next;
		}
	
		newItem = (kk_dev_config_item *)malloc(sizeof(kk_dev_config_item));
		memset(newItem,0,sizeof(kk_dev_config_item));

		
		len = strlen(identity);
		newItem->identity = (char *)malloc(len+1);
		memcpy(newItem->identity, identity,len);
		newItem->identity[len] = '\0';
		
		newItem->endpoint = ep;
		newItem->cluster = clu;
		newItem->attribute = attr;
		newItem->iasZoneStatusMask = mask;
		
		len = strlen(reportFuncName);
		newItem->reportFuncName = (char *)malloc(len+1);
		memcpy(newItem->reportFuncName, reportFuncName,len);
		newItem->reportFuncName[len] = '\0';
		
		len = strlen(controlFuncName);
		newItem->controlFuncName = (char *)malloc(len+1);
		memcpy(newItem->controlFuncName, controlFuncName,len);
		newItem->controlFuncName[len] = '\0';
			
		newItem->reportFunc = kk_find_rpc_report_function_api(reportFuncName);
		newItem->controlFunc = kk_find_rpc_set_function_api(controlFuncName);
	

		itemPre->next = newItem;
	
	}

	return true;
}

void kk_append_extra_data_to_list(const char *productCode,kk_dev_config_item_extra_data *data)
{
	kk_dev_config_map * map = kk_device_config_find(productCode);
	if(data==NULL) return ;
	
	if(map!=NULL){
		kk_dev_config_item *item = &map->item;
		while(item!=NULL){
			if(item->identity!=NULL &&
				data->tag!=NULL
				&&(strcmp(item->identity,data->tag)==0)){
				data->tag = item->identity;//note!!!
				item->data = data;
				return ;
			}
			item = item->next;
		}
		
	}
}
bool get_extra_data_from_hexString(char *tag,char *str,kk_dev_config_item_extra_data *extra)
{
	if(str == NULL) return false;

	int len = strlen(str);
	
	if(len<2) return false;
	
	len = len/3+1;

	uint8_t *data = (uint8_t *)malloc(len);
	for(int i=0;i<len;i++){
		data[i] = (rpc_convert_char(str[3*i])<<4)|rpc_convert_char((str[3*i+1]));
	}

	extra->len = len;
	extra->data = data;
	extra->tag = tag;
	return true;
}


kk_dev_config_item_extra_data * kk_find_extra_data_by_productCode(const char *productCode,const char * tag)
{
	kk_dev_config_map * map = NULL;
	kk_dev_config_item *item = NULL;
	kk_dev_config_item_extra_data *data;
	map = kk_device_config_find(productCode);
	item = &map->item;
	
	while(item!=NULL){
		if(item->data!=NULL ){
			data = item->data;
			while(data!=NULL){
				if(!strcmp(item->identity,tag)){
					return item->data;
				}
				data = data->next;
			}
			
		}
		item = item->next;
	}
	return NULL;

}

kk_dev_config_item_extra_data * kk_find_extra_data(EmberNodeId node,const char * tag)
{
	EmberEUI64 mac;
	char *productCode = NULL;
	kk_dev_config_map * map = NULL;

	if(emberLookupEui64ByNodeId(node,mac)==EMBER_SUCCESS){
		productCode = kk_device_find_productCode(mac);
		map = kk_device_config_find(productCode);
		return kk_find_extra_data_by_productCode(productCode,tag);
	}
	return NULL;
}
void kk_add_dev_config_map_table_to_list(cJSON * root,const char *productCode)
{
	uint8_t ep = 0;
	uint16_t clu = 0;
	uint16_t attr = 0;
	uint16_t mask = 0;
	int i,j,len,size,extraSize;
	cJSON *item,*identity;
	cJSON *endpoint,*cluster,*attribute,*reportFuncName,*controlFuncName;
	cJSON *extraRoot,*extraData,*extraDataItem;
	cJSON *iasZoneStatusMask;

	cJSON * table = rpc_cJSON_GetObjectItem(root,KK_DEVICE_CONFIG_MAP_TABLE_ARRAY_IDENTIFY);
	kk_dev_config_item_extra_data *pData = NULL,*ptr = NULL;

	if(table==NULL){
		UTIL_LOG_INFO("can not add dev map to list!!!\n");
		return ;
	}
	size = rpc_cJSON_GetArraySize(table);

	for(i=0;i<size;i++){
		item = rpc_cJSON_GetArrayItem(table,i);
		identity = cJSON_GetObjectItem(item, "identity");
		endpoint = cJSON_GetObjectItem(item, "endpoint");
		cluster = cJSON_GetObjectItem(item, "cluster");
		attribute = cJSON_GetObjectItem(item, "attribute");
		reportFuncName = cJSON_GetObjectItem(item, "reportFunc");
		controlFuncName = cJSON_GetObjectItem(item, "controlFunc");
		iasZoneStatusMask = cJSON_GetObjectItem(item, "iasStatusMask");
		extraRoot = cJSON_GetObjectItem(item, KK_DEVICE_CONFIG_MAP_TABLE_EXTRA_DATA_IDENTIFY);
		if(extraRoot!=NULL){
			extraSize = rpc_cJSON_GetArraySize(extraRoot);
			emberAfCorePrintln("extraSize:%d\n",extraSize);
		

			
			
			for(j=0;j<extraSize;j++){
				extraData = rpc_cJSON_GetArrayItem(extraRoot,j);
				if(!strcmp("1022",productCode)){
					char buffer[20] = {0};
					sprintf(buffer,"mode_%d",j+1);

					extraDataItem = cJSON_GetObjectItem(extraData,buffer);
					if(extraDataItem!=NULL){
						emberAfCorePrintln("extraDataItem:%s\n",extraDataItem->valuestring);
						extraDataItem = cJSON_GetObjectItem(extraData, "data");
						
						if(extraDataItem!=NULL){
							kk_dev_config_item_extra_data *extra = (kk_dev_config_item_extra_data *)malloc(sizeof(kk_dev_config_item_extra_data));
							memset(extra,0,sizeof(kk_dev_config_item_extra_data));
							emberAfCorePrintln("extraDataItem:%s\n",extraDataItem->valuestring);
							get_extra_data_from_hexString(identity->valuestring,extraDataItem->valuestring,extra);

							if(ptr==NULL){
								ptr = extra;
								pData = extra;
							}else{
								ptr->next = extra;
								ptr = extra;
							}
						}
					}
				}
			}
		}

		ep = endpoint->valueint;
		
		if(cluster!=NULL){
			len = strlen(cluster->valuestring);
			if(len >=4){
				clu = rpc_get_u16(&cluster->valuestring[len-4]);
			}else{
				continue ;
			}
		}
		if(attribute!=NULL){
			len = strlen(attribute->valuestring);
			if(len >=4){
				attr = rpc_get_u16(&attribute->valuestring[len-4]);
			}else{
				continue ;
			}
		}
		
		if(clu==ZCL_IAS_ZONE_CLUSTER_ID && attr== ZCL_ZONE_STATUS_ATTRIBUTE_ID){
			if(iasZoneStatusMask!=NULL){
				len = strlen(iasZoneStatusMask->valuestring);
				mask = rpc_get_u16(&iasZoneStatusMask->valuestring[len-4]);
			}
		}
		kk_device_config_add(productCode,identity->valuestring,ep,clu,attr,mask,reportFuncName->valuestring,controlFuncName->valuestring);
		kk_append_extra_data_to_list(productCode,pData);


	}
	kk_device_config_map_print();
}


void kk_device_config_map_load(const char * devFile,const char *productCode)
{
	int len;
	int bufferSize;
	int fd = open(devFile,O_RDONLY);
	struct stat statbuff;

	if(kk_device_config_exist_check(productCode)==true){
		UTIL_LOG_ERR("devFile[%s] is already load!!!\n",devFile);
		return ;
	}

	
	stat(devFile, &statbuff);
	bufferSize = statbuff.st_size + 128;
	uint8_t *buffer = (uint8_t *)malloc(bufferSize);
	memset(buffer,0,bufferSize);
		
	UTIL_LOG_INFO("\n***************load device config map table***************\n");
	if(fd<0){
		free(buffer);
		UTIL_LOG_ERR("can not open %s,fd=%d!!!\n",devFile,fd);
		return ;
	}
	len = read(fd,buffer ,bufferSize);
	if(len<0){
		free(buffer);
		close(fd);
		UTIL_LOG_ERR("can not read %s!!!\n",devFile);
		return ;
	}
	

	cJSON * map = rpc_cJSON_Parse(buffer);
	if(map == NULL){
		UTIL_LOG_INFO("len=%d,data:%s\n",len,buffer);
		UTIL_LOG_INFO("can not load dev map table!!!\n");
		free(buffer);
		return ;
	}

	char* p = rpc_cJSON_Print(map);
	if(p!=NULL){
		emberAfCorePrintln("device map table JSON:\n%s\n",p);
		free(p);
	}

	free(buffer);
	close(fd);
	kk_add_dev_config_map_table_to_list(map,productCode);
	rpc_cJSON_Delete(map);
}
bool kk_device_config_map_add(const char *productCode)
{
	int len;
	char devfile[128];
	
	UTIL_LOG_INFO("\n***************device config map add***************\n");
	
	if(productCode==NULL) return false;
	sprintf(devfile,KK_DEVICE_CONFIG_MAP_TABLE_FILE_PREFIX,productCode);
	emberAfCorePrintln("devfile:%s\n",devfile);
	kk_device_config_map_load(devfile,productCode);



	return true;
}
void kk_device_config_map_print(void)
{
	int cnt1=1,cnt2 = 1,cnt3 =1;
	kk_dev_config_map *ptr = dev_config_map;
	kk_dev_config_item *item;
	kk_dev_config_item_extra_data *extra;
	UTIL_LOG_INFO("\n***************device config map list print***************\n");

	while(ptr!=NULL){
		emberAfCorePrintln("--------------------%d--------------------\n",cnt1++);
		emberAfCorePrintln("productCode:%s\n",ptr->productCode);
		item = &ptr->item;
		cnt2 = 0;
		while(item!=NULL){
			emberAfCorePrintln("**************%d**************\n",cnt2++);
			emberAfCorePrintln("identity:%s\n",item->identity);
			emberAfCorePrintln("endpoint:%d\n",item->endpoint);
			emberAfCorePrintln("cluster:0x%04X\n",item->cluster);
			emberAfCorePrintln("attribute:0x%04X\n",item->attribute);
			emberAfCorePrintln("iasZoneStatusMask:0x%04X\n",item->iasZoneStatusMask);
			emberAfCorePrintln("reportFunc:%s\n",item->reportFuncName);
			emberAfCorePrintln("controlFunc:%s\n",item->controlFuncName);
			extra = item->data;
			while(extra!=NULL){
				emberAfCorePrintln("~~~~~~~~~~~%d~~~~~~~~~~",cnt3++);
				emberAfCorePrintBuffer(extra->data,extra->len,true);
				emberAfCorePrintln("\n");
				extra = extra->next;
			}
			item = item->next;
		}

		ptr = ptr->next;
	}
}








void kk_rpc_report_attribute(EmberEUI64 eui64,
									uint8_t EP,
									EmberAfClusterId clusterId,
									EmberAfAttributeId attributeId,
									uint8_t dataType,
									uint8_t len,
									uint8_t *data)
{
	int i,j,num,status;
	char macString[19] = {0};	

	char * pCode;
	
	int res = 0;

	UTIL_LOG_INFO("\n********************kk rpc report attribute********************\n");
	emberAfDebugPrint("mac:");
	emberAfDebugPrintln(",ep:%d,clu:0x%04X,attr:0x%04X,dataType=0x%02x,len=%d,data:",
						EP,clusterId,attributeId,dataType,len);
	emberAfDebugPrintBuffer(data,len,true);
	

	kk_device_config_item_report(eui64,EP,clusterId,attributeId,dataType,len,data);

}

void kk_device_gateway_add(EmberEUI64 eui64)
{
	kk_device_config_map_add("2");
	kk_device_table_add(eui64,0,"2",0);
}



