蓝牙配网与设备认领
BLE用于近场设置WiFi和取得设备身份;MQTT用于设备连接平台、确认账号归属及后续业务。设备连接WiFi不代表账号绑定成功。手机四步向导为进入配网提示、WiFi输入、扫描选择、连接与云端确认,最后按实际阶段显示圆形进度。
操作流程
- 已登录小程序,按产品说明进入限时物理配网窗口。继电器使用同一按键三连短按,EnvSense使用BOOT长按约3秒、达到阈值即时生效。不要套用一个通用“按BOOT”提示。
- 填写SSID/密码,手机允许时可读当前SSID;密码不能从系统自动取回。仅支持DHCP,不提供静态IP/网关/DNS。进入配网时不偷偷提交旧WiFi或超时恢复旧网络。
- 扫描匹配服务UUID的设备,选择后发现特征、协商实际MTU并建立Security 2会话。普通用户不填写MQTT密钥、不扫描二维码。
- 手机经加密端点读取productId/physicalId与设置身份,向后端换10分钟单次票据;发送WiFi参数,设备取得IP后把票据与物理窗口nonce经MQTT送云端。
- 手机收到设备接受票据后断开BLE,让设备释放安全会话和配网资源;手机继续通过HTTP轮询认领状态。只有归属ACTIVE才显示添加成功。
灯态为等待/未配置快闪、正在配网/连接WiFi慢闪、STA关联成功常亮;常亮不说明DHCP、TLS、MQTT或账号归属成功。传感器窗口结束后的正常联网用绿灯,OTA/故障灯态优先。
BLE内核与端点
小程序src/ble/core复用Duruofu Dev Tools连接内核快照,负责适配器、连接生命周期、GATT串行队列和资源清理。ble/provisioning实现本平台协议、安全会话、WiFi与认领。使用ESP-IDF 6.1 + network_provisioning/protocomm Security 2,不自建简化加密算法。
服务UUID:f6d00001-7c9e-4a19-9c38-02a5840f6e31。下表特征统一为f6d0<短号>-7c9e-4a19-9c38-02a5840f6e31,read/write;正式Profile在device-profile.ts。
| 短号 | 逻辑端点 | 内容 |
|---|---|---|
| ff4f | control | 官方WiFi重试/控制 |
| ff51 | session | Security 2握手 |
| ff52 | config | 官方WiFi设置与查询 |
| ff53 | version | 版本与安全能力 |
| ff54 | info | 加密读取设备身份;探针固件曾用echo,不能混用 |
| ff55 | claim | 加密提交/确认平台票据 |
MTU协商失败不等于连接失败,先查询实际容量;不能假设Android一定517或iOS一定512。Profile缺claim时记录实际发现服务/特征,再检查固件、iOS GATT缓存及旧会话,不跳过必需特征。历史资源与缓存故障经验见设计决策。
空板身份与认领
无逐板凭据的工厂镜像首次启动本地随机生成设备身份。physicalPairing窗口中手机可从加密info取得claimSetupCode;selfProvisioning设备另给mqttPasswordHash(SHA-256摘要),手机向POST /api/v1/device-claims发送productId、physicalId、setupCode、可选bootstrapHash。摘要不是可登录密码;云端验证并按productId/physicalId创建或恢复未绑定记录。
同MAC已解绑/未绑定可重刷后替换旧身份并保留云端记录/历史;仍绑定账号或停用身份不能覆盖。允许DIY登记不等于制造商真伪证明。管理员预置出厂身份是另一入口,不要求普通用户手填设置码。
认领响应含claimId、deviceId、token、expiresAt、status=pending;token仅设备安全通道使用,数据库存哈希。查询状态不返回token或设置码,且仅认领发起账号可读。
MQTT归属握手
binding/post claim完整结构为:
{"schemaVersion":1,"op":"claim","bootId":"22222222-2222-4222-8222-222222222222","nonce":"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa","token":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}nonce、token和bootId必须来自真实窗口/票据/当前启动。prepare结构(前缀同MQTT):
{"schemaVersion":1,"op":"prepare","transitionId":"88888888-8888-4888-8888-888888888888","oldEpoch":null,"epoch":"abcdef0123456789abcdef0123456789","nonce":"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa","targetBootId":"22222222-2222-4222-8222-222222222222","expiresAtUtc":1793203800}ready回报:
{"schemaVersion":1,"op":"ready","transitionId":"88888888-8888-4888-8888-888888888888","epoch":"abcdef0123456789abcdef0123456789","nonce":"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa","bootId":"22222222-2222-4222-8222-222222222222"}commit与prepare字段相同,op改commit且expiresAtUtc为null;设备持久后以同ready结构把op改active回报。服务端最后发op=active确认。解绑使用abort/to-unassigned清理,失败不越过持久屏障。重连resume及boot_confirm通过后端30秒HMAC挑战确认当前bootId,挑战由服务端生成,设备原样回送,不在手机端制造;token-only旧认领报文不再支持。
排查与边界
等待云端确认时按顺序检查DHCP、TLS内存/证书、MQTT认证/订阅、票据期限和归属各阶段。BLE释放可以降低TLS共存峰值,但不能降低证书校验。错误提示只一句时启用开发者工具真机日志,记录stage、operation、errCode及耗时,不记录WiFi密码/票据。
新产品网关和BLE子设备当前只预留分层,不把扫描到任意BLE设备等同于已能桥接上云。具体实物版本与Android/iPhone验证范围集中在事实基线,部署和排障分别见运维章节。
