#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "kk_dm_mng.h"
#include "kk_dm_msg.h"
#include "kk_dm_api.h"
#include "kk_tsl_api.h"
#include "kk_tsl_load.h"
#include "iot_export_linkkit.h"
#include "kk_product.h"
#include "kk_log.h"
#include "kk_property_db.h"
#include "kk_sub_db.h"
#include "kk_hal.h"
#include "kk_utils.h"
#include "kk_scene_handle.h"
#include "kk_area_handle.h"
#include "kk_sync_data.h"


//const char DM_URI_SYS_PREFIX[]                        DM_READ_ONLY = "/sys/%s/%s/";
const char DM_URI_EXT_SESSION_PREFIX[]                DM_READ_ONLY = "/ext/session/%s/%s/";
const char DM_URI_EXT_NTP_PREFIX[]                    DM_READ_ONLY = "/ext/ntp/%s/%s/";
const char DM_URI_EXT_ERROR_PREFIX[]                  DM_READ_ONLY = "/ext/error/%s/%s";
const char DM_URI_REPLY_SUFFIX[]                      DM_READ_ONLY = "_reply";
const char DM_URI_OTA_DEVICE_INFORM[]                 DM_READ_ONLY = "/ota/device/inform/%s/%s";
const char DM_URI_THING_EVENT_PROPERTY_POST_METHOD[]  DM_READ_ONLY = "thing.event.property.post";


static dm_mgr_ctx g_dm_mgr = {0};
static dm_mgr_ctx *_dm_mgr_get_ctx(void)
{
	return &g_dm_mgr;
}

static void _dm_mgr_mutex_lock(void)
{
    dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
    if (ctx->mutex) {
        kk_MutexLock(ctx->mutex);
    }
}

static void _dm_mgr_mutex_unlock(void)
{
    dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
    if (ctx->mutex) {
        kk_MutexUnLock(ctx->mutex);
    }
}

int dm_mgr_search_dev_by_devid(_IN_ int devid, _OU_ dm_mgr_dev_node_t **node)
{
	dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
	dm_mgr_dev_node_t *search_node = NULL;

	list_for_each_entry(search_node, &ctx->dev_list, linked_list, dm_mgr_dev_node_t) {
		if (search_node->devid == devid) {
			/* dm_log_debug("Device Found, devid: %d", devid); */
			if (node) {
				*node = search_node;
			}
			return SUCCESS_RETURN;
		}
	}

	ERROR_PRINT("Device Not Found, devid: %d", devid);
	return FAIL_RETURN;
}


void dm_mgr_resubscribe(void)
{
	dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
	dm_mgr_dev_node_t *search_node = NULL;

	list_for_each_entry(search_node, &ctx->dev_list, linked_list, dm_mgr_dev_node_t) {
		/* dm_log_debug("Device Found, devid: %d", devid); */
		if (search_node) {
			//printf("----------------------------------------->[%s][%d] \n",__FUNCTION__,__LINE__);
			iotx_dm_subscribe_node(search_node);
		}
	}
	return ;
}
static int _dm_mgr_search_dev_by_pkdn(_IN_ char deviceCode[DEVICE_CODE_MAXLEN], _OU_ dm_mgr_dev_node_t **node)
{
	dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
	dm_mgr_dev_node_t *search_node = NULL;

	list_for_each_entry(search_node, &ctx->dev_list, linked_list, dm_mgr_dev_node_t) {
		if ( (strlen(search_node->deviceCode) == strlen(deviceCode)) &&
			(memcmp(search_node->deviceCode, deviceCode, strlen(deviceCode)) == 0)) {
			/* dm_log_debug("Device Found, Product Key: %s, Device Name: %s", product_key, device_name); */
			if (node) {
				*node = search_node;
			}
			return SUCCESS_RETURN;
		}
	}

	ERROR_PRINT("Device Not Found, Device Code: %s\n", deviceCode);
	return FAIL_RETURN;
}
static int _dm_mgr_next_devid(void)
{
	dm_mgr_ctx *ctx = _dm_mgr_get_ctx();

	return ctx->global_devid++;
}
static int _dm_init_tsl_params(kk_tsl_t * dev_shadow,char *deviceCode)
{
	int res = 0;
	char version[VERSION_MAXLEN] = {0};
	//char s_IP[NETWORK_ADDR_LEN] = {0};
	char s_mac[MAC_ADDR_LEN] = {0};
	char s_SN[SN_ADDR_LEN] = {0};
	//int port = 0;

	/*******set version***********/
	HAL_GetVersion(version);
	res = kk_tsl_set_value(kk_tsl_set_property_value,dev_shadow,KK_TSL_VERSION_IDENTIFIER,NULL,version);
	if(res != SUCCESS_RETURN)
	{
		ERROR_PRINT("[%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
	}
	
	/*******set IP*************/
	//HAL_Get_IP(s_IP,NULL);
	res = kk_tsl_set_value(kk_tsl_set_property_value,dev_shadow,KK_TSL_CCU_LANIP_IDENTIFIER,NULL,"0.0.0.0");
	if(res != SUCCESS_RETURN)
	{
		ERROR_PRINT("[%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
	}
	res = kk_tsl_set_value(kk_tsl_set_property_value,dev_shadow,KK_TSL_CCU_WANIP_IDENTIFIER,NULL,"0.0.0.0");
	if(res != SUCCESS_RETURN)
	{
		ERROR_PRINT("[%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
	}	

	/*******set MAC*************/
	HAL_Get_mac(s_mac);
	res = kk_tsl_set_value(kk_tsl_set_property_value,dev_shadow,KK_TSL_GATAWAY_MAC_IDENTIFIER,NULL,s_mac);
	if(res != SUCCESS_RETURN)
	{
		ERROR_PRINT("[%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
	}	
	
	int wanState = 0;
	res = kk_tsl_set_value(kk_tsl_set_property_value,dev_shadow,KK_TSL_CCU_WANSTATE_IDENTIFIER,&wanState,NULL);
	if(res != SUCCESS_RETURN)
	{
		ERROR_PRINT("[%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
	}		

	int IOTCloudState = 0;
	res = kk_tsl_set_value(kk_tsl_set_property_value,dev_shadow,KK_TSL_CCU_IOTCLOUD_IDENTIFIER,&IOTCloudState,NULL);
	if(res != SUCCESS_RETURN)
	{
		ERROR_PRINT("[%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
	}	
	/*******set sn*************/
	HAL_Get_SN(s_SN);
	res = kk_tsl_set_value(kk_tsl_set_property_value,dev_shadow,KK_TSL_GATAWAY_SN_IDENTIFIER,NULL,s_SN);
	if(res != SUCCESS_RETURN)
	{
		ERROR_PRINT("[%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
	}	
	char currentValue[16] = {0};
	kk_property_db_get_value(deviceCode,KK_TSL_CCU_ARMINGSTATE_IDENTIFIER,currentValue);
	if(strlen(currentValue) == 0){
		res = kk_tsl_set_value(kk_tsl_set_property_value,dev_shadow,KK_TSL_CCU_ARMINGSTATE_IDENTIFIER,NULL,"1");//默认撤防设置
		if(res != SUCCESS_RETURN)
		{
			ERROR_PRINT("[%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
		}		
	}else{
		res = kk_tsl_set_value(kk_tsl_set_property_value,dev_shadow,KK_TSL_CCU_ARMINGSTATE_IDENTIFIER,NULL,currentValue);//默认撤防设置
		if(res != SUCCESS_RETURN)
		{
			ERROR_PRINT("[%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
		}
	}
	return res;
}

/*目前支持到三级结构体的属性解析保存到数据库*/
int dm_mgr_properities_db_create(kk_tsl_t* dev_shadow,char *deviceCode,int devType )
{
	int num = 0,idx = 0,index = 0,index1 = 0;
	kk_tsl_data_t *pProperty = NULL;
	kk_tsl_data_t *current_data = NULL;
	char tmp_identifiers[256] = {0};
	if(dev_shadow == NULL || deviceCode == NULL){
		ERROR_PRINT("dm_mgr_properities_db_create fail!!\n");
		return INVALID_PARAMETER;
	}
	num = dev_shadow->property_number;
	for(idx = 0; idx < num; idx++){
		pProperty = dev_shadow->properties+idx;
		//INFO_PRINT("dm_mgr_properities_db_create pProperty->identifier:%s!!\n",pProperty->identifier);	
		if(pProperty){
			if(pProperty->data_value.type == KK_TSL_DATA_TYPE_STRUCT){
				kk_tsl_data_value_complex_t *complex_struct = NULL;
				complex_struct = pProperty->data_value.value;
				for (index = 0; index < complex_struct->size; index++) {
					current_data = (kk_tsl_data_t *)complex_struct->value + index;
					if(current_data->data_value.type != KK_TSL_DATA_TYPE_STRUCT ){
						memset(tmp_identifiers,0x0,sizeof(tmp_identifiers));
						sprintf(tmp_identifiers,"%s.%s",pProperty->identifier,current_data->identifier);
						INFO_PRINT("dm_mgr_properities_db_create tmp_identifiers:%s!!\n",tmp_identifiers);
						kk_property_db_insert(deviceCode,tmp_identifiers,current_data->data_value.type,devType);
					}
					else{
						kk_tsl_data_value_complex_t *complex_struct_1 = NULL;
						complex_struct_1 = current_data->data_value.value;
						for(index1 = 0; index1 < complex_struct_1->size; index1++){
							kk_tsl_data_t *current_data_1 = NULL;
							current_data_1 = (kk_tsl_data_t *)complex_struct_1->value + index1;
							if(current_data_1->data_value.type != KK_TSL_DATA_TYPE_STRUCT ){
								memset(tmp_identifiers,0x0,sizeof(tmp_identifiers));
								sprintf(tmp_identifiers,"%s.%s.%s",pProperty->identifier,current_data->identifier,current_data_1->identifier);
								INFO_PRINT("dm_mgr_properities_db_create tmp_identifiers:%s!!\n",tmp_identifiers);
								kk_property_db_insert(deviceCode,tmp_identifiers,current_data_1->data_value.type,devType);

							}
						}

					}
				}			
			}
			else
			{
				kk_property_db_insert(deviceCode,pProperty->identifier,pProperty->data_value.type,devType);
			}
		}
	}
	return SUCCESS_RETURN;
}

int dm_mgr_device_create(_IN_ int dev_type,_IN_ char productCode[PRODUCT_CODE_MAXLEN], _IN_ char deviceCode[DEVICE_CODE_MAXLEN],
			_IN_ char mac[DEVICE_MAC_MAXLEN],_IN_ char fatherDeviceCode[DEVICE_CODE_MAXLEN],_IN_ int isOffline, _OU_ int *devid,_OU_ int *heartbeat)
{
	int res = 0;
	dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
	dm_mgr_dev_node_t *node = NULL;
	char *tsl_str = NULL;
	//int idx = 0;
	
	if (deviceCode != NULL && strlen(deviceCode) >= DEVICE_CODE_MAXLEN) {
		return INVALID_PARAMETER;
	}

	res = _dm_mgr_search_dev_by_pkdn(deviceCode, &node);
	if (res == SUCCESS_RETURN) {
		if (devid) {
			*devid = node->devid;
		}
		return TSL_ALREADY_EXIST;
	}

	node = malloc(sizeof(dm_mgr_dev_node_t));
	if (node == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(node, 0, sizeof(dm_mgr_dev_node_t));

	if(dev_type == KK_DM_DEVICE_CCU)
		node->devid = KK_DM_DEVICE_CCU_DEVICEID;
	else
		node->devid = _dm_mgr_next_devid();
	node->dev_type = dev_type;
	node->dev_shadow = NULL;
	node->isOffline = isOffline;
	if (productCode != NULL) {
		memcpy(node->productCode, productCode, strlen(productCode));
	}
	if (deviceCode != NULL) {
		memcpy(node->deviceCode, deviceCode, strlen(deviceCode));
	}
	if (mac != NULL) {
		memcpy(node->mac, mac, strlen(mac));
	}
	if (dev_type != KK_DM_DEVICE_CCU && fatherDeviceCode != NULL) {
		memcpy(node->fatherDeviceCode, fatherDeviceCode, strlen(fatherDeviceCode));
	}
	node->timestamp = HAL_Uptimes();
	//node->dev_status = IOTX_DM_DEV_STATUS_AUTHORIZED;
	//if(strcmp(productCode,"1035") == 0){
		//tsl_str = kk_load_json("130", dev_type);

	//}else{
		//tsl_str = kk_load_json(productCode, dev_type);
	//}
		
	tsl_str = kk_load_json(productCode, dev_type);
	if(tsl_str != NULL)
	{
		int heartbeat = 0;
		kk_msg_parse_productType(tsl_str,node->productType);
		res = kk_tsl_create(tsl_str,strlen(tsl_str),&node->dev_shadow,&heartbeat,&node->dormancyDev);
		free(tsl_str);
		if(res != 0){
			return FAIL_RETURN;
		}
		node->hb_timeout = heartbeat;
	}
	else{
		return FAIL_RETURN;
	}
	INIT_LIST_HEAD(&node->linked_list);
	list_add_tail(&node->linked_list, &ctx->dev_list);
	dm_mgr_properities_db_create(node->dev_shadow,deviceCode,dev_type);

	
	if(dev_type == KK_DM_DEVICE_CCU){
		_dm_init_tsl_params(node->dev_shadow,node->deviceCode);
	}

	if (devid) {
		*devid = node->devid;
	}
	if (heartbeat){
		*heartbeat = node->hb_timeout;
	}

	return SUCCESS_RETURN;
}
int dm_mgr_search_device_by_pkdn( _IN_ char deviceCode[DEVICE_CODE_MAXLEN],_OU_ int *devid)
{
    int res = 0;
    dm_mgr_dev_node_t *node = NULL;

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

    res = _dm_mgr_search_dev_by_pkdn(deviceCode, &node);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }

    if (devid) {
        *devid = node->devid;
    }

    return SUCCESS_RETURN;
}



int dm_mgr_get_devicetype_by_devicecode(_IN_ char deviceCode[DEVICE_CODE_MAXLEN], _OU_ int* deviceType)
{
	dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
	dm_mgr_dev_node_t *node = NULL;

	list_for_each_entry(node, &ctx->dev_list, linked_list, dm_mgr_dev_node_t) {
		if ((strlen(node->deviceCode) == strlen(deviceCode)) &&
			(memcmp(node->deviceCode, deviceCode, strlen(deviceCode)) == 0)) {
			/* dm_log_debug("Device Found, Product Key: %s, Device Name: %s", product_key, device_name); */
			if (node) {
				*deviceType = node->dev_type;
			}
			return SUCCESS_RETURN;
		}
	}

	ERROR_PRINT("Device Not Found, deviceCode: %s\n", deviceCode);
	return FAIL_RETURN;
}
int dm_mgr_get_device_shadow_by_devicecode(_IN_ char deviceCode[DEVICE_CODE_MAXLEN], _OU_ kk_tsl_t **shadow)
{
    dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
    dm_mgr_dev_node_t *search_node = NULL;

    list_for_each_entry(search_node, &ctx->dev_list, linked_list, dm_mgr_dev_node_t) {
        if ((strlen(search_node->deviceCode) == strlen(deviceCode)) &&
            (memcmp(search_node->deviceCode, deviceCode, strlen(deviceCode)) == 0)) {
            /* dm_log_debug("Device Found, Product Key: %s, Device Name: %s", product_key, device_name); */
            if (shadow) {
                *shadow = search_node->dev_shadow;
            }
            return SUCCESS_RETURN;
        }
    }

    ERROR_PRINT("Device Not Found, deviceCode: %s\n", deviceCode);
    return FAIL_RETURN;
}


int dm_mgr_get_device_by_devicecode(_IN_ char deviceCode[DEVICE_CODE_MAXLEN], _OU_ dm_mgr_dev_node_t **node)
{
	dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
	dm_mgr_dev_node_t *search_node = NULL;

	list_for_each_entry(search_node, &ctx->dev_list, linked_list, dm_mgr_dev_node_t) {
		if ((strlen(search_node->deviceCode) == strlen(deviceCode)) &&
			(memcmp(search_node->deviceCode, deviceCode, strlen(deviceCode)) == 0)) {
			/* dm_log_debug("Device Found, Product Key: %s, Device Name: %s", product_key, device_name); */
			if (node) {
				*node = search_node;
			}
			return SUCCESS_RETURN;
		}
	}

	ERROR_PRINT("Device Not Found, deviceCode: %s\n", deviceCode);
	return FAIL_RETURN;
}

int dm_mgr_get_deviceNum_by_productType(_IN_ char *productType)
{
	dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
	dm_mgr_dev_node_t *search_node = NULL;
	int num = 0;
	list_for_each_entry(search_node, &ctx->dev_list, linked_list, dm_mgr_dev_node_t) {
		if ((strlen(search_node->productType) == strlen(productType)) &&
			(memcmp(search_node->productType, productType, strlen(productType)) == 0)) {
			/* dm_log_debug("Device Found, Product Key: %s, Device Name: %s", product_key, device_name); */
			num++;
		}
	}
	return num;
}
static int dm_mgr_update_gw_timestamp_by_devicecode(_IN_ char deviceCode[DEVICE_CODE_MAXLEN],time_t timestamp)
{
	dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
	dm_mgr_dev_node_t *search_node = NULL;

	//_dm_mgr_mutex_lock();
	list_for_each_entry(search_node, &ctx->dev_list, linked_list, dm_mgr_dev_node_t) {
		if ((strlen(search_node->deviceCode) == strlen(deviceCode)) &&
			(memcmp(search_node->deviceCode, deviceCode, strlen(deviceCode)) == 0)) {
			/* dm_log_debug("Device Found, Product Key: %s, Device Name: %s", product_key, device_name); */
			search_node->timestamp = timestamp;
			//_dm_mgr_mutex_unlock();
			return SUCCESS_RETURN;
		}
	}
	//_dm_mgr_mutex_unlock();
	ERROR_PRINT("Device Not Found, deviceCode: %s\n", deviceCode);
	return FAIL_RETURN;
}
int dm_mgr_update_timestamp_by_devicecode(_IN_ char deviceCode[DEVICE_CODE_MAXLEN],time_t timestamp)
{
	dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
	dm_mgr_dev_node_t *search_node = NULL;

	_dm_mgr_mutex_lock();
	list_for_each_entry(search_node, &ctx->dev_list, linked_list, dm_mgr_dev_node_t) {
		if ((strlen(search_node->deviceCode) == strlen(deviceCode)) &&
			(memcmp(search_node->deviceCode, deviceCode, strlen(deviceCode)) == 0)) {
			/* dm_log_debug("Device Found, Product Key: %s, Device Name: %s", product_key, device_name); */
			search_node->timestamp = timestamp;
			if(search_node->dev_type == KK_DM_DEVICE_SUBDEV){
				dm_mgr_update_gw_timestamp_by_devicecode(search_node->fatherDeviceCode,timestamp);
			}
			_dm_mgr_mutex_unlock();
			return SUCCESS_RETURN;
		}
	}
	_dm_mgr_mutex_unlock();
	ERROR_PRINT("Device Not Found, deviceCode: %s\n", deviceCode);
	return FAIL_RETURN;
}

int dm_mgr_set_dev_onoffline(dm_mgr_dev_node_t *node,int isOffline)
{
	if(node == NULL){
		return INVALID_PARAMETER;
	}

	if(isOffline){
		INFO_PRINT("[%s]dev timeout,send offline\n",__FUNCTION__);
		node->isOffline = KK_DEV_OFFLINE;
		iotx_dm_dev_offline(node->devid);
		kk_subDev_update_offline(node->isOffline,node->deviceCode);
	}
	else{
		INFO_PRINT("[%s]dev online,send online\n",__FUNCTION__);
		node->isOffline = KK_DEV_ONLINE;
		iotx_dm_dev_online(node->devid);
		if(node->dev_type == KK_DM_DEVICE_CCU){
			/*先上报主机属性*/
			dm_msg_ccu_property_post(node);
			/*再报对应网关和子设备的属性,主机上线后子设备属性直接从数据库获取并上报*/
			kk_subDev_send_property_get_from_db();

		}
		else{
			kk_subDev_update_offline(node->isOffline,node->deviceCode);
			/*如果网关在线，下发对应子设备的属性获取*/
			if(node->dev_type == KK_DM_DEVICE_GATEWAY){
				kk_subDev_send_property_get(node->deviceCode);
			}
		}
	}
	return SUCCESS_RETURN;
}

int dm_mgr_check_heartbeat_timeout(time_t timestamp)
{
	dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
	dm_mgr_dev_node_t *search_node = NULL;
	_dm_mgr_mutex_lock();
	list_for_each_entry(search_node, &ctx->dev_list, linked_list, dm_mgr_dev_node_t) {
		if(search_node->hb_timeout == 0){
			search_node->hb_timeout = DEFAULT_HEARTBEAT_TIMEOUT;
		}
		if(search_node->devid == KK_DM_DEVICE_CCU_DEVICEID){
			continue;
		}
		#if 0
		printf("[%s][%d]search_node->productCode:%s\n",__FUNCTION__,__LINE__,search_node->productCode);
		printf("[%s][%d]search_node->hb_timeout:%d\n",__FUNCTION__,__LINE__,search_node->hb_timeout);
		printf("[%s][%d]search_node->isOffline:%d\n",__FUNCTION__,__LINE__,search_node->isOffline);
		printf("[%s][%d]search_node->timestamp:%d\n",__FUNCTION__,__LINE__,search_node->timestamp);
		printf("[%s][%d]timestamp:%d\n",__FUNCTION__,__LINE__,timestamp);
		#endif
		if((timestamp - search_node->timestamp) >= search_node->hb_timeout){
			if(search_node->isOffline != KK_DEV_OFFLINE){
				dm_mgr_set_dev_onoffline(search_node,1);
			}
		}
		else{
			if(search_node->isOffline == KK_DEV_OFFLINE){
				/*如果是离线状态，上报在线给云端*/
				dm_mgr_set_dev_onoffline(search_node,0);
			}
		}
	}
	_dm_mgr_mutex_unlock();
	return SUCCESS_RETURN;
}

int dm_mgr_get_devId_by_devicecode(_IN_ char deviceCode[DEVICE_CODE_MAXLEN],_OU_ int *devid)
{
    int res = 0;
    dm_mgr_dev_node_t *node = NULL;

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

    res = dm_mgr_get_device_by_devicecode(deviceCode, &node);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }

    if (devid) {
        *devid = node->devid;
    }

    return SUCCESS_RETURN;
}

int dm_mgr_get_gw_deviceCode(_OU_ dm_mgr_dev_node_t **node)
{
	dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
	dm_mgr_dev_node_t *search_node = NULL;

	list_for_each_entry(search_node, &ctx->dev_list, linked_list, dm_mgr_dev_node_t) {
		if (memcmp(search_node->productCode, "gateway_2", strlen("gateway_2")) == 0) {
			/* dm_log_debug("Device Found, Product Key: %s, Device Name: %s", product_key, device_name); */
			if (node) {
				*node = search_node;
			}
			return SUCCESS_RETURN;
		}
	}

	ERROR_PRINT("gw Not Found\n");
	return FAIL_RETURN;
}
static void _dm_mgr_destroy_devlist(void)
{
	dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
	dm_mgr_dev_node_t *del_node = NULL;
	dm_mgr_dev_node_t *next_node = NULL;

	list_for_each_entry_safe(del_node, next_node, &ctx->dev_list, linked_list, dm_mgr_dev_node_t) {
		list_del(&del_node->linked_list);

		//dm_shw_destroy(&del_node->dev_shadow);

		free(del_node);
	}
}
extern char *kk_sync_get_info();
int dm_mgr_init(void)
{
	int res = 0;
	dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
	char mac[DEVICE_MAC_MAXLEN]= {0};
	char ccuid[32] = {0};
		
	int devId = 0,heartbeat = 0;
	memset(ctx, 0, sizeof(dm_mgr_ctx));
	
	/* Create Mutex */
	ctx->mutex = kk_MutexCreate();
	if (ctx->mutex == NULL) {
		goto ERROR;
	}
	/* Init Device Id*/
	ctx->global_devid = 1;
	kk_property_db_init();
	HAL_Get_ccuid(ccuid);	
	/* Init Device List */
	INIT_LIST_HEAD(&ctx->dev_list);
	HAL_Get_mac(mac);
	kk_sync_init();
	//kk_sync_get_info();
	res = dm_mgr_device_create(KK_DM_DEVICE_CCU,KK_DM_CCU_DEVICE_PRODUCT_CODE,ccuid,mac,"",KK_DEV_UNKNOW,&devId,&heartbeat);
	if (res != SUCCESS_RETURN) {
		goto ERROR;
	}
	else{

		kk_property_db_update(ccuid);
		
	}

	return SUCCESS_RETURN;

ERROR:
	return FAIL_RETURN;
}

int dm_mgr_deinit(void)
{
	dm_mgr_ctx *ctx = _dm_mgr_get_ctx();

	_dm_mgr_mutex_lock();
	_dm_mgr_destroy_devlist();
	_dm_mgr_mutex_unlock();

	if (ctx->mutex) {
		HAL_MutexDestroy(ctx->mutex);
	}

	return SUCCESS_RETURN;
}

const char DM_URI_THING_EVENT_POST[] = "/thing/event/%s/post";
const char DM_MSG_THING_UPSTREAM_REQUEST_PARAMS[] DM_READ_ONLY = "%s";
static int _dm_mgr_upstream_request_assemble(_IN_ char *msgid, _IN_ int devid,
		_IN_ char *identify,
		_IN_ char *params, _IN_ int params_len, _IN_ char *method, _OU_ dm_msg_request_t *request)
{
	int res = 0;
	dm_mgr_dev_node_t *node = NULL;
	int paramLen = 0;
	int msgTypeLen = 0;
	char *payload_param = NULL;
	res = dm_mgr_search_dev_by_devid(devid, &node);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}

	/* dm_log_debug("Time Stamp: %s", timestamp); */
	paramLen = strlen(DM_MSG_THING_UPSTREAM_REQUEST_PARAMS) +
				params_len + 1;
	payload_param = malloc(paramLen);
	if (payload_param == NULL) {
		return MEMORY_NOT_ENOUGH;
	}

	memset(payload_param, 0, paramLen);
	HAL_Snprintf(payload_param, paramLen, DM_MSG_THING_UPSTREAM_REQUEST_PARAMS, params);


	memcpy(request->msgid,msgid,strlen(msgid));

	request->devid = devid;
	msgTypeLen = strlen(DM_URI_THING_EVENT_POST) + strlen(identify) + 1;
	request->msgTypeStr = malloc(msgTypeLen);
	if(request->msgTypeStr == NULL){
		return MEMORY_NOT_ENOUGH;
	}
	memset(request->msgTypeStr,0x0,msgTypeLen);
	snprintf(request->msgTypeStr,msgTypeLen,DM_URI_THING_EVENT_POST,identify);
	memcpy(request->productCode, node->productCode, strlen(node->productCode));	
	memcpy(request->deviceCode, node->deviceCode, strlen(node->deviceCode));
	request->params = payload_param;
	request->params_len = paramLen;
	request->method = method;

	return SUCCESS_RETURN;
}

const char DM_URI_THING_SERVICE_POST[] = "/thing/service/%s_reply";
const char DM_MSG_THING_UPSTREAM_SERVICE_PARAMS[] DM_READ_ONLY = "%s";
static int _dm_mgr_upstream_service_assemble(_IN_ char* msgid, _IN_ int devid,
		_IN_ char *identify,
		_IN_ char *params, _IN_ int params_len, _IN_ char *method, _OU_ dm_msg_request_t *request)
{
	int res = 0;
	dm_mgr_dev_node_t *node = NULL;
	int paramLen = 0;
	int msgTypeLen = 0;
	char *payload_param = NULL;
	res = dm_mgr_search_dev_by_devid(devid, &node);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}

	/* dm_log_debug("Time Stamp: %s", timestamp); */
	paramLen = strlen(DM_MSG_THING_UPSTREAM_SERVICE_PARAMS) +
					params_len + 1;
	payload_param = malloc(paramLen);
	if (payload_param == NULL) {
	  return MEMORY_NOT_ENOUGH;
	}

	memset(payload_param, 0, paramLen);
	HAL_Snprintf(payload_param, paramLen, DM_MSG_THING_UPSTREAM_REQUEST_PARAMS, params);

	memcpy(request->msgid ,msgid,strlen(msgid));
	request->devid = devid;
	msgTypeLen = strlen(DM_URI_THING_SERVICE_POST) + strlen(identify) + 1;
	request->msgTypeStr = malloc(msgTypeLen);
	if(request->msgTypeStr == NULL){
		return MEMORY_NOT_ENOUGH;
	}
	memset(request->msgTypeStr,0x0,msgTypeLen);
	snprintf(request->msgTypeStr,msgTypeLen,DM_URI_THING_SERVICE_POST,identify);
	memcpy(request->productCode, node->productCode, strlen(node->productCode)); 
	memcpy(request->deviceCode, node->deviceCode, strlen(node->deviceCode));
	request->params = payload_param;
	request->params_len = paramLen;
	request->method = method;

	return SUCCESS_RETURN;
}

static unsigned int g_report_id = 1;

int iotx_report_id(char *msgId)
{
	if(msgId == NULL){
		return INVALID_PARAMETER;
	}
	//char timerStr[16] = {0};
	//HAL_GetTime_ms();
	sprintf(msgId,"6c0645c4-f6d6-b11e-%lld",HAL_GetTime_ms());
	return SUCCESS_RETURN;
}

int dm_mgr_upstream_thing_property_post(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len,_IN_ int isAsync)
{
	int res = 0;
	dm_msg_request_t request;
	char msgId[MSG_MAX_LEN] = {0};

	if (devid < 0 || payload == NULL || payload_len <= 0) {
		return INVALID_PARAMETER;
	}

	memset(&request, 0, sizeof(dm_msg_request_t));
	iotx_report_id(msgId);
	//sprintf(msgId,"%d",iotx_report_id());
	res = _dm_mgr_upstream_request_assemble(msgId, devid, "property",
											payload, payload_len, (char*)DM_URI_THING_EVENT_PROPERTY_POST_METHOD, &request);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}

	/* Callback */
	//request.callback = dm_client_thing_event_post_reply;

	/* Send Message To Cloud */
	res = dm_msg_request(&request,isAsync);
	free(request.msgTypeStr);	
	free(request.params);
	return res;
}
int dm_mgr_upstream_thing_event_post(_IN_ int devid, _IN_ char *identifier, _IN_ int identifier_len, _IN_ char *method,
                                     _IN_ char *payload, _IN_ int payload_len)
{
    int res = 0;
	char msgId[MSG_MAX_LEN] = {0};

    dm_msg_request_t request;

    if (devid < 0 || identifier == NULL || identifier_len <= 0 ||
        method == NULL || payload == NULL || payload_len <= 0) {
        return INVALID_PARAMETER;
    }
    memset(&request, 0, sizeof(dm_msg_request_t));
	iotx_report_id(msgId);
	//sprintf(msgId,"%d",iotx_report_id());
    res = _dm_mgr_upstream_request_assemble(msgId, devid,identifier,
                                            payload, payload_len, method, &request);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }

    /* Callback */
    //request.callback = dm_client_thing_event_post_reply;

    /* Send Message To Cloud */
    res = dm_msg_request(&request,0);
	free(request.msgTypeStr);
	free(request.params);
    return res;
}

int dm_mgr_upstream_thing_event_post_ex(_IN_ int devid, _IN_ char *identifier, _IN_ int identifier_len, _IN_ char *method,
								  _IN_ char *payload, _IN_ int payload_len,const char *msgId)
{
 	int res = 0;

 	dm_msg_request_t request;

 	if (devid < 0 || identifier == NULL || identifier_len <= 0 ||
		 method == NULL || payload == NULL || payload_len <= 0) {
	 	return INVALID_PARAMETER;
 	}
 	memset(&request, 0, sizeof(dm_msg_request_t));

 	res = _dm_mgr_upstream_request_assemble((char*)msgId, devid,identifier,
										 payload, payload_len, method, &request);
 	if (res != SUCCESS_RETURN) {
	 	return FAIL_RETURN;
 	}

 /* Callback */
 //request.callback = dm_client_thing_event_post_reply;

 /* Send Message To Cloud */
 	res = dm_msg_request(&request,0);
 	free(request.msgTypeStr);
 	free(request.params);
	return res;
}

int dm_mgr_upstream_thing_service_post(_IN_ int devid, _IN_ char *identifier, _IN_ int identifier_len, _IN_ char *method,
                                     _IN_ char *payload, _IN_ int payload_len)
{
    int res = 0;

    dm_msg_request_t request;
	char msgId[MSG_MAX_LEN] = {0};
    if (devid < 0 || identifier == NULL || identifier_len <= 0 ||
        method == NULL || payload == NULL || payload_len <= 0) {
        return INVALID_PARAMETER;
    }
    memset(&request, 0, sizeof(dm_msg_request_t));
	iotx_report_id(msgId);
	//sprintf(msgId,"%d",iotx_report_id());

    res = _dm_mgr_upstream_service_assemble(msgId, devid,identifier,
                                            payload, payload_len, method, &request);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }

    /* Callback */
    //request.callback = dm_client_thing_event_post_reply;

    /* Send Message To Cloud */
    res = dm_msg_request(&request,0);
	free(request.msgTypeStr);
	free(request.params);
    return res;
}

const char DM_URI_THING_SERVICE_RESPONSE[] = "/thing/service/%.*s_reply";
static int _kk_mgr_upstream_response_assemble(_IN_ int devid, _IN_ char *msgid, _IN_ int msgid_len,
        _IN_ const char *identfy, _IN_ int code, _OU_ kk_msg_request_payload_t *request, _OU_ kk_msg_response_t *response)
{
    int res = 0;
	int msgTypeLen = 0;
    dm_mgr_dev_node_t *node = NULL;

    res = dm_mgr_search_dev_by_devid(devid, &node);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }

    request->id.value = msgid;
    request->id.value_length = msgid_len;

	msgTypeLen = strlen(DM_URI_THING_SERVICE_RESPONSE) + strlen(identfy) + 1;

    response->msgTypeStr = malloc(msgTypeLen);
	if(response->msgTypeStr == NULL){
		return MEMORY_NOT_ENOUGH;
	}
	memset(response->msgTypeStr,0x0,msgTypeLen);
	snprintf(response->msgTypeStr,msgTypeLen,DM_URI_THING_SERVICE_RESPONSE,identfy);
    memcpy(response->productCode, node->productCode, strlen(node->productCode));	
    memcpy(response->deviceCode, node->deviceCode, strlen(node->deviceCode));
    response->code = code;

    return SUCCESS_RETURN;
}

int dm_mgr_deprecated_upstream_thing_service_response(_IN_ int devid, _IN_ int msgid, _IN_ iotx_dm_error_code_t code,
        _IN_ char *identifier, _IN_ int identifier_len, _IN_ char *payload, _IN_ int payload_len)
{
    int res = 0;
    char *msgid_str = NULL;
    kk_msg_request_payload_t request;
    kk_msg_response_t response;

    memset(&request, 0, sizeof(kk_msg_request_payload_t));
    memset(&response, 0, sizeof(kk_msg_response_t));

    if (devid < 0 || msgid < 0 || identifier == NULL || identifier_len <= 0 ||
        payload == NULL || payload_len <= 0) {
        return INVALID_PARAMETER;
    }

    /* Response Msg ID */
    res = kk_utils_itoa(msgid, &msgid_str);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }
    request.id.value = msgid_str;
    request.id.value_length = strlen(msgid_str);

    /* Service Name */

    res = _kk_mgr_upstream_response_assemble(devid, msgid_str, strlen(msgid_str), identifier, code,
            &request,
            &response);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }


    dm_msg_response(&request, &response, payload, payload_len, NULL);
	free(response.msgTypeStr);
    free(msgid_str);
    return SUCCESS_RETURN;
}

const char DM_URI_THING_SUB_REGISTER[] = "/thing/sub/register";
int dm_mgr_upstream_thing_sub_register(_IN_ int devid)
{
	int res = 0;
	dm_mgr_dev_node_t *node = NULL;
	dm_mgr_dev_node_t *gw_node = NULL;	
	dm_msg_request_t request;
	char msgId[MSG_MAX_LEN] = {0};
	if (devid < 0) {
		return INVALID_PARAMETER;
	}

	res = dm_mgr_search_dev_by_devid(devid, &node);
	if (res != SUCCESS_RETURN) {
		ERROR_PRINT("ERROR [%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
		return FAIL_RETURN;
	}
	if(devid != KK_DM_DEVICE_CCU_DEVICEID){
		res = dm_mgr_get_device_by_devicecode(node->fatherDeviceCode,&gw_node);
		if (res != SUCCESS_RETURN) {
			ERROR_PRINT("ERROR [%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
			return FAIL_RETURN;
		}
	}
	memset(&request, 0, sizeof(dm_msg_request_t));
	request.msgTypeStr = (char*)DM_URI_THING_SUB_REGISTER;
	if(devid == KK_DM_DEVICE_CCU_DEVICEID){
		memcpy(request.productCode,node->productCode,strlen(node->productCode));	
		memcpy(request.deviceCode,node->deviceCode,strlen(node->deviceCode));		
	}else{
		memcpy(request.productCode,gw_node->productCode,strlen(gw_node->productCode));	
		memcpy(request.deviceCode,gw_node->deviceCode,strlen(gw_node->deviceCode));
	}
	/* Get Params And Method */
	res = dm_msg_thing_sub_register( node->productCode,node->deviceCode, &request);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}

	/* Get Msg ID */
	iotx_report_id(msgId);
	//sprintf(msgId,"%d",iotx_report_id());

	memcpy(request.msgid,msgId,strlen(msgId));

	/* Get Dev ID */
	request.devid = devid;

	/* Callback */
	//request.callback = dm_client_thing_sub_register_reply;

	/* Send Message To Cloud */
	res = dm_msg_request(&request,0);

	free(request.params);

	return res;
}

const char DM_URI_THING_SUB_UNREGISTER[] = "/thing/sub/unregister";
int dm_mgr_upstream_thing_sub_unregister(_IN_ int devid)
{
	int res = 0;
	dm_mgr_dev_node_t *node = NULL;
	dm_mgr_dev_node_t *gw_node = NULL;	
	dm_msg_request_t request;
	char msgId[MSG_MAX_LEN] = {0};

	if (devid < 0) {
		return INVALID_PARAMETER;
	}

	res = dm_mgr_search_dev_by_devid(devid, &node);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}
	res = dm_mgr_get_device_by_devicecode(node->fatherDeviceCode,&gw_node);
	if (res != SUCCESS_RETURN) {
		ERROR_PRINT("ERROR [%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
		return FAIL_RETURN;
	}

	memset(&request, 0, sizeof(dm_msg_request_t));
	request.msgTypeStr = (char*)DM_URI_THING_SUB_UNREGISTER;
	if(devid == KK_DM_DEVICE_CCU_DEVICEID){
		memcpy(request.productCode,node->productCode,strlen(node->productCode));	
		memcpy(request.deviceCode,node->deviceCode,strlen(node->deviceCode));		
	}else{
		memcpy(request.productCode,gw_node->productCode,strlen(gw_node->productCode));	
		memcpy(request.deviceCode,gw_node->deviceCode,strlen(gw_node->deviceCode));
	}

	/* Get Params And Method */
	res = dm_msg_thing_sub_unregister(node->deviceCode, &request);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}

	/* Get Msg ID */
	iotx_report_id(msgId);
	//sprintf(msgId,"%d",iotx_report_id());

	memcpy(request.msgid,msgId,strlen(msgId));


	/* Get Dev ID */
	request.devid = devid;

	/* Callback */
	//request.callback = dm_client_thing_sub_unregister_reply;


	/* Send Message To Cloud */
	res = dm_msg_request(&request,0);

	free(request.params);

	return res;
}

const char DM_URI_THING_TOPO_ADD[] = "/thing/topo/add";
int dm_mgr_upstream_thing_topo_add(_IN_ int devid)
{
    int res = 0;
    dm_mgr_dev_node_t *node = NULL;
	dm_mgr_dev_node_t *gw_node = NULL;		
    dm_msg_request_t request;
	char msgId[MSG_MAX_LEN] = {0};

    if (devid < 0) {
        return INVALID_PARAMETER;
    }

    res = dm_mgr_search_dev_by_devid(devid, &node);
    
    if (res != SUCCESS_RETURN) {
        ERROR_PRINT("ERROR res:%d\n",res);
        return FAIL_RETURN;
    }
	res = dm_mgr_get_device_by_devicecode(node->fatherDeviceCode,&gw_node);
	
    if (res != SUCCESS_RETURN) {
		ERROR_PRINT("ERROR [%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
        return FAIL_RETURN;
    }

    memset(&request, 0, sizeof(dm_msg_request_t));
    request.msgTypeStr = (char*)DM_URI_THING_TOPO_ADD;
	memcpy(request.productCode,gw_node->productCode,strlen(gw_node->productCode));	
	memcpy(request.deviceCode,gw_node->deviceCode,strlen(gw_node->deviceCode));
    

    /* Get Params And Method */
    res = dm_msg_thing_topo_add( node->productCode, node->deviceCode, node->mac,&request);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }

    /* Get Msg ID */
	iotx_report_id(msgId);
	//sprintf(msgId,"%d",iotx_report_id());

    memcpy(request.msgid,msgId,strlen(msgId));


    /* Get Dev ID */
    request.devid = devid;

    /* Callback */
    //request.callback = dm_client_thing_topo_add_reply;


    /* Send Message To Cloud */
    res = dm_msg_request(&request,0);

    free(request.params);

    return res;
}

const char DM_URI_THING_TOPO_DELETE[] = "/thing/topo/delete";
int dm_mgr_upstream_thing_topo_delete(_IN_ int devid)
{
    int res = 0;
    dm_mgr_dev_node_t *node = NULL;
	dm_mgr_dev_node_t *gw_node = NULL;	
    dm_msg_request_t request;
	char msgId[MSG_MAX_LEN] = {0};

    if (devid < 0) {
        return DM_INVALID_PARAMETER;
    }

    res = dm_mgr_search_dev_by_devid(devid, &node);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }
	
	res = dm_mgr_get_device_by_devicecode(node->fatherDeviceCode,&gw_node);
    if (res != SUCCESS_RETURN) {
		ERROR_PRINT("ERROR [%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
        return FAIL_RETURN;
    }

    memset(&request, 0, sizeof(dm_msg_request_t));
    request.msgTypeStr = (char*)DM_URI_THING_TOPO_DELETE;
	memcpy(request.productCode,gw_node->productCode,strlen(gw_node->productCode));	
	memcpy(request.deviceCode,gw_node->deviceCode,strlen(gw_node->deviceCode));



    /* Get Params And Method */
    res = dm_msg_thing_topo_delete( node->deviceCode, &request);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }

    /* Get Msg ID */
	iotx_report_id(msgId);
	//sprintf(msgId,"%d",iotx_report_id());

    memcpy(request.msgid,msgId,strlen(msgId));


    /* Get Dev ID */
    request.devid = devid;

    /* Callback */
    //request.callback = dm_client_thing_topo_delete_reply;


    /* Send Message To Cloud */
    res = dm_msg_request(&request,0);

    free(request.params);

    return res;
}

const char DM_URI_THING_TOPO_GET[] = "/thing/topo/get";
int dm_mgr_upstream_thing_topo_get(void)
{
    int res = 0;
    dm_mgr_dev_node_t *node = NULL;
	char msgId[MSG_MAX_LEN] = {0};
    dm_msg_request_t request;

    memset(&request, 0, sizeof(dm_msg_request_t));
    request.msgTypeStr = (char*)DM_URI_THING_TOPO_GET;
    HAL_Get_ccuid(request.deviceCode);


    res = _dm_mgr_search_dev_by_pkdn(request.deviceCode, &node);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }

    /* Get Params And Method */
    res = dm_msg_thing_topo_get(&request);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }

    /* Get Msg ID */
	iotx_report_id(msgId);
	//sprintf(msgId,"%d",iotx_report_id());

    memcpy(request.msgid,msgId,strlen(msgId));


    /* Get Dev ID */
    request.devid = node->devid;

    /* Callback */
    //request.callback = dm_client_thing_topo_get_reply;

    /* Send Message To Cloud */
    res = dm_msg_request(&request,0);

    free(request.params);

    return res;
}
const char DM_URI_THING_LIST_FOUND[] = "/thing/list/found";

int dm_mgr_upstream_thing_list_found(_IN_ int devid)
{
    int res = 0;
    dm_mgr_dev_node_t *node = NULL;
	dm_mgr_dev_node_t *gw_node = NULL;		
    dm_msg_request_t request;
	char msgId[MSG_MAX_LEN] = {0};

    if (devid < 0) {
        return INVALID_PARAMETER;
    }

    res = dm_mgr_search_dev_by_devid(devid, &node);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }
	res = dm_mgr_get_device_by_devicecode(node->fatherDeviceCode,&gw_node);
    if (res != SUCCESS_RETURN) {
		ERROR_PRINT("ERROR [%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
        return FAIL_RETURN;
    }

    memset(&request, 0, sizeof(dm_msg_request_t));
    request.msgTypeStr = (char*)DM_URI_THING_LIST_FOUND;
	memcpy(request.productCode,gw_node->productCode,strlen(gw_node->productCode));	
	memcpy(request.deviceCode,gw_node->deviceCode,strlen(gw_node->deviceCode));


    /* Get Params And Method */
    res = dm_msg_thing_list_found( node->deviceCode, &request);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }

    /* Get Msg ID */
	iotx_report_id(msgId);
	//sprintf(msgId,"%d",iotx_report_id());
    memcpy(request.msgid,msgId,strlen(msgId));


    /* Get Dev ID */
    request.devid = devid;

    /* Callback */
    //request.callback = dm_client_thing_list_found_reply;

    /* Send Message To Cloud */
    res = dm_msg_request(&request,0);

    free(request.params);

    return res;
}

const char DM_URI_STATUS_CLOUD[] = "/thing/ccu/cloudstate";
int dm_mgr_ccu_status_cloud(_IN_ int devid)
{
	int res = 0;
	dm_mgr_dev_node_t *node = NULL;
	//dm_mgr_dev_node_t *gw_node = NULL;		
	dm_msg_request_t request;
	char msgId[MSG_MAX_LEN] = {0};

	if (devid < 0) {
		return INVALID_PARAMETER;
	}
	memset(&request, 0, sizeof(dm_msg_request_t));

	res = dm_mgr_search_dev_by_devid(devid, &node);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}
	
	memcpy(request.productCode,node->productCode,strlen(node->productCode));	
	memcpy(request.deviceCode,node->deviceCode,strlen(node->deviceCode));
	
	request.msgTypeStr = (char*)DM_URI_STATUS_CLOUD;


	/* Get Params And Method */
	res = dm_msg_status_cloud( node->productCode, node->deviceCode, &request);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}

	/* Get Msg ID */
	iotx_report_id(msgId);
	//sprintf(msgId,"%d",iotx_report_id());
	memcpy(request.msgid,msgId,strlen(msgId));


	/* Get Dev ID */
	request.devid = devid;

	/* Callback */
	//request.callback = dm_client_combine_login_reply;


	/* Send Message To Cloud */
	res = dm_msg_request(&request,0);

	free(request.params);

	return res;
}

const char DM_URI_STATUS_ONLINE[] = "/thing/status/online";
int dm_mgr_upstream_status_online(_IN_ int devid)
{
	int res = 0;
	dm_mgr_dev_node_t *node = NULL;
	dm_mgr_dev_node_t *gw_node = NULL;		
	dm_msg_request_t request;
	char msgId[MSG_MAX_LEN] = {0};

	if (devid < 0) {
		return INVALID_PARAMETER;
	}
	memset(&request, 0, sizeof(dm_msg_request_t));


	res = dm_mgr_search_dev_by_devid(devid, &node);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}
	#if 0
	if(strlen(node->fatherDeviceCode) > 0){
		res = dm_mgr_get_device_by_devicecode(node->fatherDeviceCode,&gw_node);
		if (res != SUCCESS_RETURN) {
			ERROR_PRINT("ERROR [%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
			return FAIL_RETURN;
		}
		memcpy(request.productCode,gw_node->productCode,strlen(gw_node->productCode));	
		memcpy(request.deviceCode,gw_node->deviceCode,strlen(gw_node->deviceCode));
		
	}else
	#endif
	{
		memcpy(request.productCode,node->productCode,strlen(node->productCode));	
		memcpy(request.deviceCode,node->deviceCode,strlen(node->deviceCode));
	}
	


	request.msgTypeStr = (char*)DM_URI_STATUS_ONLINE;


	/* Get Params And Method */
	res = dm_msg_status_online( node->productCode, node->deviceCode, &request);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}

	/* Get Msg ID */
	iotx_report_id(msgId);
	//sprintf(msgId,"%d",iotx_report_id());
	memcpy(request.msgid,msgId,strlen(msgId));


	/* Get Dev ID */
	request.devid = devid;

	/* Callback */
	//request.callback = dm_client_combine_login_reply;


	/* Send Message To Cloud */
	res = dm_msg_request(&request,0);

	free(request.params);

	return res;
}

const char DM_URI_STATUS_OFFLINE[] = "/thing/status/offline";
int dm_mgr_upstream_status_offline(_IN_ int devid)
{
	int res = 0;
	dm_mgr_dev_node_t *node = NULL;
	dm_mgr_dev_node_t *gw_node = NULL;		
	dm_msg_request_t request;
	char msgId[MSG_MAX_LEN] = {0};

	if (devid < 0) {
		return INVALID_PARAMETER;
	}
	memset(&request, 0, sizeof(dm_msg_request_t));

	res = dm_mgr_search_dev_by_devid(devid, &node);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}
	//if(strlen(node->fatherDeviceCode) > 0){
		//res = dm_mgr_get_device_by_devicecode(node->fatherDeviceCode,&gw_node);
		//if (res != SUCCESS_RETURN) {
			//ERROR_PRINT("ERROR [%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
			//return FAIL_RETURN;
		//}
		//memcpy(request.productCode,gw_node->productCode,strlen(gw_node->productCode));	
		//memcpy(request.deviceCode,gw_node->deviceCode,strlen(gw_node->deviceCode));
		
	//}else
	{
		memcpy(request.productCode,node->productCode,strlen(node->productCode));	
		memcpy(request.deviceCode,node->deviceCode,strlen(node->deviceCode));
	}
	
	request.msgTypeStr = (char*)DM_URI_STATUS_OFFLINE;

	/* Get Params And Method */
	res = dm_msg_status_offline( node->productCode, node->deviceCode, &request);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}

	/* Get Msg ID */
	iotx_report_id(msgId);
	//sprintf(msgId,"%d",iotx_report_id());
	memcpy(request.msgid,msgId,strlen(msgId));


	/* Get Dev ID */
	request.devid = devid;

	/* Callback */
	//request.callback = dm_client_combine_login_reply;


	/* Send Message To Cloud */
	res = dm_msg_request(&request,0);

	free(request.params);

	return res;
}

const char DM_URI_COMBINE_LOGIN[] = "/thing/combine/login";
int dm_mgr_upstream_combine_login(_IN_ int devid)
{
    int res = 0;
    dm_mgr_dev_node_t *node = NULL;
	dm_mgr_dev_node_t *gw_node = NULL;		
    dm_msg_request_t request;
	char msgId[MSG_MAX_LEN] = {0};

    if (devid < 0) {
        return INVALID_PARAMETER;
    }

    res = dm_mgr_search_dev_by_devid(devid, &node);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }
	res = dm_mgr_get_device_by_devicecode(node->fatherDeviceCode,&gw_node);
    if (res != SUCCESS_RETURN) {
		ERROR_PRINT("ERROR [%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
        return FAIL_RETURN;
    }

    memset(&request, 0, sizeof(dm_msg_request_t));
    request.msgTypeStr = (char*)DM_URI_COMBINE_LOGIN;
	memcpy(request.productCode,gw_node->productCode,strlen(gw_node->productCode));	
	memcpy(request.deviceCode,gw_node->deviceCode,strlen(gw_node->deviceCode));


    /* Get Params And Method */
    res = dm_msg_combine_login( node->productCode, node->deviceCode, &request);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }

    /* Get Msg ID */
	iotx_report_id(msgId);
	//sprintf(msgId,"%d",iotx_report_id());
    memcpy(request.msgid,msgId,strlen(msgId));


    /* Get Dev ID */
    request.devid = devid;

    /* Callback */
    //request.callback = dm_client_combine_login_reply;


    /* Send Message To Cloud */
    res = dm_msg_request(&request,0);

    free(request.params);

    return res;
}
const char DM_URI_COMBINE_LOGOUT[] = "/thing/combine/logout";
int dm_mgr_upstream_combine_logout(_IN_ int devid)
{
    int res = 0;
    dm_mgr_dev_node_t *node = NULL;
	dm_mgr_dev_node_t *gw_node = NULL;		
    dm_msg_request_t request;
	char msgId[MSG_MAX_LEN] = {0};

    if (devid < 0) {
        return INVALID_PARAMETER;
    }

    res = dm_mgr_search_dev_by_devid(devid, &node);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }
	res = dm_mgr_get_device_by_devicecode(node->fatherDeviceCode,&gw_node);
    if (res != SUCCESS_RETURN) {
		ERROR_PRINT("ERROR [%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
        return FAIL_RETURN;
    }

    memset(&request, 0, sizeof(dm_msg_request_t));
    request.msgTypeStr = (char*)DM_URI_COMBINE_LOGOUT;
	memcpy(request.productCode,gw_node->productCode,strlen(gw_node->productCode));	
	memcpy(request.deviceCode,gw_node->deviceCode,strlen(gw_node->deviceCode));


    /* Get Params And Method */
    res = dm_msg_combine_logout( node->deviceCode, &request);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }

    /* Get Msg ID */
	iotx_report_id(msgId);
	//sprintf(msgId,"%d",iotx_report_id());
    memcpy(request.msgid,msgId,strlen(msgId));


    /* Get Dev ID */
    request.devid = devid;

    /* Callback */
    //request.callback = dm_client_combine_logout_reply;

    /* Send Message To Cloud */

    /* Send Message To Cloud */
    res = dm_msg_request(&request,0);

    free(request.params);

    return res;
}

const char KK_URI_OTA_INFORM[] = "/ota/device/inform/%s/%s";
int dm_mgr_ota_report_version(_IN_ int devid, char *version)
{
    int res = 0;
    dm_mgr_dev_node_t *node = NULL;
    dm_msg_request_t request;
	char msgId[MSG_MAX_LEN] = {0};

    if (devid < 0) {
        return INVALID_PARAMETER;
    }

    res = dm_mgr_search_dev_by_devid(devid, &node);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }

    memset(&request, 0, sizeof(dm_msg_request_t));
    request.msgTypeStr = malloc(strlen(KK_URI_OTA_INFORM)+strlen(node->productCode)+strlen(node->deviceCode)+1);
	if(request.msgTypeStr == NULL){
		return MEMORY_NOT_ENOUGH;
	}
	sprintf(request.msgTypeStr,KK_URI_OTA_INFORM,node->productCode,node->deviceCode);
    memcpy(request.productCode, node->productCode, PRODUCT_CODE_MAXLEN);	
    memcpy(request.deviceCode, node->deviceCode, DEVICE_CODE_MAXLEN);

    /* Get Params And Method */
    res = dm_msg_ota_report_version(version, &request);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }

    /* Get Msg ID */
	iotx_report_id(msgId);
	//sprintf(msgId,"%d",iotx_report_id());
    memcpy(request.msgid,msgId,strlen(msgId));


    /* Get Dev ID */
    request.devid = devid;

    /* Callback */
    //request.callback = dm_client_combine_logout_reply;

    /* Send Message To Cloud */

    /* Send Message To Cloud */
    res = dm_msg_request(&request,0);

    free(request.params);
	free(request.msgTypeStr);

    return res;
}



int dm_mgr_subdev_create(int devtype,_IN_ char productCode[PRODUCT_CODE_MAXLEN], _IN_ char deviceCode[DEVICE_CODE_MAXLEN],
		_IN_ char mac[DEVICE_MAC_MAXLEN],_IN_ char fatherDeviceCode[DEVICE_CODE_MAXLEN],_IN_ int isOffline, _OU_ int *devid,_OU_ int *heartbeat){
	int res = 0;

	res = dm_mgr_device_create(devtype,productCode,deviceCode,mac,fatherDeviceCode,isOffline,devid,heartbeat);
	if(TSL_ALREADY_EXIST == res)
	{
		ERROR_PRINT("SUBDEV ALREADY EXIST!!!\n");
	}
	return res;
}

int dm_mgr_subdev_delete(_IN_ char deviceCode[DEVICE_CODE_MAXLEN])
{
	int res = 0;
	dm_mgr_dev_node_t *node = NULL;
	if(deviceCode == NULL || strlen(deviceCode) <=0){
		ERROR_PRINT("ERROR [%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
		return FAIL_RETURN;
	}
	INFO_PRINT("dm_mgr_subdev_delete deviceCode:%s\n",deviceCode);
	kk_scene_deleteall_panel_scene_info(deviceCode);//如果是情景面板，删除对应信息
	/*房间信息中删除对应的设备*/
	kk_room_dev_remove(deviceCode,NULL);
	
	res = kk_subDev_delete_by_dcode(deviceCode);//delete sub db data
	if (res != SUCCESS_RETURN) {
		ERROR_PRINT("ERROR [%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
		return FAIL_RETURN;
	}

	res = kk_property_delete_by_dcode(deviceCode);//delete properties db data
	if (res != SUCCESS_RETURN) {
		ERROR_PRINT("ERROR [%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
		return FAIL_RETURN;
	}

	res = dm_mgr_get_device_by_devicecode(deviceCode,&node);
	if (res != SUCCESS_RETURN) {
		ERROR_PRINT("ERROR [%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
		return FAIL_RETURN;
	}
	if(strcmp(node->productType,KK_DM_AIR_GATEWAY_TYPE) == 0){
		kk_indoorAir_delete_by_dcode(deviceCode);
	}
	if(node->dev_type == KK_DM_DEVICE_CCU){
		ERROR_PRINT("ERROR [%s][%d]\n",__FUNCTION__,__LINE__);
		return FAIL_RETURN;
	}

	list_del(&node->linked_list);

	if (node->dev_shadow) {
		kk_tsl_destroy(&node->dev_shadow);
	}

	free(node);
	node = NULL;
	return SUCCESS_RETURN;
}

