Home Assistant Unofficial Reference 2024.12.1
binary_sensor.py
Go to the documentation of this file.
1 """Support for Enphase Envoy solar energy monitor."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable
6 from dataclasses import dataclass
7 from operator import attrgetter
8 
9 from pyenphase import EnvoyEncharge, EnvoyEnpower
10 
12  BinarySensorDeviceClass,
13  BinarySensorEntity,
14  BinarySensorEntityDescription,
15 )
16 from homeassistant.const import EntityCategory
17 from homeassistant.core import HomeAssistant
18 from homeassistant.helpers.device_registry import DeviceInfo
19 from homeassistant.helpers.entity_platform import AddEntitiesCallback
20 
21 from .const import DOMAIN
22 from .coordinator import EnphaseConfigEntry, EnphaseUpdateCoordinator
23 from .entity import EnvoyBaseEntity
24 
25 
26 @dataclass(frozen=True, kw_only=True)
28  """Describes an Envoy Encharge binary sensor entity."""
29 
30  value_fn: Callable[[EnvoyEncharge], bool]
31 
32 
33 ENCHARGE_SENSORS = (
35  key="communicating",
36  translation_key="communicating",
37  device_class=BinarySensorDeviceClass.CONNECTIVITY,
38  entity_category=EntityCategory.DIAGNOSTIC,
39  value_fn=attrgetter("communicating"),
40  ),
42  key="dc_switch",
43  translation_key="dc_switch",
44  entity_category=EntityCategory.DIAGNOSTIC,
45  value_fn=lambda encharge: not encharge.dc_switch_off,
46  ),
47 )
48 
49 
50 @dataclass(frozen=True, kw_only=True)
52  """Describes an Envoy Enpower binary sensor entity."""
53 
54  value_fn: Callable[[EnvoyEnpower], bool]
55 
56 
57 ENPOWER_SENSORS = (
59  key="communicating",
60  translation_key="communicating",
61  device_class=BinarySensorDeviceClass.CONNECTIVITY,
62  entity_category=EntityCategory.DIAGNOSTIC,
63  value_fn=attrgetter("communicating"),
64  ),
66  key="mains_oper_state",
67  translation_key="grid_status",
68  icon="mdi:transmission-tower",
69  value_fn=lambda enpower: enpower.mains_oper_state == "closed",
70  ),
71 )
72 
73 
75  hass: HomeAssistant,
76  config_entry: EnphaseConfigEntry,
77  async_add_entities: AddEntitiesCallback,
78 ) -> None:
79  """Set up envoy binary sensor platform."""
80  coordinator = config_entry.runtime_data
81  envoy_data = coordinator.envoy.data
82  assert envoy_data is not None
83  entities: list[BinarySensorEntity] = []
84  if envoy_data.encharge_inventory:
85  entities.extend(
86  EnvoyEnchargeBinarySensorEntity(coordinator, description, encharge)
87  for description in ENCHARGE_SENSORS
88  for encharge in envoy_data.encharge_inventory
89  )
90 
91  if envoy_data.enpower:
92  entities.extend(
93  EnvoyEnpowerBinarySensorEntity(coordinator, description)
94  for description in ENPOWER_SENSORS
95  )
96 
97  async_add_entities(entities)
98 
99 
101  """Defines a base envoy binary_sensor entity."""
102 
103 
104 class EnvoyEnchargeBinarySensorEntity(EnvoyBaseBinarySensorEntity):
105  """Defines an Encharge binary_sensor entity."""
106 
107  entity_description: EnvoyEnchargeBinarySensorEntityDescription
108 
109  def __init__(
110  self,
111  coordinator: EnphaseUpdateCoordinator,
112  description: EnvoyEnchargeBinarySensorEntityDescription,
113  serial_number: str,
114  ) -> None:
115  """Init the Encharge base entity."""
116  super().__init__(coordinator, description)
117  self._serial_number_serial_number = serial_number
118  self._attr_unique_id_attr_unique_id = f"{serial_number}_{description.key}"
119  encharge_inventory = self.datadatadata.encharge_inventory
120  assert encharge_inventory is not None
121  self._attr_device_info_attr_device_info = DeviceInfo(
122  identifiers={(DOMAIN, serial_number)},
123  manufacturer="Enphase",
124  model="Encharge",
125  name=f"Encharge {serial_number}",
126  sw_version=str(encharge_inventory[self._serial_number_serial_number].firmware_version),
127  via_device=(DOMAIN, self.envoy_serial_numenvoy_serial_num),
128  )
129 
130  @property
131  def is_on(self) -> bool:
132  """Return the state of the Encharge binary_sensor."""
133  encharge_inventory = self.datadatadata.encharge_inventory
134  assert encharge_inventory is not None
135  return self.entity_descriptionentity_description.value_fn(encharge_inventory[self._serial_number_serial_number])
136 
137 
139  """Defines an Enpower binary_sensor entity."""
140 
141  entity_description: EnvoyEnpowerBinarySensorEntityDescription
142 
143  def __init__(
144  self,
145  coordinator: EnphaseUpdateCoordinator,
146  description: EnvoyEnpowerBinarySensorEntityDescription,
147  ) -> None:
148  """Init the Enpower base entity."""
149  super().__init__(coordinator, description)
150  enpower = self.datadatadata.enpower
151  assert enpower is not None
152  self._attr_unique_id_attr_unique_id = f"{enpower.serial_number}_{description.key}"
153  self._attr_device_info_attr_device_info = DeviceInfo(
154  identifiers={(DOMAIN, enpower.serial_number)},
155  manufacturer="Enphase",
156  model="Enpower",
157  name=f"Enpower {enpower.serial_number}",
158  sw_version=str(enpower.firmware_version),
159  via_device=(DOMAIN, self.envoy_serial_numenvoy_serial_num),
160  )
161 
162  @property
163  def is_on(self) -> bool:
164  """Return the state of the Enpower binary_sensor."""
165  enpower = self.datadatadata.enpower
166  assert enpower is not None
167  return self.entity_descriptionentity_description.value_fn(enpower)
None __init__(self, EnphaseUpdateCoordinator coordinator, EnvoyEnchargeBinarySensorEntityDescription description, str serial_number)
None __init__(self, EnphaseUpdateCoordinator coordinator, EnvoyEnpowerBinarySensorEntityDescription description)
None async_setup_entry(HomeAssistant hass, EnphaseConfigEntry config_entry, AddEntitiesCallback async_add_entities)