first commit

This commit is contained in:
2026-02-10 17:11:06 +08:00
commit 12f4fb81b8
32 changed files with 2958 additions and 0 deletions

View File

@@ -0,0 +1,459 @@
# lyfPrinter 上位机 APP 迁移到 ESP32(ESP-IDF) 实施文档
本文档基于当前 Android 上位机 APP 实现(`MainActivity + ECBLE + BlueHandler + 各预览页`),给出一套可落地的 ESP32/ESP-IDF 迁移方案。
适用目标:
- 让 ESP32 作为 BLE Central 连接 `lyfPrinter` 热敏打印机
- 复用现有私有打印协议(`0x00~0x07``0xA0~0xA4`
- 在 ESP32 上实现打印、状态监控、标签纸定位、OTA打印机固件能力
---
## 1. 现有 APP 能力基线(迁移输入)
Android 端关键行为:
1. 扫描过滤设备名 `lyfPrinter`
2. 连接 BLE 外设并绑定特征:
- Notify: `0000fff1-0000-1000-8000-00805f9b34fb`
- Write: `0000fff2-0000-1000-8000-00805f9b34fb`
3. 请求 `MTU=247`
4. 向写特征发送私有协议帧,接收 Notify 回包并解析状态
5. 打印流程:
- 输入内容转 384 点宽位图
- 二值化
- 行取模8 像素打包 1 字节)
- 按 240 字节数据体分包(整帧 244 字节)
- 按应答节奏发送完毕
6. 打印前后控制:
- 开启/关闭 VH 电源
- 设置热参数(浓度映射)
- 结束后走纸留白
可参考:
- `APP_BLE打印控制实现说明.md`
- `BLE_PAIRING_PARAMETERS.md`
---
## 2. 迁移目标定义
建议按两级目标推进:
### 2.1 M1必做先跑通
1. 扫描/连接/重连
2. 状态查询与解析(纸张、电量、温度)
3. 基础打印(接收已编码点阵数据后发送)
4. 标签纸 gap 定位与偏移读写
### 2.2 M2增强
1. ESP32 端文本渲染与位图编码
2. 图片/二维码本地生成与打印
3. 打印机 OTA 完整流程
4. UI 层按键、串口命令、Web、LCD+LVGL 任一)
---
## 3. ESP-IDF 技术选型建议
推荐:
- ESP-IDF `v5.1+``v5.2+`
- BLE Host`NimBLE`内存占用更低Central 场景稳定)
备选:
- Bluedroid 也可实现,但本项目建议优先 NimBLE。
编译配置建议(`menuconfig`
1. 启用 BLENimBLE
2. 增大 GATT MTU 到 `247`
3. 提升 BT controller/host 内存预算
4. 打开 NVS存储设备地址、标签偏移、最近配置
---
## 4. Android 到 ESP32 模块映射
| Android 类 | 迁移后模块 | 说明 |
|---|---|---|
| `MainActivity` | `printer_ble_scan.c` + `app_cli.c` | 扫描、设备选择、连接触发 |
| `ECBLE` | `printer_ble_client.c` | GATT 连接、服务发现、通知订阅、写特征 |
| `BlueHandler` | `printer_proto.c` + `printer_engine.c` | 协议封装/解析、状态机、分包与流控 |
| `DataConvertTool` | `image_raster.c` | 二值化、384宽缩放、行取模 |
| 各 PreviewActivity | `content_renderer_*.c` | 文本/二维码/模板渲染 |
| `otaUpdateActivity` | `printer_ota.c` | `A0~A4` 升级流程 |
建议目录:
```text
components/
printer_ble/
include/printer_ble_client.h
printer_ble_client.c
printer_proto/
include/printer_proto.h
printer_proto.c
printer_engine/
include/printer_engine.h
printer_engine.c
image_raster/
include/image_raster.h
image_raster.c
printer_ota/
include/printer_ota.h
printer_ota.c
main/
app_main.c
app_cli.c
app_config.c
```
---
## 5. BLE 迁移要点(与 Android 行为对齐)
### 5.1 扫描与过滤
逻辑对齐 Android
- 仅处理设备名 `lyfPrinter`
- 保存 MAC、RSSI、最后发现时间
- 支持“按 MAC 直连”模式(量产更稳)
### 5.2 建链流程
1. `scan -> connect`
2. `discover service/characteristics`
3. 找到 `FFF1/FFF2`
4.`FFF1` 写 CCCD `0x0001` 开启 Notify
5. 交换 MTU目标 247
### 5.3 写入策略
与 Android 保持一致:
- Write Without Response
- 发送内容使用十六进制帧字节序列
### 5.4 断线策略
建议状态机:
- `DISCONNECTED`
- `SCANNING`
- `CONNECTING`
- `DISCOVERING`
- `READY`
- `PRINTING`
断线后:
- 延时 300ms 重连
- 最多重试 4 次(与 Android 一致)
- 失败后回 `SCANNING`
---
## 6. 私有协议迁移(核心)
### 6.1 指令定义
```c
// 打印
#define CMD_POWER 0x00
#define CMD_GET_STATUS 0x01
#define CMD_SET_DISTANCE 0x02
#define CMD_SET_PARAM 0x03
#define CMD_SEND_DATA 0x04
#define CMD_GAP_MOVE 0x05
#define CMD_GET_LABEL_OFFSET 0x06
#define CMD_SET_LABEL_OFFSET 0x07
// OTA
#define CMD_BOOT_JUMP_BOOT 0xA0
#define CMD_BOOT_ERASE_PAGE 0xA1
#define CMD_BOOT_WRITE_DATA 0xA2
#define CMD_BOOT_JUMP_APP 0xA3
#define CMD_BOOT_GET_VERSION 0xA4
```
### 6.2 帧结构
常规帧:
```text
[addr:1][func:1][lenH:1][lenL:1][payload:len][checksum:optional]
```
校验和规则:
-`addr` 到 payload 最后一个字节累加,取低 8 位
与 Android 对齐点:
- 控制类命令一般带校验
- `CMD_SEND_DATA(0x04)` 数据帧可不带校验(当前 Android 逻辑)
### 6.3 回包解析
`func` 分发处理:
1. `0x01`:设备状态
2. `0x04`:数据发送 ACK用于释放“发送下一包”锁
3. `0x05`:标签定位完成
4. `0x06`:标签偏移读取结果
5. `0xA1~0xA4`OTA流程响应
---
## 7. 打印引擎迁移设计
### 7.1 打印参数映射
浓度映射(与 Android 对齐):
- `较淡 -> 1000`
- `中等 -> 1500`
- `较浓 -> 2000`
- `最深 -> 3000`
打印前序列:
1. `CMD_POWER`
2. `CMD_SET_PARAM(hot_mode, move_time, hot_time)`
3. 分包发送 `CMD_SEND_DATA`
打印后序列:
1. `CMD_POWER`
2. `CMD_SET_DISTANCE(12.5mm)` 留白走纸
### 7.2 分包规则
与 Android 同步:
- 单帧上限 244 bytes
- 协议头 4 bytes
- 数据体 240 bytes384 点宽 -> 48 bytes/行 -> 每包 5 行)
流控策略:
- 发出数据包后等待 `0x04` ACK
- 首包后可短延时一次
- 后续每包 ACK 驱动
- ACK 超时建议 `2~5s`,整任务超时 `30s`
### 7.3 打印状态门限
建议保持一致:
- 缺纸:禁止打印
- 电量 `<=40%`:禁止打印
- 温度 `>=60℃`:禁止打印
---
## 8. 图像处理迁移策略(重点)
ESP32 内存有限,不建议一次性处理大图。推荐 3 种模式:
### 8.1 模式 A推荐首版
外部PC/手机/云先生成“384宽 + 二值化 + 行取模”数据ESP32 仅负责协议发送。
优点:
- 开发最快
- ESP32 负载最低
### 8.2 模式 B文本优先
ESP32 只做文本/模板渲染,不做复杂图片解码。
优点:
- 资源可控
- 适合收据、标签、测试页
### 8.3 模式 C全本地
ESP32 本地做图片解码+缩放+二值化+取模。需外接 PSRAM建议 ESP32-S3。
---
## 9. FreeRTOS 任务模型建议
建议拆成 4 个任务 + 2 个队列:
1. `ble_task`
- 处理 GAP/GATT 事件
2. `proto_task`
- 帧收发、ACK 管理、回包解析
3. `print_task`
- 打印流程状态机(预热、分包、收尾)
4. `cmd_task`
- 外部命令入口(串口/Web/UI
队列:
- `q_cmd`业务命令print/status/ota
- `q_evt`BLE/协议事件connected/ack/timeout
同步对象:
- `EventGroup``READY``ACK_04``GAP_OK``OTA_ACK`
- `Mutex`:写特征互斥
---
## 10. 关键 C 接口建议
```c
// BLE
esp_err_t printer_ble_start_scan(void);
esp_err_t printer_ble_connect_by_name(const char *name);
esp_err_t printer_ble_write(const uint8_t *data, size_t len, bool no_rsp);
// 协议
size_t printer_proto_build_frame(uint8_t addr, uint8_t cmd,
const uint8_t *payload, uint16_t len,
bool with_checksum, uint8_t *out);
void printer_proto_handle_notify(const uint8_t *data, size_t len);
// 打印引擎
esp_err_t printer_engine_print_raw(const uint8_t *raw, size_t len, int hot_time);
esp_err_t printer_engine_get_status(void);
esp_err_t printer_engine_gap_move(void);
esp_err_t printer_engine_set_label_offset(uint8_t value);
// OTA
esp_err_t printer_ota_run(const uint8_t *fw, size_t len);
```
---
## 11. OTA 迁移(针对打印机固件升级)
流程对齐 Android
1. `A0` 跳 Boot
2. `A1` 擦页(按 1024 bytes 估页数)
3. `A2` 写入(单包 236 bytes 数据)
4. `A3` 跳回 App
5. `A4` 读版本确认
建议:
- 每步都有超时和重试(每步 3 次)
- 断电恢复策略:记录 last packet index
---
## 12. 分阶段实施计划
### Phase 13~5天
1. BLE 扫描连接 + 订阅通知 + MTU
2. 实现 `GET_STATUS`
3. 实现 `POWER / SET_PARAM / SEND_DATA / SET_DISTANCE`
4. 用固定测试页 raw 数据打印
验收:
- 可稳定打印 50 次无死锁
### Phase 23~7天
1. 文本模板渲染
2. 标签定位/偏移
3. 设备参数保存NVS
验收:
- 标签纸对齐稳定
### Phase 33~7天
1. OTA 全流程
2. 回归测试与异常恢复
验收:
- 升级成功率 > 99%
---
## 13. 测试清单
基础通信:
1. 扫描到 `lyfPrinter`
2. 连接后找到 `FFF1/FFF2`
3. Notify 有数据
4. MTU 协商到 247
协议一致性:
1. 每条命令帧结构正确
2. 校验和与 Android 一致
3. `0x04` ACK 能正确驱动分包
打印质量:
1. 浓度 4 档效果一致
2. 长图连续打印无丢行
3. 结束留白距离稳定
异常场景:
1. 打印中断线后可恢复
2. 缺纸/低电/高温阻断生效
3. OTA 超时重试有效
---
## 14. 常见问题与规避
1. `write without response` 太快导致对端缓存溢出
规避:严格按 `0x04 ACK` 节奏发送。
2. 连接成功但收不到 Notify
规避:确认 CCCD 写成功且未被后续重连覆盖。
3. 打印偏移不稳定
规避:先 `GAP_MOVE`,再按偏移走纸,偏移值写入 NVS。
4. ESP32 内存不足
规避:首版采用“外部预编码 raw 数据”,不在设备端做重图像处理。
---
## 15. 最小可用迁移路径(建议)
如果你希望最快落地,按下面最小路径:
1. 先只做 BLE + 协议 + raw 发送
2. 用串口命令输入 `print_raw/status/gap/offset`
3. 打通后再逐步补 UI 和本地渲染
这样可以最短时间复用 Android 的核心协议能力,并把主要风险收敛在 BLE 链路与分包流控上。
---
## 16. 附:协议发送伪代码
```c
void do_print(const uint8_t *raw, size_t raw_len, int hot_time) {
send_cmd_power(true); // 0x00
send_cmd_set_param(1, 2, hot_time); // 0x03
const size_t chunk = 240;
size_t off = 0;
int idx = 0;
while (off < raw_len) {
size_t n = (raw_len - off > chunk) ? chunk : (raw_len - off);
send_cmd_data(raw + off, n); // 0x04
if (idx > 0) {
if (!wait_ack_04(3000)) {
// 超时处理:重发或中止
break;
}
} else {
vTaskDelay(pdMS_TO_TICKS(10));
}
off += n;
idx++;
}
send_cmd_power(false); // 0x00
send_cmd_set_distance(12.5f); // 0x02
}
```