Files
AI_Printer/ESP32_ESP-IDF移植实施文档.md
2026-02-10 17:11:06 +08:00

460 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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
}
```