diff --git a/homeassistant/components/lutron_caseta/__init__.py b/homeassistant/components/lutron_caseta/__init__.py index 3c74e378336..d91dc8f31e5 100644 --- a/homeassistant/components/lutron_caseta/__init__.py +++ b/homeassistant/components/lutron_caseta/__init__.py @@ -1,19 +1,19 @@ """Component for interacting with a Lutron Caseta system.""" +from __future__ import annotations + import asyncio import contextlib import logging import ssl -from aiolip import LIP -from aiolip.data import LIPMode -from aiolip.protocol import LIP_BUTTON_PRESS import async_timeout +from pylutron_caseta import BUTTON_STATUS_PRESSED from pylutron_caseta.smartbridge import Smartbridge import voluptuous as vol from homeassistant import config_entries from homeassistant.const import CONF_HOST, Platform -from homeassistant.core import callback +from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.helpers import device_registry as dr import homeassistant.helpers.config_validation as cv @@ -26,12 +26,12 @@ from .const import ( ATTR_AREA_NAME, ATTR_BUTTON_NUMBER, ATTR_DEVICE_NAME, + ATTR_LEAP_BUTTON_NUMBER, ATTR_SERIAL, ATTR_TYPE, BRIDGE_DEVICE, BRIDGE_DEVICE_ID, BRIDGE_LEAP, - BRIDGE_LIP, BRIDGE_TIMEOUT, BUTTON_DEVICES, CONF_CA_CERTS, @@ -41,6 +41,10 @@ from .const import ( LUTRON_CASETA_BUTTON_EVENT, MANUFACTURER, ) +from .device_trigger import ( + DEVICE_TYPE_SUBTYPE_MAP_TO_LIP, + LEAP_TO_DEVICE_TYPE_SUBTYPE_MAP, +) _LOGGER = logging.getLogger(__name__) @@ -97,8 +101,11 @@ async def async_setup(hass, base_config): return True -async def async_setup_entry(hass, config_entry): +async def async_setup_entry( + hass: HomeAssistant, config_entry: config_entries.ConfigEntry +) -> bool: """Set up a bridge from a config entry.""" + entry_id = config_entry.entry_id host = config_entry.data[CONF_HOST] keyfile = hass.config.path(config_entry.data[CONF_KEYFILE]) certfile = hass.config.path(config_entry.data[CONF_CERTFILE]) @@ -130,85 +137,30 @@ async def async_setup_entry(hass, config_entry): devices = bridge.get_devices() bridge_device = devices[BRIDGE_DEVICE_ID] - _async_register_bridge_device(hass, config_entry.entry_id, bridge_device) + buttons = bridge.buttons + _async_register_bridge_device(hass, entry_id, bridge_device) + button_devices = _async_register_button_devices( + hass, entry_id, bridge_device, buttons + ) + _async_subscribe_pico_remote_events(hass, bridge, buttons) + # Store this bridge (keyed by entry_id) so it can be retrieved by the # platforms we're setting up. - hass.data[DOMAIN][config_entry.entry_id] = { + hass.data[DOMAIN][entry_id] = { BRIDGE_LEAP: bridge, BRIDGE_DEVICE: bridge_device, - BUTTON_DEVICES: {}, - BRIDGE_LIP: None, + BUTTON_DEVICES: button_devices, } - if bridge.lip_devices: - # If the bridge also supports LIP (Lutron Integration Protocol) - # we can fire events when pico buttons are pressed to allow - # pico remotes to control other devices. - await async_setup_lip(hass, config_entry, bridge.lip_devices) - hass.config_entries.async_setup_platforms(config_entry, PLATFORMS) return True -async def async_setup_lip(hass, config_entry, lip_devices): - """Connect to the bridge via Lutron Integration Protocol to watch for pico remotes.""" - host = config_entry.data[CONF_HOST] - config_entry_id = config_entry.entry_id - data = hass.data[DOMAIN][config_entry_id] - bridge_device = data[BRIDGE_DEVICE] - bridge = data[BRIDGE_LEAP] - lip = LIP() - try: - await lip.async_connect(host) - except asyncio.TimeoutError: - _LOGGER.warning( - "Failed to connect to via LIP at %s:23, Pico and Shade remotes will not be available; " - "Enable Telnet Support in the Lutron app under Settings >> Advanced >> Integration", - host, - ) - return - - _LOGGER.debug("Connected to Lutron Caseta bridge via LIP at %s:23", host) - button_devices_by_lip_id = _async_merge_lip_leap_data(lip_devices, bridge) - button_devices_by_dr_id = _async_register_button_devices( - hass, config_entry_id, bridge_device, button_devices_by_lip_id - ) - _async_subscribe_pico_remote_events(hass, lip, button_devices_by_lip_id) - data[BUTTON_DEVICES] = button_devices_by_dr_id - data[BRIDGE_LIP] = lip - - @callback -def _async_merge_lip_leap_data(lip_devices, bridge): - """Merge the leap data into the lip data.""" - sensor_devices = bridge.get_devices_by_domain("sensor") - - button_devices_by_id = { - id: device for id, device in lip_devices.items() if "Buttons" in device - } - sensor_devices_by_name = {device["name"]: device for device in sensor_devices} - - # Add the leap data into the lip data - # so we know the type, model, and serial - for device in button_devices_by_id.values(): - area = device.get("Area", {}).get("Name", "") - name = device["Name"] - leap_name = f"{area}_{name}" - device["leap_name"] = leap_name - leap_device_data = sensor_devices_by_name.get(leap_name) - if leap_device_data is None: - continue - for key in ("type", "model", "serial"): - if (val := leap_device_data.get(key)) is not None: - device[key] = val - - _LOGGER.debug("Button Devices: %s", button_devices_by_id) - return button_devices_by_id - - -@callback -def _async_register_bridge_device(hass, config_entry_id, bridge_device): +def _async_register_bridge_device( + hass: HomeAssistant, config_entry_id: str, bridge_device: dict +) -> None: """Register the bridge device in the device registry.""" device_registry = dr.async_get(hass) device_registry.async_get_or_create( @@ -217,24 +169,30 @@ def _async_register_bridge_device(hass, config_entry_id, bridge_device): config_entry_id=config_entry_id, identifiers={(DOMAIN, bridge_device["serial"])}, model=f"{bridge_device['model']} ({bridge_device['type']})", + configuration_url="https://device-login.lutron.com", ) @callback def _async_register_button_devices( - hass, config_entry_id, bridge_device, button_devices_by_id -): + hass: HomeAssistant, + config_entry_id: str, + bridge_device, + button_devices_by_id: dict[int, dict], +) -> dict[str, dr.DeviceEntry]: """Register button devices (Pico Remotes) in the device registry.""" device_registry = dr.async_get(hass) button_devices_by_dr_id = {} + seen = set() for device in button_devices_by_id.values(): - if "serial" not in device: + if "serial" not in device or device["serial"] in seen: continue + seen.add(device["serial"]) dr_device = device_registry.async_get_or_create( - name=device["leap_name"], - suggested_area=device["leap_name"].split("_")[0], + name=device["name"], + suggested_area=device["name"].split("_")[0], manufacturer=MANUFACTURER, config_entry_id=config_entry_id, identifiers={(DOMAIN, device["serial"])}, @@ -248,54 +206,74 @@ def _async_register_button_devices( @callback -def _async_subscribe_pico_remote_events(hass, lip, button_devices_by_id): +def _async_subscribe_pico_remote_events( + hass: HomeAssistant, + bridge_device: Smartbridge, + button_devices_by_id: dict[int, dict], +): """Subscribe to lutron events.""" @callback - def _async_lip_event(lip_message): - if lip_message.mode != LIPMode.DEVICE: - return - - device = button_devices_by_id.get(lip_message.integration_id) + def _async_button_event(button_id, event_type): + device = button_devices_by_id.get(button_id) if not device: return - if lip_message.value == LIP_BUTTON_PRESS: + if event_type == BUTTON_STATUS_PRESSED: action = ACTION_PRESS else: action = ACTION_RELEASE + type_ = device["type"] + name = device["name"] + button_number = device["button_number"] + # The original implementation used LIP instead of LEAP + # so we need to convert the button number to maintain compat + sub_type_to_lip_button = DEVICE_TYPE_SUBTYPE_MAP_TO_LIP[type_] + leap_button_to_sub_type = LEAP_TO_DEVICE_TYPE_SUBTYPE_MAP[type_] + if (sub_type := leap_button_to_sub_type.get(button_number)) is None: + _LOGGER.error( + "Unknown LEAP button number %s is not in %s for %s (%s)", + button_number, + leap_button_to_sub_type, + name, + type_, + ) + return + lip_button_number = sub_type_to_lip_button[sub_type] + hass.bus.async_fire( LUTRON_CASETA_BUTTON_EVENT, { - ATTR_SERIAL: device.get("serial"), - ATTR_TYPE: device.get("type"), - ATTR_BUTTON_NUMBER: lip_message.action_number, - ATTR_DEVICE_NAME: device["Name"], - ATTR_AREA_NAME: device.get("Area", {}).get("Name"), + ATTR_SERIAL: device["serial"], + ATTR_TYPE: type_, + ATTR_BUTTON_NUMBER: lip_button_number, + ATTR_LEAP_BUTTON_NUMBER: button_number, + ATTR_DEVICE_NAME: name, + ATTR_AREA_NAME: name.split("_")[0], ATTR_ACTION: action, }, ) - lip.subscribe(_async_lip_event) - - asyncio.create_task(lip.async_run()) + for button_id in button_devices_by_id: + bridge_device.add_button_subscriber( + str(button_id), + lambda event_type, button_id=button_id: _async_button_event( + button_id, event_type + ), + ) -async def async_unload_entry(hass, config_entry): +async def async_unload_entry( + hass: HomeAssistant, entry: config_entries.ConfigEntry +) -> bool: """Unload the bridge bridge from a config entry.""" - data = hass.data[DOMAIN][config_entry.entry_id] - data[BRIDGE_LEAP].close() - if data[BRIDGE_LIP]: - await data[BRIDGE_LIP].async_stop() - - unload_ok = await hass.config_entries.async_unload_platforms( - config_entry, PLATFORMS - ) - if unload_ok: - hass.data[DOMAIN].pop(config_entry.entry_id) - + data = hass.data[DOMAIN][entry.entry_id] + smartbridge: Smartbridge = data[BRIDGE_LEAP] + await smartbridge.close() + if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS): + hass.data[DOMAIN].pop(entry.entry_id) return unload_ok diff --git a/homeassistant/components/lutron_caseta/const.py b/homeassistant/components/lutron_caseta/const.py index 89472f3366b..90303dc0023 100644 --- a/homeassistant/components/lutron_caseta/const.py +++ b/homeassistant/components/lutron_caseta/const.py @@ -11,7 +11,6 @@ ERROR_CANNOT_CONNECT = "cannot_connect" ABORT_REASON_CANNOT_CONNECT = "cannot_connect" BRIDGE_LEAP = "leap" -BRIDGE_LIP = "lip" BRIDGE_DEVICE = "bridge_device" BUTTON_DEVICES = "button_devices" LUTRON_CASETA_BUTTON_EVENT = "lutron_caseta_button_event" @@ -22,7 +21,8 @@ MANUFACTURER = "Lutron Electronics Co., Inc" ATTR_SERIAL = "serial" ATTR_TYPE = "type" -ATTR_BUTTON_NUMBER = "button_number" +ATTR_LEAP_BUTTON_NUMBER = "leap_button_number" +ATTR_BUTTON_NUMBER = "button_number" # LIP button number ATTR_DEVICE_NAME = "device_name" ATTR_AREA_NAME = "area_name" ATTR_ACTION = "action" diff --git a/homeassistant/components/lutron_caseta/device_trigger.py b/homeassistant/components/lutron_caseta/device_trigger.py index ce50923f2f5..4974a10d9ba 100644 --- a/homeassistant/components/lutron_caseta/device_trigger.py +++ b/homeassistant/components/lutron_caseta/device_trigger.py @@ -46,106 +46,180 @@ LUTRON_BUTTON_TRIGGER_SCHEMA = DEVICE_TRIGGER_BASE_SCHEMA.extend( ) -PICO_2_BUTTON_BUTTON_TYPES = { +PICO_2_BUTTON_BUTTON_TYPES_TO_LIP = { "on": 2, "off": 4, } +PICO_2_BUTTON_BUTTON_TYPES_TO_LEAP = { + "on": 0, + "off": 2, +} +LEAP_TO_PICO_2_BUTTON_BUTTON_TYPES = { + v: k for k, v in PICO_2_BUTTON_BUTTON_TYPES_TO_LEAP.items() +} PICO_2_BUTTON_TRIGGER_SCHEMA = LUTRON_BUTTON_TRIGGER_SCHEMA.extend( { - vol.Required(CONF_SUBTYPE): vol.In(PICO_2_BUTTON_BUTTON_TYPES), + vol.Required(CONF_SUBTYPE): vol.In(PICO_2_BUTTON_BUTTON_TYPES_TO_LIP), } ) -PICO_2_BUTTON_RAISE_LOWER_BUTTON_TYPES = { +PICO_2_BUTTON_RAISE_LOWER_BUTTON_TYPES_TO_LIP = { "on": 2, "off": 4, "raise": 5, "lower": 6, } +PICO_2_BUTTON_RAISE_LOWER_BUTTON_TYPES_TO_LEAP = { + "on": 0, + "off": 2, + "raise": 3, + "lower": 4, +} +LEAP_TO_PICO_2_BUTTON_RAISE_LOWER_BUTTON_TYPES = { + v: k for k, v in PICO_2_BUTTON_RAISE_LOWER_BUTTON_TYPES_TO_LEAP.items() +} PICO_2_BUTTON_RAISE_LOWER_TRIGGER_SCHEMA = LUTRON_BUTTON_TRIGGER_SCHEMA.extend( { - vol.Required(CONF_SUBTYPE): vol.In(PICO_2_BUTTON_RAISE_LOWER_BUTTON_TYPES), + vol.Required(CONF_SUBTYPE): vol.In( + PICO_2_BUTTON_RAISE_LOWER_BUTTON_TYPES_TO_LIP + ), } ) -PICO_3_BUTTON_BUTTON_TYPES = { +PICO_3_BUTTON_BUTTON_TYPES_TO_LIP = { "on": 2, "stop": 3, "off": 4, } +PICO_3_BUTTON_BUTTON_TYPES_TO_LEAP = { + "on": 0, + "stop": 1, + "off": 2, +} +LEAP_TO_PICO_3_BUTTON_BUTTON_TYPES = { + v: k for k, v in PICO_3_BUTTON_BUTTON_TYPES_TO_LEAP.items() +} PICO_3_BUTTON_TRIGGER_SCHEMA = LUTRON_BUTTON_TRIGGER_SCHEMA.extend( { - vol.Required(CONF_SUBTYPE): vol.In(PICO_3_BUTTON_BUTTON_TYPES), + vol.Required(CONF_SUBTYPE): vol.In(PICO_3_BUTTON_BUTTON_TYPES_TO_LIP), } ) -PICO_3_BUTTON_RAISE_LOWER_BUTTON_TYPES = { +PICO_3_BUTTON_RAISE_LOWER_BUTTON_TYPES_TO_LIP = { "on": 2, "stop": 3, "off": 4, "raise": 5, "lower": 6, } +PICO_3_BUTTON_RAISE_LOWER_BUTTON_TYPES_TO_LEAP = { + "on": 0, + "stop": 1, + "off": 2, + "raise": 3, + "lower": 4, +} +LEAP_TO_PICO_3_BUTTON_RAISE_LOWER_BUTTON_TYPES = { + v: k for k, v in PICO_3_BUTTON_RAISE_LOWER_BUTTON_TYPES_TO_LEAP.items() +} PICO_3_BUTTON_RAISE_LOWER_TRIGGER_SCHEMA = LUTRON_BUTTON_TRIGGER_SCHEMA.extend( { - vol.Required(CONF_SUBTYPE): vol.In(PICO_3_BUTTON_RAISE_LOWER_BUTTON_TYPES), + vol.Required(CONF_SUBTYPE): vol.In( + PICO_3_BUTTON_RAISE_LOWER_BUTTON_TYPES_TO_LIP + ), } ) -PICO_4_BUTTON_BUTTON_TYPES = { +PICO_4_BUTTON_BUTTON_TYPES_TO_LIP = { "button_1": 8, "button_2": 9, "button_3": 10, "button_4": 11, } +PICO_4_BUTTON_BUTTON_TYPES_TO_LEAP = { + "button_1": 1, + "button_2": 2, + "button_3": 3, + "button_4": 4, +} +LEAP_TO_PICO_4_BUTTON_BUTTON_TYPES = { + v: k for k, v in PICO_4_BUTTON_BUTTON_TYPES_TO_LEAP.items() +} PICO_4_BUTTON_TRIGGER_SCHEMA = LUTRON_BUTTON_TRIGGER_SCHEMA.extend( { - vol.Required(CONF_SUBTYPE): vol.In(PICO_4_BUTTON_BUTTON_TYPES), + vol.Required(CONF_SUBTYPE): vol.In(PICO_4_BUTTON_BUTTON_TYPES_TO_LIP), } ) -PICO_4_BUTTON_ZONE_BUTTON_TYPES = { +PICO_4_BUTTON_ZONE_BUTTON_TYPES_TO_LIP = { "on": 8, "raise": 9, "lower": 10, "off": 11, } +PICO_4_BUTTON_ZONE_BUTTON_TYPES_TO_LEAP = { + "on": 1, + "raise": 2, + "lower": 3, + "off": 4, +} +LEAP_TO_PICO_4_BUTTON_ZONE_BUTTON_TYPES = { + v: k for k, v in PICO_4_BUTTON_ZONE_BUTTON_TYPES_TO_LEAP.items() +} PICO_4_BUTTON_ZONE_TRIGGER_SCHEMA = LUTRON_BUTTON_TRIGGER_SCHEMA.extend( { - vol.Required(CONF_SUBTYPE): vol.In(PICO_4_BUTTON_ZONE_BUTTON_TYPES), + vol.Required(CONF_SUBTYPE): vol.In(PICO_4_BUTTON_ZONE_BUTTON_TYPES_TO_LIP), } ) -PICO_4_BUTTON_SCENE_BUTTON_TYPES = { +PICO_4_BUTTON_SCENE_BUTTON_TYPES_TO_LIP = { "button_1": 8, "button_2": 9, "button_3": 10, "off": 11, } +PICO_4_BUTTON_SCENE_BUTTON_TYPES_TO_LEAP = { + "button_1": 1, + "button_2": 2, + "button_3": 3, + "off": 4, +} +LEAP_TO_PICO_4_BUTTON_SCENE_BUTTON_TYPES = { + v: k for k, v in PICO_4_BUTTON_SCENE_BUTTON_TYPES_TO_LEAP.items() +} PICO_4_BUTTON_SCENE_TRIGGER_SCHEMA = LUTRON_BUTTON_TRIGGER_SCHEMA.extend( { - vol.Required(CONF_SUBTYPE): vol.In(PICO_4_BUTTON_SCENE_BUTTON_TYPES), + vol.Required(CONF_SUBTYPE): vol.In(PICO_4_BUTTON_SCENE_BUTTON_TYPES_TO_LIP), } ) -PICO_4_BUTTON_2_GROUP_BUTTON_TYPES = { +PICO_4_BUTTON_2_GROUP_BUTTON_TYPES_TO_LIP = { "group_1_button_1": 8, "group_1_button_2": 9, "group_2_button_1": 10, "group_2_button_2": 11, } +PICO_4_BUTTON_2_GROUP_BUTTON_TYPES_TO_LEAP = { + "group_1_button_1": 1, + "group_1_button_2": 2, + "group_2_button_1": 3, + "group_2_button_2": 4, +} +LEAP_TO_PICO_4_BUTTON_2_GROUP_BUTTON_TYPES = { + v: k for k, v in PICO_4_BUTTON_2_GROUP_BUTTON_TYPES_TO_LEAP.items() +} PICO_4_BUTTON_2_GROUP_TRIGGER_SCHEMA = LUTRON_BUTTON_TRIGGER_SCHEMA.extend( { - vol.Required(CONF_SUBTYPE): vol.In(PICO_4_BUTTON_2_GROUP_BUTTON_TYPES), + vol.Required(CONF_SUBTYPE): vol.In(PICO_4_BUTTON_2_GROUP_BUTTON_TYPES_TO_LIP), } ) -FOUR_GROUP_REMOTE_BUTTON_TYPES = { +FOUR_GROUP_REMOTE_BUTTON_TYPES_TO_LIP = { "open_all": 2, "stop_all": 3, "close_all": 4, @@ -172,9 +246,39 @@ FOUR_GROUP_REMOTE_BUTTON_TYPES = { "raise_4": 37, "lower_4": 38, } +FOUR_GROUP_REMOTE_BUTTON_TYPES_TO_LEAP = { + "open_all": 0, + "stop_all": 1, + "close_all": 2, + "raise_all": 3, + "lower_all": 4, + "open_1": 5, + "stop_1": 6, + "close_1": 7, + "raise_1": 8, + "lower_1": 9, + "open_2": 10, + "stop_2": 11, + "close_2": 12, + "raise_2": 13, + "lower_2": 14, + "open_3": 15, + "stop_3": 16, + "close_3": 17, + "raise_3": 18, + "lower_3": 19, + "open_4": 20, + "stop_4": 21, + "close_4": 22, + "raise_4": 23, + "lower_4": 24, +} +LEAP_TO_FOUR_GROUP_REMOTE_BUTTON_TYPES = { + v: k for k, v in FOUR_GROUP_REMOTE_BUTTON_TYPES_TO_LEAP.items() +} FOUR_GROUP_REMOTE_TRIGGER_SCHEMA = LUTRON_BUTTON_TRIGGER_SCHEMA.extend( { - vol.Required(CONF_SUBTYPE): vol.In(FOUR_GROUP_REMOTE_BUTTON_TYPES), + vol.Required(CONF_SUBTYPE): vol.In(FOUR_GROUP_REMOTE_BUTTON_TYPES_TO_LIP), } ) @@ -190,16 +294,28 @@ DEVICE_TYPE_SCHEMA_MAP = { "FourGroupRemote": FOUR_GROUP_REMOTE_TRIGGER_SCHEMA, } -DEVICE_TYPE_SUBTYPE_MAP = { - "Pico2Button": PICO_2_BUTTON_BUTTON_TYPES, - "Pico2ButtonRaiseLower": PICO_2_BUTTON_RAISE_LOWER_BUTTON_TYPES, - "Pico3Button": PICO_3_BUTTON_BUTTON_TYPES, - "Pico3ButtonRaiseLower": PICO_3_BUTTON_RAISE_LOWER_BUTTON_TYPES, - "Pico4Button": PICO_4_BUTTON_BUTTON_TYPES, - "Pico4ButtonScene": PICO_4_BUTTON_SCENE_BUTTON_TYPES, - "Pico4ButtonZone": PICO_4_BUTTON_ZONE_BUTTON_TYPES, - "Pico4Button2Group": PICO_4_BUTTON_2_GROUP_BUTTON_TYPES, - "FourGroupRemote": FOUR_GROUP_REMOTE_BUTTON_TYPES, +DEVICE_TYPE_SUBTYPE_MAP_TO_LIP = { + "Pico2Button": PICO_2_BUTTON_BUTTON_TYPES_TO_LIP, + "Pico2ButtonRaiseLower": PICO_2_BUTTON_RAISE_LOWER_BUTTON_TYPES_TO_LIP, + "Pico3Button": PICO_3_BUTTON_BUTTON_TYPES_TO_LIP, + "Pico3ButtonRaiseLower": PICO_3_BUTTON_RAISE_LOWER_BUTTON_TYPES_TO_LIP, + "Pico4Button": PICO_4_BUTTON_BUTTON_TYPES_TO_LIP, + "Pico4ButtonScene": PICO_4_BUTTON_SCENE_BUTTON_TYPES_TO_LIP, + "Pico4ButtonZone": PICO_4_BUTTON_ZONE_BUTTON_TYPES_TO_LIP, + "Pico4Button2Group": PICO_4_BUTTON_2_GROUP_BUTTON_TYPES_TO_LIP, + "FourGroupRemote": FOUR_GROUP_REMOTE_BUTTON_TYPES_TO_LIP, +} + +LEAP_TO_DEVICE_TYPE_SUBTYPE_MAP = { + "Pico2Button": LEAP_TO_PICO_2_BUTTON_BUTTON_TYPES, + "Pico2ButtonRaiseLower": LEAP_TO_PICO_2_BUTTON_RAISE_LOWER_BUTTON_TYPES, + "Pico3Button": LEAP_TO_PICO_3_BUTTON_BUTTON_TYPES, + "Pico3ButtonRaiseLower": LEAP_TO_PICO_3_BUTTON_RAISE_LOWER_BUTTON_TYPES, + "Pico4Button": LEAP_TO_PICO_4_BUTTON_BUTTON_TYPES, + "Pico4ButtonScene": LEAP_TO_PICO_4_BUTTON_SCENE_BUTTON_TYPES, + "Pico4ButtonZone": LEAP_TO_PICO_4_BUTTON_ZONE_BUTTON_TYPES, + "Pico4Button2Group": LEAP_TO_PICO_4_BUTTON_2_GROUP_BUTTON_TYPES, + "FourGroupRemote": LEAP_TO_FOUR_GROUP_REMOTE_BUTTON_TYPES, } TRIGGER_SCHEMA = vol.Any( @@ -238,7 +354,7 @@ async def async_get_triggers( if not (device := get_button_device_by_dr_id(hass, device_id)): raise InvalidDeviceAutomationConfig(f"Device not found: {device_id}") - valid_buttons = DEVICE_TYPE_SUBTYPE_MAP.get(device["type"], []) + valid_buttons = DEVICE_TYPE_SUBTYPE_MAP_TO_LIP.get(device["type"], []) for trigger in SUPPORTED_INPUTS_EVENTS_TYPES: for subtype in valid_buttons: @@ -273,7 +389,7 @@ async def async_attach_trigger( device_type = _device_model_to_type(device.model) _, serial = list(device.identifiers)[0] schema = DEVICE_TYPE_SCHEMA_MAP.get(device_type) - valid_buttons = DEVICE_TYPE_SUBTYPE_MAP.get(device_type) + valid_buttons = DEVICE_TYPE_SUBTYPE_MAP_TO_LIP.get(device_type) config = schema(config) event_config = { event_trigger.CONF_PLATFORM: CONF_EVENT, diff --git a/homeassistant/components/lutron_caseta/manifest.json b/homeassistant/components/lutron_caseta/manifest.json index b6f0785ffe7..b6d3eb51f7a 100644 --- a/homeassistant/components/lutron_caseta/manifest.json +++ b/homeassistant/components/lutron_caseta/manifest.json @@ -2,7 +2,7 @@ "domain": "lutron_caseta", "name": "Lutron Cas\u00e9ta", "documentation": "https://www.home-assistant.io/integrations/lutron_caseta", - "requirements": ["pylutron-caseta==0.11.0", "aiolip==1.1.6"], + "requirements": ["pylutron-caseta==0.13.0"], "config_flow": true, "zeroconf": ["_leap._tcp.local."], "homekit": { diff --git a/requirements_all.txt b/requirements_all.txt index 45b538f86c1..cf103d060cf 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -209,9 +209,6 @@ aiolifx==0.7.0 # homeassistant.components.lifx aiolifx_effects==0.2.2 -# homeassistant.components.lutron_caseta -aiolip==1.1.6 - # homeassistant.components.lookin aiolookin==0.1.0 @@ -1625,7 +1622,7 @@ pylitejet==0.3.0 pylitterbot==2021.12.0 # homeassistant.components.lutron_caseta -pylutron-caseta==0.11.0 +pylutron-caseta==0.13.0 # homeassistant.components.lutron pylutron==0.2.8 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 9b8813faf3c..70245fcf559 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -142,9 +142,6 @@ aiohue==3.0.6 # homeassistant.components.apache_kafka aiokafka==0.6.0 -# homeassistant.components.lutron_caseta -aiolip==1.1.6 - # homeassistant.components.lookin aiolookin==0.1.0 @@ -995,7 +992,7 @@ pylitejet==0.3.0 pylitterbot==2021.12.0 # homeassistant.components.lutron_caseta -pylutron-caseta==0.11.0 +pylutron-caseta==0.13.0 # homeassistant.components.mailgun pymailgunner==1.4