Support for security systems controlled by IFTTT (#12975)
* Add IFTTT alarm control panel * Update .coveragerc * Add support for code * Bugfix * Fix logging problem * Pin requirements * Update requirements_all.txt * Fix lint errors * Use ifttt component as a dependency instead of interacting with ifttt manually Take into account review comments * No default value for code * Take into account review comments * Provide a "push_alarm_state" service to change the state from IFTTT * Add service description * Fix @balloob review comments. Thanks! * Fix service description namepull/13154/head
parent
1e17b2fd63
commit
022d8fb816
|
@ -312,6 +312,7 @@ omit =
|
|||
homeassistant/components/alarm_control_panel/canary.py
|
||||
homeassistant/components/alarm_control_panel/concord232.py
|
||||
homeassistant/components/alarm_control_panel/ialarm.py
|
||||
homeassistant/components/alarm_control_panel/ifttt.py
|
||||
homeassistant/components/alarm_control_panel/manual_mqtt.py
|
||||
homeassistant/components/alarm_control_panel/nx584.py
|
||||
homeassistant/components/alarm_control_panel/simplisafe.py
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
"""
|
||||
Interfaces with alarm control panels that have to be controlled through IFTTT.
|
||||
|
||||
For more details about this platform, please refer to the documentation at
|
||||
https://home-assistant.io/components/alarm_control_panel.ifttt/
|
||||
"""
|
||||
import logging
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
import homeassistant.components.alarm_control_panel as alarm
|
||||
from homeassistant.components.alarm_control_panel import (
|
||||
DOMAIN, PLATFORM_SCHEMA)
|
||||
from homeassistant.components.ifttt import (
|
||||
ATTR_EVENT, DOMAIN as IFTTT_DOMAIN, SERVICE_TRIGGER)
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID, ATTR_STATE, CONF_NAME, CONF_CODE,
|
||||
STATE_ALARM_DISARMED, STATE_ALARM_ARMED_NIGHT,
|
||||
STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_AWAY)
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
DEPENDENCIES = ['ifttt']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ALLOWED_STATES = [
|
||||
STATE_ALARM_DISARMED, STATE_ALARM_ARMED_NIGHT,
|
||||
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME]
|
||||
|
||||
DATA_IFTTT_ALARM = 'ifttt_alarm'
|
||||
DEFAULT_NAME = "Home"
|
||||
|
||||
EVENT_ALARM_ARM_AWAY = "alarm_arm_away"
|
||||
EVENT_ALARM_ARM_HOME = "alarm_arm_home"
|
||||
EVENT_ALARM_ARM_NIGHT = "alarm_arm_night"
|
||||
EVENT_ALARM_DISARM = "alarm_disarm"
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||
vol.Optional(CONF_CODE): cv.string,
|
||||
})
|
||||
|
||||
SERVICE_PUSH_ALARM_STATE = "ifttt_push_alarm_state"
|
||||
|
||||
PUSH_ALARM_STATE_SERVICE_SCHEMA = vol.Schema({
|
||||
vol.Required(ATTR_ENTITY_ID): cv.entity_ids,
|
||||
vol.Required(ATTR_STATE): cv.string,
|
||||
})
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Set up a control panel managed through IFTTT."""
|
||||
if DATA_IFTTT_ALARM not in hass.data:
|
||||
hass.data[DATA_IFTTT_ALARM] = []
|
||||
|
||||
name = config.get(CONF_NAME)
|
||||
code = config.get(CONF_CODE)
|
||||
|
||||
alarmpanel = IFTTTAlarmPanel(name, code)
|
||||
hass.data[DATA_IFTTT_ALARM].append(alarmpanel)
|
||||
add_devices([alarmpanel])
|
||||
|
||||
async def push_state_update(service):
|
||||
"""Set the service state as device state attribute."""
|
||||
entity_ids = service.data.get(ATTR_ENTITY_ID)
|
||||
state = service.data.get(ATTR_STATE)
|
||||
devices = hass.data[DATA_IFTTT_ALARM]
|
||||
if entity_ids:
|
||||
devices = [d for d in devices if d.entity_id in entity_ids]
|
||||
|
||||
for device in devices:
|
||||
device.push_alarm_state(state)
|
||||
device.async_schedule_update_ha_state()
|
||||
|
||||
hass.services.register(DOMAIN, SERVICE_PUSH_ALARM_STATE, push_state_update,
|
||||
schema=PUSH_ALARM_STATE_SERVICE_SCHEMA)
|
||||
|
||||
|
||||
class IFTTTAlarmPanel(alarm.AlarmControlPanel):
|
||||
"""Representation of an alarm control panel controlled throught IFTTT."""
|
||||
|
||||
def __init__(self, name, code):
|
||||
"""Initialize the alarm control panel."""
|
||||
self._name = name
|
||||
self._code = code
|
||||
self._state = None
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the device."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
"""Return the state of the device."""
|
||||
return self._state
|
||||
|
||||
@property
|
||||
def assumed_state(self):
|
||||
"""Notify that this platform return an assumed state."""
|
||||
return True
|
||||
|
||||
@property
|
||||
def code_format(self):
|
||||
"""Return one or more characters."""
|
||||
return None if self._code is None else '.+'
|
||||
|
||||
def alarm_disarm(self, code=None):
|
||||
"""Send disarm command."""
|
||||
if not self._check_code(code):
|
||||
return
|
||||
self.set_alarm_state(EVENT_ALARM_DISARM)
|
||||
|
||||
def alarm_arm_away(self, code=None):
|
||||
"""Send arm away command."""
|
||||
if not self._check_code(code):
|
||||
return
|
||||
self.set_alarm_state(EVENT_ALARM_ARM_AWAY)
|
||||
|
||||
def alarm_arm_home(self, code=None):
|
||||
"""Send arm home command."""
|
||||
if not self._check_code(code):
|
||||
return
|
||||
self.set_alarm_state(EVENT_ALARM_ARM_HOME)
|
||||
|
||||
def alarm_arm_night(self, code=None):
|
||||
"""Send arm night command."""
|
||||
if not self._check_code(code):
|
||||
return
|
||||
self.set_alarm_state(EVENT_ALARM_ARM_NIGHT)
|
||||
|
||||
def set_alarm_state(self, event):
|
||||
"""Call the IFTTT trigger service to change the alarm state."""
|
||||
data = {ATTR_EVENT: event}
|
||||
|
||||
self.hass.services.call(IFTTT_DOMAIN, SERVICE_TRIGGER, data)
|
||||
_LOGGER.debug("Called IFTTT component to trigger event %s", event)
|
||||
|
||||
def push_alarm_state(self, value):
|
||||
"""Push the alarm state to the given value."""
|
||||
if value in ALLOWED_STATES:
|
||||
_LOGGER.debug("Pushed the alarm state to %s", value)
|
||||
self._state = value
|
||||
|
||||
def _check_code(self, code):
|
||||
return self._code is None or self._code == code
|
|
@ -69,3 +69,13 @@ alarmdecoder_alarm_toggle_chime:
|
|||
code:
|
||||
description: A required code to toggle the alarm control panel chime with.
|
||||
example: 1234
|
||||
|
||||
ifttt_push_alarm_state:
|
||||
description: Update the alarm state to the specified value.
|
||||
fields:
|
||||
entity_id:
|
||||
description: Name of the alarm control panel which state has to be updated.
|
||||
example: 'alarm_control_panel.downstairs'
|
||||
state:
|
||||
description: The state to which the alarm control panel has to be set.
|
||||
example: 'armed_night'
|
||||
|
|
Loading…
Reference in New Issue