Initial commit: ESP32-C3 WiFi→BLE bridge for Phomemo M110

- BLE client (NimBLE) with auto-scan/reconnect
- ESC/POS protocol encoder (GS v 0 raster)
- Web API: /api/status, /api/connect, /api/print
- Web UI: image upload with dithering, QR codes, positioning
- Client-side QR generation (qrcode-generator)
- Supports bitmap, QR, and raw ESC/POS print types
This commit is contained in:
2026-06-13 16:38:54 +02:00
commit 42efd83bc0
11 changed files with 1330 additions and 0 deletions
+146
View File
@@ -0,0 +1,146 @@
# ESP32 M110 Label Printer Bridge
WiFi → BLE Bridge für den **Phomemo M110** Bluetooth-Etikettendrucker.
Läuft auf **ESP32-C3** (PlatformIO / Arduino).
## Hardware
- **ESP32-C3** DevKit (oder kompatibel mit WiFi + BLE)
- **Phomemo M110** Etikettendrucker (203 dpi, 48mm Druckbreite)
## Quickstart
### 1. Konfiguration
WiFi-Zugangsdaten und BLE-Name des Druckers in `platformio.ini` eintragen:
```ini
build_flags = -std=gnu++17 -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1
-DWIFI_SSID='"MeinWLAN"'
-DWIFI_PASS='"MeinPasswort"'
-DPRINTER_BLE_NAME='"Q199G4180950002"'
```
Den BLE-Namen findest du auf dem Etikett auf der Drucker-Rückseite.
### 2. Build & Flash
```bash
pio run -t upload # Firmware
pio run -t uploadfs # Web-Interface (LittleFS)
```
### 3. Verwenden
Web-Interface unter `http://<esp32-ip>/` öffnen.
Oder per curl:
```bash
# Status
curl http://192.168.1.100/api/status
# QR-Code drucken (106×106px, zentriert)
curl -X POST http://192.168.1.100/api/print \
-H "Content-Type: application/json" \
-d '{"type":"qr","data":"https://techahead.de","scale":4}'
# Bild drucken (1-Bit Bitmap als Base64)
curl -X POST http://192.168.1.100/api/print \
-H "Content-Type: application/json" \
-d '{"type":"bitmap","data":"...","width":384,"height":200,"density":15,"offsetX":0}'
# BLE-Scan starten
curl -X POST http://192.168.1.100/api/connect
```
## API
| Endpoint | Methode | Beschreibung |
|----------|---------|-------------|
| `/` | GET | Web-Interface |
| `/api/status` | GET | JSON: WiFi, BLE, Drucker-Status |
| `/api/connect` | POST | BLE-Scan starten |
| `/api/print` | POST | Druckauftrag |
### POST /api/print
```json
{
"type": "qr",
"data": "https://example.com",
"scale": 4,
"offsetX": 0
}
```
```json
{
"type": "bitmap",
"data": "<base64>",
"width": 384,
"height": 200,
"density": 15,
"offsetX": 0
}
```
```json
{
"type": "raw",
"data": "<base64-ESC/POS-bytes>"
}
```
## Web-Interface
- **🖼️ Bild drucken:** Upload per Drag & Drop, Vorschau mit B/W-Dithering (Atkinson, Floyd-Steinberg, Schwellwert), Positionierung auf 48mm-Band, einstellbare Druckdichte
- **📱 QR-Code:** Text/URL eingeben, Skalierung, Positionierung. QR wird client-seitig generiert — Vorschau = Druckergebnis
- **Status:** WiFi/BLE-Verbindung, RSSI, Uptime
## M110 BLE Protokoll
- **Service UUID:** `0000FF00-0000-1000-8000-00805F9B34FB`
- **Write Characteristic:** `0000FF02-0000-1000-8000-00805F9B34FB`
- **Verbindung:** Per advertised name, kein Pairing
- **Protokoll:** ESC/POS `GS v 0` Raster-Bitmap
- **Auflösung:** 384px (48mm) @ 203dpi → 48 Bytes/Zeile
- **Esc/POS-Kommandos:**
- `ESC @` — Drucker initialisieren
- `ESC N 0x0D <speed>` — Druckgeschwindigkeit (15)
- `ESC N 0x04 <density>` — Druckdichte (115)
- `GS DC1 <type>` — Medientyp (0x0A=LabelWithGaps, 0x0B=Continuous)
- `GS v 0 <xL><xH><yL><yH> <data>` — Raster-Bitmap (max 240 Zeilen empfohlen)
- `GS F0 05 00` / `GS F0 03 00` — Footer
Das Protokoll basiert auf Reverse-Engineering von [phomemo-tools](https://github.com/vivier/phomemo-tools) und [phomemo-macos](https://github.com/jacquesg/phomemo-macos).
## Projektstruktur
```
esp32-m110-label/
├── platformio.ini # PlatformIO Config
├── private_config.ini.example # Vorlage für Credentials
├── README.md
├── src/
│ ├── main.cpp # WiFi, HTTP-API, Setup
│ ├── config.h # UUIDs, Konstanten
│ ├── printer.h # M110 ESC/POS Encoder
│ ├── ble_client.h # NimBLE Scanner + Connection Manager
│ └── qr_renderer.h # QR-Code → Bitmap Renderer
└── data/
├── index.html # Web-Interface
└── qrcode.min.js # QR-Code Generator (client-side)
```
## Libraries
- [NimBLE-Arduino](https://github.com/h2zero/NimBLE-Arduino) — BLE Stack (ESP32-C3 optimiert)
- [ESPAsyncWebServer](https://github.com/esphome/ESPAsyncWebServer) — Async HTTP Server
- [ArduinoJson](https://arduinojson.org/) — JSON Parsing
- [QRCode](https://github.com/ricmoo/QRCode) — QR-Code Generation (ESP32, optional)
- [qrcode-generator](https://github.com/kazuhikoarase/qrcode-generator) — QR-Code Generation (Client/JS)
## Lizenz
MIT