#include "kk_dm_msg.h"

#include "kk_dm_queue.h"
#include "lite-cjson.h"
#include "kk_hal.h"
#include "com_api.h"
#include "kk_log.h"
#include "kk_utils.h"
#include "kk_sync_data.h"

const char DM_MSG_REQUEST[] DM_READ_ONLY = "{\"msgId\":\"%s\",\"version\":\"%s\",\"params\":%s,\"time\":\"%lu\",\"method\":\"%s\"}";
const char DM_MSG_INFO[] DM_READ_ONLY = "{\"msgtype\":\"%s\",\"productCode\":\"%s\",\"deviceCode\":\"%s\"}";

void kk_sendData2app(void *info, void *payload,int isAsync){
    void *buf = NULL;
    cJSON *root=cJSON_CreateObject();
    cJSON* infoObj = cJSON_Parse(info);
    cJSON* payloadObj = cJSON_Parse(payload);
    cJSON_AddItemToObject(root, "info", infoObj);
    cJSON_AddItemToObject(root, "payload",payloadObj);	
    buf = cJSON_Print(root);
	if(isAsync){
		dm_queue_msg_insert4(buf);
		
	}else{
    	kk_ipc_send(IPC_MID2APP, buf, strlen(buf)+1 );
		free(buf);
	}
    cJSON_Delete(root);
}

const char DM_MSG_THING_SUB_REGISTER_METHOD[] = "thing.sub.register";
const char DM_MSG_THING_SUB_REGISTER_PARAMS[] = "[{\"productCode\":\"%s\",\"deviceCode\":\"%s\"}]";

int dm_msg_thing_sub_register(_IN_ char productCode[DEVICE_CODE_MAXLEN], _IN_ char deviceCode[DEVICE_CODE_MAXLEN],
                              _OU_ dm_msg_request_t *request)
{
    int params_len = 0;
    char *params = NULL;

    if (request == NULL || deviceCode == NULL ||
        (strlen(deviceCode) >= DEVICE_CODE_MAXLEN) ||
        (strlen(request->deviceCode) >= DEVICE_CODE_MAXLEN)) {
        return INVALID_PARAMETER;
    }

    params_len = strlen(DM_MSG_THING_SUB_REGISTER_PARAMS) +strlen(productCode) + strlen(deviceCode) + 1;
    params = malloc(params_len);
    if (params == NULL) {
        return MEMORY_NOT_ENOUGH;
    }

    memset(params, 0, params_len);
    snprintf(params, params_len, DM_MSG_THING_SUB_REGISTER_PARAMS,productCode, deviceCode);

    /* Get Params */
    request->params = params;
    request->params_len = strlen(request->params);

    /* Get Method */
    request->method = (char *)DM_MSG_THING_SUB_REGISTER_METHOD;

    return SUCCESS_RETURN;
}

const char DM_MSG_THING_SUB_UNREGISTER_METHOD[] DM_READ_ONLY = "thing.sub.unregister";
const char DM_MSG_THING_SUB_UNREGISTER_PARAMS[] DM_READ_ONLY = "[{\"deviceCode\":\"%s\"}]";
int dm_msg_thing_sub_unregister(_IN_ char deviceCode[DEVICE_CODE_MAXLEN],_OU_ dm_msg_request_t *request)
{
    int params_len = 0;
    char *params = NULL;

    if (request == NULL || deviceCode == NULL ||
        (strlen(deviceCode) >= DEVICE_CODE_MAXLEN) ||
        (strlen(request->deviceCode) >= DEVICE_CODE_MAXLEN)) {
        return INVALID_PARAMETER;
    }

    params_len = strlen(DM_MSG_THING_SUB_UNREGISTER_PARAMS) + strlen(deviceCode) + 1;
    params = malloc(params_len);
    if (params == NULL) {
    return MEMORY_NOT_ENOUGH;
    }
    memset(params, 0, params_len);
    snprintf(params, params_len, DM_MSG_THING_SUB_UNREGISTER_PARAMS, deviceCode);

    /* Get Params */
    request->params = params;
    request->params_len = strlen(request->params);

    /* Get Method */
    request->method = (char *)DM_MSG_THING_SUB_UNREGISTER_METHOD;

    return SUCCESS_RETURN;
}

const char DM_MSG_THING_TOPO_ADD_SIGN_SOURCE[] DM_READ_ONLY = "clientId%sdeviceCode%stimestamp%s";
const char DM_MSG_THING_TOPO_ADD_METHOD[] DM_READ_ONLY = "thing.topo.add";
const char DM_MSG_THING_TOPO_ADD_PARAMS[] DM_READ_ONLY =
          //"[{\"productKey\":\"%s\",\"deviceName\":\"%s\",\"signmethod\":\"%s\",\"sign\":\"%s\",\"timestamp\":\"%s\",\"clientId\":\"%s\"}]";
          "{\"productCode\":\"%s\",\"deviceCode\":\"%s\",\"mac\":\"%s\"}";
          
int dm_msg_thing_topo_add(_IN_ char productCode[PRODUCT_CODE_MAXLEN],
                        _IN_ char deviceCode[DEVICE_CODE_MAXLEN], _IN_ char mac[DEVICE_MAC_MAXLEN],
                        _OU_ dm_msg_request_t *request)
{
    char *params = NULL;
    int params_len = 0;
    char client_id[PRODUCT_TYPE_MAXLEN + DEVICE_CODE_MAXLEN + 1] = {0};

    if (request == NULL ||
         deviceCode == NULL ||
        (strlen(productCode) >= PRODUCT_CODE_MAXLEN) ||
        (strlen(deviceCode) >= DEVICE_CODE_MAXLEN) ||
        (strlen(request->deviceCode) >= DEVICE_CODE_MAXLEN)) {
        return INVALID_PARAMETER;
    }

#if 0
    /* TimeStamp */
    HAL_Snprintf(timestamp, DM_UTILS_UINT64_STRLEN, "%llu", (unsigned long long)HAL_UptimeMs());
    /* dm_log_debug("Time Stamp: %s", timestamp); */

    /* Client ID */
    HAL_Snprintf(client_id, DEVICE_CODE_MAXLEN + 1, "%s", deviceCode);

    /* Sign */
    sign_source_len = strlen(DM_MSG_THING_TOPO_ADD_SIGN_SOURCE) + strlen(client_id) +
                    strlen(deviceCode) + strlen(timestamp) + 1;
    sign_source = malloc(sign_source_len);
    if (sign_source == NULL) {
      return MEMORY_NOT_ENOUGH;
    }
    memset(sign_source, 0, sign_source_len);
    HAL_Snprintf(sign_source, sign_source_len, DM_MSG_THING_TOPO_ADD_SIGN_SOURCE, client_id,
               deviceCode, timestamp);
               

    /* dm_log_debug("Sign Srouce: %s", sign_source); */
#if 0
  if (strcmp(sign_method, DM_MSG_SIGN_METHOD_HMACMD5) == 0) {
      utils_hmac_md5(sign_source, strlen(sign_source), sign, device_secret, strlen(device_secret));
  } else if (strcmp(sign_method, DM_MSG_SIGN_METHOD_HMACSHA1) == 0) {
      utils_hmac_sha1(sign_source, strlen(sign_source), sign, device_secret, strlen(device_secret));
  } else if (strcmp(sign_method, DM_MSG_SIGN_METHOD_HMACSHA256) == 0) {
      utils_hmac_sha256(sign_source, strlen(sign_source), sign, device_secret, strlen(device_secret));
  } else {
      DM_free(sign_source);
      return FAIL_RETURN;
  }
#else
  //utils_hmac_sha1(sign_source, strlen(sign_source), sign, device_secret, strlen(device_secret));
#endif
  free(sign_source);
  /* dm_log_debug("Sign : %s", sign); */
#endif

  /* Params */
  request->method = (char *)DM_MSG_THING_TOPO_ADD_METHOD;
  //params_len = strlen(DM_MSG_THING_TOPO_ADD_PARAMS) + strlen(deviceCode) +
  //             strlen(sign_method) + strlen(sign) + strlen(timestamp) + strlen(client_id) + 1;
  params_len = strlen(DM_MSG_THING_TOPO_ADD_PARAMS) + strlen(deviceCode) +
               strlen(productCode) + strlen(mac) + strlen(client_id) + 1;          
  params = malloc(params_len);

  if (params == NULL) {
      return MEMORY_NOT_ENOUGH;
  }
  memset(params, 0, params_len);
  //HAL_Snprintf(params, params_len, DM_MSG_THING_TOPO_ADD_PARAMS, productType, deviceCode,
  //             sign_method, sign, timestamp, client_id);
  HAL_Snprintf(params, params_len, DM_MSG_THING_TOPO_ADD_PARAMS, productCode, deviceCode,mac);

  request->params = params;
  request->params_len = strlen(request->params);

  return SUCCESS_RETURN;
}

const char DM_MSG_THING_TOPO_DELETE_METHOD[] DM_READ_ONLY = "thing.topo.delete";
const char DM_MSG_THING_TOPO_DELETE_PARAMS[] DM_READ_ONLY = "[{\"deviceCode\":\"%s\"}]";
int dm_msg_thing_topo_delete(_IN_ char deviceCode[DEVICE_CODE_MAXLEN],_OU_ dm_msg_request_t *request)
{
    char *params = NULL;
    int params_len = 0;

    if (request == NULL ||
        deviceCode == NULL ||
        (strlen(deviceCode) >= DEVICE_CODE_MAXLEN) ||
        (strlen(request->deviceCode) >= DEVICE_CODE_MAXLEN)) {
        return INVALID_PARAMETER;
    }

    /* Params */
    request->method = (char *)DM_MSG_THING_TOPO_DELETE_METHOD;
    params_len = strlen(DM_MSG_THING_TOPO_DELETE_PARAMS) + strlen(deviceCode) + 1;
    params = malloc(params_len);
    if (params == NULL) {
        return MEMORY_NOT_ENOUGH;
    }
    memset(params, 0, params_len);
    HAL_Snprintf(params, params_len, DM_MSG_THING_TOPO_DELETE_PARAMS, deviceCode);

    request->params = params;
    request->params_len = strlen(request->params);

    return SUCCESS_RETURN;
}

 const char DM_MSG_THING_TOPO_GET_METHOD[] DM_READ_ONLY = "thing.topo.get";
 const char DM_MSG_THING_TOPO_GET_PARAMS[] DM_READ_ONLY = "{}";
 int dm_msg_thing_topo_get(_OU_ dm_msg_request_t *request)
 {
     char *params = NULL;
     int params_len = 0;
 
     /* Params */
     request->method = (char *)DM_MSG_THING_TOPO_GET_METHOD;
     params_len = strlen(DM_MSG_THING_TOPO_GET_PARAMS) + 1;
     params = malloc(params_len);
     if (params == NULL) {
         return MEMORY_NOT_ENOUGH;
     }
     memset(params, 0, params_len);
     memcpy(params, DM_MSG_THING_TOPO_GET_PARAMS, strlen(DM_MSG_THING_TOPO_GET_PARAMS));
 
     request->params = params;
     request->params_len = strlen(request->params);
 
     return SUCCESS_RETURN;
 }

 const char DM_MSG_THING_LIST_FOUND_METHOD[] DM_READ_ONLY = "thing.list.found";
 const char DM_MSG_THING_LIST_FOUND_PARAMS[] DM_READ_ONLY = "[{\"deviceCode\":\"%s\"}]";
 int dm_msg_thing_list_found(_IN_ char deviceCode[DEVICE_CODE_MAXLEN],
                             _OU_ dm_msg_request_t *request)
 {
     char *params = NULL;
     int params_len = 0;
 
     if ( deviceCode == NULL ||
         (strlen(deviceCode) >= DEVICE_CODE_MAXLEN) ||
         request == NULL) {
         return INVALID_PARAMETER;
     }
 
     /* Params */
     request->method = (char *)DM_MSG_THING_LIST_FOUND_METHOD;
     params_len = strlen(DM_MSG_THING_LIST_FOUND_PARAMS) + strlen(deviceCode) + 1;
     params = malloc(params_len);
     if (params == NULL) {
         return MEMORY_NOT_ENOUGH;
     }
     memset(params, 0, params_len);
     HAL_Snprintf(params, params_len, DM_MSG_THING_LIST_FOUND_PARAMS, deviceCode);
 
     request->params = params;
     request->params_len = strlen(request->params);
 
     return SUCCESS_RETURN;
 }

const char DM_MSG_STATUS_CLOUD_METHOD[] DM_READ_ONLY = "thing.ccu.cloudstate";							 
const char DM_MSG_STATUS_CLOUD[] DM_READ_ONLY =
            "{\"deviceCode\":\"%s\"}";							 
 int dm_msg_status_cloud(_IN_ char productCode[PRODUCT_CODE_MAXLEN],
						  _IN_ char deviceCode[DEVICE_CODE_MAXLEN], _OU_ dm_msg_request_t *request)
 {
	 char *params = NULL;
	 int params_len = 0;

	 if (request == NULL || 
		 deviceCode == NULL || productCode == NULL ||
		 (strlen(deviceCode) >= DEVICE_CODE_MAXLEN) ||
		 (strlen(productCode) >= PRODUCT_CODE_MAXLEN) ||
		 (strlen(request->deviceCode) >= DEVICE_CODE_MAXLEN)) {
		 return INVALID_PARAMETER;
	 }
 
	 /* Params */
	 request->method = (char *)DM_MSG_STATUS_CLOUD_METHOD;
	 params_len = strlen(DM_MSG_STATUS_CLOUD) + strlen(deviceCode)  + 1;
	 params = malloc(params_len);
 
	 if (params == NULL) {
		 return DM_MEMORY_NOT_ENOUGH;
	 }
	 memset(params, 0, params_len);
	 HAL_Snprintf(params, params_len, DM_MSG_STATUS_CLOUD,deviceCode);
 
	 request->params = params;
	 request->params_len = strlen(request->params);
 
	 return SUCCESS_RETURN;
 }
const char DM_MSG_COMBINE_STATUS_ONLINE_METHOD[] DM_READ_ONLY = "thing.status.online";							 
const char DM_MSG_COMBINE_STATUS_ONLINE[] DM_READ_ONLY =
            "{\"deviceCode\":\"%s\"}";							 
 int dm_msg_status_online(_IN_ char productCode[PRODUCT_CODE_MAXLEN],
						  _IN_ char deviceCode[DEVICE_CODE_MAXLEN], _OU_ dm_msg_request_t *request)
 {
	 char *params = NULL;
	 int params_len = 0;
	 char timestamp[DM_UTILS_UINT64_STRLEN] = {0};
 
	 if (request == NULL || 
		 deviceCode == NULL || productCode == NULL ||
		 (strlen(deviceCode) >= DEVICE_CODE_MAXLEN) ||
		 (strlen(productCode) >= PRODUCT_CODE_MAXLEN) ||
		 (strlen(request->deviceCode) >= DEVICE_CODE_MAXLEN)) {
		 return INVALID_PARAMETER;
	 }
 
	 /* TimeStamp */
	 HAL_Snprintf(timestamp, DM_UTILS_UINT64_STRLEN, "%d", HAL_GetTime());
	 /* dm_log_debug("Time Stamp: %s", timestamp); */
 

	 /* Params */
	 request->method = (char *)DM_MSG_COMBINE_STATUS_ONLINE_METHOD;
	 params_len = strlen(DM_MSG_COMBINE_STATUS_ONLINE) + strlen(deviceCode)  + 1;
	 params = malloc(params_len);
 
	 if (params == NULL) {
		 return DM_MEMORY_NOT_ENOUGH;
	 }
	 memset(params, 0, params_len);
	 HAL_Snprintf(params, params_len, DM_MSG_COMBINE_STATUS_ONLINE,deviceCode);
 
	 request->params = params;
	 request->params_len = strlen(request->params);
 
	 return SUCCESS_RETURN;
 }

const char DM_MSG_COMBINE_STATUS_OFFLINE_METHOD[] DM_READ_ONLY = "thing.status.offline";						   
const char DM_MSG_COMBINE_STATUS_OFFLINE[] DM_READ_ONLY =
		  "{\"deviceCode\":\"%s\"}";						   
int dm_msg_status_offline(_IN_ char productCode[PRODUCT_CODE_MAXLEN],
						_IN_ char deviceCode[DEVICE_CODE_MAXLEN], _OU_ dm_msg_request_t *request)
{
   char *params = NULL;
   int params_len = 0;
   char timestamp[DM_UTILS_UINT64_STRLEN] = {0};

   if (request == NULL || 
	   deviceCode == NULL || productCode == NULL ||
	   (strlen(deviceCode) >= DEVICE_CODE_MAXLEN) ||
	   (strlen(productCode) >= PRODUCT_CODE_MAXLEN) ||
	   (strlen(request->deviceCode) >= DEVICE_CODE_MAXLEN)) {
	   return INVALID_PARAMETER;
   }

   /* TimeStamp */
   HAL_Snprintf(timestamp, DM_UTILS_UINT64_STRLEN, "%d", HAL_GetTime());
   /* dm_log_debug("Time Stamp: %s", timestamp); */


   /* Params */
   request->method = (char *)DM_MSG_COMBINE_STATUS_OFFLINE_METHOD;
   params_len = strlen(DM_MSG_COMBINE_STATUS_OFFLINE) + strlen(deviceCode)  + 1;
   params = malloc(params_len);

   if (params == NULL) {
	   return DM_MEMORY_NOT_ENOUGH;
   }
   memset(params, 0, params_len);
   HAL_Snprintf(params, params_len, DM_MSG_COMBINE_STATUS_OFFLINE,deviceCode);

   request->params = params;
   request->params_len = strlen(request->params);

   return SUCCESS_RETURN;
}

const char DM_MSG_COMBINE_LOGIN_SIGN_SOURCE[] DM_READ_ONLY = "clientId%sdeviceCode%stimestamp%s";
const char DM_MSG_COMBINE_LOGIN_METHOD[] DM_READ_ONLY = "combine.login";
const char DM_MSG_COMBINE_LOGIN_PARAMS[] DM_READ_ONLY =
            "{\"deviceCode\":\"%s\",\"clientId\":\"%s\",\"timestamp\":\"%s\",\"signMethod\":\"%s\",\"sign\":\"%s\",\"cleanSession\":\"%s\"}";
int dm_msg_combine_login(_IN_ char productCode[PRODUCT_CODE_MAXLEN],
                         _IN_ char deviceCode[DEVICE_CODE_MAXLEN], _OU_ dm_msg_request_t *request)
{
    char *params = NULL;
    int params_len = 0;
    char timestamp[DM_UTILS_UINT64_STRLEN] = {0};
    char client_id[PRODUCT_TYPE_MAXLEN + DEVICE_CODE_MAXLEN + 20] = {0};
    char *sign_source = NULL;
    int sign_source_len = 0;
    char *sign_method = DM_MSG_SIGN_METHOD_HMACSHA1;
    char sign[64] = {0};

    if (request == NULL ||
        deviceCode == NULL || productCode == NULL ||
        (strlen(deviceCode) >= DEVICE_CODE_MAXLEN) ||
        (strlen(productCode) >= PRODUCT_CODE_MAXLEN) ||
        (strlen(request->deviceCode) >= DEVICE_CODE_MAXLEN)) {
        return INVALID_PARAMETER;
    }

    /* TimeStamp */
    HAL_Snprintf(timestamp, DM_UTILS_UINT64_STRLEN, "%d", HAL_GetTime());
    /* dm_log_debug("Time Stamp: %s", timestamp); */

    /* Client ID */
    HAL_Snprintf(client_id, PRODUCT_TYPE_MAXLEN + DEVICE_CODE_MAXLEN + 20, "%s|_v=sdk-c-3.0.1|", deviceCode);

    /* Sign */
    sign_source_len = strlen(DM_MSG_COMBINE_LOGIN_SIGN_SOURCE) + strlen(client_id) +
                      strlen(deviceCode) + strlen(timestamp) + 1;
    sign_source = malloc(sign_source_len);
    if (sign_source == NULL) {
        return DM_MEMORY_NOT_ENOUGH;
    }
    memset(sign_source, 0, sign_source_len);
    HAL_Snprintf(sign_source, sign_source_len, DM_MSG_COMBINE_LOGIN_SIGN_SOURCE, client_id,
                 deviceCode, timestamp);

    /* dm_log_debug("Sign Srouce: %s", sign_source); */
#if 0
    if (strcmp(sign_method, DM_MSG_SIGN_METHOD_HMACMD5) == 0) {
        utils_hmac_md5(sign_source, strlen(sign_source), sign, device_secret, strlen(device_secret));
    } else if (strcmp(sign_method, DM_MSG_SIGN_METHOD_HMACSHA1) == 0) {
        utils_hmac_sha1(sign_source, strlen(sign_source), sign, device_secret, strlen(device_secret));
    } else if (strcmp(sign_method, DM_MSG_SIGN_METHOD_HMACSHA256) == 0) {
        utils_hmac_sha256(sign_source, strlen(sign_source), sign, device_secret, strlen(device_secret));
    } else {
        DM_free(sign_source);
        return FAIL_RETURN;
    }
#else
    //utils_hmac_sha1(sign_source, strlen(sign_source), sign, device_secret, strlen(device_secret));
#endif
    free(sign_source);
    /* dm_log_debug("Sign : %s", sign); */

    /* Params */
    request->method = (char *)DM_MSG_COMBINE_LOGIN_METHOD;
    params_len = strlen(DM_MSG_COMBINE_LOGIN_PARAMS) + strlen(deviceCode) +
                 strlen(sign_method) + strlen(sign) + strlen(timestamp) + strlen(client_id) + 1;
    params = malloc(params_len);

    if (params == NULL) {
        return DM_MEMORY_NOT_ENOUGH;
    }
    memset(params, 0, params_len);
    HAL_Snprintf(params, params_len, DM_MSG_COMBINE_LOGIN_PARAMS, deviceCode,
                 client_id, timestamp, sign_method, sign, "true");

    request->params = params;
    request->params_len = strlen(request->params);

    return SUCCESS_RETURN;
}


const char DM_MSG_COMBINE_LOGOUT_METHOD[] DM_READ_ONLY = "combine.logout";
const char DM_MSG_COMBINE_LOGOUT_PARAMS[] DM_READ_ONLY = "{\"deviceCode\":\"%s\"}";
int dm_msg_combine_logout(_IN_ char deviceCode[DEVICE_CODE_MAXLEN],_OU_ dm_msg_request_t *request)
{

    char *params = NULL;
    int params_len = 0;

    if ( deviceCode == NULL ||
        (strlen(deviceCode) >= DEVICE_CODE_MAXLEN) ||
        request == NULL){
        return INVALID_PARAMETER;
    }

    /* Params */
    request->method = (char *)DM_MSG_COMBINE_LOGOUT_METHOD;
    params_len = strlen(DM_MSG_COMBINE_LOGOUT_PARAMS) + strlen(deviceCode) + 1;
    params = malloc(params_len);

    if (params == NULL) {
        return MEMORY_NOT_ENOUGH;
    }
    memset(params, 0, params_len);
    HAL_Snprintf(params, params_len, DM_MSG_COMBINE_LOGOUT_PARAMS, deviceCode);

    request->params = params;
    request->params_len = strlen(request->params);

    return SUCCESS_RETURN;
 
}


 const char DM_MSG_OTA_VERSION_PARAMS[] DM_READ_ONLY = "{\"version\":\"%s\"}";
 int dm_msg_ota_report_version(_IN_ char *version,
                                      _OU_ dm_msg_request_t *request)
 {
 
     char *params = NULL;
     int params_len = 0;
 
     if (NULL == version ){
         return INVALID_PARAMETER;
     }
 
     /* Params */
     request->method = (char *)"";
     params_len = strlen(DM_MSG_OTA_VERSION_PARAMS) + strlen(version) + 1;
     params = malloc(params_len);
 
     if (params == NULL) {
         return MEMORY_NOT_ENOUGH;
     }
     memset(params, 0, params_len);
     HAL_Snprintf(params, params_len, DM_MSG_OTA_VERSION_PARAMS, version);
 
     request->params = params;
     request->params_len = strlen(request->params);
 
     return SUCCESS_RETURN;
  
 }

 
int dm_msg_request (_IN_ dm_msg_request_t *request,_IN_ int isAsync)
{
    int res = 0, payload_len = 0,req_info_len = 0;
    char *payload = NULL;
    lite_cjson_t lite;
	char *req_info = NULL;
    if (request == NULL || request->params == NULL || request->method == NULL) {
        return INVALID_PARAMETER;
    }

    payload_len = strlen(DM_MSG_REQUEST) + 10 + strlen(DM_MSG_VERSION) + request->params_len + strlen(
                              request->method) + 1 + 20 + strlen(request->msgid);
    payload = malloc(payload_len);
    if (payload == NULL) {
        return MEMORY_NOT_ENOUGH;
    }
    memset(payload, 0, payload_len);
    snprintf(payload, payload_len, DM_MSG_REQUEST, request->msgid,
                 DM_MSG_VERSION, request->params,HAL_GetTime(), request->method);

	req_info_len = strlen(DM_MSG_INFO)+10+strlen(request->productCode)+strlen(request->deviceCode)+strlen(request->msgTypeStr)+1;
    req_info = malloc(req_info_len);
    if (req_info == NULL) {
		free(payload);
        return MEMORY_NOT_ENOUGH;
    }
    memset(req_info, 0, req_info_len);
    snprintf(req_info, req_info_len, DM_MSG_INFO, request->msgTypeStr, request->productCode, request->deviceCode);

    memset(&lite, 0, sizeof(lite_cjson_t));
    res = lite_cjson_parse(payload, payload_len, &lite);
    if (res < SUCCESS_RETURN) {
        ERROR_PRINT("Wrong JSON Format, Payload: %s", payload);
        free(req_info);
        free(payload);
        return FAIL_RETURN;
    }
    memset(&lite, 0, sizeof(lite_cjson_t));
    res = lite_cjson_parse(req_info, req_info_len, &lite);
    if (res < SUCCESS_RETURN) {
        ERROR_PRINT("Wrong JSON Format, Payload: %d", req_info_len);
        free(req_info);
        free(payload);
        return FAIL_RETURN;
    }
    //if (type & DM_MSG_DEST_CLOUD) {
    // dm_client_publish(uri, (unsigned char *)payload, strlen(payload), request->callback);
     kk_sendData2app(req_info, payload,isAsync);

    free(req_info);
    free(payload);
    return SUCCESS_RETURN;
}


const char DM_MSG_RESPONSE_WITH_DATA[] DM_READ_ONLY = "{\"msgId\":\"%.*s\",\"code\":%d,\"data\":%.*s}";
int dm_msg_response(_IN_ kk_msg_request_payload_t *request, _IN_ kk_msg_response_t *response,
                    _IN_ char *data, _IN_ int data_len, _IN_ void *user_data)
{
    int res = 0, payload_len = 0,res_info_len = 0;
    char *uri = NULL, *payload = NULL;
    lite_cjson_t lite;
	char *res_info = NULL;

    if (request == NULL || response == NULL || data == NULL || data_len <= 0) {
        return INVALID_PARAMETER;
    }

    /* Response Payload */
    payload_len = strlen(DM_MSG_RESPONSE_WITH_DATA) + request->id.value_length + DM_UTILS_UINT32_STRLEN + data_len + 1;
    payload = malloc(payload_len);
    if (payload == NULL) {
        free(uri);
        return MEMORY_NOT_ENOUGH;
    }

    memset(payload, 0, payload_len);
    snprintf(payload, payload_len, DM_MSG_RESPONSE_WITH_DATA,
                 request->id.value_length, request->id.value, response->code, data_len, data);

	 res_info_len = strlen(DM_MSG_INFO)+10+strlen(response->productCode)+strlen(response->deviceCode)+strlen(response->msgTypeStr)+1;
	 res_info = malloc(res_info_len);
	 if (res_info == NULL) {
		 free(payload);
		 return MEMORY_NOT_ENOUGH;
	 }

	 memset(res_info, 0, res_info_len);
	 snprintf(res_info, res_info_len, DM_MSG_INFO, response->msgTypeStr,response->productCode, response->deviceCode);


    memset(&lite, 0, sizeof(lite_cjson_t));
    res = lite_cjson_parse(payload, payload_len, &lite);
    if (res < SUCCESS_RETURN) {
        ERROR_PRINT("Wrong JSON Format, URI: %s, Payload: %s", uri, payload);
        free(uri);
        free(payload);
        return FAIL_RETURN;
    }

    memset(&lite, 0, sizeof(lite_cjson_t));
    res = lite_cjson_parse(res_info, res_info_len, &lite);
    if (res < SUCCESS_RETURN) {
        ERROR_PRINT("Wrong JSON Format, Payload: %d", res_info_len);
        free(res_info);
        free(payload);
        return FAIL_RETURN;
    }

    //dm_client_publish(uri, (unsigned char *)payload, strlen(payload), NULL);
    kk_sendData2app(res_info, payload,0);

    free(res_info);
    free(payload);

    return SUCCESS_RETURN;
}

int dm_msg_response_parse(_IN_ char *payload, _IN_ int payload_len, _OU_ dm_msg_response_payload_t *response)
{
    lite_cjson_t lite, lite_message;

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

    if (kk_utils_json_parse(payload, payload_len, cJSON_Invalid, &lite) != SUCCESS_RETURN ||
        kk_utils_json_object_item(&lite, DM_MSG_KEY_ID, strlen(DM_MSG_KEY_ID), cJSON_Invalid, &response->id) != SUCCESS_RETURN ||
        kk_utils_json_object_item(&lite, DM_MSG_KEY_CODE, strlen(DM_MSG_KEY_CODE), cJSON_Invalid,
                                  &response->code) != SUCCESS_RETURN ||
        kk_utils_json_object_item(&lite, DM_MSG_KEY_DATA, strlen(DM_MSG_KEY_DATA), cJSON_Invalid,
                                  &response->data) != SUCCESS_RETURN) {
        ERROR_PRINT("Current Request parse faild \n");                          
        return FAIL_RETURN;
    }

    INFO_PRINT("Current Request Message ID: %.*s", response->id.value_length, response->id.value);
    INFO_PRINT("Current Request Message Code: %d", response->code.value_int);
    INFO_PRINT("Current Request Message Data: %.*s", response->data.value_length, response->data.value);

    memset(&lite_message, 0, sizeof(lite_cjson_t));
    if (kk_utils_json_object_item(&lite, DM_MSG_KEY_MESSAGE, strlen(DM_MSG_KEY_MESSAGE), cJSON_Invalid,
                                  &response->message) == SUCCESS_RETURN) {
        INFO_PRINT("Current Request Message Desc: %.*s", response->message.value_length, response->message.value);
    }

    return SUCCESS_RETURN;
}

static int dm_msg_request_parse(_IN_ char *payload, _IN_ int payload_len, _OU_ kk_msg_request_payload_t *request)
{
    lite_cjson_t lite;

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

    if (lite_cjson_parse(payload, payload_len, &lite) != SUCCESS_RETURN ||
        lite_cjson_object_item(&lite, KK_MSG_KEY_ID, strlen(KK_MSG_KEY_ID), &request->id) != SUCCESS_RETURN ||
        lite_cjson_object_item(&lite, KK_MSG_KEY_VERSION, strlen(KK_MSG_KEY_VERSION),
                                  &request->version) != SUCCESS_RETURN ||
        lite_cjson_object_item(&lite, KK_MSG_KEY_METHOD, strlen(KK_MSG_KEY_METHOD),
                                  &request->method) != SUCCESS_RETURN ||
        lite_cjson_object_item(&lite, KK_MSG_KEY_PARAMS, strlen(KK_MSG_KEY_PARAMS),
                                  &request->params) != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }

    INFO_PRINT("Current Request Message ID: %.*s", request->id.value_length, request->id.value);
    INFO_PRINT("Current Request Message Version: %.*s", request->version.value_length, request->version.value);
    INFO_PRINT("Current Request Message Method: %.*s", request->method.value_length, request->method.value);
    INFO_PRINT("Current Request Message Params: %.*s", request->params.value_length, request->params.value);

    return SUCCESS_RETURN;
}

int dm_msg_thing_syncinfo_reply(void){
        
    kk_msg_request_payload_t request;
    kk_msg_response_t response;
	dm_mgr_dev_node_t *node = NULL;
    char *info = NULL;
    int res = 0;

    memset(&request, 0, sizeof(kk_msg_request_payload_t));
    memset(&response, 0, sizeof(kk_msg_response_t));
    printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    res = dm_mgr_search_dev_by_devid(KK_DM_DEVICE_CCU_DEVICEID, &node);
    if (res != SUCCESS_RETURN) {
        printf("[%s][%d]\n",__FUNCTION__,__LINE__);
        return FAIL_RETURN;
    }
    printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    //res = dm_msg_request_parse((char *)payload, payload_len, &request);
    //if (res < SUCCESS_RETURN) {
		//ERROR_PRINT("dm_msg_request_parse failed");
        //return res ;
    //}
    printf("[%s][%d]\n",__FUNCTION__,__LINE__);
	response.msgTypeStr = KK_THING_SERVICE_SYNCINFO_REPLY;
    memcpy(response.productCode, node->productCode, strlen( node->productCode));	
    memcpy(response.deviceCode, node->deviceCode, strlen(node->deviceCode));
    response.code = (res == SUCCESS_RETURN) ? (IOTX_DM_ERR_CODE_SUCCESS) : (IOTX_DM_ERR_CODE_REQUEST_ERROR);
    printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    info = kk_sync_get_info();
    printf("[%s][%d]\n",__FUNCTION__,__LINE__);
	dm_msg_response(&request, &response, info, strlen(info), NULL);
    free(info);
	return SUCCESS_RETURN;
}
const char DM_URI_THING_SERVICE_PROPERTY_SET_REPLY[] = "/thing/service/property/set_reply";

int dm_msg_thing_property_set_reply(char deviceCode[DEVICE_CODE_MAXLEN],char *payload, unsigned int payload_len,
        void *context){
        
    kk_msg_request_payload_t request;
    kk_msg_response_t response;
	dm_mgr_dev_node_t *node = NULL;

    int res = 0;

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

    res = dm_mgr_get_device_by_devicecode(deviceCode, &node);
    if (res < SUCCESS_RETURN) {
		ERROR_PRINT("dm_mgr_search_device_by_pkdn failed");
        return res;
    }
    res = dm_msg_request_parse((char *)payload, payload_len, &request);
    if (res < SUCCESS_RETURN) {
		ERROR_PRINT("dm_msg_request_parse failed");
        return res ;
    }

	response.msgTypeStr = (char*)DM_URI_THING_SERVICE_PROPERTY_SET_REPLY;
    memcpy(response.productCode, node->productCode, strlen( node->productCode));	
    memcpy(response.deviceCode, node->deviceCode, strlen(node->deviceCode));
    response.code = (res == SUCCESS_RETURN) ? (IOTX_DM_ERR_CODE_SUCCESS) : (IOTX_DM_ERR_CODE_REQUEST_ERROR);
	dm_msg_response(&request, &response, "{}", strlen("{}"), NULL);
	return SUCCESS_RETURN;
}
int dm_msg_thing_event_post(const char *deviceCode, const char *identifier,const char *msgId)
{
	int res = 0;
	char *payload = NULL;
	dm_mgr_dev_node_t *node = NULL; 
    void *event = NULL;
	char *method = NULL;
	INFO_PRINT("dm_msg_thing_event_post enter\n");

	if(deviceCode == NULL){
		ERROR_PRINT("dm_msg_thing_event_post failed\n");
		return FAIL_RETURN;
	}
	
	res = dm_mgr_get_device_by_devicecode((char*)deviceCode, &node);
	if (res != SUCCESS_RETURN) {
		ERROR_PRINT("dm_msg_thing_event_post failed\n");
		return FAIL_RETURN;
	}
	payload = kk_tsl_get_post_event_str(node->dev_shadow,(char*)identifier,strlen(identifier));
	if(payload != NULL){
	    res = kk_tsl_get_event_by_identifier(node->dev_shadow, identifier, &event);
	    if (res != SUCCESS_RETURN) {
	        free(payload);
			ERROR_PRINT("dm_msg_thing_event_post failed\n");
			return FAIL_RETURN;

	    }	
	    res = kk_tsl_get_event_method(event, &method);
	    if (res != SUCCESS_RETURN) {
	        free(payload);
			ERROR_PRINT("dm_msg_thing_event_post failed\n");
			return FAIL_RETURN;
	    }		
		if(msgId != NULL){
	    	dm_mgr_upstream_thing_event_post_ex(node->devid, (char*)identifier, strlen(identifier), method, payload, strlen(payload),msgId);	

		}else
		{
	    	dm_mgr_upstream_thing_event_post(node->devid, identifier, strlen(identifier), method, payload, strlen(payload));	
		}
		free(method);
		method = NULL;
		free(payload);
		payload = NULL;
	}
	return SUCCESS_RETURN;
}
int dm_msg_scene_event_post(const char *identifier,kk_tsl_t *dev_shadow,const char *msgId)
{
	int res = 0; 
	char *payload = NULL;
    void *event = NULL;
	char *method = NULL;
	
	payload = kk_tsl_get_post_event_str(dev_shadow,identifier,strlen(identifier));
	if(payload != NULL){
	    res = kk_tsl_get_event_by_identifier(dev_shadow, identifier, &event);
	    if (res != SUCCESS_RETURN) {
	        free(payload);
			return FAIL_RETURN;

	    }	
	    res = kk_tsl_get_event_method(event, &method);
	    if (res != SUCCESS_RETURN) {
	        free(payload);
			return FAIL_RETURN;
	    }		
	    dm_mgr_upstream_thing_event_post_ex(KK_DM_DEVICE_CCU_DEVICEID, identifier, strlen(identifier), method, payload, strlen(payload),msgId);		
		free(method);
		method = NULL;
		free(payload);
		payload = NULL;
	}
	return SUCCESS_RETURN;
}

int dm_msg_thing_service_post(const char *deviceCode, const char *identifier)
{
	int res = 0;
	char *payload = NULL;
	dm_mgr_dev_node_t *node = NULL; 
	char *method = NULL;
    void *service = NULL;

	if(deviceCode == NULL){
		return FAIL_RETURN;
	}
	
	res = dm_mgr_get_device_by_devicecode(deviceCode, &node);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}
	payload = kk_tsl_get_post_service_str(node->dev_shadow,identifier);
	if(payload != NULL){	
	    res = kk_tsl_get_service_by_identifier(node->dev_shadow, identifier, &service);
	    if (res != SUCCESS_RETURN) {
	        free(payload);
			return FAIL_RETURN;

	    }			
		res = kk_tsl_get_service_method(service,&method);
	    if (res != SUCCESS_RETURN) {
	        free(payload);
			return FAIL_RETURN;
	    }		
	    dm_mgr_upstream_thing_service_post(node->devid, identifier, strlen(identifier),method, payload, strlen(payload));
		free(method);
		method = NULL;
		free(payload);
		payload = NULL;

	}
	return SUCCESS_RETURN;
}


int dm_msg_thing_property_post_all(char *deviceCode)
{
	int res = 0;
	char *payload = NULL;
	dm_mgr_dev_node_t *node = NULL; 

	if(deviceCode == NULL){
		return FAIL_RETURN;
	}
	
	res = dm_mgr_get_device_by_devicecode(deviceCode, &node);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}
	payload = kk_tsl_get_post_property_str(node->dev_shadow,NULL);//here need async post
	if(payload != NULL){
		dm_mgr_upstream_thing_property_post(node->devid, payload, strlen(payload),1);
		free(payload);
		payload = NULL;
	}
	return SUCCESS_RETURN;
}
int dm_msg_ccu_property_post(dm_mgr_dev_node_t *node)
{
	if(node == NULL){
		return INVALID_PARAMETER;

	}
	char *payload_property = kk_tsl_get_post_property_str(node->dev_shadow,NULL);
	if(payload_property != NULL){
		dm_mgr_upstream_thing_property_post(node->devid, payload_property, strlen(payload_property),0);
		free(payload_property);
		payload_property = NULL;
	}	
	return SUCCESS_RETURN;
}

int dm_msg_thing_property_post_by_identify(char *deviceCode,cJSON *params)
{
	int res = 0;
	int nums = 0;
	int idx = 0; 
	dm_mgr_dev_node_t *node = NULL; 
	kk_tsl_data_t *property = NULL;
	cJSON *propertyItem = NULL;
	char tmpValue[20] = {0};	
	if(params == NULL || deviceCode == NULL){
		return INVALID_PARAMETER;
	}
	
	res = dm_mgr_get_device_by_devicecode(deviceCode, &node);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}
	//printf("dm_msg_thing_property_post_by_identify:%s\n",params->valuestring);

	nums = node->dev_shadow->property_number;
	for(idx = 0; idx < nums; idx++){
		property = (kk_tsl_data_t *)(node->dev_shadow->properties + idx);
		if(property == NULL){
			continue;
		}
		propertyItem = cJSON_GetObjectItem(params, property->identifier);
		if(propertyItem != NULL){
			
			/*update the db data */
			if(property->data_value.type == KK_TSL_DATA_TYPE_INT ||
				property->data_value.type == KK_TSL_DATA_TYPE_ENUM||
				property->data_value.type == KK_TSL_DATA_TYPE_BOOL){
				sprintf(tmpValue,"%d",property->data_value.value_int);
				kk_property_db_update_value(deviceCode,property->identifier,tmpValue);
			}
			else if(property->data_value.type == KK_TSL_DATA_TYPE_FLOAT){
				sprintf(tmpValue,"%f",property->data_value.value_float);
				kk_property_db_update_value(deviceCode,property->identifier,tmpValue);
			}
			else if(property->data_value.type == KK_TSL_DATA_TYPE_DOUBLE){
				sprintf(tmpValue,"%f",property->data_value.value_double);
				kk_property_db_update_value(deviceCode,property->identifier,tmpValue);
			}	
			else if(property->data_value.type == KK_TSL_DATA_TYPE_TEXT||
				property->data_value.type == KK_TSL_DATA_TYPE_DATE){
				kk_property_db_update_value(deviceCode,property->identifier,property->data_value.value);
			
			}
			else if(property->data_value.type == KK_TSL_DATA_TYPE_STRUCT){
				kk_tsl_data_value_complex_t *complex_struct = NULL;
				int index = 0;	
			    kk_tsl_data_t *current_data = NULL;
				cJSON *propertyItem_1 = NULL;
				char tmp_identifiers[256] = {0};
				complex_struct = property->data_value.value;
			    for (index = 0; index < complex_struct->size; index++) {
			        current_data = (kk_tsl_data_t *)complex_struct->value + index;
					propertyItem_1 = cJSON_GetObjectItem(propertyItem, current_data->identifier);
					if(propertyItem_1 != NULL){
						memset(tmp_identifiers,0x0,sizeof(tmp_identifiers));
						sprintf(tmp_identifiers,"%s.%s",property->identifier,current_data->identifier);
						if(current_data->data_value.type == KK_TSL_DATA_TYPE_INT ||
							current_data->data_value.type == KK_TSL_DATA_TYPE_ENUM||
							current_data->data_value.type == KK_TSL_DATA_TYPE_BOOL){
							sprintf(tmpValue,"%d",current_data->data_value.value_int);
							kk_property_db_update_value(deviceCode,tmp_identifiers,tmpValue);
						}
						else if(current_data->data_value.type == KK_TSL_DATA_TYPE_FLOAT){
							sprintf(tmpValue,"%f",current_data->data_value.value_float);
							kk_property_db_update_value(deviceCode,tmp_identifiers,tmpValue);
						}
						else if(current_data->data_value.type == KK_TSL_DATA_TYPE_DOUBLE){
							sprintf(tmpValue,"%u",current_data->data_value.value_double);
							kk_property_db_update_value(deviceCode,tmp_identifiers,tmpValue);
						}	
						else if(current_data->data_value.type == KK_TSL_DATA_TYPE_TEXT||
							current_data->data_value.type == KK_TSL_DATA_TYPE_DATE){
							kk_property_db_update_value(deviceCode,tmp_identifiers,current_data->data_value.value);
						}	
						else if(current_data->data_value.type == KK_TSL_DATA_TYPE_STRUCT){
							kk_tsl_data_value_complex_t *complex_struct_1 = NULL;
							complex_struct_1 = current_data->data_value.value;
							int index1 = 0;
							kk_tsl_data_t *current_data_1 = NULL;
							cJSON *propertyItem_2 = NULL;
							for(index1 = 0; index1 < complex_struct_1->size; index1++){
								current_data_1 = (kk_tsl_data_t *)complex_struct_1->value + index1;
								propertyItem_2 = cJSON_GetObjectItem(propertyItem_1, current_data_1->identifier);
								if(propertyItem_2 != NULL){
									memset(tmp_identifiers,0x0,sizeof(tmp_identifiers));
									sprintf(tmp_identifiers,"%s.%s.%s",property->identifier,current_data->identifier,current_data_1->identifier);
									if(current_data_1->data_value.type == KK_TSL_DATA_TYPE_INT ||
										current_data_1->data_value.type == KK_TSL_DATA_TYPE_ENUM||
										current_data_1->data_value.type == KK_TSL_DATA_TYPE_BOOL){
										sprintf(tmpValue,"%d",current_data_1->data_value.value_int);
										kk_property_db_update_value(deviceCode,tmp_identifiers,tmpValue);
									}
									else if(current_data_1->data_value.type == KK_TSL_DATA_TYPE_FLOAT){
										sprintf(tmpValue,"%f",current_data_1->data_value.value_float);
										kk_property_db_update_value(deviceCode,tmp_identifiers,tmpValue);
									}
									else if(current_data_1->data_value.type == KK_TSL_DATA_TYPE_DOUBLE){
										sprintf(tmpValue,"%u",current_data_1->data_value.value_double);
										kk_property_db_update_value(deviceCode,tmp_identifiers,tmpValue);
									}	
									else if(current_data_1->data_value.type == KK_TSL_DATA_TYPE_TEXT||
										current_data_1->data_value.type == KK_TSL_DATA_TYPE_DATE){
										kk_property_db_update_value(deviceCode,tmp_identifiers,current_data_1->data_value.value);
									}
									else{
										ERROR_PRINT("Unsupport Type ~~\n");
									}

								}

							}
						}
						else{
							ERROR_PRINT("Unsupport  Type\n");
						}

					}
			    }				
			}
			else{
				ERROR_PRINT("Unkonwn Number Type");
			}		
		}
	}
	char* outstr = cJSON_Print(params);
	dm_mgr_upstream_thing_property_post(node->devid,outstr,strlen(outstr),0);
	free(outstr);
	return SUCCESS_RETURN;

}

int kk_msg_execute_property_set(const char *productCode,const char *deviceCode,const char* params,const char *fatherDeviceCode)
{
	char *method = "thing.service.property.set";
	char *req_info = NULL,*payload = NULL;
	int req_info_len = 0,payload_len = 0;
	char msgId[MSG_MAX_LEN] = {0};

	req_info_len = strlen(DM_MSG_INFO)+10+strlen(productCode)+strlen(productCode)+strlen(KK_THING_SERVICE_PROPERTY_SET)+1;
    req_info = malloc(req_info_len);
    if (req_info == NULL) {
        return MEMORY_NOT_ENOUGH;
    }
    memset(req_info, 0, req_info_len);
    snprintf(req_info, req_info_len, DM_MSG_INFO, KK_THING_SERVICE_PROPERTY_SET,productCode, deviceCode);

    payload_len = strlen(DM_MSG_REQUEST) + 10 + strlen(DM_MSG_VERSION) + strlen(params) + strlen(
                              method) + 1 + 20 + sizeof(msgId);
    payload = malloc(payload_len);
    if (payload == NULL) {
		free(req_info);
        return MEMORY_NOT_ENOUGH;
    }
    memset(payload, 0, payload_len);
	sprintf(msgId,"%d",iotx_report_id());	
    snprintf(payload, payload_len, DM_MSG_REQUEST, msgId,
                 DM_MSG_VERSION, params,HAL_GetTime(), method);

    cJSON *root=cJSON_CreateObject();
    cJSON* infoObj = cJSON_Parse(req_info);
    cJSON* payloadObj = cJSON_Parse(payload);
    cJSON_AddItemToObject(root, "info", infoObj);
    cJSON_AddItemToObject(root, "payload",payloadObj);
	void *buf = cJSON_Print(root);
	kk_sendData2gw(buf, strlen(buf), fatherDeviceCode);
	free(buf);
	free(req_info);
	free(payload);
	cJSON_Delete(root);
	return SUCCESS_RETURN;

}


int kk_msg_execute_property_get(dm_mgr_dev_node_t *node)
{
	char *method = "thing.service.property.get";
	char *req_info = NULL,*payload = NULL;
	int req_info_len = 0,payload_len = 0;
	int res = 0;
	int needFree = 0;
	int i = 0,j = 0,serviceNum = 0;
	char *paramS = NULL;
	char msgId[MSG_MAX_LEN] = {0};

	if(node == NULL){
		return INVALID_PARAMETER;
	}
	req_info_len = strlen(DM_MSG_INFO)+10+strlen(node->productCode)+strlen(node->productCode)+strlen(KK_THING_SERVICE_PROPERTY_SET)+1;
    req_info = malloc(req_info_len);
    if (req_info == NULL) {
        return MEMORY_NOT_ENOUGH;
    }
    memset(req_info, 0, req_info_len);
    snprintf(req_info, req_info_len, DM_MSG_INFO, KK_THING_SERVICE_PROPERTY_GET,node->productCode, node->deviceCode);

	cJSON *rootParam = cJSON_CreateObject();
	cJSON *array = cJSON_CreateArray();

	serviceNum = node->dev_shadow->service_number;
	for(i = 0; i < serviceNum; i++){ 
		kk_tsl_service_t *item = node->dev_shadow->services + i;
		if(!strcmp(item->identifier,"get")){
			
			int inputNum = item->input_data_number;
			if(inputNum == 0){
				paramS = "{}";
				
			}else{
				for(j = 0; j < inputNum; j++){
					kk_tsl_data_t *inputItem = item->input_datas + j;
					cJSON_AddItemToArray(array,cJSON_CreateString(inputItem->identifier));
				}
				cJSON_AddItemToObject(rootParam, KK_TSL_KEY_IDENTIFIER, array);
				paramS = cJSON_Print(rootParam);
				needFree = 1;
			}
			break;
		}	
	}

    payload_len = strlen(DM_MSG_REQUEST) + 10 + strlen(DM_MSG_VERSION) + strlen(paramS) + strlen(
                              method) + 1 + 20+sizeof(msgId);
    payload = malloc(payload_len);
    if (payload == NULL) {
		free(req_info);
        return MEMORY_NOT_ENOUGH;
    }
    memset(payload, 0, payload_len);
	sprintf(msgId,"%d",iotx_report_id());
    snprintf(payload, payload_len, DM_MSG_REQUEST, msgId,
                 DM_MSG_VERSION, paramS,HAL_GetTime(), method);
    cJSON *root=cJSON_CreateObject();
    cJSON* infoObj = cJSON_Parse(req_info);
    cJSON* payloadObj = cJSON_Parse(payload);
    cJSON_AddItemToObject(root, "info", infoObj);
    cJSON_AddItemToObject(root, "payload",payloadObj);
	void *buf = cJSON_Print(root);
	if(node->dev_type == KK_DM_DEVICE_GATEWAY)
		kk_sendData2gw(buf, strlen(buf), node->deviceCode);
	else
		kk_sendData2gw(buf, strlen(buf), node->fatherDeviceCode);

	if(needFree){
		free(paramS);
	}	
	free(buf);
	free(req_info);
	free(payload);

	cJSON_Delete(root);
	cJSON_Delete(rootParam);
	return SUCCESS_RETURN;

}


int kk_msg_parse_productType(char *str,char *productType)
{
	cJSON *item = NULL;
	cJSON *json=cJSON_Parse(str);
	if(json == NULL){
		return FAIL_RETURN;
	}
	item = cJSON_GetObjectItem(json, KK_TSL_KEY_PRODUCTTYPE);
	if(item != NULL&&strlen(item->valuestring) < PRODUCT_TYPE_MAXLEN){
		memcpy(productType,item->valuestring,strlen(item->valuestring));
	}
	 cJSON_Delete(json);
	return SUCCESS_RETURN;
	
}

int kk_msg_execute_scene_set(const char* params,const char *fatherDeviceCode,int isUpdate)
{
	int res = 0;
	char *method = KK_THING_METHOD_ADDSCENC;
	char *msgType = KK_THING_SERVICE_ADDSCENC;	
	char *req_info = NULL,*payload = NULL;
	int req_info_len = 0,payload_len = 0;
    dm_mgr_dev_node_t *node = NULL;
	char msgId[MSG_MAX_LEN] = {0};
	
	if(isUpdate){
		method = KK_THING_METHOD_UPDATESCENC;
		msgType = KK_THING_SERVICE_UPDATESCENC;
	}
	res = dm_mgr_get_device_by_devicecode(fatherDeviceCode,&node);
    if (res != SUCCESS_RETURN) {
		ERROR_PRINT("ERROR [%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
        return FAIL_RETURN;
    }

	req_info_len = strlen(DM_MSG_INFO)+10+strlen(node->productCode)+strlen(fatherDeviceCode)+strlen(msgType)+1;
    req_info = malloc(req_info_len);
    if (req_info == NULL) {
        return MEMORY_NOT_ENOUGH;
    }
    memset(req_info, 0, req_info_len);
    snprintf(req_info, req_info_len, DM_MSG_INFO, msgType,node->productCode, fatherDeviceCode);

    payload_len = strlen(DM_MSG_REQUEST) + 10 + strlen(DM_MSG_VERSION) + strlen(params) + strlen(
                              method) + 1 + 20 + sizeof(msgId);
    payload = malloc(payload_len);
    if (payload == NULL) {
		free(req_info);
        return MEMORY_NOT_ENOUGH;
    }
    memset(payload, 0, payload_len);
	sprintf(msgId,"%d",iotx_report_id());	
    snprintf(payload, payload_len, DM_MSG_REQUEST, msgId,
                 DM_MSG_VERSION, params,HAL_GetTime(), method);

    cJSON *root=cJSON_CreateObject();
    cJSON* infoObj = cJSON_Parse(req_info);
    cJSON* payloadObj = cJSON_Parse(payload);
    cJSON_AddItemToObject(root, "info", infoObj);
    cJSON_AddItemToObject(root, "payload",payloadObj);
	void *buf = cJSON_Print(root);
	kk_sendData2gw(buf, strlen(buf), fatherDeviceCode);
	free(buf);
	free(req_info);
	free(payload);
	cJSON_Delete(root);
	return SUCCESS_RETURN;

}

int kk_msg_execute_scene_action(const char* params,const char *fatherDeviceCode)
{
	int res = 0;
	char *method = KK_THING_METHOD_EXECUTESCENE;
	char *req_info = NULL,*payload = NULL;
	int req_info_len = 0,payload_len = 0;
	char msgId[MSG_MAX_LEN] = {0};

    dm_mgr_dev_node_t *node = NULL;
	res = dm_mgr_get_device_by_devicecode(fatherDeviceCode,&node);
    if (res != SUCCESS_RETURN) {
		ERROR_PRINT("ERROR [%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
        return FAIL_RETURN;
    }

	req_info_len = strlen(DM_MSG_INFO)+10+strlen(node->productCode)+strlen(fatherDeviceCode)+strlen(KK_THING_SERVICE_EXECUTESCENE)+1;
    req_info = malloc(req_info_len);
    if (req_info == NULL) {
        return MEMORY_NOT_ENOUGH;
    }
    memset(req_info, 0, req_info_len);
    snprintf(req_info, req_info_len, DM_MSG_INFO, KK_THING_SERVICE_EXECUTESCENE,node->productCode, fatherDeviceCode);

    payload_len = strlen(DM_MSG_REQUEST) + 10 + strlen(DM_MSG_VERSION) + strlen(params) + strlen(
                              method) + 1 + 20 + sizeof(msgId);
    payload = malloc(payload_len);
    if (payload == NULL) {
		free(req_info);
        return MEMORY_NOT_ENOUGH;
    }
    memset(payload, 0, payload_len);
	sprintf(msgId,"%d",iotx_report_id());		
    snprintf(payload, payload_len, DM_MSG_REQUEST, msgId,
                 DM_MSG_VERSION, params,HAL_GetTime(), method);

    cJSON *root=cJSON_CreateObject();
    cJSON* infoObj = cJSON_Parse(req_info);
    cJSON* payloadObj = cJSON_Parse(payload);
    cJSON_AddItemToObject(root, "info", infoObj);
    cJSON_AddItemToObject(root, "payload",payloadObj);
	void *buf = cJSON_Print(root);
	kk_sendData2gw(buf, strlen(buf), fatherDeviceCode);
	free(buf);
	free(req_info);
	free(payload);
	cJSON_Delete(root);
	return SUCCESS_RETURN;

}

int kk_msg_execute_scene_delete(const char* params,const char *fatherDeviceCode)
{
	int res = 0;
	char *method = KK_THING_METHOD_DELETESCENC;
	char *req_info = NULL,*payload = NULL;
	int req_info_len = 0,payload_len = 0;
	char msgId[MSG_MAX_LEN] = {0};

    dm_mgr_dev_node_t *node = NULL;
	res = dm_mgr_get_device_by_devicecode(fatherDeviceCode,&node);
    if (res != SUCCESS_RETURN) {
		ERROR_PRINT("ERROR [%s][%d] res:%d\n",__FUNCTION__,__LINE__,res);
        return FAIL_RETURN;
    }

	req_info_len = strlen(DM_MSG_INFO)+10+strlen(node->productCode)+strlen(fatherDeviceCode)+strlen(KK_THING_SERVICE_DELETESCENC)+1;
    req_info = malloc(req_info_len);
    if (req_info == NULL) {
        return MEMORY_NOT_ENOUGH;
    }
    memset(req_info, 0, req_info_len);
    snprintf(req_info, req_info_len, DM_MSG_INFO, KK_THING_SERVICE_DELETESCENC,node->productCode, fatherDeviceCode);

    payload_len = strlen(DM_MSG_REQUEST) + 10 + strlen(DM_MSG_VERSION) + strlen(params) + strlen(
                              method) + 1 + 20 + sizeof(msgId);
    payload = malloc(payload_len);
    if (payload == NULL) {
		free(req_info);
        return MEMORY_NOT_ENOUGH;
    }
    memset(payload, 0, payload_len);
	sprintf(msgId,"%d",iotx_report_id());
    snprintf(payload, payload_len, DM_MSG_REQUEST, msgId,
                 DM_MSG_VERSION, params,HAL_GetTime(), method);

    cJSON *root=cJSON_CreateObject();
    cJSON* infoObj = cJSON_Parse(req_info);
    cJSON* payloadObj = cJSON_Parse(payload);
    cJSON_AddItemToObject(root, "info", infoObj);
    cJSON_AddItemToObject(root, "payload",payloadObj);
	void *buf = cJSON_Print(root);
	printf("----------------->buf:%s\n",buf);
	kk_sendData2gw(buf, strlen(buf), fatherDeviceCode);
	free(buf);
	free(req_info);
	free(payload);
	cJSON_Delete(root);
	return SUCCESS_RETURN;

}

