/************************************************************
*版权所有 （C）2020，公司（或个人）名称
*
*文件名称： kcloud_data_handle.c
*内容摘要： application层数据处理
*其他说明： 
*当前版本：  
*************************************************************/
 
/*************************************************************
头文件引用 
*************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mqtt_api.h"
#include "com_api.h"
#include "cJSON.h"
#include "kk_product.h"
//#include "kcloud_log.h"

#define KK_FILTER_TOPO_TOPIC 		           "/thing/topo/"
#define KK_FILTER_TOPO_REPLY 		           "_reply"
#define KK_FILTER_DELETE_TOPIC                 "/thing/topo/delete"
#define KK_FILTER_DELETE_TOPIC_REPLY           "/thing/topo/delete_reply"
#define KK_FILTER_REGISTER_TOPIC               "/thing/sub/register"
#define KK_FILTER_REGISTER_TOPIC_REPLY         "/thing/sub/register_reply"
#define KK_FILTER_LOGIN_TOPIC                  "/thing/combine/login"
#define KK_FILTER_LOGIN_TOPIC_REPLY            "/thing/combine/login_reply"
#define KK_FILTER_SET_TOPIC                    "/thing/service/property/set"
#define KK_FILTER_SET_TOPIC_REPLY              "/thing/service/property/set_reply"
#define KK_FILTER_EVENT_POST_TOPIC1            "/thing/event/"
#define KK_FILTER_EVENT_POST_TOPIC2            "/post"
#define KK_FILTER_EVENT_POST_REPLY             "/post_reply"
#define KK_FILTER_STATUS_ONLINE                "/thing/status/online"
#define KK_FILTER_STATUS_ONLINE_REPLY          "/thing/status/online_reply"
#define KK_FILTER_STATUS_OFFLINE               "/thing/status/offline"
#define KK_FILTER_STATUS_OFFLINE_REPLY         "/thing/status/offline_reply"
#define KK_FILTER_TOPO_BATCH_DELETE            "/thing/topo/batch_delete"
#define KK_FILTER_TOPO_CHANEG_REPLY            "/thing/topo/change_reply"

#define KK_CLOUDSTATE_MSG                      "/thing/ccu/cloudstate"
#define KK_CLOUDSTATE_MSG_REPLY                "/thing/ccu/cloudstate_reply"
#define KK_CLOUDHB_MSG                         "/thing/ccu/cloudHB"
#define KK_CLOUDHB_MSG_REPLY                   "/thing/ccu/cloudHB_reply"
#define KK_TOPO_CHANGE_MSG_STR                 "/thing/topo/change"
#define KK_FILTER_SERVICE_CALL_TOPIC          "/thing/service/"
#define KK_FILTER_SERVICE_CALL_REPLY           "_reply"

const char DM_MSG_TO_MIDDWARE[] = "{\"msgtype\":\"%s\",\"productCode\":\"%s\",\"deviceCode\":\"%s\"}";
#define KK_TOPIC_SERVICE_DELIMITER 			  '/'
#define KK_POWER_SWITCH_1      		"PowerSwitch_1"
#define KK_POWER_SWITCH_2      		"PowerSwitch_2"
#define KK_POWER_SWITCH_3      		"PowerSwitch_3"
#define KK_POWER_SWITCH_4      		"PowerSwitch_4"
extern char* KK_Make_Topic(cJSON *info,cJSON *data);
extern int KK_Subdev_UnSubscribe(cJSON *payload);
extern int KK_Subdev_UnSubscribe_By_DeviceCode(const char *deviceCode,const char *productCode );
extern int KK_Subdev_Subscribe(const cJSON *root);
int KK_Send_CloudState(int state);

static char *s_split_product[] = {
	"3002", 		//星辰系列双路面板
	"3003",         //星辰系列三路面板
	"3010",			//铂金系列双路面板
	"3011",			//铂金系列三路面板	
	"3023",			//肖邦系列双路面板
	"3024"			//肖邦系列三路面板	
};

static int kk_utils_memtok(_IN_ char *input, _IN_ int input_len, _IN_ char delimiter, _IN_ int index, _OU_ int *offset)
{
	int item_index = 0;
	int count = 0;

	if (input == NULL || input_len <= 0 || offset == NULL) {
		return -2;
	}

	for (item_index = 0; item_index < input_len; item_index++) {
		if (input[item_index] == delimiter && (item_index + 1) < input_len) {
			count++;
			if (count == index) {
				*offset = item_index;
				return 0;
			}
		}
	}

	return -1;
}
/************************************************************
*功能描述：灯控面板需要分开上报属性
*输入参数： info：所上报数据
*输出参数： 无
*返 回 值：  1：需要拆分；0：不需要
*其他说明：
*************************************************************/
static int kk_check_need_split(cJSON * info)
{
	//return 0;//暂时不用拆分处理
#if 1	
	cJSON *productCode = NULL;
	int i = 0;
	int num = sizeof(s_split_product)/sizeof(char*);

	if(info == NULL){
		return 0;
	}
	productCode = cJSON_GetObjectItem(info, MSG_PRODUCT_CODE_STR);
	if(productCode == NULL){
		return 0;
	}
	for(i = 0; i < num; i++){
		if(strncmp(s_split_product[i],productCode->valuestring,strlen(productCode->valuestring)) == 0){
			return 1;
		}
	}
	return 0;
#endif	
}

/************************************************************
*功能描述：灯控面板拆分具体的属性并逐个上报
*输入参数： pData：所上报数据
		  topic：主题
*输出参数： 无
*返 回 值：  0：成功；其他：失败
*其他说明：
*************************************************************/
static int kk_split_send_data(cJSON *pData,const char* topic)
{ 
	cJSON *pParam = NULL;
	cJSON *pParam_new = NULL;	
	cJSON *powerswitch1 = NULL;
	cJSON *powerswitch2 = NULL;	
	cJSON *powerswitch3 = NULL;	
	cJSON *powerswitch4 = NULL;	
	if(pData == NULL){
		return RETURN_FAIL;
	}
	pParam = cJSON_GetObjectItem(pData, MSG_PARAMS_STR);
	if(pParam == NULL){
		return RETURN_FAIL;
	}	
	char* param_tmp = cJSON_Print(pParam);		
	powerswitch1 = cJSON_GetObjectItem(pParam, KK_POWER_SWITCH_1);
	if(powerswitch1 != NULL){
		cJSON_DeleteItemFromObject(pData,MSG_PARAMS_STR);
		cJSON *pParam_new = cJSON_CreateObject();
	 	cJSON_AddNumberToObject(pParam_new, "PowerSwitch", powerswitch1->valueint);
		cJSON_AddStringToObject(pParam_new, "epNum", "1");
		cJSON_AddItemToObject(pData,MSG_PARAMS_STR,pParam_new);
		char* out=cJSON_Print(pData);
		KK_MQTT_SendMsg((char*)topic,(const char*)out);	
		free(out);
		
	}
	pParam = cJSON_Parse(param_tmp);
	powerswitch2 = cJSON_GetObjectItem(pParam, KK_POWER_SWITCH_2);
	if(powerswitch2 != NULL){
		cJSON_DeleteItemFromObject(pData,MSG_PARAMS_STR);
		pParam_new = cJSON_CreateObject();
	 	cJSON_AddNumberToObject(pParam_new, "PowerSwitch", powerswitch2->valueint);
		cJSON_AddStringToObject(pParam_new, "epNum", "2");
		cJSON_AddItemToObject(pData,MSG_PARAMS_STR,pParam_new);
		char* out=cJSON_Print(pData);
		KK_MQTT_SendMsg((char*)topic,(const char*)out);	
		free(out);
	}	
	powerswitch3 = cJSON_GetObjectItem(pParam, KK_POWER_SWITCH_3);
	if(powerswitch3 != NULL){
		cJSON_DeleteItemFromObject(pData,MSG_PARAMS_STR);
		pParam_new = cJSON_CreateObject();
	 	cJSON_AddNumberToObject(pParam_new, "PowerSwitch", powerswitch3->valueint);
		cJSON_AddStringToObject(pParam_new, "epNum", "3");
		cJSON_AddItemToObject(pData,MSG_PARAMS_STR,pParam_new);
		char* out=cJSON_Print(pData);
		KK_MQTT_SendMsg((char*)topic,(const char*)out);	
		free(out);
	}	
	powerswitch4 = cJSON_GetObjectItem(pParam, KK_POWER_SWITCH_4);
	if(powerswitch4 != NULL){
		cJSON_DeleteItemFromObject(pData,MSG_PARAMS_STR);
		pParam_new = cJSON_CreateObject();
	 	cJSON_AddNumberToObject(pParam_new, "PowerSwitch", powerswitch4->valueint);
		cJSON_AddStringToObject(pParam_new, "epNum", "4");
		cJSON_AddItemToObject(pData,MSG_PARAMS_STR,pParam_new);
		char* out=cJSON_Print(pData);
		KK_MQTT_SendMsg((char*)topic,(const char*)out);	
		free(out);
	}	
	free(param_tmp);
	return RETURN_SUCCESS;
	
}
char * g_filerToCloudTable[] = 
{
	(char *){"/thing/service/historyAlarm_reply"},	
	(char *){"/thing/service/delAlarm_reply"},
	(char *){"/thing/service/syncinfo_reply"},
	(char *){"/thing/service/syncinfopush_reply"},
	(char *){"/thing/service/clientReport_reply"},	
	(char *){"/thing/service/clientOnlinePush"},
	(char *){"/thing/service/getClientInfo_reply"},
	(char *){"/thing/topo/change_reply"},
};
/************************************************************
*功能描述：过滤不需要下发给网关的消息
*输入参数：msgtype：消息类型
*输出参数：无
*返 回 值：1:过滤；0：不过滤
*其他说明：
*************************************************************/
static int _kk_filter_to_cloud(const char* msgtype)
{
	int i = 0,num = 0;
	num = sizeof(g_filerToCloudTable)/sizeof(char *);
	for(i =0; i < num; i++){
		if(strstr(msgtype,g_filerToCloudTable[i]))
		{
			return 1;
		}
	}
	return 0;
}
/************************************************************
*功能描述：上报数据给云端
*输入参数： root：所上报数据
*输出参数： 无
*返 回 值：  0：成功；其他：失败
*其他说明：
*************************************************************/

int _kk_sendto_cloud(cJSON *root)
{
	cJSON *info,*pData;
	char *topic = NULL;
	cJSON *msgTypeStr = NULL;
	info = cJSON_GetObjectItem(root, MSG_INFO_STR);
	if(info == NULL){
		return RETURN_FAIL;
	}
	msgTypeStr = cJSON_GetObjectItem(info, MSG_TYPE_STR);
	if(msgTypeStr == NULL){
		return RETURN_FAIL;
	}	
	if(_kk_filter_to_cloud(msgTypeStr->valuestring)){
		INFO_PRINT(" this msg do not send to cloud!!!\n");
		return RETURN_FAIL;
	}
	pData = cJSON_GetObjectItem(root, MSG_PAYLOAD_STR);
	if(pData == NULL){
		free(topic);
		return RETURN_FAIL;
	}
	topic = KK_Make_Topic(info,pData);
	if(topic == NULL){
		return RETURN_FAIL;
	}	
	//If topo delete,need UnSubscribe the topic
	if(strstr(msgTypeStr->valuestring,KK_FILTER_DELETE_TOPIC) != NULL){
		KK_Subdev_UnSubscribe(pData);
		char* out=cJSON_Print(pData);
		KK_MQTT_SendMsg(topic,(const char*)out);	
		free(out);		
		free(topic);
		return RETURN_SUCCESS;
	}
	else if(strstr(msgTypeStr->valuestring,KK_FILTER_TOPO_BATCH_DELETE) != NULL){
		cJSON *params = NULL;
		params = cJSON_GetObjectItem(pData, MSG_PARAMS_STR);
		if(params != NULL){
			cJSON * devices = cJSON_GetObjectItem(params, MSG_TOPO_CHANGE_DEVICES_STR);
			if(devices != NULL){
				cJSON * item = devices->child;
				while(item != NULL){
					char *deviceCode = cJSON_GetObjectItem(item,MSG_DEVICE_CODE_STR)->valuestring;
					char *productCode = cJSON_GetObjectItem(item,MSG_PRODUCT_CODE_STR)->valuestring;
					KK_Subdev_UnSubscribe_By_DeviceCode(deviceCode,productCode);
					item = item->next;
				} 
			}	
		}
		char* out=cJSON_Print(pData);
		KK_MQTT_SendMsg(topic,(const char*)out);	
		free(out);		
		free(topic);
		return RETURN_SUCCESS;
	}
	else if(strstr(msgTypeStr->valuestring,KK_CLOUDSTATE_MSG) != NULL){
		KK_Send_CloudState(kk_get_cloud_status());
		free(topic);
		return RETURN_SUCCESS;
	}
	else if(strstr(msgTypeStr->valuestring,KK_CLOUDHB_MSG) != NULL){
		KK_Send_CloudHB2Mid(1);
		free(topic);
		return RETURN_SUCCESS;
	}
	//if(kk_check_need_split(info)){
		//kk_split_send_data(pData,topic);
	//}
	//else
	{
		#if 0
		cJSON *pParam = NULL;
		cJSON *PowerSwitch = NULL;
		int i = 0;
		int tmpPS[32] = {0};
		int tmpIdx[4] = {0};
		pParam = cJSON_GetObjectItem(pData, MSG_PARAMS_STR);
		if(pParam == NULL){
			return RETURN_FAIL;
		}	
		for(i = 0; i < 64; i++){
			sprintf(tmpPS,"PowerSwitch_%d",i);
			PowerSwitch = cJSON_GetObjectItem(pParam, tmpPS);
			if(PowerSwitch != NULL){
				cJSON_DeleteItemFromObject(pParam,tmpPS);
				sprintf(tmpIdx,"%d",i);
				cJSON_AddNumberToObject(pParam, "PowerSwitch", PowerSwitch->valueint);
				cJSON_AddStringToObject(pParam, "epNum", tmpIdx);
				break;
			}
		}
		#endif
		char* out=cJSON_Print(pData);
		
		KK_MQTT_SendMsg(topic,(const char*)out);	
		free(out);
	}
	free(topic);
	return RETURN_SUCCESS;
}

/************************************************************
*功能描述：获取midware上报的数据
*输入参数： str：所上报数据
          len：数据长度
*输出参数： 无
*返 回 值：  无
*其他说明：
*************************************************************/

void KK_Data_FromDev(void* str,int len)
{
	cJSON *root,*cmd;
	if(str == NULL){
		return;
	}
	
	INFO_PRINT("KK_Data_FromDev--->\n%s\n",str);
	root=cJSON_Parse((char*)str);
	if(root == NULL){
		ERROR_PRINT("[%s][%d] root is null \n",__FUNCTION__,__LINE__);
		return;
	}
	cmd = cJSON_GetObjectItem(root, "cmd");
	if(cmd == NULL){
		_kk_sendto_cloud(root);
	}
	else{
		KK_Subdev_Subscribe(root);
	}
	cJSON_Delete(root);

}
/************************************************************
*功能描述：无效主题过滤
*输入参数： topic：主题
*输出参数： 无
*返 回 值：  1：过滤；0：不过滤
*其他说明：
*************************************************************/

static int _check_invalid_topic(const char* topic)
{
	if(strstr(topic, KK_FILTER_TOPO_TOPIC) != NULL && \
		strstr(topic,KK_FILTER_TOPO_REPLY) == NULL && \
		 strstr(topic,KK_TOPO_CHANGE_MSG_STR) == NULL){
		return 1;
	}
	else if(strstr(topic, KK_FILTER_REGISTER_TOPIC) != NULL && \
		strstr(topic,KK_FILTER_REGISTER_TOPIC_REPLY) == NULL){
		return 1;
	}		
	else if(strstr(topic, KK_FILTER_LOGIN_TOPIC) != NULL && \
		strstr(topic,KK_FILTER_LOGIN_TOPIC_REPLY) == NULL){
		return 1;
	}		
	else if(strstr(topic,KK_FILTER_TOPO_CHANEG_REPLY) != NULL){
		return 1;
	}
	else if(strstr(topic, KK_FILTER_EVENT_POST_TOPIC1) != NULL && \
		strstr(topic,KK_FILTER_EVENT_POST_TOPIC2) != NULL && \
		strstr(topic,KK_FILTER_EVENT_POST_REPLY) == NULL){
		return 1;
	}
	else if(strstr(topic, KK_FILTER_SERVICE_CALL_TOPIC) != NULL && \
		strstr(topic,KK_FILTER_SERVICE_CALL_REPLY) != NULL){
		return 1;
	}		
	else if(strstr(topic, KK_FILTER_STATUS_ONLINE) != NULL && \
		strstr(topic,KK_FILTER_STATUS_ONLINE_REPLY) == NULL){
		return 1;
	}
	else if(strstr(topic, KK_FILTER_STATUS_OFFLINE) != NULL && \
		strstr(topic,KK_FILTER_STATUS_OFFLINE_REPLY) == NULL){
		return 1;
	}				
	return 0;
}
/************************************************************
*功能描述：从主题解析出消息
*输入参数： topic：主题
          start_deli：从第start_deli个'/'开始解析
*输出参数： msgTypeStr：消息类型
*返 回 值：  0：成功；其他：失败
*其他说明：
*************************************************************/
static int _kk_topic_parse_msgType(_IN_ char *topic, _IN_ int start_deli,_OU_ char **msgTypeStr)
{
	int res = 0, start = 0, len = 0;
	char *msgTypeStr_tmp = NULL;

	if (topic == NULL) {
		return RETURN_FAIL;
	}
	res = kk_utils_memtok(topic, strlen(topic), KK_TOPIC_SERVICE_DELIMITER, start_deli, &start);
	if (res != 0) {
		return RETURN_FAIL;
	}
	len = strlen(topic) - start + 1;
	msgTypeStr_tmp = (char*)malloc(len+1);
	if(msgTypeStr_tmp == NULL){
		ERROR_PRINT("[%s][%d]malloc fail!!!\n",__FUNCTION__,__LINE__);
		return RETURN_FAIL;
	}
	memcpy(msgTypeStr_tmp, topic + start, len);
	*msgTypeStr = msgTypeStr_tmp;
	INFO_PRINT("[%s][%d]%s\n",__FUNCTION__,__LINE__,*msgTypeStr);


    /* dm_log_debug("URI Product Key: %.*s, Device Name: %.*s", slice - start - 1, uri + start + 1, end - slice - 1,
                 uri + slice + 1); */

	return RETURN_SUCCESS;
}

/************************************************************
*功能描述：从主题解析出productCode和deviceCode
*输入参数： topic：主题
          start_deli：从第start_deli个'/'开始解析
*输出参数： productCode：产品ID
          deviceCode：设备deviceCode
*返 回 值：  0：成功；其他：失败
*其他说明：
*************************************************************/

static int _kk_topic_parse_pkdn(_IN_ char *topic, _IN_ int start_deli,
							_OU_ char productCode[PRODUCT_CODE_LEN],_OU_ char deviceCode[DEVICE_CODE_LEN])
{
	int res = 0, start = 0, end = 0, slice = 0;

	if (topic == NULL || deviceCode == NULL) {
		return RETURN_FAIL;
	}
	res = kk_utils_memtok(topic, strlen(topic), KK_TOPIC_SERVICE_DELIMITER, start_deli, &start);
	if (res != 0) {
		return RETURN_FAIL;
	}
	res = kk_utils_memtok(topic, strlen(topic), KK_TOPIC_SERVICE_DELIMITER, start_deli + 1, &slice);
	if (res != 0) {
		return RETURN_FAIL;
	}

	res = kk_utils_memtok(topic, strlen(topic), KK_TOPIC_SERVICE_DELIMITER, start_deli + 2, &end);
	if (res != 0) {
		return RETURN_FAIL;
	}

	memcpy(productCode, topic + start + 1, slice - start - 1);	
	memcpy(deviceCode, topic + slice + 1, end - slice - 1);

	return RETURN_SUCCESS;
}
						   
/************************************************************
*功能描述：topo change消息处理
*输入参数： payload：具体数据
*输出参数： 无
*返 回 值：  0：成功；其他：失败
*其他说明：此接口主要手机端主动删除设备时调用
*************************************************************/						   
static int _kk_topo_change_handle(cJSON *payload)
{
	cJSON *paramStr = cJSON_GetObjectItem(payload, MSG_PARAMS_STR);
	if(paramStr == NULL){
		ERROR_PRINT("[%s][%d]\n",__FUNCTION__,__LINE__);
		return RETURN_FAIL;
	}
	cJSON *state = cJSON_GetObjectItem(paramStr, MSG_TOPO_CHANGE_TYPE_STR);
	if(state != NULL && state->valueint == 1){
		cJSON *deviceArray = cJSON_GetObjectItem(paramStr, MSG_TOPO_CHANGE_DEVICES_STR);
		if(deviceArray == NULL){
			ERROR_PRINT("[%s][%d]\n",__FUNCTION__,__LINE__);
			return RETURN_FAIL;
		}
		cJSON * item = deviceArray->child;
		while(item != NULL){
			char *deviceCode = cJSON_GetObjectItem(item,MSG_DEVICE_CODE_STR)->valuestring;
			char *productCode = cJSON_GetObjectItem(item,MSG_PRODUCT_CODE_STR)->valuestring;
			KK_Subdev_UnSubscribe_By_DeviceCode(deviceCode,productCode);
			item = item->next;
		}
	}
	return RETURN_SUCCESS;

}

/************************************************************
*功能描述：从云端数据转化成业务协议数据
*输入参数： data：具体数据
          topic：主题
*输出参数： 无
*返 回 值：  NULL：失败；其他：具体协议数据
*其他说明：
*************************************************************/			
static char * _kk_data_create(const char *topic,const char *data)
{
	cJSON *root;
	char *out;
	char *infoStr = NULL;
	int infoStr_len = 0;
	int res = 0;
	char productCode[PRODUCT_CODE_LEN] = {0};	
	char deviceCode[DEVICE_CODE_LEN] = {0};	
	char * msgStr = NULL;

	res =_kk_topic_parse_pkdn((char *)topic,2,productCode,deviceCode);
	//if(!strcmp("gateway_2",productCode)){
		//memset(productCode,0x0,sizeof(productCode));
		//memcpy(productCode,"2",strlen("2"));
	//}
	res|=_kk_topic_parse_msgType((char *)topic,4,&msgStr);
	infoStr_len = strlen(DM_MSG_TO_MIDDWARE)+strlen(productCode)+strlen(deviceCode)+strlen(msgStr)+10;
	infoStr = malloc(infoStr_len);
	if(infoStr == NULL){
		ERROR_PRINT("[%s][%d]\n",__FUNCTION__,__LINE__);
		free(msgStr);
		return NULL;
	}
	memset(infoStr,0x0,infoStr_len);
	snprintf(infoStr,infoStr_len,DM_MSG_TO_MIDDWARE,msgStr,productCode,deviceCode);

	root=cJSON_CreateObject();
	cJSON* infoObj = cJSON_Parse(infoStr);
	cJSON* payloadObj = cJSON_Parse(data);
#if 0
	cJSON * params = cJSON_GetObjectItem(payloadObj,"params");
	if(params != NULL){
		cJSON * PowerSwitch = cJSON_GetObjectItem(params,"PowerSwitch");
		cJSON * epNUm = cJSON_GetObjectItem(params,"epNUm");
		if(PowerSwitch != NULL && epNUm != NULL){
			char tmpPS[32] = {0};
			strcat(tmpPS,"PowerSwitch");
			strcat(tmpPS,"_");
			strcat(tmpPS,epNUm->valuestring);
			cJSON_AddNumberToObject(params,tmpPS,PowerSwitch->valueint);
			cJSON_DeleteItemFromObject(params, "PowerSwitch");
			cJSON_DeleteItemFromObject(params, "epNUm");
		}
	}
#endif	
	cJSON_AddItemToObject(root, MSG_INFO_STR, infoObj);
	cJSON_AddItemToObject(root, MSG_PAYLOAD_STR,payloadObj);	
	if(strstr(topic,KK_TOPO_CHANGE_MSG_STR)){
		_kk_topo_change_handle(payloadObj);
	}	
	
	out=cJSON_Print(root);
	cJSON_Minify(out);
	cJSON_Delete(root);
	free(msgStr);
	free(infoStr);
	INFO_PRINT("[out]%s\n",out);	
	
	return out;
	//free(out);	/* Print to text, Delete the cJSON, print it, release the string. */
}

/************************************************************
*功能描述：通知midware是否连云成功
*输入参数： state：1，连上；0：未连上
*输出参数： 无
*返 回 值：  0：成功；其他：失败
*其他说明：
*************************************************************/		
const char DM_MSG_CLOUDSTATE[] = "{\"msgId\":\"1\",\"version\":\"1.0\",\"params\":{\"IOTCloudState\":\"%d\"},\"method\":\"thing.ccu.cloudstate_reply\"}";
int KK_Send_CloudState(int state)
{
	char *infoStr = NULL;
	char *payloadStr = NULL;	
	int infoStr_len = 0;
	int payloadStr_len = 0;	
	cJSON *root;
	char *out;
	char pid[32] = {0};
	char ccuid[32] = {0};
	kk_cloud_get_pid(pid);
	KK_Get_ccuid(ccuid);
	infoStr_len = strlen(DM_MSG_TO_MIDDWARE)+strlen(KK_CLOUDSTATE_MSG_REPLY)+10;
	infoStr = malloc(infoStr_len);
	if(infoStr == NULL){
		ERROR_PRINT("infoStr == NULL\n");
		return RETURN_FAIL;
	}
	memset(infoStr,0x0,infoStr_len);
	snprintf(infoStr,infoStr_len,DM_MSG_TO_MIDDWARE,KK_CLOUDSTATE_MSG_REPLY,pid,ccuid);

	payloadStr_len = strlen(DM_MSG_CLOUDSTATE) + 10;
	payloadStr = malloc(payloadStr_len);
	if(payloadStr == NULL){
		ERROR_PRINT("payloadStr == NULL\n");
		return RETURN_FAIL;
	}
	memset(payloadStr,0x0,payloadStr_len);
	snprintf(payloadStr,payloadStr_len,DM_MSG_CLOUDSTATE,state);
	
	root=cJSON_CreateObject();
	cJSON* infoObj = cJSON_Parse(infoStr);
	cJSON* payloadObj = cJSON_Parse(payloadStr);
	cJSON_AddItemToObject(root, MSG_INFO_STR, infoObj);
	cJSON_AddItemToObject(root, MSG_PAYLOAD_STR,payloadObj);
	out=cJSON_Print(root);	
	kk_ipc_send(IPC_APP2MID, out, strlen(out)+1);
	cJSON_Delete(root);
	free(payloadStr);
	free(infoStr);
	INFO_PRINT("%s\n",out);
	free(out);
	return RETURN_SUCCESS;
}
const char DM_MSG_CLOUDHB[] = "{\"msgId\":\"1\",\"version\":\"1.0\",\"params\":{\"heartbeat\":\"%d\"},\"method\":\"thing.ccu.cloudHB_reply\"}";
int KK_Send_CloudHB2Mid(int state)
{
	char *infoStr = NULL;
	char *payloadStr = NULL;	
	int infoStr_len = 0;
	int payloadStr_len = 0;	
	cJSON *root;
	char *out;

	infoStr_len = strlen(DM_MSG_TO_MIDDWARE)+strlen(KK_CLOUDHB_MSG_REPLY)+10;
	infoStr = malloc(infoStr_len);
	if(infoStr == NULL){
		ERROR_PRINT("infoStr == NULL\n");
		return RETURN_FAIL;
	}
	memset(infoStr,0x0,infoStr_len);
	snprintf(infoStr,infoStr_len,DM_MSG_TO_MIDDWARE,KK_CLOUDHB_MSG_REPLY,"","");

	payloadStr_len = strlen(DM_MSG_CLOUDHB) + 10;
	payloadStr = malloc(payloadStr_len);
	if(payloadStr == NULL){
		ERROR_PRINT("payloadStr == NULL\n");
		return RETURN_FAIL;
	}
	memset(payloadStr,0x0,payloadStr_len);
	snprintf(payloadStr,payloadStr_len,DM_MSG_CLOUDHB,state);
	
	root=cJSON_CreateObject();
	cJSON* infoObj = cJSON_Parse(infoStr);
	cJSON* payloadObj = cJSON_Parse(payloadStr);
	cJSON_AddItemToObject(root, MSG_INFO_STR, infoObj);
	cJSON_AddItemToObject(root, MSG_PAYLOAD_STR,payloadObj);
	out=cJSON_Print(root);	
	kk_ipc_send(IPC_APP2MID, out, strlen(out)+1);
	cJSON_Delete(root);
	free(payloadStr);
	free(infoStr);
	INFO_PRINT("%s\n",out);
	free(out);
	return RETURN_SUCCESS;
}
/************************************************************
*功能描述：发送数据给Midware
*输入参数： topic：主题；
          data：具体数据
*输出参数： 无
*返 回 值：  无
*其他说明：
*************************************************************/	
void KK_Sendto_DevData(const char *topic,const char *data)
{
	if(_check_invalid_topic(topic))
	{
		INFO_PRINT("ingore the topic:%s\n",topic);
		return;//ingore the message
	}
	INFO_PRINT("receive from cloud,topic:%s\n",topic);	
	INFO_PRINT("receive from cloud,data:%s\n",data);
	char *send_data = _kk_data_create(topic,data);
	if(send_data == NULL){
		return;
	}
	kk_ipc_send(IPC_APP2MID, send_data, strlen(send_data)+1);
	free(send_data);
}
