1. 目标与调用链

本文介绍在 OpenHarmony 5.1 小型系统中,把 iot-management 的设备发现和连接能力接到 WS73 Wi-Fi 的实践方法。

最终调用链可以概括为:

iot-management
    -> OpenHarmony Wi-Fi C API
    -> Wi-Fi Manager / HAL
    -> WPA + nl80211
    -> cfg80211
    -> WS73 内核模块与固件

真正的难点不是某个接口能否单独调用,而是异步回调、Lite IPC 权限、扫描状态、配置编号、DHCP 和底层驱动要形成同一条可重复验证的链路。

2. 先证明底层 Wi-Fi 正常

在排查 iot-management 之前,先用通用 Wi-Fi 接口确认以下能力:

  • Wi-Fi 可以启用并进入工作状态;
  • 扫描能够返回真实 AP;
  • 可以添加网络配置;
  • 能够连接目标热点并获得 IP 和网关;
  • 可以断开并删除配置。

如果 wlan0 不存在、WPA 配置解析失败或 DHCP 没有启动,继续分析 iot-management 回调没有意义。建议把“驱动/固件、Wi-Fi 服务、通用 API、iot-management”分成四层记录结果。

3. Lite 扫描接口不要照搬两阶段长度查询

部分平台习惯先传入空指针查询列表长度,再分配数组:

GetScanInfoList(nullptr, &size);

但 OpenHarmony Lite 的相关实现可能要求调用方预先提供固定容量数组。更稳妥的写法是:

std::vector<WifiScanInfo> scanInfos(WIFI_SCAN_HOTSPOT_LIMIT);
unsigned int size = scanInfos.size();
int ret = GetScanInfoList(scanInfos.data(), &size);
if (ret != WIFI_SUCCESS) {
    return ret;
}
scanInfos.resize(size);

这里的关键不是 vector,而是遵守公共 C API 的真实参数契约。调用方式应同时对照头文件、服务端参数校验和目标产品实现,不能根据其他平台经验推测。

4. networkId=0 是合法值

空配置环境下,第一个 Wi-Fi 配置编号经常是 0。如果业务代码使用 networkId > 0 判断成功,就会出现“添加配置返回成功,但首次连接仍失败”的问题。

正确做法是只把接口定义的无效值视为失败,例如:

if (networkId == WIFI_CONFIG_INVALID) {
    return IOTC_ERROR;
}

后续连接、断开和删除配置都应遵循同一语义,避免不同函数对 0 的判断不一致。

5. 定时器语义决定异步扫描能否收口

iot-management 的扫描通常依赖周期定时器。如果使用带谓词的 condition_variable::wait_for(),返回值表示“谓词是否满足”,而不是“是否发生超时”。

建议用能表达真实含义的变量名:

bool cancelled = condition_.wait_for(lock, period_, [this] {
    return stopped_;
});

if (!cancelled) {
    callback_();
}

若把返回值误命名为 timeout,并在其为 true 时执行回调,正常到期反而不会触发,最终表现为服务入口已执行、测试程序也返回了,但 finished=0failed=0,底层扫描从未发生。

6. Lite IPC 权限和服务自启动必须一起检查

客户端报 Cannot Find Feature 不一定表示服务没有编译。需要交叉检查:

  1. /bin/iotc_management 是否进入 rootfs;
  2. init 配置中的执行路径是否与真实文件一致;
  3. 服务是否由 init 自动启动;
  4. Samgr 是否注册默认 Feature;
  5. Lite IPC 策略是否允许访问 iotc_management

服务名可以与可执行文件名不同,但 init 的 path 必须指向真实文件。构建成功后建议直接比较源 init 配置、OUT 中间文件和 rootfs 最终文件,避免旧增量产物残留。

7. WPA 配置要匹配当前 Lite 变体

通用模板里的字段不一定被当前 Lite/UDP WPA 构建支持。若 wifi_client enable 失败,应先使用可观察日志定位具体字段,再收敛为产品级模板。

一个最小示意如下:

country=CN
ctrl_interface=udp

network={
}

产品发布前要反向检查最终 rootfs 的配置,而不是只检查 vendor 源文件。配置解析失败属于 WPA 层问题,不应误判为 WS73 驱动失败。

8. 异步验收不要只看进程退出码

完整扫描验收至少记录五项:

同步调用返回
服务端进入扫描入口
底层 Wi-Fi 扫描发生
完成或失败回调到达
本轮资源和状态被释放

测试程序建议连续执行两轮,每轮同时要求:

  • finished=1
  • failed=0
  • 原生扫描返回成功;
  • 真实 AP 数大于 0。

连接生命周期则继续验证:目标 SSID/BSSID、添加配置、连接成功、非零 IP/网关、主动断开、删除配置。若目标热点不可见,应停在扫描阶段,不要把环境问题写成连接代码失败。

9. 构建图也要验证

把适配代码写进某个 GN 模板,不代表目标一定使用了它。每次修改后应检查生成的 Ninja 文件:

  • 原 source 是否已按预期移除;
  • 新 object 是否实际编译;
  • wrap 或链接参数是否进入最终命令;
  • 最终 ELF 是否定义所需符号;
  • rootfs 中是否使用本轮新库。

这一步可以避免“源码改对了、产品也显示 build success,但最终库仍是旧实现”的假成功。

10. 总结

OpenHarmony Lite 上打通 iot-management 与 WS73,核心不是增加更多兼容代码,而是严格对齐每一层的真实接口契约:扫描数组、配置 ID、定时器返回值、IPC 权限、WPA 配置和异步回调。

建议始终按“驱动和固件 → Wi-Fi 服务 → 通用 C API → iot-management 回调 → 连接与 DHCP”逐层推进。每层都有独立证据,问题就不会在错误模块里反复兜圈。

Logo

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

更多推荐