mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Add Insteon backlight control support to ISY994, bump PyISY to 3.1.8 (#85981)
Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
parent
89d085a69c
commit
7636477760
@ -4,6 +4,8 @@ from __future__ import annotations
|
|||||||
from typing import cast
|
from typing import cast
|
||||||
|
|
||||||
from pyisy.constants import (
|
from pyisy.constants import (
|
||||||
|
BACKLIGHT_SUPPORT,
|
||||||
|
CMD_BACKLIGHT,
|
||||||
ISY_VALUE_UNKNOWN,
|
ISY_VALUE_UNKNOWN,
|
||||||
PROP_BUSY,
|
PROP_BUSY,
|
||||||
PROP_COMMS_ERROR,
|
PROP_COMMS_ERROR,
|
||||||
@ -15,6 +17,7 @@ from pyisy.constants import (
|
|||||||
PROTO_PROGRAM,
|
PROTO_PROGRAM,
|
||||||
PROTO_ZWAVE,
|
PROTO_ZWAVE,
|
||||||
TAG_FOLDER,
|
TAG_FOLDER,
|
||||||
|
UOM_INDEX,
|
||||||
)
|
)
|
||||||
from pyisy.nodes import Group, Node, Nodes
|
from pyisy.nodes import Group, Node, Nodes
|
||||||
from pyisy.programs import Programs
|
from pyisy.programs import Programs
|
||||||
@ -277,6 +280,16 @@ def _is_sensor_a_binary_sensor(isy_data: IsyData, node: Group | Node) -> bool:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _add_backlight_if_supported(isy_data: IsyData, node: Node) -> None:
|
||||||
|
"""Check if a node supports setting a backlight and add entity."""
|
||||||
|
if not getattr(node, "is_backlight_supported", False):
|
||||||
|
return
|
||||||
|
if BACKLIGHT_SUPPORT[node.node_def_id] == UOM_INDEX:
|
||||||
|
isy_data.aux_properties[Platform.SELECT].append((node, CMD_BACKLIGHT))
|
||||||
|
return
|
||||||
|
isy_data.aux_properties[Platform.NUMBER].append((node, CMD_BACKLIGHT))
|
||||||
|
|
||||||
|
|
||||||
def _generate_device_info(node: Node) -> DeviceInfo:
|
def _generate_device_info(node: Node) -> DeviceInfo:
|
||||||
"""Generate the device info for a root node device."""
|
"""Generate the device info for a root node device."""
|
||||||
isy = node.isy
|
isy = node.isy
|
||||||
@ -336,6 +349,7 @@ def _categorize_nodes(
|
|||||||
isy_data.aux_properties[Platform.SENSOR].append((node, control))
|
isy_data.aux_properties[Platform.SENSOR].append((node, control))
|
||||||
platform = NODE_AUX_FILTERS[control]
|
platform = NODE_AUX_FILTERS[control]
|
||||||
isy_data.aux_properties[platform].append((node, control))
|
isy_data.aux_properties[platform].append((node, control))
|
||||||
|
_add_backlight_if_supported(isy_data, node)
|
||||||
|
|
||||||
if node.protocol == PROTO_GROUP:
|
if node.protocol == PROTO_GROUP:
|
||||||
isy_data.nodes[ISY_GROUP_PLATFORM].append(node)
|
isy_data.nodes[ISY_GROUP_PLATFORM].append(node)
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"name": "Universal Devices ISY/IoX",
|
"name": "Universal Devices ISY/IoX",
|
||||||
"integration_type": "hub",
|
"integration_type": "hub",
|
||||||
"documentation": "https://www.home-assistant.io/integrations/isy994",
|
"documentation": "https://www.home-assistant.io/integrations/isy994",
|
||||||
"requirements": ["pyisy==3.1.6"],
|
"requirements": ["pyisy==3.1.8"],
|
||||||
"codeowners": ["@bdraco", "@shbatm"],
|
"codeowners": ["@bdraco", "@shbatm"],
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"ssdp": [
|
"ssdp": [
|
||||||
|
@ -4,18 +4,37 @@ from __future__ import annotations
|
|||||||
from dataclasses import replace
|
from dataclasses import replace
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from pyisy.constants import ISY_VALUE_UNKNOWN, PROP_ON_LEVEL
|
from pyisy.constants import (
|
||||||
|
ATTR_ACTION,
|
||||||
|
CMD_BACKLIGHT,
|
||||||
|
DEV_BL_ADDR,
|
||||||
|
DEV_CMD_MEMORY_WRITE,
|
||||||
|
DEV_MEMORY,
|
||||||
|
ISY_VALUE_UNKNOWN,
|
||||||
|
PROP_ON_LEVEL,
|
||||||
|
TAG_ADDRESS,
|
||||||
|
UOM_PERCENTAGE,
|
||||||
|
)
|
||||||
from pyisy.helpers import EventListener, NodeProperty
|
from pyisy.helpers import EventListener, NodeProperty
|
||||||
|
from pyisy.nodes import Node, NodeChangedEvent
|
||||||
from pyisy.variables import Variable
|
from pyisy.variables import Variable
|
||||||
|
|
||||||
from homeassistant.components.number import (
|
from homeassistant.components.number import (
|
||||||
NumberEntity,
|
NumberEntity,
|
||||||
NumberEntityDescription,
|
NumberEntityDescription,
|
||||||
NumberMode,
|
NumberMode,
|
||||||
|
RestoreNumber,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_VARIABLES, PERCENTAGE, Platform
|
from homeassistant.const import (
|
||||||
|
CONF_VARIABLES,
|
||||||
|
PERCENTAGE,
|
||||||
|
STATE_UNAVAILABLE,
|
||||||
|
STATE_UNKNOWN,
|
||||||
|
Platform,
|
||||||
|
)
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers.entity import DeviceInfo, EntityCategory
|
from homeassistant.helpers.entity import DeviceInfo, EntityCategory
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.util.percentage import (
|
from homeassistant.util.percentage import (
|
||||||
@ -42,8 +61,17 @@ CONTROL_DESC = {
|
|||||||
native_min_value=1.0,
|
native_min_value=1.0,
|
||||||
native_max_value=100.0,
|
native_max_value=100.0,
|
||||||
native_step=1.0,
|
native_step=1.0,
|
||||||
)
|
),
|
||||||
|
CMD_BACKLIGHT: NumberEntityDescription(
|
||||||
|
key=CMD_BACKLIGHT,
|
||||||
|
native_unit_of_measurement=PERCENTAGE,
|
||||||
|
entity_category=EntityCategory.CONFIG,
|
||||||
|
native_min_value=0.0,
|
||||||
|
native_max_value=100.0,
|
||||||
|
native_step=1.0,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
BACKLIGHT_MEMORY_FILTER = {"memory": DEV_BL_ADDR, "cmd1": DEV_CMD_MEMORY_WRITE}
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
@ -54,7 +82,9 @@ async def async_setup_entry(
|
|||||||
"""Set up ISY/IoX number entities from config entry."""
|
"""Set up ISY/IoX number entities from config entry."""
|
||||||
isy_data = hass.data[DOMAIN][config_entry.entry_id]
|
isy_data = hass.data[DOMAIN][config_entry.entry_id]
|
||||||
device_info = isy_data.devices
|
device_info = isy_data.devices
|
||||||
entities: list[ISYVariableNumberEntity | ISYAuxControlNumberEntity] = []
|
entities: list[
|
||||||
|
ISYVariableNumberEntity | ISYAuxControlNumberEntity | ISYBacklightNumberEntity
|
||||||
|
] = []
|
||||||
var_id = config_entry.options.get(CONF_VAR_SENSOR_STRING, DEFAULT_VAR_SENSOR_STRING)
|
var_id = config_entry.options.get(CONF_VAR_SENSOR_STRING, DEFAULT_VAR_SENSOR_STRING)
|
||||||
|
|
||||||
for node in isy_data.variables[Platform.NUMBER]:
|
for node in isy_data.variables[Platform.NUMBER]:
|
||||||
@ -95,15 +125,17 @@ async def async_setup_entry(
|
|||||||
)
|
)
|
||||||
|
|
||||||
for node, control in isy_data.aux_properties[Platform.NUMBER]:
|
for node, control in isy_data.aux_properties[Platform.NUMBER]:
|
||||||
entities.append(
|
entity_init_info = {
|
||||||
ISYAuxControlNumberEntity(
|
"node": node,
|
||||||
node=node,
|
"control": control,
|
||||||
control=control,
|
"unique_id": f"{isy_data.uid_base(node)}_{control}",
|
||||||
unique_id=f"{isy_data.uid_base(node)}_{control}",
|
"description": CONTROL_DESC[control],
|
||||||
description=CONTROL_DESC[control],
|
"device_info": device_info.get(node.primary_node),
|
||||||
device_info=device_info.get(node.primary_node),
|
}
|
||||||
)
|
if control == CMD_BACKLIGHT:
|
||||||
)
|
entities.append(ISYBacklightNumberEntity(**entity_init_info))
|
||||||
|
continue
|
||||||
|
entities.append(ISYAuxControlNumberEntity(**entity_init_info))
|
||||||
async_add_entities(entities)
|
async_add_entities(entities)
|
||||||
|
|
||||||
|
|
||||||
@ -140,7 +172,10 @@ class ISYAuxControlNumberEntity(ISYAuxControlEntity, NumberEntity):
|
|||||||
await self._node.set_on_level(value)
|
await self._node.set_on_level(value)
|
||||||
return
|
return
|
||||||
|
|
||||||
await self._node.send_cmd(self._control, val=value, uom=node_prop.uom)
|
if not await self._node.send_cmd(self._control, val=value, uom=node_prop.uom):
|
||||||
|
raise HomeAssistantError(
|
||||||
|
f"Could not set {self.name} to {value} for {self._node.address}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ISYVariableNumberEntity(NumberEntity):
|
class ISYVariableNumberEntity(NumberEntity):
|
||||||
@ -198,4 +233,68 @@ class ISYVariableNumberEntity(NumberEntity):
|
|||||||
|
|
||||||
async def async_set_native_value(self, value: float) -> None:
|
async def async_set_native_value(self, value: float) -> None:
|
||||||
"""Set new value."""
|
"""Set new value."""
|
||||||
await self._node.set_value(value, init=self._init_entity)
|
if not await self._node.set_value(value, init=self._init_entity):
|
||||||
|
raise HomeAssistantError(
|
||||||
|
f"Could not set {self.name} to {value} for {self._node.address}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ISYBacklightNumberEntity(ISYAuxControlEntity, RestoreNumber):
|
||||||
|
"""Representation of a ISY/IoX Backlight Number entity."""
|
||||||
|
|
||||||
|
_assumed_state = True # Backlight values aren't read from device
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
node: Node,
|
||||||
|
control: str,
|
||||||
|
unique_id: str,
|
||||||
|
description: NumberEntityDescription,
|
||||||
|
device_info: DeviceInfo | None,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize the ISY Backlight number entity."""
|
||||||
|
super().__init__(node, control, unique_id, description, device_info)
|
||||||
|
self._memory_change_handler: EventListener | None = None
|
||||||
|
self._attr_native_value = 0
|
||||||
|
|
||||||
|
async def async_added_to_hass(self) -> None:
|
||||||
|
"""Load the last known state when added to hass."""
|
||||||
|
await super().async_added_to_hass()
|
||||||
|
if (last_state := await self.async_get_last_state()) and (
|
||||||
|
last_number_data := await self.async_get_last_number_data()
|
||||||
|
):
|
||||||
|
if last_state.state not in (STATE_UNKNOWN, STATE_UNAVAILABLE):
|
||||||
|
self._attr_native_value = last_number_data.native_value
|
||||||
|
|
||||||
|
# Listen to memory writing events to update state if changed in ISY
|
||||||
|
self._memory_change_handler = self._node.isy.nodes.status_events.subscribe(
|
||||||
|
self.async_on_memory_write,
|
||||||
|
event_filter={
|
||||||
|
TAG_ADDRESS: self._node.address,
|
||||||
|
ATTR_ACTION: DEV_MEMORY,
|
||||||
|
},
|
||||||
|
key=self.unique_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_on_memory_write(self, event: NodeChangedEvent, key: str) -> None:
|
||||||
|
"""Handle a memory write event from the ISY Node."""
|
||||||
|
if not (BACKLIGHT_MEMORY_FILTER.items() <= event.event_info.items()):
|
||||||
|
return # This was not a backlight event
|
||||||
|
value = ranged_value_to_percentage((0, 127), event.event_info["value"])
|
||||||
|
if value == self._attr_native_value:
|
||||||
|
return # Change was from this entity, don't update twice
|
||||||
|
self._attr_native_value = value
|
||||||
|
self.async_write_ha_state()
|
||||||
|
|
||||||
|
async def async_set_native_value(self, value: float) -> None:
|
||||||
|
"""Update the current value."""
|
||||||
|
|
||||||
|
if not await self._node.send_cmd(
|
||||||
|
CMD_BACKLIGHT, val=int(value), uom=UOM_PERCENTAGE
|
||||||
|
):
|
||||||
|
raise HomeAssistantError(
|
||||||
|
f"Could not set backlight to {value}% for {self._node.address}"
|
||||||
|
)
|
||||||
|
self._attr_native_value = value
|
||||||
|
self.async_write_ha_state()
|
||||||
|
@ -4,20 +4,31 @@ from __future__ import annotations
|
|||||||
from typing import cast
|
from typing import cast
|
||||||
|
|
||||||
from pyisy.constants import (
|
from pyisy.constants import (
|
||||||
|
ATTR_ACTION,
|
||||||
|
BACKLIGHT_INDEX,
|
||||||
|
CMD_BACKLIGHT,
|
||||||
COMMAND_FRIENDLY_NAME,
|
COMMAND_FRIENDLY_NAME,
|
||||||
|
DEV_BL_ADDR,
|
||||||
|
DEV_CMD_MEMORY_WRITE,
|
||||||
|
DEV_MEMORY,
|
||||||
INSTEON_RAMP_RATES,
|
INSTEON_RAMP_RATES,
|
||||||
ISY_VALUE_UNKNOWN,
|
ISY_VALUE_UNKNOWN,
|
||||||
PROP_RAMP_RATE,
|
PROP_RAMP_RATE,
|
||||||
|
TAG_ADDRESS,
|
||||||
|
UOM_INDEX as ISY_UOM_INDEX,
|
||||||
UOM_TO_STATES,
|
UOM_TO_STATES,
|
||||||
)
|
)
|
||||||
from pyisy.helpers import NodeProperty
|
from pyisy.helpers import EventListener, NodeProperty
|
||||||
|
from pyisy.nodes import Node, NodeChangedEvent
|
||||||
|
|
||||||
from homeassistant.components.select import SelectEntity, SelectEntityDescription
|
from homeassistant.components.select import SelectEntity, SelectEntityDescription
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import Platform, UnitOfTime
|
from homeassistant.const import STATE_UNAVAILABLE, STATE_UNKNOWN, Platform, UnitOfTime
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers.entity import EntityCategory
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
|
from homeassistant.helpers.entity import DeviceInfo, EntityCategory
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
from homeassistant.helpers.restore_state import RestoreEntity
|
||||||
|
|
||||||
from .const import _LOGGER, DOMAIN, UOM_INDEX
|
from .const import _LOGGER, DOMAIN, UOM_INDEX
|
||||||
from .entity import ISYAuxControlEntity
|
from .entity import ISYAuxControlEntity
|
||||||
@ -32,6 +43,7 @@ def time_string(i: int) -> str:
|
|||||||
|
|
||||||
|
|
||||||
RAMP_RATE_OPTIONS = [time_string(rate) for rate in INSTEON_RAMP_RATES.values()]
|
RAMP_RATE_OPTIONS = [time_string(rate) for rate in INSTEON_RAMP_RATES.values()]
|
||||||
|
BACKLIGHT_MEMORY_FILTER = {"memory": DEV_BL_ADDR, "cmd1": DEV_CMD_MEMORY_WRITE}
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
@ -42,21 +54,26 @@ async def async_setup_entry(
|
|||||||
"""Set up ISY/IoX select entities from config entry."""
|
"""Set up ISY/IoX select entities from config entry."""
|
||||||
isy_data: IsyData = hass.data[DOMAIN][config_entry.entry_id]
|
isy_data: IsyData = hass.data[DOMAIN][config_entry.entry_id]
|
||||||
device_info = isy_data.devices
|
device_info = isy_data.devices
|
||||||
entities: list[ISYAuxControlIndexSelectEntity | ISYRampRateSelectEntity] = []
|
entities: list[
|
||||||
|
ISYAuxControlIndexSelectEntity
|
||||||
|
| ISYRampRateSelectEntity
|
||||||
|
| ISYBacklightSelectEntity
|
||||||
|
] = []
|
||||||
|
|
||||||
for node, control in isy_data.aux_properties[Platform.SELECT]:
|
for node, control in isy_data.aux_properties[Platform.SELECT]:
|
||||||
name = COMMAND_FRIENDLY_NAME.get(control, control).replace("_", " ").title()
|
name = COMMAND_FRIENDLY_NAME.get(control, control).replace("_", " ").title()
|
||||||
if node.address != node.primary_node:
|
if node.address != node.primary_node:
|
||||||
name = f"{node.name} {name}"
|
name = f"{node.name} {name}"
|
||||||
|
|
||||||
node_prop: NodeProperty = node.aux_properties[control]
|
|
||||||
|
|
||||||
options = []
|
options = []
|
||||||
if control == PROP_RAMP_RATE:
|
if control == PROP_RAMP_RATE:
|
||||||
options = RAMP_RATE_OPTIONS
|
options = RAMP_RATE_OPTIONS
|
||||||
if node_prop.uom == UOM_INDEX:
|
elif control == CMD_BACKLIGHT:
|
||||||
if options_dict := UOM_TO_STATES.get(node_prop.uom):
|
options = BACKLIGHT_INDEX
|
||||||
options = list(options_dict.values())
|
else:
|
||||||
|
if uom := node.aux_properties[control].uom == UOM_INDEX:
|
||||||
|
if options_dict := UOM_TO_STATES.get(uom):
|
||||||
|
options = list(options_dict.values())
|
||||||
|
|
||||||
description = SelectEntityDescription(
|
description = SelectEntityDescription(
|
||||||
key=f"{node.address}_{control}",
|
key=f"{node.address}_{control}",
|
||||||
@ -75,6 +92,9 @@ async def async_setup_entry(
|
|||||||
if control == PROP_RAMP_RATE:
|
if control == PROP_RAMP_RATE:
|
||||||
entities.append(ISYRampRateSelectEntity(**entity_detail))
|
entities.append(ISYRampRateSelectEntity(**entity_detail))
|
||||||
continue
|
continue
|
||||||
|
if control == CMD_BACKLIGHT:
|
||||||
|
entities.append(ISYBacklightSelectEntity(**entity_detail))
|
||||||
|
continue
|
||||||
if node.uom == UOM_INDEX and options:
|
if node.uom == UOM_INDEX and options:
|
||||||
entities.append(ISYAuxControlIndexSelectEntity(**entity_detail))
|
entities.append(ISYAuxControlIndexSelectEntity(**entity_detail))
|
||||||
continue
|
continue
|
||||||
@ -124,3 +144,63 @@ class ISYAuxControlIndexSelectEntity(ISYAuxControlEntity, SelectEntity):
|
|||||||
await self._node.send_cmd(
|
await self._node.send_cmd(
|
||||||
self._control, val=self.options.index(option), uom=node_prop.uom
|
self._control, val=self.options.index(option), uom=node_prop.uom
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ISYBacklightSelectEntity(ISYAuxControlEntity, SelectEntity, RestoreEntity):
|
||||||
|
"""Representation of a ISY/IoX Backlight Select entity."""
|
||||||
|
|
||||||
|
_assumed_state = True # Backlight values aren't read from device
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
node: Node,
|
||||||
|
control: str,
|
||||||
|
unique_id: str,
|
||||||
|
description: SelectEntityDescription,
|
||||||
|
device_info: DeviceInfo | None,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize the ISY Backlight Select entity."""
|
||||||
|
super().__init__(node, control, unique_id, description, device_info)
|
||||||
|
self._memory_change_handler: EventListener | None = None
|
||||||
|
self._attr_current_option = None
|
||||||
|
|
||||||
|
async def async_added_to_hass(self) -> None:
|
||||||
|
"""Load the last known state when added to hass."""
|
||||||
|
await super().async_added_to_hass()
|
||||||
|
if (
|
||||||
|
last_state := await self.async_get_last_state()
|
||||||
|
) and last_state.state not in (STATE_UNKNOWN, STATE_UNAVAILABLE):
|
||||||
|
self._attr_current_option = last_state.state
|
||||||
|
|
||||||
|
# Listen to memory writing events to update state if changed in ISY
|
||||||
|
self._memory_change_handler = self._node.isy.nodes.status_events.subscribe(
|
||||||
|
self.async_on_memory_write,
|
||||||
|
event_filter={
|
||||||
|
TAG_ADDRESS: self._node.address,
|
||||||
|
ATTR_ACTION: DEV_MEMORY,
|
||||||
|
},
|
||||||
|
key=self.unique_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_on_memory_write(self, event: NodeChangedEvent, key: str) -> None:
|
||||||
|
"""Handle a memory write event from the ISY Node."""
|
||||||
|
if not (BACKLIGHT_MEMORY_FILTER.items() <= event.event_info.items()):
|
||||||
|
return # This was not a backlight event
|
||||||
|
option = BACKLIGHT_INDEX[event.event_info["value"]]
|
||||||
|
if option == self._attr_current_option:
|
||||||
|
return # Change was from this entity, don't update twice
|
||||||
|
self._attr_current_option = option
|
||||||
|
self.async_write_ha_state()
|
||||||
|
|
||||||
|
async def async_select_option(self, option: str) -> None:
|
||||||
|
"""Change the selected option."""
|
||||||
|
|
||||||
|
if not await self._node.send_cmd(
|
||||||
|
CMD_BACKLIGHT, val=BACKLIGHT_INDEX.index(option), uom=ISY_UOM_INDEX
|
||||||
|
):
|
||||||
|
raise HomeAssistantError(
|
||||||
|
f"Could not set backlight to {option} for {self._node.address}"
|
||||||
|
)
|
||||||
|
self._attr_current_option = option
|
||||||
|
self.async_write_ha_state()
|
||||||
|
@ -1693,7 +1693,7 @@ pyirishrail==0.0.2
|
|||||||
pyiss==1.0.1
|
pyiss==1.0.1
|
||||||
|
|
||||||
# homeassistant.components.isy994
|
# homeassistant.components.isy994
|
||||||
pyisy==3.1.6
|
pyisy==3.1.8
|
||||||
|
|
||||||
# homeassistant.components.itach
|
# homeassistant.components.itach
|
||||||
pyitachip2ir==0.0.7
|
pyitachip2ir==0.0.7
|
||||||
|
@ -1212,7 +1212,7 @@ pyiqvia==2022.04.0
|
|||||||
pyiss==1.0.1
|
pyiss==1.0.1
|
||||||
|
|
||||||
# homeassistant.components.isy994
|
# homeassistant.components.isy994
|
||||||
pyisy==3.1.6
|
pyisy==3.1.8
|
||||||
|
|
||||||
# homeassistant.components.kaleidescape
|
# homeassistant.components.kaleidescape
|
||||||
pykaleidescape==1.0.1
|
pykaleidescape==1.0.1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user