M6-T08: add energy_cost expose provider + post-billing state publish

- expose.py: _energy_cost_provider yields buy/sell_price_now + import_cost_total
  /export_revenue_total (total_increasing, monetary), value_getters read from
  energy_cost_period; 2-element identifiers so the existing HA Discovery builder
  (which indexes identifiers[1]) works. Other providers/mechanism untouched.
- main.py: energy-cost job calls publish_states after computing periods (no-op
  when MQTT/Discovery off). Tests added.
Note: energy-cost sensors lack an availability heartbeat (ha_discovery mechanism
limitation, out of scope here).
This commit is contained in:
2026-06-23 22:44:41 +02:00
parent d35ac7d752
commit c61fc2d4ba
5 changed files with 1040 additions and 6 deletions
+18 -5
View File
@@ -203,16 +203,29 @@ def test_register_provider_direct_call():
def test_build_catalog_empty_with_no_devices(expose_db):
"""build_catalog with no enabled devices must return an empty list."""
"""build_catalog with no enabled modbus devices must contain no modbus entities.
The energy_cost provider is always registered and always produces its 4 entities
regardless of device state, so the catalog will not be empty. This test checks
that no *modbus* entities are present when there are no enabled modbus devices.
"""
from app.integrations.expose import build_catalog
with Session(expose_db) as session:
catalog = build_catalog(session)
# The modbus provider will find no enabled devices; other providers may
# add entries only if registered. Since we only register the modbus
# provider at module load, the result should be empty.
assert catalog == []
# The modbus provider finds no enabled devices → no modbus entities.
# The energy_cost provider always produces 4 entities, so the catalog is non-empty.
modbus_entities = [e for e in catalog if e.entity.key.startswith("modbus.")]
assert modbus_entities == [], (
"Expected no modbus entities when no modbus devices are enabled"
)
# The 4 energy_cost entities should always be present.
energy_keys = {e.entity.key for e in catalog if e.entity.key.startswith("energy.")}
assert len(energy_keys) == 4, (
f"Expected exactly 4 energy_cost entities, got {energy_keys!r}"
)
def test_build_catalog_produces_entities_for_enabled_device(expose_db):