Hi3863 未配网阶段:从配网到上云的完整流程
1. 引言
设备首次上电(或恢复出厂)时,flash 中没有任何 Wi-Fi 账密与云端登录凭据,netFlag == 0,设备处于"未配网"状态。此时设备需要经历一条完整的链路才能最终上线:
待配网(BLE 广播) → App 下发配网报文 → 保存凭据 → 连接 Wi-Fi → 验证 → 云端注册 → 云端登录 → 在线
本文以 hi3863 瘦设备 + BLE_SUP 配网模式为例,梳理从"未配网"到"设备上线"的完整过程,涉及代码均以 foundation/communication/iot_connect 为准。
2. 整体执行流(从设备上电到连接上线)
下面把从设备上电到最终连接的完整执行流串成一条连贯的时间线(→ 表示调用,★ 表示关键节点)。
第一幕:系统启动,创建业务线程
系统上电
└─ SYS_RUN(IOTWifiBleExampleEntry)
└─ 构造 osThreadAttr_t(栈 0x4000、优先级 19)
└─ osThreadNew(IotTask, NULL, &attr)
├─ DEMO_LOG("sleep 30 seconds to wait ble ready.")
└─ IotcOhDemoEntry()
(线程返回后 while(true) osDelay(3000) 空转保活)
第二幕:IotcOhDemoEntry —— 注册能力与配置
IotcOhDemoEntry()
├─ IotcOhDevInit()
│ ├─ IotcOhOptionRegister(DEVICE_OPTION_TABLE)
│ ├─ FwkRegInitUnitArray(OH_DEVICE_INIT)
│ └─ CoreSecurityRegisterInitUnit()
├─ IotcOhBleEnable()
│ └─ FwkRegInitUnitArray(OH_BLE)
├─ IotcOhWifiEnable()
│ ├─ IotcOhOptionRegister(WIFI_OPTION_TABLE)
│ ├─ FwkRegInitUnitArray(OH_WIFI)
│ └─ CoreWifiRegisterInitItem()
│ └─ FwkRegInitUnitArray(CORE_WIFI)
├─ SET_OH_SDK_OPTION(...) 注册 10+ 个回调/参数
└─ IotcOhMain()
关键:
IotcOhSetOption内部把回调存进ProductHooks全局钩子表,后续由ProductProfPutCharState等函数取回调用。
第三幕:IotcOhMain —— 登记基础设施并拉起主线程
IotcOhMain()
├─ FwkRegInitUnitArray(OH_COMM)
├─ FwkRegInitUnits(CoreInfrastructureGetInitUnit(),
│ CoreInfrastructureGetInitUnitSize(), ...)
└─ IotcFwkMain(g_taskSize)
└─ 构造 IotcTaskParam{ iotc_main_task, 优先级 MID }
└─ IotcTaskCreate()
第四幕:主线程 FwkInitAll —— 一次性执行所有初始化单元
IotcFwkMainTaskBody()
└─ FwkInitAll(FWK_INIT_FAILED_RETURN)
├─ DEP/COMP 基础设施:内存/日志/事件总线/消息队列/调度器/security
├─ FWK DeviceServiceInit → ServiceManagerRegisterInstance(DEVICE)
├─ FWK WifiSchedFdWatchInit → 注册 WiFi fd 监听
├─ BIZ WifiServiceConnectInit → ★ ServiceManagerRegisterInstance(WIFI_CONNECT)
│ 存下 .onStart = StartWifiConnectService
├─ BIZ WifiServiceSoftapInit / LanSearchServiceInit / LocalControlServiceInit / M2mCloudServiceInit
│ (各自注册 SOFTAP/LAN_SEARCH/LOCAL_CONTROL/M2M_CLOUD)
├─ BIZ IotcOhDevMainInit → 订阅 MAIN_INITIALIZED、SECURITY_SVC_START
├─ BIZ IotcOhWifiMainInit → ★ 订阅 DEVICE_SVC_START → EventBusStartWifiSvcCallback
├─ BIZ IotcOhBleMainInit → 订阅 DEVICE_SVC_START → EventBusStartBleSvcCallback
└─ BIZ IotcOhStoreDataInit → 存储路径初始化(/data/app/iotc)
所有服务的 initFunc 只是"注册进服务管理器",没有任何 onStart 被调用。
第五幕:主循环 —— 事件链逐级拉起服务
FwkMainLoopEntry(g_stackSize)
└─ 发布 IOTC_CORE_COMM_EVENT_MAIN_INITIALIZED
│ ↓ 订阅者:IotcOhDevMainInit 注册的 EventBusStartSecSvcCallback
▼
ServiceProxyStartService(IOTC_SERVICE_ID_SECURITY)
└─ SecurityServiceStart()
├─ SecConfInfoInit()
├─ SecConfLoadKeyCert()
└─ 发布 IOTC_EVENT_INNER_SECURITY_SVC_START
│ ↓ 订阅者:EventBusStartDevSvcCallback
▼
ServiceProxyStartService(IOTC_SERVICE_ID_DEVICE)
└─ DeviceServiceStart()
├─ ProfileReportRegUplink(DeviceReportCallback, "DEVICE")
├─ ConfigInfoInit()
└─ 发布 IOTC_EVENT_INNER_DEVICE_SVC_START
│ ↓ 订阅者:WiFi/BLE/SLE 各模块
├─ EventBusStartWifiSvcCallback()
│ ├─ ServiceProxyStartService(WIFI_CONNECT) → ★ StartWifiConnectService()
│ ├─ 配网模式是 BLE_SUP/BLE_AGT 时跳过 SoftAP
│ └─ ServiceProxyStartService(M2M_CLOUD)
│ └─ M2mCloudServiceStart() → M2mCloudFsmInit()(FSM 定时器驱动登录)
└─ EventBusStartBleSvcCallback()
└─ ServiceProxyStartService(IOTC_SERVICE_ID_BLE)
└─ BleServiceStart()
├─ BleSvcCtxInit() + BleServiceInit()
└─ 开始 BLE 广播,等待 App 接入
3. 未配网阶段:待配网状态
前提:设备首次上电(或恢复出厂),flash 中没有 Wi-Fi 配置,netFlag == 0。
3.1 StartWifiConnectService 执行(本次调用不发起连接)
StartWifiConnectService()
├─ ConnectConfigInfoInit()
│ └─ netFlag = 0 → ConfigIsNetInfoNeedVerify() = false
│ ConfigIsNetInfoChecked() = false
├─ ConfigIsNetInfoNeedVerify()==false,ConfigIsNetInfoChecked()==false
│ └─ 跳过 ConnSvcActionConnectWifi()
├─ 订阅 IOTC_CORE_COMM_EVENT_MAIN_RESTORE
└─ ConnSvcStartNetCheckTimer()
设备继续停留在待配网状态:
- 配网模式为
IOTC_NET_CONFIG_MODE_BLE_SUP→ 不启动 SoftAP(`` 判断) - BLE 服务已启动并广播(``),等待手机 App 接入
3.2 待配网状态特征
★ 状态:设备 netFlag=0 + BLE 广播中 + 1s 网络检测待命 → 等 App 配网
4. 配网阶段:App 经 BLE 下发配网报文
4.1 BLE 接收配网报文
手机 App 通过 BLE 发送配网报文(含 SSID/密码 + 注册信息):
App 经 BLE 写入 netCfg 特征值
→ 链路层解密 → LinkLayerProcessData
→ 按服务名 "netCfg" 路由到 PutBleSvcNetCfg
4.2 JSON 解析与分发(顺序很重要)
PutBleSvcNetCfg
│
├─ ProductRecvNetCfgInfo(jsonStr)
│ └─ 返回 IOTC_ERR_CALLBACK_NULL(Demo 未注册产品回调)
│
└─ NetCfgProcessFromString
└─ NetCfgProcessFromJson
│
├─① DevSvcProxyRecvBindInfo(json) ← 先存 registerInfo
│ → DeviceServiceRecvBindingInfo
│
└─② ConnSvcProxySetNetCfgInfo(json) ← 再存 WiFi 账密
→ SvcConnSetNetInfo
顺序很重要:先存注册信息,再存 WiFi 账密。如果注册信息解析失败,WiFi 账密不会保存。
4.3 registerInfo 各字段解析(纯 RAM 存储)
DeviceServiceRecvBindingInfo
从 JSON 中逐字段提取:
├─ devId ← STR_NETINFO_DEVICE_ID (40字符)
├─ pskHex ← STR_NETINFO_PSK (hex编码)
│ └─ UtilsUnhexify → info.psk (16字节二进制)
├─ code ← STR_NETINFO_CODE (40字符)
├─ url ← STR_NETINFO_URL (64字符)
└─ backupUrl ← STR_NETINFO_BACKUP_URL (64字符) 失败仅告警,不中断
→ ConfigSaveRegisterInfo(&info)
├─ memcpy_s(&g_devRegInfo, ..., info, sizeof(DevRegInfo)) ← 拷贝到 RAM
├─ g_regFlag = true ← 标记存在
└─ return IOTC_OK(不写 flash!)
核心特征:registerInfo 纯 RAM 存储,不落 flash,每次开机被清零。
4.4 配网 JSON 格式
{
"ssid": "MyWiFi",
"password": "12345678",
"deviceId": "xxx-xxx",
"psk": "a1b2c3...",
"code": "verification_code",
"url": "https:
"backupUrl": "https:
}
5. 保存凭据并触发连接
5.1 SvcConnSetNetInfo —— 核心保存逻辑
SvcConnSetNetInfo()
├─ ParseAndSaveNetCfgWifiInfo()
│ ├─ UtilsJsonGetString(ssid/password)
│ └─ IotcSetWifiInfo(ssid, pwd)
│ ├─ ClearWifiConfig() 清RAM旧配置
│ └─ AddDeviceConfig() 写WiFi HAL(RAM+落盘/hilink/wifi.cfg)
├─ ConfigSetNetInfoNeedVerify()
└─ 非 SoftAP 模式(BLE_SUP 走这里):
SchedTimerAdd(10ms) → DelayConnetWifiCb → ConnSvcActionConnectWifi()
5.2 netFlag 状态机
App BLE 下发 netCfg
(ssid/password + devId/psk/code/url)
┌─────────┐ ────────────────────────► ┌─────────┐
│ netFlag=0 │ │ netFlag=1 │
│ 未配网 │ ◄──────────────────────── │ 待验证 │
└─────────┘ 清除(WiFi连不上/超时/开机) └─────────┘
▲ │
│ │ WiFi 连上
│ ▼
│ ┌─────────┐
│ │ netFlag=2 │
└────────────────────────────────────────│ 已验证 │
恢复出厂 / 删除WiFi └─────────┘
| netFlag | 枚举值 | 含义 | 存储 |
|---|---|---|---|
| 0 | — | 未配网 | flash (conn_data),默认值 |
| 1 | NET_INFO_FLAG_NEED_VERIFY | WiFi 账密已保存,等待验证 | flash (conn_data) |
| 2 | NET_INFO_FLAG_CHECKED | WiFi 已连接验证通过 | flash (conn_data) |
6. 连接 Wi-Fi 并验证
6.1 ConnSvcActionConnectWifi —— 连接动作
ConnSvcActionConnectWifi()
├─ 移除旧验证定时器
├─ 发布 IOTC_CORE_WIFI_EVENT_CONNECTING
├─ IotcConnectWifi()
│ ├─ IsWifiActive()? → EnableWifi() 驱动上电
│ ├─ GetWifiConfigFromOhos() 取RAM/文件凭据
│ ├─ AdvanceScanWifiByOhos() ×N 扫描找AP
│ └─ ConnectTo(netId) 关联 + DHCP拿IP
└─ ConfigIsNetInfoNeedVerify()==true →
SchedTimerAdd(60s, WifiVerifyConnectTimeoutTimerCallback)
6.2 验证流程(并发运行)
并发运行:WifiStatusCheckTimerCallback(1s 周期,)
├─ 检测到 IsNetworkConnected() 由 false→true:
│ ├─ 设置 CONN_SVC_BIT_MAP_WIFI_CONNECTED
│ ├─ 移除验证/重连定时器
│ └─ ConfigSetNetInfoChecked()
└─ 60s 验证超时 → WifiVerifyFailedProcess()
├─ IotcDisconnectWifi() + IotcDeleteWifiInfo()
├─ ConfigClearNetInfoFlag()
└─ IotcFwkNotifyReset()
验证窗口内 WiFi 连上 → netFlag 升级为 2(信任凭据);60s 内没连上 → 清除一切,回到 netFlag=0(重新配网)。
6.3 配网涉及的两个定时器
| 定时器 | 周期 | 回调 | 作用 |
|---|---|---|---|
| 10ms 一次性 | 配网后 | DelayConnetWifiCb | 异步发起连接,不阻塞 BLE 响应 |
| 60s 一次性 | NEED_VERIFY 时 | WifiVerifyConnectTimeoutTimerCallback | 验证超时 → 失败清理复位 |
| 1s 周期 | 常驻 | WifiStatusCheckTimerCallback | 检测连上网 → 翻 CHECKED;断网 → 重连 |
7. 云端注册与登录(M2M FSM)
WiFi 连接成功且 netFlag=CHECKED 后,M2M_CLOUD 服务的 FSM 定时器推进云端注册/登录流程。
7.1 FSM 状态机总览
云FSM: INIT → CREATE_LINK → CONNECT → PSK → REGISTER → LOGIN → ... → ONLINE
7.2 INIT 状态:判定走注册路径
CloudFsmInitHandler
│
├─ GetBindStatus()
│ └─ IsDeviceBinded(): 读 flash CONFIG_INFO_KEY_DEVICE_ID
│ └─ devId 为空 → NOT_BIND
│
└─ NOT_BIND 分支:
├─ DevSvcProxyGetRegisterInfo(&isExist, ®Info)
│ └─ IsRegisterInfoExist() → g_regFlag == true ✓
│ └─ ConfigGetRegisterInfo() → 从 RAM 拷贝到 ctx->authInfo.regInfo
│
├─ 设置 M2M_CLOUD_CTX_BIT_REGISTER 标记
├─ 启动注册超时定时器 (M2M_CLOUD_REGISTER_TIMEOUT_MS)
└─ → CREATE_LINK
7.3 云端连接链路建立
CREATE_LINK
├─ M2mCloudLinkCreate(ctx) ← 建立 CoAP/DTLS 链路
├─ M2mCloudCtlInit(ctx) ← 初始化控制层
├─ M2mCloudBackoffInit(ctx) ← 退避初始化(3s)
└─ → CONNECT
CONNECT
├─ 检查 ConnSvcProxyIsNetConnected() == true ✓
├─ M2mCloudLinkConnect(ctx) ← TCP/UDP 连接到云端服务器
└─ → PSK
PSK
├─ M2mCloudSendRequest:
│ ├─ M2mCloudBuildPskRequest ← 用 regInfo.psk 构建 PSK 协商请求
│ └─ M2mCloudPskRegRespHandler ← 等待响应
└─ → PSK_WAIT_RESP
├─ PSK 协商成功 → REGISTER(因为有 REGISTER bit)
└─ PSK 协商失败 → 回 CONNECT
7.4 REGISTER 状态:发送注册请求
REGISTER
└─ M2mCloudSendRequest:
├─ M2mCloudBuildRegisterRequest
│ ├─ JSON 添加 "code": regInfo.code ← 注册激活码
│ ├─ JSON 添加 "devid": regInfo.devId ← 设备ID
│ └─ M2mCloudAddDevInfoToJson ← 产品型号等附加信息
└─ M2mCloudRegisterRegRespHandler ← 等待响应
└─ → REGISTER_WAIT_RESP
7.5 注册响应处理 —— registerInfo 的使命完成
M2mCloudRegisterRegRespHandler
│
├─ M2mCloudParseRegisterResponse
│ ├─ 解析 errcode
│ ├─ errcode != OK → 注册失败 → FSM EXIT
│ └─ errcode == OK → ParseRegRespSenseInfo
│ │
│ │ ★ 从注册响应 + registerInfo 合成 loginInfo ★
│ │
│ ├─ 从 regInfo 提取: psk, url, backupUrl
│ ├─ 从云端响应提取: secret(服务端下发的登录密钥)
│ ├─ devId 已在 regInfo 中
│ │
│ └─ DevSvcProxyRecvLoginInfo(json)
│ → DeviceServiceRecvLoginInfo
│ → ConfigSaveLoginInfo(&info)
│ ├─ ConfigInfoSet(DEVICE_ID, devId) ← flash
│ ├─ ConfigInfoSet(LOGIN_SECRET, secret) ← flash
│ ├─ ConfigInfoSet(LOGIN_PSK, psk) ← flash
│ ├─ ConfigInfoSet(LOGIN_URL, url) ← flash
│ ├─ ConfigInfoSet(LOGIN_BACKUP_URL, backupUrl) ← flash
│ └─ ConfigInfoSave() ← flush 到 flash
│ → /data/app/iotc/dev_data(加密存储)
│
├─ 清除 REGISTER bit
├─ memset_s(&ctx->authInfo.regInfo, ...) ← 清零 FSM 上下文中的 regInfo
│
├─ 重新读取 loginInfo: DevSvcProxyGetLoginInfo → 从 flash 读回
│ └─ 此时 IsDeviceBinded() == true(devId 已写入 flash)
│
├─ BleSvcProxyStopAdv() ← 停止 BLE 广播(配网完成)
└─ → LOGIN 状态
7.6 LOGIN → ONLINE
LOGIN:
→ M2mCloudBuildLoginRequest → 用 loginInfo.secret/psk 构建登录请求
→ 发送到云端 → 云端验证通过 → 返回成功
→ ONLINE ✓
ONLINE:
→ 心跳/Token定时器启动 → 发布上线事件
8. 完整时序图(从待配网到上线)
App 设备(ble_svc_netcfg) WiFi驱动 Cloud FSM
│ │ │ │
│── BLE write netCfg ──►│ │ │
│ │── 解析JSON │ │
│ │ registerInfo→RAM │ │
│ │ ssid/pwd→平台存储 │ │
│ │── netFlag=1 ──────────│ │
│ │── 10ms后连接 ────────►│ │
│ │ │── WiFi连接中 │
│ │◄── 1s轮询:连上了 ─────│ │
│ │── netFlag=2 ★ │ │
│ │ │ │
│ │──────────registerInfo(RAM) + WiFi ──────►│
│ │ │ INIT→CREATE │
│ │ │ →CONNECT→PSK │
│ │ │ →REGISTER │
│ │ │ →注册成功 │
│ │ │ loginInfo→flash│
│ │ │ →LOGIN→ONLINE │
│ BLE广播停止 │ │ │
9. 关键状态量流转
netFlag: 0(未配网) ──收到账密──► 1(NEED_VERIFY) ──连上网──► 2(CHECKED)
▲ │
└────── 60s验证失败,清0 ──────────────┘
广播模式: 未绑定+BLE_SUP → PROTOCOL_WIFI_NETCFG(可配网)
已绑定+在线 → PROTOCOL_POP_CONTRL_BOX(控制)
已绑定+离线 → PROTOCOL_WIFI_OFFLINE(离线)
云FSM: INIT → CREATE_LINK → CONNECT → PSK → REGISTER → LOGIN → ... → ONLINE
10. 代码位置速查
| 功能 | 文件 | 函数 |
|---|---|---|
| 业务总入口 | wifi_ble_combo.c | IotcOhDemoEntry |
| 主入口登记 | iotc_oh_connect.c | IotcOhMain |
| 执行初始化单元 | fwk_init.c | FwkInitAll |
| 注册 WIFI_CONNECT 服务 | wifi_svc_conn.c | WifiServiceConnectInit |
| 拉起 WIFI_CONNECT | iotc_oh_wifi.c | EventBusStartWifiSvcCallback |
| onStart 实现 | wifi_svc_conn.c | StartWifiConnectService |
| 配网信息到达(BLE) | ble_svc_netcfg.c | PutBleSvcNetCfg |
| JSON 解析分流 | ble_svc_netcfg.c | NetCfgProcessFromJson |
| 存 registerInfo | svc_cloud_setup.c | DeviceServiceRecvBindingInfo |
| 写 RAM | config_register_info.c | ConfigSaveRegisterInfo |
| 存 WiFi 账密+netFlag=1 | svc_conn_net_info.c | SvcConnSetNetInfo |
| 连接 WiFi + 验证定时器 | svc_conn_action.c | ConnSvcActionConnectWifi |
| 验证超时处理 | svc_conn_action.c | WifiVerifyFailedProcess |
| 网络状态轮询 | svc_conn_action.c | WifiStatusCheckTimerCallback |
| netFlag 1→2 升级 | svc_conn_action.c | ConfigSetNetInfoChecked |
| 云 FSM INIT 决策 | m2m_cloud_fsm.c | CloudFsmInitHandler |
| 注册请求构建 | m2m_cloud_reg.c | M2mCloudBuildRegisterRequest |
| 注册响应处理 | m2m_cloud_fsm.c | M2mCloudRegisterRegRespHandler |
| 合成 loginInfo | m2m_cloud_reg.c | ParseRegRespSenseInfo |
| 存 loginInfo | config_login_info.c | ConfigSaveLoginInfo |
11. 总结
未配网设备从配网到上云的完整链路可以概括为:
待配网(BLE 广播)→ App 经 BLE 下发 {ssid,password,devId,psk,code,url} → SvcConnSetNetInfo 存账密 + 置 NEED_VERIFY → 10ms 延迟 ConnSvcActionConnectWifi → 60s 内连上拿 IP 即翻 CHECKED → 云 FSM(CREATE_LINK→CONNECT→PSK→REGISTER)注册 → loginInfo 落 flash → LOGIN → ONLINE。
核心要点:
- registerInfo 纯 RAM,用于首次注册,注册成功后合成 loginInfo 落 flash,registerInfo 使命完成。
- netFlag 三态(0/1/2)决定设备是等配网、验证连接还是直接回连。
- **配网后的 Wi-Fi 连接不走
StartWifiConnectService**,而是经SvcConnSetNetInfo → ConnSvcActionConnectWifi独立路径。 - 整个配网流程是事务式的:任一环节失败(WiFi 连不上、注册失败)都会清理状态回退到待配网,避免设备卡在中间态。
更多推荐
所有评论(0)