Remove home_plus_control and mark as virtual integration supported by Netatmo (#107587)
* Mark home_plus_control a virtual integration using Netatmo * Apply code review suggestion Co-authored-by: Robert Resch <robert@resch.dev> --------- Co-authored-by: Robert Resch <robert@resch.dev>
This commit is contained in:
parent
f3b1f47d34
commit
13887793a7
19 changed files with 5 additions and 1418 deletions
|
@ -1,208 +1 @@
|
|||
"""The Legrand Home+ Control integration."""
|
||||
import asyncio
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
from homepluscontrol.homeplusapi import HomePlusControlApiError
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET, Platform
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import (
|
||||
config_entry_oauth2_flow,
|
||||
config_validation as cv,
|
||||
dispatcher,
|
||||
)
|
||||
from homeassistant.helpers.device_registry import async_get as async_get_device_registry
|
||||
from homeassistant.helpers.issue_registry import (
|
||||
IssueSeverity,
|
||||
async_create_issue,
|
||||
async_delete_issue,
|
||||
)
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
|
||||
from . import config_flow, helpers
|
||||
from .api import HomePlusControlAsyncApi
|
||||
from .const import (
|
||||
API,
|
||||
CONF_SUBSCRIPTION_KEY,
|
||||
DATA_COORDINATOR,
|
||||
DISPATCHER_REMOVERS,
|
||||
DOMAIN,
|
||||
ENTITY_UIDS,
|
||||
SIGNAL_ADD_ENTITIES,
|
||||
)
|
||||
|
||||
# Configuration schema for component in configuration.yaml
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
{
|
||||
DOMAIN: vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_CLIENT_ID): cv.string,
|
||||
vol.Required(CONF_CLIENT_SECRET): cv.string,
|
||||
vol.Required(CONF_SUBSCRIPTION_KEY): cv.string,
|
||||
}
|
||||
)
|
||||
},
|
||||
extra=vol.ALLOW_EXTRA,
|
||||
)
|
||||
|
||||
# The Legrand Home+ Control platform is currently limited to "switch" entities
|
||||
PLATFORMS = [Platform.SWITCH]
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
_ISSUE_MOVE_TO_NETATMO = "move_to_netatmo"
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
"""Set up the Legrand Home+ Control component from configuration.yaml."""
|
||||
hass.data[DOMAIN] = {}
|
||||
|
||||
if DOMAIN not in config:
|
||||
return True
|
||||
|
||||
async_create_issue(
|
||||
hass,
|
||||
DOMAIN,
|
||||
_ISSUE_MOVE_TO_NETATMO,
|
||||
is_fixable=False,
|
||||
is_persistent=False,
|
||||
breaks_in_ha_version="2023.12.0", # Netatmo decided to shutdown the api in december
|
||||
severity=IssueSeverity.WARNING,
|
||||
translation_key=_ISSUE_MOVE_TO_NETATMO,
|
||||
translation_placeholders={
|
||||
"url": "https://www.home-assistant.io/integrations/netatmo/"
|
||||
},
|
||||
)
|
||||
|
||||
# Register the implementation from the config information
|
||||
config_flow.HomePlusControlFlowHandler.async_register_implementation(
|
||||
hass,
|
||||
helpers.HomePlusControlOAuth2Implementation(hass, config[DOMAIN]),
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Set up Legrand Home+ Control from a config entry."""
|
||||
hass_entry_data = hass.data[DOMAIN].setdefault(entry.entry_id, {})
|
||||
|
||||
async_create_issue(
|
||||
hass,
|
||||
DOMAIN,
|
||||
_ISSUE_MOVE_TO_NETATMO,
|
||||
is_fixable=False,
|
||||
is_persistent=False,
|
||||
breaks_in_ha_version="2023.12.0", # Netatmo decided to shutdown the api in december
|
||||
severity=IssueSeverity.WARNING,
|
||||
translation_key=_ISSUE_MOVE_TO_NETATMO,
|
||||
translation_placeholders={
|
||||
"url": "https://www.home-assistant.io/integrations/netatmo/"
|
||||
},
|
||||
)
|
||||
|
||||
# Retrieve the registered implementation
|
||||
implementation = (
|
||||
await config_entry_oauth2_flow.async_get_config_entry_implementation(
|
||||
hass, entry
|
||||
)
|
||||
)
|
||||
|
||||
# Using an aiohttp-based API lib, so rely on async framework
|
||||
# Add the API object to the domain's data in HA
|
||||
api = hass_entry_data[API] = HomePlusControlAsyncApi(hass, entry, implementation)
|
||||
|
||||
# Set of entity unique identifiers of this integration
|
||||
uids: set[str] = set()
|
||||
hass_entry_data[ENTITY_UIDS] = uids
|
||||
|
||||
# Integration dispatchers
|
||||
hass_entry_data[DISPATCHER_REMOVERS] = []
|
||||
|
||||
device_registry = async_get_device_registry(hass)
|
||||
|
||||
# Register the Data Coordinator with the integration
|
||||
async def async_update_data():
|
||||
"""Fetch data from API endpoint.
|
||||
|
||||
This is the place to pre-process the data to lookup tables
|
||||
so entities can quickly look up their data.
|
||||
"""
|
||||
try:
|
||||
# Note: asyncio.TimeoutError and aiohttp.ClientError are already
|
||||
# handled by the data update coordinator.
|
||||
async with asyncio.timeout(10):
|
||||
return await api.async_get_modules()
|
||||
except HomePlusControlApiError as err:
|
||||
raise UpdateFailed(
|
||||
f"Error communicating with API: {err} [{type(err)}]"
|
||||
) from err
|
||||
|
||||
coordinator = DataUpdateCoordinator(
|
||||
hass,
|
||||
_LOGGER,
|
||||
# Name of the data. For logging purposes.
|
||||
name="home_plus_control_module",
|
||||
update_method=async_update_data,
|
||||
# Polling interval. Will only be polled if there are subscribers.
|
||||
update_interval=timedelta(seconds=300),
|
||||
)
|
||||
hass_entry_data[DATA_COORDINATOR] = coordinator
|
||||
|
||||
@callback
|
||||
def _async_update_entities():
|
||||
"""Process entities and add or remove them based after an update."""
|
||||
if not (module_data := coordinator.data):
|
||||
return
|
||||
|
||||
# Remove obsolete entities from Home Assistant
|
||||
entity_uids_to_remove = uids - set(module_data)
|
||||
for uid in entity_uids_to_remove:
|
||||
uids.remove(uid)
|
||||
device = device_registry.async_get_device(identifiers={(DOMAIN, uid)})
|
||||
device_registry.async_remove_device(device.id)
|
||||
|
||||
# Send out signal for new entity addition to Home Assistant
|
||||
new_entity_uids = set(module_data) - uids
|
||||
if new_entity_uids:
|
||||
uids.update(new_entity_uids)
|
||||
dispatcher.async_dispatcher_send(
|
||||
hass,
|
||||
SIGNAL_ADD_ENTITIES,
|
||||
new_entity_uids,
|
||||
coordinator,
|
||||
)
|
||||
|
||||
entry.async_on_unload(coordinator.async_add_listener(_async_update_entities))
|
||||
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
|
||||
# Only refresh the coordinator after all platforms are loaded.
|
||||
await coordinator.async_refresh()
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
|
||||
"""Unload the Legrand Home+ Control config entry."""
|
||||
unload_ok = await hass.config_entries.async_unload_platforms(
|
||||
config_entry, PLATFORMS
|
||||
)
|
||||
if unload_ok:
|
||||
# Unsubscribe the config_entry signal dispatcher connections
|
||||
dispatcher_removers = hass.data[DOMAIN][config_entry.entry_id].pop(
|
||||
"dispatcher_removers"
|
||||
)
|
||||
for remover in dispatcher_removers:
|
||||
remover()
|
||||
|
||||
# And finally unload the domain config entry data
|
||||
hass.data[DOMAIN].pop(config_entry.entry_id)
|
||||
|
||||
async_delete_issue(hass, DOMAIN, _ISSUE_MOVE_TO_NETATMO)
|
||||
|
||||
return unload_ok
|
||||
"""Virtual integration: Legrand Home+ Control."""
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
"""API for Legrand Home+ Control bound to Home Assistant OAuth."""
|
||||
from homepluscontrol.homeplusapi import HomePlusControlAPI
|
||||
|
||||
from homeassistant import config_entries, core
|
||||
from homeassistant.helpers import aiohttp_client, config_entry_oauth2_flow
|
||||
|
||||
from .const import DEFAULT_UPDATE_INTERVALS
|
||||
from .helpers import HomePlusControlOAuth2Implementation
|
||||
|
||||
|
||||
class HomePlusControlAsyncApi(HomePlusControlAPI):
|
||||
"""Legrand Home+ Control object that interacts with the OAuth2-based API of the provider.
|
||||
|
||||
This API is bound the HomeAssistant Config Entry that corresponds to this component.
|
||||
|
||||
Attributes:.
|
||||
hass (HomeAssistant): HomeAssistant core object.
|
||||
config_entry (ConfigEntry): ConfigEntry object that configures this API.
|
||||
implementation (AbstractOAuth2Implementation): OAuth2 implementation that handles AA and
|
||||
token refresh.
|
||||
_oauth_session (OAuth2Session): OAuth2Session object within implementation.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
hass: core.HomeAssistant,
|
||||
config_entry: config_entries.ConfigEntry,
|
||||
implementation: config_entry_oauth2_flow.AbstractOAuth2Implementation,
|
||||
) -> None:
|
||||
"""Initialize the HomePlusControlAsyncApi object.
|
||||
|
||||
Initialize the authenticated API for the Legrand Home+ Control component.
|
||||
|
||||
Args:.
|
||||
hass (HomeAssistant): HomeAssistant core object.
|
||||
config_entry (ConfigEntry): ConfigEntry object that configures this API.
|
||||
implementation (AbstractOAuth2Implementation): OAuth2 implementation that handles AA
|
||||
and token refresh.
|
||||
"""
|
||||
self._oauth_session = config_entry_oauth2_flow.OAuth2Session(
|
||||
hass, config_entry, implementation
|
||||
)
|
||||
|
||||
assert isinstance(implementation, HomePlusControlOAuth2Implementation)
|
||||
|
||||
# Create the API authenticated client - external library
|
||||
super().__init__(
|
||||
subscription_key=implementation.subscription_key,
|
||||
oauth_client=aiohttp_client.async_get_clientsession(hass),
|
||||
update_intervals=DEFAULT_UPDATE_INTERVALS,
|
||||
)
|
||||
|
||||
async def async_get_access_token(self) -> str:
|
||||
"""Return a valid access token."""
|
||||
if not self._oauth_session.valid_token:
|
||||
await self._oauth_session.async_ensure_token_valid()
|
||||
|
||||
return self._oauth_session.token["access_token"]
|
|
@ -1,30 +0,0 @@
|
|||
"""Config flow for Legrand Home+ Control."""
|
||||
import logging
|
||||
|
||||
from homeassistant.helpers import config_entry_oauth2_flow
|
||||
|
||||
from .const import DOMAIN
|
||||
|
||||
|
||||
class HomePlusControlFlowHandler(
|
||||
config_entry_oauth2_flow.AbstractOAuth2FlowHandler, domain=DOMAIN
|
||||
):
|
||||
"""Config flow to handle Home+ Control OAuth2 authentication."""
|
||||
|
||||
DOMAIN = DOMAIN
|
||||
|
||||
# Pick the Cloud Poll class
|
||||
|
||||
@property
|
||||
def logger(self) -> logging.Logger:
|
||||
"""Return logger."""
|
||||
return logging.getLogger(__name__)
|
||||
|
||||
async def async_step_user(self, user_input=None):
|
||||
"""Handle a flow start initiated by the user."""
|
||||
await self.async_set_unique_id(DOMAIN)
|
||||
|
||||
if self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
|
||||
return await super().async_step_user(user_input)
|
|
@ -1,45 +0,0 @@
|
|||
"""Constants for the Legrand Home+ Control integration."""
|
||||
API = "api"
|
||||
CONF_SUBSCRIPTION_KEY = "subscription_key"
|
||||
CONF_PLANT_UPDATE_INTERVAL = "plant_update_interval"
|
||||
CONF_PLANT_TOPOLOGY_UPDATE_INTERVAL = "plant_topology_update_interval"
|
||||
CONF_MODULE_STATUS_UPDATE_INTERVAL = "module_status_update_interval"
|
||||
|
||||
DATA_COORDINATOR = "coordinator"
|
||||
DOMAIN = "home_plus_control"
|
||||
ENTITY_UIDS = "entity_unique_ids"
|
||||
DISPATCHER_REMOVERS = "dispatcher_removers"
|
||||
|
||||
# Legrand Model Identifiers - https://developer.legrand.com/documentation/product-cluster-list/#
|
||||
HW_TYPE = {
|
||||
"NLC": "NLC - Cable Outlet",
|
||||
"NLF": "NLF - On-Off Dimmer Switch w/o Neutral",
|
||||
"NLP": "NLP - Socket (Connected) Outlet",
|
||||
"NLPM": "NLPM - Mobile Socket Outlet",
|
||||
"NLM": "NLM - Micromodule Switch",
|
||||
"NLV": "NLV - Shutter Switch with Neutral",
|
||||
"NLLV": "NLLV - Shutter Switch with Level Control",
|
||||
"NLL": "NLL - On-Off Toggle Switch with Neutral",
|
||||
"NLT": "NLT - Remote Switch",
|
||||
"NLD": "NLD - Double Gangs On-Off Remote Switch",
|
||||
}
|
||||
|
||||
# Legrand OAuth2 URIs
|
||||
OAUTH2_AUTHORIZE = "https://partners-login.eliotbylegrand.com/authorize"
|
||||
OAUTH2_TOKEN = "https://partners-login.eliotbylegrand.com/token"
|
||||
|
||||
# The Legrand Home+ Control API has very limited request quotas - at the time of writing, it is
|
||||
# limited to 500 calls per day (resets at 00:00) - so we want to keep updates to a minimum.
|
||||
DEFAULT_UPDATE_INTERVALS = {
|
||||
# Seconds between API checks for plant information updates. This is expected to change very
|
||||
# little over time because a user's plants (homes) should rarely change.
|
||||
CONF_PLANT_UPDATE_INTERVAL: 7200, # 120 minutes
|
||||
# Seconds between API checks for plant topology updates. This is expected to change little
|
||||
# over time because the modules in the user's plant should be relatively stable.
|
||||
CONF_PLANT_TOPOLOGY_UPDATE_INTERVAL: 3600, # 60 minutes
|
||||
# Seconds between API checks for module status updates. This can change frequently so we
|
||||
# check often
|
||||
CONF_MODULE_STATUS_UPDATE_INTERVAL: 300, # 5 minutes
|
||||
}
|
||||
|
||||
SIGNAL_ADD_ENTITIES = "home_plus_control_add_entities_signal"
|
|
@ -1,53 +0,0 @@
|
|||
"""Helper classes and functions for the Legrand Home+ Control integration."""
|
||||
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import config_entry_oauth2_flow
|
||||
|
||||
from .const import CONF_SUBSCRIPTION_KEY, DOMAIN, OAUTH2_AUTHORIZE, OAUTH2_TOKEN
|
||||
|
||||
|
||||
class HomePlusControlOAuth2Implementation(
|
||||
config_entry_oauth2_flow.LocalOAuth2Implementation
|
||||
):
|
||||
"""OAuth2 implementation that extends the HomeAssistant local implementation.
|
||||
|
||||
It provides the name of the integration and adds support for the subscription key.
|
||||
|
||||
Attributes:
|
||||
hass (HomeAssistant): HomeAssistant core object.
|
||||
client_id (str): Client identifier assigned by the API provider when registering an app.
|
||||
client_secret (str): Client secret assigned by the API provider when registering an app.
|
||||
subscription_key (str): Subscription key obtained from the API provider.
|
||||
authorize_url (str): Authorization URL initiate authentication flow.
|
||||
token_url (str): URL to retrieve access/refresh tokens.
|
||||
name (str): Name of the implementation (appears in the HomeAssistant GUI).
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
config_data: dict,
|
||||
) -> None:
|
||||
"""HomePlusControlOAuth2Implementation Constructor.
|
||||
|
||||
Initialize the authentication implementation for the Legrand Home+ Control API.
|
||||
|
||||
Args:
|
||||
hass (HomeAssistant): HomeAssistant core object.
|
||||
config_data (dict): Configuration data that complies with the config Schema
|
||||
of this component.
|
||||
"""
|
||||
super().__init__(
|
||||
hass=hass,
|
||||
domain=DOMAIN,
|
||||
client_id=config_data[CONF_CLIENT_ID],
|
||||
client_secret=config_data[CONF_CLIENT_SECRET],
|
||||
authorize_url=OAUTH2_AUTHORIZE,
|
||||
token_url=OAUTH2_TOKEN,
|
||||
)
|
||||
self.subscription_key = config_data[CONF_SUBSCRIPTION_KEY]
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""Name of the implementation."""
|
||||
return "Home+ Control"
|
|
@ -1,11 +1,6 @@
|
|||
{
|
||||
"domain": "home_plus_control",
|
||||
"name": "Legrand Home+ Control",
|
||||
"codeowners": ["@chemaaa"],
|
||||
"config_flow": true,
|
||||
"dependencies": ["auth"],
|
||||
"documentation": "https://www.home-assistant.io/integrations/home_plus_control",
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["homepluscontrol"],
|
||||
"requirements": ["homepluscontrol==0.0.5"]
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "netatmo"
|
||||
}
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"pick_implementation": {
|
||||
"title": "[%key:common::config_flow::title::oauth2_pick_implementation%]"
|
||||
}
|
||||
},
|
||||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_account%]",
|
||||
"already_in_progress": "[%key:common::config_flow::abort::already_in_progress%]",
|
||||
"missing_configuration": "[%key:common::config_flow::abort::oauth2_missing_configuration%]",
|
||||
"authorize_url_timeout": "[%key:common::config_flow::abort::oauth2_authorize_url_timeout%]",
|
||||
"no_url_available": "[%key:common::config_flow::abort::oauth2_no_url_available%]",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]",
|
||||
"oauth_error": "[%key:common::config_flow::abort::oauth2_error%]",
|
||||
"oauth_timeout": "[%key:common::config_flow::abort::oauth2_timeout%]",
|
||||
"oauth_unauthorized": "[%key:common::config_flow::abort::oauth2_unauthorized%]",
|
||||
"oauth_failed": "[%key:common::config_flow::abort::oauth2_failed%]"
|
||||
},
|
||||
"create_entry": {
|
||||
"default": "[%key:common::config_flow::create_entry::authenticated%]"
|
||||
}
|
||||
},
|
||||
"issues": {
|
||||
"move_to_netatmo": {
|
||||
"title": "Legrand Home+ Control deprecation",
|
||||
"description": "Home Assistant has been informed that the platform the Legrand Home+ Control integration is using, will be shutting down upcoming December.\n\nOnce that happens, it means this integration is no longer functional. We advise you to remove this integration and switch to the [Netatmo]({url}) integration, which provides a replacement for controlling your Legrand Home+ Control devices."
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,131 +0,0 @@
|
|||
"""Legrand Home+ Control Switch Entity Module that uses the HomeAssistant DataUpdateCoordinator."""
|
||||
from functools import partial
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.components.switch import SwitchDeviceClass, SwitchEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import dispatcher
|
||||
from homeassistant.helpers.device_registry import DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from .const import DISPATCHER_REMOVERS, DOMAIN, HW_TYPE, SIGNAL_ADD_ENTITIES
|
||||
|
||||
|
||||
@callback
|
||||
def add_switch_entities(new_unique_ids, coordinator, add_entities):
|
||||
"""Add switch entities to the platform.
|
||||
|
||||
Args:
|
||||
new_unique_ids (set): Unique identifiers of entities to be added to Home Assistant.
|
||||
coordinator (DataUpdateCoordinator): Data coordinator of this platform.
|
||||
add_entities (function): Method called to add entities to Home Assistant.
|
||||
"""
|
||||
new_entities = []
|
||||
for uid in new_unique_ids:
|
||||
new_ent = HomeControlSwitchEntity(coordinator, uid)
|
||||
new_entities.append(new_ent)
|
||||
add_entities(new_entities)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up the Legrand Home+ Control Switch platform in HomeAssistant.
|
||||
|
||||
Args:
|
||||
hass (HomeAssistant): HomeAssistant core object.
|
||||
config_entry (ConfigEntry): ConfigEntry object that configures this platform.
|
||||
async_add_entities (function): Function called to add entities of this platform.
|
||||
"""
|
||||
partial_add_switch_entities = partial(
|
||||
add_switch_entities, add_entities=async_add_entities
|
||||
)
|
||||
# Connect the dispatcher for the switch platform
|
||||
hass.data[DOMAIN][config_entry.entry_id][DISPATCHER_REMOVERS].append(
|
||||
dispatcher.async_dispatcher_connect(
|
||||
hass, SIGNAL_ADD_ENTITIES, partial_add_switch_entities
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class HomeControlSwitchEntity(CoordinatorEntity, SwitchEntity):
|
||||
"""Entity that represents a Legrand Home+ Control switch.
|
||||
|
||||
It extends the HomeAssistant-provided classes of the CoordinatorEntity and the SwitchEntity.
|
||||
|
||||
The CoordinatorEntity class provides:
|
||||
should_poll
|
||||
async_update
|
||||
async_added_to_hass
|
||||
|
||||
The SwitchEntity class provides the functionality of a ToggleEntity and additional power
|
||||
consumption methods and state attributes.
|
||||
"""
|
||||
|
||||
_attr_has_entity_name = True
|
||||
_attr_name = None
|
||||
|
||||
def __init__(self, coordinator, idx):
|
||||
"""Pass coordinator to CoordinatorEntity."""
|
||||
super().__init__(coordinator)
|
||||
self.idx = idx
|
||||
self.module = self.coordinator.data[self.idx]
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
"""ID (unique) of the device."""
|
||||
return self.idx
|
||||
|
||||
@property
|
||||
def device_info(self) -> DeviceInfo:
|
||||
"""Device information."""
|
||||
return DeviceInfo(
|
||||
identifiers={
|
||||
# Unique identifiers within the domain
|
||||
(DOMAIN, self.unique_id)
|
||||
},
|
||||
manufacturer="Legrand",
|
||||
model=HW_TYPE.get(self.module.hw_type),
|
||||
name=self.module.name,
|
||||
sw_version=self.module.fw,
|
||||
)
|
||||
|
||||
@property
|
||||
def device_class(self):
|
||||
"""Return the class of this device, from component DEVICE_CLASSES."""
|
||||
if self.module.device == "plug":
|
||||
return SwitchDeviceClass.OUTLET
|
||||
return SwitchDeviceClass.SWITCH
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
"""Return if entity is available.
|
||||
|
||||
This is the case when the coordinator is able to update the data successfully
|
||||
AND the switch entity is reachable.
|
||||
|
||||
This method overrides the one of the CoordinatorEntity
|
||||
"""
|
||||
return self.coordinator.last_update_success and self.module.reachable
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return entity state."""
|
||||
return self.module.status == "on"
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the light on."""
|
||||
# Do the turning on.
|
||||
await self.module.turn_on()
|
||||
# Update the data
|
||||
await self.coordinator.async_request_refresh()
|
||||
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn the entity off."""
|
||||
await self.module.turn_off()
|
||||
# Update the data
|
||||
await self.coordinator.async_request_refresh()
|
Loading…
Add table
Add a link
Reference in a new issue