跳到主要内容

固件开发

提示

本页面介绍了固件开发相关的内容。

配网(Wi-Fi 配网)

配网 (Provisioning) 是物联网 (IoT) 设备部署过程中的第一步,并至关重要。在此环节中,设备会配置好网络凭证,并完成云端服务的身份认证。

ESP RainMaker 集成了 ESP-IDF 中的网络配网组件,大幅简化了配网流程。通过安卓或 iOS 手机应用程序,选择蓝牙 (BLE) 或软接入点 (SoftAP),即可完成设备配网。

此外,用户-节点映射操作也在配网过程中完成。


配网传输方式:BLE/SoftAP

方式通信方式设备广播用户操作优点缺点
BLEBLE GATTBLE 广播,设备名称格式如 PROV_XXXX手机扫描设备 → 建立 BLE 连接 → 建立安全会话 → 发送 Wi-Fi 凭证及其他信息速度快、用户体验流畅、反馈清晰、手机可保持联网状态设备须支持 BLE、可能存在兼容性问题
SoftAP基于 Wi-Fi 的 HTTP 协议设备创建热点,热点名称 (SSID) 格式如 PROV_XXXX手机连接至该热点 → 建立安全会话 → 发送 Wi-Fi 凭证及其他信息实现简单、兼容性高需手动切换 Wi-Fi、过程中可能断连、切换网络时手机可能断连

配网流程(BLE 示例)

  1. 设备开启 BLE 广播,包含以下信息:
    • 设备名称:PROV_xxxxxx
    • 服务 UUID:0xFF50(乐鑫自定义配网服务)
  2. 手机应用扫描并发现设备
  3. 应用建立 GATT 通信
  4. 应用建立安全会话(可选择输入 PoP 验证码)
  5. 应用交换数据以完成用户-设备映射
  6. 应用发送 Wi-Fi SSID 和密码
  7. 设备尝试连接网络,并向云端上报状态
  8. 应用先在本地检查 Wi-Fi 连接状态,随后通过云端验证设备状态
信息

SoftAP 遵循类似流程,区别在于其通信方式为 HTTP 而非 BLE。


配网流程(扫描二维码)

在生产环境中,部分设备会附带一个二维码,其中包含基础的配网元数据(名称、验证码、传输方式)。使用应用程序扫描此二维码后:

  1. 应用程序解析二维码内容,其中包含传输方式 (BLE/SoftAP)。
  2. 应用程序根据传输方式字段,选择对应的配网流程。
  3. 此方式可省去手动发现设备的步骤,提升配网的一致性。

二维码仅作为引导机制,而非传输载体。实际数据的传输仍通过 BLE 或 SoftAP 完成。这一方式能避免手动搜索或选择设备,从而简化用户体验。

二维码内容示例

RainMaker 二维码通常包含 JSON 格式数据或 Base64 编码的 URL,格式如下:

{
"ver": "v1",
"name": "PROV_AB12CD",
"pop": "abcd1234",
"transport": "ble"
}

或:

https://rainmaker.espressif.com/qrcode.html?data={"ver":"v1","name":"PROV_AB12CD","pop":"abcd1234","transport":"ble"}

扫描二维码后,应用程序可实现以下功能:

  • 获取设备名称(用于 BLE 扫描或 Wi-Fi SSID)
  • 获取 POP(如需使用)
  • 确定配网方式(BLE 或 SoftAP)

开发者参考:相关 API

目前有两套配网接口:

  • network_provisioningidf-extra-components 项目下的组件。(推荐)
  • wifi_provisioning:ESP-IDF 下的组件。(旧版接口)

当配置项 CONFIG_ESP_RMAKER_USING_NETWORK_PROV 启用时(默认启用),系统将使用 network_provisioning 接口;若该配置项未启用,则会回退使用 wifi_provisioning 接口。


主要差异
  • 功能层面

    network_provisioning 组件不仅支持通过 BLE 传输实现的 Wi-Fi 配网,还支持通过 BLE 实现的 Thread 配网

  • API 命名

    • network_provisioning 的 API 以 network_ 为前缀。
    • wifi_provisioning 的 API 以 wifi_ 为前缀。

app_network 接口

底层的 network_provisioning 组件通过 app_network 接口进行封装抽象。该接口为配网操作提供了更易用的接口。

功能API 接口
初始化配网app_network_init
启动配网app_network_start()(需传入验证码类型参数)
设置自定义设备类型及子类型app_network_set_custom_mfg_data()
设置自定义验证码app_network_set_custom_pop()

配网 PoP

在 Wi-Fi 配网场景中,PoP(Proof of Possession,持有凭证)是一个关键的安全机制。 PoP 的主要作用如下:

  1. 防止未授权用户对设备进行配网/绑定
    • 当设备公开广播 BLE 信号时,任何人都能发现该设备。一旦没有 PoP 验证,他人可能直接控制你的设备。
  2. 确保配网者是“合法持有者”
    • PoP 就像一把钥匙,只有实际持有 PoP(例如通过扫描二维码获取)的人,才能成功为设备配网。
  3. 在配网过程中完成身份验证
    • 手机应用与设备建立 BLE 连接后,会向设备提供 PoP;随后,设备验证该 PoP 是否匹配。验证成功后,才会继续配网流程。

通过应用程序配网时,PoP 数值必须与设备上设置的数值一致,才能建立有效的配网通道。PoP 数值分为以下四种类型:

  • POP_TYPE_MAC:使用设备 Wi-Fi MAC 地址的后 3 个字节,转换为 6 位十六进制字符。
  • POP_TYPE_RANDOM:使用存储在 fctry 分区(该分区同时存储 RainMaker 证书)中的随机值的前 3 个字节。使用 admin-cli 工具生成证书时,可选择同时生成二维码,此时二维码中的 PoP 与设备中读取的 PoP 值一致。
  • POP_TYPE_NONE:不使用 PoP,适用于无需扫描二维码的场景。应用程序通过蓝牙发现设备,然后直接开始配网。
  • POP_TYPE_CUSTOM:使用自定义 PoP 数值,需通过 app_network_set_custom_pop() 进行配置。

配网广播

修改配网名称前缀

配网名称前缀通过配置项 CONFIG_APP_NETWORK_PROV_NAME_PREFIX 进行设置,默认值为 PROV_。用户可根据需求修改该前缀。配网名称的后缀则取自以下两者之一:设备 Wi-Fi MAC 地址的后三位字符,或 RainMaker 证书中 random 字段的后三位字符。

向 BLE 广播中添加自定义信息

RainMaker 的 wifi_provisioning 组件支持修改蓝牙厂商数据。参考 app_network_set_custom_mfg_data() 函数可设置蓝牙广播数据,但仅支持修改设备类型与子类型。如需修改其他数据,请查看 app_network_set_custom_mfg_data() 的实现代码及下文对应的规范说明。

开发者可在厂商数据中添加产品信息、类型、生产厂商等详情。当应用程序通过蓝牙扫描设备时,即可获取这些信息,并显示对应的产品图标。

备注
字段字节长度默认值
固定头部20xE5, 0x02
应用 ID3'N', 'o', 'v'
版本1'a'
客户 ID20x00, 0x01
设备类型码20x0005
设备子类型码10x01
设备附加码10x00
保留位 010xFF
保留位 110xFF
esp_err_t app_network_set_custom_mfg_data(uint16_t device_type, uint8_t device_subtype)
{
int8_t mfg_data[] = {MFG_DATA_HEADER, MGF_DATA_APP_ID, MFG_DATA_VERSION, MFG_DATA_CUSTOMER_ID};//{0xe5, 0x02, 'N', 'o', 'v', 'a', 0x00, 0x01}
size_t mfg_data_len = sizeof(mfg_data) + 4; // 4 bytes of device type, subtype, and extra-code
custom_mfg_data = (uint8_t *)MEM_ALLOC_EXTRAM(mfg_data_len);
if (custom_mfg_data == NULL) {
ESP_LOGE(TAG, "Failed to allocate memory to custom mfg data");
return ESP_ERR_NO_MEM;
}
memcpy(custom_mfg_data, mfg_data, sizeof(mfg_data));
custom_mfg_data[8] = 0xff & (device_type >> 8);
custom_mfg_data[9] = 0xff & device_type;
custom_mfg_data[10] = device_subtype;
custom_mfg_data[11] = 0;
custom_mfg_data_len = mfg_data_len;
ESP_LOG_BUFFER_HEXDUMP("tag", custom_mfg_data, mfg_data_len, 3);
return ESP_OK;
}

其他配置与功能

传输方式选择

CONFIG_APP_NETWORK_PROV_TRANSPORT_BLE 用于配置配网的 BLE 传输方式。 CONFIG_APP_NETWORK_PROV_TRANSPORT_SOFTAP 用于配置配网的 SoftAP 传输方式。

配网超时时间

CONFIG_APP_NETWORK_PROV_TIMEOUT_PERIOD 可用于配置配网自动停止的超时时间(单位:分钟)。超时后需重启设备才能重新开始配网。建议始终将该值设置为非零值,尤其在不使用 PoP 时。若不希望配网自动停止,可将其设为 0。

暴力破解防护

CONFIG_APP_NETWORK_PROV_MAX_POP_MISMATCH 用于配置允许的 PoP 匹配失败最大次数,超过该次数后配网流程将自动停止。

失败后重置

CONFIG_APP_NETWORK_RESET_PROV_ON_FAILURE 可用于配置配网的失败后重置功能。若启用该配置,配网失败时设备将自动重置。CONFIG_APP_NETWORK_PROV_MAX_RETRY_CNT 可用于配置配网允许的最大重试次数,超过该次数后,配网流程自动停止并触发设备重置。

SSID 数量

默认情况下,Wi-Fi/网络配网会返回 16 个 SSID。可通过 CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES/CONFIG_NETWORK_PROV_SCAN_MAX_ENTRIES 配置该数量。

OTA

回滚

当 OTA 升级失败或新版本固件出现异常时,可通过回滚功能将设备恢复到之前的固件版本。

OTA 版本回滚功能基于 ESP-IDF 中的 APP 回滚功能实现。在 ESP RainMaker 中,启用 CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE 即可开启该功能。ESP RainMaker 示例中已默认启用。设备重启后,固件会等待 CONFIG_ESP_RMAKER_OTA_ROLLBACK_WAIT_PERIOD 秒(默认 90 秒)尝试建立 MQTT 连接,若连接失败则触发回滚。

OTA 获取

默认情况下,固件会在启动时尝试一次 OTA fetch(由 CONFIG_ESP_RMAKER_OTA_AUTOFETCH 配置控制)。若设置了 CONFIG_ESP_RMAKER_OTA_AUTOFETCH_PERIOD,固件会每隔 CONFIG_ESP_RMAKER_OTA_AUTOFETCH_PERIOD 小时自动尝试一次 OTA Fetch。

OTA 重试

CONFIG_ESP_RMAKER_OTA_MAX_RETRIES 用于配置 OTA 最大重试次数。设备在 OTA 下载失败后会不断重试,直到重试次数到达此上限。默认值为 3,取值范围为 1-10。

CONFIG_ESP_RMAKER_OTA_RETRY_DELAY_MINUTES 用于配置所有重试失败后,重新获取 OTA 详情的时间延迟(单位:分钟),适用于通过主题 (topics) 进行的 OTA。默认值为 5 分钟,取值范围为 1-60 分钟。

OTA 压缩

1. 在 CMakeLists.txt 中添加 include(gen_compressed_ota)

在项目的 CMakeLists.txt 中添加以下代码:

# 以下代码示例必须严格按顺序放入项目的 CMakeLists 中
# 以确保 cmake 正常工作
cmake_minimum_required(VERSION 3.16)

# (非示例代码的部分)
# 本示例使用一个额外组件来提供通用功能,如 Wi-Fi 和以太网连接
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(simple_ota)
include(gen_compressed_ota)

2. 添加 bootloader_components

从以下路径复制 bootloader_components 目录:

https://github.com/espressif/esp-iot-solution/tree/master/examples/ota/simple_ota_example

将其粘贴到你的项目中,然后删除此目录下的 idf_component.yml 文件。

3. 修改分区表

压缩 OTA 要求 secondary OTA 分区的容量更小。请按以下方式创建常规的 ota_0 分区和用于存储压缩固件的 ota_1 分区:

# 名称, 类型, 子类型, 偏移, 大小, 标志
esp_secure_cert, 0x3F, ,0xd000, 0x2000, encrypted
nvs, data, nvs, 0x10000, 0xC000,
nvs_keys, data, nvs_keys,, 0x1000, encrypted
otadata, data, ota, , 0x2000
phy_init, data, phy, , 0x1000,
ota_0, app, ota_0, 0x20000, 0x120000,
ota_1, app, ota_1, 0x140000, 0xBA000,
fctry, data, nvs, 0x1FA000, 0x6000,

ota_1 分区的容量只需足够容纳压缩后的固件即可。

4. 修改 idf_component.yml

更新项目主目录下的 idf_component.yml 文件,在其中添加 bootloader_support_plus

dependencies:
bootloader_support_plus:
version: "0.*"

5. 启用 OTA 压缩功能

在默认配置中启用以下配置项:

CONFIG_BOOTLOADER_COMPRESSED_ENABLED=y
CONFIG_BOOTLOADER_DECOMPRESSOR_XZ=y

MQTT 消息配额机制

ESP RainMaker 使用 MQTT 消息配额机制 (MQTT budgeting) 来限制节点发送的 MQTT 消息数量。该功能有助于防止过度云端通信,有效控制成本。对于私有部署场景,如果数据上报频率已合理设计且服务质量至关重要,通常建议禁用此功能。如果仍然担心固件代码出现异常(如发送过多消息),则可启用此功能。

配置项

基础设置

  • 通过 CONFIG_ESP_RMAKER_MQTT_ENABLE_BUDGETING 启用或禁用该机制(默认:启用)
  • 默认配额:CONFIG_ESP_RMAKER_MQTT_DEFAULT_BUDGET(默认:100)
    • 取值范围:64 至最大额度
    • 每发送一条 MQTT 消息,配额减少 1
    • 当配额降至 0 时,消息将被丢弃

配额上限

  • 最大配额:CONFIG_ESP_RMAKER_MQTT_MAX_BUDGET(默认:1024)
    • 取值范围:64 至 2048
    • 配额达到上限后将不再继续增加

配额恢复

  • 恢复周期:CONFIG_ESP_RMAKER_MQTT_BUDGET_REVIVE_PERIOD(默认:5 秒)

    • 取值范围:5 至 600 秒
    • 每经过一个配额恢复周期,配额数量自动增加
  • 恢复数量:CONFIG_ESP_RMAKER_MQTT_BUDGET_REVIVE_COUNT(默认:1)

    • 取值范围:1 至 16
    • 每个恢复周期内增加的配额数量

工作原理

  1. 节点启动时,初始配额为默认值(每 5 秒 100 个)
  2. 每发送一条 MQTT 消息,流量额度减少 1
  3. 每隔一个恢复周期,自动增加恢复数量的配额
  4. 若额度降至 0,后续消息将被丢弃
  5. 配额数量不会超过配额上限

最佳实践

  • 根据应用的消息发送频率配置额度
  • 结合实时性需求设置流量额度恢复周期
  • 恢复数量应根据可能出现的突发消息量调整
  • 监控被丢弃的消息数量,必要时调整相关配置
note

MQTT 配额限制对于防止消息泛滥和管控云服务成本至关重要,请根据具体使用场景谨慎配置。

On this page