🏠 home › concepts › iot-device-bootstrap
tags
[IoT, bootstrap, 配网, 4G, 服务发现, 信任根]
created
2026-04-24
updated
2026-04-24
sources
[raw/snippets/bk7258-build/iot-architecture-onboarding.md]

定义

IoT 设备启动后必须知道"开机第一个该连谁"——即去哪里拿 MQTT broker 地址、TLS 证书、设备身份。这是 IoT 版本的 service discovery 问题。WiFi 设备可以通过 BLE 配网时由 APP 当场推送,4G 设备没有蓝牙就不能这么做——固件总得知道某个入口作为信任根。本页梳理业内 5 种主流方案 + 信任根的本质问题,以及它对 sentino-iot 扩展到 4G 形态时的工程含义。

背景:WiFi 模式的"配网时下发 MQTT 接入点"

sentino-iot 当前 BK7258 + WiFi 形态走的是这个路径:APP 通过蓝牙下发的 JSON 不只包含 WiFi SSID + 密码,还包含 MQTT 接入信息(8 字段):

字段 含义 写到哪
sid WiFi SSID Config_Net_info->Wifi_Info.Ssid
pw WiFi password Config_Net_info->Wifi_Info.Key
mq MQTT host 域名 Config_Net_info->Mqtt_Info.Mqtt_Host
iport MQTT 端口 Config_Net_info->Mqtt_Info.Mqtt_Port
bid 绑定 ID(用户绑设备的关系凭证) Config_Net_info->Bind_Id
userId 用户 ID Config_Net_info->User_Id
country 国家码(默认 CN) Config_Net_info->Country_Code
tz 时区(默认 Asia/Shanghai) Config_Net_info->User_Tz_Str

MQTT 接入地址不是固件硬编码的,由 APP 在配网时动态下发,存到 Flash。这种设计的好处:APP 端可以根据用户区域、账号路由到不同的 MQTT 集群(国内/海外、生产/测试),固件出厂后不用换。

→ Sentino 当前实际接入点是 mqtt-iot.sentino.jp:8883(Sentino 自建 MQTT 集群),不是腾讯云原厂常量。这一条事实在排查"MQTT 连不上"的问题时容易被误以为是固件硬编码——实际是 Flash 里的配网信息

4G 设备的核心约束:没有蓝牙怎么办

4G 设备: - SIM 卡是运营商烧录的凭证(IMSI/Ki),上电就能联网 - 没有"配网"概念——rino_ble/rino_app/rino_config_net.crino_wifi/ 在 4G 项目里全都用不上 - 但固件总得知道"开机第一个该连谁",否则啥都干不了

这跟后台的 service discovery 是同一类问题。业内 5 种主流方案,按"灵活度 vs 复杂度"排序:

5 种方案对比

方案 A:出厂硬编码

#define MQTT_HOST "mqtt-iot.sentino.jp"
#define MQTT_PORT 8883

方案 B:引导服务器重定向 (Bootstrap Server) ★ 行业主流

固件硬编码一个轻量引导地址,开机先连它,引导服务器返回真正的 broker 地址:

开机 → 4G 拨号上网 → HTTPS POST https://bootstrap.sentino.jp/v1/lookup
       Body: {"device_id":"xxx","region":"JP","fw":"1.0.5"}
       ↓
       应答: {"mqtt_host":"mqtt-iot-jp.sentino.jp","mqtt_port":8883,"expires":3600}
       ↓
       缓存到 Flash → 连 MQTT
       下次开机直接读 Flash 缓存,跳过引导

引导服务器可以根据: - 设备区域(SIM 卡国家码、IP 地理位置)→ 路由到最近 broker - 租户/品牌(设备 ID 前缀)→ 路由到对应集群 - 灰度/AB 测(按 device_id 分桶)→ 部分设备连新 broker

这是腾讯云/阿里云/AWS IoT Core 的标准做法: - AWS:Fleet Provisioning by Claim(设备出厂烧 claim cert,首次连用 claim cert 申请独立 cert,5 分钟内换证。详见 AWS IoT 官方) - 阿里云:一型一密(动态注册) - 腾讯云:动态注册(dynamic register)

方案 C:DNS 间接寻址(最优雅)

固件硬编码一个逻辑域名,靠 DNS 把它解析到具体集群: - GeoDNS:日本来的解析到日本节点 - CNAME:今天指向 cluster-a,明天切到 cluster-b - TTL 5 分钟:可以快速切换

方案 D:HTTP 拉配置文件

固件硬编码一个配置 URL,开机拉 JSON:

GET https://config.sentino.jp/devices/xxx/config.json
→ {"mqtt_host":"...", "mqtt_port":8883, "ca_cert_url":"...", ...}

方案 E:LwM2M Bootstrap(电信/工业标准)

NB-IoT/LTE-M 设备的标准做法。固件烧一个 BS server URI:

固件硬编码: coaps://bootstrap.operator.com:5684
设备连 BS server (CoAP over DTLS)
BS server 用 LwM2M 协议把真正的 server 配置写进设备 Object 1

信任根问题:不可能"零硬编码"

无论哪种方案,固件里总得硬编码"某个入口"作为信任根。区别只是入口的形态:

方案 硬编码的是什么 信任怎么验证
A 硬编码 MQTT host:port TLS 证书(pin 在固件里)
B 引导 Bootstrap URL TLS 证书 + 应答签名
C DNS 逻辑域名 TLS 证书 + DNSSEC
D HTTP 配置 URL TLS 证书 + 文件签名
E LwM2M BS server URI DTLS PSK / 证书

不可能完全"零硬编码",否则设备会被任何 DNS 投毒/中间人接管。问题不是要不要硬编码,而是硬编码什么 + 怎么验证

选型决策树

要不要让 APP 当场参与配置?
├─ 要 → 蓝牙配网(Sentino 当前 WiFi 项目方案)
└─ 不要
    ├─ 要按设备做差异化路由(多租户/灰度)?
    │   ├─ 要 → 方案 B 引导服务器
    │   └─ 不要
    │       ├─ 要按区域路由?
    │       │   ├─ 要 → 方案 C DNS(GeoDNS)
    │       │   └─ 不要 → 方案 A 硬编码
    │       └─ 偏静态 → 方案 D HTTP 配置文件
    └─ 是 NB-IoT 运营商方案 → 方案 E LwM2M Bootstrap

Sentino 已有基础设施(方案 B 留位)

Sentino BK7258 项目的 rino_iot_sdk 已经为方案 B(动态注册)留好了基础设施,只是当前 WiFi 流程不走它:

文件 作用
rino_iot_sdk/factory_test/factory_dynamic_register.c 动态注册客户端(连引导服务器拿三元组)
rino_iot_sdk/factory_test/factory_dynamic_register.h:17 Register_Test_Mqtt_Client_Task_Start(host, port, cbs)
rino_iot_common.h:22 DYN_REG_SERVER_URL 引导服务器域名常量(腾讯版本,需替换为 Sentino

纯 4G 版本最自然的接入路径: 1. 固件硬编码 bootstrap.sentino.jp(替换上述常量) 2. 4G 拨号上网后第一件事:HTTPS 请求引导服务器 3. 引导服务器返回 mqtt_host/mqtt_port/triple/user_id 4. 缓存到 Flash → 连 MQTT 5. 下次开机直接读缓存,跳过引导

完全不需要蓝牙,且保留"换集群不换固件"的能力——这是方案 B 在 Sentino 4G 形态产品上的具体落地。

4G 设备的三芯片架构(Sentino SDK 已预留)

虽然当前 BK7258 + WiFi 项目不用 4G,但 SDK 里 rino_iot_sdk/rino_protocol/rino_soc_mcu_protocol.{h,c} 预留了 4G 协议代码——属于另一种产品形态:

BK7258 (SoC) ─UART1─ 外挂 MCU (低功耗,电池供电,PIR/电量) ─UART2─ CAT1 模组 (移远 EG800G-EULD)
   ↑                                                                ↑
业务大脑                                                       接入运营商网络

典型场景:电池供电的低功耗联网设备(户外摄像头、智能门锁、无人值守传感器)。平时外挂 MCU 深度睡眠,PIR 触发或定时唤醒,唤醒后通过 CAT1 上报数据,BK7258(如果存在)只在需要 WiFi 配置/OTA 时才启动。

SoC-MCU 协议关键命令: - SOC_MCU_CMD_GET_RSSI (0x90) — 获取 CAT1 信号强度 - SOC_MCU_CMD_CAT1_INIT (0xC0) — 命令 CAT1 重新初始化 - SOC_MCU_CMD_GET_CAT1_STATE (0xC1) — 获取 CAT1 状态 - SOC_MCU_CMD_EXT_UART_SET (0x93) — 透传扩展串口数据(让 SoC 直接发 AT 指令到 CAT1) - SOC_MCU_CMD_REPORT_RSSI (0xD4) — MCU 主动上报信号强度

注意 SoC 不直接说 AT 指令,而是通过 SOC_MCU_CMD_EXT_UART_SET 让外挂 MCU 把数据透传到 CAT1 那条串口。AT 指令的脏活在外挂 MCU 那边——这是把"通信协议复杂度"和"业务大脑"物理隔离的典型嵌入式做法。

协议帧格式:Header(0xAB) | Length(2B) | Cmd(1B) | Data(nB) | XOR(1B),小端序、异或校验、错误码 0~5——嵌入式 UART 自定义二进制协议的典型样式。

4G 项目特有考量

维度 说明
流量成本 物联网卡按 MB 计费,要拉长 MQTT keepalive、压缩 payload
信号波动 隧道/电梯掉网常态,必须做断线重连 + 离线消息缓存到 Flash
功耗管理 NB-IoT 靠 PSM/eDRX 深度睡眠,秒级 vs 分钟级上报差几十倍电池寿命
运营商管理 物联网卡有实名制、专网、机卡绑定政策,换 SIM 可能停卡
位置定位 没 WiFi 但有基站定位 (LBS) / GPS / AGPS
远程升级 4G 流量贵,必须用差分升级(只下发 patch)
TCP 长连接 运营商 NAT 超时一般 5~10 分钟,MQTT keepalive 必须小于这个

对 Sentino 战略的工程含义

  1. 当前 BK7258 + WiFi + BLE 配网形态是消费 IoT 主流——只要客户场景在室内固定位置(玩偶、故事机、桌面陪伴),不需要切换到 4G
  2. 如果未来扩展户外/移动场景(车载玩偶、户外宠物追踪、儿童手表),方案 B 引导服务器 + 现有动态注册基础设施可以支撑,不需要重新设计
  3. 可以做混合形态产品——同一套 SDK + 业务代码,BSP 层切换 + bootstrap 路径分流,WiFi 和 4G 双形态客户都能服务(这是 embedded-firmware-layering 分层架构的复用价值)
  4. 客户对话时的话术:当客户问"你们设备要不要后台改硬件支持 4G?"——答"BSP 层重写 + bootstrap 路径切换,业务零改动",体现工程成熟度

相关概念