Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Enphase switch platform and grid enable switch #98261

Merged
merged 4 commits into from
Aug 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ omit =
homeassistant/components/enphase_envoy/coordinator.py
homeassistant/components/enphase_envoy/entity.py
homeassistant/components/enphase_envoy/sensor.py
homeassistant/components/enphase_envoy/switch.py
homeassistant/components/entur_public_transport/*
homeassistant/components/environment_canada/__init__.py
homeassistant/components/environment_canada/camera.py
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/enphase_envoy/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@

DOMAIN = "enphase_envoy"

PLATFORMS = [Platform.BINARY_SENSOR, Platform.SENSOR]
PLATFORMS = [Platform.BINARY_SENSOR, Platform.SENSOR, Platform.SWITCH]

INVALID_AUTH_ERRORS = (EnvoyAuthenticationError, EnvoyAuthenticationRequired)
2 changes: 1 addition & 1 deletion homeassistant/components/enphase_envoy/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"documentation": "https://www.home-assistant.io/integrations/enphase_envoy",
"iot_class": "local_polling",
"loggers": ["pyenphase"],
"requirements": ["pyenphase==1.3.0"],
"requirements": ["pyenphase==1.4.0"],
"zeroconf": [
{
"type": "_enphase-envoy._tcp.local."
Expand Down
5 changes: 5 additions & 0 deletions homeassistant/components/enphase_envoy/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@
"lifetime_consumption": {
"name": "Lifetime energy consumption"
}
},
"switch": {
"grid_enabled": {
"name": "Grid enabled"
}
}
}
}
113 changes: 113 additions & 0 deletions homeassistant/components/enphase_envoy/switch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
"""Switch platform for Enphase Envoy solar energy monitor."""
from __future__ import annotations

from collections.abc import Callable, Coroutine
from dataclasses import dataclass
import logging
from typing import Any

from pyenphase import Envoy, EnvoyEnpower

from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from .const import DOMAIN
from .coordinator import EnphaseUpdateCoordinator
from .entity import EnvoyBaseEntity

_LOGGER = logging.getLogger(__name__)


@dataclass
class EnvoyEnpowerRequiredKeysMixin:
"""Mixin for required keys."""

value_fn: Callable[[EnvoyEnpower], bool]
turn_on_fn: Callable[[Envoy], Coroutine[Any, Any, dict[str, Any]]]
turn_off_fn: Callable[[Envoy], Coroutine[Any, Any, dict[str, Any]]]


@dataclass
class EnvoyEnpowerSwitchEntityDescription(
SwitchEntityDescription, EnvoyEnpowerRequiredKeysMixin
):
"""Describes an Envoy Enpower switch entity."""


ENPOWER_GRID_SWITCH = EnvoyEnpowerSwitchEntityDescription(
key="mains_admin_state",
translation_key="grid_enabled",
value_fn=lambda enpower: enpower.mains_admin_state == "closed",
turn_on_fn=lambda envoy: envoy.go_on_grid(),
bdraco marked this conversation as resolved.
Show resolved Hide resolved
turn_off_fn=lambda envoy: envoy.go_off_grid(),
)


async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up Enphase Envoy switch 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[SwitchEntity] = []
if envoy_data.enpower:
entities.extend(
[
EnvoyEnpowerSwitchEntity(
coordinator, ENPOWER_GRID_SWITCH, envoy_data.enpower
)
]
)
async_add_entities(entities)


class EnvoyEnpowerSwitchEntity(EnvoyBaseEntity, SwitchEntity):
"""Representation of an Enphase Enpower switch entity."""

entity_description: EnvoyEnpowerSwitchEntityDescription

def __init__(
self,
coordinator: EnphaseUpdateCoordinator,
description: EnvoyEnpowerSwitchEntityDescription,
enpower: EnvoyEnpower,
) -> None:
"""Initialize the Enphase Enpower 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),
)

@property
def is_on(self) -> bool:
"""Return the state of the Enpower switch."""
enpower = self.data.enpower
assert enpower is not None
return self.entity_description.value_fn(enpower)

async def async_turn_on(self):
"""Turn on the Enpower switch."""
await self.entity_description.turn_on_fn(self.envoy)
await self.coordinator.async_request_refresh()

async def async_turn_off(self):
"""Turn off the Enpower switch."""
await self.entity_description.turn_off_fn(self.envoy)
await self.coordinator.async_request_refresh()
2 changes: 1 addition & 1 deletion requirements_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1665,7 +1665,7 @@ pyedimax==0.2.1
pyefergy==22.1.1

# homeassistant.components.enphase_envoy
pyenphase==1.3.0
pyenphase==1.4.0

# homeassistant.components.envisalink
pyenvisalink==4.6
Expand Down
2 changes: 1 addition & 1 deletion requirements_test_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1229,7 +1229,7 @@ pyeconet==0.1.20
pyefergy==22.1.1

# homeassistant.components.enphase_envoy
pyenphase==1.3.0
pyenphase==1.4.0

# homeassistant.components.everlights
pyeverlights==0.1.0
Expand Down