1 """Switch platform for Enphase Envoy solar energy monitor."""
3 from __future__
import annotations
5 from collections.abc
import Awaitable, Callable, Coroutine
6 from dataclasses
import dataclass
9 from pyenphase
import Envoy, EnvoyDryContactStatus, EnvoyEnpower
10 from pyenphase.const
import SupportedFeatures
11 from pyenphase.models.dry_contacts
import DryContactStatus
12 from pyenphase.models.tariff
import EnvoyStorageSettings
19 from .const
import DOMAIN
20 from .coordinator
import EnphaseConfigEntry, EnphaseUpdateCoordinator
21 from .entity
import EnvoyBaseEntity
24 @dataclass(frozen=True, kw_only=True)
26 """Describes an Envoy Enpower switch entity."""
28 value_fn: Callable[[EnvoyEnpower], bool]
29 turn_on_fn: Callable[[Envoy], Coroutine[Any, Any, dict[str, Any]]]
30 turn_off_fn: Callable[[Envoy], Coroutine[Any, Any, dict[str, Any]]]
33 @dataclass(frozen=True, kw_only=True)
35 """Describes an Envoy Enpower dry contact switch entity."""
37 value_fn: Callable[[EnvoyDryContactStatus], bool]
38 turn_on_fn: Callable[[Envoy, str], Coroutine[Any, Any, dict[str, Any]]]
39 turn_off_fn: Callable[[Envoy, str], Coroutine[Any, Any, dict[str, Any]]]
42 @dataclass(frozen=True, kw_only=True)
44 """Describes an Envoy storage settings switch entity."""
46 value_fn: Callable[[EnvoyStorageSettings], bool]
47 turn_on_fn: Callable[[Envoy], Awaitable[dict[str, Any]]]
48 turn_off_fn: Callable[[Envoy], Awaitable[dict[str, Any]]]
52 key=
"mains_admin_state",
53 translation_key=
"grid_enabled",
54 value_fn=
lambda enpower: enpower.mains_admin_state ==
"closed",
55 turn_on_fn=
lambda envoy: envoy.go_on_grid(),
56 turn_off_fn=
lambda envoy: envoy.go_off_grid(),
61 value_fn=
lambda dry_contact: dry_contact.status == DryContactStatus.CLOSED,
62 turn_on_fn=
lambda envoy, id: envoy.close_dry_contact(id),
63 turn_off_fn=
lambda envoy, id: envoy.open_dry_contact(id),
67 key=
"charge_from_grid",
68 translation_key=
"charge_from_grid",
69 value_fn=
lambda storage_settings: storage_settings.charge_from_grid,
70 turn_on_fn=
lambda envoy: envoy.enable_charge_from_grid(),
71 turn_off_fn=
lambda envoy: envoy.disable_charge_from_grid(),
77 config_entry: EnphaseConfigEntry,
78 async_add_entities: AddEntitiesCallback,
80 """Set up Enphase Envoy switch platform."""
81 coordinator = config_entry.runtime_data
82 envoy_data = coordinator.envoy.data
83 assert envoy_data
is not None
84 entities: list[SwitchEntity] = []
85 if envoy_data.enpower:
89 coordinator, ENPOWER_GRID_SWITCH, envoy_data.enpower
94 if envoy_data.dry_contact_status:
97 for relay
in envoy_data.dry_contact_status
102 and envoy_data.tariff.storage_settings
103 and (coordinator.envoy.supported_features & SupportedFeatures.ENCHARGE)
107 coordinator, CHARGE_FROM_GRID_SWITCH, envoy_data.enpower
115 """Representation of an Enphase Enpower switch entity."""
117 entity_description: EnvoyEnpowerSwitchEntityDescription
121 coordinator: EnphaseUpdateCoordinator,
122 description: EnvoyEnpowerSwitchEntityDescription,
123 enpower: EnvoyEnpower,
125 """Initialize the Enphase Enpower switch entity."""
126 super().
__init__(coordinator, description)
133 manufacturer=
"Enphase",
135 name=f
"Enpower {self._serial_number}",
136 sw_version=
str(enpower.firmware_version),
142 """Return the state of the Enpower switch."""
144 assert enpower
is not None
148 """Turn on the Enpower switch."""
153 """Turn off the Enpower switch."""
159 """Representation of an Enphase dry contact switch entity."""
161 entity_description: EnvoyDryContactSwitchEntityDescription
166 coordinator: EnphaseUpdateCoordinator,
167 description: EnvoyDryContactSwitchEntityDescription,
170 """Initialize the Enphase dry contact switch entity."""
171 super().
__init__(coordinator, description)
174 assert enpower
is not None
176 serial_number = enpower.serial_number
177 self.
_attr_unique_id_attr_unique_id = f
"{serial_number}_relay_{relay_id}_{description.key}"
178 relay = self.
datadatadata.dry_contact_settings[relay_id]
180 identifiers={(DOMAIN, relay_id)},
181 manufacturer=
"Enphase",
182 model=
"Dry contact relay",
183 name=relay.load_name,
184 sw_version=
str(enpower.firmware_version),
185 via_device=(DOMAIN, enpower.serial_number),
190 """Return the state of the dry contact."""
192 assert relay
is not None
196 """Turn on (close) the dry contact."""
201 """Turn off (open) the dry contact."""
207 """Representation of an Enphase storage settings switch entity."""
209 entity_description: EnvoyStorageSettingsSwitchEntityDescription
213 coordinator: EnphaseUpdateCoordinator,
214 description: EnvoyStorageSettingsSwitchEntityDescription,
215 enpower: EnvoyEnpower |
None,
217 """Initialize the Enphase storage settings switch entity."""
218 super().
__init__(coordinator, description)
226 manufacturer=
"Enphase",
228 name=f
"Enpower {self._serial_number}",
229 sw_version=
str(enpower.firmware_version),
234 self.
_attr_unique_id_attr_unique_id = f
"{self.envoy_serial_num}_{description.key}"
237 manufacturer=
"Enphase",
238 model=coordinator.envoy.envoy_model,
239 name=coordinator.name,
240 sw_version=
str(coordinator.envoy.firmware),
241 hw_version=coordinator.envoy.part_number,
247 """Return the state of the storage settings switch."""
248 assert self.
datadatadata.tariff
is not None
249 assert self.
datadatadata.tariff.storage_settings
is not None
253 """Turn on the storage settings switch."""
258 """Turn off the storage switch."""
None async_turn_off(self, **Any kwargs)
None __init__(self, EnphaseUpdateCoordinator coordinator, EnvoyEnpowerSwitchEntityDescription description, EnvoyEnpower enpower)
None async_turn_on(self, **Any kwargs)
None async_turn_off(self, **Any kwargs)
None async_turn_on(self, **Any kwargs)
None __init__(self, EnphaseUpdateCoordinator coordinator, EnvoyStorageSettingsSwitchEntityDescription description, EnvoyEnpower|None enpower)
None async_write_ha_state(self)
None async_request_refresh(self)
None async_setup_entry(HomeAssistant hass, EnphaseConfigEntry config_entry, AddEntitiesCallback async_add_entities)