Six silent failures found by installing this on a live system
Migrated the reference site off the YAML packages and onto the add-on. Every bug below presented identically: the add-on starts, logs "started", serves its UI, and cannot do its job. - run.sh needs #!/usr/bin/with-contenv sh. s6-overlay sanitises the environment for services, so a plain shebang means SUPERVISOR_TOKEN is absent and every Core API call is 401 - while homeassistant_api: true makes permissions look granted. Startup now prints the token length and probes the API. - Supervisor keys the image by config.yaml `version`, so rebuilding without a bump reuses the old image. Two fixes appeared not to work because of it. - Alpine is musl and has no aiohttp wheel on PyPI; deps now come from apk so nothing compiles on a client's Pi. - Alpine ships paho-mqtt 1.x, which has no CallbackAPIVersion. That raised at construction and took the control loop down with it - so MQTT setup is now wrapped too. Observability must never be able to stop the controller. - MQTT discovery is published from on_connect: paho silently drops QoS-0 publishes issued before the CONNACK, so the previous code announced nothing while logging "MQTT connected". - Repeated failures now log once a minute. Six warnings a second rolled the log buffer and destroyed the startup diagnostics needed to find the 401. - auto_start could never fire, because the store's defaults always supplied auto: False for the fallback to find. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016NckgXecasQb2eSsPYNSW6
This commit is contained in:
@@ -384,13 +384,45 @@ async def amain() -> None:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
hass = HomeAssistant(session)
|
||||
|
||||
broker = await hass.mqtt_service()
|
||||
pub = MqttPublisher(
|
||||
broker.get("host") if broker else None,
|
||||
broker.get("port", 1883) if broker else 1883,
|
||||
broker.get("username") if broker else None,
|
||||
broker.get("password") if broker else None,
|
||||
)
|
||||
# Startup self-check: prove we can actually reach the Core API before
|
||||
# anything tries to control an inverter with it. A 401 here is a
|
||||
# permissions/token problem, not a configuration mistake, and saying so
|
||||
# explicitly saves an installer from re-checking entity ids for an hour.
|
||||
import os as _os
|
||||
_tok = _os.environ.get("SUPERVISOR_TOKEN", "")
|
||||
_LOG.info("supervisor token: %s (%d chars); env has: %s",
|
||||
"present" if _tok else "MISSING", len(_tok),
|
||||
",".join(sorted(k for k in _os.environ if "TOKEN" in k.upper())) or "none")
|
||||
try:
|
||||
async with session.get("http://supervisor/core/api/",
|
||||
headers={"Authorization": f"Bearer {_tok}"},
|
||||
timeout=10) as _r:
|
||||
_LOG.info("core api probe: HTTP %s %s", _r.status, (await _r.text())[:80])
|
||||
except Exception as _e: # noqa: BLE001
|
||||
_LOG.error("core api probe failed: %s", _e)
|
||||
|
||||
# ⚠️ Status publishing must NEVER be able to stop the controller. A
|
||||
# broken broker, a missing library, an API change in paho - all of it is
|
||||
# observability, and the battery does not care. Caught broadly and on
|
||||
# purpose: this crashed the add-on once already (paho 1.x vs 2.x) and
|
||||
# took the control loop down with it.
|
||||
try:
|
||||
broker = await hass.mqtt_service()
|
||||
pub = MqttPublisher(
|
||||
broker.get("host") if broker else None,
|
||||
broker.get("port", 1883) if broker else 1883,
|
||||
broker.get("username") if broker else None,
|
||||
broker.get("password") if broker else None,
|
||||
)
|
||||
except Exception as err: # noqa: BLE001
|
||||
_LOG.warning("MQTT unavailable (%s) - continuing without status entities", err)
|
||||
|
||||
class _NoMqtt:
|
||||
enabled = False
|
||||
def publish(self, *a, **k): pass
|
||||
def close(self): pass
|
||||
|
||||
pub = _NoMqtt()
|
||||
|
||||
controller = Controller(opts, hass, store, pub)
|
||||
runner = await web.start(controller, port=8099)
|
||||
|
||||
Reference in New Issue
Block a user