"""The ingress UI: status, commissioning checks and the two buttons that matter. Served inside Home Assistant, so no authentication of our own and no external port. All URLs here are RELATIVE - ingress serves the add-on under a generated path prefix, and an absolute "/status" would 404 in the field while working perfectly on a developer's laptop. Design bias: this page must be readable at the end of a long day, on a phone, in a cellar, by someone who did not write it. Numbers alone are not enough - it says what is wrong in words. """ import logging from aiohttp import web _LOG = logging.getLogger("goodwe.web") PAGE = """ GoodWe RS485 Controller

GoodWe RS485 Controller

Commissioning
""" def build_app(controller) -> web.Application: async def index(_request): return web.Response(text=PAGE, content_type="text/html") async def status(_request): return web.json_response(controller.status_payload()) async def action(request): try: body = await request.json() except ValueError: raise web.HTTPBadRequest(text="expected JSON") what = body.get("action") result = await controller.handle_action(what) if result is None: raise web.HTTPBadRequest(text=f"unknown action {what!r}") return web.json_response({"ok": True, "result": result}) app = web.Application() app.add_routes([ web.get("/", index), web.get("/status", status), web.post("/action", action), ]) return app async def start(controller, port: int = 8099): runner = web.AppRunner(build_app(controller)) await runner.setup() site = web.TCPSite(runner, "0.0.0.0", port) await site.start() _LOG.info("ingress UI listening on :%s", port) return runner