#include<stdio.h>
#include <string.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include "kk_data_handle.h"
#include "kk_opcode.h"
#include "com_api.h"
#include "kk_data_mng.h"
#include "kk_lan_ctrl.h"
#include "kk_lan_sync.h"
#include "kk_lan_debug.h"
#include "kk_findccu_handle.h"
#include "kk_voice_panel_handle.h"
#include "kk_lan_node_db.h"
#include "kk_oldccu_msg.h"
#include "kk_login_handle.h"


const char DM_MSG_TO_MIDDWARE[] = "{\"msgtype\":\"%s\",\"productCode\":\"%s\",\"deviceCode\":\"%s\"}";
static char *strrpl(char *in, char *out, int outlen, char *src, char *dst)
{
	char *p = in;
	unsigned int  len = outlen - 1;

	// 这几段检查参数合法性
	if((NULL == src) || (NULL == dst) || (NULL == in) || (NULL == out))
	{
		return NULL;
	}
	if((strcmp(in, "") == 0) || (strcmp(src, "") == 0))
	{
		return NULL;
	}
	if(outlen <= 0)
	{
		return NULL;
	}
	
	while((*p != '\0') && (len > 0))
	{
		if(strncmp(p, src, strlen(src)) != 0)
		{
			int n = strlen(out);
 
			out[n] = *p;
			out[n + 1] = '\0';
 
			p++;
			len--;
		}
		else
		{
			strcat(out, dst);
			p += strlen(src);
			len -= strlen(dst);
		}
	}
	return out;
}
char * _kk_data_create(char *msgtype,const char *productCode,const char *deviceCode,const char *param)
{
	cJSON *root;
	cJSON *payload;
	cJSON* infoObj;
	char *out;
	char *infoStr = NULL;
	int infoStr_len = 0;
	int res = 0;
	char method[128] = {0};

	strrpl(msgtype+1,method,sizeof(method),"/",".");
	printf("method:%s\n",method);
	infoStr_len = strlen(DM_MSG_TO_MIDDWARE)+strlen(productCode)+strlen(deviceCode)+strlen(msgtype)+10;
	infoStr = malloc(infoStr_len);
	if(infoStr == NULL){
		ERROR_PRINT("[%s][%d]\n",__FUNCTION__,__LINE__);
		return NULL;
	}
	memset(infoStr,0x0,infoStr_len);
	snprintf(infoStr,infoStr_len,DM_MSG_TO_MIDDWARE,msgtype,productCode,deviceCode);

	root=cJSON_CreateObject();
	infoObj = cJSON_Parse(infoStr);
	cJSON_AddItemToObject(root, MSG_INFO_STR, infoObj);

	payload = cJSON_CreateObject();
	if(payload){
		cJSON_AddItemToObject(root, MSG_PAYLOAD_STR, payload);	
		cJSON_AddStringToObject(payload, "msgId", "*");
		cJSON_AddStringToObject(payload, "version", "1.0");
		cJSON_AddStringToObject(payload, "method", method);
		cJSON_AddStringToObject(payload, "params", param);
	}
	out=cJSON_Print(root);
	cJSON_Minify(out);
	cJSON_Delete(root);
	free(infoStr);
	INFO_PRINT("[out]%s\n",out);	
	
	return out;
	//free(out);	/* Print to text, Delete the cJSON, print it, release the string. */
}




extern void kk_sync_info_push(void);
extern void kk_sync_info(void);

void kk_handle_sync_info(void)
{
	kk_sync_info();
}
void kk_handle_sync_push_info(void)
{
	kk_sync_info_push();
}


void kk_handle_get_history_info(void)
{
	char *send_data = NULL;
	send_data  = _kk_data_create(GET_HISTORY_MSG_TYPE,"*","*","*");
	if(send_data == NULL){
		return;
	}
	INFO_PRINT("kk_ipc_send........%s	\n",send_data);
	kk_ipc_send(IPC_APP2MID, send_data, strlen(send_data)+1);
	free(send_data);
}
static int kk_send_ack(cJSON *root,int sockfd)
{
	char *out = NULL;
	char *tmpBuf = NULL;
	out=cJSON_Print(root);
	cJSON_Minify((char*)out);
	tmpBuf = calloc(strlen(out) + 4,1);
	if(tmpBuf == NULL){
		free(out);
		return -1;
	}
	strcat(tmpBuf,"!");
	strcat(tmpBuf,out);
	strcat(tmpBuf,"$");
	INFO_PRINT("tmpBuf:%s\n",tmpBuf);
	send(sockfd, tmpBuf, strlen(tmpBuf), 0);
	free(out);
	free(tmpBuf);
	return 0; 
}

static int kk_heartbeat_ack(int sockfd)
{
	cJSON *root;
	root=cJSON_CreateObject();
	if(root){
		cJSON_AddStringToObject(root, "nodeid", "*");
		cJSON_AddStringToObject(root, "opcode", HEARTBEAT_OPCODE);
		cJSON_AddStringToObject(root, "status", "success");
		cJSON_AddStringToObject(root, "arg", "*");
		kk_send_ack(root,sockfd);
	}
	cJSON_Delete(root);
	return 0;
}
static int kk_loginccu_ack(cJSON *arg,int sockfd)
{
	cJSON *zkid;
	cJSON *root;
	cJSON *args;
	char *out = NULL;
	char *tmpBuf = NULL;
	if(arg == NULL){
		return -1;
	}
	char ccuid[32] = {0};
	kk_lan_get_ccuid(ccuid);	
	zkid = cJSON_GetObjectItem(arg, ZKID_STRING);
	if(zkid != NULL){
		if(strstr(ccuid,zkid->valuestring) != NULL){
			root=cJSON_CreateObject();
			if(root){
				args = cJSON_CreateObject();
				if(args){
					cJSON_AddItemToObject(root, "arg", args);
					cJSON_AddStringToObject(args, "error_code", "0");
					cJSON_AddStringToObject(args, "seq", "");
					cJSON_AddStringToObject(args, "zkid", zkid->valuestring);
				}
				cJSON_AddStringToObject(root, "nodeid", "*");
				cJSON_AddStringToObject(root, "opcode", LOGIN_OPCODE);
				cJSON_AddStringToObject(root, "status", "success");
				kk_send_ack(root,sockfd);
			}
			cJSON_Delete(root);
		}
	}else{
		ERROR_PRINT("data error...\n");
		return -1;
	}
	return 0;
}

//构建hw信息
static cJSON *kk_zb_dev_hw_info_build(const char *deviceCode,const char *productCode,int online,const char *hw_ver,const char *sw_ver)
{
	cJSON *item;
	char mac[32] = {0};
	int online_status = 0;
	int pid;
	if(mac==NULL){
		return NULL;
	}
	
	item = cJSON_CreateObject();
	if(item){
		if(hw_ver!=NULL){
			cJSON_AddStringToObject(item, "hardware_version", hw_ver);
		}else{
			cJSON_AddStringToObject(item, "hardware_version", "");
		}
		_deviceCode_switchto_mac(deviceCode,mac);

		if(online==0){
			online_status = 2; //离线
		}else if(online==1){
			online_status = 1; //在线
		}else{
			online_status = 0; //未知
		}
		pid = atoi(productCode);
		
		cJSON_AddStringToObject(item, "mac", mac);
		cJSON_AddNumberToObject(item, "online_status",online_status);
		cJSON_AddNumberToObject(item, "product_id", pid);

		if(sw_ver!=NULL){
			cJSON_AddStringToObject(item, "version", sw_ver);
		}else{
			cJSON_AddStringToObject(item, "version", "");
		}
	}
	return item;
}

static void _kk_zb_devs_hw_ack(int sockfd,cJSON *arg)
{
	cJSON *root;
	root=cJSON_CreateObject();
	if(root){
		cJSON_AddStringToObject(root, "nodeid", "*");
		cJSON_AddStringToObject(root, "opcode", GET_ZB_DEVS_HW_INFO_OPCODE);
		cJSON_AddStringToObject(root, "status", "success");
		cJSON_AddItemToObject(root, "arg", arg);
		kk_send_ack(root,sockfd);
	}
	cJSON_Delete(root);
}

int kk_zb_devs_hw_ack_all(int sockfd)
{
	kk_map_dev_ctx *ctx = _kk_map_dev_ctx();
	kk_map_dev_node_t *search_node = NULL;
	cJSON *array = cJSON_CreateArray();
	cJSON *item;
	
	_kk_map_dev_mutex_lock();
	list_for_each_entry(search_node, &ctx->dev_list, linked_list, kk_map_dev_node_t) {
		if((item = kk_zb_dev_hw_info_build(search_node->deviceCode,search_node->productCode,search_node->online_status,NULL,NULL))!=NULL){
			cJSON_AddItemToArray(array,item);
		}
	}
	_kk_map_dev_mutex_unlock();
	
	_kk_zb_devs_hw_ack(sockfd,array);
	return 0;
}

cJSON * kk_zb_dev_hw_info_build_by_deviceCode(int sockfd,const char *deviceCode,int online)//
{
	kk_map_dev_ctx *ctx = _kk_map_dev_ctx();
	kk_map_dev_node_t *search_node = NULL;
	cJSON *item;
	unsigned char online_status = 0;
	int pid =-1;

	_kk_map_dev_mutex_lock();
	list_for_each_entry(search_node, &ctx->dev_list, linked_list, kk_map_dev_node_t) {
		if ( (strlen(search_node->deviceCode) == strlen(deviceCode)) &&
			(memcmp(search_node->deviceCode, deviceCode, strlen(deviceCode)) == 0)) {
			if(online == -1){
				item = kk_zb_dev_hw_info_build(search_node->deviceCode,search_node->productCode,search_node->online_status,NULL,NULL);
			}else{
				item = kk_zb_dev_hw_info_build(search_node->deviceCode,search_node->productCode,online,NULL,NULL);
			}
			_kk_map_dev_mutex_unlock();
			return item;
		}
	}
	_kk_map_dev_mutex_unlock();
	return NULL;
}


static void kk_zb_devs_hw_ack(int sockfd,cJSON *conditions)
{
	int i,size;
	cJSON *type;
	cJSON *arg;
	
	char devCode[33] ={0};
	
	type = cJSON_GetObjectItem(conditions,"condition_type");
	if(type==NULL){
		kk_zb_devs_hw_ack_all(sockfd);
	}else{
		if(strcmp(type->valuestring,"dev_list")){
			WARNING_PRINT("[type err]%s,%s\n",type->valuestring,"dev_list");
			return ;
		}
		arg = cJSON_GetObjectItem(conditions,"condition_arg");
		size = cJSON_GetArraySize(arg);
		cJSON *qMac;
		cJSON *item;
		cJSON *array = cJSON_CreateArray();
		for(i=0;i<size;i++){
			qMac=cJSON_GetArrayItem(arg,i);
			if(mac_switchto_deviceCode(qMac->valuestring,devCode)==0){
				if((item=kk_zb_dev_hw_info_build_by_deviceCode(sockfd,devCode,-1))!=NULL){
					cJSON_AddItemToArray(array,item);
				}
			}
		}
		_kk_zb_devs_hw_ack(sockfd,array);
	}
	return ;
}

static void kk_handle_del_history_info(char *key)
{
	char *send_data = NULL;
	send_data  = _kk_data_create(DEL_HISTORY_MSG_TYPE,"*","*",key);
	if(send_data == NULL){
		return;
	}
	kk_ipc_send(IPC_APP2MID, send_data, strlen(send_data)+1);
	free(send_data);
}







int kk_data_handle(cJSON *json,int sockfd)
{
	cJSON *opcode = NULL;
	cJSON *arg = NULL;

	opcode = cJSON_GetObjectItem(json, OPCODE_STRING);
	if(opcode != NULL){
		if(strcmp(opcode->valuestring,LOGIN_OPCODE) == 0){
			arg = cJSON_GetObjectItem(json, ARG_STRING);
			kk_loginccu_ack(arg,sockfd);
		}else if(strcmp(opcode->valuestring,HEARTBEAT_OPCODE) == 0){
			kk_heartbeat_ack(sockfd);
		}else if(strcmp(opcode->valuestring,SYNC_OPCODE) == 0){
			kk_handle_sync_info();
		}else if(strcmp(opcode->valuestring,GET_ZB_DEVS_HW_INFO_OPCODE) == 0){
			cJSON *conditions = cJSON_GetObjectItem(json, OPCODE_STRING);
			kk_zb_devs_hw_ack(sockfd,conditions);
		}else if(strcmp(opcode->valuestring,GET_HISTORY_ALARM_LOG) == 0){
			kk_handle_get_history_info();
		}else if(strcmp(opcode->valuestring,DEL_HISTORY_ALARM_LOG) == 0){
			cJSON *key = cJSON_GetObjectItem(json, "arg");
			if(key != NULL){
				kk_handle_del_history_info(key->valuestring);
			}
		}else if(strcmp(opcode->valuestring,GET_CCU_INFO) == 0){
			char *send_data = _kk_data_create(KK_THING_SERVICE_GET_CCU_INFO,"*","*","*");
			kk_ipc_send(IPC_APP2MID, send_data, strlen(send_data)+1);
		}
		#ifdef VOICE_SUPPORT
		else if(strcmp(opcode->valuestring,VOICE_VOLUME_CTRL) == 0){
			cJSON *vol = cJSON_GetObjectItem(json, "arg");
			if(vol != NULL){
				kk_voice_control(atoi(vol->valuestring));
			}
		}else if(strcmp(opcode->valuestring,VOICE_SWITCH_CTRL) == 0){
			cJSON *onff = cJSON_GetObjectItem(json, "arg");
			int value = 0;
			if(onff != NULL){
				if(strcmp(onff->valuestring,"on") == 0){
					value = 1;
				}else{
					value = 0;
				}
    			kk_voice_switch(value);
			}
		}else if(strcmp(opcode->valuestring,VOICE_VERSION_QUERY) == 0){
			char ver[16] = {0};
			kk_vp_voice_version_get(ver,sizeof(ver));
			cJSON * root=cJSON_CreateObject();
			cJSON_AddStringToObject(root, "nodeid", "*");
			cJSON_AddStringToObject(root, "opcode", VOICE_VERSION_QUERY);
			cJSON_AddStringToObject(root, "status", "success");
			cJSON_AddStringToObject(root, "arg", ver);
			send_msg_to_module(root);	
			cJSON_Delete(root);		
		}else if(strcmp(opcode->valuestring,VOICE_OTA) == 0){
			cJSON *otafile = cJSON_GetObjectItem(json, "arg");
			if(otafile != NULL){
				kk_voice_ota_mtu_set(KK_VOICE_OTA_MTU);
				kk_vp_ota_file_update_start(otafile->valuestring);
			}
		}else if(strcmp(opcode->valuestring,EXIT_VOICE_FACTORY) == 0){
			kk_voice_exit_factory_mode();
		}
		#endif
		else{
			kk_ccu_opcode_handle(json);
		}
	}

	return 0;
}
static int kk_parse_syncinfo(cJSON *payload)
{
	cJSON *dataStr;
	cJSON *gwdevices,*subdevices;
	cJSON * gwitem,*properties;  
	cJSON *onlineStatus;
	char *gwdevicecode;
	char *deviceCode,*productCode;
	char *identifier,*valuetype;
	cJSON * subitem;
	cJSON * newccuItem;
	cJSON *valuejson;
	int value;

	kk_map_dev_deinit();


	dataStr = cJSON_GetObjectItem(payload, DATA_STRING);
	if(dataStr == NULL) return -1;
	gwdevices = cJSON_GetObjectItem(dataStr, DEVICES_STRING);
	if(gwdevices == NULL) return -1; 
	gwitem = gwdevices->child;
	while(gwitem != NULL){

		subdevices = cJSON_GetObjectItem(gwitem,DEVICES_STRING);
		
		gwdevicecode = cJSON_GetObjectItem(gwitem,MSG_DEVICE_CODE_STR)->valuestring;
		if(subdevices != NULL){
			subitem = subdevices->child;
			while(subitem != NULL){
				deviceCode = cJSON_GetObjectItem(subitem,MSG_DEVICE_CODE_STR)->valuestring;
				productCode = cJSON_GetObjectItem(subitem,MSG_PRODUCT_CODE_STR)->valuestring;
				onlineStatus =  cJSON_GetObjectItem(subitem,MSG_ONLINE_STATUS_STR);
				properties = cJSON_GetObjectItem(subitem,MSG_PROPERTIES_STR);
				kk_map_dev_node_add(deviceCode,productCode,gwdevicecode,(onlineStatus->valueint==1)?"1":"0");
				kk_lan_property_syn_deal(deviceCode,properties);
				subitem = subitem->next;
			}
		}

		gwitem = gwitem->next;
	}
	return 0;
}


int is_ccu_msg(cJSON *productCode,cJSON *deviceCode)
{
	char ccuid[33] = {0};
	char pid[33] = {0};
	kk_lan_get_ccuid(ccuid);
	kk_lan_get_pid(pid);
	if((strlen(productCode->valuestring)==strlen(pid) &&
		!strcmp(productCode->valuestring,pid)) &&
		(strlen(deviceCode->valuestring)==strlen(ccuid) &&
		!strcmp(deviceCode->valuestring,ccuid))){
		return 1;
	}
	return 0;
}

int is_arming_status_notify(cJSON *payload)
{
	cJSON *params = NULL;
	cJSON *ArmingState = NULL;
	if((params = cJSON_GetObjectItem(payload, MSG_PARAMS_STR))!=NULL){
		if((ArmingState = cJSON_GetObjectItem(params, "ArmingState"))!=NULL){
			if(ArmingState->type==cJSON_String &&
				ArmingState->valuestring!=NULL){
				return atoi(ArmingState->valuestring);
			}
		}
	}

	return -1;
}

static void kk_dev_node_onoffline_handle(const char *deviceCode,int online)
{
	kk_map_dev_node_t *node = NULL;
	if(kk_map_dev_search_by_deviceCode(deviceCode,&node) != 0){
		return ;
	}
	node->online_status = (online==1)?1:0;
}

static int kk_device_onoffline_handle(cJSON *payload,int online)
{


	if(payload == NULL){
		return -1;
	}
	cJSON *params = cJSON_GetObjectItem(payload, MSG_PARAMS_STR);
	if(params == NULL) return -1;
	cJSON *deviceCode = cJSON_GetObjectItem(params, "deviceCode");
	if(deviceCode == NULL) return -1;
	kk_dev_node_onoffline_handle(deviceCode->valuestring,online);

	
	cJSON *hw_info = kk_zb_dev_hw_info_build_by_deviceCode(0,deviceCode->valuestring,online);
	cJSON *root;
	cJSON *array = cJSON_CreateArray();
	cJSON_AddItemToArray(array,hw_info);
	root=cJSON_CreateObject();
	cJSON_AddStringToObject(root, "nodeid", "*");
	cJSON_AddStringToObject(root, "opcode", ZIGBEE_DEV_HW_INFO_PUSH);
	cJSON_AddStringToObject(root, "status", "success");
	cJSON_AddItemToObject(root, "arg", array);
	send_msg_to_module(root);
	cJSON_Delete(root);


	
	return 0;
}
static int kk_del_historyalarm_handle(cJSON *payload)
{
	if(payload == NULL){
		return -1;
	}
	cJSON *key = cJSON_GetObjectItem(payload, MSG_PARAMS_STR);
	if(key == NULL) return -1;
	cJSON *root;
	root=cJSON_CreateObject();
	cJSON_AddStringToObject(root, "nodeid", "*");
	cJSON_AddStringToObject(root, "opcode", DEL_HISTORY_ALARM_LOG);
	cJSON_AddStringToObject(root, "status", "success");
	cJSON_AddStringToObject(root, "arg", key->valuestring);
	send_msg_to_module(root);
	cJSON_Delete(root);
	return 0;
}
typedef struct{
	char *productId;
	char *msg;
}alarmcontext_map_s;
static alarmcontext_map_s alarmContext[] = {
	{"3049","检测到有人 告警时间戳"},
	{"3053","检测到有人 告警时间戳"},	
	{"3054","SOS 按钮触发报警 告警时间戳"},	
	{"3083","检测到浓雾 告警时间戳"},
	{"3082","检测到燃气 告警时间戳"},
	{"3051","检测到有开关门 告警时间戳"},	
	{"3055","检测到有水浸入 告警时间戳"},	
};
static alarmcontext_map_s lowbatteryContext[] = {
	{"3049","人体感应设备电量低 告警时间戳"},
	{"3053","人体感应设备电量低 告警时间戳"},	
	{"3054","SOS按钮电量低 告警时间戳"},	
	{"3083","烟感电量低 告警时间戳"},
	{"3082","气感电量低 告警时间戳"},
	{"3051","门磁电量低 告警时间戳"},	
	{"3055","水浸电量低 告警时间戳"},	
};
static alarmcontext_map_s DismantleStateContext[] = {	
	{"3083","烟感被拆除 告警时间戳"},		
	{"3082","气感被拆除 告警时间戳"},	
};
int kk_get_alarmcontext_type_table_size(void)
{
	return sizeof(alarmContext)/sizeof(alarmcontext_map_s);
}
int kk_get_lowbattery_table_size(void)
{
	return sizeof(lowbatteryContext)/sizeof(alarmcontext_map_s);
}
int kk_get_DismantleState_table_size(void)
{
	return sizeof(DismantleStateContext)/sizeof(alarmcontext_map_s);
}
static cJSON *  kk_device_alarm_build(char *key,char *context,char *deviceCode)
{
	int nodeId = 0;
	cJSON *arg = cJSON_CreateObject();
	cJSON_AddStringToObject(arg, "alarm_key", key);
	cJSON_AddStringToObject(arg, "alarm_msg", context);	
	cJSON_AddStringToObject(arg, "alarm_nodeid", "");	
	nodeId = kk_lan_db_node_get(deviceCode,1);	
	cJSON *root=cJSON_CreateObject();
	cJSON_AddStringToObject(root, "nodeid", "*");
	cJSON_AddStringToObject(root, "opcode", "ALARM_NOTIFY");
	cJSON_AddStringToObject(root, "status", "success");
	cJSON_AddItemToObject(root, "arg", arg);
	return root;
}
static int kk_device_alarm_handle(cJSON *payload,char * productid,char *deviceCode,char *key)
{
	int size = 0,k = 0;
	cJSON *root = NULL;
	cJSON *params = cJSON_GetObjectItem(payload, MSG_PARAMS_STR);
	if(params == NULL) return -1;
	cJSON *CommonAlarmState = cJSON_GetObjectItem(params, "CommonAlarmState");
	if(CommonAlarmState != NULL){
		size = kk_get_alarmcontext_type_table_size();
		for(k = 0; k < size; k++){
			//printf("---------------------------->producTypeMap[k].type:%s\n",producTypeMap[k].type);
			if(!strcmp(productid,alarmContext[k].productId)){
				root = kk_device_alarm_build(key,alarmContext[k].msg,deviceCode);
				send_msg_to_module(root);
				cJSON_Delete(root);
				return 0;
			}
		}
	}else{
		cJSON *LowBatteryState = cJSON_GetObjectItem(params, "LowBatteryState");
		if(LowBatteryState != NULL){
			size = kk_get_lowbattery_table_size();
			for(k = 0; k < size; k++){
				//printf("---------------------------->producTypeMap[k].type:%s\n",producTypeMap[k].type);
				if(!strcmp(productid,lowbatteryContext[k].productId)){
					root = kk_device_alarm_build(key,lowbatteryContext[k].msg,deviceCode);
					send_msg_to_module(root);
					cJSON_Delete(root);
					return 0;
				}
			}			
		}
		cJSON *DismantleState = cJSON_GetObjectItem(params, "DismantleState");
		if(DismantleState != NULL){
			size = kk_get_DismantleState_table_size();
			for(k = 0; k < size; k++){
				//printf("---------------------------->producTypeMap[k].type:%s\n",producTypeMap[k].type);
				if(!strcmp(productid,DismantleStateContext[k].productId)){
					root = kk_device_alarm_build(key,DismantleStateContext[k].msg,deviceCode);
					send_msg_to_module(root);
					cJSON_Delete(root);
					return 0;
				}
			}			
		}
	}
	return -1;
}
static int _timer_conver(char *buffer,time_t itime)
{

   struct tm *info;
   info = localtime(&itime );
   strftime(buffer, 80, "%Y-%m-%d %H:%M:%S", info);
   return(0);
}
static int kk_device_historyalarm_handle(cJSON *payload)
{
	int size = 0,k = 0;
	cJSON *root = NULL;
	char timerStr[16] = {0};
	char timerBuf[80] = {0};
	cJSON *params = cJSON_GetObjectItem(payload, MSG_PARAMS_STR);
	if(params == NULL || params->type != cJSON_Array){
		ERROR_PRINT("DATA ERROR!!!");
		return -1;
	}	
	cJSON * contentObj = cJSON_CreateArray();
	cJSON *client_list  = params->child;
	while( client_list != NULL ){
		memset(timerStr,0x0,sizeof(timerStr));
		memset(timerBuf,0x0,sizeof(timerBuf));;
		cJSON *infoItem = cJSON_CreateObject();
		cJSON *identifier = cJSON_GetObjectItem(client_list ,"identifier");
		if(identifier == NULL){
			cJSON_Delete(infoItem);
			return -1;
		}

		cJSON *productCodeJ = cJSON_GetObjectItem(client_list ,"productCode");
		if(productCodeJ == NULL){
			cJSON_Delete(infoItem);
			printf("----------------->6\n");
			return -1;
		}
		cJSON * itime = cJSON_GetObjectItem(client_list ,"alarm_time");
		if(itime == NULL){
			cJSON_Delete(infoItem);
			printf("----------------->1212\n");
			return -1;
		}
		sprintf(timerStr,"%d",itime->valueint);	
		_timer_conver(timerBuf,itime->valuedouble);
		cJSON_AddStringToObject(infoItem, "alarm_key", timerStr);
		cJSON_AddStringToObject(infoItem, "alarm_read", "0");
		cJSON_AddStringToObject(infoItem, "alarm_active_time", timerBuf);				
		if(strcmp(identifier->valuestring,"BatteryAlarm") == 0){
			size = kk_get_lowbattery_table_size();
			for(k = 0; k < size; k++){
				//printf("---------------------------->producTypeMap[k].type:%s\n",producTypeMap[k].type);
				if(!strcmp(productCodeJ->valuestring,lowbatteryContext[k].productId)){
					cJSON_AddStringToObject(infoItem, "alarm_msg", lowbatteryContext[k].msg);
					break;
				}
			}	
		}else if(strcmp(identifier->valuestring,"DismantleState") == 0){
			size = kk_get_DismantleState_table_size();
			for(k = 0; k < size; k++){
				//printf("---------------------------->producTypeMap[k].type:%s\n",producTypeMap[k].type);
				if(!strcmp(productCodeJ->valuestring,DismantleStateContext[k].productId)){
					cJSON_AddStringToObject(infoItem, "alarm_msg", DismantleStateContext[k].msg);
					break;
				}
			}	

		}
		else{
			size = kk_get_alarmcontext_type_table_size();
			for(k = 0; k < size; k++){
				//printf("---------------------------->producTypeMap[k].type:%s\n",producTypeMap[k].type);
				if(!strcmp(productCodeJ->valuestring,alarmContext[k].productId)){
					cJSON_AddStringToObject(infoItem, "alarm_msg", alarmContext[k].msg);
					break;
				}
			}
		}
		cJSON_AddItemToArray(contentObj, infoItem);
		client_list = client_list->next ;
	}	
	cJSON *arg = cJSON_CreateObject();
	cJSON_AddItemToObject(arg, "content", contentObj);
	cJSON_AddStringToObject(arg, "total_pages", "1");
	cJSON_AddStringToObject(arg, "total_elements", "3");
	cJSON_AddStringToObject(arg, "current_page", "1");
	cJSON_AddNumberToObject(arg, "page_size", 10);
	root = cJSON_CreateObject();
	cJSON_AddItemToObject(root, "arg", arg);
	cJSON_AddStringToObject(root, "status", "success");
	cJSON_AddStringToObject(root, "nodeid", "*");
	cJSON_AddStringToObject(root, "opcode", "GET_HISTORY_ALARM_LOG");
	send_msg_to_module(root);
	cJSON_Delete(root);
	return 0;
}

static int kk_lan_scene_handle(cJSON *payload,int isAdd)
{
	cJSON *params = NULL;
	cJSON *sceneId = NULL;

	if(payload == NULL){
		DEBUG_PRINT("[err] payload.\n");
		return -1;
	}

	if((params = cJSON_GetObjectItem(payload, MSG_PARAMS_STR))==NULL||
		params->type!=cJSON_Object){
		DEBUG_PRINT("[err] params err.\n");
		return -1;
	}
	if((sceneId = cJSON_GetObjectItem(params, MSG_SCENE_SCENEID))==NULL ||
		sceneId->type!=cJSON_String){
		DEBUG_PRINT("[err] sceneId err.\n");
		return -1;
	}

	if(isAdd!=0){
		kk_lan_add_scene_notify(sceneId->valuestring);
	}else{
		kk_lan_delete_scene_notify(sceneId->valuestring);
	}
	

	return 0;
}


static int  kk_client_reoprt_reply_handle(cJSON *payload)
{
	int nodeId = 0;
	if(payload == NULL){
		return -1;
	}
	cJSON *params = cJSON_GetObjectItem(payload,"params");
	if(params == NULL){
		return -1;
	}
	cJSON *serialId = cJSON_GetObjectItem(params, "serialId");
	if(serialId == NULL){
		return -1;
	}
	cJSON *arg = cJSON_CreateObject();
	cJSON_AddStringToObject(arg, "serialId", serialId->valuestring);		
	cJSON *root=cJSON_CreateObject();
	cJSON_AddStringToObject(root, "nodeid", "*");
	cJSON_AddStringToObject(root, "opcode", "CCU_CLIENT_REPORT");
	cJSON_AddStringToObject(root, "status", "success");
	cJSON_AddItemToObject(root, "arg", arg);
	send_msg_to_module(root);
	cJSON_Delete(root);	
	return 0;
}
static int  kk_client_online_push_handle(cJSON *payload)
{
	int nodeId = 0;
	if(payload == NULL){
		return -1;
	}
	cJSON *params = cJSON_GetObjectItem(payload,"params");
	if(params == NULL){
		return -1;
	}
	cJSON *serialId = cJSON_GetObjectItem(params, "serialId");
	if(serialId == NULL){
		return -1;
	}
	cJSON *online = cJSON_GetObjectItem(params, "online");
	if(online == NULL){
		return -1;
	}
	cJSON *arg = cJSON_CreateObject();
	cJSON_AddStringToObject(arg, "serialId", serialId->valuestring);
	cJSON_AddNumberToObject(arg, "online", online->valueint);		
	cJSON *root=cJSON_CreateObject();
	cJSON_AddStringToObject(root, "nodeid", "*");
	cJSON_AddStringToObject(root, "opcode", "CCU_CLIENT_ONLINE_PUSH");
	cJSON_AddStringToObject(root, "status", "success");
	cJSON_AddItemToObject(root, "arg", arg);
	send_msg_to_module(root);
	cJSON_Delete(root);	
	return 0;
}
static int  kk_client_info_push_handle(cJSON *payload)
{
	int nodeId = 0;
	if(payload == NULL){
		return -1;
	}
	cJSON *params = cJSON_GetObjectItem(payload,"params");
	if(params == NULL){
		return -1;
	}		
	char* pData = cJSON_Print(params);
	cJSON *root=cJSON_CreateObject();
	cJSON_AddStringToObject(root, "nodeid", "*");
	cJSON_AddStringToObject(root, "opcode", "GET_CCU_CLIENT_INFO");
	cJSON_AddStringToObject(root, "status", "success");
	cJSON_AddItemToObject(root, "arg", cJSON_Parse(pData));
	send_msg_to_module(root);
	cJSON_Delete(root);	
	free(pData);
	return 0;
}

static int  kk_get_ccu_info_handle(cJSON *param)
{
	cJSON *root = cJSON_CreateObject();

	cJSON_AddStringToObject(root, "nodeid", "*");
	cJSON_AddStringToObject(root, "opcode", "GET_CCU_INFO");
	cJSON_AddStringToObject(root, "status", "success");
	cJSON_AddItemToObject(root, "arg", param);

	char *data = cJSON_Print(root);
	kk_send_data_to_sdk(data);

	cJSON_Delete(root);
	free(data);
	
	return 0;
}


void KK_Data_FromMid(void* str,int len, char* chalMark)
{
	cJSON *json = NULL;
	cJSON *info = NULL,*payload = NULL;
	cJSON *msgtype = NULL,*deviceCode = NULL,*productCode = NULL;

	if (str == NULL || len == 0){
		INFO_PRINT("[midware->lan][%s] str or len is error \n",__FUNCTION__);
		return;
	}



	INFO_PRINT("[midware->lan] len=%d,data=%s\n",len,(char *)str);


	if((json= cJSON_Parse(str)) == NULL) {
		return;
	}

	info = cJSON_GetObjectItem(json, MSG_INFO_STR);
	payload = cJSON_GetObjectItem(json, MSG_PAYLOAD_STR);

	if(info==NULL || payload==NULL ||
		info->type != cJSON_Object ||payload->type!= cJSON_Object){
		cJSON_Delete(json);
		return;
	}
	
	msgtype = cJSON_GetObjectItem(info, MSG_TYPE_STR);

	//
	if(strstr(msgtype->valuestring,KK_THING_SERVICE_GET_CCU_INFO_REPLY)!= NULL){
		INFO_PRINT("getCCUInfo_reply!!!");
		kk_get_ccu_info_handle(payload);
		return;
	}
		
	productCode = cJSON_GetObjectItem(info, MSG_PRODUCT_CODE_STR);
	deviceCode= cJSON_GetObjectItem(info, MSG_DEVICE_CODE_STR);

	if(msgtype == NULL || productCode==NULL || deviceCode==NULL||
		msgtype->type != cJSON_String || productCode->type!= cJSON_String||deviceCode->type!= cJSON_String ||
		msgtype->valuestring==NULL|| productCode->valuestring==NULL || deviceCode->valuestring==NULL){
		cJSON_Delete(json);
		return;
	}

	if (strstr(msgtype->valuestring,SYNC_MSG_TYPE_REPLY) != NULL){
		INFO_PRINT("syncinfo_reply handle!!!");
		kk_parse_syncinfo(payload);
		kk_create_syncinfo_to_sdk(payload,0);
		#ifdef VOICE_SUPPORT
		kk_vp_syncinfo_handle(payload);
		#endif
		
	}else if (strstr(msgtype->valuestring,SYNCPUSH_MSG_TYPE_REPLY) != NULL){
		INFO_PRINT("syncinfopush_reply handle!!!");
		kk_parse_syncinfo(payload);
		kk_create_syncinfo_to_sdk(payload,1);
		#ifdef VOICE_SUPPORT
		kk_vp_syncinfo_handle(payload);
		#endif
	}
	else if(strstr(msgtype->valuestring,"/thing/event/property/post")!= NULL){
		INFO_PRINT("property post handle!!!");
		if(is_ccu_msg(productCode,deviceCode)){
			
			int type;
			if((type = is_arming_status_notify(payload))!=-1){
				kk_lan_arming_status_notify(type);
			}
		}else{
			kk_lan_property_post_deal(deviceCode->valuestring,payload);
		}
	}else if(strstr(msgtype->valuestring,"/thing/topo/delete")!= NULL){
		INFO_PRINT("topo delete handle!!!");
		kk_lan_device_delete_notify(payload);
	}else if(strstr(msgtype->valuestring,"/thing/status/online")!= NULL){
		INFO_PRINT("online handle!!!");
		kk_device_onoffline_handle(payload,1);
	}else if(strstr(msgtype->valuestring,"/thing/status/offline")!= NULL){
		INFO_PRINT("offline handle!!!");
		kk_device_onoffline_handle(payload,0);
	}else if(strstr(msgtype->valuestring,"/thing/service/addDeviceToRoom_reply")!= NULL){
		sleep(3);
		INFO_PRINT("addDeviceToRoom_reply handle!!!");
		device_add_sync(payload);
	}else if(strstr(msgtype->valuestring,"/thing/service/removeDeviceFromRoom_reply")!= NULL){
		kk_handle_sync_push_info();
	}else if(strstr(msgtype->valuestring,"/thing/event/alarmNotify")!= NULL){
		INFO_PRINT("alarmNotify handle!!!");
		cJSON * msgId = cJSON_GetObjectItem(payload, "msgId");
		kk_device_alarm_handle(payload,productCode->valuestring,deviceCode->valuestring,msgId->valuestring);
	}else if(strstr(msgtype->valuestring,"/thing/service/historyAlarm_reply")!= NULL){
		INFO_PRINT("historyAlarm_reply handle!!!");
		kk_device_historyalarm_handle(payload);
	}else if(strstr(msgtype->valuestring,"/thing/service/delAlarm_reply")!= NULL){
		INFO_PRINT("delAlarm_reply handle!!!");
		kk_del_historyalarm_handle(payload);
	}else if(strstr(msgtype->valuestring,"/thing/event/addSceneNotification/post")!= NULL){
		INFO_PRINT("addSceneNotification handle!!!");
		kk_lan_scene_handle(payload,1);
	}else if(strstr(msgtype->valuestring,"/thing/event/updateSceneNotification/post")!= NULL){
		INFO_PRINT("updateSceneNotification handle!!!");
		kk_lan_scene_handle(payload,1);
	}else if(strstr(msgtype->valuestring,"/thing/event/deleteSceneNotification/post")!= NULL){
		INFO_PRINT("deleteSceneNotification handle!!!");
		kk_lan_scene_handle(payload,0);
	}else if(strstr(msgtype->valuestring,"/thing/service/clientReport_reply")!= NULL){
		INFO_PRINT("clientReport_reply handle!!!");
		kk_client_reoprt_reply_handle(payload);
	}else if(strstr(msgtype->valuestring,"/thing/service/clientOnlinePush")!= NULL){
		INFO_PRINT("clientOnlinePush handle!!!");
		kk_client_online_push_handle(payload);
	}else if(strstr(msgtype->valuestring,"/thing/service/getClientInfo_reply")!= NULL){
		INFO_PRINT("getClientInfo_reply handle!!!");
		kk_client_info_push_handle(payload);
	}
	cJSON_Delete(json);
	
}





