From f7d3f3a1ede78b6701d4013f27216c0e4a14215e Mon Sep 17 00:00:00 2001 From: Glenn Waters Date: Mon, 12 Oct 2020 22:41:19 -0400 Subject: [PATCH] Add elkm1 bypass and trigger services (#41584) --- homeassistant/components/elkm1/__init__.py | 5 -- .../components/elkm1/alarm_control_panel.py | 49 ++++++++++++------- homeassistant/components/elkm1/const.py | 7 +++ homeassistant/components/elkm1/manifest.json | 2 +- homeassistant/components/elkm1/sensor.py | 32 +++++++++++- homeassistant/components/elkm1/services.yaml | 37 ++++++++++++++ requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 8 files changed, 107 insertions(+), 29 deletions(-) diff --git a/homeassistant/components/elkm1/__init__.py b/homeassistant/components/elkm1/__init__.py index dbb45ec317f..e8e226f7882 100644 --- a/homeassistant/components/elkm1/__init__.py +++ b/homeassistant/components/elkm1/__init__.py @@ -47,11 +47,6 @@ SYNC_TIMEOUT = 120 _LOGGER = logging.getLogger(__name__) -SERVICE_ALARM_DISPLAY_MESSAGE = "alarm_display_message" -SERVICE_ALARM_ARM_VACATION = "alarm_arm_vacation" -SERVICE_ALARM_ARM_HOME_INSTANT = "alarm_arm_home_instant" -SERVICE_ALARM_ARM_NIGHT_INSTANT = "alarm_arm_night_instant" - SUPPORTED_DOMAINS = [ "alarm_control_panel", "climate", diff --git a/homeassistant/components/elkm1/alarm_control_panel.py b/homeassistant/components/elkm1/alarm_control_panel.py index 2e3c1ca3187..88b307ab4c0 100644 --- a/homeassistant/components/elkm1/alarm_control_panel.py +++ b/homeassistant/components/elkm1/alarm_control_panel.py @@ -14,7 +14,6 @@ from homeassistant.components.alarm_control_panel.const import ( SUPPORT_ALARM_ARM_NIGHT, ) from homeassistant.const import ( - ATTR_CODE, ATTR_ENTITY_ID, STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, @@ -28,26 +27,13 @@ from homeassistant.helpers import entity_platform import homeassistant.helpers.config_validation as cv from homeassistant.helpers.restore_state import RestoreEntity -from . import ( - SERVICE_ALARM_ARM_HOME_INSTANT, - SERVICE_ALARM_ARM_NIGHT_INSTANT, - SERVICE_ALARM_ARM_VACATION, - SERVICE_ALARM_DISPLAY_MESSAGE, - ElkAttachedEntity, - create_elk_entities, -) +from . import ElkAttachedEntity, create_elk_entities from .const import ( ATTR_CHANGED_BY_ID, ATTR_CHANGED_BY_KEYPAD, ATTR_CHANGED_BY_TIME, DOMAIN, -) - -ELK_ALARM_SERVICE_SCHEMA = vol.Schema( - { - vol.Required(ATTR_ENTITY_ID, default=[]): cv.entity_ids, - vol.Required(ATTR_CODE): vol.All(vol.Coerce(int), vol.Range(0, 999999)), - } + ELK_USER_CODE_SERVICE_SCHEMA, ) DISPLAY_MESSAGE_SERVICE_SCHEMA = vol.Schema( @@ -63,6 +49,13 @@ DISPLAY_MESSAGE_SERVICE_SCHEMA = vol.Schema( } ) +SERVICE_ALARM_DISPLAY_MESSAGE = "alarm_display_message" +SERVICE_ALARM_ARM_VACATION = "alarm_arm_vacation" +SERVICE_ALARM_ARM_HOME_INSTANT = "alarm_arm_home_instant" +SERVICE_ALARM_ARM_NIGHT_INSTANT = "alarm_arm_night_instant" +SERVICE_ALARM_BYPASS = "alarm_bypass" +SERVICE_ALARM_CLEAR_BYPASS = "alarm_clear_bypass" + async def async_setup_entry(hass, config_entry, async_add_entities): """Set up the ElkM1 alarm platform.""" @@ -85,17 +78,17 @@ async def async_setup_entry(hass, config_entry, async_add_entities): platform.async_register_entity_service( SERVICE_ALARM_ARM_VACATION, - ELK_ALARM_SERVICE_SCHEMA, + ELK_USER_CODE_SERVICE_SCHEMA, "async_alarm_arm_vacation", ) platform.async_register_entity_service( SERVICE_ALARM_ARM_HOME_INSTANT, - ELK_ALARM_SERVICE_SCHEMA, + ELK_USER_CODE_SERVICE_SCHEMA, "async_alarm_arm_home_instant", ) platform.async_register_entity_service( SERVICE_ALARM_ARM_NIGHT_INSTANT, - ELK_ALARM_SERVICE_SCHEMA, + ELK_USER_CODE_SERVICE_SCHEMA, "async_alarm_arm_night_instant", ) platform.async_register_entity_service( @@ -103,6 +96,16 @@ async def async_setup_entry(hass, config_entry, async_add_entities): DISPLAY_MESSAGE_SERVICE_SCHEMA, "async_display_message", ) + platform.async_register_entity_service( + SERVICE_ALARM_BYPASS, + ELK_USER_CODE_SERVICE_SCHEMA, + "async_bypass", + ) + platform.async_register_entity_service( + SERVICE_ALARM_CLEAR_BYPASS, + ELK_USER_CODE_SERVICE_SCHEMA, + "async_clear_bypass", + ) class ElkArea(ElkAttachedEntity, AlarmControlPanelEntity, RestoreEntity): @@ -261,3 +264,11 @@ class ElkArea(ElkAttachedEntity, AlarmControlPanelEntity, RestoreEntity): async def async_display_message(self, clear, beep, timeout, line1, line2): """Display a message on all keypads for the area.""" self._element.display_message(clear, beep, timeout, line1, line2) + + async def async_bypass(self, code=None): + """Bypass all zones in area.""" + self._element.bypass(code) + + async def async_clear_bypass(self, code=None): + """Clear bypass for all zones in area.""" + self._element.clear_bypass(code) diff --git a/homeassistant/components/elkm1/const.py b/homeassistant/components/elkm1/const.py index 27b6445a4c1..91f51eefeef 100644 --- a/homeassistant/components/elkm1/const.py +++ b/homeassistant/components/elkm1/const.py @@ -1,6 +1,9 @@ """Support the ElkM1 Gold and ElkM1 EZ8 alarm/integration panels.""" from elkm1_lib.const import Max +import voluptuous as vol + +from homeassistant.const import ATTR_CODE DOMAIN = "elkm1" @@ -37,3 +40,7 @@ ELK_ELEMENTS = { ATTR_CHANGED_BY_KEYPAD = "changed_by_keypad" ATTR_CHANGED_BY_ID = "changed_by_id" ATTR_CHANGED_BY_TIME = "changed_by_time" + +ELK_USER_CODE_SERVICE_SCHEMA = { + vol.Required(ATTR_CODE): vol.All(vol.Coerce(int), vol.Range(0, 999999)) +} diff --git a/homeassistant/components/elkm1/manifest.json b/homeassistant/components/elkm1/manifest.json index 1e8c1cf44f9..c7d4ca4ca2c 100644 --- a/homeassistant/components/elkm1/manifest.json +++ b/homeassistant/components/elkm1/manifest.json @@ -2,7 +2,7 @@ "domain": "elkm1", "name": "Elk-M1 Control", "documentation": "https://www.home-assistant.io/integrations/elkm1", - "requirements": ["elkm1-lib==0.8.1"], + "requirements": ["elkm1-lib==0.8.2"], "codeowners": ["@gwww", "@bdraco"], "config_flow": true } diff --git a/homeassistant/components/elkm1/sensor.py b/homeassistant/components/elkm1/sensor.py index 20efb3e956d..c628105dc60 100644 --- a/homeassistant/components/elkm1/sensor.py +++ b/homeassistant/components/elkm1/sensor.py @@ -8,10 +8,14 @@ from elkm1_lib.const import ( from elkm1_lib.util import pretty_const, username from homeassistant.const import VOLT +from homeassistant.exceptions import HomeAssistantError +from homeassistant.helpers import entity_platform from . import ElkAttachedEntity, create_elk_entities -from .const import DOMAIN +from .const import DOMAIN, ELK_USER_CODE_SERVICE_SCHEMA +SERVICE_SENSOR_ZONE_BYPASS = "sensor_zone_bypass" +SERVICE_SENSOR_ZONE_TRIGGER = "sensor_zone_trigger" UNDEFINED_TEMPATURE = -40 @@ -27,6 +31,19 @@ async def async_setup_entry(hass, config_entry, async_add_entities): create_elk_entities(elk_data, elk.zones, "zone", ElkZone, entities) async_add_entities(entities, True) + platform = entity_platform.current_platform.get() + + platform.async_register_entity_service( + SERVICE_SENSOR_ZONE_BYPASS, + ELK_USER_CODE_SERVICE_SCHEMA, + "async_zone_bypass", + ) + platform.async_register_entity_service( + SERVICE_SENSOR_ZONE_TRIGGER, + {}, + "async_zone_trigger", + ) + def temperature_to_state(temperature, undefined_temperature): """Convert temperature to a state.""" @@ -46,6 +63,18 @@ class ElkSensor(ElkAttachedEntity): """Return the state of the sensor.""" return self._state + async def async_zone_bypass(self, code=None): + """Bypass zone.""" + if not isinstance(self, ElkZone): + raise HomeAssistantError("supported only on ElkM1 Zone sensors") + self._element.bypass(code) + + async def async_zone_trigger(self): + """Trigger zone.""" + if not isinstance(self, ElkZone): + raise HomeAssistantError("supported only on ElkM1 Zone sensors") + self._element.trigger() + class ElkCounter(ElkSensor): """Representation of an Elk-M1 Counter.""" @@ -180,7 +209,6 @@ class ElkZone(ElkSensor): ).name.lower() attrs["definition"] = ZoneType(self._element.definition).name.lower() attrs["area"] = self._element.area + 1 - attrs["bypassed"] = self._element.bypassed attrs["triggered_alarm"] = self._element.triggered_alarm return attrs diff --git a/homeassistant/components/elkm1/services.yaml b/homeassistant/components/elkm1/services.yaml index beb4427d14c..6d30fa5ae92 100644 --- a/homeassistant/components/elkm1/services.yaml +++ b/homeassistant/components/elkm1/services.yaml @@ -1,3 +1,23 @@ +alarm_bypass: + description: Bypass all zones for the area. + fields: + entity_id: + description: Name of alarm control panel to bypass. + example: "alarm_control_panel.main" + code: + description: An code to authorize the bypass of the alarm control panel. + example: 4242 + +alarm_clear_bypass: + description: Remove bypass on all zones for the area. + fields: + entity_id: + description: Name of alarm control panel to clear bypass. + example: "alarm_control_panel.main" + code: + description: An code to authorize the bypass clear of the alarm control panel. + example: 4242 + alarm_arm_home_instant: description: Arm the ElkM1 in home instant mode. fields: @@ -63,3 +83,20 @@ speak_word: number: description: Word number to speak. example: 142 + +sensor_zone_bypass: + description: Bypass zone. + fields: + entity_id: + description: Name of zone to bypass. + example: "sensor.window42" + code: + description: An code to authorize the bypass of the zone. + example: 4242 + +sensor_zone_trigger: + description: Trigger zone. + fields: + entity_id: + description: Name of zone to trigger. + example: "sensor.motion42" diff --git a/requirements_all.txt b/requirements_all.txt index d69ae1a8e85..97fcdcb20d7 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -541,7 +541,7 @@ elgato==0.2.0 eliqonline==1.2.2 # homeassistant.components.elkm1 -elkm1-lib==0.8.1 +elkm1-lib==0.8.2 # homeassistant.components.mobile_app emoji==0.5.4 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index af43479ed0c..d2927b71046 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -281,7 +281,7 @@ eebrightbox==0.0.4 elgato==0.2.0 # homeassistant.components.elkm1 -elkm1-lib==0.8.1 +elkm1-lib==0.8.2 # homeassistant.components.mobile_app emoji==0.5.4