Add Encharge binary sensors to Enphase integration (#98039)

* Add Encharge binary sensors to Enphase integration

* Code review minor cleanup

* Add to coveragerc
pull/83430/head
Charles Garwood 2023-08-08 14:03:02 -04:00 committed by GitHub
parent 45d4c307de
commit c154077177
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 154 additions and 1 deletions

View File

@ -302,6 +302,7 @@ omit =
homeassistant/components/enocean/sensor.py
homeassistant/components/enocean/switch.py
homeassistant/components/enphase_envoy/__init__.py
homeassistant/components/enphase_envoy/binary_sensor.py
homeassistant/components/enphase_envoy/coordinator.py
homeassistant/components/enphase_envoy/sensor.py
homeassistant/components/entur_public_transport/*

View File

@ -0,0 +1,141 @@
"""Support for Enphase Envoy solar energy monitor."""
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
import logging
from pyenphase import (
EnvoyData,
EnvoyEncharge,
)
from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
BinarySensorEntity,
BinarySensorEntityDescription,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import (
CoordinatorEntity,
)
from .const import DOMAIN
from .coordinator import EnphaseUpdateCoordinator
_LOGGER = logging.getLogger(__name__)
@dataclass
class EnvoyEnchargeRequiredKeysMixin:
"""Mixin for required keys."""
value_fn: Callable[[EnvoyEncharge], bool]
@dataclass
class EnvoyEnchargeBinarySensorEntityDescription(
BinarySensorEntityDescription, EnvoyEnchargeRequiredKeysMixin
):
"""Describes an Envoy Encharge binary sensor entity."""
ENCHARGE_SENSORS = (
EnvoyEnchargeBinarySensorEntityDescription(
key="communicating",
translation_key="communicating",
device_class=BinarySensorDeviceClass.CONNECTIVITY,
entity_category=EntityCategory.DIAGNOSTIC,
value_fn=lambda encharge: encharge.communicating,
),
EnvoyEnchargeBinarySensorEntityDescription(
key="dc_switch",
translation_key="dc_switch",
entity_category=EntityCategory.DIAGNOSTIC,
value_fn=lambda encharge: not encharge.dc_switch_off,
),
EnvoyEnchargeBinarySensorEntityDescription(
key="operating",
translation_key="operating",
entity_category=EntityCategory.DIAGNOSTIC,
value_fn=lambda encharge: encharge.operating,
),
)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up envoy binary sensor platform."""
coordinator: EnphaseUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
envoy_data = coordinator.envoy.data
assert envoy_data is not None
envoy_serial_num = config_entry.unique_id
assert envoy_serial_num is not None
entities: list[BinarySensorEntity] = []
if envoy_data.encharge_inventory:
entities.extend(
EnvoyEnchargeBinarySensorEntity(coordinator, description, encharge)
for description in ENCHARGE_SENSORS
for encharge in envoy_data.encharge_inventory
)
async_add_entities(entities)
class EnvoyEnchargeBinarySensorEntity(
CoordinatorEntity[EnphaseUpdateCoordinator], BinarySensorEntity
):
"""Defines a base envoy binary_sensor entity."""
_attr_has_entity_name = True
entity_description: EnvoyEnchargeBinarySensorEntityDescription
def __init__(
self,
coordinator: EnphaseUpdateCoordinator,
description: EnvoyEnchargeBinarySensorEntityDescription,
serial_number: str,
) -> None:
"""Init the Encharge base entity."""
self.entity_description = description
self.coordinator = coordinator
assert serial_number is not None
self.envoy_serial_num = coordinator.envoy.serial_number
assert self.envoy_serial_num is not None
self._serial_number = serial_number
self._attr_unique_id = f"{serial_number}_{description.key}"
encharge_inventory = self.data.encharge_inventory
assert encharge_inventory is not None
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, serial_number)},
manufacturer="Enphase",
model="Encharge",
name=f"Encharge {serial_number}",
sw_version=str(encharge_inventory[self._serial_number].firmware_version),
via_device=(DOMAIN, self.envoy_serial_num),
)
super().__init__(coordinator)
@property
def data(self) -> EnvoyData:
"""Return envoy data."""
data = self.coordinator.envoy.data
assert data is not None
return data
@property
def is_on(self) -> bool:
"""Return the state of the Encharge binary_sensor."""
encharge_inventory = self.data.encharge_inventory
assert encharge_inventory is not None
return self.entity_description.value_fn(encharge_inventory[self._serial_number])

View File

@ -8,6 +8,6 @@ from homeassistant.const import Platform
DOMAIN = "enphase_envoy"
PLATFORMS = [Platform.SENSOR]
PLATFORMS = [Platform.BINARY_SENSOR, Platform.SENSOR]
INVALID_AUTH_ERRORS = (EnvoyAuthenticationError, EnvoyAuthenticationRequired)

View File

@ -22,6 +22,17 @@
}
},
"entity": {
"binary_sensor": {
"communicating": {
"name": "Communicating"
},
"dc_switch": {
"name": "DC Switch"
},
"operating": {
"name": "Operating"
}
},
"sensor": {
"last_reported": {
"name": "Last reported"