From 9790f3f6098eaab3314d1d9a181ca995c1dcd27e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 31 Mar 2021 06:22:30 -1000 Subject: [PATCH] Create homekit locks according to spec (#48453) Any accessories, regardless of transport, that enable physical access to the home, such as door locks, must not be bridged. --- homeassistant/components/homekit/strings.json | 2 +- .../components/homekit/translations/en.json | 23 +++---------------- homeassistant/components/homekit/util.py | 4 +++- tests/components/homekit/test_util.py | 7 ++++++ 4 files changed, 14 insertions(+), 22 deletions(-) diff --git a/homeassistant/components/homekit/strings.json b/homeassistant/components/homekit/strings.json index 4e3437a1fa0..56bc5438eac 100644 --- a/homeassistant/components/homekit/strings.json +++ b/homeassistant/components/homekit/strings.json @@ -18,7 +18,7 @@ "mode": "[%key:common::config_flow::data::mode%]", "entities": "Entities" }, - "description": "Choose the entities to be included. In accessory mode, only a single entity is included. In bridge include mode, all entities in the domain will be included unless specific entities are selected. In bridge exclude mode, all entities in the domain will be included except for the excluded entities. For best performance, a separate HomeKit accessory will be created for each tv media player and camera.", + "description": "Choose the entities to be included. In accessory mode, only a single entity is included. In bridge include mode, all entities in the domain will be included unless specific entities are selected. In bridge exclude mode, all entities in the domain will be included except for the excluded entities. For best performance, a separate HomeKit accessory will be created for each tv media player, activity based remote, lock, and camera.", "title": "Select entities to be included" }, "cameras": { diff --git a/homeassistant/components/homekit/translations/en.json b/homeassistant/components/homekit/translations/en.json index 42bcb5bd0f2..aa78c3e4adc 100644 --- a/homeassistant/components/homekit/translations/en.json +++ b/homeassistant/components/homekit/translations/en.json @@ -4,29 +4,13 @@ "port_name_in_use": "An accessory or bridge with the same name or port is already configured." }, "step": { - "accessory_mode": { - "data": { - "entity_id": "Entity" - }, - "description": "Choose the entity to be included. In accessory mode, only a single entity is included.", - "title": "Select entity to be included" - }, - "bridge_mode": { - "data": { - "include_domains": "Domains to include" - }, - "description": "Choose the domains to be included. All supported entities in the domain will be included.", - "title": "Select domains to be included" - }, "pairing": { "description": "To complete pairing following the instructions in \u201cNotifications\u201d under \u201cHomeKit Pairing\u201d.", "title": "Pair HomeKit" }, "user": { "data": { - "auto_start": "Autostart (disable if using Z-Wave or other delayed start system)", - "include_domains": "Domains to include", - "mode": "Mode" + "include_domains": "Domains to include" }, "description": "Choose the domains to be included. All supported entities in the domain will be included. A separate HomeKit instance in accessory mode will be created for each tv media player and camera.", "title": "Select domains to be included" @@ -37,8 +21,7 @@ "step": { "advanced": { "data": { - "auto_start": "Autostart (disable if you are calling the homekit.start service manually)", - "safe_mode": "Safe Mode (enable only if pairing fails)" + "auto_start": "Autostart (disable if you are calling the homekit.start service manually)" }, "description": "These settings only need to be adjusted if HomeKit is not functional.", "title": "Advanced Configuration" @@ -55,7 +38,7 @@ "entities": "Entities", "mode": "Mode" }, - "description": "Choose the entities to be included. In accessory mode, only a single entity is included. In bridge include mode, all entities in the domain will be included unless specific entities are selected. In bridge exclude mode, all entities in the domain will be included except for the excluded entities. For best performance, a separate HomeKit accessory will be created for each tv media player and camera.", + "description": "Choose the entities to be included. In accessory mode, only a single entity is included. In bridge include mode, all entities in the domain will be included unless specific entities are selected. In bridge exclude mode, all entities in the domain will be included except for the excluded entities. For best performance, a separate HomeKit accessory will be created for each tv media player, activity based remote, lock, and camera.", "title": "Select entities to be included" }, "init": { diff --git a/homeassistant/components/homekit/util.py b/homeassistant/components/homekit/util.py index d0a83b1a12a..a746355e124 100644 --- a/homeassistant/components/homekit/util.py +++ b/homeassistant/components/homekit/util.py @@ -12,6 +12,7 @@ import voluptuous as vol from homeassistant.components import binary_sensor, media_player, sensor from homeassistant.components.camera import DOMAIN as CAMERA_DOMAIN +from homeassistant.components.lock import DOMAIN as LOCK_DOMAIN from homeassistant.components.media_player import ( DEVICE_CLASS_TV, DOMAIN as MEDIA_PLAYER_DOMAIN, @@ -502,7 +503,8 @@ def state_needs_accessory_mode(state): return True return ( - state.domain == MEDIA_PLAYER_DOMAIN + state.domain == LOCK_DOMAIN + or state.domain == MEDIA_PLAYER_DOMAIN and state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_TV or state.domain == REMOTE_DOMAIN and state.attributes.get(ATTR_SUPPORTED_FEATURES) & SUPPORT_ACTIVITY diff --git a/tests/components/homekit/test_util.py b/tests/components/homekit/test_util.py index c458d1dc4ef..33c5c8623d1 100644 --- a/tests/components/homekit/test_util.py +++ b/tests/components/homekit/test_util.py @@ -33,6 +33,7 @@ from homeassistant.components.homekit.util import ( format_sw_version, port_is_available, show_setup_message, + state_needs_accessory_mode, temperature_to_homekit, temperature_to_states, validate_entity_config as vec, @@ -298,3 +299,9 @@ async def test_accessory_friendly_name(): assert accessory_friendly_name("hass title", accessory) == "hass title (same)" accessory.display_name = "Hass title 123" assert accessory_friendly_name("hass title", accessory) == "Hass title 123" + + +async def test_lock_state_needs_accessory_mode(hass): + """Test that locks are setup as accessories.""" + hass.states.async_set("lock.mine", "locked") + assert state_needs_accessory_mode(hass.states.get("lock.mine")) is True