收到七个字节,怎样显示成 4000 毫伏
从主线已经见过的电量帧开始,在电脑上完成解析,再让解析结果更新页面。先把字节到含义这一步独立跑通。
1 · 先拿一条知道答案的消息
十六进制消息 · 电压 4000 mV,百分比 60
AA 06 03 A0 0F 3C 62AA 是帧头,06 表示电量消息,03 表示载荷有三个字节;A0 0F 按小端组成 0x0FA0,也就是 4000;3C 是百分比 60。前六字节之和为 0x19E,取负数再保留低八位得到 62;连同校验相加,低八位为零。主线已经解释帧边界和校验,本节用 Dart 表达相同规则。
Uint8List 表示每项为一个字节的连续数据,适合设备收发;普通 List
2 · 先检查长度和校验,再读字段
完整单帧电压解析函数 · 无效时返回 null
int? batteryMillivolts(Uint8List frame) {
if (frame.length != 7 || frame[0] != 0xAA ||
frame[1] != 0x06 || frame[2] != 3) return null;
var sum = 0;
for (var i = 0; i < frame.length - 1; i++) {
sum = (sum + frame[i]) & 0xFF;
}
if (((-sum) & 0xFF) != frame.last) return null;
return ByteData.sublistView(frame, 3, 5)
.getUint16(0, Endian.little);
}sublistView 让这两个载荷字节形成视图,getUint16 按小端读取无符号整数。先确认范围,才不会越界。视图可能共享原缓冲,长期保存数据前要考虑上游是否复用数组。完整下载示例还会翻转一个字节,确认坏校验被拒绝。
3 · 为什么一次通知不一定是一整条消息
蓝牙通知给出的是这一批收到的字节。协议帧可能拆成前后三批,也可能一批里有两条帧。前面的函数只接受已经完整的一帧,不能直接当成所有通知的处理器。
仓库 SmartWatchBLE 的接收缓冲先寻找帧头、等待载荷长度足够、核对校验,再调用 ble_protocol.dart 中的字段解析函数。读代码时先画出这个顺序,不先把所有消息类型复制到练习程序。
4 · 让模拟帧也经过真实解析路径
把此前的模拟整数换成已知字节帧。每收到一帧,先解析成功才更新 millivolts。再分别注入错误校验、缺字节和断连事件。无效帧不应被转换成看起来正常的新测量;是否清除旧值则按页面的数据有效期约定执行。
心率、睡眠、血氧具有不同字段和有效性规则。当前 App 的实时血氧在 invalid、断连或超过五秒没有有效更新时清除;历史睡眠最低血氧不能拿来填补实时血氧。遇到这些业务数据时再解释,不能用一个“有数字即正常”的通用判断。
5 · 对照项目,保持一种协议含义
协议常量、字段和字节序对应 ble_protocol.dart;数据流装帧与消息分发对应 ble_service.dart。固定示例使用的 4000 毫伏消息也可以与主线 C 打包示例互相核对。
运行下载示例,确认输出 4000 与 null。再把一条合法帧从每个可能位置拆开,沿装帧过程追踪什么时候才允许读字段;不要把缺失的尾字节补零。
资料与代码
配套文件
先复制到独立练习目录;用法见 支线示例说明。完整 Flutter 小应用见 tutorial/examples/flutter_watch/README.md。