项目源码:小鸿 SE AI 门锁平台 AtomGit 仓库
FRB 项目:oh-flutter/flutter_rust_bridge
Rust 社区:开放原子旋武开源社区

从摄像头上的一个人脸框,到 HarmonyOS PC 上持续更新的实时画面,中间需要经过 ESP32-P4 推理、板内 UART、WS63 缓存、星闪 SSAP 和 Flutter 展示。小鸿 SE AI 门锁平台已经将这条链路接通,本文进一步讨论如何通过 FRB 为它增加可独立测试的 Rust 协议解析层。

先说明项目现状:当前正式仓库使用 Flutter + Dart Gateway + ArkTS + WS63 + ESP32-P4,README 明确记录已裁剪 Rust/FRB。本文的 FRB 部分是新增扩展方案;文中的设备实拍来自现有系统,不能作为 FRB 扩展已完成真机集成的证据。

本文会先介绍社区与框架,引用已有环境教程,再拆解现有数据闭环、给出 Rust STATUS 解析器和 Dart 接入方式,最后说明运行验证、Issue 反馈与 PR 贡献流程。

一、认识旋武社区与 FRB

1. 旋武社区:Rust 学习与开源协作入口

开放原子旋武开源社区是开放原子开源基金会旗下的 Rust 专项社区,围绕 Rust 学习、工具使用和开源项目协作建设生态。官网提供 Rust 发行版及镜像、学习资料、在线编码体验、社区项目和技术活动等资源。

对于希望将 Rust 引入 Flutter 或鸿蒙项目的开发者,可以先从社区资源了解语言和工程实践,再进入具体仓库阅读代码、反馈问题和贡献修复。社区提供学习交流入口,Issue 与 Pull Request 则让项目中的问题和解决过程可以持续追踪。

2. FRB:让 Dart 调用 Rust 的业务接口

flutter_rust_bridge(简称 FRB)是 Flutter/Dart 与 Rust 之间的跨语言绑定工具。开发者定义 Rust 函数和数据结构,通过代码生成器生成桥接代码,再从 Dart 调用这些接口、接收结果并处理错误。

本文使用的项目入口为:https://atomgit.com/oh-flutter/flutter_rust_bridge。鸿蒙接入说明、框架版本和相关问题,可从该仓库查阅与反馈。

在本次扩展中,FRB 只连接 Dart Gateway 与 Rust STATUS 解析器。NearLink 权限、扫描、配对和 SSAP 传输仍由 ArkTS 处理,ESP-DL 人脸检测仍运行在 P4 上。Rust 解析器不执行 AI 推理,也不提供开锁授权。

二、为什么为当前项目选择 FRB 扩展

现有 Dart 链路已经可用,引入 Rust 应解决具体的维护问题。STATUS 包字段少、边界清晰,适合用作第一次跨语言接入:先验证字节传递、类型映射、错误返回和原生库加载,再决定是否扩大迁移范围。

当前需求扩展方式预期收益
多处字节偏移容易写错Rust 集中解析 XH v1 STATUS通过固定字节样本检查长度、字节序和字段映射
协议错误不容易在 UI 测试中复现解析器接受字节数组,返回结构或错误无需连接开发板就能测试截断包和错误人数
Flutter 页面需要稳定业务数据FRB 返回 DetectionStatus 与人脸框页面使用结构化结果,减少手写跨语言转换
迁移需要可回退先对比 Dart 与 Rust 两份结果在不改变无线和 JPEG 链路的情况下定位差异

STATUS 包很小,跨桥调用开销可能高于解析计算本身,因此这里不承诺性能提升。引入 FRB 的主要价值是把协议校验集中到可测试的模块中;代价是增加 Rust 工具链、生成器版本管理,以及鸿蒙原生库构建与打包工作。

本次选型也有明确范围:先迁移 STATUS,JPEG 重组仍使用现有 Dart 实现。后续若要迁移图像链路,需要单独评估内存、分片处理和断线恢复,不能因为状态包已解析成功,就认为全部协议已经完成迁移。

三、环境搭建:引用教程并区分现有工程与扩展依赖

1. 基础环境参考两篇已有文章

  1. 《2026 年如何上车 Flutter-OH:环境搭建与上手流程》:用于准备 Flutter-OH、DevEco Studio、HarmonyOS SDK,了解工具链检查、真机运行与签名流程。
  2. 《Rust | VS Code搭建Rust开发环境的超详细图文教程总结(含Rust开发常用插件)》:用于了解 Rust、Cargo、VS Code 和常用扩展。该文主要以 Windows 为例,macOS 开发者应按本机平台准备编译与调试工具。

两篇教程分别解决 Flutter-OH 和 Rust 的基础环境问题。复现门锁项目时,还需使用包含 NearLinkKit 的 SDK,并按仓库说明准备 P4 与 WS63 固件。教程中的版本示例不能直接替代项目要求。

2. 当前仓库记录的环境

项目仓库记录
HarmonyOS PCHAD-W24
系统版本6.1.0.117 / OpenHarmony 6.1
HarmonyOS SDK6.0.2(22),包含 NearLinkKit
Flutter支持 OHOS 的 Flutter 3.35 系列
Dart应用 SDK 约束为 ^3.9.2
WS63小鸿 SE WS63,OpenHarmony mini 产品树,SDK v106
ESP32-P4小鸿 SE P4,ESP-IDF 5.4/5.5 工具链

获取现有工程:

git clone https://atomgit.com/xiaohong-ai/xiaohong-se-ai-lock-platform.git
cd xiaohong-se-ai-lock-platform/apps/xiaohong_se_manager
flutter pub get
flutter doctor -v
dart analyze lib test integration_test

当前 App 只保留 HarmonyOS 工程,不提供 macOS 桌面演示壳。完整运行还需要两颗芯片的匹配固件;首次只验证星闪连接时,可以先观察“等待 P4 相机帧”,但这不算图像链路验收通过。

3. FRB 扩展需要另外准备什么

本文扩展示例选用 FRB 2.13.0-beta.6。这是教程选择的版本,不是现有项目已经使用或验证过的依赖。Dart 包、Rust crate 和代码生成器应保持一致:

rustc --version
cargo --version
cargo install flutter_rust_bridge_codegen --version 2.13.0-beta.6
flutter_rust_bridge_codegen --version

新增目录和文件的目标结构如下:

apps/xiaohong_se_manager/
├── flutter_rust_bridge.yaml        新增:绑定生成配置
├── rust/
│   ├── Cargo.toml                  新增:原生 crate
│   └── src/
│       ├── lib.rs                  新增:模块入口
│       ├── protocol.rs             新增:纯 Rust 解析器
│       ├── api.rs                  新增:FRB 包装
│       └── frb_generated.rs        生成器输出
├── lib/src/rust/                   生成器输出
└── rust_builder/                   需另行接入的原生构建插件

flutter_rust_bridge_codegen generate 负责生成绑定,并不会自动完成本工程的 OHOS 构建插件、交叉编译、HAR/HAP 打包和签名。第五节会分别说明主机解析验证和真机集成门槛。

四、项目开发细节:现有链路与 Rust 解析扩展

1. 当前系统的完整数据闭环

UART 0x0C01 至 0x0C05

NearLink SLE / SSAP

MethodChannel / Base64

Camera

ESP32-P4 / ESP-DL 人脸检测

LCD 实时画面与检测框

WS63 缓存与转发

ArkTS NearLinkKit

Dart Device Gateway

Flutter 实时监控与会话记录

状态路径由 App 发起:Dart 每 350ms 查询一次状态,ArkTS 通过 SSAP 写入请求,WS63 与 P4 交换状态并更新缓存,随后把 STATUS 回传给 App。P4 是画面和人脸检测结果的数据源,WS63 不执行人脸检测。

画面路径使用 GET_FRAME 请求较新的 JPEG。P4 将图像分片交给 WS63,WS63 组装完成后更新缓存,再通过 FRAME_BEGINFRAME_CHUNKFRAME_END 发给 App。Dart 完成校验后,Flutter 才显示图像。

可从以下文件阅读现有实现:

apps/xiaohong_se_manager/lib/services/device_gateway.dart
    XH 包编码、状态轮询、STATUS 解析和 JPEG 重组
apps/xiaohong_se_manager/lib/models/device_models.dart
    检测结果、人脸框、相机帧类型
apps/xiaohong_se_manager/lib/features/dashboard/
    实时监控与当前会话访客记录
apps/xiaohong_se_manager/ohos/entry/src/main/ets/entryability/EntryAbility.ets
    NearLink 权限、配对、服务发现与通知
firmware/ws63/src/sle_server/sle_server_task.c
    SSAP 请求与响应
firmware/ws63/src/uart_bridge/
    P4 状态缓存与图像组装
firmware/esp32-p4/
    摄像头、LCD 与 ESP-DL

2. XH v1 包头与 STATUS 字段

App 与 WS63 的包使用小端整数,包头为 10 字节:

偏移长度含义
02Magic:0x58 0x48,即 XH
21包头版本,当前为 1
31消息类型
44request_sequence
82payload_length
10Npayload

STATUS 类型为 0x81。下面的偏移均从 payload 开头计算:

偏移类型字段
0u16protocol_version
2u32last_request_sequence
6u32inference_sequence
10u32timestamp_ms
14u16latency_ms
16 / 18u16 / u16图像宽度 / 高度
20u8flags:bit0 上报启用、bit1 检测器就绪、bit2 结果有效
21u8人脸数,最多 4
22 起每张 10 字节置信度千分值、x1、y1、x2、y2,均为 u16

因此合法 STATUS 的 payload 长度必须为 22 + face_count * 10。包头请求序号、负载中的最近请求序号和推理序号是三个不同字段,不能因为它们都叫 sequence 就合并使用。

3. 先提取不依赖 Flutter 的纯 Rust 解析器

将下面代码放入新增的 rust/src/protocol.rs。它保留现有 Dart 对包头、负载长度和人脸记录的主要检查,同时完整返回协议版本和最近请求序号,便于后续比对。

#[derive(Clone, Debug, PartialEq)]
pub struct FaceBox {
    pub score: f64,
    pub x1: u16,
    pub y1: u16,
    pub x2: u16,
    pub y2: u16,
}

#[derive(Clone, Debug, PartialEq)]
pub struct DetectionStatus {
    pub request_sequence: u32,
    pub protocol_version: u16,
    pub last_request_sequence: u32,
    pub inference_sequence: u32,
    pub timestamp_ms: u32,
    pub latency_ms: u16,
    pub image_width: u16,
    pub image_height: u16,
    pub flags: u8,
    pub faces: Vec<FaceBox>,
}

pub fn parse_status(packet: &[u8]) -> Result<DetectionStatus, String> {
    if packet.len() < 10 {
        return Err("XH_PACKET_TOO_SHORT".into());
    }
    if packet[..2] != [0x58, 0x48] || packet[2] != 1 {
        return Err("XH_BAD_MAGIC_OR_VERSION".into());
    }
    if packet[3] != 0x81 {
        return Err("XH_NOT_STATUS".into());
    }
    let payload_len = u16::from_le_bytes([packet[8], packet[9]]) as usize;
    if payload_len != packet.len() - 10 {
        return Err("XH_LENGTH_MISMATCH".into());
    }
    let p = &packet[10..];
    if p.len() < 22 {
        return Err("XH_STATUS_TOO_SHORT".into());
    }
    let count = usize::from(p[21]);
    if count > 4 || p.len() != 22 + count * 10 {
        return Err("XH_FACE_RECORD_MISMATCH".into());
    }
    let u16le = |i| u16::from_le_bytes([p[i], p[i + 1]]);
    let u32le = |i| u32::from_le_bytes([p[i], p[i + 1], p[i + 2], p[i + 3]]);
    let faces = (0..count)
        .map(|index| {
            let i = 22 + index * 10;
            FaceBox {
                score: f64::from(u16le(i)) / 1000.0,
                x1: u16le(i + 2),
                y1: u16le(i + 4),
                x2: u16le(i + 6),
                y2: u16le(i + 8),
            }
        })
        .collect();
    Ok(DetectionStatus {
        request_sequence: u32::from_le_bytes([packet[4], packet[5], packet[6], packet[7]]),
        protocol_version: u16le(0),
        last_request_sequence: u32le(2),
        inference_sequence: u32le(6),
        timestamp_ms: u32le(10),
        latency_ms: u16le(14),
        image_width: u16le(16),
        image_height: u16le(18),
        flags: p[20],
        faces,
    })
}

解析器先检查固定长度,再读取字段;确认人脸数和记录长度后才遍历数组,避免对截断包越界读取。错误返回明确原因,而不是将错误包解释为“没有人脸”。

这里读取并返回 payload 中的 protocol_version,没有新增严格版本拒绝策略;现有 Dart STATUS 解析也未执行这项检查。保留两边行为有助于第一次迁移比对。后续若按协议增加负载版本、坐标范围或置信度范围校验,应独立说明规则变化并补充测试。

解析成功也不等于所有业务条件成立。请求序号是否属于当前会话、数据是否过期,应由请求与会话管理层判断,不能靠这个无状态函数推断。

4. 添加 FRB 包装与生成配置

新增 rust/Cargo.toml

[package]
name = "xiaohong_se_protocol"
version = "0.1.0"
edition = "2024"

[lib]
crate-type = ["cdylib", "staticlib"]

[dependencies]
flutter_rust_bridge = "=2.13.0-beta.6"

rust/src/api.rs 中包装解析器,并把初始化函数放在生成器扫描的 API 模块中:

pub use crate::protocol::{DetectionStatus, FaceBox};

#[flutter_rust_bridge::frb(init)]
pub fn init_app() {
    flutter_rust_bridge::setup_default_user_utils();
}

#[flutter_rust_bridge::frb(sync)]
pub fn parse_status_packet(packet: Vec<u8>) -> Result<DetectionStatus, String> {
    crate::protocol::parse_status(&packet)
}

rust/src/lib.rs 导出模块:

pub mod api;
pub mod protocol;
mod frb_generated;

应用根目录中的 flutter_rust_bridge.yaml

rust_input: crate::api
rust_root: rust/
dart_output: lib/src/rust

在现有 pubspec.yaml 的 dependencies 中加入 flutter_rust_bridge: 2.13.0-beta.6。原生插件接入完成后,还需加入对应的本地插件依赖;不能先写一个不存在的 rust_builder 路径并认为集成已经完成。

frb(sync) 明确让 Dart 同步取得解析结果,与下一节的同步 _handlePacket 分派保持一致。若使用默认异步接口,则 Dart 必须 await,并另外处理迟到结果、断线和新旧会话顺序;不能把返回的 Future 当作状态对象直接读取。

5. Dart 只替换 STATUS 分支

生成绑定并完成原生库接入后,在 Gateway 中引入接口:

import 'package:flutter/foundation.dart';
import 'package:xiaohong_se_manager/src/rust/api.dart' as rust;

保留 _handlePacket 的包头与总长度检查,把原 STATUS 分支调用替换为 _handleStatusWithRust(packet)。这里传入完整包,因为 Rust 解析器还要读取包头:

void _handleStatusWithRust(Uint8List packet) {
  try {
    final status = rust.parseStatusPacket(packet: packet);
    _results.add(
      FaceDetectionResult(
        deviceId: _nearLinkDeviceId,
        timestampMs: BigInt.from(status.timestampMs),
        sequence: status.inferenceSequence,
        faceCount: status.faces.length,
        latencyMs: status.latencyMs,
        imageWidth: status.imageWidth,
        imageHeight: status.imageHeight,
        faces: status.faces.map((face) => FaceBox(
          score: face.score,
          x1: face.x1,
          y1: face.y1,
          x2: face.x2,
          y2: face.y2,
        )).toList(),
        modelVersion: (status.flags & 0x06) == 0x06
            ? 'ESPDet-Pico 416'
            : 'ESPDet-Pico 416(等待 P4 相机帧)',
      ),
    );
  } catch (error) {
    debugPrint('STATUS 协议解析失败:$error');
  }
}

这段是放入现有 Gateway 类的接入示例,沿用其 Uint8ListFaceDetectionResultFaceBox 和结果流。解析失败时不发布新的有效结果;页面对旧结果的保留时间和过期提示仍需另行设计。

正式切换前建议先进行双解析比对:同一包同时交给 Dart 和 Rust,按字段比较人数、坐标、宽高、flags、推理序号及时间戳。现有 Dart 未暴露的版本和最近请求序号,应通过协议样本核对。新解析器失败或结果不一致时记录差异,影子阶段继续使用原 Dart 结果。

初始化策略也要区分阶段:影子验证时可以捕获 FRB 初始化失败、禁用扩展并继续原链路;正式以 Rust 为主路径后,初始化失败应明确展示错误,不能把没有运行解析器的页面当作集成成功。

6. 扩展后的链路和保留的 JPEG 检查

STATUS 完整包

DetectionStatus

BEGIN / CHUNK / END

ArkTS 原始包

Dart Gateway

FRB 同步绑定

Rust XH v1 解析器

Flutter Dashboard

现有 Dart JPEG 重组

图像链路各处的限制不同:P4 UART 分片最大 1024 字节,WS63 完整 JPEG 缓存上限 40 KiB,SSAP JPEG 数据块最大 220 字节,App 完整帧缓冲上限 64 KiB。整条链路的完整 JPEG 上限受 WS63 限制,为 40 KiB。

现有 Dart 校验请求序号、图像序号、offset 连续性、分片长度、总长度与 JPEG FFD8/FFD9 首尾标记。当前 XH v1 SSAP 图像协议没有定义图像 CRC 字段,现有 Dart 重组代码也未计算整图 CRC,不能把其他项目的 CRC 校验能力写成本项目已实现功能。

五、运行方式、效果图与验证结果

1. 先运行现有 HarmonyOS 应用

apps/xiaohong_se_manager/ 中执行:

flutter pub get
flutter devices
flutter run -d <HARMONY_DEVICE_ID>

将设备标识替换为实际 HarmonyOS PC。构建签名包可使用 DevEco Studio 打开该应用的 ohos/,在 Project Structure 中配置本机签名,再执行 Build Hap。仓库记录的典型输出位置为:

apps/xiaohong_se_manager/ohos/entry/build/default/outputs/default/
  entry-default-signed.hap

回到仓库根目录,安装并启动:

hdc list targets
hdc -t <HARMONY_DEVICE_ID> install -r \
  apps/xiaohong_se_manager/ohos/entry/build/default/outputs/default/entry-default-signed.hap
hdc -t <HARMONY_DEVICE_ID> shell aa start \
  -a EntryAbility \
  -b com.xiaohongse.xiaohong_se_manager

运行前确认 P4 与 WS63 都已烧录匹配固件并启动。App 首次连接需允许星闪权限,扫描目标广播 xiaohong_se_lock,确认配对后发现服务 0x2222、属性 0x2323 并订阅通知。点击开始检测,观察 JPEG 帧序号、人脸数和推理耗时是否持续更新。

两颗芯片的构建与烧录按项目 README、firmware/esp32-p4/README.mdfirmware/ws63/README.md 执行。TTL Type-C 用于烧录和日志,App 的运行数据通过无线星闪传输。

2. 原有真机效果图

小鸿 SE 现场摄像头预览与 ESP-DL 人脸检测效果之一

小鸿 SE 现场摄像头预览与 ESP-DL 人脸检测效果之二

两张照片沿用原有现场资料,展示相机、LCD 和人脸检测框的实际运行。它们证明的是现有系统中的视觉功能,不证明人物身份、开锁授权或真实锁舌动作,也不证明新增 FRB 库已经装载。

当前项目只做人脸检测,访客记录最多保留当前 App 会话的 50 条,重启后不恢复。这一能力不能等同于身份识别或长期访客审计。

3. 本文解析器已执行的主机测试

本文配套提供 protocol.rsprotocol_tests.rs。解析器不依赖 FRB,可直接用 Rust 工具链测试:

rustc --edition 2024 --test protocol_tests.rs -o protocol-tests
./protocol-tests

本次使用 rustc 1.93.0 实际执行,结果为 10 passed,0 failed。测试使用人工构造的协议数据,不使用真实访客图像,覆盖:

测试检查点
完整单人脸包所有状态字段、小端序、置信度 0.923 与坐标
零人脸和四人脸合法数量边界
逐字节截断合法包每个截断位置都返回错误
错误 Magic 与包头版本拒绝不匹配包头
非 STATUS 类型不把图像分片当状态包
包头声明长度错误拒绝长度不一致
固定负载不足包头长度匹配时仍拒绝不足 22 字节的状态
五张人脸拒绝超过当前协议限制
人脸记录缺字节或多字节记录长度必须精确匹配
payload 版本字段完整返回字段,未偷偷引入新的拒绝策略

这组测试验证纯 Rust 解析逻辑,没有执行 FRB codegen、Flutter 绑定调用或鸿蒙 HAP 装载验证。

4. FRB 扩展真正接入 HAP 的步骤

完成第四节新增文件后,按以下顺序继续集成:

  1. 配置 Dart FRB 依赖,在应用目录执行 flutter pub getflutter_rust_bridge_codegen generate,确认两端生成文件更新。
  2. 按指定 FRB 仓库的鸿蒙接入说明配置原生构建插件及 OHOS target,构建 xiaohong_se_protocol 并将目标架构动态库打包到 HAP。
  3. 加入实际存在的本地插件依赖,在 main.dart 中、runApp 前初始化 RustLib。库名和加载方式要与插件构建产物一致。
  4. 启动目标 HAP,实际调用一条合法 STATUS 和一条错误包,确认结构映射和错误传播。
  5. 用同一批真实 STATUS 样本进行 Dart/Rust 比对,覆盖重连、重复包、截断包和异常字段。
  6. 结果一致后切换 STATUS 主路径,重新检查实时状态、JPEG 接收及断开清理。

应用初始化形态可参考:

import 'package:flutter/material.dart';
import 'package:xiaohong_se_manager/app.dart';
import 'package:xiaohong_se_manager/src/rust/frb_generated.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await RustLib.init();
  runApp(const XiaohongSeApp());
}

这段假设生成配置和构建插件已经提供正确的库加载配置;若使用显式加载,应按最终动态库名配置 externalLibrary。不能仅凭这几行入口代码宣称 OHOS 原生集成完成。

绑定生成成功后,在对应位置执行检查:

# 在 apps/xiaohong_se_manager 中执行。
cargo test --manifest-path rust/Cargo.toml
dart analyze lib test integration_test

# 连接并准备好真机后执行硬件集成测试。
flutter test integration_test/simple_test.dart -d <HARMONY_DEVICE_ID>

这些 FRB 命令只适用于新增文件和依赖后的扩展工作区;原仓库没有 rust/Cargo.toml 和生成配置,不能直接执行。

5. 验收状态按实际证据区分

检查项当前依据状态或限制
P4 相机、LCD、人脸检测原有现场实拍已有演示资料
P4 → WS63 → HarmonyOS 状态与 JPEG仓库现有运行记录正式链路仍由 Dart Gateway 解析
本文 Rust STATUS 解析器10 项主机单测本次测试通过
FRB 绑定与 Dart 结构映射本文接入方案待实际生成并验证
FRB 扩展真机 HAP需完成插件、原生构建和安装待集成验证
人脸身份识别与活体检测当前仅检测框不属于现有完成能力
真实锁舌执行与量产安全能力当前原型范围尚不能据此宣称完成

六、FAQ:问题反馈、修复和 PR

1. 遇到框架问题,如何提 Issue?

先判断故障是否来自 FRB。现有正式仓库没有 FRB,当前星闪连接、P4 画面和 Dart JPEG 问题应优先到门锁项目仓库Issues 反馈。扩展后若最小示例仍能复现绑定生成、类型映射或原生调用异常,则进入 FRB 项目仓库Issues

提交前搜索相同报错和版本,按模板填写;最少应包含:

标题:[OHOS][版本] 操作与实际错误

环境:
- 主机系统、CPU 架构:
- Flutter-OH / Dart / Rust / Cargo:
- FRB Dart、Rust 依赖和 codegen 版本(仅扩展路径):
- DevEco / SDK / 目标 HarmonyOS 设备:
- 项目 commit、P4 与 WS63 固件版本:

复现步骤:
预期结果:
实际结果:
完整错误日志或堆栈:
最小复现仓库、补丁或人工构造的协议样本:
已尝试的排查步骤及结果:

FRB 问题尽量缩小为一个 Rust 函数和一次 Dart 调用。协议问题给出消息类型、长度、相关序号和字段差异;先使用人工构造包复现,避免提交真实人脸 JPEG、设备地址、证书或口令。

2. 问题解决后,如何提 PR?

如果修复来自新增代码、测试或文档,完成本地验证后再提交 Pull Request。通常无需先关闭 Issue,可由 PR 关联问题,待合并和验证后再更新状态。

  1. 确认修改属于门锁项目还是 FRB 框架,阅读对应贡献说明并确认目标分支。
  2. Fork AtomGit 仓库,从目标分支创建独立修复分支,例如 fix/status-payload-length
  3. 修改导致问题的源代码,增加能复现缺陷的回归测试。涉及 FRB API 时同步重新生成 Dart 与 Rust 绑定。
  4. 执行适用的 Rust、Dart 和目标平台检查。只通过主机解析器测试时,就明确写主机范围,不写“真机通过”。
  5. 推送到个人 Fork,在原仓库的 Pull Requests 页面选择源分支和目标分支,关联实际 Issue。
  6. 描述触发条件、根因、修复后的行为、验证命令和结果,根据评审意见继续修改。
  7. 合并后记录修复提交或版本,在受影响应用中更新并复测原场景,最后更新 Issue。

门锁协议发生变化时,按仓库约定同步协议文档、Dart Gateway、WS63 SSAP/UART 实现及 P4 协议实现。若只是把现有解析迁移到 Rust,应证明线上协议未改变,同时说明解析器有无新增校验规则。

PR 描述可以使用:

问题:哪种包或操作会触发错误。
原因:哪项字段解释或状态处理不正确。
修改:修复后有什么可观察的变化。
验证:测试命令、样本范围和实际平台结果。
关联:Issue #<实际编号或链接>。

若问题只是 SDK 配置错误,修复环境并反馈即可;若维护者已合并修复,更新版本后验证即可,不必再提交相同补丁。

3. 其他常见问题与解决方案

现象主要检查方向解决方式
原仓库执行 FRB 命令找不到配置是否已新增扩展文件正式仓库没有 FRB,先按扩展步骤准备 crate、依赖和配置
Dart 把返回值当 Future 或对象时出错API 同步/异步声明本文使用 frb(sync);若改为异步需 await 并处理结果顺序
RustLib.init() 失败动态库名、架构及 HAP 打包检查实际原生插件和加载配置,绑定生成成功不代表库已打包
Rust 与 Dart 字段不同包头/payload 偏移、字节序对照协议表检查三种 sequence 和 22 字节固定部分
单测只有错误包通过正常字段映射未验证加入合法单人脸、零人脸和四人脸样本,逐字段断言
App 发现 XH-KBWS63 是否为键盘示例固件按本项目固件说明核对并更新正确门锁固件
配对后报 1009700099-5连接有效性及板端 CCCD 日志对照仓库的定向兼容逻辑;其他错误或实际断线不能直接忽略
已连接但没有画面P4 摄像头、推理、UART JPEG检查 0x0C05 分片、图像大小和连续性,不只检查星闪
JPEG 大于 40 KiBWS63 缓存上限调整分辨率或 JPEG 质量;App 64 KiB 缓冲不提升整条链路上限
Hvigor 报 SDK 组件缺失SDK、Node 和 Hvigor 是否同套优先使用同一 DevEco Studio 发行版的工具与 SDK
HAP 安装失败signed/unsigned、证书与设备配置匹配设备的签名,安装正确签名产物
访客记录重启后消失当前会话存储设计当前最多 50 条内存记录,持久化需另行实现

七、后续方向与项目入口

当前项目已经提供摄像头、人脸检测、双芯片 UART、星闪 SSAP 与 HarmonyOS 展示链路。本文的 FRB 扩展从 STATUS 开始,将字节解析组织成可单测模块,再通过类型化 API 接入 Dart;下一步是完成目标 HAP 的真实加载与逐包比对。

从“检测到人脸”走向门锁产品,还需要身份识别、活体检测、授权判断和执行器反馈等独立能力。FRB 可以帮助整理软件边界,不能替代这些功能,也不能把检测框直接解释为开锁权限。

进一步阅读和参与项目:

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐