#include "kk_dm_msg.h"
#include "kk_dm_mng.h"
#include "kk_tsl_api.h"

#include "lite-cjson.h"
#include "cJSON.h"
#include "com_api.h"
#include "kk_log.h"


const char DM_MSG_REQUEST[] DM_READ_ONLY = "{\"msgId\":\"%d\",\"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){
    cJSON *root=cJSON_CreateObject();
    cJSON* infoObj = cJSON_Parse(info);
    cJSON* payloadObj = cJSON_Parse(payload);
    cJSON_AddItemToObject(root, "info", infoObj);
    cJSON_AddItemToObject(root, "payload",payloadObj);	
    void *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 timestamp[DM_UTILS_UINT64_STRLEN] = {0};
    char client_id[PRODUCT_TYPE_MAXLEN + DEVICE_CODE_MAXLEN + 1] = {0};
    char *sign_source = NULL;
    int sign_source_len = 0;
    char *sign_method = DM_MSG_SIGN_METHOD_HMACSHA1;
    char sign[65] = {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};
	 char client_id[PRODUCT_TYPE_MAXLEN + DEVICE_CODE_MAXLEN + 20] = {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); */
 

	 /* 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};
   char client_id[PRODUCT_TYPE_MAXLEN + DEVICE_CODE_MAXLEN + 20] = {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); */


   /* 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;
    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: %s", 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: %s", 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;
}

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, devid = 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 = 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)
{
	int res = 0;
	int nums = 0;
	int idx = 0; 
	char *payload = NULL;
	dm_mgr_dev_node_t *node = NULL; 
    void *event = NULL;
	char *method = 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_event_str(node->dev_shadow,identifier,strlen(identifier));
	if(payload != NULL){
	    res = kk_tsl_get_event_by_identifier(node->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(node->devid, identifier, strlen(identifier), method, payload, strlen(payload));		
		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;
	int nums = 0;
	int idx = 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;
	int nums = 0;
	int idx = 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_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 FAIL_RETURN;
	}
	
	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,"%u",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;

	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;
    payload = malloc(payload_len);
    if (payload == NULL) {
		free(req_info);
        return MEMORY_NOT_ENOUGH;
    }
    memset(payload, 0, payload_len);
    snprintf(payload, payload_len, DM_MSG_REQUEST, iotx_report_id(),
                 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);

}

