/******************************************************************************* * File Name : MQTTClient.c * Description : *******************************************************************************/ /******************************************************************************* * Include Files * *******************************************************************************/ #include "MQTTClient.h" #include "string.h" #include "DBG.h" #include "HIDO_Timer.h" #include "HIDO_Debug.h" #include "HIDO_Util.h" #include "HIDO_Json.h" #include "HIDO_VLQueue.h" #include "Socket.h" #include "Module.h" #include "HIDO_Log.h" #include "stdlib.h" // #include "Param.h" #include "MsgPack.h" #include "Internet.h" #include "HIDO_Base64.h" #include "MQTT.h" #include "AppConfig.h" #include "global_param.h" #include "MQTTApp.h" #include "PathStorage.h" /******************************************************************************* * Macro * *******************************************************************************/ #define INVALID_SN 0xFFFFFFFF #define MQTT_CLIENT_QUEUE_BUF_SIZE (1024 * 2) #define MQTT_CLIENT_QUEUE_MEMBER_CNT 16 /******************************************************************************* * Type Definition * *******************************************************************************/ typedef enum { REPORT_STATE_IDLE, REPORT_STATE_BUSY, } E_ReportState; typedef enum { RECV_STATE_LEN, RECV_STATE_BODY, } E_RecvState; typedef enum { CONNECT_STATE_IDEL = 0, CONNECT_STATE_CONNECT_WAIT, CONNECT_STATE_CONNECTING, CONNECT_STATE_CLOSED, CONNECT_STATE_CONNECTED, CONNECT_STATE_DISCONNECT_WAIT, CONNECT_STATE_DISCONNECTING, } E_ConnectState; typedef struct { HIDO_CHAR m_acHost[64]; HIDO_UINT16 m_u16Port; HIDO_UINT32 m_u32KeepAlive; HIDO_CHAR m_acClientID[64]; HIDO_CHAR m_acUsername[64]; HIDO_CHAR m_acPassword[64]; HIDO_CHAR m_acGpsTopic[128]; HIDO_CHAR m_acStatusTopic[128]; HIDO_CHAR m_acControlTopic[128]; HIDO_CHAR m_acPathTopic[128]; HIDO_CHAR m_acBaseStationTopic[128]; HIDO_CHAR m_acResponseTopic[128]; } ST_MQTTClientParam; /******************************************************************************* * Local Variable * *******************************************************************************/ static ST_MsgPackage l_stSendPackage; static E_ConnectState l_eConectState = CONNECT_STATE_IDEL; static HIDO_INT32 l_i32MQTTClientID = 0; static ST_MQTTConfig l_stMQTTConfig; static ST_MQTTClientParam l_stConnectParam; static HIDO_UINT32 l_u32MQTTConnectTick = 0; static HIDO_BOOL l_bMQTTDebugFlag = HIDO_FALSE; FN_MQTTClientEventCallback l_fnMQTTClientEventCallback; HIDO_VOID *l_pMQTTClientEventArg = HIDO_NULL; static HIDO_UINT8 l_au8SendBuff[512]; static HIDO_UINT8 l_au8RecvBuf[1500]; static HIDO_CHAR l_acRecvTopic[64]; static ST_CtrlData l_stCtrlData; /* �ڴ���� */ static HIDO_VLQStruct l_stMQTTClientQueue; static HIDO_UINT8 l_au8MQTTSendQueueBuf[MQTT_CLIENT_QUEUE_BUF_SIZE]; /******************************************************************************* * Local Function Declaration * *******************************************************************************/ static HIDO_INT32 MQTTClient_EventNotify(E_MQTTClientEvent _eEvent); static HIDO_INT32 MQTTClient_RequestParam(HIDO_VOID); /******************************************************************************* * Local Function * *******************************************************************************/ /******************************************************************************* * Function Name : MQTTClient_GetConnectStateName * Description : * Input : None * Output : None * Return : HIDO_OK �ɹ� * HIDO_ERR ʧ�� *******************************************************************************/ HIDO_CHAR *MQTTClient_GetConnectStateName(E_ConnectState _eConectState) { switch (_eConectState) { case CONNECT_STATE_IDEL: { return "IDEL"; } case CONNECT_STATE_CONNECT_WAIT: { return "CONNECT_WAIT"; } case CONNECT_STATE_CONNECTING: { return "CONNECTING"; } case CONNECT_STATE_CLOSED: { return "CLOSED"; } case CONNECT_STATE_CONNECTED: { return "CONNECTED"; } case CONNECT_STATE_DISCONNECT_WAIT: { return "DISCONNECT_WAIT"; } case CONNECT_STATE_DISCONNECTING: { return "DISCONNECTING"; } default: { return "ERR"; } } } /******************************************************************************* * Function Name : MQTTClient_SetConnectState * Description : ��������״̬ * Input : _eConnectState ����״̬ * Output : None * Return : HIDO_OK �ɹ� * HIDO_ERR ʧ�� *******************************************************************************/ static HIDO_INT32 MQTTClient_SetConnectState(E_ConnectState _eConnectState) { E_ConnectState eOldConnectState = l_eConectState; l_eConectState = _eConnectState; HIDO_Log(HIDO_LOG_LEVEL_DEBUG, "l_eConectState = %s -> %s\r\n", MQTTClient_GetConnectStateName(eOldConnectState), MQTTClient_GetConnectStateName(l_eConectState)); HIDO_DebugEx("l_eConectState = %s -> %s\r\n", MQTTClient_GetConnectStateName(eOldConnectState), MQTTClient_GetConnectStateName(l_eConectState)); return HIDO_OK; } /******************************************************************************* * Function Name : MQTTClient_ReportGps * Description : * Input : _pstPackage ���ݰ� * Output : None * Return : HIDO_OK �ɹ� * HIDO_ERR ʧ�� *******************************************************************************/ static HIDO_INT32 MQTTClient_ReportGps(ST_MsgPackage *_pstPackage) { if (MQTT_Publish(l_i32MQTTClientID, l_stConnectParam.m_acGpsTopic, _pstPackage->m_au8Data, _pstPackage->m_u32Len, 1) == HIDO_OK) { if (l_bMQTTDebugFlag == HIDO_TRUE) { if (_pstPackage->m_u32Len < sizeof(_pstPackage->m_au8Data)) { _pstPackage->m_au8Data[_pstPackage->m_u32Len] = '\0'; HIDO_DebugEx("[S] %s\r\n", (HIDO_CHAR *)_pstPackage->m_au8Data); } } return HIDO_OK; } else { return HIDO_ERR; } } /******************************************************************************* * Function Name : MQTTClient_ReportStatus * Description : ���ݰ��ϱ� * Input : _pstPackage ���ݰ� * Output : None * Return : HIDO_OK �ɹ� * HIDO_ERR ʧ�� *******************************************************************************/ static HIDO_INT32 MQTTClient_ReportStatus(ST_MsgPackage *_pstPackage) { if (MQTT_Publish(l_i32MQTTClientID, l_stConnectParam.m_acStatusTopic, _pstPackage->m_au8Data, _pstPackage->m_u32Len, 1) == HIDO_OK) { if (l_bMQTTDebugFlag == HIDO_TRUE) { if (_pstPackage->m_u32Len < sizeof(_pstPackage->m_au8Data)) { _pstPackage->m_au8Data[_pstPackage->m_u32Len] = '\0'; HIDO_DebugEx("[S] %s\r\n", (HIDO_CHAR *)_pstPackage->m_au8Data); } } return HIDO_OK; } else { return HIDO_ERR; } } /******************************************************************************* * Function Name : MQTTClient_ReportResponse * Description : ���ݰ��ϱ� * Input : _pstPackage ���ݰ� * Output : None * Return : HIDO_OK �ɹ� * HIDO_ERR ʧ�� *******************************************************************************/ static HIDO_INT32 MQTTClient_ReportResponse(ST_MsgPackage *_pstPackage) { if (MQTT_Publish(l_i32MQTTClientID, l_stConnectParam.m_acResponseTopic, _pstPackage->m_au8Data, _pstPackage->m_u32Len, 1) == HIDO_OK) { if (l_bMQTTDebugFlag == HIDO_TRUE) { if (_pstPackage->m_u32Len < sizeof(_pstPackage->m_au8Data)) { _pstPackage->m_au8Data[_pstPackage->m_u32Len] = '\0'; HIDO_DebugEx("[S] %s\r\n", (HIDO_CHAR *)_pstPackage->m_au8Data); } } return HIDO_OK; } else { return HIDO_ERR; } } /******************************************************************************* * Function Name : MQTTClient_MsgProc * Description : * Input : _pstPackage ���ݰ� * Output : None * Return : HIDO_OK �ɹ� * HIDO_ERR ʧ�� *******************************************************************************/ static HIDO_INT32 MQTTClient_MsgProc(HIDO_CHAR *_pstTopic, ST_CtrlData *_pstCtrlData) { HIDO_CHAR *pcRequestID = HIDO_NULL; HIDO_BOOL bSaveFence = HIDO_FALSE; // TODO MsgPack_Parse return HIDO_OK; } /******************************************************************************* * Function Name : MQTTClient_MQTTEventProc * Description : ���ӷ������¼����� * Input : None * Output : None * Return : None *******************************************************************************/ static HIDO_VOID MQTTClient_MQTTEventProc(HIDO_INT32 _i32ClientID, E_MQTTEvent _eEvent, HIDO_VOID *_pArg) { HIDO_Log(HIDO_LOG_LEVEL_DEBUG, "_i32ClientID=%d _eEvent=%u @%s\r\n", _i32ClientID, _eEvent, __FUNCTION__); switch (_eEvent) { case MQTT_EVENT_CONNECT_FAILED: { HIDO_Log(HIDO_LOG_LEVEL_WARN, "server connect failed\r\n"); if (CONNECT_STATE_CONNECTING == l_eConectState) { l_u32MQTTConnectTick = HIDO_TimerGetTick(); MQTTClient_SetConnectState(CONNECT_STATE_CLOSED); } break; } case MQTT_EVENT_CONNECTED: { HIDO_Log(HIDO_LOG_LEVEL_INFO, "server connect success\r\n"); if (CONNECT_STATE_CONNECTING == l_eConectState) { MQTTClient_SetConnectState(CONNECT_STATE_CONNECTED); MQTTClient_EventNotify(MQTT_CLIENT_EVENT_CONNECT); } break; } case MQTT_EVENT_CLOSED: { if (CONNECT_STATE_DISCONNECTING == l_eConectState) { MQTTClient_SetConnectState(CONNECT_STATE_IDEL); MQTTClient_EventNotify(MQTT_CLIENT_EVENT_DISCONNECT); } else if (l_eConectState != CONNECT_STATE_IDEL) { HIDO_Log(HIDO_LOG_LEVEL_WARN, "socket closed by server\r\n"); l_u32MQTTConnectTick = HIDO_TimerGetTick(); MQTTClient_SetConnectState(CONNECT_STATE_CLOSED); } break; } case MQTT_EVENT_DATA_PUBLISHED: { break; } case MQTT_EVENT_RECV_DATA: { HIDO_UINT32 u32RecvLen = 0; while (MQTT_Recv(l_i32MQTTClientID, l_acRecvTopic, l_au8RecvBuf, sizeof(l_au8RecvBuf), &u32RecvLen) == HIDO_OK) { // ����MQTTApp�������Ϣ MQTTApp_ParseMessage(l_acRecvTopic, l_au8RecvBuf, u32RecvLen); } break; } default: { break; } } } /******************************************************************************* * Global Function * *******************************************************************************/ /******************************************************************************* * Function Name : MQTTClient_IsNetWorkReady * Description : ��������Ƿ�׼������ * Input : None * Output : None * Return : None *******************************************************************************/ HIDO_BOOL MQTTClient_IsNetWorkReady(void) { if (Internet_IsIPReady() == HIDO_TRUE) { return HIDO_TRUE; } return HIDO_FALSE; } /******************************************************************************* * Function Name : MQTTClient_IsConnected * Description : ����Ƿ�Ҳ�������粢׼������ * Input : None * Output : None * Return : HIDO_TRUE �� * HIDO_FALSE �� *******************************************************************************/ HIDO_BOOL MQTTClient_IsConnected(void) { return (HIDO_BOOL)(CONNECT_STATE_CONNECTED == l_eConectState); } /******************************************************************************* * Function Name : MQTTClient_ConnectPoll * Description : ������ѯ * Input : None * Output : None * Return : None *******************************************************************************/ void MQTTClient_ConnectPoll(void) { HIDO_UINT32 u32CurTick = HIDO_TimerGetTick(); switch (l_eConectState) { /* ��ʼ���� */ case CONNECT_STATE_CONNECT_WAIT: { if (MQTTClient_IsNetWorkReady() == HIDO_FALSE) { break; } HIDO_DebugEx("Connect Server\r\n"); MQTT_Connect(l_i32MQTTClientID); MQTTClient_SetConnectState(CONNECT_STATE_CONNECTING); l_u32MQTTConnectTick = u32CurTick; break; } /* δ���ӻ�����ʧ�� */ case CONNECT_STATE_CLOSED: { if (MQTTClient_IsNetWorkReady() == HIDO_FALSE) { break; } /* ����ʱ�䵽 */ if ((u32CurTick - l_u32MQTTConnectTick) >= HIDO_TIMER_TICK_S(5)) { HIDO_DebugEx("Reconnect Server\r\n"); MQTT_Connect(l_i32MQTTClientID); MQTTClient_SetConnectState(CONNECT_STATE_CONNECTING); l_u32MQTTConnectTick = u32CurTick; } break; } /* ������ */ case CONNECT_STATE_CONNECTED: { ST_MQTTMessage *pstMQTTMessage = HIDO_NULL; HIDO_VLQMemberStruct *pstMember = HIDO_NULL; /* �����ڴ���� */ while ((pstMember = HIDO_VLQGetDequeueMember(&l_stMQTTClientQueue)) != HIDO_NULL) { pstMQTTMessage = (ST_MQTTMessage *)pstMember->m_pDataAddr; if (MQTT_Publish(l_i32MQTTClientID, pstMQTTMessage->m_acTopic, pstMQTTMessage->m_au8Data, pstMQTTMessage->m_u32DataLen, pstMQTTMessage->m_u32QOS) == HIDO_OK) { if (l_bMQTTDebugFlag == HIDO_TRUE) { HIDO_DebugEx("[S]"); HIDO_DebugString((HIDO_CHAR *)pstMQTTMessage->m_au8Data, pstMQTTMessage->m_u32DataLen); HIDO_DebugEx("\r\n"); } HIDO_VLQDequeue(&l_stMQTTClientQueue, pstMember); } else { break; } } break; } /* �ȴ��Ͽ� */ case CONNECT_STATE_DISCONNECT_WAIT: { MQTT_Close(l_i32MQTTClientID); MQTTClient_SetConnectState(CONNECT_STATE_DISCONNECTING); break; } default: { break; } } } /******************************************************************************* * Function Name : MQTTClient_Poll * Description : TCP�ͻ�����ѯ�ӿ� * Input : None * Output : None * Return : None *******************************************************************************/ void MQTTClient_Poll(void) { MQTTClient_ConnectPoll(); } /******************************************************************************* * Function Name : MQTTClient_DebugOn * Description : * Input : None * Output : None * Return : HIDO_OK �ɹ� * HIDO_ERR ʧ�� *******************************************************************************/ void MQTTClient_DebugOn(void) { l_bMQTTDebugFlag = HIDO_TRUE; } /******************************************************************************* * Function Name : MQTTClient_DebugOff * Description : * Input : None * Output : None * Return : HIDO_OK �ɹ� * HIDO_ERR ʧ�� *******************************************************************************/ void MQTTClient_DebugOff(void) { l_bMQTTDebugFlag = HIDO_FALSE; } /******************************************************************************* * Function Name : MQTTClient_GetConnectState * Description : * Input : None * Output : None * Return : HIDO_OK �ɹ� * HIDO_ERR ʧ�� *******************************************************************************/ HIDO_CHAR *MQTTClient_GetConnectState(void) { return MQTTClient_GetConnectStateName(l_eConectState); } /******************************************************************************* * Function Name : MQTTClient_EventNotify * Description : ������ѯ * Input : None * Output : None * Return : None *******************************************************************************/ static HIDO_INT32 MQTTClient_EventNotify(E_MQTTClientEvent _eEvent) { if (l_fnMQTTClientEventCallback != HIDO_NULL) { l_fnMQTTClientEventCallback(_eEvent, l_pMQTTClientEventArg); } return HIDO_OK; } /******************************************************************************* * Function Name : MQTTClient_SetEventCallback * Description : ������ѯ * Input : None * Output : None * Return : None *******************************************************************************/ HIDO_INT32 MQTTClient_SetEventCallback(FN_MQTTClientEventCallback _fnEventCallback, HIDO_VOID *_pArg) { l_fnMQTTClientEventCallback = _fnEventCallback; l_pMQTTClientEventArg = _pArg; return HIDO_OK; } /******************************************************************************* * Function Name : MQTTClient_Connect * Description : ��ʼ���� * Input : None * Output : None * Return : None *******************************************************************************/ HIDO_INT32 MQTTClient_Connect(void) { switch (l_eConectState) { case CONNECT_STATE_IDEL: case CONNECT_STATE_CLOSED: case CONNECT_STATE_DISCONNECT_WAIT: case CONNECT_STATE_DISCONNECTING: { MQTTClient_SetConnectState(CONNECT_STATE_CONNECT_WAIT); break; } case CONNECT_STATE_CONNECTED: { MQTTClient_EventNotify(MQTT_CLIENT_EVENT_CONNECT); break; } default: { break; } } return HIDO_OK; } /******************************************************************************* * Function Name : MQTTClient_Disconnect * Description : �Ͽ����� * Input : None * Output : None * Return : None *******************************************************************************/ HIDO_INT32 MQTTClient_Disconnect(void) { switch (l_eConectState) { case CONNECT_STATE_IDEL: { MQTTClient_EventNotify(MQTT_CLIENT_EVENT_DISCONNECT); break; } case CONNECT_STATE_CONNECT_WAIT: case CONNECT_STATE_CLOSED: { MQTTClient_SetConnectState(CONNECT_STATE_IDEL); MQTTClient_EventNotify(MQTT_CLIENT_EVENT_DISCONNECT); break; } case CONNECT_STATE_CONNECTING: case CONNECT_STATE_CONNECTED: { MQTTClient_SetConnectState(CONNECT_STATE_DISCONNECT_WAIT); break; } default: { break; } } return HIDO_OK; } /******************************************************************************* * Function Name : MQTTClient_IsReportIdle * Description : * Input : None * Output : None * Return : HIDO_OK �ɹ� * HIDO_ERR ʧ�� *******************************************************************************/ HIDO_BOOL MQTTClient_IsReportIdle(HIDO_VOID) { if (HIDO_VLQGetDequeueMember(&l_stMQTTClientQueue) != HIDO_NULL) { return HIDO_FALSE; } HIDO_VLQStruct *pstMQTTQueue = MQTT_GetSendQueue(l_i32MQTTClientID); if (HIDO_VLQGetDequeueMember(pstMQTTQueue) != HIDO_NULL) { return HIDO_FALSE; } return HIDO_TRUE; } /******************************************************************************* * Function Name : MQTTClient_GpsReport * Description : * Input : None * Output : None * Return : None *******************************************************************************/ HIDO_INT32 MQTTClient_GpsReport(ST_ReportGps *_pstReporGps) { if (l_eConectState == CONNECT_STATE_CONNECTED) { MsgPack_ReportGps(&l_stSendPackage, _pstReporGps); MQTTClient_ReportGps(&l_stSendPackage); } #if 0 ST_MQTTMessage *pstMQTTMessage = HIDO_NULL; HIDO_VLQMemberStruct *pstMember = HIDO_NULL; pstMember = HIDO_VLQGetEnqueueMember(&l_stMQTTClientQueue, sizeof(ST_MQTTMessage) + l_stSendPackage.m_u32Len); if(HIDO_NULL == pstMember) { return HIDO_ERR; } pstMQTTMessage = (ST_MQTTMessage *)pstMember->m_pDataAddr; pstMQTTMessage->m_u32DataLen = l_stSendPackage.m_u32Len; pstMQTTMessage->m_u32QOS = 1; HIDO_UtilSnprintf(pstMQTTMessage->m_acTopic, sizeof(pstMQTTMessage->m_acTopic), l_stConnectParam.m_acGpsTopic); memcpy(pstMQTTMessage->m_au8Data, l_stSendPackage.m_au8Data, l_stSendPackage.m_u32Len); HIDO_VLQEnqueue(&l_stMQTTClientQueue, pstMember); #endif return HIDO_OK; } /******************************************************************************* * Function Name : MQTTClient_Init * Description : TCP�ͻ��˳�ʼ�� * Input : None * Output : None * Return : HIDO_OK �ɹ� * HIDO_ERR ʧ�� *******************************************************************************/ HIDO_INT32 MQTTClient_Init(void) { MQTT_Create(&l_i32MQTTClientID, MQTTClient_MQTTEventProc, HIDO_NULL); HIDO_UINT32 device_id = g_com_map[DEV_ID]; /* ��ʼ�����Ӳ��� */ HIDO_UtilSnprintf(l_stConnectParam.m_acHost, sizeof(l_stConnectParam.m_acHost), "%u.%u.%u.%u", g_com_map[MQTT_IP_0], g_com_map[MQTT_IP_1], g_com_map[MQTT_IP_2], g_com_map[MQTT_IP_3]); l_stConnectParam.m_u16Port = g_com_map[MQTT_PORT]; l_stConnectParam.m_u32KeepAlive = 60; HIDO_UtilSnprintf(l_stConnectParam.m_acClientID, sizeof(l_stConnectParam.m_acClientID), "%u", device_id); HIDO_UtilSnprintf(l_stConnectParam.m_acUsername, sizeof(l_stConnectParam.m_acUsername), ""); HIDO_UtilSnprintf(l_stConnectParam.m_acPassword, sizeof(l_stConnectParam.m_acPassword), ""); // topic HIDO_UtilSnprintf(l_stConnectParam.m_acGpsTopic, sizeof(l_stConnectParam.m_acGpsTopic), "mower/%u/gps", device_id); HIDO_UtilSnprintf(l_stConnectParam.m_acStatusTopic, sizeof(l_stConnectParam.m_acStatusTopic), "mower/%u/status", device_id); HIDO_UtilSnprintf(l_stConnectParam.m_acControlTopic, sizeof(l_stConnectParam.m_acControlTopic), "app/p/mower/%u/control", device_id); HIDO_UtilSnprintf(l_stConnectParam.m_acPathTopic, sizeof(l_stConnectParam.m_acPathTopic), "app/p/mower/%u/path", device_id); HIDO_UtilSnprintf(l_stConnectParam.m_acBaseStationTopic, sizeof(l_stConnectParam.m_acBaseStationTopic), "app/p/mower/%u/basestation", device_id); HIDO_UtilSnprintf(l_stConnectParam.m_acResponseTopic, sizeof(l_stConnectParam.m_acResponseTopic), "mower/%u/response", device_id); HIDO_UtilSnprintf(l_stMQTTConfig.m_acClientID, sizeof(l_stMQTTConfig.m_acClientID), l_stConnectParam.m_acClientID); HIDO_UtilSnprintf(l_stMQTTConfig.m_acUsername, sizeof(l_stMQTTConfig.m_acUsername), l_stConnectParam.m_acUsername); HIDO_UtilSnprintf(l_stMQTTConfig.m_acPassword, sizeof(l_stMQTTConfig.m_acPassword), l_stConnectParam.m_acPassword); HIDO_UtilSnprintf(l_stMQTTConfig.m_acRemoteAddr, sizeof(l_stMQTTConfig.m_acRemoteAddr), l_stConnectParam.m_acHost); l_stMQTTConfig.m_u16RemotePort = l_stConnectParam.m_u16Port; l_stMQTTConfig.m_u8Version = 3; l_stMQTTConfig.m_u32KeepAlive = 60; l_stMQTTConfig.m_u32PktTimeout = 15; l_stMQTTConfig.m_u32RetryTimes = 3; l_stMQTTConfig.m_u8CleanSession = 0; l_stMQTTConfig.m_u8PdpCid = 1; MQTT_Config(l_i32MQTTClientID, &l_stMQTTConfig); MQTT_Subscribe(l_i32MQTTClientID, l_stConnectParam.m_acControlTopic, 1); MQTT_Subscribe(l_i32MQTTClientID, l_stConnectParam.m_acPathTopic, 1); MQTT_Subscribe(l_i32MQTTClientID, l_stConnectParam.m_acBaseStationTopic, 1); /* ��ʼ��״̬ */ l_eConectState = CONNECT_STATE_IDEL; /* ���г�ʼ�� */ HIDO_VLQInit(&l_stMQTTClientQueue, l_au8MQTTSendQueueBuf, MQTT_CLIENT_QUEUE_BUF_SIZE, MQTT_CLIENT_QUEUE_MEMBER_CNT); MQTTClient_Connect(); return HIDO_OK; } /******************************************************************************* * Function Name : MQTTClient_TestPathDownload * Description : 测试路径文件下载功能 * Input : None * Output : None * Return : HIDO_OK 成功 * HIDO_ERR 失败 *******************************************************************************/ HIDO_INT32 MQTTClient_TestPathDownload(void) { HIDO_INT32 ret; const HIDO_CHAR *url = "http://39.99.43.227:8866/api/file/download/21b09df9-9232-4e38-a5cc-19458d324019_data.bin"; HIDO_Debug("[MQTTClient] Start path download test\r\n"); // 启动下载 ret = PathStorage_DownloadFromHTTP(url); if (ret != 0) { HIDO_Debug("[MQTTClient] PathStorage_DownloadFromHTTP failed: %d\r\n", ret); return HIDO_ERR; } HIDO_Debug("[MQTTClient] Download started, check status later\r\n"); return HIDO_OK; } /******************************************************************************* * Function Name : MQTTClient_CheckPathStatus * Description : 检查路径下载和存储状态 * Input : None * Output : None * Return : None *******************************************************************************/ void MQTTClient_CheckPathStatus(void) { E_PathStorageStatus status = PathStorage_GetStatus(); HIDO_UINT8 progress = PathStorage_GetProgress(); HIDO_Debug("[MQTTClient] Path Storage Status: %d, Progress: %u%%\r\n", status, progress); if (status == PATH_STORAGE_STATUS_SUCCESS) { // 下载成功,读取并验证数据 MowerPathHeader_t header; HIDO_INT32 ret = PathStorage_ReadHeader(&header); if (ret == 0) { HIDO_Debug("[MQTTClient] === Path File Info ===\r\n"); HIDO_Debug(" SOF: 0x%04X\r\n", header.sof); HIDO_Debug(" Type: 0x%02X\r\n", header.type); HIDO_Debug(" Version: 0x%02X\r\n", header.version); HIDO_Debug(" Path ID: 0x%08X\r\n", header.path_id); HIDO_Debug(" Timestamp: %u\r\n", header.timestamp); HIDO_Debug(" Origin: (%.8f, %.8f, %.2f)\r\n", header.origin_lon, header.origin_lat, header.origin_alt); HIDO_Debug(" Boundary Count: %u\r\n", header.boundary_count); HIDO_Debug(" Path Count: %u\r\n", header.path_count); // 读取前几个点作为示例 if (header.boundary_count > 0) { PathPoint_t point; ret = PathStorage_ReadPoint(HIDO_TRUE, 0, &point); if (ret == 0) { HIDO_Debug(" First Boundary Point: (%.3f, %.3f)\r\n", point.x, point.y); } } if (header.path_count > 0) { PathPoint_t point; ret = PathStorage_ReadPoint(HIDO_FALSE, 0, &point); if (ret == 0) { HIDO_Debug(" First Path Point: (%.3f, %.3f)\r\n", point.x, point.y); } } HIDO_Debug("[MQTTClient] === Path File Valid ===\r\n"); } else { HIDO_Debug("[MQTTClient] Read header failed: %d\r\n", ret); } } else if (status == PATH_STORAGE_STATUS_FAIL_NETWORK) { HIDO_Debug("[MQTTClient] Download failed: Network error\r\n"); } else if (status == PATH_STORAGE_STATUS_FAIL_FLASH) { HIDO_Debug("[MQTTClient] Download failed: Flash error\r\n"); } else if (status == PATH_STORAGE_STATUS_FAIL_CRC) { HIDO_Debug("[MQTTClient] Download failed: CRC error\r\n"); } else if (status == PATH_STORAGE_STATUS_FAIL_FORMAT) { HIDO_Debug("[MQTTClient] Download failed: Format error\r\n"); } }