0.1.30
Some checks failed
Deploy to GitHub Pages / build (push) Has been cancelled
Deploy to GitHub Pages / deploy (push) Has been cancelled

This commit is contained in:
paul2212
2026-03-16 19:01:14 +01:00
parent 4c1bedf166
commit a23c33e293
3 changed files with 91 additions and 11 deletions

View File

@@ -27,8 +27,10 @@ from typing import Annotated
from fastapi import FastAPI, File, Form, HTTPException, UploadFile
from fastapi.middleware.cors import CORSMiddleware
from fastapi.openapi.docs import get_swagger_ui_html
from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from PIL import Image
from bleak import BleakScanner
from fichero.cli import DOTS_PER_MM, do_print
from fichero.imaging import text_to_image
@@ -75,7 +77,7 @@ async def lifespan(app: FastAPI): # noqa: ARG001
app = FastAPI(
title="Fichero Printer API",
description="REST API for the Fichero D11s (AiYin) thermal label printer.",
version = "0.1.29",
version = "0.1.30",
lifespan=lifespan,
docs_url=None,
redoc_url=None,
@@ -88,6 +90,13 @@ app.add_middleware(
allow_headers=["*"],
)
# Serve static files for the modern web UI (if built and present in 'web' dir)
_WEB_ROOT = Path(__file__).parent / "web"
if _WEB_ROOT.exists():
# Typical SPA assets folder
if (_WEB_ROOT / "assets").exists():
app.mount("/assets", StaticFiles(directory=_WEB_ROOT / "assets"), name="assets")
def _address(address: str | None) -> str | None:
"""Return the effective BLE address (request value overrides env default)."""
@@ -105,21 +114,67 @@ def _ui_html() -> str:
return "<h1>Error: index.html not found</h1>"
# Simple substitution for initial values
return (
template = (
template.replace("{default_address}", default_address)
.replace("{ble_selected}", " selected" if default_transport == "ble" else "")
.replace("{classic_selected}", " selected" if default_transport == "classic" else "")
.replace("{default_channel}", str(_DEFAULT_CHANNEL))
)
# Inject debug scan section and script
scan_html = """
<div class="section">
<h2>Debug Scan</h2>
<p>Scans for all nearby BLE devices to help with debugging connection issues.</p>
<button type="button" onclick="scanForDevices()">Scan for BLE Devices (10s)</button>
<pre id="scan-results" style="background-color: #f0f0f0; border: 1px solid #ccc; padding: 10px; margin-top: 10px; white-space: pre-wrap; word-wrap: break-word;"></pre>
</div>
"""
scan_script = r'''
<script>
async function scanForDevices() {
const resultsEl = document.getElementById('scan-results');
resultsEl.textContent = 'Scanning for 10 seconds...';
try {
const response = await fetch('/scan');
if (!response.ok) {
const error = await response.json();
throw new Error(error.detail || `HTTP error! status: ${response.status}`);
}
const devices = await response.json();
if (devices.length === 0) {
resultsEl.textContent = 'No BLE devices found.';
} else {
resultsEl.textContent = 'Found devices:\n\n' +
devices.map(d => ` ${d.address} | RSSI: ${d.rssi} | ${d.name}`).join('\n');
}
} catch (e) {
resultsEl.textContent = 'Error during scan: ' + e.message;
}
}
</script>
'''
# Inject before the closing </body> tag
if "</body>" in template:
parts = template.split("</body>", 1)
template = parts[0] + scan_html + scan_script + "</body>" + parts[1]
else:
# Fallback if no body tag
template += scan_html + scan_script
return template
# ---------------------------------------------------------------------------
# Endpoints
# ---------------------------------------------------------------------------
@app.get("/", include_in_schema=False, response_class=HTMLResponse)
async def root():
async def root(legacy: bool = False):
"""Serve a compact printer UI for Home Assistant."""
# Prefer the modern SPA if available, unless ?legacy=true is used
if not legacy and (_WEB_ROOT / "index.html").exists():
return HTMLResponse((_WEB_ROOT / "index.html").read_text(encoding="utf-8"))
return HTMLResponse(_ui_html())
@@ -190,6 +245,26 @@ async def get_info(
return info
@app.get(
"/scan",
summary="Scan for BLE devices",
response_description="List of discovered BLE devices",
)
async def scan_devices():
"""Scan for nearby BLE devices for 10 seconds for debugging."""
try:
devices = await BleakScanner.discover(timeout=10.0)
return [
{"address": d.address, "name": d.name or "N/A", "rssi": d.rssi}
for d in devices
]
except Exception as exc:
# This provides more debug info to the user if scanning fails
raise HTTPException(
status_code=500, detail=f"An error occurred during BLE scanning: {exc}"
)
@app.post(
"/pair",
summary="Pair and trust a Bluetooth device",