ChiaraCannolee/thermal-pocket-printer
GitHub: ChiaraCannolee/thermal-pocket-printer
通过逆向工程 BLE 协议,摆脱隐私 intrusive 的官方应用,实现直接从浏览器或命令行控制热敏口袋打印机。
Stars: 0 | Forks: 0
# crafts-and-co-thermal-pocket-printer
通过蓝牙直接从电脑打印到 **Crafts & Co 3128** 热敏口袋打印机,无需使用 App。
Crafts & Co 3128(在荷兰/欧洲的 Action 商店有售)是厦门普润未来科技有限公司生产的 **DP-L1S** 的贴牌产品,使用的是 **LuckPrinter SDK**。它的配套应用(“Luck Jingle”)要求获取过多的权限,对于一个仅通过蓝牙打印的设备来说,甚至还需要持久的互联网连接。本项目旨在将这个应用从流程中移除。
## 快速开始:打开 Web 应用
**无需安装。** 只需在 Chrome、Edge 或 Opera 浏览器中打开此链接:
**https://ChiaraCannolee.github.io/thermal-pocket-printer/**
(需要 Web Bluetooth 支持——支持台式机上的 Chrome/Edge/Opera,不支持 Firefox/Safari)
## 功能介绍
Web 应用提供了设计和打印标签、贴纸和收据所需的一切功能:
### 设计工具
- **图片选项卡**:拖放 PNG/JPG 等格式的图片,应用会自动将其调整为适合标签的尺寸
- **文本选项卡**:输入文本,调整大小,直接在预览中拖动以重新定位(或使用方向键微调——按 Shift+方向键可进行较大步幅的调整)。点击“⊕ Center”可使其迅速回到中心位置。
- **测试选项卡**:打印带有渐变条的对齐图案,以便您验证密度和抖动设置
### 标签尺寸
包含六种预设,涵盖了 Action 最常见的贴纸卷(29×12、40×12、50×30、40×30mm 矩形标签,以及 30mm 圆形贴纸),还有针对 56mm 连续纸的自动/收据模式,支持以毫米为单位的自定义尺寸。白色预览面板会进行缩放,以匹配您所选标签的比例。
对于 56mm 连续纸,预览界面会在两侧显示阴影区域,用于指示实际的打印区域——打印头覆盖 56mm 宽纸张中的 48mm,每侧留有 4mm 的边距。
对于圆形标签,内容会自动遮罩为圆形,因此外部任何不在范围内的内容都不会被打印出来。
### 打印设置
- **Density(浓度)** – 三个级别(浅、正常、深)
- **Dither(抖动)** – Floyd-Steinberg 算法,适用于照片和渐变
- **Invert(反转)** – 交换黑白颜色
- **Label mode(标签模式)** – 适用于带有间隙的预切标签。关闭 = 连续纸。
### 打印预览
在打印之前,您会看到一个预览对话框,包含:
- **阈值滑块** – 实时预览阈值如何影响您的图像 (0-255)
- **份数** – 最多可打印 99 份相同的设计
- **Density override(密度覆盖)** – 仅为此次打印覆盖侧边栏的密度设置
- **Feed after print(打印后进纸)** – 额外进纸量(以毫米为单位)
即使未连接打印机,预览也会打开,因此您可以在连接前查看设置(这非常实用,因为打印机在闲置一段时间后会自动关机)。
### 模板
点击软盘图标即可将任何设计保存为模板。模板会存储图像、所有打印设置、标签尺寸和文本位置。将其中一个设为默认模板,在下次访问时即可自动加载。数据存储在您的浏览器本地(无云同步,无需账户)。
### 其他贴心细节
- **撤销/重做**,使用 Ctrl+Z / Ctrl+Shift+Z(在 Mac 上为 Cmd 键),支持深度 30 步的操作
- **可编辑打印机名称** – 点击标题即可重命名您的打印机;跨会话持久化保存
- **按 ESC 键关闭任何打开的模态框**
- **点击模态框外部可将其关闭**
- 连接后会出现**电池指示器**
## Python CLI(用于自动化)
如果您更喜欢命令行,或者想批量处理打印任务:
```
# 安装依赖
pip install bleak Pillow
# 打印测试图案
python3 print.py test
# 打印图片
python3 print.py image photo.png
# 使用 dithering 打印 (适用于照片/渐变)
python3 print.py image photo.png --dither
# 打印文本
python3 print.py text "Hello World"
# 在 sticker paper 上打印 (label mode)
python3 print.py text "My Label" --label
# 检查打印机电池和状态
python3 print.py info
```
## Web GUI 与 CLI 对比
**Web GUI**(`index.html`)是最容易上手的途径——无需安装,只需在 Chrome 中打开即可。
**Python CLI**(`print.py`)适用于自动化、批处理任务和集成。需要运行 `pip install bleak Pillow`。
## 用法 (CLI)
```
python3 print.py [options]
Commands:
scan Scan for nearby BLE printers
info Show printer info (model, battery, firmware)
test Print a test pattern
image Print an image (PNG, JPG, BMP, etc.)
text Print text
Options:
--address, -a Printer BLE address (skip scanning)
--density, -d 0|1|2 Print darkness (0=light, 1=normal, 2=dark)
--dither Floyd-Steinberg dithering (better for photos)
--invert Invert colours (white-on-black)
--label Label/sticker mode with gap detection
--copies, -c N Number of copies
--width, -w N Print width in pixels (default: 384)
--feed, -f N Paper feed after print in dots (default: 80)
```
## 兼容纸张
打印机使用 56mm 宽的热敏贴纸和标签卷(30mm 标签直径)。兼容的耗材包括:
- 标准白色热敏纸(打印机附带)
- Crafts & Co 透明光面贴纸卷
- Crafts & Co 白色贴纸卷
- Crafts & Co 彩色贴纸卷(粉色、黄色等)
- 标准 56mm 热敏贴纸/标签卷
该打印机是“免墨”的:它利用热量激活热敏涂层。彩色纸张仅用于在黑色打印内容下提供彩色的背景。
## 工作原理
打印机使用 ESC/POS 热敏打印机协议的变体通过 BLE 进行通信。该协议是通过对反编译的 Android APK 进行逆向工程得出的,并经过了硬件验证。
### 连接与协议
1. **连接**到 BLE 服务 `ff00`,写入特征 `ff02`,监听 `ff01` 上的通知
2. **广播名称**:打印机以 "C&Co 3128_BLE" 的名称进行广播——注意:广播中没有服务 UUID,因此 Web 应用通过名称前缀进行过滤
3. **启用打印机**:发送 `10 FF F1 03`(特定于 Lujiang 的命令)
4. **唤醒**:发送 12 个空字节
5. **设置 density(浓度)**(可选):发送 `10 FF 10 00 [0|1|2]`,分别对应浅/正常/深
6. **发送 bitmap(位图)**:GS v 0 光栅图像(宽 384 像素,1位,MSB 优先)
7. **进纸**:`1B 4A 50`(进纸 80 点)
8. **停止作业**:`10 FF F1 45`(等待响应)
对于带有间隙检测的标签/贴纸纸:
- 将步骤 7 替换为 `1D 0C`(定位到下一个标签)
- 在打印前使用 `1F 11 51`,在打印后使用 `1F 11 50` 进行位置调整
有关完整的命令参考,请参见 [PROTOCOL.md](PROTOCOL.md)。
## 兼容打印机
此工具已确认可与 Crafts & Co 3128 (DP-L1S) 配合使用。它很可能也适用于 LuckPrinter 家族中使用相同 SDK 和 `BaseNormalDevice` 类的其他打印机;包括各种 DP-/DP 系列、LuckP-/LuckP 系列以及 MiniPocketPrinter 型号。打印宽度可能有所不同(请使用 `print.py info` 进行检查)。
**其他打印机类别使用不同的启用/停止命令:**
对于 Fichero D11s 和其他基于 AiYin 的标签打印机,请参见 0xMH 开发的 [fichero-printer](https://github.com/0xMH/fichero-printer),他针对不同的设备类别逆向工程了相同的 SDK。
## 背景
本项目最初是出于隐私动机而进行的逆向工程尝试。“Luck Jingle”应用要求获取位置权限、互联网访问权限以及各种其他与蓝牙打印机毫不相干的权限。该协议是通过使用 JADX 反编译 Android APK,并阅读 LuckPrinter SDK 中的 `PrinterImageProcessor` 和 `BaseNormalDevice` 类进行逆向工程得出的。
## 许可证
MIT
标签:BLE通信, CMS安全, Crafts & Co 3128, CSS, DP-L1S, Floyd-Steinberg算法, JavaScript, Python CLI, receipts, Web Bluetooth API, Web GUI, 后端开发, 图像处理, 开源硬件, 数据可视化, 无App打印, 标签设计与打印, 浏览器应用, 热敏打印机, 物联网, 蓝牙协议逆向工程, 调试辅助, 贴纸制作, 逆向工具