diff --git a/README.md b/README.md index b818e77..af68d20 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,11 @@ Web GUI, Python CLI, and protocol documentation for the Fichero D11s thermal label printer. +## Credits + +- Original developer/project: [0xMH/fichero-printer](https://github.com/0xMH/fichero-printer) +- This repository version was additionally extended with AI-assisted changes. + Blog post: [Reverse Engineering Action's Cheap Fichero Labelprinter](https://blog.dbuglife.com/reverse-engineering-fichero-label-printer/) The [Fichero](https://www.action.com/nl-nl/p/3212141/fichero-labelprinter/) is a cheap Bluetooth thermal label printer sold at Action. Internally it's an AiYin D11s made by Xiamen Print Future Technology. The official app is closed-source and doesn't expose the protocol, so this project reverse-engineers it from the decompiled APK. diff --git a/fichero/api.py b/fichero/api.py index f916e2b..9af0940 100644 --- a/fichero/api.py +++ b/fichero/api.py @@ -23,6 +23,7 @@ from typing import Annotated from fastapi import FastAPI, File, Form, HTTPException, UploadFile from fastapi.middleware.cors import CORSMiddleware +from fastapi.responses import RedirectResponse from PIL import Image from fichero.cli import DOTS_PER_MM, do_print @@ -91,6 +92,11 @@ def _address(address: str | None) -> str | None: # Endpoints # --------------------------------------------------------------------------- +@app.get("/", include_in_schema=False) +async def root(): + """Redirect root to interactive API docs.""" + return RedirectResponse(url="/docs") + @app.get( "/status", diff --git a/fichero/printer.py b/fichero/printer.py index cd42067..446d7ad 100644 --- a/fichero/printer.py +++ b/fichero/printer.py @@ -12,6 +12,7 @@ from collections.abc import AsyncGenerator from contextlib import asynccontextmanager from bleak import BleakClient, BleakGATTCharacteristic, BleakScanner +from bleak.exc import BleakDBusError, BleakError # --- RFCOMM (Classic Bluetooth) support - Linux + Windows (Python 3.9+) --- @@ -374,7 +375,17 @@ async def connect( yield pc else: addr = address or await find_printer() - async with BleakClient(addr) as client: - pc = PrinterClient(client) - await pc.start() - yield pc + try: + async with BleakClient(addr) as client: + pc = PrinterClient(client) + await pc.start() + yield pc + except BleakDBusError as exc: + if "br-connection-not-supported" in str(exc).lower(): + raise PrinterError( + "BLE connection failed (br-connection-not-supported). " + "Try Classic Bluetooth with classic=true and channel=1." + ) from exc + raise PrinterError(f"BLE connection failed: {exc}") from exc + except BleakError as exc: + raise PrinterError(f"BLE error: {exc}") from exc diff --git a/fichero_printer/DOCS.md b/fichero_printer/DOCS.md index 887f4ed..5f25e6b 100644 --- a/fichero_printer/DOCS.md +++ b/fichero_printer/DOCS.md @@ -4,6 +4,11 @@ Ein HTTP-REST-API-Server für den **Fichero D11s** (auch bekannt als AiYin D11s) Thermodrucker. Das Add-on ermöglicht das Drucken von Textetiketten und Bildern direkt aus Home Assistant-Automationen, Skripten oder externen Anwendungen. +## Herkunft / Credits + +- Originalentwickler / Ursprungsprojekt: https://github.com/0xMH/fichero-printer +- Diese Variante wurde zusätzlich mit AI-unterstützten Erweiterungen ergänzt. + ## Voraussetzungen - Fichero D11s / AiYin D11s Drucker @@ -21,8 +26,12 @@ direkt aus Home Assistant-Automationen, Skripten oder externen Anwendungen. ## Verwendung -Nach dem Start ist die API unter `http://:` erreichbar. -Die interaktive Swagger-Dokumentation ist unter `http://:/docs` verfügbar. +Das Add-on ist nach dem Start auf zwei Arten erreichbar: + +1. Home Assistant UI (Ingress): In der Add-on-Seite auf **"Öffnen"** klicken. +2. Direkt per Port im Netzwerk: `http://:` (z.B. `http://homeassistant.local:8765`). + +Hinweis: `/` leitet auf `/docs` weiter (Swagger UI). ### Endpunkte diff --git a/fichero_printer/config.yaml b/fichero_printer/config.yaml index 696a7e5..f83f967 100644 --- a/fichero_printer/config.yaml +++ b/fichero_printer/config.yaml @@ -14,6 +14,11 @@ arch: init: false startup: application boot: auto +ingress: true +ingress_port: 8765 +panel_icon: mdi:printer +panel_title: Fichero Printer +webui: "http://[HOST]:[PORT:8765]/docs" host_network: true host_dbus: true diff --git a/fichero_printer/fichero/api.py b/fichero_printer/fichero/api.py index f916e2b..9af0940 100644 --- a/fichero_printer/fichero/api.py +++ b/fichero_printer/fichero/api.py @@ -23,6 +23,7 @@ from typing import Annotated from fastapi import FastAPI, File, Form, HTTPException, UploadFile from fastapi.middleware.cors import CORSMiddleware +from fastapi.responses import RedirectResponse from PIL import Image from fichero.cli import DOTS_PER_MM, do_print @@ -91,6 +92,11 @@ def _address(address: str | None) -> str | None: # Endpoints # --------------------------------------------------------------------------- +@app.get("/", include_in_schema=False) +async def root(): + """Redirect root to interactive API docs.""" + return RedirectResponse(url="/docs") + @app.get( "/status", diff --git a/fichero_printer/fichero/printer.py b/fichero_printer/fichero/printer.py index cd42067..446d7ad 100644 --- a/fichero_printer/fichero/printer.py +++ b/fichero_printer/fichero/printer.py @@ -12,6 +12,7 @@ from collections.abc import AsyncGenerator from contextlib import asynccontextmanager from bleak import BleakClient, BleakGATTCharacteristic, BleakScanner +from bleak.exc import BleakDBusError, BleakError # --- RFCOMM (Classic Bluetooth) support - Linux + Windows (Python 3.9+) --- @@ -374,7 +375,17 @@ async def connect( yield pc else: addr = address or await find_printer() - async with BleakClient(addr) as client: - pc = PrinterClient(client) - await pc.start() - yield pc + try: + async with BleakClient(addr) as client: + pc = PrinterClient(client) + await pc.start() + yield pc + except BleakDBusError as exc: + if "br-connection-not-supported" in str(exc).lower(): + raise PrinterError( + "BLE connection failed (br-connection-not-supported). " + "Try Classic Bluetooth with classic=true and channel=1." + ) from exc + raise PrinterError(f"BLE connection failed: {exc}") from exc + except BleakError as exc: + raise PrinterError(f"BLE error: {exc}") from exc