Add enable/disable config switch for ISY994 devices (#85975)
Co-authored-by: J. Nick Koston <nick@koston.org>pull/86013/head^2
parent
b087c1e734
commit
3aad153913
|
@ -87,7 +87,12 @@ NODE_PLATFORMS = [
|
|||
Platform.SENSOR,
|
||||
Platform.SWITCH,
|
||||
]
|
||||
NODE_AUX_PROP_PLATFORMS = [Platform.SELECT, Platform.SENSOR, Platform.NUMBER]
|
||||
NODE_AUX_PROP_PLATFORMS = [
|
||||
Platform.NUMBER,
|
||||
Platform.SELECT,
|
||||
Platform.SENSOR,
|
||||
Platform.SWITCH,
|
||||
]
|
||||
PROGRAM_PLATFORMS = [
|
||||
Platform.BINARY_SENSOR,
|
||||
Platform.COVER,
|
||||
|
|
|
@ -16,6 +16,7 @@ from pyisy.constants import (
|
|||
PROTO_INSTEON,
|
||||
PROTO_PROGRAM,
|
||||
PROTO_ZWAVE,
|
||||
TAG_ENABLED,
|
||||
TAG_FOLDER,
|
||||
UOM_INDEX,
|
||||
)
|
||||
|
@ -349,6 +350,8 @@ def _categorize_nodes(
|
|||
isy_data.aux_properties[Platform.SENSOR].append((node, control))
|
||||
platform = NODE_AUX_FILTERS[control]
|
||||
isy_data.aux_properties[platform].append((node, control))
|
||||
if hasattr(node, TAG_ENABLED):
|
||||
isy_data.aux_properties[Platform.SWITCH].append((node, TAG_ENABLED))
|
||||
_add_backlight_if_supported(isy_data, node)
|
||||
|
||||
if node.protocol == PROTO_GROUP:
|
||||
|
|
|
@ -3,16 +3,30 @@ from __future__ import annotations
|
|||
|
||||
from typing import Any
|
||||
|
||||
from pyisy.constants import ISY_VALUE_UNKNOWN, PROTO_GROUP
|
||||
from pyisy.constants import (
|
||||
ATTR_ACTION,
|
||||
ISY_VALUE_UNKNOWN,
|
||||
NC_NODE_ENABLED,
|
||||
PROTO_GROUP,
|
||||
TAG_ADDRESS,
|
||||
)
|
||||
from pyisy.helpers import EventListener
|
||||
from pyisy.nodes import Node, NodeChangedEvent
|
||||
|
||||
from homeassistant.components.switch import SwitchEntity
|
||||
from homeassistant.components.switch import (
|
||||
SwitchDeviceClass,
|
||||
SwitchEntity,
|
||||
SwitchEntityDescription,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.entity import DeviceInfo, EntityCategory, EntityDescription
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import _LOGGER, DOMAIN
|
||||
from .entity import ISYNodeEntity, ISYProgramEntity
|
||||
from .const import DOMAIN
|
||||
from .entity import ISYAuxControlEntity, ISYNodeEntity, ISYProgramEntity
|
||||
from .models import IsyData
|
||||
|
||||
|
||||
|
@ -21,7 +35,9 @@ async def async_setup_entry(
|
|||
) -> None:
|
||||
"""Set up the ISY switch platform."""
|
||||
isy_data: IsyData = hass.data[DOMAIN][entry.entry_id]
|
||||
entities: list[ISYSwitchProgramEntity | ISYSwitchEntity] = []
|
||||
entities: list[
|
||||
ISYSwitchProgramEntity | ISYSwitchEntity | ISYEnableSwitchEntity
|
||||
] = []
|
||||
device_info = isy_data.devices
|
||||
for node in isy_data.nodes[Platform.SWITCH]:
|
||||
primary = node.primary_node
|
||||
|
@ -34,6 +50,24 @@ async def async_setup_entry(
|
|||
for name, status, actions in isy_data.programs[Platform.SWITCH]:
|
||||
entities.append(ISYSwitchProgramEntity(name, status, actions))
|
||||
|
||||
for node, control in isy_data.aux_properties[Platform.SWITCH]:
|
||||
# Currently only used for enable switches, will need to be updated for NS support
|
||||
# by making sure control == TAG_ENABLED
|
||||
description = SwitchEntityDescription(
|
||||
key=control,
|
||||
device_class=SwitchDeviceClass.SWITCH,
|
||||
name=control.title(),
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
)
|
||||
entities.append(
|
||||
ISYEnableSwitchEntity(
|
||||
node=node,
|
||||
control=control,
|
||||
unique_id=f"{isy_data.uid_base(node)}_{control}",
|
||||
description=description,
|
||||
device_info=device_info.get(node.primary_node),
|
||||
)
|
||||
)
|
||||
async_add_entities(entities)
|
||||
|
||||
|
||||
|
@ -50,12 +84,12 @@ class ISYSwitchEntity(ISYNodeEntity, SwitchEntity):
|
|||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Send the turn off command to the ISY switch."""
|
||||
if not await self._node.turn_off():
|
||||
_LOGGER.debug("Unable to turn off switch")
|
||||
HomeAssistantError(f"Unable to turn off switch {self._node.address}")
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Send the turn on command to the ISY switch."""
|
||||
if not await self._node.turn_on():
|
||||
_LOGGER.debug("Unable to turn on switch")
|
||||
HomeAssistantError(f"Unable to turn on switch {self._node.address}")
|
||||
|
||||
@property
|
||||
def icon(self) -> str | None:
|
||||
|
@ -76,14 +110,77 @@ class ISYSwitchProgramEntity(ISYProgramEntity, SwitchEntity):
|
|||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Send the turn on command to the ISY switch program."""
|
||||
if not await self._actions.run_then():
|
||||
_LOGGER.error("Unable to turn on switch")
|
||||
HomeAssistantError(
|
||||
f"Unable to run 'then' clause on program switch {self._actions.address}"
|
||||
)
|
||||
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Send the turn off command to the ISY switch program."""
|
||||
if not await self._actions.run_else():
|
||||
_LOGGER.error("Unable to turn off switch")
|
||||
HomeAssistantError(
|
||||
f"Unable to run 'else' clause on program switch {self._actions.address}"
|
||||
)
|
||||
|
||||
@property
|
||||
def icon(self) -> str:
|
||||
"""Get the icon for programs."""
|
||||
return "mdi:script-text-outline" # Matches isy program icon
|
||||
|
||||
|
||||
class ISYEnableSwitchEntity(ISYAuxControlEntity, SwitchEntity):
|
||||
"""A representation of an ISY enable/disable switch."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
node: Node,
|
||||
control: str,
|
||||
unique_id: str,
|
||||
description: EntityDescription,
|
||||
device_info: DeviceInfo | None,
|
||||
) -> None:
|
||||
"""Initialize the ISY Aux Control Number entity."""
|
||||
super().__init__(
|
||||
node=node,
|
||||
control=control,
|
||||
unique_id=unique_id,
|
||||
description=description,
|
||||
device_info=device_info,
|
||||
)
|
||||
self._attr_name = description.name # Override super
|
||||
self._change_handler: EventListener = None
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Subscribe to the node control change events."""
|
||||
self._change_handler = self._node.isy.nodes.status_events.subscribe(
|
||||
self.async_on_update,
|
||||
event_filter={
|
||||
TAG_ADDRESS: self._node.address,
|
||||
ATTR_ACTION: NC_NODE_ENABLED,
|
||||
},
|
||||
key=self.unique_id,
|
||||
)
|
||||
|
||||
@callback
|
||||
def async_on_update(self, event: NodeChangedEvent, key: str) -> None:
|
||||
"""Handle a control event from the ISY Node."""
|
||||
self.async_write_ha_state()
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
"""Return entity availability."""
|
||||
return True # Enable switch is always available
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool | None:
|
||||
"""Get whether the ISY device is in the on state."""
|
||||
return bool(self._node.enabled)
|
||||
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Send the turn off command to the ISY switch."""
|
||||
if not await self._node.disable():
|
||||
raise HomeAssistantError(f"Unable to disable device {self._node.address}")
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Send the turn on command to the ISY switch."""
|
||||
if not await self._node.enable():
|
||||
raise HomeAssistantError(f"Unable to enable device {self._node.address}")
|
||||
|
|
Loading…
Reference in New Issue