Add support for Ohmpilots to Fronius integration (#60765)
* add support for Fronius Ohmpilot * disable the debugger
This commit is contained in:
parent
da2fb17d94
commit
f2f6602890
4 changed files with 108 additions and 2 deletions
|
@ -22,6 +22,7 @@ from .coordinator import (
|
||||||
FroniusInverterUpdateCoordinator,
|
FroniusInverterUpdateCoordinator,
|
||||||
FroniusLoggerUpdateCoordinator,
|
FroniusLoggerUpdateCoordinator,
|
||||||
FroniusMeterUpdateCoordinator,
|
FroniusMeterUpdateCoordinator,
|
||||||
|
FroniusOhmpilotUpdateCoordinator,
|
||||||
FroniusPowerFlowUpdateCoordinator,
|
FroniusPowerFlowUpdateCoordinator,
|
||||||
FroniusStorageUpdateCoordinator,
|
FroniusStorageUpdateCoordinator,
|
||||||
)
|
)
|
||||||
|
@ -83,6 +84,7 @@ class FroniusSolarNet:
|
||||||
self.inverter_coordinators: list[FroniusInverterUpdateCoordinator] = []
|
self.inverter_coordinators: list[FroniusInverterUpdateCoordinator] = []
|
||||||
self.logger_coordinator: FroniusLoggerUpdateCoordinator | None = None
|
self.logger_coordinator: FroniusLoggerUpdateCoordinator | None = None
|
||||||
self.meter_coordinator: FroniusMeterUpdateCoordinator | None = None
|
self.meter_coordinator: FroniusMeterUpdateCoordinator | None = None
|
||||||
|
self.ohmpilot_coordinator: FroniusOhmpilotUpdateCoordinator | None = None
|
||||||
self.power_flow_coordinator: FroniusPowerFlowUpdateCoordinator | None = None
|
self.power_flow_coordinator: FroniusPowerFlowUpdateCoordinator | None = None
|
||||||
self.storage_coordinator: FroniusStorageUpdateCoordinator | None = None
|
self.storage_coordinator: FroniusStorageUpdateCoordinator | None = None
|
||||||
|
|
||||||
|
@ -121,6 +123,15 @@ class FroniusSolarNet:
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.ohmpilot_coordinator = await self._init_optional_coordinator(
|
||||||
|
FroniusOhmpilotUpdateCoordinator(
|
||||||
|
hass=self.hass,
|
||||||
|
solar_net=self,
|
||||||
|
logger=_LOGGER,
|
||||||
|
name=f"{DOMAIN}_ohmpilot_{self.host}",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
self.power_flow_coordinator = await self._init_optional_coordinator(
|
self.power_flow_coordinator = await self._init_optional_coordinator(
|
||||||
FroniusPowerFlowUpdateCoordinator(
|
FroniusPowerFlowUpdateCoordinator(
|
||||||
hass=self.hass,
|
hass=self.hass,
|
||||||
|
|
|
@ -22,6 +22,7 @@ from .sensor import (
|
||||||
INVERTER_ENTITY_DESCRIPTIONS,
|
INVERTER_ENTITY_DESCRIPTIONS,
|
||||||
LOGGER_ENTITY_DESCRIPTIONS,
|
LOGGER_ENTITY_DESCRIPTIONS,
|
||||||
METER_ENTITY_DESCRIPTIONS,
|
METER_ENTITY_DESCRIPTIONS,
|
||||||
|
OHMPILOT_ENTITY_DESCRIPTIONS,
|
||||||
POWER_FLOW_ENTITY_DESCRIPTIONS,
|
POWER_FLOW_ENTITY_DESCRIPTIONS,
|
||||||
STORAGE_ENTITY_DESCRIPTIONS,
|
STORAGE_ENTITY_DESCRIPTIONS,
|
||||||
)
|
)
|
||||||
|
@ -158,6 +159,19 @@ class FroniusMeterUpdateCoordinator(FroniusCoordinatorBase):
|
||||||
return data["meters"] # type: ignore[no-any-return]
|
return data["meters"] # type: ignore[no-any-return]
|
||||||
|
|
||||||
|
|
||||||
|
class FroniusOhmpilotUpdateCoordinator(FroniusCoordinatorBase):
|
||||||
|
"""Query Fronius Ohmpilots and keep track of seen conditions."""
|
||||||
|
|
||||||
|
default_interval = timedelta(minutes=1)
|
||||||
|
error_interval = timedelta(minutes=10)
|
||||||
|
valid_descriptions = OHMPILOT_ENTITY_DESCRIPTIONS
|
||||||
|
|
||||||
|
async def _update_method(self) -> dict[SolarNetId, Any]:
|
||||||
|
"""Return data per solar net id from pyfronius."""
|
||||||
|
data = await self.solar_net.fronius.current_system_ohmpilot_data()
|
||||||
|
return data["ohmpilots"] # type: ignore[no-any-return]
|
||||||
|
|
||||||
|
|
||||||
class FroniusPowerFlowUpdateCoordinator(FroniusCoordinatorBase):
|
class FroniusPowerFlowUpdateCoordinator(FroniusCoordinatorBase):
|
||||||
"""Query Fronius power flow endpoint and keep track of seen conditions."""
|
"""Query Fronius power flow endpoint and keep track of seen conditions."""
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@ if TYPE_CHECKING:
|
||||||
FroniusInverterUpdateCoordinator,
|
FroniusInverterUpdateCoordinator,
|
||||||
FroniusLoggerUpdateCoordinator,
|
FroniusLoggerUpdateCoordinator,
|
||||||
FroniusMeterUpdateCoordinator,
|
FroniusMeterUpdateCoordinator,
|
||||||
|
FroniusOhmpilotUpdateCoordinator,
|
||||||
FroniusPowerFlowUpdateCoordinator,
|
FroniusPowerFlowUpdateCoordinator,
|
||||||
FroniusStorageUpdateCoordinator,
|
FroniusStorageUpdateCoordinator,
|
||||||
)
|
)
|
||||||
|
@ -110,6 +111,10 @@ async def async_setup_entry(
|
||||||
solar_net.meter_coordinator.add_entities_for_seen_keys(
|
solar_net.meter_coordinator.add_entities_for_seen_keys(
|
||||||
async_add_entities, MeterSensor
|
async_add_entities, MeterSensor
|
||||||
)
|
)
|
||||||
|
if solar_net.ohmpilot_coordinator is not None:
|
||||||
|
solar_net.ohmpilot_coordinator.add_entities_for_seen_keys(
|
||||||
|
async_add_entities, OhmpilotSensor
|
||||||
|
)
|
||||||
if solar_net.power_flow_coordinator is not None:
|
if solar_net.power_flow_coordinator is not None:
|
||||||
solar_net.power_flow_coordinator.add_entities_for_seen_keys(
|
solar_net.power_flow_coordinator.add_entities_for_seen_keys(
|
||||||
async_add_entities, PowerFlowSensor
|
async_add_entities, PowerFlowSensor
|
||||||
|
@ -510,6 +515,45 @@ METER_ENTITY_DESCRIPTIONS: list[SensorEntityDescription] = [
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
OHMPILOT_ENTITY_DESCRIPTIONS: list[SensorEntityDescription] = [
|
||||||
|
SensorEntityDescription(
|
||||||
|
key="energy_real_ac_consumed",
|
||||||
|
name="Energy consumed",
|
||||||
|
native_unit_of_measurement=ENERGY_WATT_HOUR,
|
||||||
|
device_class=DEVICE_CLASS_ENERGY,
|
||||||
|
state_class=STATE_CLASS_TOTAL_INCREASING,
|
||||||
|
),
|
||||||
|
SensorEntityDescription(
|
||||||
|
key="power_real_ac",
|
||||||
|
name="Power",
|
||||||
|
native_unit_of_measurement=POWER_WATT,
|
||||||
|
device_class=DEVICE_CLASS_POWER,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
SensorEntityDescription(
|
||||||
|
key="temperature_channel_1",
|
||||||
|
name="Temperature Channel 1",
|
||||||
|
native_unit_of_measurement=TEMP_CELSIUS,
|
||||||
|
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
SensorEntityDescription(
|
||||||
|
key="error_code",
|
||||||
|
name="Error code",
|
||||||
|
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
||||||
|
),
|
||||||
|
SensorEntityDescription(
|
||||||
|
key="state_code",
|
||||||
|
name="State code",
|
||||||
|
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
||||||
|
),
|
||||||
|
SensorEntityDescription(
|
||||||
|
key="state_message",
|
||||||
|
name="State message",
|
||||||
|
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
POWER_FLOW_ENTITY_DESCRIPTIONS: list[SensorEntityDescription] = [
|
POWER_FLOW_ENTITY_DESCRIPTIONS: list[SensorEntityDescription] = [
|
||||||
SensorEntityDescription(
|
SensorEntityDescription(
|
||||||
key="energy_day",
|
key="energy_day",
|
||||||
|
@ -760,6 +804,33 @@ class MeterSensor(_FroniusSensorEntity):
|
||||||
self._attr_unique_id = f'{meter_data["serial"]["value"]}-{key}'
|
self._attr_unique_id = f'{meter_data["serial"]["value"]}-{key}'
|
||||||
|
|
||||||
|
|
||||||
|
class OhmpilotSensor(_FroniusSensorEntity):
|
||||||
|
"""Defines a Fronius Ohmpilot sensor entity."""
|
||||||
|
|
||||||
|
entity_descriptions = OHMPILOT_ENTITY_DESCRIPTIONS
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
coordinator: FroniusOhmpilotUpdateCoordinator,
|
||||||
|
key: str,
|
||||||
|
solar_net_id: str,
|
||||||
|
) -> None:
|
||||||
|
"""Set up an individual Fronius meter sensor."""
|
||||||
|
self._entity_id_prefix = f"ohmpilot_{solar_net_id}"
|
||||||
|
super().__init__(coordinator, key, solar_net_id)
|
||||||
|
device_data = self._device_data()
|
||||||
|
|
||||||
|
self._attr_device_info = DeviceInfo(
|
||||||
|
identifiers={(DOMAIN, device_data["serial"]["value"])},
|
||||||
|
manufacturer=device_data["manufacturer"]["value"],
|
||||||
|
model=f"{device_data['model']['value']} {device_data['hardware']['value']}",
|
||||||
|
name=device_data["model"]["value"],
|
||||||
|
sw_version=device_data["software"]["value"],
|
||||||
|
via_device=(DOMAIN, coordinator.solar_net.solar_net_device_id),
|
||||||
|
)
|
||||||
|
self._attr_unique_id = f'{device_data["serial"]["value"]}-{key}'
|
||||||
|
|
||||||
|
|
||||||
class PowerFlowSensor(_FroniusSensorEntity):
|
class PowerFlowSensor(_FroniusSensorEntity):
|
||||||
"""Defines a Fronius power flow sensor entity."""
|
"""Defines a Fronius power flow sensor entity."""
|
||||||
|
|
||||||
|
|
|
@ -373,11 +373,11 @@ async def test_gen24_storage(hass, aioclient_mock):
|
||||||
mock_responses(aioclient_mock, fixture_set="gen24_storage")
|
mock_responses(aioclient_mock, fixture_set="gen24_storage")
|
||||||
config_entry = await setup_fronius_integration(hass, is_logger=False)
|
config_entry = await setup_fronius_integration(hass, is_logger=False)
|
||||||
|
|
||||||
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 31
|
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 36
|
||||||
await enable_all_entities(
|
await enable_all_entities(
|
||||||
hass, config_entry.entry_id, FroniusMeterUpdateCoordinator.default_interval
|
hass, config_entry.entry_id, FroniusMeterUpdateCoordinator.default_interval
|
||||||
)
|
)
|
||||||
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 63
|
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 68
|
||||||
# inverter 1
|
# inverter 1
|
||||||
assert_state("sensor.current_dc_fronius_inverter_1_http_fronius", 0.3952)
|
assert_state("sensor.current_dc_fronius_inverter_1_http_fronius", 0.3952)
|
||||||
assert_state("sensor.voltage_dc_2_fronius_inverter_1_http_fronius", 318.8103)
|
assert_state("sensor.voltage_dc_2_fronius_inverter_1_http_fronius", 318.8103)
|
||||||
|
@ -437,6 +437,16 @@ async def test_gen24_storage(hass, aioclient_mock):
|
||||||
assert_state("sensor.voltage_ac_phase_3_fronius_meter_0_http_fronius", 228.3)
|
assert_state("sensor.voltage_ac_phase_3_fronius_meter_0_http_fronius", 228.3)
|
||||||
assert_state("sensor.power_apparent_fronius_meter_0_http_fronius", 821.9)
|
assert_state("sensor.power_apparent_fronius_meter_0_http_fronius", 821.9)
|
||||||
assert_state("sensor.power_apparent_phase_3_fronius_meter_0_http_fronius", 118.4)
|
assert_state("sensor.power_apparent_phase_3_fronius_meter_0_http_fronius", 118.4)
|
||||||
|
# ohmpilot
|
||||||
|
assert_state(
|
||||||
|
"sensor.energy_real_ac_consumed_fronius_ohmpilot_0_http_fronius", 1233295.0
|
||||||
|
)
|
||||||
|
assert_state("sensor.power_real_ac_fronius_ohmpilot_0_http_fronius", 0.0)
|
||||||
|
assert_state("sensor.temperature_channel_1_fronius_ohmpilot_0_http_fronius", 38.9)
|
||||||
|
assert_state("sensor.state_code_fronius_ohmpilot_0_http_fronius", 0.0)
|
||||||
|
assert_state(
|
||||||
|
"sensor.state_message_fronius_ohmpilot_0_http_fronius", "Up and running"
|
||||||
|
)
|
||||||
# power_flow
|
# power_flow
|
||||||
assert_state("sensor.power_grid_fronius_power_flow_0_http_fronius", 2274.9)
|
assert_state("sensor.power_grid_fronius_power_flow_0_http_fronius", 2274.9)
|
||||||
assert_state("sensor.power_battery_fronius_power_flow_0_http_fronius", 0.1591)
|
assert_state("sensor.power_battery_fronius_power_flow_0_http_fronius", 0.1591)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue