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

11 KiB
Raw Blame History

lyfPrinter 上位机 APP 迁移到 ESP32(ESP-IDF) 实施文档

本文档基于当前 Android 上位机 APP 实现(MainActivity + ECBLE + BlueHandler + 各预览页),给出一套可落地的 ESP32/ESP-IDF 迁移方案。

适用目标:

  • 让 ESP32 作为 BLE Central 连接 lyfPrinter 热敏打印机
  • 复用现有私有打印协议(0x00~0x070xA0~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 HostNimBLE内存占用更低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 升级流程

建议目录:

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 指令定义

// 打印
#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 帧结构

常规帧:

[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~0xA4OTA流程响应

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_evtBLE/协议事件connected/ack/timeout

同步对象:

  • EventGroupREADYACK_04GAP_OKOTA_ACK
  • Mutex:写特征互斥

10. 关键 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. 附:协议发送伪代码

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
}