发帖
8 0 0

基于AI-WB2实现MQTTS(MQTT-SSL)单向+双向加密传输

云烟
中级会员

6

主题

4

回帖

428

积分

中级会员

积分
428
Ai-WB2系列 1071 8 2026-2-9 14:02:37

基于AI-WB2实现MQTTS(MQTT-SSL)单向+双向加密传输


前言

你将学到什么

通过本教程,你将掌握以下核心技能:

  • ✅ 理解 MQTT over SSL/TLS(MQTTS)的安全传输原理
  • ✅ 掌握单向认证和双向认证的区别及应用场景
  • ✅ 使用 OpenSSL (Git内置)生成 SSL/TLS 证书
  • ✅ 配置 EMQX 云服务端和 MQTTX 客户端
  • ✅ 在 Ai-WB2 开发板上实现 MQTTS 双向加密通信
  • ✅ 通过 MQTT 消息控制开发板 RGB LED 点亮

MQTTS(MQTT over SSL/TLS)加密传输

在物联网应用中,设备传输的数据往往涉及敏感信息(如控制指令、传感器数据),因此 安全性 至关重要。MQTT 本身不提供加密功能,需要依赖传输层安全协议。

1️⃣ SSL/TLS 基础

SSL(Secure Sockets Layer)TLS(Transport Layer Security) 是为网络通信提供安全及数据完整性的加密协议。TLS 是 SSL 的继任者,目前广泛使用的是 TLS 1.2 和 TLS 1.3。

TLS 提供的安全保障

  • 加密:防止数据被窃听(对称加密传输数据)
  • 身份认证:验证通信双方身份(非对称加密交换密钥)
  • 完整性:防止数据被篡改(消息认证码 MAC)

MQTT over TLS(MQTTS)协议栈

应用层:MQTT 协议
安全层:SSL/TLS(加密/解密、身份认证)
传输层:TCP 协议
网络层:IP 协议

MQTTS 默认端口为 8883(MQTT 为 1883)。

2️⃣ 单向认证(One-way Authentication)

单向认证 是指 客户端验证服务器身份,服务器不验证客户端身份。这是最常见的 TLS 配置方式。

工作原理

  1. 客户端发起 TLS 连接请求
  2. 服务器返回自己的证书(包含公钥)
  3. 客户端验证服务器证书的合法性(检查 CA 签名、有效期、域名匹配等)
  4. 验证通过后,客户端生成会话密钥,用服务器公钥加密后发送
  5. 服务器用私钥解密获取会话密钥
  6. 双方使用会话密钥进行对称加密通信

证书需求

角色 需要的证书
服务器 服务器证书(含公钥)+ 私钥
客户端 CA 根证书(用于验证服务器证书)

适用场景

  • 公共物联网平台(设备只需确认连接到正确的服务器)
  • 设备数量庞大,难以管理每个设备的证书
  • 对安全性要求不是极端严格的场景

优点:配置简单,客户端只需存储 CA 证书
缺点:服务器无法验证客户端身份,存在被未授权设备连接的风险

3️⃣ 双向认证(Mutual Authentication / mTLS)

双向认证 是指 客户端和服务器互相验证对方身份,提供最高级别的安全性。

工作原理

  1. 客户端发起 TLS 连接请求
  2. 服务器返回自己的证书
  3. 客户端验证服务器证书
  4. 服务器请求客户端证书
  5. 客户端发送自己的证书
  6. 服务器验证客户端证书(检查 CA 签名、有效期、是否吊销等)
  7. 双方互相验证通过后,交换会话密钥
  8. 使用会话密钥进行加密通信

证书需求

角色 需要的证书
服务器 服务器证书 + 私钥 + CA 证书(验证客户端)
客户端 客户端证书 + 私钥 + CA 证书(验证服务器)

适用场景

  • 金融、医疗等高安全要求的行业
  • 工业控制系统(防止未授权设备接入)
  • 需要精确控制设备接入权限的场景

优点:最高安全性,服务器可精确识别每个客户端
缺点:证书管理复杂,每个设备需要独立证书,证书分发和更新成本高

4️⃣ 证书类型与选型

类型 说明 适用场景
DV SSL 域名验证证书,仅验证域名所有权 测试环境、非核心应用
OV SSL 组织验证证书,验证组织身份 企业应用、工业物联网
EV SSL 扩展验证证书,最高级别验证 金融、关键基础设施
自签名证书 自己生成的证书,无第三方 CA 内网测试、开发环境

密钥算法选择

  • RSA:兼容性好,应用广泛,但密钥较长、计算开销大
  • ECC(椭圆曲线):密钥短、计算快、功耗低,适合资源受限的物联网设备

一、准备工作

📦 硬件与软件清单

分类 项目 数量/版本 说明
硬件 Ai-WB2-12F 开发板 1 核心控制 MCU
Type-C 数据线 1 烧录程序与调试
软件 安信可 Ai-WB2 开源仓库 最新版 Gitee
MQTTX 客户端 最新版 官网下载
EMQX 服务端 最新版 点击跳转
Git(内置OpenSSL) 最新版 官网下载

⏱️ 预计完成时间:约 2-3 小时(包含证书生成、配置、编译和测试)

📋 前置要求

  • 熟悉 GPIO 控制和 FreeRTOS
  • 对 Linux、make、Git 指令有一定的了解
  • 对回调函数、JSON、MQTT 协议有一定了解

二、克隆完整仓库

1️⃣ 克隆仓库

以下指令可直接一键克隆完整 Git 仓库和子模块,也可点击链接跳转直接下载 ZIP 包:(⚠️务必克隆最新仓库!)

# Gitee
git clone --recursive https://gitee.com/Ai-Thinker-Open/Ai-Thinker-WB2.git

🔴 提示:该仓库包含子模块内容较大(约几百兆),需要耐心等待克隆完成。

2️⃣ 检查仓库完整性

克隆下来的完整文件如图,重点关注图中红框部分的子模块包含内容是否完整无缺失:

image.png

图:Ai-WB2 项目仓库目录结构,红框标注的 toolchain/riscv 子模块应包含 Darwin、Linux、MSYS 三个文件夹且文件夹内应包含有内容。


三、注册配置EMQX服务端

3️⃣ 注册 EMQX 服务端

  1. 打开 EMQX 官网注册登录后创建一个新的 MQTT 连接实例,选择 专有版 的云服务区域和配置(免费套餐即可),完成实例创建点击进入后记下连接地址(例如 xx.aliyun.emqxcloud.cn)和端口(默认 8883)。

image.png

图:EMQX 服务端连接信息界面,显示服务器地址、端口信息及 CA 证书下载按钮。

4️⃣ 配置客户端认证参数

  1. 在左侧栏中点击 访问控制客户端认证,点击 添加 按钮,创建两个用户与对应密码信息用于后续设备连接:

image.png

图:EMQX 客户端认证配置界面,红框和箭头标注了从进入「客户端认证」页面到点击「+添加」按钮,再到输入账号密码的完整操作流程。


四、认证证书生成与配置

该步骤为双向认证所需配置,如果你电脑里没有 Git,请去上述官网下载并安装(一路默认 Next 即可)。它内置了 OpenSSL,不需要繁琐的 Windows 环境变量配置。

1️⃣ 生成 CA 根证书

  1. 首先生成 CA 根证书和私钥,建议创建一个专门用于存放生成证书的文件夹 ssl_certs 在该文件夹右键 → 选择 "Open Git Bash here" 打开,复制以下命令到 Git Bash 中执行:
# 生成一个 2048 位的 RSA 私钥,命名为 ca.key
# 这里的 -out 表示输出文件名
openssl genrsa -out ca.key 2048
  1. 生成 CA 根证书,命令如下:
# 使用刚才的私钥 (ca.key) 生成一张自签名的证书 (ca.pem)
# -x509: 生成自签名证书的标准格式
# -days 3650: 证书有效期 10 年,避免频繁过期
# -subj: 填写证书信息,CN=MyRootCA 表示发证机构的名字
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -out ca.pem -subj "//CN=MyRootCA"

产出文件:ca.key(严加保管),ca.pem(发证机关的公开执照)。

2️⃣ 生成服务器证书

这套证书是给你的 MQTT 服务器(EMQX Cloud)用的,证明它是合法的服务器。

  1. 生成服务器私钥:
# 生成服务端的私钥,命名为 server.key
openssl genrsa -out server.key 2048
  1. 生成服务端签名请求(CSR):

⚠️ 注意:为了稳妥,Common Name(CN)最好填写你创建的EMQX连接地址(例如 xx.aliyun.emqxcloud.cn),或者是你的自定义域名。

# 生成请求文件 server.csr
# CN=xxx 替换为 3.1 中的连接地址
openssl req -new -key server.key -out server.csr -subj "//CN=XXX.cn"
  1. 使用 CA 给服务端颁发证书:
# CA 拿出它的私钥 (ca.key) 和证书 (ca.pem) 给服务端的请求 (server.csr) 盖章
# 生成最终的服务端公钥证书: server.pem
openssl x509 -req -in server.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out server.pem -days 3650 -sha256

产出文件:server.keyserver.pem

3️⃣ 生成客户端证书

双向认证的核心在于:设备也要出示证件。

  1. 生成客户端私钥:
# 生成客户端私钥,命名为 client.key
openssl genrsa -out client.key 2048
  1. 生成客户端签名请求:
# 生成请求文件 client.csr
# CN=client1 这里可以代表设备的 ID
openssl req -new -key client.key -out client.csr -subj "//CN=client1"
  1. 使用 CA 给客户端颁发证书:
# CA 再次出马,给客户端盖章
# 生成最终的客户端公钥证书: client.pem
openssl x509 -req -in client.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out client.pem -days 3650 -sha256

产出文件:client.keyclient.pem

此时你的 ssl_certs 文件夹将有以下文件,对应不同角色的证书和私钥:

image.png

图:生成的证书文件列表,包含 CA 根证书、服务器证书和客户端证书及其对应的私钥文件。


五、证书上传与 EMQX 配置

该步骤为双向认证所需步骤。

1️⃣ 上传服务器证书到 EMQX

image.png

图:EMQX 双向 TLS/SSL 证书配置界面,红框标注选择"双向"认证类型,红色箭头指引依次上传服务器端 .pem 文件、服务器端 .key 文件和 CA 证书文件。

2️⃣ 配置 MQTTX 使用客户端证书

单向认证配置如下:

image.png

图:MQTTX 单向认证连接配置界面。

双向认证配置如下:

image.png

图:MQTTX 双向认证连接配置界面,红框和箭头标注用户名密码输入、证书配置区域的提示文字以及右上角"连接"按钮。

3️⃣ 配置 AI-WB2 使用客户端证书

  1. 需要将客户端证书中的内容复制替换到例程中的证书宏定义中,期间需要涉及到大量的修改格式和转义字符的工作,以下推荐一种一键修改的方法:

在 Git Bash 中我们可以利用 Linux 经典的 sed 工具,一行指令直接生成你想要的宏定义格式。在你的证书目录下右击打开 Git Bash 并运行:

# 将 ca.pem 处理并输出到 ca_config.h 文件中
# s/$/\\r\\n\\/ : 在每行末尾加上 \r\n\
# s/^/\"/ : 在每行开头加上 "
# s/$/\"/ : 在每行末尾(刚才的斜杠前)加上 "
sed -e 's/^/"/' -e 's/$/\\r\\n\\"/' ca.pem > ca_config.h

此时打开 ca_config.h 文件,可以看到内容已经转换为宏定义格式。

⚠️ 注意:最后一行末尾的 \ 需要手动删掉,然后在前后加上 #define 以及换号转义 \,将修改好格式的证书内容分别复制替换到例程中 Ai-Thinker-WB2/applications/protocols/mqtt/ssl/ssl/demo.c 的宏定义:EMQX_CA_CRTCLIENT_CRTCLIENT_KEY 即可。


六、点灯代码配置与编译

1️⃣ 配置 WiFi 路由器信息

Ai-Thinker-WB2/applications/protocols/mqtt/ssl/ssl/main.c 文件下,修改两个宏定义:ROUTER_SSIDROUTER_PWD,填入你的 WiFi 名称和密码:

// 路由器配置信息(需要用户根据实际情况修改)
#define ROUTER_SSID "WIFI"         // 填入你的 WiFi 名称
#define ROUTER_PWD "1234567890"    // 填入你的 WiFi 密码

2️⃣ 添加 RGB LED 控制代码

📌 关键配置点:引入头文件与定义引脚

Ai-Thinker-WB2/applications/protocols/mqtt/ssl/ssl/demo.c 文件下,增加以下代码。在 #include <task.h> 以下添加以下头文件和宏定义:

#include "cJSON.h"    // JSON 解析库
#include <bl_gpio.h>  // GPIO 控制库

// RGB LED 引脚定义(根据实际硬件连接修改)
#define GPIO_LED_RED    14
#define GPIO_LED_GREEN  17
#define GPIO_LED_BLUE   3

📌 关键配置点:LED 状态枚举与任务实现

紧接着在 #define EMQX_CA_CRT 函数上添加以下代码:

/* ================= LED 指示灯业务逻辑 ================= */
typedef enum {
    LED_OFF = 0,      // 闲置(全灭)
    LED_BLUE,         // 蓝灯常亮
    LED_GREEN,        // 绿灯常亮
    LED_RED           // 红灯常亮
} led_indicator_state_t;

static volatile led_indicator_state_t g_led_state = LED_OFF;

// 设置 RGB LED 的亮灭状态
static void led_set_level(uint8_t r, uint8_t g, uint8_t b) {
    bl_gpio_output_set(GPIO_LED_RED, r);
    bl_gpio_output_set(GPIO_LED_GREEN, g);
    bl_gpio_output_set(GPIO_LED_BLUE, b);
}

// LED 指示灯任务(FreeRTOS 任务)
static void led_indicator_task(void *pvParameters) {
    // 初始化 GPIO 为输出模式
    bl_gpio_enable_output(GPIO_LED_RED, 0, 0);
    bl_gpio_enable_output(GPIO_LED_GREEN, 0, 0);
    bl_gpio_enable_output(GPIO_LED_BLUE, 0, 0);
    led_set_level(0, 0, 0); // 初始状态:全灭

    while (1) {
        switch (g_led_state) {
            case LED_BLUE: // 蓝灯常亮
                led_set_level(0, 0, 1);
                vTaskDelay(pdMS_TO_TICKS(500)); 
                break;
            case LED_GREEN: // 绿灯常亮
                led_set_level(0, 1, 0);
                vTaskDelay(pdMS_TO_TICKS(500)); 
                break;
            case LED_RED:   // 红灯常亮
                led_set_level(1, 0, 0);
                vTaskDelay(pdMS_TO_TICKS(500));
                break;
            case LED_OFF:   // 全灭
            default:
                led_set_level(0, 0, 0);
                vTaskDelay(pdMS_TO_TICKS(500));
                break;
        }
    }
}

📌 关键配置点:MQTT 客户端参数配置

mqtt_start(void) 函数中配置 MQTT 客户端参数:

/* 
 * 配置 MQTT 客户端参数
 * uri: MQTT 代理服务器地址,使用 mqtts:// 协议(加密)
 * event_handle: 设置事件回调函数,用于接收连接状态和数据
 */
void mqtt_start(void)
{
    axk_mqtt_client_config_t mqtt_cfg = {
        .uri = "mqtts://xx.aliyun.emqxcloud.cn:8883",  // Broker 服务器地址与端口
        .cert_pem = EMQX_CA_CRT,                                          // CA 根证书内容(单向认证时需要,双向认证时也需要)
        .cert_len = sizeof(EMQX_CA_CRT),                                  // 证书长度
        .client_cert_pem = CLIENT_CRT,                                    // 客户端证书内容(双向认证时需要,单证时注释)
        .client_key_pem = CLIENT_KEY,                                     // 客户端私钥内容(双向认证时需要,单证时注释)
        .username = "wb2-12f",                                            // 用户名(必须与服务器端设置保持一致)
        .password = "12345678",                                           // 密码(必须与服务器端设置保持一致)
        .client_id = "Ai-Thinker-WB2",                                    // ID 用于区分不同设备,必须唯一
        .event_handle = event_cb,                                         // 事件回调函数
        /* 注意:启动是异步的,连接成功/失败会通过 event_cb 回调通知 */
    };
    
    // 初始化 MQTT 客户端并启动连接
    axk_mqtt_client_handle_t client = axk_mqtt_client_init(&mqtt_cfg);
    axk_mqtt_client_start(client);
    
    // LED 指示灯任务创建
    static TaskHandle_t led_task_handle;
    xTaskCreate(led_indicator_task, "led", 512, NULL, 10, &led_task_handle); 
}

📌 关键配置点:MQTT 事件回调函数实现

修改回调函数 event_cb(axk_mqtt_event_handle_t event),实现以下三个关键事件:

/* ==================== MQTT 连接成功事件 ==================== */
case MQTT_EVENT_CONNECTED:
    blog_info("MQTT_EVENT_CONNECTED");
    
    // 订阅主题 "/topic/qos0",QoS 等级 0(最多送达一次,不保证送达)
    msg_id = axk_mqtt_client_subscribe(client, "/topic/qos0", 0);
    blog_info("sent subscribe successful, msg_id=%d", msg_id);
    break;
/* ==================== 订阅成功确认事件 ==================== */
case MQTT_EVENT_SUBSCRIBED:
    blog_info("MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
    
    // 订阅成功后,立即向该主题发布一条 QoS 0 的消息 "hello,MQTT!"
    msg_id = axk_mqtt_client_publish(client, "/topic/qos", "hello,MQTT!", 0, 0, 0);
    blog_info("sent publish successful, msg_id=%d", msg_id);
    break;
/* ==================== 收到 MQTT 消息数据事件 ==================== */
case MQTT_EVENT_DATA:
    blog_info("MQTT_EVENT_DATA");

    // 1. 解析 JSON 字符串为 cJSON 对象
    cJSON *root = cJSON_Parse(event->data);
    if (root == NULL) {
        printf("Error parsing JSON!\n");
        break;
    }

    // 2. 获取 LED 字段
    cJSON *LED = cJSON_GetObjectItem(root, "LED");
    
    // 3. 访问值并进行类型检查
    if (LED && LED->type == cJSON_String) {
        if (strcmp(LED->valuestring, "LED_RED") == 0) {
            g_led_state = LED_RED;
            printf("LED_RED_ON");
        }
        else if (strcmp(LED->valuestring, "LED_GREEN") == 0) {
            g_led_state = LED_GREEN;
            printf("LED_GREEN_ON");
        }
        else if (strcmp(LED->valuestring, "LED_BLUE") == 0) {
            g_led_state = LED_BLUE;
            printf("LED_BLUE_ON");
        }
        else if (strcmp(LED->valuestring, "LED_OFF") == 0) {
            g_led_state = LED_OFF;
            printf("LED_OFF");
        }
        else {
            printf("LED ERROR");
        }    
    }

    // 4. 核心:必须手动释放 cJSON 内存!
    cJSON_Delete(root);

    printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
    printf("DATA=%.*s\r\n", event->data_len, event->data);

    break;

3️⃣ 编译与烧录

保存代码后,执行以下命令进行编译与烧录:

make flash p=/dev/ttyUSB0

编译过程如下:

image.png

图:编译成功提示,生成 tcp.bin 二进制文件。

烧录过程如下:

image.png

图:烧录成功日志,红色标注显示 "[All Success]"。

按下复位键重启开发板,打开串口助手,波特率设置为 115200,查看串口打印信息:

image.png

图:串口日志显示 MQTT 连接成功、订阅成功、发布成功的消息。


七、测试验证

1️⃣ 添加主题订阅

点击左侧 "+ 添加订阅"按钮,填写订阅信息:

image.png

图:添加订阅对话框。

配置项 说明
Topic /topic/qos0 订阅的主题名称
QoS 0(最多一次) 消息服务质量等级

2️⃣ 发布消息测试

向主题 /topic/qos0 发布 JSON 格式消息,控制 LED 亮灭:

发布红色 LED

{
  "LED": "LED_RED"
}

发布绿色 LED

{
  "LED": "LED_GREEN"
}

发布蓝色 LED

{
  "LED": "LED_BLUE"
}

关闭 LED

{
  "LED": "LED_OFF"
}

发布消息后,可在串口助手中看到相应的打印信息,开发板 RGB 灯也会对应亮起:

image.png

图:MQTTX 消息收发界面,显示订阅主题、已发布和已接收的消息。

image.png

图:Ai-WB2 开发板 RGB LED 点亮效果(绿色)。

3️⃣ 常见错误排查

⚠️ 问题 1:编译报错 "command not found: make"

原因:系统未安装 make 工具或未正确配置环境变量。

解决方法

  • Windows 用户:确保安装了 Git Bash 并在其中运行 make 命令
  • 检查是否在项目根目录下执行命令

⚠️ 问题 2:MQTT 连接失败,串口打印连接超时

可能原因

  1. WiFi 路由器名称或密码错误
  2. EMQX 服务器地址或端口配置错误
  3. 证书内容格式不正确

解决方法

  1. 检查 ROUTER_SSIDROUTER_PWD 宏定义是否正确
  2. 确认 EMQX 服务器地址和端口是否与控制台一致
  3. 重新使用 sed 命令生成证书宏定义,确保转义字符正确

⚠️ 问题 3:双向认证连接失败,提示证书验证错误

可能原因

  1. 服务器证书的 Common Name 与连接地址不匹配
  2. CA 证书未正确上传到 EMQX
  3. 客户端证书与私钥不匹配

解决方法

  1. 重新生成服务器证书,确保 CN 与连接地址一致
  2. 检查 EMQX 的 TLS/SSL 配置,确认证书已正确上传
  3. 确保客户端证书和私钥是同一对生成的证书文件

⚠️ 问题 4:LED 不响应 MQTT 消息

可能原因

  1. JSON 格式错误
  2. 主题名称不匹配
  3. 引脚定义与实际硬件连接不一致

解决方法

  1. 检查 MQTTX 发布的 JSON 消息格式是否正确(注意双引号和逗号)
  2. 确认订阅主题与发布主题一致
  3. 检查 GPIO_LED_REDGPIO_LED_GREENGPIO_LED_BLUE 的引脚定义

总结

至此,基于 Ai-WB2 使用 MQTT 协议实现订阅、发布及点灯功能的全部内容已完成!

本教程完整覆盖了:

  • 单向认证:客户端验证服务器,适用于公共物联网平台
  • 双向认证:客户端和服务器互相验证,适用于高安全要求的场景
  • 证书生成:使用 OpenSSL (Gitn内置)生成完整的证书链
  • EMQX 配置:服务端和客户端认证信息配置
  • MQTTX 测试:模拟设备连接和消息收发
  • RGB LED 控制:通过 MQTT 消息控制硬件

如有问题或建议,欢迎在评论区留言讨论!

──── 0人觉得很赞 ────

使用道具 举报

🧨🧨🧨
棒!
非常有用!
2026-3-24 14:40:42
#include "cJSON.h"    // JSON 解析库

applications\protocols\mqtt\ssl项目基础上使用此教程,编译报错,不存在cJSON.h 。

纠正:

参考 applications\system\app_json\Makefile

  1. 在VFS增加cjson

COMPONENTS_VFS := romfs cjson

  1. include改为 #include <cJSON.h>
2026-3-24 14:52:40
KevinLi 发表于 2026-3-24 14:40
#include &quot;cJSON.h&quot;    // JSON 解析库

applications\protocols\mqtt\ssl项目基础上使用此教程,编译报错 ...

或者只在【INCLUDE_COMPONENTS 】新增cjson.
参考【[【Ai-WB2高级篇】MQTT 协议连接 - Ai-WB2系列 - 物联网开发者社区-安信可论坛 - Powered by Discuz!](https://bbs.aithinker.com/forum.php?mod=viewthread&tid=45256)】
2026-3-24 20:19:34

对于以下ssl(使用MQTTX公共服务器的CA证书连接)最简代码,为什么连不上呢?LOG会对证书和底层的文件报错。

参考教程:

IP: 172.16.1.36
  MK: 255.255.254.0
  GW: 172.16.1.1
[WF][SM] Exiting wifiConnected_ipObtaining state
[WF][SM] State Action ###wifiConnected_ipObtaining### --->>> ###wifiConnected_IPOK###
[WF][SM] Entering wifiConnected_IPOK state
INFO (5134)[main.c:  79] [APP] [EVT] GOT IP 5134
INFO (5139)[main.c:  80] [SYS] Memory left is 151616 Bytes
INFO (5145)[demo.c: 278] ###MQTT client init SUCCESS
INFO (5151)[demo.c: 245] Other event id:7
ERROR (5348)[axk_tls_mbedtls.c: 681] No server verification option set in axk_tls_cfg_t structure. Check axk_tls API reference
ERROR (5358)[axk_tls_mbedtls.c:  85] Failed to set client configurations, returned [0x8017] (UNKNOWN ERROR)
ERROR (5368)[axk_tls.c: 410] create_ssl_handle failed
ERROR (5374)[axk_tls.c: 453] Failed to open new connection
ERROR (5380)[transport_ssl.c: 113] Failed to open a new connection
INFO (5388)[demo.c: 236] MQTT_EVENT_ERROR
INFO (5391)[demo.c: 241] Last errno string (Success)
INFO (5396)[demo.c: 175] MQTT_EVENT_DISCONNECTED
INFO (15401)[demo.c: 245] Other event id:7
ERROR (15581)[axk_tls_mbedtls.c: 681] No server verification option set in axk_tls_cfg_t structure. Check axk_tls API reference
ERROR (15590)[axk_tls_mbedtls.c:  85] Failed to set client configurations, returned [0x8017] (UNKNOWN ERROR)
ERROR (15601)[axk_tls.c: 410] create_ssl_handle failed
const char ca_cert_G2[] = 
"-----BEGIN CERTIFICATE-----\n"
"MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh\n"
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH\n"
"MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT\n"
"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n"
"b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG\n"
"9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI\n"
"2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx\n"
"1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ\n"
"q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz\n"
"tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ\n"
"vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP\n"
"BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV\n"
"5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY\n"
"1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4\n"
"NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG\n"
"Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91\n"
"8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe\n"
"pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl\n"
"MrY=\n"
"-----END CERTIFICATE-----\n";

void mqtt_start(void) {
    axk_mqtt_client_config_t mqtt_cfg = {
        .uri          = "mqtts://broker.emqx.io:8883",
        .cert_pem     = ca_cert_G2,
        .cert_len     = sizeof(ca_cert_G2),
        .client_id    = "WB2-TEST-123",
        .event_handle = event_cb,
    };

    axk_mqtt_client_handle_t client = axk_mqtt_client_init(&mqtt_cfg);
    if(client) axk_mqtt_client_start(client);
}
2026-3-25 09:57:07

更换另一种 CA格式和cfg,报错信息就变成:

MQTT client init SUCCESS
[axk_tls_mbedtls.c: 328] mbedtls_x509_crt_parse returned -0x2800

没办法参考以下代码,因为没有0x2800 Mbed TLS 常见报错排查 - - — ESP-Techpedia latest 文档


void mqtt_start(void) {

axk_mqtt_client_config_t mqtt_cfg = {
.uri = "mqtts://broker.emqx.io:8883",
.cert_pem = CA_CERT_G2, // 数组名,不是指针
// .cert_len = sizeof(ca_cert_G2), //
.cert_len = 0, // PEM 格式必须填 0
.client_id = "WB2-SSL-FINAL",
.event_handle = event_cb,

.use_global_ca_store = false,
.skip_cert_common_name_check = false,

};

// ==============================
// 判断证书是否为 NULL
// ==============================
if (mqtt_cfg.cert_pem == NULL) {
blog_error("cert_pem is NULL !!!");
return;
}

// ==============================
// 打印所有 TLS 字段
// ==============================
blog_info("========= MQTT TLS CONFIG DEBUG =========");
blog_info("cert_pem = %p", mqtt_cfg.cert_pem);
blog_info("cert_len = %u", (unsigned int)mqtt_cfg.cert_len);
blog_info("use_global_ca_store = %d", mqtt_cfg.use_global_ca_store);
blog_info("skip_cert_common_name_check = %d", mqtt_cfg.skip_cert_common_name_check);
blog_info("========================================");

axk_mqtt_client_handle_t client = axk_mqtt_client_init(&mqtt_cfg);
if (client == NULL) {
blog_error("###MQTT client init failed");
return;
}

blog_info("###MQTT client init SUCCESS");
axk_mqtt_client_start(client);

// 创建 LED 任务(原代码遗漏,需补上)
static TaskHandle_t led_task_handle;
if (xTaskCreate(led_indicator_task, "led", 1024, NULL, 10, &led_task_handle) != pdPASS) {
blog_error("LED task create failed");
}

}

```text
[WF][SM] Exiting wifiConnected_ipObtaining state
[WF][SM] State Action ###wifiConnected_ipObtaining### --->>> ###wifiConnected_IPOK###
[WF][SM] Entering wifiConnected_IPOK state
INFO (137634)[main.c:  79] [APP] [EVT] GOT IP 137634
INFO (137639)[main.c:  80] [SYS] Memory left is 129248 Bytes
INFO (137645)[demo.c: 317] ========= MQTT TLS CONFIG DEBUG =========
INFO (137652)[demo.c: 318] cert_pem          = 0x23089400
INFO (137658)[demo.c: 319] cert_len          = 0
INFO (137663)[demo.c: 320] use_global_ca_store = 0
INFO (137668)[demo.c: 321] skip_cert_common_name_check = 0
INFO (137674)[demo.c: 322] ========================================
INFO (137682)[demo.c: 341] ###MQTT client init SUCCESS
INFO (137687)[demo.c: 270] Other event id:7
ERROR (137899)[axk_tls_mbedtls.c: 328] mbedtls_x509_crt_parse returned -0x2800
ERROR (137904)[axk_tls_mbedtls.c:  85] Failed to set client configurations, returned [0x8015] (UNKNOWN ERROR)
ERROR (137914)[axk_tls.c: 410] create_ssl_handle failed
ERROR (137920)[axk_tls.c: 453] Failed to open new connection
ERROR (137926)[transport_ssl.c: 113] Failed to open a new connection
INFO (137935)[demo.c: 261] MQTT_EVENT_ERROR
INFO (137938)[demo.c: 266] Last errno string (Success)
INFO (137943)[demo.c: 200] MQTT_EVENT_DISCONNECTED
INFO (138680)[demo.c: 270] Other event id:7
ERROR (138924)[axk_tls_mbedtls.c: 328] mbedtls_x509_crt_parse returned -0x2800
ERROR (138930)[axk_tls_mbedtls.c:  85] Failed to set client configurations, returned [0x8015] (UNKNOWN ERROR)
2026-3-25 17:49:27
[i=s] 本帖最后由 KevinLi 于 2026-3-25 17:56 编辑 [/i]

我解决了!是SDK有问题,最新版(上个月更新的)的可用。具体如下

SDK的 components/network/axk_protocol_stack的4个文件夹内容在26年2月份在github更新了,尤其是开放了c文件,方便根据log进行调试。我的原SDK是25年7月份Pull的,我只更新了这一个子文件夹的内容,再去编译烧录运行,就不报错了。根据axk论坛25年3月18的评论,只替换2个.a文件是不行的。

只更新替换子文件夹,需要3步:进入SDK根目录;git fetch;git checkout origin/main -- components/network/axk_protocol_stack


mqttx免费服务器 单向CA验证的点灯代码可直接使用这个人的【Robot/wb2-mqtt-demo - Gitee.com】。使用sdk的example需要改服务器CA。

您需要登录后才可以回帖 立即登录
高级模式
返回
统计信息
  • 会员数: 30873 个
  • 话题数: 44830 篇