From 774ab06206fbf003cbfe3893599d0b44172dbd97 Mon Sep 17 00:00:00 2001 From: NANI Date: Thu, 23 Oct 2025 19:25:10 +0200 Subject: [PATCH] Add energy platform to Victron Remote Monitoring (#155046) --- .../victron_remote_monitoring/energy.py | 21 +++++++++ .../victron_remote_monitoring/test_energy.py | 44 +++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 homeassistant/components/victron_remote_monitoring/energy.py create mode 100644 tests/components/victron_remote_monitoring/test_energy.py diff --git a/homeassistant/components/victron_remote_monitoring/energy.py b/homeassistant/components/victron_remote_monitoring/energy.py new file mode 100644 index 00000000000..b3209703115 --- /dev/null +++ b/homeassistant/components/victron_remote_monitoring/energy.py @@ -0,0 +1,21 @@ +"""Victron Remote Monitoring energy platform.""" + +from __future__ import annotations + +from homeassistant.config_entries import ConfigEntryState +from homeassistant.core import HomeAssistant + + +async def async_get_solar_forecast( + hass: HomeAssistant, config_entry_id: str +) -> dict[str, dict[str, float | int]] | None: + """Get solar forecast for a config entry ID.""" + if ( + entry := hass.config_entries.async_get_entry(config_entry_id) + ) is None or entry.state != ConfigEntryState.LOADED: + return None + data = entry.runtime_data.data.solar + if data is None: + return None + + return {"wh_hours": data.get_dict_isoformat} diff --git a/tests/components/victron_remote_monitoring/test_energy.py b/tests/components/victron_remote_monitoring/test_energy.py new file mode 100644 index 00000000000..0eab17cdece --- /dev/null +++ b/tests/components/victron_remote_monitoring/test_energy.py @@ -0,0 +1,44 @@ +"""Test the Victron Remote Monitoring energy platform.""" + +from homeassistant.components.victron_remote_monitoring import energy +from homeassistant.config_entries import ConfigEntryState +from homeassistant.core import HomeAssistant + +from tests.common import MockConfigEntry + + +async def test_energy_solar_forecast( + hass: HomeAssistant, init_integration: MockConfigEntry +) -> None: + """Test fetching the solar forecast for the energy dashboard.""" + config_entry = init_integration + + assert config_entry.state is ConfigEntryState.LOADED + + assert await energy.async_get_solar_forecast(hass, config_entry.entry_id) == { + "wh_hours": { + "2025-04-23T10:00:00+00:00": 5050.1, + "2025-04-23T11:00:00+00:00": 5000.2, + "2025-04-24T10:00:00+00:00": 2250.3, + "2025-04-24T11:00:00+00:00": 2000.4, + "2025-04-25T10:00:00+00:00": 1000.5, + "2025-04-25T11:00:00+00:00": 500.6, + } + } + + +async def test_energy_missing_entry(hass: HomeAssistant) -> None: + """Return None when config entry cannot be found.""" + assert await energy.async_get_solar_forecast(hass, "missing") is None + + +async def test_energy_no_solar_data( + hass: HomeAssistant, init_integration: MockConfigEntry +) -> None: + """Return None when the coordinator has no solar forecast data.""" + config_entry = init_integration + assert config_entry.state is ConfigEntryState.LOADED + + config_entry.runtime_data.data.solar = None + + assert await energy.async_get_solar_forecast(hass, config_entry.entry_id) is None