/**
*@file    sr_senthink.c
*@brief   贤芯X平台组件接口
*@details 提供贤芯X平台相关接口
*@copyright Copyright (c) 2024 lierda. All rights reserved.
*@author  Lierda-RDC
*@date    2024-05-07
*@example ZhaoyangSDK\example\component\senthink_example.c
*/

#include "sr_senthink.h"
#include "senthink_crypt.h"
#include "sr_cjson.h"

#include "sr_osal.h"
#include "sr_config.h"
#include "sr_log.h"


#include <string.h>

#include "cmsis_os2.h"

static int _StkPropSetAckJs(uint16_t msgId, uint8_t isOK);
static int _StkOtaNotifyAckJs(uint16_t msgId, char *downId);
static int _GetNextMsgId(SR_STK_MNG_T *cloudMng);

static SR_STK_MNG_T gs_stkMng;

static void *SR_StkGetMng(void)
{
	return (void *)&gs_stkMng;
}

static void _DownLinkCb(SR_MQTT_CLIENT_T *mqttc, SR_MQTT_MSG_T *mqttMsg)
{
	// 数据样例：{"HeaderCtrl":1,"MessageId":1231,"Version":"2.0","Payload":{"Code":0,"DeviceSecret":"B8C4F7465AD26CE3BC77E898D96EA75C"}}
	SR_STK_MNG_T *cloudMng = (SR_STK_MNG_T *)SR_StkGetMng();

	cJSON *root = cJSON_Parse((char *)mqttMsg->payload);

	cJSON *authPayload = cJSON_GetObjectItem(root, "Payload");
	if (authPayload != SR_NULL)
	{
		cJSON *Code = cJSON_GetObjectItem(authPayload, "Code");
		if (Code != NULL)
		{
			if (Code->valueint == 0)
			{
				cJSON *secret = SR_NULL;
				SR_LOG(DEBUG,"[CLD] CB,Auth OK!\n");

				// 通知用户记录密钥
				secret = cJSON_GetObjectItem(authPayload, "DeviceSecret"); // 获取密钥
				if (cloudMng->eventCb)
					cloudMng->eventCb(SR_STK_EVENT_AUTH_OK, secret->valuestring, strlen(secret->valuestring), cloudMng->eventCbArgs);

				// 发送事件
				osEventFlagsSet(cloudMng->event, SR_STK_EVENT_AUTH_OK);
			}
			else
			{
				SR_LOG(DEBUG,"[CLD] Auth fail!\n");
			}
		}
	}

	cJSON_Delete(root);
}

static void _ReportAckCb(SR_MQTT_CLIENT_T *mqttc, SR_MQTT_MSG_T *mqttMsg)
{
	// 数据样例：{"HeaderCtrl":16,"MessageId":1231,"Version":"2.0","Payload":{"Code":"200","Msg":"SUCCESS"}}

	SR_STK_MNG_T *cloudMng = (SR_STK_MNG_T *)SR_StkGetMng();

	cJSON *root = cJSON_Parse((char *)mqttMsg->payload);
	cJSON *payload = cJSON_GetObjectItem(root, "Payload");

	if (payload != SR_NULL)
	{
		cJSON *msg = cJSON_GetObjectItem(payload, "Msg");
		if (msg != SR_NULL)
		{
			if (!strcmp(msg->valuestring, "SUCCESS"))
			{
				// report成功，发送事件
				osEventFlagsSet(cloudMng->event, SR_STK_EVENT_PROP_RPT_OK);
			}
			else
			{
				SR_LOG(DEBUG,"[CLD] report fail!\n");
			}
		}
	}

	cJSON_Delete(root);
}

static void _PropSetCb(SR_MQTT_CLIENT_T *mqttc, SR_MQTT_MSG_T *mqttMsg)
{
	SR_PRINTF("[PROP] 1 prop set cb enter");
	// 数据示例：{"HeaderCtrl":20,"MessageId":357605888,"Version":"2.0","Payload":{"params":[{"value":12,"identify":"frequency"}]}}
	uint8_t i, arraySize = 0, isOK = 1;
	int ret = -1;
	SR_STK_MNG_T *cloudMng = (SR_STK_MNG_T *)SR_StkGetMng();

	// 解析处理数据
	cJSON *root = cJSON_Parse((char *)mqttMsg->payload);
	cJSON *msgId = cJSON_GetObjectItem(root, "MessageId");

	cJSON *payload = cJSON_GetObjectItem(root, "Payload");
	if (payload != SR_NULL)
	{
		cJSON *params = cJSON_GetObjectItem(payload, "params"); // 是数组类型
		if (params != SR_NULL)
		{
			SR_STK_PROP_DATA_T propData = {0};
			arraySize = cJSON_GetArraySize(params); // 获取json数组大小

			SR_PRINTF("[PROP] 2 arraysize=%d", arraySize);
			for (i = 0; i < arraySize; i++)
			{
				cJSON *subArr = cJSON_GetArrayItem(params, i); // 遍历每个元素

				cJSON *value = cJSON_GetObjectItem(subArr, "value");	   // 获取每个元素的 value字段
				cJSON *identify = cJSON_GetObjectItem(subArr, "identify"); // 获取每个元素的identify字段

				propData.key = identify->valuestring;

				if (value->type == cJSON_Number)
				{
					propData.vType = 0;
					propData.vNum = value->valuedouble;
				}
				else
				{
					propData.vType = 1;
					propData.vString = value->string;
				}

				if (cloudMng->eventCb)
				{
					ret = cloudMng->eventCb(SR_STK_EVENT_PROP_SET, &propData, sizeof(SR_STK_MNG_T), cloudMng->eventCbArgs);

					if (ret != 0)
					{
						isOK = 0;
						break;
					}
				}
			}
		}
	}

	// 返回响应
	_StkPropSetAckJs(msgId->valueint, isOK);

	cJSON_Delete(root);
}

static void _ReportFwVerAckCb(SR_MQTT_CLIENT_T *mqttc, SR_MQTT_MSG_T *mqttMsg)
{
	// 数据样例 {"HeaderCtrl":8,"MessageId":1231,"Version":"2.0","Payload":{"Code":"200","Msg":"SUCCESS"}}

	SR_STK_MNG_T *cloudMng = (SR_STK_MNG_T *)SR_StkGetMng();

	cJSON *root = cJSON_Parse((char *)mqttMsg->payload);
	cJSON *payload = cJSON_GetObjectItem(root, "Payload");

	if (payload != SR_NULL)
	{

		cJSON *msg = cJSON_GetObjectItem(payload, "Msg");
		if (msg != SR_NULL)
		{

			if (!strcmp(msg->valuestring, "SUCCESS"))
			{
				// report FW ver成功，发送事件
				osEventFlagsSet(cloudMng->event, SR_STK_EVENT_FW_RPT_OK);
			}
			else
			{
				SR_LOG(DEBUG,"[CLD] report fw ver fail!\n");
			}
		}
	}

	cJSON_Delete(root);
}

static void _OtaNotifyCb(SR_MQTT_CLIENT_T *mqttc, SR_MQTT_MSG_T *mqttMsg)
{
	// 数据样例：{"MessageId":1231,"HeaderCtrl":9,"Version":"V2.0","Payload":{"SoftVer":"v1.0.1","SoftSize":27448,"MD5":"4856592e00e9360a3202034dedc8e71a","DownID":"A32E196D","Url":"http://api-aep.xiot.senthink.com/senthink/aep/ota/v1/firm/down/762DF087/73AF9252/DEV0001","firmwareName":"dev0001-SV1_0_1","Type":2}}

	SR_STK_MNG_T *cloudMng = (SR_STK_MNG_T *)SR_StkGetMng();

	cJSON *root = cJSON_Parse((char *)mqttMsg->payload);
	// cJSON *msgId = cJSON_GetObjectItem(root, "MessageId");
	cJSON *payload = cJSON_GetObjectItem(root, "Payload");

	if (payload != SR_NULL)
	{
		SR_STK_OTA_INFO_T otaInfo = {0};
		char stkUrl[128] = {0}; // 为 "Url/DownID"
		cJSON *softVer = cJSON_GetObjectItem(payload, "SoftVer");
		if (softVer != SR_NULL)
			otaInfo.softVer = softVer->valuestring;

		cJSON *softSize = cJSON_GetObjectItem(payload, "SoftSize");
		if (softSize != SR_NULL)
			otaInfo.softSize = (uint32_t)softSize->valuedouble;

		cJSON *md5 = cJSON_GetObjectItem(payload, "MD5");
		if (md5 != SR_NULL)
			otaInfo.md5 = md5->valuestring;

		cJSON *downID = cJSON_GetObjectItem(payload, "DownID");
		cJSON *url = cJSON_GetObjectItem(payload, "Url");
		if ((downID != SR_NULL) && (url != SR_NULL))
		{
			snprintf(stkUrl, 128, "%s/%s", url->valuestring, downID->valuestring);
			otaInfo.url = stkUrl;
		}

		cJSON *fwName = cJSON_GetObjectItem(payload, "firmwareName");
		if (fwName != SR_NULL)
			otaInfo.fwName = fwName->valuestring;

		cJSON *type = cJSON_GetObjectItem(payload, "Type");
		if (type != SR_NULL)
			otaInfo.type = (uint32_t)type->valuedouble;

		// 调用回调通知用户
		if (cloudMng->eventCb)
			cloudMng->eventCb(SR_STK_EVENT_OTA_NOTIFY, &otaInfo, sizeof(SR_STK_OTA_INFO_T), cloudMng->eventCbArgs);

		// 发送响应
		if (downID != SR_NULL)
			_StkOtaNotifyAckJs(_GetNextMsgId(cloudMng), downID->valuestring);
	}

	cJSON_Delete(root);
}

static SR_SUB_CB_TABLE_T g_subCbTable[] =
	{
		{"downlink", _DownLinkCb},  //认证响应处理函数
		{"property/report_ack", _ReportAckCb},  //属性上报响应处理函数
		{"property/set", _PropSetCb},           //属性设置处理函数
		{"firmware_report_ack", _ReportFwVerAckCb},  //固件版本上报响应处理函数
		{"ota_notify", _OtaNotifyCb},  //OTA升级推送处理函数

};

static void _MqttEventCb(SR_MQTT_CLIENT_T *mqttc, SR_MQTT_EVENT_E event, SR_MQTT_MSG_T *mqttMsg)
{
	SR_STK_MNG_T *cloudMng = &gs_stkMng;

	switch (event)
	{

	case SR_MQTT_EVENT_RECV_PUBLISH: /*!< 收到平台下行PUBLISH数据 */

		break;

	case SR_MQTT_EVENT_CONN_OK: /*!< 平台CONNECT OK */

		break;

	case SR_MQTT_EVENT_DISCONNECT: /*!< 平台DISCONNECT */

		if (cloudMng->eventCb)
			cloudMng->eventCb(SR_STK_EVENT_DISCONNECT, SR_NULL, 0, cloudMng->eventCbArgs);

		break;
	}
}

static int _GetNextMsgId(SR_STK_MNG_T *cloudMng)
{
	return cloudMng->nextMsgId = (cloudMng->nextMsgId == SR_STK_MAX_MSG_ID) ? 1 : cloudMng->nextMsgId + 1;
}

static void _SenthinkEncrypt(uint8_t *deviceSecret, uint8_t secretlen, uint8_t *content, uint8_t contentlen, uint8_t *output, uint8_t *outlen)
{
	AES_CMAC_CTX cmac_ctx = {0};
	uint8_t deviceSecretHex[32] = {0};
	uint8_t outBufHex[100] = {0};

	SL_AsciiToHex(deviceSecret, deviceSecretHex, secretlen); // 32
	AES_CMAC_Init(&cmac_ctx);
	AES_CMAC_SetKey(&cmac_ctx, deviceSecretHex);

	AES_CMAC_GetAesKey(&cmac_ctx, content, outBufHex, contentlen);
	SL_HexToAscii(outBufHex, output, 64);

	*outlen = 64; // 待优化
}

void _StkGetMqttJoinAcct(char *clientID, char *username, char *password, uint8_t type, uint32_t timestamp)
{
	char passwordTemp[200] = {0};
	uint8_t passwardLen = 0;
	uint8_t content[100] = {0};

	SR_STK_MNG_T *cloudMng = &gs_stkMng;

	// 计算password
	if (type == 0)
		// 不校验时间戳
		sprintf(content, "%s.%s_%s", SR_STK_PRODUCT_ID, cloudMng->deviceID, SR_STK_PRODUCT_KEY);
	else
		// 校验时间戳
		sprintf(content, "%s.%s_%s_%d", SR_STK_PRODUCT_ID, cloudMng->deviceID, SR_STK_PRODUCT_KEY, timestamp);

	_SenthinkEncrypt(cloudMng->deviceSecret, SR_STK_DEV_SECRET_LEN, content, strlen(content), passwordTemp, &passwardLen);

	snprintf(clientID, SR_STK_MQTT_CLIENTID_LEN, "V2_%s.%s_%d_%d", SR_STK_PRODUCT_ID, cloudMng->deviceID, type, timestamp);
	snprintf(username, SR_STK_MQTT_UAERNAME_LEN, "%s-%s-%s", SR_STK_OPEN_ID, SR_STK_PRODUCT_ID, cloudMng->deviceID);
	snprintf(password, SR_STK_MQTT_PASSWORD_LEN, "%s", passwordTemp);
}

void _StkGetMqttAuthAcct(char *clientID, char *username, char *password)
{
	SR_STK_MNG_T *cloudMng = &gs_stkMng;

	snprintf(clientID, SR_STK_MQTT_CLIENTID_LEN, "%s-%s", SR_STK_PRODUCT_ID, cloudMng->deviceID);
	snprintf(username, SR_STK_MQTT_UAERNAME_LEN, "AUTH-%s-%s", SR_STK_OPEN_ID, SR_STK_PRODUCT_ID);
	snprintf(password, SR_STK_MQTT_PASSWORD_LEN, "%s", SR_STK_PRODUCT_KEY);
}


//初始化云平台的MQTT资源
int SR_StkMqttInit(char *netAdptName, SR_STK_INIT_PARAMS_T *initParams)
{
	int ret = -1;
	SR_MQTT_INIT_PARAMS_T mqttInitParams = {0};

	SR_STK_MNG_T *cloudMng = &gs_stkMng;

	if ((cloudMng == SR_NULL) || (netAdptName == SR_NULL) || (initParams == SR_NULL))
		return SR_INVALID;

	if ((initParams->serverIP == SR_NULL) || (initParams->serverPort == SR_NULL) || (initParams->deviceID == SR_NULL))
		return SR_INVALID;

	memset(&gs_stkMng, 0, sizeof(SR_STK_MNG_T));

	// 创建mqttc
	SR_MQTT_CLIENT_T *mqttc = (SR_MQTT_CLIENT_T *)SR_OsMalloc(sizeof(SR_MQTT_CLIENT_T));
	if (SR_NULL == mqttc)
	{
		ret = SR_NOMEM;
		goto _MALLOC_ERR;
	}

	// 将网络适配器和mqttc客户端关联到一起,保存连接参数
	cloudMng->netAdapter = SR_NetAdpFind(netAdptName);
	if (SR_NULL == cloudMng->netAdapter)
	{
		ret = SR_NOEXIST;
		goto _ADAPTER_ERR;
	}

	cloudMng->mqttc = mqttc;
	memcpy(&cloudMng->mqttConnParams, &initParams->mqttConnParams, sizeof(SR_MQTT_CONN_PARAMS_T));

	// 注册mqtt事件回调，订阅回调列表
	SR_NetMqttcSetEvtCb(mqttc, _MqttEventCb);
	mqttc->table = g_subCbTable;
	mqttc->tableSize = sizeof(g_subCbTable) / sizeof(SR_SUB_CB_TABLE_T);

	// 获取服务器IP和Port
	mqttInitParams.serverIP = initParams->serverIP;
	mqttInitParams.serverPort = initParams->serverPort;

	// 获取device ID和secret
	strcpy(cloudMng->deviceID, initParams->deviceID);
	if (initParams->deviceSecret != SR_NULL)
		strcpy(cloudMng->deviceSecret, initParams->deviceSecret);

	// 创建内部事件集
	cloudMng->event = osEventFlagsNew(SR_NULL);
	if (SR_NULL == cloudMng->event)
	{
		ret = SR_EKERNEL;
		goto _EVENT_ERR;
	}

	ret = SR_NetMqttcInit(cloudMng->netAdapter, cloudMng->mqttc, &mqttInitParams);
	if (ret)
	{
		ret = SR_FAIL;
		goto _MQTT_ERR;
	}
	return SR_OK;

_MQTT_ERR:
	osEventFlagsDelete(cloudMng->event);
_EVENT_ERR:
_ADAPTER_ERR:
	SR_OsFree(mqttc);
_MALLOC_ERR:
	return ret;
}

//去初始化云平台的MQTT资源
int SR_StkMqttDeinit(void)
{
	SR_STK_MNG_T *cloudMng = &gs_stkMng;

	SR_NetMqttcDeinit(cloudMng->mqttc);

	SR_OsFree(cloudMng->mqttc);

	if (cloudMng->event)
		osEventFlagsDelete(cloudMng->event);

	return 0;
}

//设置设备密钥至组件中
int SR_StkSetDevSecret(uint8_t *secret, uint16_t secretLen)
{

	SR_STK_MNG_T *cloudMng = &gs_stkMng;
	memcpy(cloudMng->deviceSecret, secret, secretLen);
	cloudMng->deviceSecret[secretLen] = 0;

	return 0;
}

//设备认证.     待完善：多次调用的保护机制
int SR_StkMqttAuth(void)
{
	int ret = -1;

	SR_STK_MNG_T *cloudMng = &gs_stkMng;

	SR_MQTT_CONN_PARAMS_T *connParams = &(cloudMng->mqttConnParams);

	// 1、连接
	char clientID[SR_STK_MQTT_CLIENTID_LEN] = {0}, username[SR_STK_MQTT_UAERNAME_LEN] = {0}, password[SR_STK_MQTT_PASSWORD_LEN] = {0};
	_StkGetMqttAuthAcct(clientID, username, password); // 获取认证的三元素信息
	SR_LOG(DEBUG,"[CLD] clientID=%s username=%s password=%s\n", clientID, username, password);

	connParams->clientID = clientID;
	connParams->username = username;
	connParams->password = password;

	ret = SR_NetMqttcConnect(cloudMng->mqttc, connParams);
	if (ret)
	{
		SR_LOG(DEBUG,"[CLD] mqtt connect fail\n");
		return -1;
	}

	// 2、订阅
	{
		char auth_topic_sub[64];
		sprintf(auth_topic_sub, SR_STK_AUTH_SUB, SR_STK_OPEN_ID, SR_STK_PRODUCT_ID, cloudMng->deviceID);
		SR_LOG(DEBUG,"[CLD] auth sub: %s\n", auth_topic_sub);
		ret = SR_NetMqttcSubscribe(cloudMng->mqttc, auth_topic_sub, QOS0);

		if (ret)
		{
			SR_LOG(DEBUG,"[CLD] Auth sub fail");
			ret = -1;
			goto _SUB_FAIL;
		}

		osDelay(1000);
	}

	// 3、认证
	{
		char *auth_topic_pub = SR_STK_AUTH_PUB;
		char payload[200];
		char *p = SR_NULL;
		sprintf(payload, SR_STK_AUTH_DATA, SR_STK_OPEN_ID, SR_STK_PRODUCT_ID, cloudMng->deviceID);

		// 待完善，考虑设备接入方式

		SR_LOG(DEBUG,"[CLD] auth data: %s\n", payload);
		ret = SR_NetMqttcPublish(cloudMng->mqttc, QOS0, auth_topic_pub, payload, strlen(payload));
		if (ret)
		{
			SR_LOG(DEBUG,"[CLD] auth pub fail");
			ret = -1;
			goto _SUB_FAIL;
		}

		// 超时等待云端 AUTHACK
		uint32_t eventFlag = 0;
		// ret =  luat_rtos_flag_wait(cloudMng->event, SR_STK_EVENT_AUTH_OK, LUAT_FLAG_OR_CLEAR, &eventFlag,6000);
		eventFlag = osEventFlagsWait(cloudMng->event, SR_STK_EVENT_AUTH_OK, osFlagsWaitAny, 3000);

		if ((eventFlag == osFlagsErrorParameter) || (eventFlag == osFlagsErrorISR) || (eventFlag == osFlagsErrorResource) || (eventFlag == osFlagsErrorTimeout))
		{
			SR_LOG(DEBUG,"[CLD] Auth wait flag(%d) Fail!\n", eventFlag);
			ret = SR_EKERNEL;
			goto _SUB_FAIL;
		}

		SR_LOG(DEBUG,"[CLD] Auth OK!\n");
	}

_SUB_FAIL:
	// 4、断开连接
	SR_NetMqttcDisconnect(cloudMng->mqttc);

	return ret;
}

//设备入网
int SR_StkMqttJoin(void)
{

	int ret = -1;

	SR_STK_MNG_T *cloudMng = &gs_stkMng;

	SR_MQTT_CONN_PARAMS_T *connParams = &(cloudMng->mqttConnParams);

	// 1、连接
	char clientID[SR_STK_MQTT_CLIENTID_LEN] = {0}, username[SR_STK_MQTT_UAERNAME_LEN] = {0}, password[SR_STK_MQTT_PASSWORD_LEN] = {0};
	_StkGetMqttJoinAcct(clientID, username, password, 0, SR_STK_TIMESTAMPE_TEST);

	SR_LOG(DEBUG,"[CLD] clientID=%s username=%s password=%s\n", clientID, username, password);

	connParams->clientID = clientID;
	connParams->username = username;
	connParams->password = password;

	ret = SR_NetMqttcConnect(cloudMng->mqttc, connParams);
	if (ret)
	{
		SR_LOG(DEBUG,"[CLD] mqtt connect fail\n");
		return -1;
	}

	if (cloudMng->eventCb)
		cloudMng->eventCb(SR_STK_EVENT_JOIN_OK, SR_NULL, 0, cloudMng->eventCbArgs);
	return 0;
}

//退出云平台连接
int SR_StkMqttExit(void)
{
	int ret = -1;
	SR_STK_MNG_T *cloudMng = &gs_stkMng;

	ret = SR_NetMqttcDisconnect(cloudMng->mqttc);

	return (ret == 0) ? SR_OK : SR_FAIL;
}

//通用的订阅云平台的MQTT主题
int SR_StkMqttSub(uint8_t qos, char *topic)
{
	// char auth_topic_sub[64];
	SR_STK_MNG_T *cloudMng = &gs_stkMng;

	return SR_NetMqttcSubscribe(cloudMng->mqttc, topic, qos);
}

//通用的取消订阅云平台的MQTT主题
int SR_StkMqttUnsub(char *topic)
{
	SR_STK_MNG_T *cloudMng = &gs_stkMng;

	return SR_NetMqttcUnsub(cloudMng->mqttc, topic);
}

//订阅接收属性上报响应的主题
int SR_StkPropReportAckSub(void)
{
	char subTopic[72] = {0};
	int ret = -1;

	SR_STK_MNG_T *cloudMng = &gs_stkMng;

	ret = sprintf(subTopic, SR_STK_PROP_RPTACK_SUB, SR_STK_OPEN_ID, SR_STK_PRODUCT_ID, cloudMng->deviceID);
	SR_LOG(DEBUG,"[CLD] prop report subTopic: %s\n", subTopic);
	if (ret <= 0)
		return SR_NOMEM;

	ret = SR_NetMqttcSubscribe(cloudMng->mqttc, subTopic, QOS0);

	return (ret == 0) ? SR_OK : SR_FAIL;
}


//产品物模型属性上报
int SR_StkPropReportJs(char *jsPayload)
{
	char topicPub[SR_STK_MQTT_TOPIC_LEN] = {0};
	char mqttPayload[SR_STK_MQTT_PAYLOAD_LEN] = {0};
	uint32_t eventFlag = 0;
	int ret = -1, mqttPldLen = 0;

	SR_STK_MNG_T *cloudMng = &gs_stkMng;

	if (jsPayload == SR_NULL)
		return SR_INVALID;

	// 封装数据
	ret = sprintf(topicPub, SR_STK_PROP_RPT_PUB, SR_STK_OPEN_ID, SR_STK_PRODUCT_ID, cloudMng->deviceID);
	mqttPldLen = sprintf(mqttPayload, SR_STK_PROP_RPT_DATA, _GetNextMsgId(cloudMng), jsPayload);

	if (ret <= 0 || mqttPldLen <= 0)
		return SR_FAIL;

	SR_LOG(DEBUG,"[CLD] report property\n topic: %s\npayload: %s\n", topicPub, mqttPayload);

	// publish
	ret = SR_NetMqttcPublish(cloudMng->mqttc, QOS0, topicPub, mqttPayload, mqttPldLen);
	if (ret)
	{
		SR_LOG(DEBUG,"[CLD] publish fail\n");
		return SR_FAIL;
	}

	// 等待响应事件
	eventFlag = osEventFlagsWait(cloudMng->event, SR_STK_EVENT_PROP_RPT_OK, osFlagsWaitAny, 6000);

	if ((eventFlag == osFlagsErrorParameter) || (eventFlag == osFlagsErrorISR) || (eventFlag == osFlagsErrorResource) || (eventFlag == osFlagsErrorTimeout))
	{
		SR_LOG(DEBUG,"[CLD] Report prop, wait flag(%d) Fail!\n", eventFlag);
		return SR_EKERNEL;
	}
	else
	{
		SR_LOG(DEBUG,"[CLD] Report property OK!\n");
	}

	return 0;
}

/**
 * @brief JSON格式产品,物模型属性设置响应
 *
 * @param cloudMng  云平台管理器指针
 * @param msgId 下行属性设置收到的消息ID
 * @param isOK 响应成功还是失败
 */
static int _StkPropSetAckJs(uint16_t msgId, uint8_t isOK)
{

	char topicPub[SR_STK_MQTT_TOPIC_LEN] = {0};
	char mqttPayload[SR_STK_MQTT_PAYLOAD_LEN] = {0};
	int32_t mqttPldLen = 0;
	int ret = -1, code = 200;
	char *result = "SUCCESS";

	SR_STK_MNG_T *cloudMng = &gs_stkMng;

	ret = sprintf(topicPub, SR_STK_PROP_SETACK_PUB, SR_STK_OPEN_ID, SR_STK_PRODUCT_ID, cloudMng->deviceID);
	if (ret <= 0)
		return SR_NOMEM;

	if (!isOK)
	{
		code = 4001;
		result = "Failed";
	}

	mqttPldLen = sprintf(mqttPayload, SR_STK_PROP_SETACK_DATA, msgId, code, result);
	if (mqttPldLen <= 0)
		return SR_NOMEM;

	SR_LOG(DEBUG,"[CLD] SetACK\n topic: %s\npayload: %s\n", topicPub, mqttPayload);

	ret = SR_NetMqttcPublish(cloudMng->mqttc, QOS0, topicPub, mqttPayload, mqttPldLen);
	if (ret)
	{
		SR_LOG(DEBUG,"[CLD] SetACK publish fail\n");
	}

	return (ret == 0) ? SR_OK : SR_FAIL;
}


//订阅用于接收物模型属性设置的主题
int SR_StkPropSetSub(void)
{
	char subTopic[72] = {0};
	int ret = -1;

	SR_STK_MNG_T *cloudMng = &gs_stkMng;

	ret = sprintf(subTopic, SR_STK_PROP_SET_SUB, SR_STK_OPEN_ID, SR_STK_PRODUCT_ID, cloudMng->deviceID);
	SR_LOG(DEBUG,"[CLD] prop set subTopic: %s\n", subTopic);
	if (ret <= 0)
		return SR_NOMEM;

	ret = SR_NetMqttcSubscribe(cloudMng->mqttc, subTopic, QOS0);

	return (ret == 0) ? SR_OK : SR_FAIL;
}


//上报设备固件版本信息
int SR_StkFwVerReportJs(SR_STK_FWVER_T *version)
{

	char topicPub[SR_STK_MQTT_TOPIC_LEN] = {0};
	char mqttPayload[SR_STK_MQTT_PAYLOAD_LEN] = {0};
	uint32_t eventFlag = 0, mqttPldLen = 0;
	int ret = -1;

	SR_STK_MNG_T *cloudMng = &gs_stkMng;

	sprintf(topicPub, SR_STK_FWVER_RPT_PUB, SR_STK_OPEN_ID, SR_STK_PRODUCT_ID, cloudMng->deviceID);
	mqttPldLen = sprintf(mqttPayload, SR_STK_FWVER_RPT_DATA, _GetNextMsgId(cloudMng), version->HardVer, version->SoftVer, version->type, version->module);

	SR_LOG(DEBUG,"[CLD] report FW\n topic: %s\npayload: %s\n", topicPub, mqttPayload);

	ret = SR_NetMqttcPublish(cloudMng->mqttc, QOS0, topicPub, mqttPayload, mqttPldLen);
	if (ret)
	{
		SR_LOG(DEBUG,"[CLD] publish fail\n");
		return -1;
	}

	eventFlag = osEventFlagsWait(cloudMng->event, SR_STK_EVENT_FW_RPT_OK, osFlagsWaitAny, 6000);

	if ((eventFlag == osFlagsErrorParameter) || (eventFlag == osFlagsErrorISR) || (eventFlag == osFlagsErrorResource) || (eventFlag == osFlagsErrorTimeout))
	{
		SR_LOG(DEBUG,"[CLD] Report FW, wait flag(%d) Fail!\n", eventFlag);
		return SR_EKERNEL;
	}
	else
	{
		SR_LOG(DEBUG,"[CLD] Report FW OK!\n");
	}

	return 0;
}


//订阅用于接收固件版本上报响应的主题
int SR_StkFwVerReportAckSub(void)
{
	char subTopic[72] = {0};
	int ret = -1;

	SR_STK_MNG_T *cloudMng = &gs_stkMng;

	ret = sprintf(subTopic, SR_STK_FWVER_RPTACK_SUB, SR_STK_OPEN_ID, SR_STK_PRODUCT_ID, cloudMng->deviceID);
	SR_LOG(DEBUG,"[CLD] FW report subTopic: %s\n", subTopic);
	if (ret <= 0)
		return SR_NOMEM;

	ret = SR_NetMqttcSubscribe(cloudMng->mqttc, subTopic, QOS0);

	return (ret == 0) ? SR_OK : SR_FAIL;
}

// OTA推送响应
static int _StkOtaNotifyAckJs(uint16_t msgId, char *downId)
{

	char topicPub[SR_STK_MQTT_TOPIC_LEN] = {0};
	char mqttPayload[SR_STK_MQTT_PAYLOAD_LEN] = {0};
	uint32_t mqttPldLen = 0;
	int ret = -1;

	SR_STK_MNG_T *cloudMng = &gs_stkMng;

	sprintf(topicPub, SR_STK_OTA_NTYACK_PUB, SR_STK_OPEN_ID, SR_STK_PRODUCT_ID, cloudMng->deviceID);

	mqttPldLen = sprintf(mqttPayload, SR_STK_OTA_NTYACK_DATA, msgId, downId);

	SR_LOG(DEBUG,"[CLD] OTA notify ack\n topic: %s\npayload: %s\n", topicPub, mqttPayload);

	ret = SR_NetMqttcPublish(cloudMng->mqttc, QOS0, topicPub, mqttPayload, mqttPldLen);
	if (ret)
	{
		SR_LOG(DEBUG,"[CLD] Ack publish fail\n");
		return -1;
	}
}


//订阅OTA升级通知的主题
int SR_StkOtaNotifySub(void)
{
	char subTopic[72] = {0};
	int ret = -1;

	SR_STK_MNG_T *cloudMng = &gs_stkMng;

	ret = sprintf(subTopic, SR_STK_OTA_NTY_SUB, SR_STK_OPEN_ID, SR_STK_PRODUCT_ID, cloudMng->deviceID);
	SR_LOG(DEBUG,"[CLD] OTA NTY subTopic: %s\n", subTopic);
	if (ret <= 0)
		return SR_NOMEM;

	ret = SR_NetMqttcSubscribe(cloudMng->mqttc, subTopic, QOS0);

	return (ret == 0) ? SR_OK : SR_FAIL;
}


//注册事件通知回调
int SR_StkSetEventCb(StkEventCb cb, void *args)
{

	SR_STK_MNG_T *cloudMng = &gs_stkMng;

	cloudMng->eventCb = cb;
	cloudMng->eventCbArgs = args;

	return 0;
}

