From 081883c823ec37662ffb9e1f1bae8749d8ff3e52 Mon Sep 17 00:00:00 2001 From: paul2212 Date: Sat, 7 Mar 2026 14:13:44 +0100 Subject: [PATCH] Add HA print web UI and release version 0.1.8 --- CHANGELOG.md | 45 +++++ README.md | 5 + fichero/api.py | 320 ++++++++++++++++++++++++++++++++- fichero_printer/DOCS.md | 6 +- fichero_printer/config.yaml | 3 +- fichero_printer/fichero/api.py | 320 ++++++++++++++++++++++++++++++++- pyproject.toml | 2 +- 7 files changed, 689 insertions(+), 12 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..5500feb --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,45 @@ +# Changelog + +All notable changes to this project are documented in this file. + +The format is based on Keep a Changelog and this project uses Semantic Versioning. + +## [0.1.8] - 2026-03-07 + +### Added +- Root URL now serves a built-in printer web interface for Home Assistant with status, info, text printing, and image upload printing. + +### Changed +- Swagger docs remain available under `/docs` while the Home Assistant "Open" action now lands on the print UI. + +## [0.1.7] - 2026-03-07 + +### Fixed +- Home Assistant ingress docs now use a custom Swagger UI route with a relative `openapi.json` URL, avoiding `404 /openapi.json` behind ingress prefixes. + +### Changed +- Home Assistant add-on now requests `full_access: true` in addition to Bluetooth capabilities to unblock Classic RFCOMM socket access on stricter hosts. + +## [0.1.6] - 2026-03-07 + +### Added +- Added this `CHANGELOG.md` and established a release policy to update version and changelog for every change. + +## [0.1.5] - 2026-03-07 + +### Changed +- Home Assistant add-on now requests `NET_RAW` in addition to `NET_ADMIN` for Classic Bluetooth RFCOMM sockets. +- Add-on documentation updated with Classic permission requirements. + +## [0.1.4] - 2026-03-07 + +### Fixed +- RFCOMM connection under `uvloop` now uses direct Bluetooth socket connect in a worker thread, avoiding address-family resolution issues. +- Classic Bluetooth socket errors are mapped to API-safe printer errors instead of unhandled 500s. + +## [0.1.3] - 2026-03-07 + +### Changed +- Home Assistant add-on metadata updated for ingress/web UI access. +- API root endpoint now redirects to docs in an ingress-compatible way. +- Added attribution for original upstream project and AI-assisted extension note. diff --git a/README.md b/README.md index af68d20..f8ff60e 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,11 @@ Web GUI, Python CLI, and protocol documentation for the Fichero D11s thermal lab - Original developer/project: [0xMH/fichero-printer](https://github.com/0xMH/fichero-printer) - This repository version was additionally extended with AI-assisted changes. +## Release Policy + +- Maintain `CHANGELOG.md` for every user-visible change. +- Bump the project/add-on version with every merged change. + 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 d191d8a..a96eb7b 100644 --- a/fichero/api.py +++ b/fichero/api.py @@ -23,7 +23,8 @@ from typing import Annotated from fastapi import FastAPI, File, Form, HTTPException, UploadFile from fastapi.middleware.cors import CORSMiddleware -from fastapi.responses import RedirectResponse +from fastapi.openapi.docs import get_swagger_ui_html +from fastapi.responses import HTMLResponse, RedirectResponse from PIL import Image from fichero.cli import DOTS_PER_MM, do_print @@ -73,6 +74,8 @@ app = FastAPI( description="REST API for the Fichero D11s (AiYin) thermal label printer.", version="0.1.0", lifespan=lifespan, + docs_url=None, + redoc_url=None, ) app.add_middleware( @@ -88,14 +91,323 @@ def _address(address: str | None) -> str | None: return address or _DEFAULT_ADDRESS +def _ui_html() -> str: + default_address = _DEFAULT_ADDRESS or "" + default_transport = "classic" if _DEFAULT_CLASSIC else "ble" + return f""" + + + + + Fichero Printer + + + +
+
+

Fichero Printer

+

Home Assistant print console for status, text labels, and image uploads.

+

API docs remain available at /docs.

+
+ +
+
+

Connection

+ + + +
+
+ + +
+
+ + +
+
+ +
+ + +
+
+ +
+

Output

+
Ready.
+
+ +
+

Print Text

+ + +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ + +
+ +
+
+ +
+

Print Image

+ + +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+
+ + + +""" + + # --------------------------------------------------------------------------- # Endpoints # --------------------------------------------------------------------------- -@app.get("/", include_in_schema=False) +@app.get("/", include_in_schema=False, response_class=HTMLResponse) async def root(): - """Redirect root to interactive API docs.""" - return RedirectResponse(url="docs") + """Serve a compact printer UI for Home Assistant.""" + return HTMLResponse(_ui_html()) + + +@app.get("/docs", include_in_schema=False) +async def docs(): + """Serve Swagger UI with ingress-safe relative OpenAPI URL.""" + return get_swagger_ui_html( + openapi_url="openapi.json", + title=f"{app.title} - Swagger UI", + ) @app.get( diff --git a/fichero_printer/DOCS.md b/fichero_printer/DOCS.md index c0718d2..82e51b5 100644 --- a/fichero_printer/DOCS.md +++ b/fichero_printer/DOCS.md @@ -28,10 +28,10 @@ direkt aus Home Assistant-Automationen, Skripten oder externen Anwendungen. Das Add-on ist nach dem Start auf zwei Arten erreichbar: -1. Home Assistant UI (Ingress): In der Add-on-Seite auf **"Öffnen"** klicken. +1. Home Assistant UI (Ingress): In der Add-on-Seite auf **"Öffnen"** klicken. Dort erscheint direkt das Webinterface zum Abrufen von Status/Info sowie zum Drucken von Text und Bildern. 2. Direkt per Port im Netzwerk: `http://:` (z.B. `http://homeassistant.local:8765`). -Hinweis: `/` leitet auf `/docs` weiter (Swagger UI). +Hinweis: Die API-Dokumentation bleibt unter `/docs` erreichbar. ### Endpunkte @@ -148,6 +148,8 @@ rest_command: - **Classic Bluetooth (RFCOMM):** Nur unter Linux verfügbar. Erfordert die direkte Bluetooth-Adresse (kein automatischer Scan möglich) und Container- Rechte für Bluetooth-Sockets (`NET_ADMIN` + `NET_RAW`). +- Das Add-on läuft dafür mit `full_access`, weil einige Home-Assistant-Hosts + RFCOMM trotz gesetzter Capabilities sonst weiterhin blockieren. - Wenn die BLE-Adresse bekannt ist, diese in der Konfiguration eintragen – das beschleunigt den Verbindungsaufbau erheblich (kein Scan nötig). - Der Drucker muss eingeschaltet sein, bevor eine Anfrage gestellt wird. diff --git a/fichero_printer/config.yaml b/fichero_printer/config.yaml index e6f58c0..4edbadc 100644 --- a/fichero_printer/config.yaml +++ b/fichero_printer/config.yaml @@ -1,5 +1,5 @@ name: "Fichero Printer" -version: "0.1.5" +version: "0.1.8" slug: "fichero_printer" description: "REST API for the Fichero D11s (AiYin) thermal label printer over Bluetooth" url: "https://git.leuschner.dev/Tobias/Fichero" @@ -19,6 +19,7 @@ ingress_port: 8765 panel_icon: mdi:printer panel_title: Fichero Printer webui: "http://[HOST]:[PORT:8765]/" +full_access: true host_network: true host_dbus: true diff --git a/fichero_printer/fichero/api.py b/fichero_printer/fichero/api.py index d191d8a..a96eb7b 100644 --- a/fichero_printer/fichero/api.py +++ b/fichero_printer/fichero/api.py @@ -23,7 +23,8 @@ from typing import Annotated from fastapi import FastAPI, File, Form, HTTPException, UploadFile from fastapi.middleware.cors import CORSMiddleware -from fastapi.responses import RedirectResponse +from fastapi.openapi.docs import get_swagger_ui_html +from fastapi.responses import HTMLResponse, RedirectResponse from PIL import Image from fichero.cli import DOTS_PER_MM, do_print @@ -73,6 +74,8 @@ app = FastAPI( description="REST API for the Fichero D11s (AiYin) thermal label printer.", version="0.1.0", lifespan=lifespan, + docs_url=None, + redoc_url=None, ) app.add_middleware( @@ -88,14 +91,323 @@ def _address(address: str | None) -> str | None: return address or _DEFAULT_ADDRESS +def _ui_html() -> str: + default_address = _DEFAULT_ADDRESS or "" + default_transport = "classic" if _DEFAULT_CLASSIC else "ble" + return f""" + + + + + Fichero Printer + + + +
+
+

Fichero Printer

+

Home Assistant print console for status, text labels, and image uploads.

+

API docs remain available at /docs.

+
+ +
+
+

Connection

+ + + +
+
+ + +
+
+ + +
+
+ +
+ + +
+
+ +
+

Output

+
Ready.
+
+ +
+

Print Text

+ + +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ + +
+ +
+
+ +
+

Print Image

+ + +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+
+ + + +""" + + # --------------------------------------------------------------------------- # Endpoints # --------------------------------------------------------------------------- -@app.get("/", include_in_schema=False) +@app.get("/", include_in_schema=False, response_class=HTMLResponse) async def root(): - """Redirect root to interactive API docs.""" - return RedirectResponse(url="docs") + """Serve a compact printer UI for Home Assistant.""" + return HTMLResponse(_ui_html()) + + +@app.get("/docs", include_in_schema=False) +async def docs(): + """Serve Swagger UI with ingress-safe relative OpenAPI URL.""" + return get_swagger_ui_html( + openapi_url="openapi.json", + title=f"{app.title} - Swagger UI", + ) @app.get( diff --git a/pyproject.toml b/pyproject.toml index ac6e3de..b881a46 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "fichero-printer" -version = "0.1.4" +version = "0.1.8" description = "Fichero D11s thermal label printer - BLE CLI tool" requires-python = ">=3.10" dependencies = [