#include #include #include "esp_common.h" #include "user_config.h" #include "cfg.h" #include "log.h" #include "c_types.h" #include "protocol.h" #include "user_main.h" #include "jsprase.h" #include "uthash/libut.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/semphr.h" static xSemaphoreHandle g_MCUMutex = NULL; static PMCU_MSG_INFO g_pMCUMsg = NULL; int ProCacheMCUMsg(unsigned char* pData, int msgSize, int msgType) { int codeSize, iCount = 0; PMCU_MSG_INFO pMsg = NULL; if(pData == NULL || msgSize <= 0) { return ERR_OK; } LL_COUNT(g_pMCUMsg, pMsg, iCount); if(iCount >= MAX_MSG_CACHE) { LOG_EX(LOG_Error, "MCU Msg Full(%d)\n", iCount); return -ERR_MSG_FULL; } pMsg = (PMCU_MSG_INFO)malloc(sizeof(struct MCU_MSG_INFO)); if(pMsg == NULL) { LOG_EX(LOG_Error, "Malloc Memory(%u) Error\n", sizeof(struct MCU_MSG_INFO)); return -ERR_MALLOC_MEMORY; } memset(pMsg, 0, sizeof(struct MCU_MSG_INFO)); codeSize = ((msgSize + 3) / 3) * 4 + 4; pMsg->pMessage = (char*)malloc(codeSize); pMsg->msgType = msgType; if(pMsg->pMessage == NULL) { LOG_EX(LOG_Error, "Malloc Memory(%u) Error\n", sizeof(codeSize)); free(pMsg); return -ERR_MALLOC_MEMORY; } memset(pMsg->pMessage, 0, codeSize); mbedtls_base64_encode(pMsg->pMessage, codeSize, &iCount, pData, msgSize); xSemaphoreTake(g_MCUMutex, portMAX_DELAY); LL_APPEND(g_pMCUMsg, pMsg); xSemaphoreGive(g_MCUMutex); return ERR_OK; } char* ProGetMCUMsg(int* pMsgType) { PMCU_MSG_INFO pMsg = NULL, pTmp = NULL; char* pMQTTMsg = NULL; int ret = ERR_OK; BYPASS_INFO bypassInfo; char* pMsgContent = NULL; int msgType; xSemaphoreTake(g_MCUMutex, portMAX_DELAY); LL_FOREACH_SAFE(g_pMCUMsg, pMsg, pTmp) { LL_DELETE(g_pMCUMsg, pMsg); break; } xSemaphoreGive(g_MCUMutex); if(pMsg == NULL) { return NULL; } msgType = pMsg->msgType; if(pMsgType) { *pMsgType = msgType; } memset(&bypassInfo, 0, sizeof(BYPASS_INFO)); bypassInfo.mcuCmd = pMsg->pMessage; free(pMsg); pMsg = NULL; if(MSG_TYPE_BYPASS == msgType || MSG_TYPE_BIGDATA == msgType) { CLOUND_API api; api.cmdId = MSG_BYPASS; api.ver = PROTOCOL_VERSION; api.cryptoType = 0; api.timeStamp = 0; api.msgContent = (char*)Struct2Json(&bypassInfo, JE_BYPASS, CRYPTO_NONE, &ret); free(bypassInfo.mcuCmd); if(ret != ERR_OK || api.msgContent == NULL) { LOG_EX(LOG_Error, "Create Bypass Message Error %p: %d\n", api.msgContent, ret); if(api.msgContent) { free(api.msgContent); } return NULL; } pMQTTMsg = (char *)Struct2Json(&api, JE_PROMAIN, CRYPTO_NONE, &ret); if(api.msgContent) { free(api.msgContent); } if(ret != ERR_OK || pMQTTMsg == NULL) { LOG_EX(LOG_Error, "Create Protocol Message Error %p: %d\n", pMQTTMsg, ret); if(pMQTTMsg) { free(pMQTTMsg); } return NULL; } } else if(MSG_TYPE_SHADOW == msgType) { SHADOW_UPDATE shadow; memset(&shadow, 0, sizeof(SHADOW_UPDATE)); shadow.method = "update"; shadow.version = 1; shadow.state.reported.mcuCmd = bypassInfo.mcuCmd; pMQTTMsg = (char *)Struct2Json(&shadow, JE_SHADOWUP, CRYPTO_NONE, &ret); free(bypassInfo.mcuCmd); if(ret != ERR_OK || pMQTTMsg == NULL) { LOG_EX(LOG_Error, "Create Bypass Message Error %p: %d\n", pMQTTMsg, ret); if(pMQTTMsg) { free(pMQTTMsg); } return NULL; } } else { free(bypassInfo.mcuCmd); } return pMQTTMsg; } int ProCacheMQTTMsg(char* pData) { int codeSize, iCount = 0; MQTT_MSG msg; if(pData == NULL) { return ERR_OK; } memset(&msg, 0, sizeof(MQTT_MSG)); codeSize = ((strlen(pData) + 4) / 4) * 3; msg.pMessage = (unsigned char *)malloc(codeSize); if(msg.pMessage == NULL) { LOG_EX(LOG_Error, "Malloc Memory(%u) Error\n", sizeof(codeSize)); return -ERR_MALLOC_MEMORY; } memset(msg.pMessage, 0, codeSize); mbedtls_base64_decode(msg.pMessage, codeSize, &iCount, pData, strlen(pData)); msg.msgSize = iCount; #if 0 char buf[512]; SysBin2HexStr(buf, pMsg->pMQTTMsg->pMessage, iCount); LOG_EX(LOG_Debug, "Cache:\n%s\n", buf); #endif if(iCount > codeSize) { LOG_EX(LOG_Error, "Memory overlay: iCount = %d, malloc = %d\n", iCount, codeSize); } ne_device_send_queue(msg.pMessage, msg.msgSize, MSG_DIRECTION_CLOUD_DOWN); free(msg.pMessage); return ERR_OK; } void ProDumpCloundApi(PCLOUND_API pApi) { LOG_EX(LOG_Debug, "Dump CLOUND API Info:\n"); LOG_RAW(LOG_Debug, "-----------------------------------------------------\n"); LOG_RAW(LOG_Debug, "CmdId : %s(%d)\n", ProName2Str(pApi->cmdId), pApi->cmdId); LOG_RAW(LOG_Debug, "Crypto : %s(%d)\n", ProCryptoName2Str(pApi->cryptoType), pApi->cryptoType); LOG_RAW(LOG_Debug, "Timestamp : %d\n", pApi->timeStamp); LOG_RAW(LOG_Debug, "Message : %s\n", pApi->msgContent ? pApi->msgContent : ""); } int ProtocolOnMsg(PCLOUND_API pApi) { int isRspMsg = FALSE; int err = ERR_OK; void* pObject = NULL; char* pSubMsg = NULL; CLOUND_API api; switch(pApi->cmdId) { default: return -ERR_UNKNOWN_CMD_ID; case GET_DEV_ID: { RSP_GET_DEVID_PRO devId; uint8 product_id[5]; memset(product_id, 0, sizeof(product_id)); memset(&devId, 0, sizeof(RSP_GET_DEVID_PRO)); devId.cpuId = (char*)GetPlatformDevId(); devId.macAddr = (char *)GetSTAMacAddr(); if(ne_cfg_get_product_id(product_id, sizeof(product_id)) == ERR_OK){ devId.productSign = product_id; } pSubMsg = (char*)Struct2Json(&devId, JE_GETID, CRYPTO_NONE, &err); if(err != ERR_OK || pSubMsg == NULL) { LOG_EX(LOG_Error, "Create %s Message Error %p: %d\n", ProName2Str(pApi->cmdId), pSubMsg, err); if(pSubMsg) { free(pSubMsg); } pSubMsg = NULL; } isRspMsg = TRUE; break; } case CONFIG_AP: { PCFG_AP_INFO pApInfo = (PCFG_AP_INFO)Json2Struct(pApi->msgContent, JE_CFG_AP, CRYPTO_NONE, &err); if(err != ERR_OK || pApInfo == NULL) { LOG_EX(LOG_Error, "Process %s Message Error %p: %d\n", ProName2Str(pApi->cmdId), pSubMsg, err); if(pApInfo) { free(pApInfo); } break; } #if 0 pApInfo->gbkpasswd = strdup(pApInfo->passwd); pApInfo->gbkssid = strdup("zt7P31dpRmnExLzSx7+wocC2z+g="); #endif soft_ap_start_test(pApInfo); if(pApInfo->bssid) { free(pApInfo->bssid); } if(pApInfo->passwd) { free(pApInfo->passwd); } if(pApInfo->ssid) { free(pApInfo->ssid); } if(pApInfo->gbkssid) { free(pApInfo->gbkssid); } if(pApInfo->gbkpasswd) { free(pApInfo->gbkpasswd); } free(pApInfo); break; } case EXIT_SOFTAP_MODE: { isRspMsg = TRUE; SoftAPExitCfgMode(1); break; } case MSG_BYPASS: { PBYPASS_INFO pInfo = (PBYPASS_INFO)Json2Struct(pApi->msgContent, JE_BYPASS, CRYPTO_NONE, &err); if(err != ERR_OK || pInfo == NULL) { LOG_EX(LOG_Error, "Process %s Message Error %p: %d\n", ProName2Str(pApi->cmdId), pInfo, err); if(pInfo) { free(pInfo); } } else if(pInfo->mcuCmd && strlen(pInfo->mcuCmd) > 0) { ProCacheMQTTMsg(pInfo->mcuCmd); } if(pInfo->mcuCmd) { free(pInfo->mcuCmd); } free(pInfo); break; } } if(isRspMsg) { char *pRspMsg = NULL; api.msgContent = NULL; api.ver = PROTOCOL_VERSION; api.cmdId = CLOUND_API_CMD_RSP_BASE + pApi->cmdId; api.cryptoType = 0; api.timeStamp = 0; if(err != ERR_OK) { CLOUND_API_RSP_ERR rspErr; rspErr.errNo = err < 0 ? -err : err; rspErr.errMsg = (char*)SysGetErrName(rspErr.errNo); pSubMsg = (char*)Struct2Json(&rspErr, JE_RSP_STATUS, CRYPTO_NONE, &err); if(err != ERR_OK || pRspMsg == NULL) { LOG_EX(LOG_Error, "Create Rsponse Error Message Error %p: %d\n", pRspMsg, err); } } if(pSubMsg) { api.msgContent = pSubMsg; } pRspMsg = (char*)Struct2Json(&api, JE_PROMAIN, CRYPTO_NONE, &err); if(err != ERR_OK || pRspMsg == NULL) { LOG_EX(LOG_Error, "Create Rsponse Error %p: %d\n", pRspMsg, err); } if(pApi->cmdId == GET_DEV_ID || pApi->cmdId == CONFIG_AP || pApi->cmdId == EXIT_SOFTAP_MODE) { SoftAPSendRspMsg(pRspMsg); } if(pRspMsg) { free(pRspMsg); } } if(pSubMsg) { free(pSubMsg); } return err; } int ProtocolProcess(char* pStrJson) { int err = ERR_OK; PCLOUND_API pApi = (PCLOUND_API)Json2Struct(pStrJson, JE_PROMAIN, CRYPTO_NONE, &err); if(pApi == NULL || err != ERR_OK) { LOG_EX(LOG_Error, "Protocol %p: %d\n", pApi, err); return err; } ProDumpCloundApi(pApi); err = ProtocolOnMsg(pApi); if(pApi->msgContent) { free(pApi->msgContent); } free(pApi); return err; } int ProtocolInitEnv(void) { g_MCUMutex = xSemaphoreCreateMutex(); if(g_MCUMutex == NULL) { LOG_EX(LOG_Error, "Create Mutex Error\n"); return -ERR_MALLOC_MEMORY; } }