/************************************************************
*版权所有 （C）2020，公司（或个人）名称
*
*文件名称： kk_linkkit.c
*内容摘要： 收到云端数据后的回调处理
*其他说明： 
*当前版本：  
*************************************************************/

/*************************************************************
头文件引用 
*************************************************************/

#include "kk_tsl_common.h"
#include "klist.h"
#include "cJSON.h"
#include "kk_dm_msg.h"
#include "kk_dm_mng.h"
#include "kk_dm_api.h"
#include "kk_sub_db.h"
#include "kk_tsl_api.h"
#include "com_api.h"
#include "kk_log.h"
#include "kk_area_handle.h"
#include "kk_scene_handle.h"
#include "kk_property_db.h"
#include "kk_product.h"
#include "kk_hal.h"

#define IOTX_LINKKIT_KEY_ID          "id"
#define IOTX_LINKKIT_KEY_CODE        "code"
#define IOTX_LINKKIT_KEY_DEVID       "devid"
#define IOTX_LINKKIT_KEY_SERVICEID   "serviceid"
#define IOTX_LINKKIT_KEY_PROPERTYID  "propertyid"
#define IOTX_LINKKIT_KEY_EVENTID     "eventid"
#define IOTX_LINKKIT_KEY_PAYLOAD     "payload"
#define IOTX_LINKKIT_KEY_CONFIG_ID   "configId"
#define IOTX_LINKKIT_KEY_CONFIG_SIZE "configSize"
#define IOTX_LINKKIT_KEY_GET_TYPE    "getType"
#define IOTX_LINKKIT_KEY_SIGN        "sign"
#define IOTX_LINKKIT_KEY_SIGN_METHOD "signMethod"
#define IOTX_LINKKIT_KEY_URL         "url"
#define IOTX_LINKKIT_KEY_VERSION     "version"
#define IOTX_LINKKIT_KEY_UTC         "utc"
#define IOTX_LINKKIT_KEY_RRPCID      "rrpcid"
#define IOTX_LINKKIT_KEY_CTX         "ctx"
#define IOTX_LINKKIT_KEY_TOPO        "topo"
#define IOTX_LINKKIT_KEY_PRODUCT_KEY "productKey"
#define IOTX_LINKKIT_KEY_TIME        "time"
#define IOTX_LINKKIT_KEY_DATA        "data"

#define IOTX_LINKKIT_SYNC_DEFAULT_TIMEOUT_MS 10000
#define dm_log_err          ERROR_PRINT
#define dm_log_debug        WARNING_PRINT
#define dm_log_info         INFO_PRINT





typedef struct {
    int msgid;
    void *semaphore;
    int code;
    struct list_head linked_list;
} iotx_linkkit_upstream_sync_callback_node_t;

typedef struct {
	void *mutex;
	void *upstream_mutex;
	int is_opened;
	int is_connected;
	struct list_head upstream_sync_callback_list;
} iotx_linkkit_ctx_t;

static iotx_linkkit_ctx_t g_iotx_linkkit_ctx = {0};

static iotx_linkkit_ctx_t *_iotx_linkkit_get_ctx(void)
{
	return &g_iotx_linkkit_ctx;
}
/************************************************************
*功能描述：本模块互斥锁，加锁处理
*输入参数：无
*输出参数：无
*返 回 值： 无
*其他说明：
*************************************************************/
static void _iotx_linkkit_mutex_lock(void)
{
	iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
	if (ctx->mutex) {
		HAL_MutexLock(ctx->mutex);
	}
}

/************************************************************
*功能描述：本模块互斥锁，解锁处理
*输入参数：无
*输出参数：无
*返 回 值： 无
*其他说明：
*************************************************************/
static void _iotx_linkkit_mutex_unlock(void)
{
	iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
	if (ctx->mutex) {
		HAL_MutexUnlock(ctx->mutex);
	}
}

#if 1
/************************************************************
*功能描述：互斥锁，添加topo关系时加锁处理
*输入参数：无
*输出参数：无
*返 回 值： 无
*其他说明：
*************************************************************/
static void _iotx_linkkit_upstream_mutex_lock(void)
{
	iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
	if (ctx->upstream_mutex) {
		HAL_MutexLock(ctx->upstream_mutex);
	}
}
/************************************************************
*功能描述：互斥锁，添加topo关系时解锁处理
*输入参数：无
*输出参数：无
*返 回 值： 无
*其他说明：
*************************************************************/
static void _iotx_linkkit_upstream_mutex_unlock(void)
{
	iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
	if (ctx->upstream_mutex) {
		HAL_MutexUnlock(ctx->upstream_mutex);
	}
}

/************************************************************
*功能描述：添加topo关系时添加消息同步队列
*输入参数：msgid：消息Id
		  semaphore:同步用的信号量
*输出参数：node：添加的队列节点
*返 回 值： 0：成功；其他：失败
*其他说明：此消息队列只有MSG_NEED_RESP被定义了才使用到，如添加topo.add时，只
          有服务器回reply或者超时10秒后才往下执行
*************************************************************/
static int _iotx_linkkit_upstream_sync_callback_list_insert(int msgid, void *semaphore,
        iotx_linkkit_upstream_sync_callback_node_t **node)
{
    iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
    iotx_linkkit_upstream_sync_callback_node_t *search_node = NULL;

    list_for_each_entry(search_node, &ctx->upstream_sync_callback_list, linked_list,
                        iotx_linkkit_upstream_sync_callback_node_t) {
        if (search_node->msgid == msgid) {
            WARNING_PRINT("Message Already Exist: %d", msgid);
            return FAIL_RETURN;
        }
    }

    search_node = malloc(sizeof(iotx_linkkit_upstream_sync_callback_node_t));
    if (search_node == NULL) {
        dm_log_debug("malloc error");
        return FAIL_RETURN;
    }
    memset(search_node, 0, sizeof(iotx_linkkit_upstream_sync_callback_node_t));
    search_node->msgid = msgid;
    search_node->semaphore = semaphore;
    INIT_LIST_HEAD(&search_node->linked_list);

    list_add(&search_node->linked_list, &ctx->upstream_sync_callback_list);
    INFO_PRINT("New Message, msgid: %d", msgid);

    *node = search_node;
    return SUCCESS_RETURN;
}
/************************************************************
*功能描述：删除消息同步队列
*输入参数：msgid：消息Id
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：此消息队列只有MSG_NEED_RESP被定义了才使用到
*************************************************************/
static int _iotx_linkkit_upstream_sync_callback_list_remove(int msgid)
{
    iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
    iotx_linkkit_upstream_sync_callback_node_t *search_node = NULL;

    list_for_each_entry(search_node, &ctx->upstream_sync_callback_list, linked_list,
                        iotx_linkkit_upstream_sync_callback_node_t) {
        if (search_node->msgid == msgid) {
            INFO_PRINT("Message Found: %d, Delete It \n", msgid);
            HAL_SemaphoreDestroy(search_node->semaphore);
            list_del(&search_node->linked_list);
            free(search_node);
            return SUCCESS_RETURN;
        }
    }

    return FAIL_RETURN;
}
/************************************************************
*功能描述：根据msgid查询对应节点
*输入参数：msgid：消息Id
*输出参数：node：查询到的节点
*返 回 值： 0：成功；其他：失败
*其他说明：此消息队列只有MSG_NEED_RESP被定义了才使用到
*************************************************************/

int _iotx_linkkit_upstream_sync_callback_list_search(int msgid,
        iotx_linkkit_upstream_sync_callback_node_t **node)
{
    iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
    iotx_linkkit_upstream_sync_callback_node_t *search_node = NULL;

    if (node == NULL || *node != NULL) {
        dm_log_debug("invalid param");
        return FAIL_RETURN;
    }

    list_for_each_entry(search_node, &ctx->upstream_sync_callback_list, linked_list,
                        iotx_linkkit_upstream_sync_callback_node_t) {
        if (search_node->msgid == msgid) {
            dm_log_debug("Sync Message Found: %d", msgid);
            *node = search_node;
            return SUCCESS_RETURN;
        }
    }

    return FAIL_RETURN;
}
/************************************************************
*功能描述：删除整个消息同步队列
*输入参数：无
*输出参数：无
*返 回 值： 无
*其他说明：此消息队列只有MSG_NEED_RESP被定义了才使用到
*************************************************************/
static void _iotx_linkkit_upstream_sync_callback_list_destroy(void)
{
    iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
    iotx_linkkit_upstream_sync_callback_node_t *search_node = NULL, *next_node = NULL;

    list_for_each_entry_safe(search_node, next_node, &ctx->upstream_sync_callback_list, linked_list,
                             iotx_linkkit_upstream_sync_callback_node_t) {
        list_del(&search_node->linked_list);
        HAL_SemaphoreDestroy(search_node->semaphore);
        free(search_node);
    }
}

/************************************************************
*功能描述：释放对应的同步信号量
*输入参数：msgid：消息Id
          code:错误码值
*输出参数：无
*返 回 值： 无
*其他说明：此消息队列只有MSG_NEED_RESP被定义了才使用到
*************************************************************/
static void _iotx_linkkit_upstream_callback_remove(int msgid, int code)
{
     INFO_PRINT("_iotx_linkkit_upstream_callback_remove : [%d] ,code= %d  \n",msgid, code );
    int res = 0;
    iotx_linkkit_upstream_sync_callback_node_t *sync_node = NULL;
    res = _iotx_linkkit_upstream_sync_callback_list_search(msgid, &sync_node);
    if (res == SUCCESS_RETURN) {
        sync_node->code = (code == IOTX_DM_ERR_CODE_SUCCESS) ? (SUCCESS_RETURN) : (FAIL_RETURN);
        INFO_PRINT("Sync Message %d Result: %d", msgid, sync_node->code);
        HAL_SemaphorePost(sync_node->semaphore);
    }
}
#endif

#ifdef LOG_REPORT_TO_CLOUD
    int  report_sample = 0;
#endif
#ifdef ALCS_ENABLED
    extern void dm_server_free_context(_IN_ void *ctx);
#endif
static int s_CloudStatus = 0;
static int s_CloudStatusRecv = 0;

/************************************************************
*功能描述：获取连云状态
*输入参数：无
*输出参数：无
*返 回 值： 1，已连上；0：未连上
*其他说明：
*************************************************************/
int kk_get_cloudstatus(void){
	return s_CloudStatus;
}
/************************************************************
*功能描述：获取是否有连云状态的通知
*输入参数：无
*输出参数：无
*返 回 值： 1，有；0：未通知
*其他说明：
*************************************************************/
int kk_get_cloud_recv_status(void){
	return s_CloudStatusRecv;
}

/************************************************************
*功能描述：手机端主动删除设备处理函数
*输入参数：payload：云端传下来数据
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
int kk_topo_delete_handle(cJSON *payload)
{
	if(payload == NULL){
		return FAIL_RETURN;
	}
	cJSON *paramStr = cJSON_GetObjectItem(payload, MSG_PARAMS_STR); 
	cJSON *state = cJSON_GetObjectItem(paramStr, MSG_TOPO_CHANGE_TYPE_STR);
	if(state != NULL && state->valueint == 1){
		cJSON *deviceArray = cJSON_GetObjectItem(paramStr, MSG_TOPO_CHANGE_DEVICES_STR);
		if(deviceArray == NULL){
			return FAIL_RETURN;
		}
		cJSON * item = deviceArray->child;
		while(item != NULL){
			char *deviceCode = cJSON_GetObjectItem(item,MSG_DEVICE_CODE_STR)->valuestring;
			dm_mgr_subdev_delete(deviceCode);
			
			item = item->next;
		}

	}
	
	return SUCCESS_RETURN;
}

/************************************************************
*功能描述：添加房间处理函数
*输入参数：params：云端传下来JSON数据，主要包含房间名称
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
static int kk_service_addRoom_handle(const char *deviceCode, cJSON *params)
{
	dm_mgr_dev_node_t *node = NULL;
	char roomId[32] = {0};
	int res = 0;
	//int idx = 0,idxIpt = 0;
	//int start  = 0,serverNum = 0;
	//kk_tsl_service_t *serviceItem = NULL;
	//kk_tsl_data_t* pinputData = NULL;
	//cJSON *currentItem  =NULL;
	if(deviceCode == NULL||params == NULL){
		return INVALID_PARAMETER;
	}
	res = dm_mgr_get_device_by_devicecode((char*)deviceCode, &node);
	if (res < SUCCESS_RETURN) {
		ERROR_PRINT("dm_mgr_get_device_by_devicecode failed\n");
		return res;
	}
	cJSON *roomInfoStr = cJSON_GetObjectItem(params, MSG_AREA_ADDROOM_ROOMNAME);
	cJSON *roomIdStr = cJSON_GetObjectItem(params, MSG_AREA_ROOM_ROOMID);
	if(roomInfoStr == NULL){
		return FAIL_RETURN;
	}
	memcpy(roomId,roomIdStr->valuestring,strlen(roomIdStr->valuestring));
	//HAL_GetTime_s((char*)roomId);
	kk_room_add(roomInfoStr->valuestring,roomId);
	kk_tsl_set_value(kk_tsl_set_event_output_value,node->dev_shadow,MSG_AREA_ADDROOM_NOTIFICATION_ROOMID,NULL,roomId);
	return SUCCESS_RETURN;
}
/************************************************************
*功能描述：删除房间处理函数
*输入参数：params：云端传下来JSON数据，主要包含房间ID
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
static int kk_service_deleteRoom_handle(cJSON *params)
{
	if(params == NULL){
		return INVALID_PARAMETER;
	}

	cJSON *roomInfoStr = cJSON_GetObjectItem(params, MSG_AREA_ROOM_ROOMID);	
	if(roomInfoStr == NULL){
		return FAIL_RETURN;
	}
	kk_room_delete(roomInfoStr->valuestring);
	return SUCCESS_RETURN;
	
}

static int kk_service_addDeviceToRoom_reply(cJSON *param,cJSON *msgId)
{
	int res = 0;
	int i = 0,num = 0;
	if(param == NULL || msgId == NULL){
		return INVALID_PARAMETER;
	}
	INFO_PRINT(" adddevicetoroom reply  \n");
	cJSON *deviceCode = cJSON_GetObjectItem(param, MSG_DEVICE_CODE_STR);	
	if(deviceCode == NULL){
		return FAIL_RETURN;
	}		
	cJSON *productCode = cJSON_GetObjectItem(param, MSG_PRODUCT_CODE_STR);	
	if(productCode == NULL){
		return FAIL_RETURN;
	}		
	INFO_PRINT(" adddevicetoroom reply  \n");
	cJSON *info = cJSON_CreateObject();
	cJSON_AddStringToObject(info, MSG_TYPE_STR, KK_THING_SERVICE_ADDDEVICETOROOM_REPLY);
	cJSON_AddStringToObject(info, MSG_DEVICE_CODE_STR, deviceCode->valuestring);
	cJSON_AddStringToObject(info, MSG_PRODUCT_CODE_STR, productCode->valuestring);
	char *infff=cJSON_Print(info);

	cJSON *payload = cJSON_CreateObject();
	cJSON_AddStringToObject(payload, "desc", "success");
	cJSON_AddStringToObject(payload, "version", "1.0");
	cJSON_AddStringToObject(payload, "code", "0");
	cJSON_AddStringToObject(payload, "msgId", msgId->valuestring);
	INFO_PRINT(" adddevicetoroom reply  \n");
	cJSON *Item = cJSON_CreateObject();
	cJSON_AddItemToObject(payload, "params", Item);
	char *payload11=cJSON_Print(payload);
	INFO_PRINT(" adddevicetoroom reply  \n");
	kk_sendData2app(infff,payload11,0);
	INFO_PRINT(" adddevicetoroom reply  \n");
	free(payload11);
	free(infff);
	cJSON_Delete(payload);
	cJSON_Delete(info);
	return res;
}
/************************************************************
*功能描述：添加设备到房间处理函数
*输入参数：params：云端传下来JSON数据，主要包含房间ID和设备deviceCode
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
static int kk_service_addDeviceToRoom_handle(cJSON *params)
{
	char epNumStr[10] = {0};
	int isAirGwFlag = 0;
	int res = 0;
	dm_mgr_dev_node_t *node = NULL;
	if(params == NULL){
		return INVALID_PARAMETER;
	}

	cJSON *dev_name = cJSON_GetObjectItem(params, MSG_AREA_ADDROOM_DEVICENAME);
	if(dev_name == NULL){
		return FAIL_RETURN;
	}
	cJSON *room_name = cJSON_GetObjectItem(params, MSG_AREA_ADDROOM_ROOMNAME);
	if(room_name == NULL){
		return FAIL_RETURN;
	}
	cJSON *roomId = cJSON_GetObjectItem(params, MSG_AREA_ROOM_ROOMID);	
	if(roomId == NULL){
		return FAIL_RETURN;
	}
	cJSON *deviceCode = cJSON_GetObjectItem(params, MSG_DEVICE_CODE_STR);	
	if(deviceCode == NULL){
		return FAIL_RETURN;
	}	
	res = dm_mgr_get_device_by_devicecode((char*)deviceCode->valuestring,&node);
	if (res != SUCCESS_RETURN) {
		ERROR_PRINT("ERROR [%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
		return FAIL_RETURN;
	}	
	cJSON *epNum = cJSON_GetObjectItem(params, MSG_AREA_ROOM_EPNUM);	
	if(epNum == NULL){
		if(strcmp(node->productType,KK_DM_AIR_GATEWAY_TYPE) == 0){
			isAirGwFlag = 1;
		}
		strcpy(epNumStr,"1");
	}else{
		strcpy(epNumStr,epNum->valuestring);
	}		
	kk_room_dev_add(roomId->valuestring,room_name->valuestring,deviceCode->valuestring,epNumStr,dev_name->valuestring);

	//内机默认添加到跟网关同个房间
	if(strcmp(node->productType,KK_DM_AIR_GATEWAY_TYPE) == 0 && isAirGwFlag){
		int eplist[64] = {0};
		char name[128] = {0};
		int i = 0;
		int count = kk_indoorAir_query_epnums(deviceCode->valuestring,eplist);
		for(i = 0; i < count; i++){
			memset(epNumStr,0x0,sizeof(epNumStr));
			memset(name,0x0,sizeof(name));
			sprintf(epNumStr,"%d",eplist[i]);
			sprintf(name,"空调%d",eplist[i]);
			kk_room_dev_add(roomId->valuestring,room_name->valuestring,deviceCode->valuestring,epNumStr,name);
		}
	}		
	return SUCCESS_RETURN;
}
/************************************************************
*功能描述：删除设备从房间处理函数
*输入参数：params：云端传下来JSON数据，主要包含设备deviceCode
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
static int kk_service_removeDeviceFromRoom_handle(cJSON *params)
{
	char epNumStr[10] = {0};

	if(params == NULL){
		return INVALID_PARAMETER;
	}

	cJSON *deviceCode = cJSON_GetObjectItem(params, MSG_DEVICE_CODE_STR);	
	if(deviceCode == NULL){
		return FAIL_RETURN;
	}	
	cJSON *epNum = cJSON_GetObjectItem(params, MSG_AREA_ROOM_EPNUM);	
	if(epNum == NULL){
		strcpy(epNumStr,"1");
	}else{
		strcpy(epNumStr,epNum->valuestring);
	}			
	kk_room_dev_remove(deviceCode->valuestring,epNumStr);
	return SUCCESS_RETURN;
}

/************************************************************
*功能描述：执行房间设备处理
*输入参数：action：具体动作
          node:设备节点
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
static int kk_service_execute_action(cJSON *action,dm_mgr_dev_node_t *node)
{
	//int idx = 0;
	//kk_tsl_data_t *pCurrentItem = NULL;
	//cJSON *pCurrentData = NULL;
	if(node == NULL){
		return INVALID_PARAMETER;
	}
	void *param = cJSON_Print(action);
	kk_msg_execute_property_set(node->productCode,node->deviceCode,param,node->fatherDeviceCode);
	
#if 0	
	for(idx = 0; idx < shadow->property_number; idx++){
		pCurrentItem = shadow->properties + idx;
		if(pCurrentItem != NULL){
			cJSON *pCurrentData = cJSON_GetObjectItem(action, pCurrentItem->identifier);
			if(pCurrentData != NULL){

			}
		}
	}
#endif	
	free(param);
	return SUCCESS_RETURN;


}
/************************************************************
*功能描述：批量执行房间设备处理
*输入参数：params：云端下发数据，包含房间号，productCode等
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
static int kk_service_executeRoom_handle(cJSON *params)
{
	int res = 0;
	kk_dev_list_t *pList = NULL;
	dm_mgr_dev_node_t *search_node = NULL;	

	if(params == NULL){
		return INVALID_PARAMETER;
	}
	cJSON *roomId = cJSON_GetObjectItem(params, MSG_AREA_ROOM_ROOMID);	
	if(roomId == NULL){
		return FAIL_RETURN;
	}

	cJSON *productCodeStr = cJSON_GetObjectItem(params, MSG_PRODUCT_TYPE_STR);	
	if(productCodeStr == NULL){
		return FAIL_RETURN;
	}	

	pList = kk_get_room_deviceCode(roomId->valuestring);
	if(pList != NULL){
		while(pList != NULL){
			res = dm_mgr_get_device_by_devicecode(pList->deviceCode,&search_node);
			if (res != SUCCESS_RETURN) {
				pList = pList->next;
				continue;
			}
			if(strcmp(search_node->productCode,productCodeStr->valuestring) == 0){
				cJSON *action = cJSON_GetObjectItem(params, MSG_AREA_ROOM_ACTION);
				if(action != NULL){
					kk_service_execute_action(action,search_node);
				}
			}
			pList = pList->next;
		}
	}
	kk_free_room_dev_list();
	return SUCCESS_RETURN;
}

/************************************************************
*功能描述：添加场景处理
*输入参数：params：云端下发数据，包含场景名称，场景类型，场景使能等
          msgId：消息Id
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
static int kk_service_addScene_handle(cJSON *param,cJSON *msgId)
{
	int res = 0;
	char sceneId[32] = {0};
	//kk_tsl_t *pSceneShadow = NULL;
	if(param == NULL || msgId == NULL){
		return INVALID_PARAMETER;
	}
	res = kk_scene_parse_addscene(param,sceneId,0,msgId->valuestring);

	return res;
}
/************************************************************
*功能描述：编辑场景处理
*输入参数：params：云端下发数据，包含场景名称，场景类型，场景使能，场景Id等
          msgId：消息Id
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
static int kk_service_updateScene_handle(cJSON *param,cJSON *msgId)
{
	int res = 0;
	kk_tsl_t *pSceneShadow = NULL;
	if(param == NULL || msgId == NULL){
		return INVALID_PARAMETER;
	}	
	cJSON *sceneId = cJSON_GetObjectItem(param,MSG_SCENE_SCENEID);
	if(sceneId == NULL) return FAIL_RETURN;
	pSceneShadow = kk_scene_shadow();
	if(pSceneShadow != NULL){
		kk_tsl_set_value(kk_tsl_set_event_output_value,pSceneShadow,MSG_SCENE_UPDATENOTIFICATION_SCENEID,NULL,sceneId->valuestring);
		dm_msg_scene_event_post(MSG_SCENE_UPDATENOTIFICATION,pSceneShadow,msgId->valuestring);		
	}
	res = kk_scene_parse_updatescene(param,sceneId->valuestring);
	return res;
}
/************************************************************
*功能描述：删除场景处理
*输入参数：params：云端下发数据，包含场景Id等
          msgId：消息Id
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
static int kk_service_deleteScene_handle(cJSON *param,cJSON *msgId)
{
	int res = 0;
	kk_tsl_t *pSceneShadow = NULL;
	char sceneIdBuf[16] = {0};
	if(param == NULL || msgId == NULL){
		return INVALID_PARAMETER;
	}
	cJSON *sceneId = cJSON_GetObjectItem(param,MSG_SCENE_SCENEID);
	if(sceneId == NULL) return FAIL_RETURN;
	if(sceneId->valuestring == NULL){
		sprintf(sceneIdBuf,"%d",sceneId->valueint);
		res = kk_scene_parse_deletescene(sceneIdBuf);
	}
	else{
		res = kk_scene_parse_deletescene(sceneId->valuestring);
	}
	if(res == SUCCESS_RETURN){
		pSceneShadow = kk_scene_shadow();
		if(pSceneShadow != NULL){
			if(strlen(sceneIdBuf) > 0){
				kk_tsl_set_value(kk_tsl_set_event_output_value,pSceneShadow,MSG_SCENE_DELETENOTIFICATION_SCENEID,NULL,sceneIdBuf);
			}
			else{
				kk_tsl_set_value(kk_tsl_set_event_output_value,pSceneShadow,MSG_SCENE_DELETENOTIFICATION_SCENEID,NULL,sceneId->valuestring);
			}
			dm_msg_scene_event_post(MSG_SCENE_DELETENOTIFICATION,pSceneShadow,msgId->valuestring);		
		}
	}
	return res;
}
/************************************************************
*功能描述：执行场景处理
*输入参数：params：云端下发数据，包含场景Id等
          msgId：消息Id
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
static int kk_service_executeScene_handle(cJSON *param,cJSON *msgId)
{
	int res = 0;

	if(param == NULL || msgId == NULL){
		return INVALID_PARAMETER;
	}
	cJSON *sceneId = cJSON_GetObjectItem(param,MSG_SCENE_SCENEID);
	if(sceneId == NULL) return FAIL_RETURN;		

	res = kk_scene_execute_scene(sceneId->valuestring,msgId->valuestring);

	return res;
}
/************************************************************
*功能描述：获取主机下安防设备及对应等级
*输入参数：params：云端下发数据，包含场景Id等
          msgId：消息Id
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
static int kk_service_getGuardSensors_handle(cJSON *param,cJSON *msgId)
{
	int res = 0;
	int i = 0,num = 0;
	SensorType_t *pList = NULL;
	if(param == NULL || msgId == NULL){
		return INVALID_PARAMETER;
	}
	cJSON *deviceCode = cJSON_GetObjectItem(param, MSG_DEVICE_CODE_STR);	
	if(deviceCode == NULL){
		return FAIL_RETURN;
	}		
	cJSON *productCode = cJSON_GetObjectItem(param, MSG_PRODUCT_CODE_STR);	
	if(productCode == NULL){
		return FAIL_RETURN;
	}		
	cJSON *info = cJSON_CreateObject();
	cJSON_AddStringToObject(info, MSG_TYPE_STR, "/thing/service/getGuardSensors_reply");
	cJSON_AddStringToObject(info, MSG_DEVICE_CODE_STR, deviceCode->valuestring);
	cJSON_AddStringToObject(info, MSG_PRODUCT_CODE_STR, productCode->valuestring);
	char *infff=cJSON_Print(info);

	cJSON *payload = cJSON_CreateObject();
	cJSON_AddStringToObject(payload, "desc", "success");
	cJSON_AddStringToObject(payload, "version", "1.0");
	cJSON_AddStringToObject(payload, "code", "0");
	cJSON_AddStringToObject(payload, "msgId", msgId->valuestring);
	cJSON *paramArray = cJSON_CreateArray();
	num = dm_mgr_get_deviceNum_by_productType("sensor");
	pList = (SensorType_t*)malloc(sizeof(SensorType_t)*num);
	if(pList == NULL){
		ERROR_PRINT("MALLOC ERROR!!!");
		return -1;
	}
	memset(pList,0x0, sizeof(SensorType_t)*num);
	kk_subDev_getSensors_reply(pList);
	for(i = 0; i < num; i++){
		cJSON *Item = cJSON_CreateObject();
		cJSON_AddNumberToObject(Item, "SensorType", pList[i].SensorType);
		cJSON_AddStringToObject(Item, "DeviceCode", pList[i].deviceCode);
		cJSON_AddItemToArray(paramArray, Item);
	}
	char *paramArray22=cJSON_Print(paramArray);
	cJSON_AddItemToObject(payload, "params", paramArray);
	char *payload11=cJSON_Print(payload);
	kk_sendData2app(infff,payload11,0);
	free(payload11);
	free(infff);
	free(pList);
	cJSON_Delete(payload);
	cJSON_Delete(info);
	return res;
}
/************************************************************
*功能描述：获取主机版本信息
*输入参数：params：云端下发数据，包含场景Id等
          msgId：消息Id
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
static int kk_service_getCCUVersion_handle(cJSON *param,cJSON *msgId)
{
	int res = 0;
	int i = 0,num = 0;
	SensorType_t *pList = NULL;
	char version[VERSION_MAXLEN] = {0};
	if(param == NULL || msgId == NULL){
		return INVALID_PARAMETER;
	}
	cJSON *deviceCode = cJSON_GetObjectItem(param, MSG_DEVICE_CODE_STR);	
	if(deviceCode == NULL){
		return FAIL_RETURN;
	}		
	cJSON *productCode = cJSON_GetObjectItem(param, MSG_PRODUCT_CODE_STR);	
	if(productCode == NULL){
		return FAIL_RETURN;
	}		
	cJSON *info = cJSON_CreateObject();
	cJSON_AddStringToObject(info, MSG_TYPE_STR, "/thing/service/getCCUVersion_reply");
	cJSON_AddStringToObject(info, MSG_DEVICE_CODE_STR, deviceCode->valuestring);
	cJSON_AddStringToObject(info, MSG_PRODUCT_CODE_STR, productCode->valuestring);
	char *infff=cJSON_Print(info);

	cJSON *payload = cJSON_CreateObject();
	cJSON_AddStringToObject(payload, "desc", "success");
	cJSON_AddStringToObject(payload, "version", "1.0");
	cJSON_AddStringToObject(payload, "code", "0");
	cJSON_AddStringToObject(payload, "msgId", msgId->valuestring);

	cJSON *Item = cJSON_CreateObject();
	HAL_GetVersion(version);
	cJSON_AddStringToObject(Item, "currentDbVersion", "1.0");
	cJSON_AddStringToObject(Item, "downloadedVersion", version);
	cJSON_AddStringToObject(Item, "currentVersion", version);
	cJSON_AddStringToObject(Item, "firmwareVersion", version);
	cJSON_AddItemToObject(payload, "params", Item);
	char *payload11=cJSON_Print(payload);
	kk_sendData2app(infff,payload11,0);
	free(payload11);
	free(infff);
	cJSON_Delete(payload);
	cJSON_Delete(info);
	return res;
}
/************************************************************
*功能描述：获取主机版本信息
*输入参数：params：云端下发数据，包含场景Id等
          msgId：消息Id
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
static int kk_service_upgrade_reply(cJSON *param,cJSON *msgId)
{
	int res = 0;
	int i = 0,num = 0;
	SensorType_t *pList = NULL;
	char version[VERSION_MAXLEN] = {0};
	if(param == NULL || msgId == NULL){
		return INVALID_PARAMETER;
	}
	cJSON *deviceCode = cJSON_GetObjectItem(param, MSG_DEVICE_CODE_STR);	
	if(deviceCode == NULL){
		return FAIL_RETURN;
	}		
	cJSON *productCode = cJSON_GetObjectItem(param, MSG_PRODUCT_CODE_STR);	
	if(productCode == NULL){
		return FAIL_RETURN;
	}		
	cJSON *info = cJSON_CreateObject();
	cJSON_AddStringToObject(info, MSG_TYPE_STR, "/ota/device/upgrade_reply");
	cJSON_AddStringToObject(info, MSG_DEVICE_CODE_STR, deviceCode->valuestring);
	cJSON_AddStringToObject(info, MSG_PRODUCT_CODE_STR, productCode->valuestring);
	char *infff=cJSON_Print(info);

	cJSON *payload = cJSON_CreateObject();
	cJSON_AddStringToObject(payload, "desc", "success");
	cJSON_AddStringToObject(payload, "version", "1.0");
	cJSON_AddStringToObject(payload, "code", "0");
	cJSON_AddStringToObject(payload, "msgId", msgId->valuestring);

	cJSON *Item = cJSON_CreateObject();
	cJSON_AddItemToObject(payload, "params", Item);
	char *payload11=cJSON_Print(payload);
	kk_sendData2app(infff,payload11,0);
	free(payload11);
	free(infff);
	cJSON_Delete(payload);
	cJSON_Delete(info);
	return res;
}
/************************************************************
*功能描述：告警信息查询返回
*输入参数：params：云端下发数据，包含场景Id等
          msgId：消息Id
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
static int kk_service_historyalarm_reply(cJSON *param)
{
	int res = 0;
	int i = 0,num = 0;
	if(param == NULL){
		return INVALID_PARAMETER;
	}
	cJSON *deviceCode = cJSON_GetObjectItem(param, MSG_DEVICE_CODE_STR);	
	if(deviceCode == NULL){
		return FAIL_RETURN;
	}		
	cJSON *productCode = cJSON_GetObjectItem(param, MSG_PRODUCT_CODE_STR);	
	if(productCode == NULL){
		return FAIL_RETURN;
	}		
	cJSON *info = cJSON_CreateObject();
	cJSON_AddStringToObject(info, MSG_TYPE_STR, KK_THING_SERVICE_HISTORYALARM_REPLY);
	cJSON_AddStringToObject(info, MSG_DEVICE_CODE_STR, deviceCode->valuestring);
	cJSON_AddStringToObject(info, MSG_PRODUCT_CODE_STR, productCode->valuestring);
	char *infff=cJSON_Print(info);

	cJSON *payload = cJSON_CreateObject();
	cJSON_AddStringToObject(payload, "desc", "success");
	cJSON_AddStringToObject(payload, "version", "1.0");
	cJSON_AddStringToObject(payload, "code", "0");
	cJSON *alarminfo = kk_history_get_sensor_info();
	cJSON_AddItemToObject(payload, "params", alarminfo);
	char *payload11=cJSON_Print(payload);
	kk_sendData2app(infff,payload11,0);
	free(payload11);
	free(infff);
	cJSON_Delete(payload);
	cJSON_Delete(info);
	return res;
}
/************************************************************
*功能描述：删除告警信息返回
*输入参数：params：云端下发数据，包含场景Id等
          msgId：消息Id
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
static int kk_service_del_historyalarm_reply(cJSON *param,char *key)
{
	int res = 0;
	int i = 0,num = 0;
	if(param == NULL){
		return INVALID_PARAMETER;
	}
	cJSON *deviceCode = cJSON_GetObjectItem(param, MSG_DEVICE_CODE_STR);	
	if(deviceCode == NULL){
		return FAIL_RETURN;
	}		
	cJSON *productCode = cJSON_GetObjectItem(param, MSG_PRODUCT_CODE_STR);	
	if(productCode == NULL){
		return FAIL_RETURN;
	}		
	cJSON *info = cJSON_CreateObject();
	cJSON_AddStringToObject(info, MSG_TYPE_STR, KK_THING_SERVICE_DEL_HISTORYALARM_REPLY);
	cJSON_AddStringToObject(info, MSG_DEVICE_CODE_STR, deviceCode->valuestring);
	cJSON_AddStringToObject(info, MSG_PRODUCT_CODE_STR, productCode->valuestring);
	char *infff=cJSON_Print(info);

	cJSON *payload = cJSON_CreateObject();
	cJSON_AddStringToObject(payload, "desc", "success");
	cJSON_AddStringToObject(payload, "version", "1.0");
	cJSON_AddStringToObject(payload, "code", "0");
	cJSON_AddStringToObject(payload, "params", key);
	char *payload11=cJSON_Print(payload);
	kk_sendData2app(infff,payload11,0);
	free(payload11);
	free(infff);
	cJSON_Delete(payload);
	cJSON_Delete(info);
	return res;
}
/************************************************************
*功能描述：情景面板绑定处理
*输入参数：params：云端下发数据
           msgId：消息Id
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
static int kk_service_bindScene_handle(cJSON *params,char *deviceCodeStr)
{
	int res = 0;
	int i = 0,num = 0;
	char sceneId[32] = {0};
	char btnId[16] = {0};
	SensorType_t *pList = NULL;
	if(params == NULL || deviceCodeStr == NULL){
		return INVALID_PARAMETER;
	}
	
	cJSON *bindType = cJSON_GetObjectItem(params, "bindType");	
	if(bindType == NULL || bindType->type != cJSON_Number){
		ERROR_PRINT("DATA ERROR!!!");
		return FAIL_RETURN;
	}		
	cJSON *ButtonId = cJSON_GetObjectItem(params, "ButtonId");	
	if(ButtonId == NULL || ButtonId->type != cJSON_Number){
		ERROR_PRINT("DATA ERROR!!!");
		return FAIL_RETURN;
	}
	sprintf(btnId,"%d",ButtonId->valueint);
	kk_scene_delete_panel_scene_info(btnId,deviceCodeStr);//如果已经关联，先删除关联
	
	if(bindType->valueint == 2 || bindType->valueint == 3 ){
		HAL_GetTime_s(sceneId);//use time to create the sceneId
		kk_scene_parse_scene_action(params,sceneId,0);
		kk_scene_insert_panel_scene_info(bindType->valueint,btnId,deviceCodeStr,sceneId);
	}
	else if(bindType->valueint == 1){
		cJSON * action = cJSON_GetObjectItem(params,MSG_SCENE_ACTIONS);
		if(action == NULL || action->type != cJSON_Array){
			ERROR_PRINT("DATA ERROR!!!");
			return FAIL_RETURN;
		}	
		cJSON *client_list  = action->child;
	    while( client_list != NULL ){
	        int isceneId  = cJSON_GetObjectItem( client_list ,"sceneId")->valueint ;
			sprintf(sceneId,"%d",isceneId);
			kk_scene_insert_panel_scene_info(bindType->valueint,btnId,deviceCodeStr,sceneId);
			client_list = client_list->next ;
    	}		
		
	}else if(bindType->valueint == 4){
		HAL_GetTime_s(sceneId);//use time to create the sceneId
		cJSON * action = cJSON_GetObjectItem(params,MSG_SCENE_ACTIONS);
		if(action == NULL || action->type != cJSON_Array) {
			ERROR_PRINT("DATA ERROR!!!");
			return FAIL_RETURN;
		}
		cJSON *item = action->child;
		while(item != NULL){
			cJSON *type = cJSON_GetObjectItem(item,MSG_SCENE_TYPE);
			if(type == NULL) return FAIL_RETURN;
			cJSON *propertyName = cJSON_GetObjectItem(item,MSG_SCENE_PROPERTYNAME);
			if(propertyName == NULL) return FAIL_RETURN;
			cJSON *propertyValue = cJSON_GetObjectItem(item,MSG_SCENE_PROPERTYVALUE);
			if(propertyValue == NULL) return FAIL_RETURN;	
			cJSON *deviceCode = cJSON_GetObjectItem(item,MSG_DEVICE_CODE_STR);
			if(deviceCode == NULL) return FAIL_RETURN;

			res = kk_scene_insert_scene_action(type->valuestring,deviceCode->valuestring,1,
				propertyName->valuestring,propertyValue->valuestring,0,sceneId,deviceCode->valuestring);		
			kk_scene_insert_panel_scene_info(bindType->valueint,btnId,deviceCodeStr,sceneId);
			item = item->next;
		}	

	}
	return res;
}
int kk_service_arming_set(char *state)
{
	int res = 0;
	dm_mgr_dev_node_t *node = NULL;
	dm_mgr_search_dev_by_devid(KK_DM_DEVICE_CCU_DEVICEID,&node);
	res = kk_tsl_set_value(kk_tsl_set_property_value,node->dev_shadow,KK_TSL_CCU_ARMINGSTATE_IDENTIFIER,NULL,state);
	if(res != SUCCESS_RETURN)
	{
		ERROR_PRINT("[%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
	}		
	//HAL_Get_ccuid(ccuid);
	kk_property_db_update(node->deviceCode);	
	//dm_msg_thing_property_set_reply(deviceCode->valuestring,payload_Str, strlen(payload_Str), NULL);
	dm_msg_ccu_property_post(node);
}
/************************************************************
*功能描述：收到云端数据后的回调处理
*输入参数：type：数据类型
          data：具体数据
*输出参数：无
*返 回 值： 无
*其他说明：
*************************************************************/
static void _iotx_linkkit_event_callback(iotx_dm_event_types_t type, char *data)
{
	char *out;
	int res = 0;
	cJSON *json;
	cJSON *info_root;
	cJSON *payload,*typeJson;
	char *payload_Str = NULL;
	cJSON *deviceCode = NULL;
	json=cJSON_Parse(data);

	if (json == NULL) {
		WARNING_PRINT("Error before: [%s]\n","cJSON_Parse");
		return;
	}
	info_root = cJSON_GetObjectItem(json, MSG_INFO_STR);
	if(info_root == NULL) return;
	typeJson = cJSON_GetObjectItem(info_root, MSG_TYPE_STR);
	if(typeJson == NULL) return;	
	payload = cJSON_GetObjectItem(json, MSG_PAYLOAD_STR);
	if(payload == NULL) return;
	payload_Str = cJSON_Print(payload);
	deviceCode = cJSON_GetObjectItem(info_root, MSG_DEVICE_CODE_STR);
	if(deviceCode == NULL) return;

	if (strstr(typeJson->valuestring,KK_REGISTER_TOPIC_REPLY)){
		INFO_PRINT(" topic:register_reply  \n");
		dm_msg_response_payload_t response;
		res = dm_msg_response_parse((char *)payload_Str, strlen(payload->valuestring)+1, &response);
		if (res != SUCCESS_RETURN) {
			goto directReturn;
		}

		_iotx_linkkit_upstream_mutex_lock();
        _iotx_linkkit_upstream_callback_remove(atoi(response.id.value), response.code.value_int);
		_iotx_linkkit_upstream_mutex_unlock();

	}else if (strstr(typeJson->valuestring,KK_ADD_TOPIC_REPLY)){
		INFO_PRINT(" topic:add_reply  \n");
		dm_msg_response_payload_t response;
		res = dm_msg_response_parse((char *)payload_Str, strlen(payload->valuestring)+1, &response);
		if (res != SUCCESS_RETURN) {
			goto directReturn;
		}

		_iotx_linkkit_upstream_mutex_lock();
        _iotx_linkkit_upstream_callback_remove(atoi(response.id.value), response.code.value_int);
		_iotx_linkkit_upstream_mutex_unlock();

	}else if (strstr(typeJson->valuestring,KK_LOGIN_TOPIC_REPLY)){
		INFO_PRINT(" topic:login_reply  \n");
		dm_msg_response_payload_t response;
		res = dm_msg_response_parse((char *)payload_Str, strlen(payload->valuestring)+1, &response);
		if (res != SUCCESS_RETURN) {
			goto directReturn;
		}

		_iotx_linkkit_upstream_mutex_lock();
        _iotx_linkkit_upstream_callback_remove(atoi(response.id.value), response.code.value_int);
		_iotx_linkkit_upstream_mutex_unlock();
	}else if (strstr(typeJson->valuestring,KK_THING_SERVICE_PROPERTY_SET)){
		INFO_PRINT("property set \n");	
		char ccuid[32] = {0};
		dm_mgr_dev_node_t *node = NULL;
		cJSON *paramStr = cJSON_GetObjectItem(payload, MSG_PARAMS_STR);	
		cJSON *state = cJSON_GetObjectItem(paramStr, KK_TSL_CCU_ARMINGSTATE_IDENTIFIER);
		if(state != NULL){
			cJSON *RoomIds = cJSON_GetObjectItem(paramStr, "RoomIds");
			if(RoomIds != NULL){
				kk_room_reset_armingstate();
				int  array_size   = cJSON_GetArraySize ( RoomIds );
				for( int iCnt = 0 ; iCnt < array_size ; iCnt ++ ){
					cJSON * pSub = cJSON_GetArrayItem(RoomIds, iCnt);
					if(NULL == pSub ){continue ; }
					char roomId[16] = {0};
					sprintf(roomId,"%d",pSub->valueint);
					INFO_PRINT("id [%d] : %s\n",iCnt,roomId);
					kk_room_update_armingstate(1,roomId);
				}
				
			}
			kk_service_arming_set(state->valuestring);
		}
	}else if (strstr(typeJson->valuestring,KK_THING_CLOUDSTATE_MSG)){
		INFO_PRINT("cloud state notify \n");
		char ccuid[32] = {0};
		s_CloudStatusRecv = 1;
		cJSON *paramStr = cJSON_GetObjectItem(payload, MSG_PARAMS_STR);	
		cJSON *state = cJSON_GetObjectItem(paramStr, MSG_IOTClOUDSTATE_STR);
		

		dm_mgr_dev_node_t *node = NULL;
		dm_mgr_search_dev_by_devid(KK_DM_DEVICE_CCU_DEVICEID,&node);
		res = kk_tsl_set_value(kk_tsl_set_property_value,node->dev_shadow,KK_TSL_CCU_WANSTATE_IDENTIFIER,&s_CloudStatus,NULL);
		if(res != SUCCESS_RETURN)
		{
			ERROR_PRINT("[%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
		}	

		res = kk_tsl_set_value(kk_tsl_set_property_value,node->dev_shadow,KK_TSL_CCU_IOTCLOUD_IDENTIFIER,&s_CloudStatus,NULL);
		if(res != SUCCESS_RETURN)
		{
			ERROR_PRINT("[%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
		}		
		HAL_Get_ccuid(ccuid);
		kk_property_db_update(ccuid);

		if(s_CloudStatus != atoi(state->valuestring) && atoi(state->valuestring) == 1){
			node->isOffline = KK_DEV_ONLINE;
			dm_mgr_upstream_thing_sub_register(KK_DM_DEVICE_CCU_DEVICEID);
			iotx_dm_dev_online(KK_DM_DEVICE_CCU_DEVICEID);//first online,report the online status
			usleep(200000);
			dm_msg_ccu_property_post(node);
			kk_load_subDevice();
		}
		s_CloudStatus = atoi(state->valuestring);
	}else if (strcmp(typeJson->valuestring,"/upgrade") == 0){
		INFO_PRINT("ota upgrade... \n");
		char tmp[256] = {0};
		snprintf(tmp, sizeof(tmp), "rm -rf %s", OTA_IMG_PATH);
		system(tmp);
		memset(tmp, 0x00, sizeof(tmp));
		snprintf(tmp, sizeof(tmp), "mkdir -p %s", OTA_IMG_PATH);
		system(tmp);		
		kk_dm_ota_send(data, strlen(data)+1);
		cJSON *msgId = cJSON_GetObjectItem(payload, MSG_COMMON_MSGID);
		kk_service_upgrade_reply(info_root,msgId);
	}else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_REBOOT) == 0){
		INFO_PRINT(" reboot called!!!\n");	
		cJSON *msgId = cJSON_GetObjectItem(payload, MSG_COMMON_MSGID);
		dm_msg_thing_event_post(deviceCode->valuestring,MSG_REBOOT_REBOOTNOTIFICATION,msgId->valuestring);
		sleep(3);
		HAL_Reboot();
	}
	else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_ADDROOM) == 0){
		INFO_PRINT(" add room!!!\n");
		cJSON *paramStr = cJSON_GetObjectItem(payload, MSG_PARAMS_STR);	
		cJSON *msgId = cJSON_GetObjectItem(payload, MSG_COMMON_MSGID);	  
		kk_service_addRoom_handle(deviceCode->valuestring,paramStr);
		dm_msg_thing_event_post(deviceCode->valuestring,MSG_AREA_ADDROOM_NOTIFICATION,msgId->valuestring);
	}
	else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_DELETEROOM) == 0){
		INFO_PRINT(" delete room  \n");
		cJSON *paramStr = cJSON_GetObjectItem(payload, MSG_PARAMS_STR);
		kk_service_deleteRoom_handle(paramStr);
	}
	else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_ADDDEVICETOROOM) == 0){
		INFO_PRINT(" adddevicetoroom  \n");
		cJSON *paramStr = cJSON_GetObjectItem(payload, MSG_PARAMS_STR);
		cJSON *msgId = cJSON_GetObjectItem(payload, MSG_COMMON_MSGID);
		kk_service_addDeviceToRoom_handle(paramStr);
		kk_service_addDeviceToRoom_reply(info_root,msgId);
	}
	else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_REMOVEDEVICEFROMROOM) == 0){
		INFO_PRINT(" removedevicefromroom  \n");
		cJSON *paramStr = cJSON_GetObjectItem(payload, MSG_PARAMS_STR);
		kk_service_removeDeviceFromRoom_handle(paramStr);
	}
	else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_EXECUTEROOM) == 0){
		INFO_PRINT(" executeroom  \n");
		cJSON *paramStr = cJSON_GetObjectItem(payload, MSG_PARAMS_STR);
		kk_service_executeRoom_handle(paramStr);
	}
	else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_ADDSCENC) == 0){
		INFO_PRINT(" add scene \n");
		cJSON *paramStr = cJSON_GetObjectItem(payload, MSG_PARAMS_STR);
		cJSON *msgId = cJSON_GetObjectItem(payload, MSG_COMMON_MSGID);
		kk_service_addScene_handle(paramStr,msgId);
	}
	else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_UPDATESCENC) == 0){
		INFO_PRINT(" update scene  \n");
		cJSON *paramStr = cJSON_GetObjectItem(payload, MSG_PARAMS_STR);
		cJSON *msgId = cJSON_GetObjectItem(payload, MSG_COMMON_MSGID);
		kk_service_updateScene_handle(paramStr,msgId);
	}
	else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_DELETESCENC) == 0){
		INFO_PRINT("delete scene  \n");
		cJSON *paramStr = cJSON_GetObjectItem(payload, MSG_PARAMS_STR);	
		cJSON *msgId = cJSON_GetObjectItem(payload, MSG_COMMON_MSGID);
		kk_service_deleteScene_handle(paramStr,msgId);
	}
	else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_EXECUTESCENE) == 0){
		INFO_PRINT("execute scene  \n");
		cJSON *paramStr = cJSON_GetObjectItem(payload, MSG_PARAMS_STR);	
		cJSON *msgId = cJSON_GetObjectItem(payload, MSG_COMMON_MSGID);
		kk_service_executeScene_handle(paramStr,msgId);
	}else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_SYNCDEVICEINFO) == 0){
		INFO_PRINT("SYNCDEVICEINFO service  \n");
		cJSON *msgId = cJSON_GetObjectItem(payload, MSG_COMMON_MSGID);
		dm_msg_thing_syncdeviceinfo_reply(msgId);
	}
	else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_GETGUARDSENSORS) == 0){
		INFO_PRINT("get guardgensors  \n");
		cJSON *msgId = cJSON_GetObjectItem(payload, MSG_COMMON_MSGID);
		kk_service_getGuardSensors_handle(info_root,msgId);
	}
	else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_NEGATIVE) == 0){
		INFO_PRINT("negative service  \n");
		cJSON *paramStr = cJSON_GetObjectItem(payload, MSG_PARAMS_STR);	
		if(paramStr != NULL){
			cJSON *identifierStr = cJSON_GetObjectItem(paramStr, MSG_SCENE_NEGATICE);
			if(identifierStr != NULL){
				int value_ = 0;
				dm_mgr_dev_node_t *node = NULL;	
				kk_property_db_get_value(deviceCode->valuestring,identifierStr->valuestring, &value_);
				value_ = !value_;
				res = dm_mgr_get_device_by_devicecode(deviceCode->valuestring, &node);
				if (res != SUCCESS_RETURN) {
					goto directReturn;
				}
				cJSON *root_ =cJSON_CreateObject();
				cJSON_AddNumberToObject(root_,identifierStr->valuestring,value_);
				char *out_=cJSON_Print(root_);
				kk_msg_execute_property_set(node->productCode,node->deviceCode,out_,node->fatherDeviceCode);
				cJSON_Delete(root_); 
				free(out_);
			}
		}
	} 
	else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_SYNCINFO) == 0){
		INFO_PRINT("SYNCINFO service  \n");
		dm_msg_thing_syncinfo_reply();
	}
	else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_BINDSCENE) == 0){
		INFO_PRINT("bind scene  \n");
		cJSON *paramStr = cJSON_GetObjectItem(payload, MSG_PARAMS_STR);
		if(paramStr != NULL){
			kk_service_bindScene_handle(paramStr,deviceCode->valuestring);
		}
	}
	else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_UNBINDSBUTTTON) == 0){
		INFO_PRINT("unbind button  \n");
		cJSON *paramStr = cJSON_GetObjectItem(payload,MSG_PARAMS_STR);
		if(paramStr != NULL){
			char btnId[16] = {0};
			cJSON *buttonId = cJSON_GetObjectItem(paramStr, "ButtonId");
			if(buttonId == NULL || buttonId->type != cJSON_Number){
				ERROR_PRINT("DATA ERROR!!!\n");
				goto directReturn;
			}		
			sprintf(btnId,"%d",buttonId->valueint);
			kk_scene_delete_panel_scene_info(btnId,deviceCode->valuestring);
		}
	}	
	else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_ACTIVEBUTTON) == 0){
		INFO_PRINT("active button  \n");
		cJSON *paramStr = cJSON_GetObjectItem(payload,MSG_PARAMS_STR);
		if(paramStr != NULL){
			char btnId[16] = {0};
			cJSON *buttonId = cJSON_GetObjectItem(paramStr, "ButtonId");
			if(buttonId == NULL || buttonId->type != cJSON_Number){
				ERROR_PRINT("DATA ERROR!!!\n");
				goto directReturn;
			}		
			sprintf(btnId,"%d",buttonId->valueint);
			kk_scene_execute_quickpanel(btnId,deviceCode->valuestring);
		}
	}
	else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_GETCCUVERSION) == 0){
		INFO_PRINT("GET CCU VERISON  \n");
		cJSON *msgId = cJSON_GetObjectItem(payload, MSG_COMMON_MSGID);
		kk_service_getCCUVersion_handle(info_root,msgId);
	}	
	else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_HISTORYALARM) == 0){
		kk_service_historyalarm_reply(info_root);	
	}
	else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_DEL_HISTORYALARM) == 0){
		cJSON *key = cJSON_GetObjectItem(payload, MSG_PARAMS_STR);
		if(key != NULL){
			kk_history_delete_by_recordtime("SensorHistoryInfo",atoi(key->valuestring)); 
			kk_service_del_historyalarm_reply(info_root,key->valuestring);
		}
			
	}	
	else{
		INFO_PRINT("Error msgtype!!! \n");
	}

directReturn:
	free(payload_Str);
	cJSON_Delete(json);
}

/************************************************************
*功能描述：模块初始化，包括回调注册
*输入参数：无
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
int kk_init_dmproc(void)
{
	int res = 0;
	iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();

	res = iotx_dm_open();
	if (res != SUCCESS_RETURN) {
		dm_log_err("DM iotx_dm_open Failed");

		return FAIL_RETURN;
	}

	res = iotx_dm_connect(_iotx_linkkit_event_callback);
	if (res != SUCCESS_RETURN) {
		dm_log_err("DM Start Failed");
		//ctx->is_connected = 0;
		return FAIL_RETURN;
	}

	if (ctx->is_opened) {
		return FAIL_RETURN;
	}
	ctx->is_opened = 1;


	/* Create Mutex */
	ctx->mutex = HAL_MutexCreate();
	if (ctx->mutex == NULL) {
		dm_log_err("Not Enough Memory");
		ctx->is_opened = 0;
		return FAIL_RETURN;
	}


	ctx->upstream_mutex = HAL_MutexCreate();
	if (ctx->upstream_mutex == NULL) {
		HAL_MutexDestroy(ctx->mutex);
		dm_log_err("Not Enough Memory");
		ctx->is_opened = 0;
		return FAIL_RETURN;
	}


	INIT_LIST_HEAD(&ctx->upstream_sync_callback_list);

	return SUCCESS_RETURN;
}
/************************************************************
*功能描述：子设备连接处理，主要是topo add
*输入参数：devid：设备ID
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
int _iotx_linkkit_slave_connect(int devid)
{
    int res = 0;
    //iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
    //iotx_linkkit_upstream_sync_callback_node_t *node = NULL;
    //void *semaphore = NULL;

    if (devid <= 0) {
        dm_log_err("devid invalid");
        return FAIL_RETURN;
    }

    /* Subdev Add Topo */
    res = kk_dm_subdev_topo_add(devid);
    if (res < SUCCESS_RETURN) {
        _iotx_linkkit_mutex_unlock();
        return FAIL_RETURN;
    }

    return SUCCESS_RETURN;
}

/************************************************************
*功能描述：子设备注册
*输入参数：devid：设备ID
*输出参数：无
*返 回 值： 0：成功；其他：失败register
*其他说明：
*************************************************************/
int _iotx_linkkit_slave_register(int devid)
{
    int res = 0;
    //iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
    //iotx_linkkit_upstream_sync_callback_node_t *node = NULL;
    //void *semaphore = NULL;
    if (devid <= 0) {
        dm_log_err("devid invalid");
        return FAIL_RETURN;
    }

    /* Subdev Add Topo */
    res = kk_dm_subdev_register(devid);
    if (res < SUCCESS_RETURN) {
        return FAIL_RETURN;
    }

    return SUCCESS_RETURN;
}
/************************************************************
*功能描述：子设备删除处理，
*输入参数：devid：设备ID
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
static int _iotx_linkkit_subdev_delete_topo(int devid)
{
    int res = 0, msgid = 0, code = 0;
    iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
    iotx_linkkit_upstream_sync_callback_node_t *node = NULL;
    void *semaphore = NULL;

    if (ctx->is_connected == 0) {
        dm_log_err("master isn't start");
        return FAIL_RETURN;
    }

    if (devid <= 0) {
        dm_log_err("devid invalid");
        return FAIL_RETURN;
    }

    /* Subdev Delete Topo */
    res = iotx_dm_subdev_topo_del(devid);
    if (res < SUCCESS_RETURN) {
        return FAIL_RETURN;
    }
    msgid = res;

    semaphore = HAL_SemaphoreCreate();
    if (semaphore == NULL) {
        return FAIL_RETURN;
    }

    _iotx_linkkit_upstream_mutex_lock();
    res = _iotx_linkkit_upstream_sync_callback_list_insert(msgid, semaphore, &node);
    if (res != SUCCESS_RETURN) {
        HAL_SemaphoreDestroy(semaphore);
        _iotx_linkkit_upstream_mutex_unlock();
        return FAIL_RETURN;
    }
    _iotx_linkkit_upstream_mutex_unlock();

    res = HAL_SemaphoreWait(semaphore, IOTX_LINKKIT_SYNC_DEFAULT_TIMEOUT_MS);
    if (res < SUCCESS_RETURN) {
        _iotx_linkkit_upstream_mutex_lock();
        _iotx_linkkit_upstream_sync_callback_list_remove(msgid);
        _iotx_linkkit_upstream_mutex_unlock();
        return FAIL_RETURN;
    }

    _iotx_linkkit_upstream_mutex_lock();
    code = node->code;
    _iotx_linkkit_upstream_sync_callback_list_remove(msgid);
    if (code != SUCCESS_RETURN) {
        _iotx_linkkit_upstream_mutex_unlock();
        return FAIL_RETURN;
    }
    _iotx_linkkit_upstream_mutex_unlock();

    return SUCCESS_RETURN;
}
/************************************************************
*功能描述：主模块释放处理
*输入参数：无
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
static int _iotx_linkkit_master_close(void)
{
    iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();

    _iotx_linkkit_mutex_lock();
    if (ctx->is_opened == 0) {
        _iotx_linkkit_mutex_unlock();
        return FAIL_RETURN;
    }
    ctx->is_opened = 0;

    //iotx_dm_close();
#if 1//DEVICE_MODEL_GATEWAY
    _iotx_linkkit_upstream_sync_callback_list_destroy();
    HAL_MutexDestroy(ctx->upstream_mutex);
#endif
    _iotx_linkkit_mutex_unlock();
    HAL_MutexDestroy(ctx->mutex);
    memset(ctx, 0, sizeof(iotx_linkkit_ctx_t));

    return SUCCESS_RETURN;
}


/************************************************************
*功能描述：子模块释放处理
*输入参数：devid：设备Id
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
static int _iotx_linkkit_slave_close(int devid)
{
    iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();

    _iotx_linkkit_mutex_lock();
    if (ctx->is_opened == 0) {
        _iotx_linkkit_mutex_unlock();
        return FAIL_RETURN;
    }

    /* Release Subdev Resources */
    //iotx_dm_subdev_destroy(devid);

    _iotx_linkkit_mutex_unlock();

    return SUCCESS_RETURN;
}

/************************************************************
*功能描述：消息处理主任务
*输入参数：timeout_ms：超时时间
*输出参数：无
*返 回 值： 无
*其他说明：
*************************************************************/

void IOT_Linkkit_Yield(int timeout_ms)
{
	//iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();

	if (timeout_ms <= 0) {
		dm_log_err("Invalid Parameter");
		return;
	}

	//if (ctx->is_opened == 0 || ctx->is_connected == 0) {
	//    return;
	//}

	//iotx_dm_yield(timeout_ms);
	iotx_dm_dispatch();

#if 1//DEVICE_MODEL_GATEWAY
	HAL_SleepMs(timeout_ms);
#endif
}

/************************************************************
*功能描述：模块释放处理
*输入参数：devid：设备Id
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
int IOT_Linkkit_Close(int devid)
{
    int res = 0;

    if (devid < 0) {
        dm_log_err("Invalid Parameter");
        return FAIL_RETURN;
    }

    if (devid == IOTX_DM_LOCAL_NODE_DEVID) {
        res = _iotx_linkkit_master_close();
#ifdef DEV_BIND_ENABLED
        awss_bind_deinit();
#endif
    } else {
#if 1//DEVICE_MODEL_GATEWAY
        res = _iotx_linkkit_slave_close(devid);
#else
        res = FAIL_RETURN;
#endif
    }

    return res;
}

/************************************************************
*功能描述：子设备注册，topo add 后的在线上报
*输入参数：devid：设备Id
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
static int _iotx_linkkit_subdev_login(int devid)
{
	int res = 0;
	//iotx_linkkit_upstream_sync_callback_node_t *node = NULL;
	//void *semaphore = NULL;
	//void *callback = NULL;

	res = iotx_dm_dev_online(devid);//iotx_dm_subdev_login(devid);
	if (res < SUCCESS_RETURN) {
		return FAIL_RETURN;
	}

#ifdef MSG_NEED_RESP
    msgid = res;
    semaphore = HAL_SemaphoreCreate();
    if (semaphore == NULL) {
        return FAIL_RETURN;
    }

    _iotx_linkkit_upstream_mutex_lock();
    res = _iotx_linkkit_upstream_sync_callback_list_insert(msgid, semaphore, &node);
    if (res != SUCCESS_RETURN) {
        HAL_SemaphoreDestroy(semaphore);
        _iotx_linkkit_upstream_mutex_unlock();
        return FAIL_RETURN;
    }
    _iotx_linkkit_upstream_mutex_unlock();

    res = HAL_SemaphoreWait(semaphore, IOTX_LINKKIT_SYNC_DEFAULT_TIMEOUT_MS);
    if (res < SUCCESS_RETURN) {
        _iotx_linkkit_upstream_mutex_lock();
        _iotx_linkkit_upstream_sync_callback_list_remove(msgid);
        _iotx_linkkit_upstream_mutex_unlock();
        return FAIL_RETURN;
    }

    _iotx_linkkit_upstream_mutex_lock();
    code = node->code;
    _iotx_linkkit_upstream_sync_callback_list_remove(msgid);
    if (code != SUCCESS_RETURN) {
        _iotx_linkkit_upstream_mutex_unlock();
        return FAIL_RETURN;
    }
    _iotx_linkkit_upstream_mutex_unlock();
#endif

	res = iotx_dm_subscribe(devid);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}

	/*iotx_dm_send_aos_active(devid);
	callback = iotx_event_callback(ITE_INITIALIZE_COMPLETED);
	if (callback) {
		((int (*)(const int))callback)(devid);
	}*/

	return res;
}

/************************************************************
*功能描述：子设备添加到设备队列和数据库中处理函数
*输入参数：devType：设备类型
          productCode：产品Id
          deviceCode:设备Id
          mac:设备MAC
          fatherDeviceCode：父设备DeviceCode
          
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
int kk_mid_subdev_add(int devType, char productCode[PRODUCT_CODE_MAXLEN], char deviceCode[DEVICE_CODE_MAXLEN],char mac[DEVICE_MAC_MAXLEN],char fatherDeviceCode[DEVICE_CODE_MAXLEN]){
	int res = 0;
	int devid = 0;
	int heartbeat = 0;
	dm_mgr_dev_node_t *node = NULL;	
	res = dm_mgr_subdev_create(devType,productCode,deviceCode,mac,fatherDeviceCode,KK_DEV_ONLINE,&devid,&heartbeat);
	if (res != SUCCESS_RETURN && TSL_ALREADY_EXIST != res) {
		ERROR_PRINT("subdev create Failed\n");
		return FAIL_RETURN;
	}

	if (TSL_ALREADY_EXIST == res){
		//todo
	}else{
        res = kk_subDev_insert_db(devType,productCode,deviceCode,fatherDeviceCode,mac,"1.1.0",heartbeat);
        if (res != SUCCESS_RETURN) {
            return FAIL_RETURN;
        }
		res = dm_mgr_get_device_by_devicecode(deviceCode, &node);
		if (res != SUCCESS_RETURN) {
			return FAIL_RETURN;
		}
		kk_subDev_update_productType(node->productType,deviceCode);
    }

	_iotx_linkkit_mutex_lock();
    res = _iotx_linkkit_slave_connect(devid);
    if (res != SUCCESS_RETURN) {

        _iotx_linkkit_mutex_unlock();
        return FAIL_RETURN;
    }

    res = _iotx_linkkit_slave_register(devid);
    if (res != SUCCESS_RETURN) {

		_iotx_linkkit_mutex_unlock();
        return FAIL_RETURN;
    }
    res = _iotx_linkkit_subdev_login(devid);
    if (res != SUCCESS_RETURN) {
        _iotx_linkkit_mutex_unlock();
        return FAIL_RETURN;
    }

	_iotx_linkkit_mutex_unlock();
	return SUCCESS_RETURN;
}

/************************************************************
*功能描述：批量子设备添加到设备队列和数据库中处理函数
*输入参数：productCode：产品Id
          deviceCode:设备Id
          mac:设备MAC
          fatherDeviceCode：父设备DeviceCode
          
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/

int kk_mid_subdev_batch_add( char productCode[PRODUCT_CODE_MAXLEN], char deviceCode[DEVICE_CODE_MAXLEN],char mac[DEVICE_MAC_MAXLEN],char fatherDeviceCode[DEVICE_CODE_MAXLEN]){
	int res = 0;
	int devid = 0;
	int heartbeat = 0;
	res = dm_mgr_subdev_create(KK_DM_DEVICE_SUBDEV,productCode,deviceCode,mac,fatherDeviceCode,KK_DEV_ONLINE,&devid,&heartbeat);
	if (res != SUCCESS_RETURN && TSL_ALREADY_EXIST != res) {
		ERROR_PRINT("subdev create Failed\n");
		return FAIL_RETURN;
	}

	if (TSL_ALREADY_EXIST == res){
		//todo
	}else{
		res = kk_subDev_insert_db(KK_DM_DEVICE_SUBDEV,productCode,deviceCode,fatherDeviceCode,mac,"1.1.0",heartbeat);
		if (res != SUCCESS_RETURN) {
			return FAIL_RETURN;
		}
	}

	res = _iotx_linkkit_subdev_login(devid);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}
	_iotx_linkkit_mutex_unlock();
	return SUCCESS_RETURN;
}


