Add storage settings for enphase_envoy batteries without enpower device (#125527)

* Add battery storage settings for enphase_envoy EU configuration

* Add EU Battery test fixture to enphase_envoy

* Add tests and snapshots for enphase_envoy EU battery

* refactor eu battery fixture to align with other enphase_envoy fixtures

* remove if from test and use test parameter for eu battery enphase_envoy tests
This commit is contained in:
Arie Catsman 2024-09-11 13:32:29 +02:00 committed by GitHub
parent 356bca119d
commit 3c1860cca2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 5143 additions and 50 deletions

View File

@ -88,7 +88,6 @@ async def async_setup_entry(
envoy_data.tariff
and envoy_data.tariff.storage_settings
and coordinator.envoy.supported_features & SupportedFeatures.ENCHARGE
and coordinator.envoy.supported_features & SupportedFeatures.ENPOWER
):
entities.append(
EnvoyStorageSettingsNumberEntity(coordinator, STORAGE_RESERVE_SOC_ENTITY)
@ -152,18 +151,30 @@ class EnvoyStorageSettingsNumberEntity(EnvoyBaseEntity, NumberEntity):
"""Initialize the Enphase relay number entity."""
super().__init__(coordinator, description)
self.envoy = coordinator.envoy
assert self.data.enpower is not None
enpower = self.data.enpower
self._serial_number = enpower.serial_number
self._attr_unique_id = f"{self._serial_number}_{description.key}"
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, self._serial_number)},
manufacturer="Enphase",
model="Enpower",
name=f"Enpower {self._serial_number}",
sw_version=str(enpower.firmware_version),
via_device=(DOMAIN, self.envoy_serial_num),
)
assert self.data is not None
if enpower := self.data.enpower:
self._serial_number = enpower.serial_number
self._attr_unique_id = f"{self._serial_number}_{description.key}"
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, self._serial_number)},
manufacturer="Enphase",
model="Enpower",
name=f"Enpower {self._serial_number}",
sw_version=str(enpower.firmware_version),
via_device=(DOMAIN, self.envoy_serial_num),
)
else:
# If no enpower device assign numbers to Envoy itself
self._attr_unique_id = f"{self.envoy_serial_num}_{description.key}"
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, self.envoy_serial_num)},
manufacturer="Enphase",
model=coordinator.envoy.envoy_model,
name=coordinator.name,
sw_version=str(coordinator.envoy.firmware),
hw_version=coordinator.envoy.part_number,
serial_number=self.envoy_serial_num,
)
@property
def native_value(self) -> float:

View File

@ -143,7 +143,6 @@ async def async_setup_entry(
envoy_data.tariff
and envoy_data.tariff.storage_settings
and coordinator.envoy.supported_features & SupportedFeatures.ENCHARGE
and coordinator.envoy.supported_features & SupportedFeatures.ENPOWER
):
entities.append(
EnvoyStorageSettingsSelectEntity(coordinator, STORAGE_MODE_ENTITY)
@ -209,18 +208,29 @@ class EnvoyStorageSettingsSelectEntity(EnvoyBaseEntity, SelectEntity):
super().__init__(coordinator, description)
self.envoy = coordinator.envoy
assert coordinator.envoy.data is not None
assert coordinator.envoy.data.enpower is not None
enpower = coordinator.envoy.data.enpower
self._serial_number = enpower.serial_number
self._attr_unique_id = f"{self._serial_number}_{description.key}"
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, self._serial_number)},
manufacturer="Enphase",
model="Enpower",
name=f"Enpower {self._serial_number}",
sw_version=str(enpower.firmware_version),
via_device=(DOMAIN, self.envoy_serial_num),
)
if enpower := coordinator.envoy.data.enpower:
self._serial_number = enpower.serial_number
self._attr_unique_id = f"{self._serial_number}_{description.key}"
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, self._serial_number)},
manufacturer="Enphase",
model="Enpower",
name=f"Enpower {self._serial_number}",
sw_version=str(enpower.firmware_version),
via_device=(DOMAIN, self.envoy_serial_num),
)
else:
# If no enpower device assign selects to Envoy itself
self._attr_unique_id = f"{self.envoy_serial_num}_{description.key}"
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, self.envoy_serial_num)},
manufacturer="Enphase",
model=coordinator.envoy.envoy_model,
name=coordinator.name,
sw_version=str(coordinator.envoy.firmware),
hw_version=coordinator.envoy.part_number,
serial_number=self.envoy_serial_num,
)
@property
def current_option(self) -> str:

View File

@ -98,8 +98,7 @@ async def async_setup_entry(
)
if (
envoy_data.enpower
and envoy_data.tariff
envoy_data.tariff
and envoy_data.tariff.storage_settings
and (coordinator.envoy.supported_features & SupportedFeatures.ENCHARGE)
):
@ -213,22 +212,35 @@ class EnvoyStorageSettingsSwitchEntity(EnvoyBaseEntity, SwitchEntity):
self,
coordinator: EnphaseUpdateCoordinator,
description: EnvoyStorageSettingsSwitchEntityDescription,
enpower: EnvoyEnpower,
enpower: EnvoyEnpower | None,
) -> None:
"""Initialize the Enphase storage settings switch entity."""
super().__init__(coordinator, description)
self.envoy = coordinator.envoy
self.enpower = enpower
self._serial_number = enpower.serial_number
self._attr_unique_id = f"{self._serial_number}_{description.key}"
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, self._serial_number)},
manufacturer="Enphase",
model="Enpower",
name=f"Enpower {self._serial_number}",
sw_version=str(enpower.firmware_version),
via_device=(DOMAIN, self.envoy_serial_num),
)
if enpower:
self._serial_number = enpower.serial_number
self._attr_unique_id = f"{self._serial_number}_{description.key}"
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, self._serial_number)},
manufacturer="Enphase",
model="Enpower",
name=f"Enpower {self._serial_number}",
sw_version=str(enpower.firmware_version),
via_device=(DOMAIN, self.envoy_serial_num),
)
else:
# If no enpower device assign switches to Envoy itself
self._attr_unique_id = f"{self.envoy_serial_num}_{description.key}"
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, self.envoy_serial_num)},
manufacturer="Enphase",
model=coordinator.envoy.envoy_model,
name=coordinator.name,
sw_version=str(coordinator.envoy.firmware),
hw_version=coordinator.envoy.part_number,
serial_number=self.envoy_serial_num,
)
@property
def is_on(self) -> bool:

View File

@ -0,0 +1,262 @@
{
"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": 4,
"serial_number": "122327081322",
"temperature": 16,
"temperature_unit": "C",
"zigbee_dongle_fw_version": "100F"
}
},
"encharge_power": {
"123456": {
"apparent_power_mva": 0,
"real_power_mw": 0,
"soc": 4
}
},
"encharge_aggregate": {
"available_energy": 140,
"backup_reserve": 0,
"state_of_charge": 4,
"reserve_state_of_charge": 0,
"configured_reserve_state_of_charge": 0,
"max_available_capacity": 3500
},
"enpower": null,
"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"
}
}
}

View File

@ -1,4 +1,97 @@
# serializer version: 1
# name: test_binary_sensor[envoy_eu_batt][binary_sensor.encharge_123456_communicating-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.encharge_123456_communicating',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.CONNECTIVITY: 'connectivity'>,
'original_icon': None,
'original_name': 'Communicating',
'platform': 'enphase_envoy',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'communicating',
'unique_id': '123456_communicating',
'unit_of_measurement': None,
})
# ---
# name: test_binary_sensor[envoy_eu_batt][binary_sensor.encharge_123456_communicating-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'connectivity',
'friendly_name': 'Encharge 123456 Communicating',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.encharge_123456_communicating',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_binary_sensor[envoy_eu_batt][binary_sensor.encharge_123456_dc_switch-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.encharge_123456_dc_switch',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'DC switch',
'platform': 'enphase_envoy',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'dc_switch',
'unique_id': '123456_dc_switch',
'unit_of_measurement': None,
})
# ---
# name: test_binary_sensor[envoy_eu_batt][binary_sensor.encharge_123456_dc_switch-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Encharge 123456 DC switch',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.encharge_123456_dc_switch',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_binary_sensor[envoy_metered_batt_relay][binary_sensor.encharge_123456_communicating-entry]
EntityRegistryEntrySnapshot({
'aliases': set({

View File

@ -1,4 +1,61 @@
# serializer version: 1
# name: test_number[envoy_eu_batt][number.envoy_1234_reserve_battery_level-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'max': 100.0,
'min': 0.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'number',
'entity_category': None,
'entity_id': 'number.envoy_1234_reserve_battery_level',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <NumberDeviceClass.BATTERY: 'battery'>,
'original_icon': None,
'original_name': 'Reserve battery level',
'platform': 'enphase_envoy',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'reserve_soc',
'unique_id': '1234_reserve_soc',
'unit_of_measurement': '%',
})
# ---
# name: test_number[envoy_eu_batt][number.envoy_1234_reserve_battery_level-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'battery',
'friendly_name': 'Envoy 1234 Reserve battery level',
'max': 100.0,
'min': 0.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
'unit_of_measurement': '%',
}),
'context': <ANY>,
'entity_id': 'number.envoy_1234_reserve_battery_level',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '0.0',
})
# ---
# name: test_number[envoy_metered_batt_relay][number.enpower_654321_reserve_battery_level-entry]
EntityRegistryEntrySnapshot({
'aliases': set({

View File

@ -1,4 +1,61 @@
# serializer version: 1
# name: test_select[envoy_eu_batt][select.envoy_1234_storage_mode-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'options': list([
'backup',
'self_consumption',
'savings',
]),
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'select',
'entity_category': None,
'entity_id': 'select.envoy_1234_storage_mode',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Storage mode',
'platform': 'enphase_envoy',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'storage_mode',
'unique_id': '1234_storage_mode',
'unit_of_measurement': None,
})
# ---
# name: test_select[envoy_eu_batt][select.envoy_1234_storage_mode-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Envoy 1234 Storage mode',
'options': list([
'backup',
'self_consumption',
'savings',
]),
}),
'context': <ANY>,
'entity_id': 'select.envoy_1234_storage_mode',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'self_consumption',
})
# ---
# name: test_select[envoy_metered_batt_relay][select.enpower_654321_storage_mode-entry]
EntityRegistryEntrySnapshot({
'aliases': set({

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,50 @@
# serializer version: 1
# name: test_switch[envoy_eu_batt][switch.envoy_1234_charge_from_grid-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'switch',
'entity_category': None,
'entity_id': 'switch.envoy_1234_charge_from_grid',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Charge from grid',
'platform': 'enphase_envoy',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'charge_from_grid',
'unique_id': '1234_charge_from_grid',
'unit_of_measurement': None,
})
# ---
# name: test_switch[envoy_eu_batt][switch.envoy_1234_charge_from_grid-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Envoy 1234 Charge from grid',
}),
'context': <ANY>,
'entity_id': 'switch.envoy_1234_charge_from_grid',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_switch[envoy_metered_batt_relay][switch.enpower_654321_charge_from_grid-entry]
EntityRegistryEntrySnapshot({
'aliases': set({

View File

@ -16,7 +16,9 @@ from tests.common import MockConfigEntry, snapshot_platform
@pytest.mark.parametrize(
("mock_envoy"), ["envoy_metered_batt_relay"], indirect=["mock_envoy"]
("mock_envoy"),
["envoy_eu_batt", "envoy_metered_batt_relay"],
indirect=["mock_envoy"],
)
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_binary_sensor(

View File

@ -21,7 +21,9 @@ from tests.common import MockConfigEntry, snapshot_platform
@pytest.mark.parametrize(
("mock_envoy"), ["envoy_metered_batt_relay"], indirect=["mock_envoy"]
("mock_envoy"),
["envoy_metered_batt_relay", "envoy_eu_batt"],
indirect=["mock_envoy"],
)
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_number(
@ -60,19 +62,24 @@ async def test_no_number(
@pytest.mark.parametrize(
("mock_envoy"), ["envoy_metered_batt_relay"], indirect=["mock_envoy"]
("mock_envoy", "use_serial"),
[
("envoy_metered_batt_relay", "enpower_654321"),
("envoy_eu_batt", "envoy_1234"),
],
indirect=["mock_envoy"],
)
async def test_number_operation_storage(
hass: HomeAssistant,
mock_envoy: AsyncMock,
config_entry: MockConfigEntry,
use_serial: bool,
) -> None:
"""Test enphase_envoy number storage entities operation."""
with patch("homeassistant.components.enphase_envoy.PLATFORMS", [Platform.NUMBER]):
await setup_integration(hass, config_entry)
sn = mock_envoy.data.enpower.serial_number
test_entity = f"{Platform.NUMBER}.enpower_{sn}_reserve_battery_level"
test_entity = f"{Platform.NUMBER}.{use_serial}_reserve_battery_level"
assert (entity_state := hass.states.get(test_entity))
assert mock_envoy.data.tariff.storage_settings.reserved_soc == float(

View File

@ -28,7 +28,9 @@ from tests.common import MockConfigEntry, snapshot_platform
@pytest.mark.parametrize(
("mock_envoy"), ["envoy_metered_batt_relay"], indirect=["mock_envoy"]
("mock_envoy"),
["envoy_metered_batt_relay", "envoy_eu_batt"],
indirect=["mock_envoy"],
)
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_select(
@ -172,19 +174,24 @@ async def test_select_relay_modes(
@pytest.mark.parametrize(
("mock_envoy"), ["envoy_metered_batt_relay"], indirect=["mock_envoy"]
("mock_envoy", "use_serial"),
[
("envoy_metered_batt_relay", "enpower_654321"),
("envoy_eu_batt", "envoy_1234"),
],
indirect=["mock_envoy"],
)
async def test_select_storage_modes(
hass: HomeAssistant,
mock_envoy: AsyncMock,
config_entry: MockConfigEntry,
use_serial: str,
) -> None:
"""Test select platform entities storage mode changes."""
with patch("homeassistant.components.enphase_envoy.PLATFORMS", [Platform.SELECT]):
await setup_integration(hass, config_entry)
sn = mock_envoy.data.enpower.serial_number
test_entity = f"{Platform.SELECT}.enpower_{sn}_storage_mode"
test_entity = f"{Platform.SELECT}.{use_serial}_storage_mode"
assert (entity_state := hass.states.get(test_entity))
assert STORAGE_MODE_MAP[mock_envoy.data.tariff.storage_settings.mode] == (

View File

@ -26,6 +26,7 @@ from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_plat
[
"envoy",
"envoy_1p_metered",
"envoy_eu_batt",
"envoy_metered_batt_relay",
"envoy_nobatt_metered_3p",
"envoy_tot_cons_metered",
@ -59,6 +60,7 @@ PRODUCTION_NAMES: tuple[str, ...] = (
[
"envoy",
"envoy_1p_metered",
"envoy_eu_batt",
"envoy_metered_batt_relay",
"envoy_nobatt_metered_3p",
"envoy_tot_cons_metered",
@ -148,6 +150,7 @@ CONSUMPTION_NAMES: tuple[str, ...] = (
("mock_envoy"),
[
"envoy_1p_metered",
"envoy_eu_batt",
"envoy_metered_batt_relay",
"envoy_nobatt_metered_3p",
],
@ -189,6 +192,7 @@ NET_CONSUMPTION_NAMES: tuple[str, ...] = (
("mock_envoy"),
[
"envoy_1p_metered",
"envoy_eu_batt",
"envoy_metered_batt_relay",
"envoy_nobatt_metered_3p",
"envoy_tot_cons_metered",
@ -735,6 +739,7 @@ async def test_sensor_storage_phase_disabled_by_integration(
[
"envoy",
"envoy_1p_metered",
"envoy_eu_batt",
"envoy_metered_batt_relay",
"envoy_nobatt_metered_3p",
"envoy_tot_cons_metered",
@ -767,6 +772,7 @@ async def test_sensor_inverter_data(
[
"envoy",
"envoy_1p_metered",
"envoy_eu_batt",
"envoy_metered_batt_relay",
"envoy_nobatt_metered_3p",
"envoy_tot_cons_metered",

View File

@ -24,7 +24,9 @@ from tests.common import MockConfigEntry, snapshot_platform
@pytest.mark.parametrize(
("mock_envoy"), ["envoy_metered_batt_relay"], indirect=["mock_envoy"]
("mock_envoy"),
["envoy_metered_batt_relay", "envoy_eu_batt"],
indirect=["mock_envoy"],
)
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_switch(
@ -109,7 +111,26 @@ async def test_switch_grid_operation(
mock_envoy.go_off_grid.assert_awaited_once_with()
mock_envoy.go_off_grid.reset_mock()
test_entity = f"{Platform.SWITCH}.enpower_{sn}_charge_from_grid"
@pytest.mark.parametrize(
("mock_envoy", "use_serial"),
[
("envoy_metered_batt_relay", "enpower_654321"),
("envoy_eu_batt", "envoy_1234"),
],
indirect=["mock_envoy"],
)
async def test_switch_charge_from_grid_operation(
hass: HomeAssistant,
mock_envoy: AsyncMock,
config_entry: MockConfigEntry,
use_serial: str,
) -> None:
"""Test switch platform operation for charge from grid switches."""
with patch("homeassistant.components.enphase_envoy.PLATFORMS", [Platform.SWITCH]):
await setup_integration(hass, config_entry)
test_entity = f"{Platform.SWITCH}.{use_serial}_charge_from_grid"
# validate envoy value is reflected in entity
assert (entity_state := hass.states.get(test_entity))