/************************************************************
*版权所有 （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_tsl_api.h"
#include "com_api.h"
#include "kk_log.h"
#include "kk_area_handle.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(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);	
	if(roomInfoStr == NULL){
		return FAIL_RETURN;
	}
	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;
	
}
/************************************************************
*功能描述：添加设备到房间处理函数
*输入参数：params：云端传下来JSON数据，主要包含房间ID和设备deviceCode
*输出参数：无
*返 回 值： 0：成功；其他：失败
*其他说明：
*************************************************************/
static int kk_service_addDeviceToRoom_handle(cJSON *params)
{
	char epNumStr[10] = {0};
	if(params == NULL){
		return INVALID_PARAMETER;
	}

	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;
	}	
	cJSON *epNum = cJSON_GetObjectItem(params, MSG_AREA_ROOM_EPNUM);	
	if(epNum == NULL){
		strcpy(epNumStr,"1");
	}else{
		strcpy(epNumStr,epNum->valuestring);
	}		
	kk_room_dev_add(roomId->valuestring,deviceCode->valuestring,epNumStr);
	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;
}
#if 0
static int kk_service_setLocalTimer_handle(cJSON *params,const char *deviceCode)
{
	int res = 0;
	kk_dev_list_t *pList = NULL;
	dm_mgr_dev_node_t *search_node = NULL;	
	char *timer = NULL,*targets = NULL;
	int isEnable  = 0, isValid = 0, zoneOffset = 0;
	int size = 0	;

	if(params == NULL || deviceCode == NULL){
		return INVALID_PARAMETER;
	}
	res = dm_mgr_get_device_by_devicecode(deviceCode,&search_node);	
    if (res < SUCCESS_RETURN) {
		ERROR_PRINT("dm_mgr_get_device_by_devicecode failed\n");
        return res;
    }

	size = kk_service_get_array_size(search_node->dev_shadow);
	
	cJSON *LocalTimerArray = cJSON_GetObjectItem(params, MSG_TIMER_SETLOCALTIMER_LOCALTIMER);	
	if(LocalTimerArray == NULL){
		return FAIL_RETURN;
	}
	cJSON * item = LocalTimerArray->child;
	while(item != NULL){

		timer = cJSON_GetObjectItem(item,MSG_TIMER_SETLOCALTIMER_TIMER)->valuestring;
	    isEnable = cJSON_GetObjectItem(item,MSG_TIMER_SETLOCALTIMER_ENABLE)->valueint;
		isValid = cJSON_GetObjectItem(item,MSG_TIMER_SETLOCALTIMER_ISVALID)->valueint;
		zoneOffset = cJSON_GetObjectItem(item,MSG_TIMER_SETLOCALTIMER_ZONEOFFSET)->valueint;
		targets = cJSON_GetObjectItem(item,MSG_TIMER_SETLOCALTIMER_TARGETS)->valuestring;
		kk_service_localtimer_set(search_node->dev_shadow,timer,isEnable,isValid,zoneOffset,targets,size);
		item = item->next;
	}
	return SUCCESS_RETURN;
}
static int kk_service_getLocalTimer_handle(const char *deviceCode)
{
	if(deviceCode == NULL){
		return INVALID_PARAMETER;
	}
	dm_msg_thing_service_post(deviceCode,MSG_TIMER_GETLOCALTIMER_GETLOCALTIMER);

	return SUCCESS_RETURN;
}

static int kk_service_setCountDown_handle(cJSON *params,const char *deviceCode)
{
	int res = 0;
	kk_dev_list_t *pList = NULL;
	dm_mgr_dev_node_t *search_node = NULL;	
	char *targets = NULL;
	int isEnable  = 0, isValid = 0, delaytimer = 0,current = 0;
	int size = 0	;

	if(params == NULL || deviceCode == NULL){
		return INVALID_PARAMETER;
	}
	res = dm_mgr_get_device_by_devicecode(deviceCode,&search_node);	
    if (res < SUCCESS_RETURN) {
		ERROR_PRINT("dm_mgr_get_device_by_devicecode failed\n");
        return res;
    }

	size = kk_service_get_array_size(search_node->dev_shadow);

	cJSON *LocalTimerArray = cJSON_GetObjectItem(params, MSG_TIMER_SETCOUNTDOWN_COUNTDOWN);	
	if(LocalTimerArray == NULL){
		return FAIL_RETURN;
	}
	cJSON * item = LocalTimerArray->child;
	while(item != NULL){
		delaytimer = cJSON_GetObjectItem(item,MSG_TIMER_SETCOUNTDOWN_DELAYTIME)->valueint;
	    current = cJSON_GetObjectItem(item,MSG_TIMER_SETCOUNTDOWN_CURRENTTIME)->valueint;
		isValid = cJSON_GetObjectItem(item,MSG_TIMER_SETLOCALTIMER_ISVALID)->valueint;
		isEnable = cJSON_GetObjectItem(item,MSG_TIMER_SETLOCALTIMER_ENABLE)->valueint;
		targets = cJSON_GetObjectItem(item,MSG_TIMER_SETLOCALTIMER_TARGETS)->valuestring;
		kk_service_setCountDown_set(search_node->dev_shadow,delaytimer,current,isEnable,isValid,targets,size);
		item = item->next;
	}
	return SUCCESS_RETURN;
}

static int kk_service_getCountDown_handle(const char *deviceCode)
{
	if(deviceCode == NULL){
		return INVALID_PARAMETER;
	}
	dm_msg_thing_service_post(deviceCode,MSG_TIMER_SETCOUNTDOWN_GETCOUNTDOWN);

	return SUCCESS_RETURN;
}

static int kk_service_getLockKeylist_handle(const char *deviceCode)
{
	if(deviceCode == NULL){
		return INVALID_PARAMETER;
	}

	return SUCCESS_RETURN;
}

static int kk_service_addKey_handle(const char *deviceCode,cJSON *param)
{
	char keyId[32] = {0};
	int res = 0;
	dm_mgr_dev_node_t *node = NULL;	
	if(deviceCode == NULL || param == NULL){
		return INVALID_PARAMETER;
	}
    res = dm_mgr_get_device_by_devicecode(deviceCode, &node);
    if (res < SUCCESS_RETURN) {
		ERROR_PRINT("dm_mgr_get_device_by_devicecode failed\n");
        return res;
    }

	cJSON *KeyType = cJSON_GetObjectItem(param,MSG_KEYADD_KEYTYPE);
	if(KeyType == NULL) return FAIL_RETURN;
	cJSON *KeyRole = cJSON_GetObjectItem(param,MSG_KEYADD_KEYROLE);	
	if(KeyRole == NULL) return FAIL_RETURN;
	cJSON *IsValid = cJSON_GetObjectItem(param,MSG_KEYADD_KEYISVALID);	
	if(IsValid == NULL) return FAIL_RETURN;
	cJSON *KeyName = cJSON_GetObjectItem(param,MSG_KEYADD_KEYNAME);
	if(KeyName == NULL) return FAIL_RETURN;;
	cJSON *KeyEffectiveTime = cJSON_GetObjectItem(param,MSG_KEYADD_KEYEFFECTIVE); 
	if(KeyEffectiveTime == NULL) return FAIL_RETURN;;
	cJSON *KeyExpiryTime = cJSON_GetObjectItem(param,MSG_KEYADD_KEYEXPIRE);
	if(KeyExpiryTime == NULL) return FAIL_RETURN;;
	HAL_GetTime_s(keyId);
	kk_property_update_lockkeys(deviceCode,keyId,KeyType->valueint,KeyRole->valueint,IsValid->valueint,
				KeyName->valuestring,KeyEffectiveTime->valueint,KeyExpiryTime->valueint);
	kk_tsl_set_value(kk_tsl_set_event_output_value,node->dev_shadow,MSG_KEYADD_NOTIFICATION_KEYID,NULL,keyId);		
	kk_tsl_set_value(kk_tsl_set_event_output_value,node->dev_shadow,MSG_KEYADD_NOTIFICATION_KEYTYPE,&KeyType->valueint,NULL);	
	kk_tsl_set_value(kk_tsl_set_event_output_value,node->dev_shadow,MSG_KEYADD_NOTIFICATION_KEYROLE,&KeyRole->valueint,NULL);
	kk_tsl_set_value(kk_tsl_set_event_output_value,node->dev_shadow,MSG_KEYADD_NOTIFICATION_KEYISVALID,&IsValid->valueint,NULL);
	kk_tsl_set_value(kk_tsl_set_event_output_value,node->dev_shadow,MSG_KEYADD_NOTIFICATION_KEYNAME,NULL,KeyName->valuestring);
	kk_tsl_set_value(kk_tsl_set_event_output_value,node->dev_shadow,MSG_KEYADD_NOTIFICATION_KEYEFFECTIVE,&IsValid->valueint,NULL);
	kk_tsl_set_value(kk_tsl_set_event_output_value,node->dev_shadow,MSG_KEYADD_NOTIFICATION_KEYEXPIRE,&IsValid->valueint,NULL);
	dm_msg_thing_event_post(deviceCode,MSG_KEYADD_NOTIFICATION);

	return SUCCESS_RETURN;
}

static int kk_service_modifyKey_handle(const char *deviceCode,cJSON *param)
{
	int res = 0;
	dm_mgr_dev_node_t *node = NULL;	
	if(deviceCode == NULL || param == NULL){
		return INVALID_PARAMETER;
	}
    res = dm_mgr_get_device_by_devicecode(deviceCode, &node);
    if (res < SUCCESS_RETURN) {
		ERROR_PRINT("dm_mgr_get_device_by_devicecode failed\n");
        return res;
    }
	cJSON *keyId = cJSON_GetObjectItem(param,MSG_KEYADD_KEYID);	
	if(keyId == NULL) return FAIL_RETURN;
	cJSON *KeyType = cJSON_GetObjectItem(param,MSG_KEYADD_KEYTYPE);
	if(KeyType == NULL) return FAIL_RETURN;
	cJSON *KeyRole = cJSON_GetObjectItem(param,MSG_KEYADD_KEYROLE);	
	if(KeyRole == NULL) return FAIL_RETURN;
	cJSON *IsValid = cJSON_GetObjectItem(param,MSG_KEYADD_KEYISVALID);	
	if(IsValid == NULL) return FAIL_RETURN;
	cJSON *KeyName = cJSON_GetObjectItem(param,MSG_KEYADD_KEYNAME);
	if(KeyName == NULL) return FAIL_RETURN;;
	cJSON *KeyEffectiveTime = cJSON_GetObjectItem(param,MSG_KEYADD_KEYEFFECTIVE); 
	if(KeyEffectiveTime == NULL) return FAIL_RETURN;;
	cJSON *KeyExpiryTime = cJSON_GetObjectItem(param,MSG_KEYADD_KEYEXPIRE);
	if(KeyExpiryTime == NULL) return FAIL_RETURN;;

	kk_property_update_lockkeys(deviceCode,keyId->valuestring,KeyType->valueint,KeyRole->valueint,IsValid->valueint,
				KeyName->valuestring,KeyEffectiveTime->valueint,KeyExpiryTime->valueint);
	kk_tsl_set_value(kk_tsl_set_event_output_value,node->dev_shadow,MSG_KEYMODIFY_NOTIFICATION_KEYID,NULL,keyId->valuestring);		
	kk_tsl_set_value(kk_tsl_set_event_output_value,node->dev_shadow,MSG_KEYMODIFY_NOTIFICATION_KEYTYPE,&KeyType->valueint,NULL);	
	kk_tsl_set_value(kk_tsl_set_event_output_value,node->dev_shadow,MSG_KEYMODIFY_NOTIFICATION_KEYROLE,&KeyRole->valueint,NULL);
	kk_tsl_set_value(kk_tsl_set_event_output_value,node->dev_shadow,MSG_KEYMODIFY_NOTIFICATION_KEYISVALID,&IsValid->valueint,NULL);
	kk_tsl_set_value(kk_tsl_set_event_output_value,node->dev_shadow,MSG_KEYMODIFY_NOTIFICATION_KEYNAME,NULL,KeyName->valuestring);
	kk_tsl_set_value(kk_tsl_set_event_output_value,node->dev_shadow,MSG_KEYMODIFY_NOTIFICATION_KEYEFFECTIVE,&IsValid->valueint,NULL);
	kk_tsl_set_value(kk_tsl_set_event_output_value,node->dev_shadow,MSG_KEYMODIFY_NOTIFICATION_KEYEXPIRE,&IsValid->valueint,NULL);
	dm_msg_thing_event_post(deviceCode,MSG_KEYMODIFY_NOTIFICATION);

	return SUCCESS_RETURN;
}

static int kk_service_deleteKey_handle(const char *deviceCode,cJSON *param)
{
	int res = 0;
	dm_mgr_dev_node_t *node = NULL;	
	if(deviceCode == NULL || param == NULL){
		return INVALID_PARAMETER;
	}
    res = dm_mgr_get_device_by_devicecode(deviceCode, &node);
    if (res < SUCCESS_RETURN) {
		ERROR_PRINT("dm_mgr_get_device_by_devicecode failed\n");
        return res;
    }
	cJSON *KeyType = cJSON_GetObjectItem(param,MSG_KEYADD_KEYTYPE);
	if(KeyType == NULL) return FAIL_RETURN;
	cJSON *KeyRole = cJSON_GetObjectItem(param,MSG_KEYADD_KEYROLE);	
	if(KeyRole == NULL) return FAIL_RETURN;
	cJSON *keyId = cJSON_GetObjectItem(param,MSG_KEYADD_KEYID);	
	if(keyId == NULL) return FAIL_RETURN;
	kk_property_delete_lockkeys(deviceCode,keyId->valuestring);
	
	kk_tsl_set_value(kk_tsl_set_event_output_value,node->dev_shadow,MSG_KEYDELETE_NOTIFICATION_KEYID,NULL,keyId->valuestring);		
	kk_tsl_set_value(kk_tsl_set_event_output_value,node->dev_shadow,MSG_KEYDELETE_NOTIFICATION_KEYTYPE,&KeyType->valueint,NULL);	
	kk_tsl_set_value(kk_tsl_set_event_output_value,node->dev_shadow,MSG_KEYDELETE_NOTIFICATION_KEYROLE,&KeyRole->valueint,NULL);
	dm_msg_thing_event_post(deviceCode,MSG_KEYDELETE_NOTIFICATION);

	return SUCCESS_RETURN;
}
#endif
/************************************************************
*功能描述：添加场景处理
*输入参数：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;
}
/************************************************************
*功能描述：收到云端数据后的回调处理
*输入参数：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");	
        dm_msg_thing_property_set_reply(deviceCode->valuestring,payload_Str, strlen(payload_Str), NULL);
   }else if (strstr(typeJson->valuestring,KK_THING_CLOUDSTATE_MSG)){
        INFO_PRINT("cloud state notify \n");
		s_CloudStatusRecv = 1;
		cJSON *paramStr = cJSON_GetObjectItem(payload, MSG_PARAMS_STR);	
		cJSON *state = cJSON_GetObjectItem(paramStr, MSG_IOTClOUDSTATE_STR);
		s_CloudStatus = atoi(state->valuestring);

		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);
		}		

		kk_property_db_update("CCU_66666");

		if(s_CloudStatus){
			node->isOffline = KK_DEV_ONLINE;

			iotx_dm_dev_online(KK_DM_DEVICE_CCU_DEVICEID);//first online,report the online status
			usleep(200000);
			dm_msg_ccu_property_post(node);
		}

   }else if (strstr(typeJson->valuestring,KK_THING_OTA_DEVICE_UPGRADE)){
        INFO_PRINT("ota upgrade... \n");
        kk_dm_ota_send(data, strlen(data)+1);
        
   }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);	
   		kk_service_addDeviceToRoom_handle(paramStr);
   }  
   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);

   }
#if 0   
   else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_SETLOCALTIMER) == 0){
   		INFO_PRINT(" setlocaltimer  \n");
		cJSON *paramStr = cJSON_GetObjectItem(payload, MSG_PARAMS_STR);
		
		kk_service_setLocalTimer_handle(paramStr,deviceCode->valuestring);
   }
   else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_GETLOCALTIMER) == 0){
   		INFO_PRINT(" getlocaltimer  \n");
		kk_service_getLocalTimer_handle(deviceCode->valuestring);
   }   
   else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_SETCOUNTDOWN) == 0){
   		INFO_PRINT(" set count down  \n");
   		cJSON *paramStr = cJSON_GetObjectItem(payload, MSG_PARAMS_STR);
		kk_service_setCountDown_handle(paramStr,deviceCode->valuestring);
   }   
   else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_GETCOUNTDOWN) == 0){
   		INFO_PRINT(" get count down  \n");
		kk_service_getCountDown_handle(deviceCode->valuestring);
   }  
   else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_GETKEYLIST) == 0){
   		INFO_PRINT(" get key list  \n");
		kk_service_getLockKeylist_handle(deviceCode->valuestring);
   }  
   else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_ADDKEY) == 0){
   		INFO_PRINT(" add key  \n");
   		cJSON *paramStr = cJSON_GetObjectItem(payload, MSG_PARAMS_STR);	
		kk_service_addKey_handle(deviceCode->valuestring,paramStr);

   }   
   else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_MODIFYKEY) == 0){
   		INFO_PRINT(" modify key  \n");
   		cJSON *paramStr = cJSON_GetObjectItem(payload, MSG_PARAMS_STR);	
		kk_service_modifyKey_handle(deviceCode->valuestring,paramStr);

   }     
   else if(strcmp(typeJson->valuestring,KK_THING_SERVICE_DELETEKEY) == 0){
   		INFO_PRINT(" delete key  \n");
   		cJSON *paramStr = cJSON_GetObjectItem(payload, MSG_PARAMS_STR);	
		kk_service_deleteKey_handle(deviceCode->valuestring,paramStr);

   }    
#endif   
   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_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{
        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, 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 (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：成功；其他：失败
*其他说明：
*************************************************************/
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, msgid = 0, code = 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_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;

}


