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 = 0ConfigIsNetInfoNeedVerify() = falseConfigIsNetInfoChecked()  = false
├─ ConfigIsNetInfoNeedVerify()==falseConfigIsNetInfoChecked()==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/密码 + 注册信息):

AppBLE 写入 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),默认值
1NET_INFO_FLAG_NEED_VERIFYWiFi 账密已保存,等待验证flash (conn_data)
2NET_INFO_FLAG_CHECKEDWiFi 已连接验证通过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()==trueSchedTimerAdd(60s, WifiVerifyConnectTimeoutTimerCallback)

6.2 验证流程(并发运行)

并发运行:WifiStatusCheckTimerCallback1s 周期,)
├─ 检测到 IsNetworkConnected() 由 falsetrue:
│     ├─ 设置 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, &regInfo)
      │   └─ 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.cIotcOhDemoEntry
主入口登记iotc_oh_connect.cIotcOhMain
执行初始化单元fwk_init.cFwkInitAll
注册 WIFI_CONNECT 服务wifi_svc_conn.cWifiServiceConnectInit
拉起 WIFI_CONNECTiotc_oh_wifi.cEventBusStartWifiSvcCallback
onStart 实现wifi_svc_conn.cStartWifiConnectService
配网信息到达(BLE)ble_svc_netcfg.cPutBleSvcNetCfg
JSON 解析分流ble_svc_netcfg.cNetCfgProcessFromJson
存 registerInfosvc_cloud_setup.cDeviceServiceRecvBindingInfo
写 RAMconfig_register_info.cConfigSaveRegisterInfo
存 WiFi 账密+netFlag=1svc_conn_net_info.cSvcConnSetNetInfo
连接 WiFi + 验证定时器svc_conn_action.cConnSvcActionConnectWifi
验证超时处理svc_conn_action.cWifiVerifyFailedProcess
网络状态轮询svc_conn_action.cWifiStatusCheckTimerCallback
netFlag 1→2 升级svc_conn_action.cConfigSetNetInfoChecked
云 FSM INIT 决策m2m_cloud_fsm.cCloudFsmInitHandler
注册请求构建m2m_cloud_reg.cM2mCloudBuildRegisterRequest
注册响应处理m2m_cloud_fsm.cM2mCloudRegisterRegRespHandler
合成 loginInfom2m_cloud_reg.cParseRegRespSenseInfo
存 loginInfoconfig_login_info.cConfigSaveLoginInfo

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 连不上、注册失败)都会清理状态回退到待配网,避免设备卡在中间态。
Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐