Implement telemetry enhancements: add reading of Deye registers 145 and 179 in telemetry collector to derive is_export_limited and pv_derating_flags. Update fn_telemetry_inverter_sample to store these flags, and adjust related documentation and API endpoints accordingly.
This commit is contained in:
@@ -28,6 +28,9 @@ DEYE_REG_GRID_EXPORT_TOTAL_LO = 524
|
||||
DEYE_REG_GRID_EXPORT_TOTAL_HI = 525
|
||||
DEYE_REG_PV1_POWER = 672
|
||||
DEYE_REG_PV2_POWER = 673
|
||||
# Solar sell (0 = přebytek řiditelné FVE nesmí do sítě) a GEN/MI cut-off (bits0–1 == 2 → cut-off ON); viz modbus-registers.md
|
||||
DEYE_REG_SOLAR_SELL = 145
|
||||
DEYE_REG_CONTROL_BOARD_SPECIAL1 = 179
|
||||
|
||||
|
||||
def aggregate_pv_production_w(pv1_w: int, pv2_w: int, gen_port_w: int) -> int:
|
||||
@@ -38,6 +41,18 @@ def aggregate_pv_production_w(pv1_w: int, pv2_w: int, gen_port_w: int) -> int:
|
||||
return max(0, int(pv1_w)) + max(0, int(pv2_w)) + max(0, int(gen_port_w))
|
||||
|
||||
|
||||
def _export_limit_flags_from_deye_regs(reg145: int | None, reg179: int | None) -> tuple[bool | None, int | None]:
|
||||
"""Odvoď is_export_limited / pv_derating_flags z přečtených holding registrů (NULL = neznámé)."""
|
||||
if reg145 is None and reg179 is None:
|
||||
return None, None
|
||||
flags = 0
|
||||
if reg145 is not None and int(reg145) == 0:
|
||||
flags |= 1
|
||||
if reg179 is not None and (int(reg179) & 3) == 2:
|
||||
flags |= 2
|
||||
return (flags != 0), flags
|
||||
|
||||
|
||||
async def poll_inverter(site_id: int, db: asyncpg.Connection) -> None:
|
||||
rows = await db.fetch(
|
||||
"""
|
||||
@@ -70,14 +85,17 @@ async def poll_inverter(site_id: int, db: asyncpg.Connection) -> None:
|
||||
grid_energy_regs = await mb.read_holding_registers(
|
||||
DEYE_REG_GRID_IMPORT_TOTAL_LO, 4
|
||||
)
|
||||
reg145 = await mb.read_register(DEYE_REG_SOLAR_SELL)
|
||||
reg179 = await mb.read_register(DEYE_REG_CONTROL_BOARD_SPECIAL1)
|
||||
pv_power_w = aggregate_pv_production_w(pv1_power, pv2_power, gen_port_power)
|
||||
grid_import_total_wh = (grid_energy_regs[1] << 16 | grid_energy_regs[0]) * 100
|
||||
grid_export_total_wh = (grid_energy_regs[3] << 16 | grid_energy_regs[2]) * 100
|
||||
is_export_limited, pv_derating_flags = _export_limit_flags_from_deye_regs(reg145, reg179)
|
||||
|
||||
logger.debug("inverter:%s Deye run_state raw=%s", code, run_state)
|
||||
|
||||
await db.execute(
|
||||
"select ems.fn_telemetry_inverter_sample($1::int, $2::int, $3::timestamptz, $4::int, $5::int, $6::int, $7::int, $8::float8, $9::int, $10::int, $11::int, $12::int, $13::int, $14::bigint, $15::bigint, $16::int)",
|
||||
"select ems.fn_telemetry_inverter_sample($1::int, $2::int, $3::timestamptz, $4::int, $5::int, $6::int, $7::int, $8::float8, $9::int, $10::int, $11::int, $12::int, $13::int, $14::bigint, $15::bigint, $16::int, $17::boolean, $18::int)",
|
||||
site_id,
|
||||
inv_id,
|
||||
measured_at,
|
||||
@@ -94,6 +112,8 @@ async def poll_inverter(site_id: int, db: asyncpg.Connection) -> None:
|
||||
grid_import_total_wh,
|
||||
grid_export_total_wh,
|
||||
run_state,
|
||||
is_export_limited,
|
||||
pv_derating_flags,
|
||||
)
|
||||
inv_temp: float | None = None
|
||||
await manager.broadcast_telemetry(
|
||||
@@ -108,6 +128,8 @@ async def poll_inverter(site_id: int, db: asyncpg.Connection) -> None:
|
||||
"load_power_w": load_power,
|
||||
"gen_port_power_w": gen_port_power,
|
||||
"inverter_temp_c": inv_temp,
|
||||
"is_export_limited": is_export_limited,
|
||||
"pv_derating_flags": pv_derating_flags,
|
||||
}
|
||||
)
|
||||
except Exception as e:
|
||||
|
||||
Reference in New Issue
Block a user