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.
+
+
+
+
+
+"""
+
+
# ---------------------------------------------------------------------------
# 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.