STM32H743/APL/MQTTClient.c
@@ -18,7 +18,7 @@
#include "Module.h"
#include "HIDO_Log.h"
#include "stdlib.h"
//#include "Param.h"
// #include "Param.h"
#include "MsgPack.h"
#include "Internet.h"
#include "HIDO_Base64.h"
@@ -26,13 +26,14 @@
#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
#define INVALID_SN 0xFFFFFFFF
#define MQTT_CLIENT_QUEUE_BUF_SIZE (1024 * 2)
#define MQTT_CLIENT_QUEUE_MEMBER_CNT 16
/*******************************************************************************
 *                             Type Definition                                 *
@@ -42,13 +43,13 @@
{
    REPORT_STATE_IDLE,
    REPORT_STATE_BUSY,
}E_ReportState;
} E_ReportState;
typedef enum
{
    RECV_STATE_LEN,
    RECV_STATE_BODY,
}E_RecvState;
} E_RecvState;
typedef enum
{
@@ -59,7 +60,7 @@
    CONNECT_STATE_CONNECTED,
    CONNECT_STATE_DISCONNECT_WAIT,
    CONNECT_STATE_DISCONNECTING,
}E_ConnectState;
} E_ConnectState;
typedef struct
{
@@ -75,7 +76,7 @@
    HIDO_CHAR m_acPathTopic[128];
    HIDO_CHAR m_acBaseStationTopic[128];
    HIDO_CHAR m_acResponseTopic[128];
}ST_MQTTClientParam;
} ST_MQTTClientParam;
/*******************************************************************************
 *                             Local Variable                                  *
@@ -99,7 +100,7 @@
static ST_CtrlData l_stCtrlData;
/* �ڴ���� */
static  HIDO_VLQStruct l_stMQTTClientQueue;
static HIDO_VLQStruct l_stMQTTClientQueue;
static HIDO_UINT8 l_au8MQTTSendQueueBuf[MQTT_CLIENT_QUEUE_BUF_SIZE];
/*******************************************************************************
@@ -123,38 +124,38 @@
{
    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";
        }
    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";
    }
    }
}
@@ -172,16 +173,16 @@
    l_eConectState = _eConnectState;
    HIDO_Log(HIDO_LOG_LEVEL_DEBUG, "l_eConectState = %s -> %s\r\n", MQTTClient_GetConnectStateName(eOldConnectState),
            MQTTClient_GetConnectStateName(l_eConectState));
             MQTTClient_GetConnectStateName(l_eConectState));
    HIDO_DebugEx("l_eConectState = %s -> %s\r\n", MQTTClient_GetConnectStateName(eOldConnectState),
            MQTTClient_GetConnectStateName(l_eConectState));
                 MQTTClient_GetConnectStateName(l_eConectState));
    return HIDO_OK;
}
/*******************************************************************************
 * Function Name     : MQTTClient_ReportGps
 * Description       :
 * Description       :
 * Input             : _pstPackage                    ���ݰ�
 * Output            : None
 * Return            : HIDO_OK                        �ɹ�
@@ -189,11 +190,11 @@
 *******************************************************************************/
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 (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))
            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);
@@ -210,7 +211,7 @@
/*******************************************************************************
 * Function Name     : MQTTClient_ReportStatus
 * Description       : ���ݰ�����
 * Description       : ���ݰ��ϱ�
 * Input             : _pstPackage                    ���ݰ�
 * Output            : None
 * Return            : HIDO_OK                        �ɹ�
@@ -218,11 +219,11 @@
 *******************************************************************************/
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 (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))
            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);
@@ -239,7 +240,7 @@
/*******************************************************************************
 * Function Name     : MQTTClient_ReportResponse
 * Description       : ���ݰ�����
 * Description       : ���ݰ��ϱ�
 * Input             : _pstPackage                    ���ݰ�
 * Output            : None
 * Return            : HIDO_OK                        �ɹ�
@@ -247,11 +248,11 @@
 *******************************************************************************/
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 (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))
            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);
@@ -278,16 +279,15 @@
{
    HIDO_CHAR *pcRequestID = HIDO_NULL;
    HIDO_BOOL bSaveFence = HIDO_FALSE;
    //TODO MsgPack_Parse
    // TODO MsgPack_Parse
    return HIDO_OK;
}
/*******************************************************************************
 * Function Name     : MQTTClient_MQTTEventProc
 * Description       : ���ӷ�����
 * Description       : ���ӷ������¼�����
 * Input             : None
 * Output            : None
 * Return            : None
@@ -298,65 +298,65 @@
    switch (_eEvent)
    {
        case MQTT_EVENT_CONNECT_FAILED:
    case MQTT_EVENT_CONNECT_FAILED:
    {
        HIDO_Log(HIDO_LOG_LEVEL_WARN, "server connect failed\r\n");
        if (CONNECT_STATE_CONNECTING == l_eConectState)
        {
            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;
            l_u32MQTTConnectTick = HIDO_TimerGetTick();
            MQTTClient_SetConnectState(CONNECT_STATE_CLOSED);
        }
        case MQTT_EVENT_CONNECTED:
        break;
    }
    case MQTT_EVENT_CONNECTED:
    {
        HIDO_Log(HIDO_LOG_LEVEL_INFO, "server connect success\r\n");
        if (CONNECT_STATE_CONNECTING == l_eConectState)
        {
            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;
            MQTTClient_SetConnectState(CONNECT_STATE_CONNECTED);
            MQTTClient_EventNotify(MQTT_CLIENT_EVENT_CONNECT);
        }
        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_CLOSED:
    {
        if (CONNECT_STATE_DISCONNECTING == l_eConectState)
        {
            break;
            MQTTClient_SetConnectState(CONNECT_STATE_IDEL);
            MQTTClient_EventNotify(MQTT_CLIENT_EVENT_DISCONNECT);
        }
        case MQTT_EVENT_RECV_DATA:
        else if (l_eConectState != CONNECT_STATE_IDEL)
        {
            HIDO_UINT32 u32RecvLen = 0;
            HIDO_Log(HIDO_LOG_LEVEL_WARN, "socket closed by server\r\n");
            while (MQTT_Recv(l_i32MQTTClientID, l_acRecvTopic, l_au8RecvBuf, sizeof(l_au8RecvBuf), &u32RecvLen) == HIDO_OK)
            {
                // 调用MQTTApp层解析消息
                MQTTApp_ParseMessage(l_acRecvTopic, l_au8RecvBuf, u32RecvLen);
            }
            break;
            l_u32MQTTConnectTick = HIDO_TimerGetTick();
            MQTTClient_SetConnectState(CONNECT_STATE_CLOSED);
        }
        default:
        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)
        {
            break;
            // ����MQTTApp�������Ϣ
            MQTTApp_ParseMessage(l_acRecvTopic, l_au8RecvBuf, u32RecvLen);
        }
        break;
    }
    default:
    {
        break;
    }
    }
}
@@ -365,7 +365,7 @@
 *******************************************************************************/
/*******************************************************************************
 * Function Name     : MQTTClient_IsNetWorkReady
 * Description       : ��������Ƿ�׼����
 * Description       : ��������Ƿ�׼������
 * Input             : None
 * Output            : None
 * Return            : None
@@ -382,7 +382,7 @@
/*******************************************************************************
 * Function Name     : MQTTClient_IsConnected
 * Description       : ����Ƿ�Ҳ����������׼����
 * Description       : ����Ƿ�Ҳ�������粢׼������
 * Input             : None
 * Output            : None
 * Return            : HIDO_TRUE                      ��
@@ -390,7 +390,7 @@
 *******************************************************************************/
HIDO_BOOL MQTTClient_IsConnected(void)
{
    return(HIDO_BOOL)(CONNECT_STATE_CONNECTED == l_eConectState);
    return (HIDO_BOOL)(CONNECT_STATE_CONNECTED == l_eConectState);
}
/*******************************************************************************
@@ -404,85 +404,84 @@
{
    HIDO_UINT32 u32CurTick = HIDO_TimerGetTick();
    switch(l_eConectState)
    switch (l_eConectState)
    {
        /* ��ʼ���� */
        case CONNECT_STATE_CONNECT_WAIT:
    /* ��ʼ���� */
    case CONNECT_STATE_CONNECT_WAIT:
    {
        if (MQTTClient_IsNetWorkReady() == HIDO_FALSE)
        {
            if(MQTTClient_IsNetWorkReady() == HIDO_FALSE)
            {
                break;
            }
            break;
        }
            HIDO_DebugEx("Connect Server\r\n");
        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_CLOSED:
        break;
    }
    /* ������ */
    case CONNECT_STATE_CONNECTED:
    {
        ST_MQTTMessage *pstMQTTMessage = HIDO_NULL;
        HIDO_VLQMemberStruct *pstMember = HIDO_NULL;
        /* �����ڴ���� */
        while ((pstMember = HIDO_VLQGetDequeueMember(&l_stMQTTClientQueue)) != HIDO_NULL)
        {
            if(MQTTClient_IsNetWorkReady() == HIDO_FALSE)
            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;
            }
            /* �������ʱ�䵽 */
            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;
        }
        break;
    }
    /* �ȴ��Ͽ� */
    case CONNECT_STATE_DISCONNECT_WAIT:
    {
        MQTT_Close(l_i32MQTTClientID);
        MQTTClient_SetConnectState(CONNECT_STATE_DISCONNECTING);
        break;
    }
    default:
    {
        break;
    }
    }
}
@@ -580,23 +579,23 @@
{
    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;
        }
    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;
@@ -613,28 +612,28 @@
{
    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;
        }
    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;
@@ -650,13 +649,13 @@
 *******************************************************************************/
HIDO_BOOL MQTTClient_IsReportIdle(HIDO_VOID)
{
    if(HIDO_VLQGetDequeueMember(&l_stMQTTClientQueue) != HIDO_NULL)
    if (HIDO_VLQGetDequeueMember(&l_stMQTTClientQueue) != HIDO_NULL)
    {
        return HIDO_FALSE;
    }
    HIDO_VLQStruct *pstMQTTQueue = MQTT_GetSendQueue(l_i32MQTTClientID);
    if(HIDO_VLQGetDequeueMember(pstMQTTQueue) != HIDO_NULL)
    if (HIDO_VLQGetDequeueMember(pstMQTTQueue) != HIDO_NULL)
    {
        return HIDO_FALSE;
    }
@@ -666,14 +665,14 @@
/*******************************************************************************
 * Function Name     : MQTTClient_GpsReport
 * Description       :
 * Description       :
 * Input             : None
 * Output            : None
 * Return            : None
 *******************************************************************************/
HIDO_INT32 MQTTClient_GpsReport(ST_ReportGps *_pstReporGps)
{
    if(l_eConectState == CONNECT_STATE_CONNECTED)
{
    if (l_eConectState == CONNECT_STATE_CONNECTED)
    {
        MsgPack_ReportGps(&l_stSendPackage, _pstReporGps);
        MQTTClient_ReportGps(&l_stSendPackage);
@@ -710,18 +709,18 @@
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",
    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);
@@ -729,8 +728,8 @@
    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_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);
@@ -752,8 +751,100 @@
    /* ���г�ʼ�� */
    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");
    }
}