Files

9.8 KiB
Raw Permalink Blame History

BLE 协议规范(4.2寸墨水屏设备 · 实现标准)

状态:单一事实来源。实现 src/ppclock 以本文件为准。 证据来源:analysis/web/protocol-raw.md(Web JS)+ analysis/apk/apk-analysis.md(APK 反编译互证)。 互证结论:GATT UUID、NRF- 前缀、240B 分块、ff/00 平面码、dd 时间帧、e2 收尾、e100/e101/e102 模式族、倒计时 04/0n/990/ff00/ffff 帧、6 种抖动(Bayer 矩阵逐值一致)、红色判定、灰度系数 —— 三线一致。 Web 独有(APK 未实现):WiFi 配置、EFEF 取设备 ID、2300/2301、14/15、e3/e4/e5、E6、FB、e901/EA000、EA0x —— 本规范以 Web 证据为准。 APK 独有:$IMG(0,0)、8000/8001 图像起始帧(属扫地/轻舞固件家族分叉,本设备不适用)。

1. 设备与 GATT

项 值
广播名前缀 NRF-
EPD Service 13187b10-eba9-a3ba-044e-83d3217d9a38
EPD Characteristic(图像+刷屏,write+notify) 4b646063-6264-f3a7-8941-e65356ea82fe(h=48)
RXTX Service 00001f10-0000-1000-8000-00805f9b34fb
RXTX 命令通道(实机) 0000331f-0000-1000-8000-00805f9b34fb(h=57,notify+write+read,svc 0x221f)
00001f1f-...(h=53,仅 write) ⚠ 实机证据:写入仅 ATT-ACK 不执行命令(2026-07-28);Web/App 文档中的"RXTX 特征",本设备弃用
SUOTA Service 0000fef5-...(h=28-45,含自定义特征,见 §9)

实机 GATT 全表(2026-07-28 bridge 诊断,设备 NRF-5DBF28): GAP/GATT/DIS(2A24/2A26/2A28/2A23/2A50)/BAS(2A19 notify) + fef5 SUOTA 六特征 + EPD + 1f1f(write-only) + 331f(notify+write+read)。 notify 订阅:设备 ID 应答案测经 331f 到达(EFEF 同样须写 331f);EPD/2A19 亦可订阅。

连接顺序:先 EPD service → 再 RXTX;写均用 write-with-response(triggerRxTxCmd2 例外,without-response)。

2. 屏幕参数

参数 值
分辨率 400 × 300
色彩 黑/白/红 三色(亦可切黑白模式)
像素打包 1bpp,MSB first,行主序(y:0→300, x:0→400)
平面 bw 平面 15000B + 红平面 15000B(红仅三色模式)
bw 位值 R,G,B 任一>0 → 1(白),全 0 → 0(黑)⚠即"非黑即白"
红平面位值 R>0,G=0,B=0 → 1(红)
日历小图 280×100(3500B)或 400×180(9000B),同 1bpp

3. 帧格式

3.1 图像数据块(EPD 通道)

[cod:1B][code:1B][offset:2B BE][payload:≤240B]
字段 值
cod 03=整图;04=日历小图(数据总长 3500B 或 9000B 时)
code ff=bw 平面;00=红平面
offset 本块在平面内的字节偏移,大端
payload ≤240 字节;按 offset 顺序连发,块间无应用层 ACK

结束:全部块发完延时 ≥300ms → 整图发 01;日历小图发 AA。

3.2 刷屏(EPD 通道)

00{param} 后接 01。

3.3 时间设置(RXTX 通道)

dd [unix:4B BE][year:2B BE][month:1B][day:1B][week:1B]   → 随后发 e2
  • unix = 本地时区修正秒(now_utc + tz);week:周一=1 … 周日=7。
  • 测试向量:2026-07-24 15:30:00 (UTC+8) 周五 → dd 6982a7f0 07ea 07 18 05(unix=1785475800=0x6982A7D8 ⚠按实现时实际值校验,此处仅示意格式)→ 待真机/互证校准。

3.4 倒计时(RXTX 通道)

  • 日期:ff00{YYYY}{MM}{DD}(时钟界面)/ ffff{YYYY}{MM}{DD}(日历界面);YYYY=4 位十进制 ASCII。
  • 前缀文字位图(时钟界面,16px 字格):≤4 字符(中文=1,英文=0.5)单包 0{charCount}{位图hex};>4 拆两包:04{前128B} 然后 0{charCount}{剩余}。
  • 前缀文字位图(日历界面,24px 字格):每字符一包 990{索引}{72B},包间隔 1s。
  • 位图打包:1bpp MSB first 行主序。
  • 收尾 E2;关闭倒计时 FA → 1s → E2。
  • 日历中文字设置:990* → FA → e10103 → E2。

3.5 激活与设备 ID(RXTX 通道)

  1. 请求 ID:发 EFEF → notify 收 14 字节(可打印即 ASCII,否则 hex 表示)。
  2. 激活码:原流程 GET http://4638e813e4.qicp.vip:8889/key_generator.php?id={用户ID}&key={设备ID} → 返回 ≥32 hex(正则 激活码1:([0-9A-F]{32,}))。⚠算法在服务端,本地化方案见 §7。
  3. 下发:EF{激活码hex大写} → 400ms → e2。

3.6 WiFi 配置(RXTX 通道)

ASCII UTF-8 直发:WIFI_SSID:{ssid};WIFI_PASS:{pass};CITY:{城市代码}(城市代码为天气代码,如 101010100)。

4. 命令 opcode 总表(RXTX 通道,除注明外)

命令 含义
e2 提交/刷新(多数命令收尾)
dd… 设置时间(§3.3)
2300 / 2301 三色模式 / 黑白模式
14 12/24 小时制切换
15 时钟颜色切换
e3 反色模式
e4 时钟字体切换
e5 旋转 180°
e10000–e10003 图片模式:显示图一~图四
e10103 / e10104 / e10105 日历模式一/二/三
e10201 / e10202 / e10203 时钟模式一/二/三
E6{01-0f} / E6{10-f0} 红 / 黑 LUT 校准(越大越深;0 无效)
FB01{HH}{MM} / FB00{HH}{MM} 开启 / 关闭休眠时段
e901{n}{01|00} 轮播间隔 n(01=分钟,00=小时)
EA0{0-3} 上传目标槽位(图一~图四)
EA000{0-3} 轮播数量 1–4(值=n-1)
EF{hex} 激活码下发
EF{数字逐位双写} 停车牌号码("12"→EF1122)
EFEF 请求设备 ID
FA 关闭倒计时
ff00… / ffff… / 990… / 04… / 0… 倒计时(§3.4)
00{xx}+01(EPD) 刷屏
01(EPD) 整图传输结束刷新
AA(EPD) 小图传输结束

模式切换命令(e1xx/23xx/14/15/e3-e5)发后 300ms 补 e2(setri 模式)。

5. 抖动算法参数(图像管线)

算法 参数
none 阈值化,threshold 默认 125
floydsteinberg 误差核 7/16,3/16,5/16,1/16
atkinson 6 邻域 ×1/8
bayer 4×4 矩阵 15,135,45,165],[195,75,225,105],[60,180,30,150],[240,120,210,90
stucki /42 核
jarvis /48 核
bwr_* 同上 6 种三色版;红色判定 r>g*1.5 && r>b*1.5 && r>threshold

预处理:亮度 ±255·v/100;对比度 (c+100)/100(128 中点);饱和度=灰度插值(0.299/0.587/0.114);diffusion 0–100/100 误差缩放。

6. 标准会话流程

  1. 扫描(namePrefix NRF-)→ 连接 → 读取 DIS 固件版本 → 按固件选择 RXTX 特征。PP_da14585_4.2 使用 331F(notify/write/read);HM42_AIO_* 使用 1F1F(write-only,不订阅 notify)。首选特征不存在时才回退到另一特征。
  2. (可选)EFEF 取设备 ID。
  3. 对时:dd… + e2。
  4. 操作:模式切换(+e2)/ 传图 / 倒计时 / WiFi。
  5. 断线自动重连 ≤5 次。

6.1 图像协议的固件差异

固件家族 RXTX 400×300 单色平面 EPD 图像会话
PP_da14585_4.2 / 未知 331F 黑白平面 旧序列:数据块 → 01(小图 AA)
HM42_AIO_* 1F1F 黑白 15,000B + 全零红色 15,000B 8001 → 0000 → 020000 → 双平面数据 → 0101 → RXTX e2

HM42 的双平面和会话帧均为必需条件:缺红色平面会出现红屏噪点,缺会话帧会出现黑白噪点。400×300 双平面在 Windows BLE 实机约需 8 分钟;调用方不得依赖跨网络的单个长 HTTP 连接,应在 BLE 主机本地执行并持久化结果后再轮询。

7. 本地化(去云)清单 —— 已全部解决

云依赖 本地化方案 状态
key_generator.php 激活码 本地 keygen:code[i]=ror2(((MAC[i]<<1)&0xFF)^0xEF)%101(firmware-analysis §4.2);ppclock activate --auto 经 EFEF 反解 MAC 自动完成;且固件侧 EF 不门禁任何命令 ✅ 已实现
file_down.php 固件下载 固件本地存档 app/;ppclock ota 本地升级(SUOTA 经 0x221F 服务,firmware-analysis §5) ✅ 已实现
qbsg.top 自助激活 同 keygen ✅
天气(CITY 代码) 原厂云功能,本地化范围外;wifi 命令仅透传。注意:本固件 WIFI 命令为 no-op(firmware-analysis §3.3) ⚠ 固件未实现
qrcodejs CDN(模板用) CLI 本地 qrcode 库 ✅

固件侧 no-op 命令(Web 端发送但本固件版本忽略,CLI 保留前向兼容):E9xx 轮播间隔、EA0x 槽位/EA000x 轮播数量、WIFI 配置(firmware-analysis §3.3 分发器跳表)。

9. SUOTA 固件升级(证据:APK §e)

项 值
Service 0000fef5-0000-1000-8000-00805f9b34fb
SERV_STATUS(notify) 64b4e8b5-0de5-401b-a21d-acc8db3b913a
MEM_DEV 8082caa8-41a6-4021-91c6-56f9b954cc34
GPIO_MAP 724249f0-5ec3-4b5f-8804-42345af08651
PATCH_DATA(自定义映射) 457871e8-d516-4ca1-9116-57d0b17b9cb2
PATCH_LEN(自定义映射) 9d84b9a3-000c-49d8-9183-855b673fda31

流程:MEM_DEV←{00,00,00,13}(SPI Flash)→ GPIO_MAP←{00,00,06,05} → 镜像+尾 1B XOR 校验 → 240B 块(PATCH_LEN 2B LE + 20B 无响应写块 + 等 SERV_STATUS==2)→ MEM_DEV←{00,00,00,FE} → 等 ==2 → {00,00,00,FD} 重启。 状态码:2=成功,3-9/17-22/0xFFFF/0xFFFE=各类错误(见 ota.py STATUS_ERRORS)。

8. 测试向量(实现前必须写入 tests/)

来源:analysis/web/protocol-raw.md 各节;标 ⚠ 的待 APK/固件互证确认。

  1. setTime 布局(§3.3)⚠
  2. 图像块帧头:400×300 bw 平面首块 → 03 ff 0000 + 240B ⚠
  3. 小图判定:3500B → cod=04;15000B → cod=03
  4. 停车牌 "12" → EF1122
  5. 轮播 5 分钟 → e9010501
  6. 槽位 3 上传前置 → EA02;轮播数量 4 → EA0003
  7. 停车牌/激活/取 ID 的 EF 前缀区分:EFEF=取ID、双写数字=车牌、≥32hex=激活