Add support for Ohmpilots to Fronius integration (#60765)

* add support for Fronius Ohmpilot

* disable the debugger
This commit is contained in:
Matthias Alphart 2021-12-02 11:05:22 +01:00 committed by GitHub
parent da2fb17d94
commit f2f6602890
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 108 additions and 2 deletions

View file

@ -22,6 +22,7 @@ from .coordinator import (
FroniusInverterUpdateCoordinator,
FroniusLoggerUpdateCoordinator,
FroniusMeterUpdateCoordinator,
FroniusOhmpilotUpdateCoordinator,
FroniusPowerFlowUpdateCoordinator,
FroniusStorageUpdateCoordinator,
)
@ -83,6 +84,7 @@ class FroniusSolarNet:
self.inverter_coordinators: list[FroniusInverterUpdateCoordinator] = []
self.logger_coordinator: FroniusLoggerUpdateCoordinator | None = None
self.meter_coordinator: FroniusMeterUpdateCoordinator | None = None
self.ohmpilot_coordinator: FroniusOhmpilotUpdateCoordinator | None = None
self.power_flow_coordinator: FroniusPowerFlowUpdateCoordinator | 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(
FroniusPowerFlowUpdateCoordinator(
hass=self.hass,

View file

@ -22,6 +22,7 @@ from .sensor import (
INVERTER_ENTITY_DESCRIPTIONS,
LOGGER_ENTITY_DESCRIPTIONS,
METER_ENTITY_DESCRIPTIONS,
OHMPILOT_ENTITY_DESCRIPTIONS,
POWER_FLOW_ENTITY_DESCRIPTIONS,
STORAGE_ENTITY_DESCRIPTIONS,
)
@ -158,6 +159,19 @@ class FroniusMeterUpdateCoordinator(FroniusCoordinatorBase):
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):
"""Query Fronius power flow endpoint and keep track of seen conditions."""

View file

@ -52,6 +52,7 @@ if TYPE_CHECKING:
FroniusInverterUpdateCoordinator,
FroniusLoggerUpdateCoordinator,
FroniusMeterUpdateCoordinator,
FroniusOhmpilotUpdateCoordinator,
FroniusPowerFlowUpdateCoordinator,
FroniusStorageUpdateCoordinator,
)
@ -110,6 +111,10 @@ async def async_setup_entry(
solar_net.meter_coordinator.add_entities_for_seen_keys(
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:
solar_net.power_flow_coordinator.add_entities_for_seen_keys(
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] = [
SensorEntityDescription(
key="energy_day",
@ -760,6 +804,33 @@ class MeterSensor(_FroniusSensorEntity):
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):
"""Defines a Fronius power flow sensor entity."""

View file

@ -373,11 +373,11 @@ async def test_gen24_storage(hass, aioclient_mock):
mock_responses(aioclient_mock, fixture_set="gen24_storage")
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(
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
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)
@ -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.power_apparent_fronius_meter_0_http_fronius", 821.9)
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
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)