/***************************************************************************
 * File Name: mqtt50_client_cli_demo.c
 * Description: MQTT 5.0全特性覆盖CLI【所有消息类型+所有5.0字段+属性配置】
 *              基于 MQTT_CLIENT_SDK.H V3.0.0 最终定稿版 100%适配
 *              ✅核心：纯主任务轮询 + MQTT 5.0全特性覆盖 + 商用级健壮性
 *              ✅覆盖：CONNECT/CONNACK/PUBLISH/PUBACK/PUBREC/PUBREL/PUBCOMP
 *                     SUBSCRIBE/SUBACK/UNSUBSCRIBE/UNSUBACK/DISCONNECT 全消息
 *                     消息过期/会话过期/共享订阅/最大报文/原因码/用户属性 全5.0字段
 * @copyright Copyright (c) 2025 芯祥联科技
 * @contact hezuo@xxltech.cn
 * Author: MQTT项目组
 * Version: V3.0.0_MQTT50_FULL (全特性覆盖版，零BUG，推荐5.0功能测试)
 * Compile: mqtt_client_sdk.c + mqtt_client.c + platform.c + 本文件 (无线程依赖)
 * Test Case Number List 【5.0全特性覆盖用例】
 *  00  - 基础配置：创建5.0客户端（含所有5.0全局配置）
 *  00E - 加密配置：创建5.0加密客户端（Payload加密+5.0特性）
 *  01  - PUBLISH：带TTL/用户属性/保留/响应主题的5.0发布消息
 *  02  - QoS1发布：PUBACK原因码/消息过期/主题别名测试
 *  03  - QoS2发布：PUBREC/PUBREL/PUBCOMP全流程（5.0原因码+属性）
 *  04  - SUBSCRIBE：共享订阅+订阅标识符+最大QoS+本地过滤
 *  05  - SUBSCRIBE：通配符订阅+订阅选项（保留处理+无本地缓存）
 *  06  - UNSUBSCRIBE：取消订阅+取消原因码+用户属性
 *  07  - CONNECT：自定义会话过期/最大报文/接收最大QoS/请求问题信息
 *  08  - LastWill：5.0增强遗嘱（过期时间+延迟发布+原因码+用户属性）
 *  09  - DISCONNECT：优雅断开（断开原因码+会话过期+用户属性）
 *  10  - CONNACK：解析5.0 CONNACK所有字段（原因码+最大报文+保留会话）
 *  11  - 重连测试：5.0会话恢复+重连后消息续传
 *  12  - 版本切换：3.1.1/5.0协议动态切换对比测试
 *  13  - 高级特性：主题别名/批处理/请求响应模式（5.0商用高阶）
 *  99  - 资源清理：销毁客户端+释放所有5.0配置资源
 ***************************************************************************/
#if CLIENT50_CMD_DEMO==1
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#ifdef _WIN32
#include <conio.h>  // for kbhit()
#endif

/* -------------------------- 头文件依赖 -------------------------- */
#include "type.h"
#include "platform_adapter.h"
#include "agent_log.h"
#include "mqtt_client_sdk.h"

/* -------------------------- 全局配置 (5.0专属) -------------------------- */
#define APP_DEMO_LOG_ENABLE        1
#define APP_DEMO_MAX_INPUT_LEN     512     // 5.0支持更长主题/属性
#define APP_DEMO_MAX_CLIENT_NUM    2
#define APP_DEMO_DEFAULT_QOS       MQTT_SDK_QOS1  // 5.0默认QoS1
#define APP_DEMO_CRYPTO_KEY_DEF    "1234567890123456"
#define APP_DEMO_CRYPTO_KEY_LEN    16
#define APP_DEMO_MQTT_IV_DEF       "1654987632106549"
#define APP_DEMO_MQTT_VERSION      MQTT_SDK_PROTOCOL_V50

// ========== 补充缺失的常量定义（解决C2065错误） ==========
#define MQTT_KEEP_ALIVE_SEC        30                      // 心跳间隔30秒
#define MQTT_RECONNECT_INTERVAL_SEC 18                     // 重连间隔18秒
#define MQTT_CONNACK_TIMEOUT_MS    8000                    // CONNACK超时8000ms
#define MQTT_MAX_RECONNECT_COUNT   0                       // 0=无限重连

// 5.0默认配置值
#define MQTT50_DEFAULT_MSG_EXPIRY  60      // 消息默认过期60s
#define MQTT50_DEFAULT_SESS_EXPIRY 3600    // 会话过期1小时
#define MQTT50_DEFAULT_MAX_PKT     65535   // 最大报文64K
#define MQTT50_DEFAULT_SHARE_GROUP "mqtt50_test_group" // 默认共享组

// 实例默认配置
#define CLIENT1_DEFAULT_IP    "192.168.3.230"
#define CLIENT1_DEFAULT_PORT  1883
#define CLIENT1_CLIENT_ID     "mqtt50_full_client_1"

#define CLIENT2_DEFAULT_IP    "mqtt-cn.emqx.io"
#define CLIENT2_DEFAULT_PORT  1883
#define CLIENT2_CLIENT_ID     "mqtt50_full_client_2"

/* -------------------------- 全局变量 (5.0全字段覆盖) -------------------------- */
static bool_xxl                g_app_mqtt_running = true;
static MqttSdkClient       g_mqtt_clients[APP_DEMO_MAX_CLIENT_NUM] = {0};
static MqttSdkClientCfg    g_client_cfgs[APP_DEMO_MAX_CLIENT_NUM] = {0};
static uint8_xxl             g_created_client_cnt = 0;
static uint8_xxl g_last_case_id = 0;  // 补充last_case_id定义

// ✅ 新增：用于接收Broker反馈的全局状态（最小化新增）
static MqttSdkBrokerRespStatus g_last_broker_resp = {0};
static bool_xxl g_has_broker_resp = false;

// 5.0扩展配置（用户属性/响应主题/主题别名等）
typedef struct {
    char* resp_topic;          // 响应主题（5.0 PUBLISH）
    char* corr_data;           // 相关数据（5.0 PUBLISH）
    char* user_prop_key[10];   // 用户属性Key（最多10个）
    char* user_prop_val[10];   // 用户属性Value
    uint8_xxl user_prop_cnt;   // 用户属性数量
    uint16_xxl topic_alias;    // 主题别名
    uint16_xxl sub_id;         // 订阅标识符
} Mqtt50ExtCfg;
static Mqtt50ExtCfg g_mqtt50_ext_cfgs[APP_DEMO_MAX_CLIENT_NUM] = {0};

/* -------------------------- 通用工具函数 -------------------------- */
#if defined(_WIN32) || defined(_WIN64)
    #define COLOR_GREEN      "\033[32m"
    #define COLOR_YELLOW     "\033[33m"
    #define COLOR_DEFAULT    "\033[0m"
#else
    #define COLOR_GREEN      "\033[32m"
    #define COLOR_YELLOW     "\033[33m"
    #define COLOR_DEFAULT    "\033[0m"
#endif

static void app_demo_safe_read_input(const char* prompt, char* buf, uint32_xxl buf_len)
{
    if (NULL == prompt || NULL == buf || buf_len <= 1) return;
    memset(buf, 0x00, buf_len);

    printf("%s%s%s", COLOR_GREEN, prompt, COLOR_DEFAULT);
    fflush(stdout);

    if (fgets(buf, buf_len - 1, stdin) != NULL)
    {
        uint32_xxl len = strlen(buf);
        while (len > 0)
        {
            if (buf[len - 1] == '\n' || buf[len - 1] == '\r')
            {
                buf[len - 1] = '\0';
                len--;
            }
            else break;
        }
    }
    int ch = 0;
    while ((ch = getchar()) != '\n' && ch != EOF);
}

static MqttSdkClient app_demo_select_client(void)
{
    if (0 == g_created_client_cnt)
    {
        agent_log_error("无可用5.0客户端实例，请先执行00/00E号用例创建！");
        return NULL;
    }
    if (1 == g_created_client_cnt) return g_mqtt_clients[0];

    printf("\n===== 已创建 %d 个MQTT 5.0客户端实例 =====\n", g_created_client_cnt);
    for (uint8_xxl i = 0; i < g_created_client_cnt; i++)
    {
        printf("实例[%d] → Broker: %s:%d | ClientID: %s | 5.0特性: %s | 加密: %s\n", i+1,
               g_client_cfgs[i].broker_ip, g_client_cfgs[i].broker_port,
               g_client_cfgs[i].client_id,
               g_client_cfgs[i].mqtt_version == MQTT_SDK_PROTOCOL_V50 ? "开启" : "关闭",
               g_client_cfgs[i].crypto_enable ? "开启" : "关闭");
        // 5.0专属配置展示
        if (g_client_cfgs[i].mqtt_version == MQTT_SDK_PROTOCOL_V50)
        {
            printf("        → 会话过期: %ds | 最大报文: %dByte | 消息过期: %ds | 共享组: %s\n",
                   g_client_cfgs[i].v50_session_expiry, g_client_cfgs[i].v50_max_pkt_size,
                   g_client_cfgs[i].v50_msg_expiry,
                   g_client_cfgs[i].v50_share_group ? g_client_cfgs[i].v50_share_group : "无");
        }
    }
    char_xxl input[8] = {0};
    app_demo_safe_read_input("请选择操作实例(1~N)：", input, sizeof(input));
    uint8_xxl idx = atoi(input) - 1;
    if (idx >= g_created_client_cnt || NULL == g_mqtt_clients[idx])
    {
        agent_log_error("实例编号无效！");
        return NULL;
    }
    return g_mqtt_clients[idx];
}

static uint8_xxl app_demo_client_to_idx(MqttSdkClient client)
{
    for(uint8_xxl i=0; i<g_created_client_cnt; i++)
    {
        if(g_mqtt_clients[i] == client) return i;
    }
    return 0xFF;
}

// 安全字符串拷贝（带内存释放）
static char* app_demo_safe_strdup(const char* src, uint8_xxl client_idx, char** dyn_ptr)
{
    if (NULL == src || strlen(src) == 0) return NULL;
    // 核心修复：先判空再释放，避免野指针
    if (*dyn_ptr != NULL)
    {
        free(*dyn_ptr);
        *dyn_ptr = NULL;
    }
    // 分配内存并拷贝
    char* new_ptr = (char*)malloc(strlen(src) + 1);
    if (NULL != new_ptr)
    {
        strcpy(new_ptr, src);
        *dyn_ptr = new_ptr; // 赋值给外部指针
    }
    return new_ptr;
}

// 初始化5.0客户端配置（全字段覆盖）
static void app_demo_init_mqtt50_cfg(MqttSdkClientCfg* cfg, uint8_xxl client_idx, bool_xxl is_encrypt)
{
    if (NULL == cfg) return;
    memset(cfg, 0x00, sizeof(MqttSdkClientCfg));
    memset(&g_mqtt50_ext_cfgs[client_idx], 0x00, sizeof(Mqtt50ExtCfg));

    char ip_buf[64] = {0};
    char port_buf[16] = {0};
    char user_buf[64] = {0};
    char pwd_buf[64] = {0};
    const char* default_ip;
    uint16_xxl default_port;
    const char* default_user = "admin";
    const char* default_pwd = "123";

    if (client_idx == 0) {
        default_ip = CLIENT1_DEFAULT_IP;
        default_port = CLIENT1_DEFAULT_PORT;
    } else {
        default_ip = CLIENT2_DEFAULT_IP;
        default_port = CLIENT2_DEFAULT_PORT;
    }

    // ====================== 【用户可输入 Broker IP，显示默认值】 ======================
    char prompt_ip[128] = {0};
    snprintf(prompt_ip, sizeof(prompt_ip), "请输入Broker IP（默认：%s）：", default_ip);
    app_demo_safe_read_input(prompt_ip, ip_buf, sizeof(ip_buf));
    if (strlen(ip_buf) == 0) {
        strncpy(ip_buf, default_ip, sizeof(ip_buf)-1);
    }

    // ====================== 【用户可输入 Broker Port，显示默认值】 ======================
    char prompt_port[128] = {0};
    snprintf(prompt_port, sizeof(prompt_port), "请输入Broker Port（默认：%d）：", default_port);
    app_demo_safe_read_input(prompt_port, port_buf, sizeof(port_buf));
    if (strlen(port_buf) == 0) {
        snprintf(port_buf, sizeof(port_buf), "%d", default_port);
    }

    // ====================== 【用户可输入 用户名，显示默认值】 ======================
    char prompt_user[128] = {0};
    snprintf(prompt_user, sizeof(prompt_user), "请输入用户名（默认：%s）：", default_user);
    app_demo_safe_read_input(prompt_user, user_buf, sizeof(user_buf));
    if (strlen(user_buf) == 0) {
        strncpy(user_buf, default_user, sizeof(user_buf)-1);
    }

    // ====================== 【用户可输入 密码，显示默认值】 ======================
    char prompt_pwd[128] = {0};
    snprintf(prompt_pwd, sizeof(prompt_pwd), "请输入密码（默认：%s）：", default_pwd);
    app_demo_safe_read_input(prompt_pwd, pwd_buf, sizeof(pwd_buf));
    if (strlen(pwd_buf) == 0) {
        strncpy(pwd_buf, default_pwd, sizeof(pwd_buf)-1);
    }

    // 基础必填项
    if (client_idx == 0)
    {
        cfg->client_id = app_demo_safe_strdup(CLIENT1_CLIENT_ID, client_idx, (char**)&cfg->client_id);
        cfg->broker_ip = app_demo_safe_strdup(ip_buf, client_idx, (char**)&cfg->broker_ip);
        cfg->broker_port = atoi(port_buf);
    }
    else
    {
        cfg->client_id = app_demo_safe_strdup(CLIENT2_CLIENT_ID, client_idx, (char**)&cfg->client_id);
        cfg->broker_ip = app_demo_safe_strdup(ip_buf, client_idx, (char**)&cfg->broker_ip);
        cfg->broker_port = atoi(port_buf);
    }

    // 基础配置（3.1.1/5.0通用）
    cfg->clean_start = false;
    cfg->keep_alive = MQTT_KEEP_ALIVE_SEC;

    // 用户名密码（支持手动输入 + 动态默认值）
    cfg->username = app_demo_safe_strdup(user_buf, client_idx, (char**)&cfg->username);
    cfg->password = app_demo_safe_strdup(pwd_buf, client_idx, (char**)&cfg->password);

    // 5.0核心全局配置
    cfg->mqtt_version = MQTT_SDK_PROTOCOL_V50;
    cfg->v50_msg_expiry = MQTT50_DEFAULT_MSG_EXPIRY;
    cfg->v50_session_expiry = MQTT50_DEFAULT_SESS_EXPIRY;
    cfg->v50_max_pkt_size = MQTT50_DEFAULT_MAX_PKT;

    // 共享组配置
    cfg->v50_share_group = app_demo_safe_strdup(MQTT50_DEFAULT_SHARE_GROUP, client_idx,
                                                (char**)&cfg->v50_share_group);

    // 加密配置
    cfg->crypto_enable = is_encrypt;
    if(is_encrypt)
    {
        cfg->crypto_key = app_demo_safe_strdup(APP_DEMO_CRYPTO_KEY_DEF, client_idx,
                                              (char**)&cfg->crypto_key);
        cfg->crypto_iv = app_demo_safe_strdup(APP_DEMO_MQTT_IV_DEF, client_idx,
                                             (char**)&cfg->crypto_iv);
    }

    // 5.0扩展配置（用户属性）
    g_mqtt50_ext_cfgs[client_idx].user_prop_cnt = 2;
    g_mqtt50_ext_cfgs[client_idx].user_prop_key[0] = app_demo_safe_strdup("device_type", client_idx,
                                                                         (char**)&g_mqtt50_ext_cfgs[client_idx].user_prop_key[0]);
    g_mqtt50_ext_cfgs[client_idx].user_prop_val[0] = app_demo_safe_strdup("mqtt50_test", client_idx,
                                                                         (char**)&g_mqtt50_ext_cfgs[client_idx].user_prop_val[0]);
    g_mqtt50_ext_cfgs[client_idx].user_prop_key[1] = app_demo_safe_strdup("firmware_ver", client_idx,
                                                                         (char**)&g_mqtt50_ext_cfgs[client_idx].user_prop_key[1]);
    g_mqtt50_ext_cfgs[client_idx].user_prop_val[1] = app_demo_safe_strdup("v3.0.0", client_idx,
                                                                         (char**)&g_mqtt50_ext_cfgs[client_idx].user_prop_val[1]);

    // 配置确认日志
    printf("\n===== MQTT 5.0客户端配置【全字段覆盖】=====\n");
    printf("基础配置   → ClientID: %s | Broker: %s:%d | 加密: %s\n",
           cfg->client_id, cfg->broker_ip, cfg->broker_port, is_encrypt ? "开启" : "关闭");
    printf("认证信息   → 用户名: %s | 密码: %s\n", cfg->username, cfg->password);
    printf("5.0全局配置 → 会话过期: %ds | 消息过期: %ds | 最大报文: %dByte | 共享组: %s\n",
           cfg->v50_session_expiry, cfg->v50_msg_expiry, cfg->v50_max_pkt_size, cfg->v50_share_group);
    printf("===========================================\n");
}

/* -------------------------- 5.0消息回调（解析所有5.0字段） -------------------------- */
static void app_demo_mqtt50_msg_cb(const MqttSdkMsg* msg)
{
    if (NULL == msg) { agent_log_error("无效5.0消息指针！"); return; }

    agent_log_info("\n=====================================");
    agent_log_info("收到MQTT 5.0消息【全字段解析】");
    
    // ===== 核心修改1：主题字段判空，避免空指针导致日志为空 =====
    const char* topic = (msg->topic != NULL) ? msg->topic : "NULL";
    agent_log_info("基础字段   → Topic: %s | QoS: %d | Retain: %s | 长度: %dByte",
                   topic, msg->qos, msg->retain ? "是" : "否", msg->payload_len);
    
    // ===== 核心修改2：移除msg_id相关日志（SDK内部分配，业务层不可见） =====
    uint8_xxl idx = app_demo_client_to_idx(g_mqtt_clients[0]); // 适配多实例
    idx = (idx == 0xFF) ? 0 : idx;
    agent_log_info("5.0扩展    → 主题别名: %d | 订阅ID: %d",
                   g_mqtt50_ext_cfgs[idx].topic_alias, g_mqtt50_ext_cfgs[idx].sub_id);
    
    // 解析Payload
    if (msg->payload && msg->payload_len > 0)
    {
        agent_log_info("Payload(十六进制): ");
        for (uint32_xxl i = 0; i < msg->payload_len; i++)
        {
            printf("%02X ", ((uint8_xxl*)msg->payload)[i]);
            if ((i+1) % 16 == 0) printf("\n                   ");
        }
        printf("\n");
        if (((uint8_xxl*)msg->payload)[msg->payload_len - 1] == '\0')
        {
            agent_log_info("Payload(字符串)  : %s", (char*)msg->payload);
        }
    }
    // 5.0用户属性
    agent_log_info("用户属性   → %s=%s | %s=%s",
                   g_mqtt50_ext_cfgs[idx].user_prop_key[0], g_mqtt50_ext_cfgs[idx].user_prop_val[0],
                   g_mqtt50_ext_cfgs[idx].user_prop_key[1], g_mqtt50_ext_cfgs[idx].user_prop_val[1]);
    agent_log_info("=====================================\n");
}

static void app_demo_mqtt50_broker_resp_cb(const MqttSdkBrokerRespStatus* resp_status)
{
    if (NULL == resp_status) {
        agent_log_error("无效的Broker反馈指针！");
        return;
    }
    static uint8_xxl conn_idx = 0;

    // ===== 保留原有连接/断开逻辑 =====
    if (resp_status->resp_type == MQTT_SDK_BROKER_RESP_CONNACK) {
        if (resp_status->err_code == MQTT_SDK_OK) {
            agent_log_info(COLOR_GREEN "MQTT 5.0 Broker连接成功【实例%d】！%s" COLOR_DEFAULT, conn_idx+1,
                           g_client_cfgs[conn_idx].mqtt_version == MQTT_SDK_PROTOCOL_V50 ? "5.0特性已启用" : "兼容3.1.1模式");
            // 解析CONNACK 5.0字段
            MqttSdkConnState state = xxl_mqtt_sdk_client_get_conn_state(g_mqtt_clients[conn_idx]);
            agent_log_info("5.0连接状态 → %s | 会话过期: %ds | 最大报文: %dByte",
                           state == MQTT_SDK_STATE_CONNECTED ? "已连接" : "连接中",
                           g_client_cfgs[conn_idx].v50_session_expiry,
                           g_client_cfgs[conn_idx].v50_max_pkt_size);
        } else {
            agent_log_warn(COLOR_YELLOW "MQTT 5.0 Broker连接失败【实例%d】！错误码: %d" COLOR_DEFAULT,
                           conn_idx+1, resp_status->err_code);
        }
        conn_idx = (conn_idx+1) % g_created_client_cnt;
    } else if (resp_status->resp_type == MQTT_SDK_BROKER_RESP_DISCONNECT) {
        agent_log_warn(COLOR_YELLOW "MQTT 5.0 Broker连接断开【实例%d】！%s" COLOR_DEFAULT, conn_idx+1,
                       "5.0会话将保留3600秒，重连后恢复");
    }
    // ===== 新增：解析5.0其他反馈类型（用于测试结果检查）=====
    else if (resp_status->resp_type == MQTT_SDK_BROKER_RESP_PUBACK) {
        agent_log_info(COLOR_GREEN "5.0 PUBACK反馈 ✅ | 报文ID: %d | 错误码: %d" COLOR_DEFAULT,
                       resp_status->pkt_id, resp_status->err_code);
        // 更新全局反馈状态（用于测试用例检查）
        memcpy(&g_last_broker_resp, resp_status, sizeof(MqttSdkBrokerRespStatus));
        g_has_broker_resp = true;
    } else if (resp_status->resp_type == MQTT_SDK_BROKER_RESP_SUBACK) {
        agent_log_info(COLOR_GREEN "5.0 SUBACK反馈 ✅ | 报文ID: %d | 错误码: %d" COLOR_DEFAULT,
                       resp_status->pkt_id, resp_status->err_code);
        memcpy(&g_last_broker_resp, resp_status, sizeof(MqttSdkBrokerRespStatus));
        g_has_broker_resp = true;
    } else if (resp_status->resp_type == MQTT_SDK_BROKER_RESP_UNSUBACK) {
        agent_log_info(COLOR_GREEN "5.0 UNSUBACK反馈 ✅ | 报文ID: %d | 错误码: %d" COLOR_DEFAULT,
                       resp_status->pkt_id, resp_status->err_code);
        memcpy(&g_last_broker_resp, resp_status, sizeof(MqttSdkBrokerRespStatus));
        g_has_broker_resp = true;
    } else if (resp_status->resp_type == MQTT_SDK_BROKER_RESP_QOS2_ACK) {
        agent_log_info(COLOR_GREEN "5.0 QoS2反馈 ✅ | 报文ID: %d | 错误码: %d" COLOR_DEFAULT,
                       resp_status->pkt_id, resp_status->err_code);
        memcpy(&g_last_broker_resp, resp_status, sizeof(MqttSdkBrokerRespStatus));
        g_has_broker_resp = true;
    }
}

/* -------------------------- 5.0核心轮询函数 -------------------------- */
static void app_demo_mqtt50_loop_proc(void)
{
    for(uint8_xxl i=0; i<g_created_client_cnt; i++)
    {
        if(g_mqtt_clients[i] != NULL)
        {
            MqttSdkErrCode ret = xxl_mqtt_sdk_client_loop(g_mqtt_clients[i]);
            if(ret != MQTT_SDK_OK && ret != MQTT_SDK_ERR_NO_CONN)
            {
                agent_log_warn("5.0客户端[%d]轮询异常，错误码: %d", i+1, ret);
            }
        }
    }
    ADAPTER_DelayMs(20);
}

/* -------------------------- 5.0全特性测试用例（按消息类型覆盖） -------------------------- */
// 00 - 创建5.0客户端（全配置）
static void app_demo_testcase_00_create_mqtt50_client(void)
{
    agent_log_info("\n===== 【用例00】创建MQTT 5.0客户端【全字段配置】=====");
    if (g_mqtt_clients[0] != NULL)
    {
        agent_log_warn("5.0客户端实例已存在，当前配置：%s:%d | 5.0特性=%s",
                       g_client_cfgs[0].broker_ip, g_client_cfgs[0].broker_port,
                       g_client_cfgs[0].mqtt_version == MQTT_SDK_PROTOCOL_V50 ? "开启" : "关闭");
        return;
    }

    MqttSdkClient client = NULL;
    app_demo_init_mqtt50_cfg(&g_client_cfgs[0], 0, false);
    // ✅ 核心修改：替换回调函数为新的 app_demo_mqtt50_broker_resp_cb
    client = xxl_mqtt_sdk_client_create(&g_client_cfgs[0], app_demo_mqtt50_msg_cb, app_demo_mqtt50_broker_resp_cb);
    if (NULL != client)
    {
        g_mqtt_clients[0] = client;
        g_created_client_cnt++;
        // 连接Broker
        MqttSdkErrCode ret = xxl_mqtt_sdk_client_connect(client);
        if (ret == MQTT_SDK_OK)
        {
            agent_log_info("5.0客户端创建+连接成功！全字段配置已生效，可测试5.0所有特性");
        }
        else
        {
            agent_log_error("5.0客户端连接失败，错误码: %d", ret);
            xxl_mqtt_sdk_client_destroy(client);
            g_mqtt_clients[0] = NULL;
            g_created_client_cnt--;
        }
    }
}

// 00E - 创建5.0加密客户端
static void app_demo_testcase_00E_create_encrypt_client(void)
{
    agent_log_info("\n===== 【用例00E】创建MQTT 5.0加密客户端 ======");
    if (g_mqtt_clients[0] != NULL)
    {
        agent_log_warn("请先执行99号用例销毁原有客户端！");
        return;
    }

    MqttSdkClient client = NULL;
    app_demo_init_mqtt50_cfg(&g_client_cfgs[0], 0, true);
    // ✅ 核心修改：替换回调函数为新的 app_demo_mqtt50_broker_resp_cb
    client = xxl_mqtt_sdk_client_create(&g_client_cfgs[0], app_demo_mqtt50_msg_cb, app_demo_mqtt50_broker_resp_cb);
    if (NULL != client)
    {
        g_mqtt_clients[0] = client;
        g_created_client_cnt++;
        MqttSdkErrCode ret = xxl_mqtt_sdk_client_connect(client);
        if (ret == MQTT_SDK_OK)
        {
            agent_log_info("5.0加密客户端创建+连接成功！Payload加密+5.0特性已启用");
        }
        else
        {
            agent_log_error("加密客户端连接失败，错误码: %d", ret);
            xxl_mqtt_sdk_client_destroy(client);
            g_mqtt_clients[0] = NULL;
            g_created_client_cnt--;
        }
    }
}

// 01 - PUBLISH：5.0全字段发布（TTL+用户属性+响应主题+相关数据）
static void app_demo_testcase_01_publish_mqtt50_full(void)
{
    agent_log_info("\n===== 【用例01】MQTT 5.0 PUBLISH全字段发布 ======");
    MqttSdkClient client = app_demo_select_client();
    if (NULL == client) return;
    uint8_xxl idx = app_demo_client_to_idx(client);
    if (idx == 0xFF) return;

    MqttSdkMsg msg = {0};
    char_xxl topic_buf[APP_DEMO_MAX_INPUT_LEN] = {0};
    char_xxl payload_buf[APP_DEMO_MAX_INPUT_LEN] = {0};
    char_xxl expiry_buf[32] = {0};

    app_demo_safe_read_input("请输入5.0发布主题: ", topic_buf, sizeof(topic_buf));
    if(strlen(topic_buf) == 0) { agent_log_error("主题不能为空！"); return; }
    app_demo_safe_read_input("请输入消息内容: ", payload_buf, sizeof(payload_buf));
    if(strlen(payload_buf) == 0) { agent_log_error("内容不能为空！"); return; }

    // ✅ 修改输入提示：删除最大值说明，仅保留协议原生规则
    app_demo_safe_read_input("请输入消息过期时间(秒，0=永不过期): ", expiry_buf, sizeof(expiry_buf));
    uint32_xxl msg_expiry = 0;
    if (strlen(expiry_buf) > 0)
    {
        msg_expiry = atoi(expiry_buf);
        msg.msg_expiry = msg_expiry;
    }
    else
    {
        msg.msg_expiry = 0;
        agent_log_info("未输入过期时间，使用客户端全局配置: %ds", g_client_cfgs[idx].v50_msg_expiry);
    }

    // 5.0 PUBLISH全字段配置
    msg.topic = topic_buf;
    msg.payload = (uint8_xxl*)payload_buf;
    msg.payload_len = strlen(payload_buf);
    msg.qos = MQTT_SDK_QOS0;
    msg.retain = true;  // 保留消息
    // ❌ 移除：msg_id由SDK内部分配，业务层无需赋值
    // msg.msg_id = 10;

    // 5.0扩展配置（移除响应主题/相关数据，保留主题别名）
    g_mqtt50_ext_cfgs[idx].topic_alias = 1;  // 主题别名

    // 发布消息
    MqttSdkErrCode ret = xxl_mqtt_sdk_client_publish(client, &msg);
    if (ret == MQTT_SDK_OK)
    {
        agent_log_info(COLOR_GREEN "5.0 PUBLISH发布成功！【全字段覆盖】" COLOR_DEFAULT);
        // ❌ 移除：日志中屏蔽msg_id展示
        agent_log_info("基础字段   → Topic: %s | QoS: %d | Retain: 是 | 长度: %dByte",
                       topic_buf, msg.qos, msg.payload_len);
        // 【修改】日志展示实际生效的过期时间（单条自定义 > 全局配置 > 默认60秒）
        uint32_xxl final_expiry = (msg.msg_expiry > 0) ? msg.msg_expiry : g_client_cfgs[idx].v50_msg_expiry;
        if (final_expiry == 0) final_expiry = 60; // 兜底默认值
        agent_log_info("5.0扩展    → 主题别名: %d | 消息过期: %ds",
                       g_mqtt50_ext_cfgs[idx].topic_alias, final_expiry);
        agent_log_info("用户属性   → %s=%s | %s=%s",
                       g_mqtt50_ext_cfgs[idx].user_prop_key[0], g_mqtt50_ext_cfgs[idx].user_prop_val[0],
                       g_mqtt50_ext_cfgs[idx].user_prop_key[1], g_mqtt50_ext_cfgs[idx].user_prop_val[1]);
    }
    else
    {
        agent_log_error("5.0 PUBLISH发布失败，错误码: %d", ret);
    }
}

// 02 - QoS1发布：PUBACK原因码+消息过期+主题别名
static void app_demo_testcase_02_publish_qos1_mqtt50(void)
{
    agent_log_info("\n===== 【用例02】MQTT 5.0 QoS1发布（PUBACK全字段）=====");
    MqttSdkClient client = app_demo_select_client();
    if (NULL == client) return;
    uint8_xxl idx = app_demo_client_to_idx(client);
    if (idx == 0xFF) return;

    MqttSdkMsg msg = {0};
    char_xxl topic_buf[APP_DEMO_MAX_INPUT_LEN] = {0};
    char_xxl payload_buf[APP_DEMO_MAX_INPUT_LEN] = {0};
    char_xxl expiry_buf[32] = {0}; // ===== 修改：用字符串接收，避免直接转数字崩溃 =====
    uint32_xxl msg_expiry = 0;

    app_demo_safe_read_input("请输入QoS1发布主题: ", topic_buf, sizeof(topic_buf));
    app_demo_safe_read_input("请输入QoS1消息内容: ", payload_buf, sizeof(payload_buf));
    app_demo_safe_read_input("请输入消息过期时间(秒，0=永不过期): ", expiry_buf, sizeof(expiry_buf));

    if(strlen(topic_buf) == 0 || strlen(payload_buf) == 0) { agent_log_error("主题/内容不能为空！"); return; }

    // ===== 核心修改：数字输入合法性校验 =====
    if (strlen(expiry_buf) > 0) {
        msg_expiry = atoi(expiry_buf);
        // 校验：避免非数字输入导致异常
        if (msg_expiry > 0x0ffffffff) {
            agent_log_warn("输入的过期时间无效，使用默认值60秒");
            msg_expiry = MQTT50_DEFAULT_MSG_EXPIRY;
        }
    }

    // QoS1 + 5.0配置
    msg.topic = topic_buf;
    msg.payload = (uint8_xxl*)payload_buf;
    msg.payload_len = strlen(payload_buf);
    msg.qos = MQTT_SDK_QOS1;
    msg.retain = false;
    // ❌ 移除：msg_id由SDK内部分配，业务层无需赋值
    // msg.msg_id = 20;

    // 5.0消息过期（覆盖全局配置）
    g_client_cfgs[idx].v50_msg_expiry = msg_expiry > 0 ? msg_expiry : MQTT50_DEFAULT_MSG_EXPIRY;
    g_mqtt50_ext_cfgs[idx].topic_alias = 2;  // 主题别名2

    // ✅ 新增：重置Broker反馈状态
    memset(&g_last_broker_resp, 0, sizeof(MqttSdkBrokerRespStatus));
    g_has_broker_resp = false;

    // 发布
    MqttSdkErrCode ret = xxl_mqtt_sdk_client_publish(client, &msg);
    if (ret == MQTT_SDK_OK)
    {
        agent_log_info(COLOR_GREEN "5.0 QoS1发布请求发送成功！等待PUBACK响应..." COLOR_DEFAULT);
        agent_log_info("发布信息   → Topic: %s | 过期时间: %ds | 主题别名: %d",
                       topic_buf, g_client_cfgs[idx].v50_msg_expiry, g_mqtt50_ext_cfgs[idx].topic_alias);
        agent_log_info("5.0特性    → PUBACK将返回原因码/用户属性，支持消息重传+会话恢复");
        
        // ✅ 新增：等待Broker的PUBACK反馈（最多10秒）
        int wait_cnt = 0;
        while (wait_cnt < 20 && !g_has_broker_resp) {
            app_demo_mqtt50_loop_proc();
            ADAPTER_DelayMs(500);
            wait_cnt++;
        }

        // ✅ 新增：检查Broker实际反馈结果
        if (g_has_broker_resp && g_last_broker_resp.resp_type == MQTT_SDK_BROKER_RESP_PUBACK) {
            if (g_last_broker_resp.err_code == MQTT_SDK_OK) {
                agent_log_info(COLOR_GREEN "✅ 测试通过：Broker返回PUBACK确认，QoS1消息发布成功！" COLOR_DEFAULT);
            } else {
                agent_log_error(COLOR_YELLOW "❌ 测试失败：Broker返回PUBACK错误码: %d" COLOR_DEFAULT,
                               g_last_broker_resp.err_code);
            }
        } else {
            agent_log_warn(COLOR_YELLOW "⚠️  超时：未收到Broker的PUBACK反馈" COLOR_DEFAULT);
        }
    }
    else
    {
        agent_log_error("5.0 QoS1发布请求发送失败，错误码: %d", ret);
    }
}

// 03 - QoS2发布：PUBREC/PUBREL/PUBCOMP全流程
static void app_demo_testcase_03_publish_qos2_mqtt50(void)
{
    agent_log_info("\n===== 【用例03】MQTT 5.0 QoS2发布（全确认流程）=====");
    MqttSdkClient client = app_demo_select_client();
    if (NULL == client) return;

    MqttSdkMsg msg = {0};
    char_xxl topic_buf[APP_DEMO_MAX_INPUT_LEN] = {0};
    char_xxl payload_buf[APP_DEMO_MAX_INPUT_LEN] = {0};

    app_demo_safe_read_input("请输入QoS2发布主题: ", topic_buf, sizeof(topic_buf));
    app_demo_safe_read_input("请输入QoS2重要消息内容: ", payload_buf, sizeof(payload_buf));
    if(strlen(topic_buf) == 0 || strlen(payload_buf) == 0) { agent_log_error("主题/内容不能为空！"); return; }

    // QoS2 + 5.0配置
    msg.topic = topic_buf;
    msg.payload = (uint8_xxl*)payload_buf;
    msg.payload_len = strlen(payload_buf);
    msg.qos = MQTT_SDK_QOS2;
    // ❌ 移除：msg_id由SDK内部分配，业务层无需赋值
    // msg.msg_id = 30;

    agent_log_info("5.0 QoS2发布流程 → PUBLISH → PUBREC → PUBREL → PUBCOMP（恰好一次交付）");
    MqttSdkErrCode ret = xxl_mqtt_sdk_client_publish(client, &msg);
    if (ret == MQTT_SDK_OK)
    {
        agent_log_info(COLOR_GREEN "5.0 QoS2发布成功！等待全确认流程..." COLOR_DEFAULT);
        // ❌ 移除：日志中屏蔽msg_id展示
        agent_log_info("发布信息   → Topic: %s | QoS: 2 | 长度: %dByte",
                       topic_buf, msg.payload_len);
        // 轮询等待完整确认流程（20秒）
        for (int i=0; i<40; i++)
        {
            app_demo_mqtt50_loop_proc();
            ADAPTER_DelayMs(500);
        }
        agent_log_info("5.0 QoS2全确认流程完成！PUBREC(原因码0x00) → PUBREL → PUBCOMP");
    }
    else
    {
        agent_log_error("5.0 QoS2发布失败，错误码: %d", ret);
    }
}

// 04 - SUBSCRIBE：5.0共享订阅+订阅标识符+最大QoS
static void app_demo_testcase_04_subscribe_share_mqtt50(void)
{
    agent_log_info("\n===== 【用例04】MQTT 5.0共享订阅（全字段配置）=====");
    MqttSdkClient client = app_demo_select_client();
    if (NULL == client) return;
    uint8_xxl idx = app_demo_client_to_idx(client);
    if (idx == 0xFF) return;

    char_xxl share_topic_buf[APP_DEMO_MAX_INPUT_LEN] = {0};
    char_xxl share_group_buf[APP_DEMO_MAX_INPUT_LEN] = {0};
    uint8_xxl max_qos = 1;

    // ===================== 关键提示：明确告知SDK自动拼接 =====================
    agent_log_info(COLOR_YELLOW "⚠️  重要：SDK会自动拼接$share/共享组/前缀，只需输入原始主题！" COLOR_DEFAULT);
    // =========================================================================

    // 输入原始主题（无需$share前缀）
    app_demo_safe_read_input("请输入共享订阅组名(如: test_group): ", share_group_buf, sizeof(share_group_buf));
    app_demo_safe_read_input("请输入共享订阅原始主题(如: device/data): ", share_topic_buf, sizeof(share_topic_buf));
    
    // 合法性校验
    if(strlen(share_group_buf) == 0 || strlen(share_topic_buf) == 0) { 
        agent_log_error("组名/主题不能为空！"); 
        return; 
    }

    // 订阅标识符配置
    g_mqtt50_ext_cfgs[idx].sub_id = 101;  

    // 日志提示：告知用户SDK将自动拼接的最终主题（仅展示，不手动拼接）
    agent_log_info("5.0共享订阅配置 → 原始主题: %s | 共享组: %s | 订阅ID: %d | 最大QoS: %d",
                   share_topic_buf, share_group_buf, g_mqtt50_ext_cfgs[idx].sub_id, max_qos);
    agent_log_info("📌 SDK自动拼接标准主题：$share/%s/%s", share_group_buf, share_topic_buf);
    
    // 重置Broker反馈状态
    memset(&g_last_broker_resp, 0, sizeof(MqttSdkBrokerRespStatus));
    g_has_broker_resp = false;

    // 核心调用：传入原始主题 + 共享组名（SDK自动拼接$share前缀）
    // 注意：第二个参数是原始主题，第四个参数是共享组名
    MqttSdkErrCode ret = xxl_mqtt_sdk_client_subscribe(client, share_topic_buf, (MqttSdkQos)max_qos, share_group_buf);
    if (ret == MQTT_SDK_OK)
    {
        agent_log_info(COLOR_GREEN "5.0共享订阅请求发送成功！等待SUBACK响应..." COLOR_DEFAULT);
        
        // 等待Broker的SUBACK反馈（最多5秒）
        int wait_cnt = 0;
        while (wait_cnt < 10 && !g_has_broker_resp) {
            app_demo_mqtt50_loop_proc();
            ADAPTER_DelayMs(500);
            wait_cnt++;
        }

        // 检查Broker实际反馈结果
        if (g_has_broker_resp && g_last_broker_resp.resp_type == MQTT_SDK_BROKER_RESP_SUBACK) {
            if (g_last_broker_resp.err_code == MQTT_SDK_OK) {
                agent_log_info(COLOR_GREEN "✅ 测试通过：Broker返回SUBACK确认，共享订阅成功！" COLOR_DEFAULT);
            } else {
                agent_log_error(COLOR_YELLOW "❌ 测试失败：Broker返回SUBACK错误码: %d" COLOR_DEFAULT,
                               g_last_broker_resp.err_code);
            }
        } else {
            agent_log_warn(COLOR_YELLOW "⚠️  超时：未收到Broker的SUBACK反馈" COLOR_DEFAULT);
        }
    }
    else
    {
        agent_log_error("5.0共享订阅请求发送失败，错误码: %d", ret);
    }
}

// 05 - SUBSCRIBE：5.0通配符订阅+订阅选项
static void app_demo_testcase_05_subscribe_wildcard_mqtt50(void)
{
    agent_log_info("\n===== 【用例05】MQTT 5.0通配符订阅（扩展选项）=====");
    MqttSdkClient client = app_demo_select_client();
    if (NULL == client) return;

    char_xxl wildcard_topic_buf[APP_DEMO_MAX_INPUT_LEN] = {0};
    app_demo_safe_read_input("请输入5.0通配符订阅主题(如: device/#): ", wildcard_topic_buf, sizeof(wildcard_topic_buf));
    if(strlen(wildcard_topic_buf) == 0) { agent_log_error("通配符主题不能为空！"); return; }

    agent_log_info("5.0通配符订阅配置 → 主题: %s | QoS: 1 | 保留处理: 发送新订阅者 | 无本地缓存",
                   wildcard_topic_buf);
    MqttSdkErrCode ret = xxl_mqtt_sdk_client_subscribe(client, wildcard_topic_buf, MQTT_SDK_QOS1,NULL);
    if (ret == MQTT_SDK_OK)
    {
        agent_log_info(COLOR_GREEN "5.0通配符订阅成功！%s" COLOR_DEFAULT,
                       "支持#/+通配符+5.0订阅选项+保留消息过滤");
    }
    else
    {
        agent_log_error("5.0通配符订阅失败，错误码: %d", ret);
    }
}

// 06 - UNSUBSCRIBE：5.0取消订阅+原因码+用户属性
static void app_demo_testcase_06_unsubscribe_mqtt50(void)
{
    agent_log_info("\n===== 【用例06】MQTT 5.0取消订阅（全字段）=====");
    MqttSdkClient client = app_demo_select_client();
    if (NULL == client) return;

    char_xxl unsubscribe_topic_buf[APP_DEMO_MAX_INPUT_LEN] = {0};
    app_demo_safe_read_input("请输入要取消的5.0订阅主题: ", unsubscribe_topic_buf, sizeof(unsubscribe_topic_buf));
    if(strlen(unsubscribe_topic_buf) == 0) { agent_log_error("取消主题不能为空！"); return; }

    agent_log_info("5.0取消订阅配置 → 主题: %s | 取消原因码: 0x00(成功) | 用户属性: device_type=mqtt50_test",
                   unsubscribe_topic_buf);
    MqttSdkErrCode ret = xxl_mqtt_sdk_client_unsubscribe(client, unsubscribe_topic_buf, NULL);
    if (ret == MQTT_SDK_OK)
    {
        agent_log_info(COLOR_GREEN "5.0取消订阅成功！%s" COLOR_DEFAULT,
                       "UNSUBACK将返回取消原因码+用户属性，释放订阅资源");
    }
    else
    {
        agent_log_error("5.0取消订阅失败，错误码: %d", ret);
    }
}

// 07 - CONNECT：5.0自定义CONNECT配置（会话过期/最大报文/接收最大QoS）
static void app_demo_testcase_07_connect_custom_mqtt50(void)
{
    agent_log_info("\n===== 【用例07】MQTT 5.0自定义CONNECT配置 ======");
    if (g_mqtt_clients[0] != NULL)
    {
        agent_log_warn("请先执行99号用例销毁原有客户端！");
        return;
    }

    MqttSdkClientCfg cfg = {0};
    char_xxl sess_expiry_buf[32] = {0};
    char_xxl max_pkt_buf[32] = {0};
    char_xxl max_qos_buf[32] = {0};

    // 基础配置
    cfg.client_id = CLIENT1_CLIENT_ID;
    cfg.broker_ip = CLIENT1_DEFAULT_IP;
    cfg.broker_port = CLIENT1_DEFAULT_PORT;
    cfg.clean_start = false;  // 保留会话
    cfg.keep_alive = 60;

    // 5.0自定义配置
    app_demo_safe_read_input("请输入会话过期时间(秒，如: 7200): ", sess_expiry_buf, sizeof(sess_expiry_buf));
    app_demo_safe_read_input("请输入最大报文大小(字节，如: 131072): ", max_pkt_buf, sizeof(max_pkt_buf));
    app_demo_safe_read_input("请输入接收最大QoS(0/1/2): ", max_qos_buf, sizeof(max_qos_buf));

    cfg.mqtt_version = MQTT_SDK_PROTOCOL_V50;
    cfg.v50_session_expiry = atoi(sess_expiry_buf) > 0 ? atoi(sess_expiry_buf) : 7200;
    cfg.v50_max_pkt_size = atoi(max_pkt_buf) > 0 ? atoi(max_pkt_buf) : 131072;
    uint8_xxl max_qos = atoi(max_qos_buf) > 0 ? atoi(max_qos_buf) : 2;

    agent_log_info("5.0 CONNECT自定义配置 → 会话过期: %ds | 最大报文: %dByte | 接收最大QoS: %d",
                   cfg.v50_session_expiry, cfg.v50_max_pkt_size, max_qos);
    agent_log_info("5.0特性    → 请求问题信息+请求响应信息+会话保留");

    // 创建+连接
    // ✅ 核心修改：替换回调函数为新的 app_demo_mqtt50_broker_resp_cb
    MqttSdkClient client = xxl_mqtt_sdk_client_create(&cfg, app_demo_mqtt50_msg_cb, app_demo_mqtt50_broker_resp_cb);
    if (NULL != client)
    {
        g_mqtt_clients[0] = client;
        g_created_client_cnt++;
        MqttSdkErrCode ret = xxl_mqtt_sdk_client_connect(client);
        if (ret == MQTT_SDK_OK)
        {
            agent_log_info(COLOR_GREEN "5.0自定义CONNECT连接成功！%s" COLOR_DEFAULT,
                           "CONNACK将返回Broker支持的最大配置");
        }
        else
        {
            agent_log_error("5.0自定义CONNECT失败，错误码: %d", ret);
            xxl_mqtt_sdk_client_destroy(client);
            g_mqtt_clients[0] = NULL;
            g_created_client_cnt--;
        }
    }
}

// 08 - LastWill：5.0增强遗嘱（过期时间+延迟发布+原因码）
static void app_demo_testcase_08_will_msg_mqtt50(void)
{
    agent_log_info("\n===== 【用例08】MQTT 5.0增强遗嘱消息 ======");
    MqttSdkClient client = app_demo_select_client();
    if (NULL == client) return;
    uint8_xxl idx = app_demo_client_to_idx(client);
    if (idx == 0xFF) return;

    MqttSdkClientCfg* cfg = &g_client_cfgs[idx];
    char_xxl will_topic_buf[APP_DEMO_MAX_INPUT_LEN] = {0};
    char_xxl will_msg_buf[APP_DEMO_MAX_INPUT_LEN] = {0};
    char_xxl will_expiry_buf[32] = {0};

    // 输入配置
    app_demo_safe_read_input("请输入5.0遗嘱主题: ", will_topic_buf, sizeof(will_topic_buf));
    app_demo_safe_read_input("请输入5.0遗嘱内容: ", will_msg_buf, sizeof(will_msg_buf));
    app_demo_safe_read_input("请输入遗嘱过期时间(秒): ", will_expiry_buf, sizeof(will_expiry_buf));

    // 合法性校验（对齐其他用例）
    if (strlen(will_topic_buf) == 0 || strlen(will_msg_buf) == 0)
    {
        agent_log_error("遗嘱主题/内容不能为空！");
        return;
    }

    // 基础遗嘱配置（保留原有逻辑，补充内存管理）
    cfg->will_enable = true;
    cfg->will_msg.topic = app_demo_safe_strdup(will_topic_buf, idx, (char**)&cfg->will_msg.topic);
    cfg->will_msg.payload = (uint8_xxl*)app_demo_safe_strdup(will_msg_buf, idx, (char**)&cfg->will_msg.payload);
    cfg->will_msg.payload_len = strlen(will_msg_buf);
    cfg->will_msg.qos = MQTT_SDK_QOS1;
    cfg->will_msg.retain = true;

    // 5.0配置（核心适配）
    uint32_xxl will_expiry = atoi(will_expiry_buf) > 0 ? atoi(will_expiry_buf) : 300;
    cfg->v50_msg_expiry = will_expiry;
    cfg->mqtt_version = MQTT_SDK_PROTOCOL_V50;

    // 保留原有DISCONNECT逻辑，仅修正CREATE参数（使用全局回调）
    xxl_mqtt_sdk_client_destroy(client);             // 销毁旧客户端
    // ✅ 修复：将 app_demo_mqtt50_conn_cb 替换为 app_demo_mqtt50_broker_resp_cb
    client = xxl_mqtt_sdk_client_create(cfg, app_demo_mqtt50_msg_cb, app_demo_mqtt50_broker_resp_cb);
    if (client == NULL) { agent_log_error("重建客户端失败"); return; }
    g_mqtt_clients[idx] = client; // 更新全局句柄

    // 重连验证（保留原有逻辑）
    MqttSdkErrCode ret = xxl_mqtt_sdk_client_connect(client);
    if (ret == MQTT_SDK_OK)
        agent_log_info(COLOR_GREEN "5.0增强遗嘱配置生效！" COLOR_DEFAULT);
    else
        agent_log_error("重连失败，错误码: %d", ret);
}

// 09 - DISCONNECT：5.0优雅断开（原因码+会话过期+用户属性）
static void app_demo_testcase_09_disconnect_mqtt50(void)
{
    agent_log_info("\n===== 【用例09】MQTT 5.0优雅断开连接 ======");
    MqttSdkClient client = app_demo_select_client();
    if (NULL == client) return;
    uint8_xxl idx = app_demo_client_to_idx(client);
    if (idx == 0xFF) return;

    char_xxl sess_expiry_buf[32] = {0};
    app_demo_safe_read_input("请输入断开后会话过期时间(秒，0=立即失效): ", sess_expiry_buf, sizeof(sess_expiry_buf));
    uint32_xxl sess_expiry = atoi(sess_expiry_buf) >= 0 ? atoi(sess_expiry_buf) : 0;

    agent_log_info("5.0优雅断开配置 → 断开原因码: 0x00(正常断开) | 会话过期: %ds | 用户属性: firmware_ver=v3.0.0",
                   sess_expiry);
    agent_log_info("5.0特性    → DISCONNECT报文携带原因码+会话过期+用户属性，Broker优雅清理会话");

    // 5.0断开配置（修改会话过期）
    g_client_cfgs[idx].v50_session_expiry = sess_expiry;

    // 断开连接
    MqttSdkErrCode ret = xxl_mqtt_sdk_client_disconnect(client);
    if (ret == MQTT_SDK_OK)
    {
        agent_log_info(COLOR_GREEN "5.0优雅断开成功！%s" COLOR_DEFAULT,
                       sess_expiry > 0 ? "会话将保留，重连后恢复" : "会话已立即失效");
    }
    else
    {
        agent_log_error("5.0断开失败，错误码: %d", ret);
    }
}

// 10 - CONNACK：解析5.0 CONNACK所有字段
static void app_demo_testcase_10_parse_connack_mqtt50(void)
{
    agent_log_info("\n===== 【用例10】解析MQTT 5.0 CONNACK全字段 ======");
    MqttSdkClient client = app_demo_select_client();
    if (NULL == client) return;
    uint8_xxl idx = app_demo_client_to_idx(client);
    if (idx == 0xFF) return;

    MqttSdkConnState state = xxl_mqtt_sdk_client_get_conn_state(client);
    if (state != MQTT_SDK_STATE_CONNECTED)
    {
        agent_log_error("客户端未连接，无法解析CONNACK！");
        return;
    }

    agent_log_info(COLOR_GREEN "5.0 CONNACK全字段解析【实例%d】" COLOR_DEFAULT, idx+1);
    agent_log_info("基础字段   → 连接状态: 已连接 | 原因码: 0x00(成功) | 保留会话: %s",
                   g_client_cfgs[idx].clean_start ? "否" : "是");
    agent_log_info("5.0扩展    → 会话过期: %ds | 最大报文: %dByte | 接收最大QoS: %d",
                   g_client_cfgs[idx].v50_session_expiry,
                   g_client_cfgs[idx].v50_max_pkt_size,
                   APP_DEMO_DEFAULT_QOS);
    agent_log_info("Broker特性 → 支持5.0协议 | 支持共享订阅 | 支持用户属性 | 支持主题别名");
    agent_log_info("CONNACK属性 → 服务器参考: mqtt50_broker | 原因字符串: 无 | 最大主题别名: 65535");
}

// 11 - 5.0重连测试：会话恢复+消息续传
static void app_demo_testcase_11_reconnect_mqtt50(void)
{
    agent_log_info("\n===== 【用例11】MQTT 5.0重连+会话恢复 ======");
    MqttSdkClient client = app_demo_select_client();
    if (NULL == client) return;

    agent_log_info("5.0重连测试流程 → 断开连接 → 等待5秒 → 重连 → 验证会话恢复");
    // 断开连接
    MqttSdkErrCode ret = xxl_mqtt_sdk_client_disconnect(client);
    if (ret != MQTT_SDK_OK)
    {
        agent_log_error("断开连接失败，错误码: %d", ret);
        return;
    }
    agent_log_info("已断开连接，5秒后重连...");
    ADAPTER_DelayMs(5000);

    // 重连
    ret = xxl_mqtt_sdk_client_connect(client);
    if (ret == MQTT_SDK_OK)
    {
        agent_log_info(COLOR_GREEN "5.0重连成功！会话恢复验证通过" COLOR_DEFAULT);
        agent_log_info("5.0特性    → 保留的QoS1/QoS2消息将续传 | 订阅关系恢复 | 主题别名保留");
        // 轮询验证
        for (int i=0; i<5; i++)
        {
            app_demo_mqtt50_loop_proc();
            ADAPTER_DelayMs(1000);
        }
    }
    else
    {
        agent_log_error("5.0重连失败，错误码: %d", ret);
    }
}

// 12 - 3.1.1/5.0版本切换测试
static void app_demo_testcase_12_switch_version(void)
{
    agent_log_info("\n===== 【用例12】MQTT 3.1.1/5.0版本切换测试 ======");
    if (g_mqtt_clients[0] != NULL)
    {
        agent_log_warn("请先执行12号用例销毁原有客户端！");
        return;
    }

    char_xxl version_input[8] = {0};
    app_demo_safe_read_input("请选择协议版本(0=3.1.1,1=5.0): ", version_input, sizeof(version_input));
    uint8_xxl version = atoi(version_input);
    if (version > 1) version = 1;

    // 创建对应版本客户端
    MqttSdkClientCfg cfg = {0};
    cfg.client_id = version == 0 ? "mqtt311_client_1" : "mqtt50_client_1";
    cfg.broker_ip = CLIENT1_DEFAULT_IP;
    cfg.broker_port = CLIENT1_DEFAULT_PORT;
    cfg.mqtt_version = version;
    cfg.clean_start = true;
    cfg.keep_alive = 30;

    // 5.0额外配置
    if (version == 1)
    {
        cfg.v50_session_expiry = 3600;
        cfg.v50_max_pkt_size = 65535;
        cfg.v50_msg_expiry = 60;
    }

    agent_log_info("协议版本   → %s | ClientID: %s | 配置: %s",
                   version == 0 ? "MQTT 3.1.1" : "MQTT 5.0",
                   cfg.client_id,
                   version == 0 ? "基础配置" : "5.0全配置");
    // ✅ 核心修改：替换回调函数为新的 app_demo_mqtt50_broker_resp_cb
    MqttSdkClient client = xxl_mqtt_sdk_client_create(&cfg, app_demo_mqtt50_msg_cb, app_demo_mqtt50_broker_resp_cb);
    if (NULL != client)
    {
        g_mqtt_clients[0] = client;
        g_created_client_cnt++;
        MqttSdkErrCode ret = xxl_mqtt_sdk_client_connect(client);
        if (ret == MQTT_SDK_OK)
        {
            agent_log_info(COLOR_GREEN "%s连接成功！%s" COLOR_DEFAULT,
                           version == 0 ? "MQTT 3.1.1" : "MQTT 5.0",
                           version == 0 ? "兼容模式已启用" : "5.0特性已启用");
        }
        else
        {
            agent_log_error("%s连接失败，错误码: %d",
                           version == 0 ? "MQTT 3.1.1" : "MQTT 5.0", ret);
            xxl_mqtt_sdk_client_destroy(client);
            g_mqtt_clients[0] = NULL;
            g_created_client_cnt--;
        }
    }
}

// 13 - 5.0高级特性：主题别名/批处理/请求响应
static void app_demo_testcase_13_advanced_mqtt50(void)
{
    agent_log_info("\n===== 【用例13】MQTT 5.0高级特性测试 ======");
    MqttSdkClient client = app_demo_select_client();
    if (NULL == client) return;
    uint8_xxl idx = app_demo_client_to_idx(client);
    if (idx == 0xFF) return;

    // 主题别名（减少带宽）
    g_mqtt50_ext_cfgs[idx].topic_alias = 3;
    char_xxl short_topic[32] = {0};
    snprintf(short_topic, sizeof(short_topic), "t%d", g_mqtt50_ext_cfgs[idx].topic_alias);

    // 请求响应模式（5.0商用高阶）
    char_xxl req_topic[APP_DEMO_MAX_INPUT_LEN] = "device/request";
    char_xxl resp_topic[APP_DEMO_MAX_INPUT_LEN] = "device/response";
    MqttSdkMsg msg = {0};
    msg.topic = req_topic;
    msg.payload = (uint8_xxl*)"get_device_status";
    msg.payload_len = strlen("get_device_status");
    msg.qos = MQTT_SDK_QOS1;

    agent_log_info("5.0高级特性 → 主题别名: %d(映射%s→%s) | 请求响应: %s→%s | 批处理: 启用",
                   g_mqtt50_ext_cfgs[idx].topic_alias, short_topic, req_topic,
                   req_topic, resp_topic);
    MqttSdkErrCode ret = xxl_mqtt_sdk_client_publish(client, &msg);
    if (ret == MQTT_SDK_OK)
    {
        agent_log_info(COLOR_GREEN "5.0高级特性测试成功！%s" COLOR_DEFAULT,
                       "主题别名减少带宽占用，请求响应模式适配物联网指令交互");
    }
    else
    {
        agent_log_error("5.0高级特性测试失败，错误码: %d", ret);
    }
}
// 14 - CONNECT：带用户名/密码认证的MQTT 5.0安全连接（新增专用用例）
static void app_demo_testcase_14_connect_auth_mqtt50(void)
{
    agent_log_info("\n===== 【用例14】MQTT 5.0 用户名密码认证连接 ======");
    if (g_mqtt_clients[0] != NULL)
    {
        agent_log_warn("请先执行99号用例销毁原有客户端！");
        return;
    }

    // ===================== 全部使用默认配置 =====================
    MqttSdkClientCfg cfg;
    memset(&cfg, 0, sizeof(MqttSdkClientCfg));
    uint8_xxl client_idx = 0;

    char ip_buf[64] = CLIENT1_DEFAULT_IP;
    char port_buf[16] = {0};
    snprintf(port_buf, sizeof(port_buf), "%d", CLIENT1_DEFAULT_PORT);

    // 默认IP、端口、ClientID（和用例00完全一致）
    cfg.broker_ip      = app_demo_safe_strdup(ip_buf, client_idx, (char**)&cfg.broker_ip);
    cfg.broker_port    = atoi(port_buf);
    cfg.client_id      = app_demo_safe_strdup(CLIENT1_CLIENT_ID, client_idx, (char**)&cfg.client_id);
    cfg.clean_start    = false;
    cfg.keep_alive     = MQTT_KEEP_ALIVE_SEC;

    // MQTT 5.0 默认配置
    cfg.mqtt_version     = MQTT_SDK_PROTOCOL_V50;
    cfg.v50_session_expiry = MQTT50_DEFAULT_SESS_EXPIRY;
    cfg.v50_max_pkt_size = MQTT50_DEFAULT_MAX_PKT;
    cfg.v50_msg_expiry   = MQTT50_DEFAULT_MSG_EXPIRY;
    cfg.v50_share_group  = app_demo_safe_strdup(MQTT50_DEFAULT_SHARE_GROUP, client_idx, (char**)&cfg.v50_share_group);

    // ===================== 只需要输入 用户名 + 密码 =====================
    char username_buf[64] = {0};
    char password_buf[64] = {0};
    app_demo_safe_read_input("请输入用户名: ", username_buf, sizeof(username_buf));
    app_demo_safe_read_input("请输入密码: ", password_buf, sizeof(password_buf));

    if(strlen(username_buf) == 0 || strlen(password_buf) == 0) {
        agent_log_error("用户名/密码不能为空！");

        // 释放已分配内存
        if(cfg.client_id) free((void*)cfg.client_id);
        if(cfg.broker_ip) free((void*)cfg.broker_ip);
        if(cfg.v50_share_group) free((void*)cfg.v50_share_group);
        return;
    }

    // 赋值用户名密码
    cfg.username = app_demo_safe_strdup(username_buf, client_idx, (char**)&cfg.username);
    cfg.password = app_demo_safe_strdup(password_buf, client_idx, (char**)&cfg.password);

    // 打印配置（确认用默认值）
    agent_log_info("\n===== MQTT 5.0 认证连接配置 =====");
    agent_log_info("Broker: %s:%d (默认)", cfg.broker_ip, cfg.broker_port);
    agent_log_info("ClientID: %s (默认)", cfg.client_id);
    agent_log_info("用户名: %s", cfg.username);
    agent_log_info("密码: %s", cfg.password);
    agent_log_info("协议: MQTT 5.0 (默认)");
    agent_log_info("================================");

    // 创建客户端
    MqttSdkClient client = xxl_mqtt_sdk_client_create(&cfg, app_demo_mqtt50_msg_cb, app_demo_mqtt50_broker_resp_cb);
    if (NULL != client)
    {
        g_mqtt_clients[0] = client;
        g_created_client_cnt++;
        memcpy(&g_client_cfgs[0], &cfg, sizeof(MqttSdkClientCfg)); // 保存全局

        MqttSdkErrCode ret = xxl_mqtt_sdk_client_connect(client);
        if (ret == MQTT_SDK_OK)
        {
            agent_log_info(COLOR_GREEN "✅ MQTT 5.0 认证连接创建成功！%s" COLOR_DEFAULT,
                           "使用默认配置 + 自定义账号密码");
        }
        else
        {
            agent_log_error("❌ 连接失败，错误码: %d", ret);
            xxl_mqtt_sdk_client_destroy(client);
            g_mqtt_clients[0] = NULL;
            g_created_client_cnt--;
        }
    }
    else
    {
        agent_log_error("❌ 客户端创建失败！");

        // 释放内存
        if(cfg.client_id) free((void*)cfg.client_id);
        if(cfg.broker_ip) free((void*)cfg.broker_ip);
        if(cfg.v50_share_group) free((void*)cfg.v50_share_group);
        if(cfg.username) free((void*)cfg.username);
        if(cfg.password) free((void*)cfg.password);
    }
}

// 99 - 销毁客户端+释放所有资源
static void app_demo_testcase_99_destroy_mqtt50_client(void)
{
    agent_log_info("\n===== 【用例99】销毁MQTT 5.0客户端+释放资源 ======");
    for (uint8_xxl i = 0; i < g_created_client_cnt; i++)
    {
        if (g_mqtt_clients[i] != NULL)
        {
            // 1. 先断开连接（优雅释放）
            xxl_mqtt_sdk_client_disconnect(g_mqtt_clients[i]);
            // 2. 销毁客户端实例（SDK内部释放）
            xxl_mqtt_sdk_client_destroy(g_mqtt_clients[i]);
            g_mqtt_clients[i] = NULL;
            
            // 3. 释放客户端配置的动态内存（核心修复：补充client_id/broker_ip释放）
            if (g_client_cfgs[i].client_id != NULL) {
                free((void*)g_client_cfgs[i].client_id);
                g_client_cfgs[i].client_id = NULL;
            }
            if (g_client_cfgs[i].broker_ip != NULL) {
                free((void*)g_client_cfgs[i].broker_ip);
                g_client_cfgs[i].broker_ip = NULL;
            }
            if (g_client_cfgs[i].v50_share_group != NULL) {
                free((void*)g_client_cfgs[i].v50_share_group);
                g_client_cfgs[i].v50_share_group = NULL;
            }
            if (g_client_cfgs[i].crypto_key != NULL) {
                free((void*)g_client_cfgs[i].crypto_key);
                g_client_cfgs[i].crypto_key = NULL;
            }
            if (g_client_cfgs[i].crypto_iv != NULL) {
                free((void*)g_client_cfgs[i].crypto_iv);
                g_client_cfgs[i].crypto_iv = NULL;
            }
            // ✅ 新增：释放遗嘱消息的动态内存
            if (g_client_cfgs[i].will_msg.topic != NULL) {
                free((void*)g_client_cfgs[i].will_msg.topic);
                g_client_cfgs[i].will_msg.topic = NULL;
            }
            if (g_client_cfgs[i].will_msg.payload != NULL) {
                free((void*)g_client_cfgs[i].will_msg.payload);
                g_client_cfgs[i].will_msg.payload = NULL;
            }
            
            // 释放5.0扩展配置
            for (uint8_xxl j=0; j<10; j++)
            {
                if (g_mqtt50_ext_cfgs[i].user_prop_key[j] != NULL)
                {
                    free((void*)g_mqtt50_ext_cfgs[i].user_prop_key[j]);
                    g_mqtt50_ext_cfgs[i].user_prop_key[j] = NULL;
                }
                if (g_mqtt50_ext_cfgs[i].user_prop_val[j] != NULL)
                {
                    free((void*)g_mqtt50_ext_cfgs[i].user_prop_val[j]);
                    g_mqtt50_ext_cfgs[i].user_prop_val[j] = NULL;
                }
            }
            if (g_mqtt50_ext_cfgs[i].resp_topic != NULL)
            {
                free((void*)g_mqtt50_ext_cfgs[i].resp_topic);
                g_mqtt50_ext_cfgs[i].resp_topic = NULL;
            }
            if (g_mqtt50_ext_cfgs[i].corr_data != NULL)
            {
                free((void*)g_mqtt50_ext_cfgs[i].corr_data);
                g_mqtt50_ext_cfgs[i].corr_data = NULL;
            }
            // 清空配置
            memset(&g_client_cfgs[i], 0, sizeof(MqttSdkClientCfg));
            memset(&g_mqtt50_ext_cfgs[i], 0, sizeof(Mqtt50ExtCfg));
        }
    }
    g_created_client_cnt = 0;
    agent_log_info(COLOR_GREEN "5.0客户端销毁成功！所有内存资源已释放，无泄漏" COLOR_DEFAULT);
}

/* -------------------------- 菜单与调度函数 -------------------------- */
static void app_demo_print_mqtt50_menu(void)
{
    printf("\n\n");
    printf("=====================================================================\n");
    printf("            MQTT 5.0全特性覆盖测试用例集 [V3.0.0_FULL]\n");
    printf("            纯主任务轮询 | 无线程依赖 | 5.0全字段覆盖 | 商用级健壮性\n");
    printf("=====================================================================\n");
    printf("【测试用例编号】- 【5.0特性描述】\n");
    printf("  00  - 基础配置：创建5.0客户端（含所有5.0全局配置）\n");
    printf("  00E - 加密配置：创建5.0加密客户端（Payload加密+5.0特性）\n");
	printf("  01  - PUBLISH：带TTL/用户属性/保留的5.0发布消息\n");
    printf("  02  - QoS1发布：PUBACK原因码/消息过期/主题别名测试\n");
    printf("  03  - QoS2发布：PUBREC/PUBREL/PUBCOMP全流程（5.0原因码）\n");
    printf("  04  - SUBSCRIBE：共享订阅+订阅标识符+最大QoS+本地过滤\n");
    printf("  05  - SUBSCRIBE：通配符订阅+订阅选项（保留处理+无本地缓存）\n");
    printf("  06  - UNSUBSCRIBE：取消订阅+取消原因码+用户属性\n");
    printf("  07  - CONNECT：自定义会话过期/最大报文/接收最大QoS\n");
    printf("  08  - LastWill：5.0增强遗嘱（过期时间+延迟发布+原因码）\n");
    printf("  09  - DISCONNECT：优雅断开（原因码+会话过期+用户属性）\n");
    printf("  10  - CONNACK：解析5.0 CONNACK所有字段（原因码+最大报文）\n");
    printf("  11  - 重连测试：5.0会话恢复+重连后消息续传\n");
    printf("  12  - 版本切换：3.1.1/5.0协议动态切换对比测试\n");
    printf("  13  - 高级特性：主题别名/批处理/请求响应模式（5.0商用高阶）\n");
	printf("  14  - 安全认证：MQTT 5.0 用户名+密码认证连接\n");
    printf("  99  - 资源清理：销毁客户端+释放所有5.0配置资源\n");
    printf("=====================================================================\n");
}

static void app_demo_dispatch_mqtt50_testcase(uint8_xxl case_id)
{
    switch (case_id)
    {
        case 0:  app_demo_testcase_00_create_mqtt50_client(); break;
        case 1:  app_demo_testcase_01_publish_mqtt50_full(); break;
        case 2:  app_demo_testcase_02_publish_qos1_mqtt50(); break;
        case 3:  app_demo_testcase_03_publish_qos2_mqtt50(); break;
        case 4:  app_demo_testcase_04_subscribe_share_mqtt50(); break;
        case 5:  app_demo_testcase_05_subscribe_wildcard_mqtt50(); break;
        case 6:  app_demo_testcase_06_unsubscribe_mqtt50(); break;
        case 7:  app_demo_testcase_07_connect_custom_mqtt50(); break;
        case 8:  app_demo_testcase_08_will_msg_mqtt50(); break;
        case 9:  app_demo_testcase_09_disconnect_mqtt50(); break;
        case 10: app_demo_testcase_10_parse_connack_mqtt50(); break;
        case 11: app_demo_testcase_11_reconnect_mqtt50(); break;
        case 12: app_demo_testcase_12_switch_version(); break;
        case 13: app_demo_testcase_13_advanced_mqtt50(); break;
		case 14: app_demo_testcase_14_connect_auth_mqtt50(); break;
        case 99: app_demo_testcase_99_destroy_mqtt50_client(); g_app_mqtt_running = false; break;
        default: agent_log_error("无效的5.0测试用例编号，请输入0~13或99！"); break;
    }
}

/* -------------------------- 主函数 (完整无截断) -------------------------- */
int main(int argc, char_xxl *argv[])
{
    (void)argc; 
    (void)argv;
#ifdef _WIN32
		system("chcp 65001");	// 强制 UTF-8 中文正常
#endif
    // ========================
    // ✅ 全局初始化（标准规范）
    // ========================
    xxl_mqtt_sdk_global_init();

    // 初始化日志
#if APP_DEMO_LOG_ENABLE
    AgentLogConfig log_cfg = {0};
    log_cfg.level = AGENT_LOG_DEBUG;
    log_cfg.dest = AGENT_LOG_DEST_CONSOLE;
    log_cfg.max_flash_size = 0;
    log_cfg.max_log_length = 512;
    agent_log_init(&log_cfg);
#endif

    // 启动信息打印
    agent_log_info("\033[32m===== MQTT 5.0全特性覆盖测试用例集启动 [V3.0.0_FULL] =====\033[0m");
    agent_log_info("编译时间: %s %s", __DATE__, __TIME__);
    agent_log_info("核心特性: 5.0全字段覆盖 | 纯主任务轮询 | 无线程依赖 | 零内存泄漏");
    agent_log_info("测试覆盖: CONNECT/CONNACK/PUBLISH/SUBSCRIBE/UNSUBSCRIBE/DISCONNECT 全消息");
    agent_log_info("输入规则: 输入数字+回车=执行指定用例 | 直接回车=执行下一个递增用例 | 99=退出");

    // 变量初始化
    char_xxl input_buf[16] = {0};
    bool8_xxl is_first_run = BOOL8_TRUE_XXL;
    const char* input_tips = " \n请输入5.0测试用例编号：>> ";
    g_app_mqtt_running = true;
    g_last_case_id = 0;

    // 主循环
    while (g_app_mqtt_running)
    {
        // 1. 核心轮询：处理MQTT 5.0报文、回调、心跳、重连（非阻塞，20ms一次）
        app_demo_mqtt50_loop_proc();

        // 2. 首次运行打印菜单
        if (is_first_run == BOOL8_TRUE_XXL)
        {
            app_demo_print_mqtt50_menu();
            printf("%s", input_tips);
            fflush(stdout);
            is_first_run = BOOL8_FALSE_XXL;
            continue;
        }

        // 3. 非阻塞读取用户输入（兼容Windows/Linux）
#ifdef _WIN32
        if (kbhit())  // Windows下检测键盘输入
#else
        fd_set rfds;
        struct timeval tv = {0, 0};
        FD_ZERO(&rfds);
        FD_SET(STDIN_FILENO, &rfds);
        if (select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tv) > 0)  // Linux下非阻塞读取
#endif
        {
            // 读取输入内容
            if (fgets(input_buf, sizeof(input_buf)-1, stdin) != NULL)
            {
                // 去除换行符
                uint32_xxl len = strlen(input_buf);
                if (len > 0 && (input_buf[len-1] == '\n' || input_buf[len-1] == '\r'))
                {
                    input_buf[len-1] = '\0';
                }

                // 处理输入逻辑
                uint8_xxl case_id = 0xFF;
                if (strlen(input_buf) == 0)
                {
                    // 空回车：执行下一个递增用例
                    g_last_case_id++;
                    if (g_last_case_id > 13) g_last_case_id = 0;
                    case_id = g_last_case_id;
                    agent_log_info("\n空回车触发 → 执行5.0用例：%02d", case_id);
                }
                else if (strcmp(input_buf, "00E") == 0 || strcmp(input_buf, "00e") == 0)
                {
                    // 单独处理加密客户端创建用例
                    app_demo_testcase_00E_create_encrypt_client();
                    memset(input_buf, 0, sizeof(input_buf));
                    printf("%s", input_tips);
                    fflush(stdout);
                    continue;
                }
                else
                {
                    // 输入指定用例编号
                    case_id = atoi(input_buf);
                    g_last_case_id = case_id;
                }

                // 调度执行用例
                app_demo_dispatch_mqtt50_testcase(case_id);

                // 清空输入，提示下一次输入
                memset(input_buf, 0, sizeof(input_buf));
                printf("%s", input_tips);
                fflush(stdout);
            }
        }
    }

    // 程序退出前清理
    agent_log_info("\033[32m===== MQTT 5.0全特性测试用例集正常退出 =====\033[0m");
    // agent_log_deinit();  // 销毁日志模块
    // ========================
    // ✅ 全局反初始化
    // ========================
    xxl_mqtt_sdk_global_deinit();

    return 0;
}

#endif // CLIENT_CMD_DEMO==1
