EV řízení: zápis Amps-to-use přes journal + watchdog + okamžitý replan po příjezdu
Bod 1 — write_ev_setpoints reálně (konec TODO stubu):
- reg 15 (0=stop, 6–32 A) z plánu přes _current_limit_for_charger; plná
journal pipeline (create_modbus_commands → execute, verify job 2 min generic)
- watchdog reg 19=300 s + reg 20=8 A: výpadek EMS → wallbox po 5 min failsafe
8 A (auto se přes noc nabije); drop-unchanged → zapisuje se jen při změně
- fn_modbus_last_verified_map: + p_asset_type (drop 2-arg; dosud hardcoded
'inverter' — pro chargery vracela {})
- verify: SELF_SUSTAIN fallback explicitně jen pro asset_type='inverter' —
mismatch wallboxu nesmí degradovat režim celé site
- journal register_name: mimo inverter platí jméno od volajícího
Bod 2 — telemetry_collector: přechod available→connected spustí fire-and-forget
run_rolling_replan(triggered_by=ev_arrival:<code>) + export_setpoints přes BG
pool — reakce na příjezd ~60 s místo až 15 min.
Bod 3 (Tesla API SoC) čeká na developer credentials.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -46,8 +46,12 @@ async def _fetch_written_deye_clock_commands(
|
||||
return list(rows)
|
||||
|
||||
|
||||
async def _fetch_last_verified_inverter_registers(
|
||||
site_id: int, inverter_asset_id: int, db: asyncpg.Connection
|
||||
async def _fetch_last_verified_registers(
|
||||
site_id: int,
|
||||
asset_id: int,
|
||||
db: asyncpg.Connection,
|
||||
*,
|
||||
asset_type: str = "inverter",
|
||||
) -> dict[int, int]:
|
||||
"""
|
||||
Poslední hodnota na zařízení podle journalu (jen status verified).
|
||||
@@ -55,15 +59,25 @@ async def _fetch_last_verified_inverter_registers(
|
||||
"""
|
||||
raw = await db.fetchval(
|
||||
"""
|
||||
select ems.fn_modbus_last_verified_map($1::int, $2::int)
|
||||
select ems.fn_modbus_last_verified_map($1::int, $2::int, $3::text)
|
||||
""",
|
||||
site_id,
|
||||
inverter_asset_id,
|
||||
asset_id,
|
||||
asset_type,
|
||||
)
|
||||
data = raw if isinstance(raw, dict) else json.loads(raw)
|
||||
return {int(k): int(v) for k, v in data.items()}
|
||||
|
||||
|
||||
async def _fetch_last_verified_inverter_registers(
|
||||
site_id: int, inverter_asset_id: int, db: asyncpg.Connection
|
||||
) -> dict[int, int]:
|
||||
"""Zpětně kompatibilní alias (Deye cesty)."""
|
||||
return await _fetch_last_verified_registers(
|
||||
site_id, inverter_asset_id, db, asset_type="inverter"
|
||||
)
|
||||
|
||||
|
||||
def _drop_registers_matching_last_verified(
|
||||
registers: list[tuple[int, str, int]],
|
||||
last_verified: dict[int, int],
|
||||
@@ -102,8 +116,14 @@ async def create_modbus_commands(
|
||||
Vrátí list command IDs.
|
||||
"""
|
||||
ids: list[int] = []
|
||||
for reg, _ignored_name, val in registers:
|
||||
register_name = DEYE_REGISTER_NAMES.get(reg, f"reg_{reg}")
|
||||
for reg, given_name, val in registers:
|
||||
# Deye registry mají kanonická jména; pro ostatní zařízení (Teltonika…)
|
||||
# platí jméno dodané volajícím.
|
||||
register_name = (
|
||||
DEYE_REGISTER_NAMES.get(reg)
|
||||
if asset_type == "inverter"
|
||||
else None
|
||||
) or given_name or f"reg_{reg}"
|
||||
cmd_id = await db.fetchval(
|
||||
"""
|
||||
INSERT INTO ems.modbus_command
|
||||
|
||||
Reference in New Issue
Block a user