MAINT-20 part 2 r2: app/main.py comments, lines 6001-6185 (amain .. main)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude
parent
40ef27c367
commit
f5714248f6
@@ -6021,7 +6021,8 @@ async def amain() -> None:
|
||||
hass = HomeAssistant(session)
|
||||
|
||||
# Startup self-check: prove we can actually reach the Core API before
|
||||
# anything tries to control an inverter with it.
|
||||
# anything tries to control an inverter with it. A 401 here is a
|
||||
# permissions/token problem, not a configuration mistake.
|
||||
# (DECISIONS/MAIN-orchestration-archive.md)
|
||||
import os as _os
|
||||
_tok = _os.environ.get("SUPERVISOR_TOKEN", "")
|
||||
@@ -6037,13 +6038,14 @@ async def amain() -> None:
|
||||
_LOG.error("core api probe failed: %s", _e)
|
||||
|
||||
# UX-09: the Details link in every notification needs this add-on's
|
||||
# slug and Home Assistant's version (see messages.docs_url()).
|
||||
# (DECISIONS/MAIN-orchestration-archive.md)
|
||||
# slug and Home Assistant's version (see messages.docs_url()); both are
|
||||
# best effort. (DECISIONS/MAIN-orchestration-archive.md)
|
||||
messages.set_site(**await docs_link_facts(session, _tok))
|
||||
|
||||
# ⚠️ THE STARTUP GATE (CFG-01). Nothing below this line may run on a
|
||||
# configuration validate.py rejects - specs §1.5: a config the system
|
||||
# cannot honour is refused at startup, not survived at runtime.
|
||||
# configuration validate.py rejects (specs §1.5). It sits HERE, before
|
||||
# the broker, web server and any task; (None, None) from an ESPHome not
|
||||
# yet up is not a refusal (run_control() re-checks).
|
||||
# (DECISIONS/MAIN-orchestration-archive.md)
|
||||
# SMA-2: the flat options are the GoodWe driver's (no Controller yet).
|
||||
_sp = str(opts.get("setpoint_entity", "") or "").strip()
|
||||
@@ -6055,8 +6057,8 @@ async def amain() -> None:
|
||||
_problems = validate_startup_config(opts, _dev_min, _dev_max)
|
||||
# UX-15: a new install names no inverter. When that is the ONLY refusal
|
||||
# it serves the setup wizard in setup-only mode, which builds nothing
|
||||
# that commands and returns when stopped.
|
||||
# (DECISIONS/MAIN-orchestration-archive.md)
|
||||
# that commands and returns when stopped; any other refusal still exits
|
||||
# 78. DECISIONS/UX-15-setup-only-mode.md
|
||||
if _problems and setuponly.applies(opts, _problems):
|
||||
await setuponly.serve(
|
||||
opts, HomeAssistant(session, read_only=True), store,
|
||||
@@ -6066,9 +6068,9 @@ async def amain() -> None:
|
||||
refuse(_problems)
|
||||
raise ConfigRefused(_problems)
|
||||
|
||||
# ⚠️ 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.
|
||||
# ⚠️ Status publishing must NEVER be able to stop the controller:
|
||||
# caught broadly and on purpose (a paho 1.x/2.x change once crashed the
|
||||
# add-on and took the control loop with it).
|
||||
# (DECISIONS/MAIN-orchestration-archive.md)
|
||||
broker = None
|
||||
try:
|
||||
@@ -6084,9 +6086,12 @@ async def amain() -> None:
|
||||
omit=() if is_enabled(opts) else ("p1_age",),
|
||||
# TEL-11. ⚠️ THE SHIPPED PREDICATE, NOT A SECOND READING OF THE
|
||||
# OPTION - `Controller.publish()` gates the row on this same
|
||||
# call. (DECISIONS/MAIN-orchestration-archive.md)
|
||||
# call; an install with no PV roster announces exactly what it
|
||||
# did before. (DECISIONS/MAIN-orchestration-archive.md)
|
||||
include=optional_keys(opts),
|
||||
# TEL-07. ⚠️ THE NAMES, NOT A ROSTER.
|
||||
# TEL-07. ⚠️ THE NAMES, NOT A ROSTER: `build_roster()` here
|
||||
# would build a SECOND set of `Inverter`s off the Store;
|
||||
# `roster_names()` is the naming rule on its own.
|
||||
# (DECISIONS/MAIN-orchestration-archive.md)
|
||||
units=roster_names(opts),
|
||||
modes=_modes,
|
||||
@@ -6122,10 +6127,11 @@ async def amain() -> None:
|
||||
control_task_done, controller=controller, stop=stop, died=died))
|
||||
tasks = [control]
|
||||
|
||||
# OPT-04.
|
||||
# STARTED FOR A PROVIDER, FOR ARMED TRADING OR FOR BATTERY MODES: see
|
||||
# `tariff_refresh_wanted()` above and DECISIONS/TARIFF-10 and TARIFF-24
|
||||
# for why each term is there.
|
||||
# OPT-04. The tariff refresh runs as its OWN task (`resolve_tariff()`
|
||||
# may fetch over HTTPS, and the tick feeds the ESP32 heartbeat).
|
||||
# Started for a provider, armed trading or battery modes
|
||||
# (`tariff_refresh_wanted()`). ⚠️ IT DOES NOT ARM ANYTHING:
|
||||
# `arbitrage.enabled()` in cycle() is the only gate on trading.
|
||||
# (DECISIONS/MAIN-orchestration-archive.md)
|
||||
if tariff_refresh_wanted(opts):
|
||||
tasks.append(asyncio.create_task(controller.run_tariff_refresh()))
|
||||
@@ -6165,8 +6171,9 @@ def main() -> None:
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
except ConfigRefused:
|
||||
# ⚠️ No traceback, on purpose.
|
||||
# (DECISIONS/MAIN-orchestration-archive.md)
|
||||
# ⚠️ No traceback, on purpose: the banner refuse() printed says
|
||||
# everything. 78 is sysexits EX_CONFIG, so a script can tell a bad
|
||||
# config from a bug. (DECISIONS/MAIN-orchestration-archive.md)
|
||||
raise SystemExit(78)
|
||||
except ControlTaskDied:
|
||||
# No second traceback: control_task_done() logged it at the death.
|
||||
|
||||
Reference in New Issue
Block a user