mirror of
https://github.com/home-assistant/core.git
synced 2025-07-16 09:47:13 +00:00
Add support for ACB batteries to Enphase Envoy (#131298)
* Add support for ACB batteries to Enphase Envoy * Add tests for ACB battery support in ENphase Envoy * make acb state sensordeviceclass ENUM * Capitalize strings and use common idle
This commit is contained in:
parent
fab92d1cf8
commit
4c91d1b402
@ -10,6 +10,8 @@ from operator import attrgetter
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from pyenphase import (
|
||||
EnvoyACBPower,
|
||||
EnvoyBatteryAggregate,
|
||||
EnvoyEncharge,
|
||||
EnvoyEnchargeAggregate,
|
||||
EnvoyEnchargePower,
|
||||
@ -723,6 +725,78 @@ ENCHARGE_AGGREGATE_SENSORS = (
|
||||
)
|
||||
|
||||
|
||||
@dataclass(frozen=True, kw_only=True)
|
||||
class EnvoyAcbBatterySensorEntityDescription(SensorEntityDescription):
|
||||
"""Describes an Envoy ACB Battery sensor entity."""
|
||||
|
||||
value_fn: Callable[[EnvoyACBPower], int | str]
|
||||
|
||||
|
||||
ACB_BATTERY_POWER_SENSORS = (
|
||||
EnvoyAcbBatterySensorEntityDescription(
|
||||
key="acb_power",
|
||||
native_unit_of_measurement=UnitOfPower.WATT,
|
||||
device_class=SensorDeviceClass.POWER,
|
||||
value_fn=attrgetter("power"),
|
||||
),
|
||||
EnvoyAcbBatterySensorEntityDescription(
|
||||
key="acb_soc",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
device_class=SensorDeviceClass.BATTERY,
|
||||
value_fn=attrgetter("state_of_charge"),
|
||||
),
|
||||
EnvoyAcbBatterySensorEntityDescription(
|
||||
key="acb_battery_state",
|
||||
translation_key="acb_battery_state",
|
||||
device_class=SensorDeviceClass.ENUM,
|
||||
options=["discharging", "idle", "charging", "full"],
|
||||
value_fn=attrgetter("state"),
|
||||
),
|
||||
)
|
||||
|
||||
ACB_BATTERY_ENERGY_SENSORS = (
|
||||
EnvoyAcbBatterySensorEntityDescription(
|
||||
key="acb_available_energy",
|
||||
translation_key="acb_available_energy",
|
||||
native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
|
||||
device_class=SensorDeviceClass.ENERGY_STORAGE,
|
||||
value_fn=attrgetter("charge_wh"),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@dataclass(frozen=True, kw_only=True)
|
||||
class EnvoyAggregateBatterySensorEntityDescription(SensorEntityDescription):
|
||||
"""Describes an Envoy aggregate Ensemble and ACB Battery sensor entity."""
|
||||
|
||||
value_fn: Callable[[EnvoyBatteryAggregate], int]
|
||||
|
||||
|
||||
AGGREGATE_BATTERY_SENSORS = (
|
||||
EnvoyAggregateBatterySensorEntityDescription(
|
||||
key="aggregated_soc",
|
||||
translation_key="aggregated_soc",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
device_class=SensorDeviceClass.BATTERY,
|
||||
value_fn=attrgetter("state_of_charge"),
|
||||
),
|
||||
EnvoyAggregateBatterySensorEntityDescription(
|
||||
key="aggregated_available_energy",
|
||||
translation_key="aggregated_available_energy",
|
||||
native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
|
||||
device_class=SensorDeviceClass.ENERGY_STORAGE,
|
||||
value_fn=attrgetter("available_energy"),
|
||||
),
|
||||
EnvoyAggregateBatterySensorEntityDescription(
|
||||
key="aggregated_max_battery_capacity",
|
||||
translation_key="aggregated_max_capacity",
|
||||
native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
|
||||
device_class=SensorDeviceClass.ENERGY_STORAGE,
|
||||
value_fn=attrgetter("max_available_capacity"),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: EnphaseConfigEntry,
|
||||
@ -847,6 +921,20 @@ async def async_setup_entry(
|
||||
EnvoyEnpowerEntity(coordinator, description)
|
||||
for description in ENPOWER_SENSORS
|
||||
)
|
||||
if envoy_data.acb_power:
|
||||
entities.extend(
|
||||
EnvoyAcbBatteryPowerEntity(coordinator, description)
|
||||
for description in ACB_BATTERY_POWER_SENSORS
|
||||
)
|
||||
entities.extend(
|
||||
EnvoyAcbBatteryEnergyEntity(coordinator, description)
|
||||
for description in ACB_BATTERY_ENERGY_SENSORS
|
||||
)
|
||||
if envoy_data.battery_aggregate:
|
||||
entities.extend(
|
||||
AggregateBatteryEntity(coordinator, description)
|
||||
for description in AGGREGATE_BATTERY_SENSORS
|
||||
)
|
||||
|
||||
async_add_entities(entities)
|
||||
|
||||
@ -1228,3 +1316,60 @@ class EnvoyEnpowerEntity(EnvoySensorBaseEntity):
|
||||
enpower = self.data.enpower
|
||||
assert enpower is not None
|
||||
return self.entity_description.value_fn(enpower)
|
||||
|
||||
|
||||
class EnvoyAcbBatteryPowerEntity(EnvoySensorBaseEntity):
|
||||
"""Envoy ACB Battery power sensor entity."""
|
||||
|
||||
entity_description: EnvoyAcbBatterySensorEntityDescription
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: EnphaseUpdateCoordinator,
|
||||
description: EnvoyAcbBatterySensorEntityDescription,
|
||||
) -> None:
|
||||
"""Initialize ACB Battery entity."""
|
||||
super().__init__(coordinator, description)
|
||||
acb_data = self.data.acb_power
|
||||
assert acb_data is not None
|
||||
self._attr_unique_id = f"{self.envoy_serial_num}_{description.key}"
|
||||
self._attr_device_info = DeviceInfo(
|
||||
identifiers={(DOMAIN, f"{self.envoy_serial_num}_acb")},
|
||||
manufacturer="Enphase",
|
||||
model="ACB",
|
||||
name=f"ACB {self.envoy_serial_num}",
|
||||
via_device=(DOMAIN, self.envoy_serial_num),
|
||||
)
|
||||
|
||||
@property
|
||||
def native_value(self) -> int | str | None:
|
||||
"""Return the state of the ACB Battery power sensors."""
|
||||
acb = self.data.acb_power
|
||||
assert acb is not None
|
||||
return self.entity_description.value_fn(acb)
|
||||
|
||||
|
||||
class EnvoyAcbBatteryEnergyEntity(EnvoySystemSensorEntity):
|
||||
"""Envoy combined ACB and Ensemble Battery Aggregate energy sensor entity."""
|
||||
|
||||
entity_description: EnvoyAcbBatterySensorEntityDescription
|
||||
|
||||
@property
|
||||
def native_value(self) -> int | str:
|
||||
"""Return the state of the aggregate energy sensors."""
|
||||
acb = self.data.acb_power
|
||||
assert acb is not None
|
||||
return self.entity_description.value_fn(acb)
|
||||
|
||||
|
||||
class AggregateBatteryEntity(EnvoySystemSensorEntity):
|
||||
"""Envoy combined ACB and Ensemble Battery Aggregate sensor entity."""
|
||||
|
||||
entity_description: EnvoyAggregateBatterySensorEntityDescription
|
||||
|
||||
@property
|
||||
def native_value(self) -> int:
|
||||
"""Return the state of the aggregate sensors."""
|
||||
battery_aggregate = self.data.battery_aggregate
|
||||
assert battery_aggregate is not None
|
||||
return self.entity_description.value_fn(battery_aggregate)
|
||||
|
@ -337,6 +337,30 @@
|
||||
},
|
||||
"configured_reserve_soc": {
|
||||
"name": "Configured reserve battery level"
|
||||
},
|
||||
"acb_battery_state": {
|
||||
"name": "Battery state",
|
||||
"state": {
|
||||
"discharging": "Discharging",
|
||||
"idle": "[%key:common::state::idle%]",
|
||||
"charging": "Charging",
|
||||
"full": "Full"
|
||||
}
|
||||
},
|
||||
"acb_available_energy": {
|
||||
"name": "Available ACB battery energy"
|
||||
},
|
||||
"acb_max_capacity": {
|
||||
"name": "ACB Battery capacity"
|
||||
},
|
||||
"aggregated_available_energy": {
|
||||
"name": "Aggregated available battery energy"
|
||||
},
|
||||
"aggregated_max_capacity": {
|
||||
"name": "Aggregated Battery capacity"
|
||||
},
|
||||
"aggregated_soc": {
|
||||
"name": "Aggregated battery soc"
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
|
@ -6,6 +6,8 @@ from unittest.mock import AsyncMock, Mock, patch
|
||||
|
||||
import jwt
|
||||
from pyenphase import (
|
||||
EnvoyACBPower,
|
||||
EnvoyBatteryAggregate,
|
||||
EnvoyData,
|
||||
EnvoyEncharge,
|
||||
EnvoyEnchargeAggregate,
|
||||
@ -172,6 +174,8 @@ def _load_json_2_production_data(
|
||||
mocked_data.system_production_phases[sub_item] = EnvoySystemProduction(
|
||||
**item_data
|
||||
)
|
||||
if item := json_fixture["data"].get("acb_power"):
|
||||
mocked_data.acb_power = EnvoyACBPower(**item)
|
||||
|
||||
|
||||
def _load_json_2_meter_data(
|
||||
@ -245,6 +249,8 @@ def _load_json_2_encharge_enpower_data(
|
||||
mocked_data.dry_contact_settings[sub_item] = EnvoyDryContactSettings(
|
||||
**item_data
|
||||
)
|
||||
if item := json_fixture["data"].get("battery_aggregate"):
|
||||
mocked_data.battery_aggregate = EnvoyBatteryAggregate(**item)
|
||||
|
||||
|
||||
def _load_json_2_raw_data(mocked_data: EnvoyData, json_fixture: dict[str, Any]) -> None:
|
||||
|
274
tests/components/enphase_envoy/fixtures/envoy_acb_batt.json
Normal file
274
tests/components/enphase_envoy/fixtures/envoy_acb_batt.json
Normal file
@ -0,0 +1,274 @@
|
||||
{
|
||||
"serial_number": "1234",
|
||||
"firmware": "7.6.358",
|
||||
"part_number": "800-00654-r08",
|
||||
"envoy_model": "Envoy, phases: 3, phase mode: three, net-consumption CT, production CT",
|
||||
"supported_features": 1759,
|
||||
"phase_mode": "three",
|
||||
"phase_count": 3,
|
||||
"active_phase_count": 0,
|
||||
"ct_meter_count": 2,
|
||||
"consumption_meter_type": "net-consumption",
|
||||
"production_meter_type": "production",
|
||||
"storage_meter_type": null,
|
||||
"data": {
|
||||
"encharge_inventory": {
|
||||
"123456": {
|
||||
"admin_state": 6,
|
||||
"admin_state_str": "ENCHG_STATE_READY",
|
||||
"bmu_firmware_version": "2.1.16",
|
||||
"comm_level_2_4_ghz": 4,
|
||||
"comm_level_sub_ghz": 4,
|
||||
"communicating": true,
|
||||
"dc_switch_off": false,
|
||||
"encharge_capacity": 3500,
|
||||
"encharge_revision": 2,
|
||||
"firmware_loaded_date": 1714736645,
|
||||
"firmware_version": "2.6.6618_rel/22.11",
|
||||
"installed_date": 1714736645,
|
||||
"last_report_date": 1714804173,
|
||||
"led_status": 17,
|
||||
"max_cell_temp": 16,
|
||||
"operating": true,
|
||||
"part_number": "830-01760-r46",
|
||||
"percent_full": 54,
|
||||
"serial_number": "122327081322",
|
||||
"temperature": 16,
|
||||
"temperature_unit": "C",
|
||||
"zigbee_dongle_fw_version": "100F"
|
||||
}
|
||||
},
|
||||
"encharge_power": {
|
||||
"123456": {
|
||||
"apparent_power_mva": 105,
|
||||
"real_power_mw": 105,
|
||||
"soc": 54
|
||||
}
|
||||
},
|
||||
"encharge_aggregate": {
|
||||
"available_energy": 1890,
|
||||
"backup_reserve": 0,
|
||||
"state_of_charge": 54,
|
||||
"reserve_state_of_charge": 0,
|
||||
"configured_reserve_state_of_charge": 0,
|
||||
"max_available_capacity": 3500
|
||||
},
|
||||
"enpower": null,
|
||||
"acb_power": {
|
||||
"power": 260,
|
||||
"charge_wh": 930,
|
||||
"state_of_charge": 25,
|
||||
"state": "discharging",
|
||||
"batteries": 3
|
||||
},
|
||||
"battery_aggregate": {
|
||||
"available_energy": 2820,
|
||||
"state_of_charge": 39,
|
||||
"max_available_capacity": 7220
|
||||
},
|
||||
"system_consumption": {
|
||||
"watt_hours_lifetime": 1234,
|
||||
"watt_hours_last_7_days": 1234,
|
||||
"watt_hours_today": 1234,
|
||||
"watts_now": 1234
|
||||
},
|
||||
"system_production": {
|
||||
"watt_hours_lifetime": 1234,
|
||||
"watt_hours_last_7_days": 1234,
|
||||
"watt_hours_today": 1234,
|
||||
"watts_now": 1234
|
||||
},
|
||||
"system_consumption_phases": null,
|
||||
"system_production_phases": null,
|
||||
"system_net_consumption": {
|
||||
"watt_hours_lifetime": 4321,
|
||||
"watt_hours_last_7_days": -1,
|
||||
"watt_hours_today": -1,
|
||||
"watts_now": 2341
|
||||
},
|
||||
"system_net_consumption_phases": null,
|
||||
"ctmeter_production": {
|
||||
"eid": "100000010",
|
||||
"timestamp": 1708006110,
|
||||
"energy_delivered": 11234,
|
||||
"energy_received": 12345,
|
||||
"active_power": 100,
|
||||
"power_factor": 0.11,
|
||||
"voltage": 111,
|
||||
"current": 0.2,
|
||||
"frequency": 50.1,
|
||||
"state": "enabled",
|
||||
"measurement_type": "production",
|
||||
"metering_status": "normal",
|
||||
"status_flags": ["production-imbalance", "power-on-unused-phase"]
|
||||
},
|
||||
"ctmeter_consumption": {
|
||||
"eid": "100000020",
|
||||
"timestamp": 1708006120,
|
||||
"energy_delivered": 21234,
|
||||
"energy_received": 22345,
|
||||
"active_power": 101,
|
||||
"power_factor": 0.21,
|
||||
"voltage": 112,
|
||||
"current": 0.3,
|
||||
"frequency": 50.2,
|
||||
"state": "enabled",
|
||||
"measurement_type": "net-consumption",
|
||||
"metering_status": "normal",
|
||||
"status_flags": []
|
||||
},
|
||||
"ctmeter_storage": null,
|
||||
"ctmeter_production_phases": {
|
||||
"L1": {
|
||||
"eid": "100000011",
|
||||
"timestamp": 1708006111,
|
||||
"energy_delivered": 112341,
|
||||
"energy_received": 123451,
|
||||
"active_power": 20,
|
||||
"power_factor": 0.12,
|
||||
"voltage": 111,
|
||||
"current": 0.2,
|
||||
"frequency": 50.1,
|
||||
"state": "enabled",
|
||||
"measurement_type": "production",
|
||||
"metering_status": "normal",
|
||||
"status_flags": ["production-imbalance"]
|
||||
},
|
||||
"L2": {
|
||||
"eid": "100000012",
|
||||
"timestamp": 1708006112,
|
||||
"energy_delivered": 112342,
|
||||
"energy_received": 123452,
|
||||
"active_power": 30,
|
||||
"power_factor": 0.13,
|
||||
"voltage": 111,
|
||||
"current": 0.2,
|
||||
"frequency": 50.1,
|
||||
"state": "enabled",
|
||||
"measurement_type": "production",
|
||||
"metering_status": "normal",
|
||||
"status_flags": ["power-on-unused-phase"]
|
||||
},
|
||||
"L3": {
|
||||
"eid": "100000013",
|
||||
"timestamp": 1708006113,
|
||||
"energy_delivered": 112343,
|
||||
"energy_received": 123453,
|
||||
"active_power": 50,
|
||||
"power_factor": 0.14,
|
||||
"voltage": 111,
|
||||
"current": 0.2,
|
||||
"frequency": 50.1,
|
||||
"state": "enabled",
|
||||
"measurement_type": "production",
|
||||
"metering_status": "normal",
|
||||
"status_flags": []
|
||||
}
|
||||
},
|
||||
"ctmeter_consumption_phases": {
|
||||
"L1": {
|
||||
"eid": "100000021",
|
||||
"timestamp": 1708006121,
|
||||
"energy_delivered": 212341,
|
||||
"energy_received": 223451,
|
||||
"active_power": 21,
|
||||
"power_factor": 0.22,
|
||||
"voltage": 112,
|
||||
"current": 0.3,
|
||||
"frequency": 50.2,
|
||||
"state": "enabled",
|
||||
"measurement_type": "net-consumption",
|
||||
"metering_status": "normal",
|
||||
"status_flags": []
|
||||
},
|
||||
"L2": {
|
||||
"eid": "100000022",
|
||||
"timestamp": 1708006122,
|
||||
"energy_delivered": 212342,
|
||||
"energy_received": 223452,
|
||||
"active_power": 31,
|
||||
"power_factor": 0.23,
|
||||
"voltage": 112,
|
||||
"current": 0.3,
|
||||
"frequency": 50.2,
|
||||
"state": "enabled",
|
||||
"measurement_type": "net-consumption",
|
||||
"metering_status": "normal",
|
||||
"status_flags": []
|
||||
},
|
||||
"L3": {
|
||||
"eid": "100000023",
|
||||
"timestamp": 1708006123,
|
||||
"energy_delivered": 212343,
|
||||
"energy_received": 223453,
|
||||
"active_power": 51,
|
||||
"power_factor": 0.24,
|
||||
"voltage": 112,
|
||||
"current": 0.3,
|
||||
"frequency": 50.2,
|
||||
"state": "enabled",
|
||||
"measurement_type": "net-consumption",
|
||||
"metering_status": "normal",
|
||||
"status_flags": []
|
||||
}
|
||||
},
|
||||
"ctmeter_storage_phases": null,
|
||||
"dry_contact_status": {},
|
||||
"dry_contact_settings": {},
|
||||
"inverters": {
|
||||
"1": {
|
||||
"serial_number": "1",
|
||||
"last_report_date": 1,
|
||||
"last_report_watts": 1,
|
||||
"max_report_watts": 1
|
||||
}
|
||||
},
|
||||
"tariff": {
|
||||
"currency": {
|
||||
"code": "EUR"
|
||||
},
|
||||
"logger": "mylogger",
|
||||
"date": "1714749724",
|
||||
"storage_settings": {
|
||||
"mode": "self-consumption",
|
||||
"operation_mode_sub_type": "",
|
||||
"reserved_soc": 0.0,
|
||||
"very_low_soc": 5,
|
||||
"charge_from_grid": true,
|
||||
"date": "1714749724"
|
||||
},
|
||||
"single_rate": {
|
||||
"rate": 0.0,
|
||||
"sell": 0.0
|
||||
},
|
||||
"seasons": [
|
||||
{
|
||||
"id": "all_year_long",
|
||||
"start": "1/1",
|
||||
"days": [
|
||||
{
|
||||
"id": "all_days",
|
||||
"days": "Mon,Tue,Wed,Thu,Fri,Sat,Sun",
|
||||
"must_charge_start": 0,
|
||||
"must_charge_duration": 0,
|
||||
"must_charge_mode": "CP",
|
||||
"enable_discharge_to_grid": false,
|
||||
"periods": [
|
||||
{
|
||||
"id": "period_1",
|
||||
"start": 0,
|
||||
"rate": 0.0
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"tiers": []
|
||||
}
|
||||
],
|
||||
"seasons_sell": []
|
||||
},
|
||||
"raw": {
|
||||
"varies_by": "firmware_version"
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -31,6 +31,7 @@ from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_plat
|
||||
"envoy_metered_batt_relay",
|
||||
"envoy_nobatt_metered_3p",
|
||||
"envoy_tot_cons_metered",
|
||||
"envoy_acb_batt",
|
||||
],
|
||||
indirect=["mock_envoy"],
|
||||
)
|
||||
@ -65,6 +66,7 @@ PRODUCTION_NAMES: tuple[str, ...] = (
|
||||
"envoy_metered_batt_relay",
|
||||
"envoy_nobatt_metered_3p",
|
||||
"envoy_tot_cons_metered",
|
||||
"envoy_acb_batt",
|
||||
],
|
||||
indirect=["mock_envoy"],
|
||||
)
|
||||
@ -154,6 +156,7 @@ CONSUMPTION_NAMES: tuple[str, ...] = (
|
||||
"envoy_eu_batt",
|
||||
"envoy_metered_batt_relay",
|
||||
"envoy_nobatt_metered_3p",
|
||||
"envoy_acb_batt",
|
||||
],
|
||||
indirect=["mock_envoy"],
|
||||
)
|
||||
@ -197,6 +200,7 @@ NET_CONSUMPTION_NAMES: tuple[str, ...] = (
|
||||
"envoy_metered_batt_relay",
|
||||
"envoy_nobatt_metered_3p",
|
||||
"envoy_tot_cons_metered",
|
||||
"envoy_acb_batt",
|
||||
],
|
||||
indirect=["mock_envoy"],
|
||||
)
|
||||
@ -803,6 +807,7 @@ async def test_sensor_inverter_disabled_by_integration(
|
||||
("mock_envoy"),
|
||||
[
|
||||
"envoy_metered_batt_relay",
|
||||
"envoy_acb_batt",
|
||||
],
|
||||
indirect=["mock_envoy"],
|
||||
)
|
||||
@ -873,6 +878,7 @@ async def test_sensor_encharge_enpower_data(
|
||||
("mock_envoy"),
|
||||
[
|
||||
"envoy_metered_batt_relay",
|
||||
"envoy_acb_batt",
|
||||
],
|
||||
indirect=["mock_envoy"],
|
||||
)
|
||||
@ -930,6 +936,101 @@ async def test_sensor_encharge_power_data(
|
||||
)
|
||||
|
||||
|
||||
ACB_POWER_INT_NAMES: tuple[str, ...] = (
|
||||
"power",
|
||||
"battery",
|
||||
)
|
||||
ACB_POWER_STR_NAMES: tuple[str, ...] = ("battery_state",)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("mock_envoy"),
|
||||
[
|
||||
"envoy_acb_batt",
|
||||
],
|
||||
indirect=["mock_envoy"],
|
||||
)
|
||||
async def test_sensor_acb_power_data(
|
||||
hass: HomeAssistant,
|
||||
config_entry: MockConfigEntry,
|
||||
mock_envoy: AsyncMock,
|
||||
) -> None:
|
||||
"""Test enphase_envoy acb battery power entities values."""
|
||||
with patch("homeassistant.components.enphase_envoy.PLATFORMS", [Platform.SENSOR]):
|
||||
await setup_integration(hass, config_entry)
|
||||
|
||||
sn = mock_envoy.serial_number
|
||||
ENTITY_BASE: str = f"{Platform.SENSOR}.acb_{sn}"
|
||||
|
||||
data = mock_envoy.data.acb_power
|
||||
ACB_POWER_INT_TARGETS: tuple[int, ...] = (
|
||||
data.power,
|
||||
data.state_of_charge,
|
||||
)
|
||||
ACB_POWER_STR_TARGETS: tuple[int, ...] = (data.state,)
|
||||
|
||||
for name, target in list(
|
||||
zip(ACB_POWER_INT_NAMES, ACB_POWER_INT_TARGETS, strict=False)
|
||||
):
|
||||
assert (entity_state := hass.states.get(f"{ENTITY_BASE}_{name}"))
|
||||
assert int(entity_state.state) == target
|
||||
|
||||
for name, target in list(
|
||||
zip(ACB_POWER_STR_NAMES, ACB_POWER_STR_TARGETS, strict=False)
|
||||
):
|
||||
assert (entity_state := hass.states.get(f"{ENTITY_BASE}_{name}"))
|
||||
assert entity_state.state == target
|
||||
|
||||
|
||||
AGGREGATED_BATTERY_NAMES: tuple[str, ...] = (
|
||||
"aggregated_battery_soc",
|
||||
"aggregated_available_battery_energy",
|
||||
"aggregated_battery_capacity",
|
||||
)
|
||||
AGGREGATED_ACB_BATTERY_NAMES: tuple[str, ...] = ("available_acb_battery_energy",)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("mock_envoy"),
|
||||
[
|
||||
"envoy_acb_batt",
|
||||
],
|
||||
indirect=["mock_envoy"],
|
||||
)
|
||||
async def test_sensor_aggegated_battery_data(
|
||||
hass: HomeAssistant,
|
||||
config_entry: MockConfigEntry,
|
||||
mock_envoy: AsyncMock,
|
||||
) -> None:
|
||||
"""Test enphase_envoy aggregated batteries entities values."""
|
||||
with patch("homeassistant.components.enphase_envoy.PLATFORMS", [Platform.SENSOR]):
|
||||
await setup_integration(hass, config_entry)
|
||||
|
||||
sn = mock_envoy.serial_number
|
||||
ENTITY_BASE: str = f"{Platform.SENSOR}.envoy_{sn}"
|
||||
|
||||
data = mock_envoy.data.battery_aggregate
|
||||
AGGREGATED_TARGETS: tuple[int, ...] = (
|
||||
data.state_of_charge,
|
||||
data.available_energy,
|
||||
data.max_available_capacity,
|
||||
)
|
||||
|
||||
for name, target in list(
|
||||
zip(AGGREGATED_BATTERY_NAMES, AGGREGATED_TARGETS, strict=False)
|
||||
):
|
||||
assert (entity_state := hass.states.get(f"{ENTITY_BASE}_{name}"))
|
||||
assert int(entity_state.state) == target
|
||||
|
||||
data = mock_envoy.data.acb_power
|
||||
AGGREGATED_ACB_TARGETS: tuple[int, ...] = (data.charge_wh,)
|
||||
for name, target in list(
|
||||
zip(AGGREGATED_ACB_BATTERY_NAMES, AGGREGATED_ACB_TARGETS, strict=False)
|
||||
):
|
||||
assert (entity_state := hass.states.get(f"{ENTITY_BASE}_{name}"))
|
||||
assert int(entity_state.state) == target
|
||||
|
||||
|
||||
def integration_disabled_entities(
|
||||
entity_registry: er.EntityRegistry, config_entry: MockConfigEntry
|
||||
) -> list[str]:
|
||||
|
Loading…
x
Reference in New Issue
Block a user