Skip to content

Commit

Permalink
Add supported_features to Alarm Control Panel to limit device_actions (
Browse files Browse the repository at this point in the history
…#29065)

* Add supported_features to Alarm Control Panel

* mark supported_features abstract

* Add SF to async_register_entity_service

* fix test

* Add missing SF SUPPORT_ALARM_ARM_CUSTOM_BYPASS

* isort

* fix async_register_entity_service

* Update alarm_control_panel.py
  • Loading branch information
SukramJ authored and balloob committed Nov 25, 2019
1 parent 3203cba commit 1fde0d1
Show file tree
Hide file tree
Showing 35 changed files with 449 additions and 66 deletions.
9 changes: 9 additions & 0 deletions homeassistant/components/abode/alarm_control_panel.py
Expand Up @@ -2,6 +2,10 @@
import logging

import homeassistant.components.alarm_control_panel as alarm
from homeassistant.components.alarm_control_panel.const import (
SUPPORT_ALARM_ARM_AWAY,
SUPPORT_ALARM_ARM_HOME,
)
from homeassistant.const import (
ATTR_ATTRIBUTION,
STATE_ALARM_ARMED_AWAY,
Expand Down Expand Up @@ -51,6 +55,11 @@ def state(self):
state = None
return state

@property
def supported_features(self) -> int:
"""Return the list of supported features."""
return SUPPORT_ALARM_ARM_HOME | SUPPORT_ALARM_ARM_AWAY

def alarm_disarm(self, code=None):
"""Send disarm command."""
self._device.set_standby()
Expand Down
45 changes: 36 additions & 9 deletions homeassistant/components/alarm_control_panel/__init__.py
@@ -1,4 +1,5 @@
"""Component to interface with an alarm control panel."""
from abc import abstractmethod
from datetime import timedelta
import logging

Expand All @@ -7,22 +8,30 @@
from homeassistant.const import (
ATTR_CODE,
ATTR_CODE_FORMAT,
SERVICE_ALARM_TRIGGER,
SERVICE_ALARM_DISARM,
SERVICE_ALARM_ARM_HOME,
SERVICE_ALARM_ARM_AWAY,
SERVICE_ALARM_ARM_NIGHT,
SERVICE_ALARM_ARM_CUSTOM_BYPASS,
SERVICE_ALARM_ARM_HOME,
SERVICE_ALARM_ARM_NIGHT,
SERVICE_ALARM_DISARM,
SERVICE_ALARM_TRIGGER,
)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.config_validation import ( # noqa: F401
ENTITY_SERVICE_SCHEMA,
PLATFORM_SCHEMA,
PLATFORM_SCHEMA_BASE,
)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.entity_component import EntityComponent

from .const import (
SUPPORT_ALARM_ARM_AWAY,
SUPPORT_ALARM_ARM_CUSTOM_BYPASS,
SUPPORT_ALARM_ARM_HOME,
SUPPORT_ALARM_ARM_NIGHT,
SUPPORT_ALARM_TRIGGER,
)

DOMAIN = "alarm_control_panel"
SCAN_INTERVAL = timedelta(seconds=30)
ATTR_CHANGED_BY = "changed_by"
Expand All @@ -49,21 +58,34 @@ async def async_setup(hass, config):
SERVICE_ALARM_DISARM, ALARM_SERVICE_SCHEMA, "async_alarm_disarm"
)
component.async_register_entity_service(
SERVICE_ALARM_ARM_HOME, ALARM_SERVICE_SCHEMA, "async_alarm_arm_home"
SERVICE_ALARM_ARM_HOME,
ALARM_SERVICE_SCHEMA,
"async_alarm_arm_home",
[SUPPORT_ALARM_ARM_HOME],
)
component.async_register_entity_service(
SERVICE_ALARM_ARM_AWAY, ALARM_SERVICE_SCHEMA, "async_alarm_arm_away"
SERVICE_ALARM_ARM_AWAY,
ALARM_SERVICE_SCHEMA,
"async_alarm_arm_away",
[SUPPORT_ALARM_ARM_AWAY],
)
component.async_register_entity_service(
SERVICE_ALARM_ARM_NIGHT, ALARM_SERVICE_SCHEMA, "async_alarm_arm_night"
SERVICE_ALARM_ARM_NIGHT,
ALARM_SERVICE_SCHEMA,
"async_alarm_arm_night",
[SUPPORT_ALARM_ARM_NIGHT],
)
component.async_register_entity_service(
SERVICE_ALARM_ARM_CUSTOM_BYPASS,
ALARM_SERVICE_SCHEMA,
"async_alarm_arm_custom_bypass",
[SUPPORT_ALARM_ARM_CUSTOM_BYPASS],
)
component.async_register_entity_service(
SERVICE_ALARM_TRIGGER, ALARM_SERVICE_SCHEMA, "async_alarm_trigger"
SERVICE_ALARM_TRIGGER,
ALARM_SERVICE_SCHEMA,
"async_alarm_trigger",
[SUPPORT_ALARM_TRIGGER],
)

return True
Expand Down Expand Up @@ -164,6 +186,11 @@ def async_alarm_arm_custom_bypass(self, code=None):
"""
return self.hass.async_add_executor_job(self.alarm_arm_custom_bypass, code)

@property
@abstractmethod
def supported_features(self) -> int:
"""Return the list of supported features."""

@property
def state_attributes(self):
"""Return the state attributes."""
Expand Down
7 changes: 7 additions & 0 deletions homeassistant/components/alarm_control_panel/const.py
@@ -0,0 +1,7 @@
"""Provides the constants needed for component."""

SUPPORT_ALARM_ARM_HOME = 1
SUPPORT_ALARM_ARM_AWAY = 2
SUPPORT_ALARM_ARM_NIGHT = 4
SUPPORT_ALARM_TRIGGER = 8
SUPPORT_ALARM_ARM_CUSTOM_BYPASS = 16
88 changes: 54 additions & 34 deletions homeassistant/components/alarm_control_panel/device_action.py
@@ -1,5 +1,6 @@
"""Provides device automations for Alarm control panel."""
from typing import Optional, List
from typing import List, Optional

import voluptuous as vol

from homeassistant.const import (
Expand All @@ -16,10 +17,17 @@
SERVICE_ALARM_DISARM,
SERVICE_ALARM_TRIGGER,
)
from homeassistant.core import HomeAssistant, Context
from homeassistant.core import Context, HomeAssistant
from homeassistant.helpers import entity_registry
import homeassistant.helpers.config_validation as cv

from . import ATTR_CODE_ARM_REQUIRED, DOMAIN
from .const import (
SUPPORT_ALARM_ARM_AWAY,
SUPPORT_ALARM_ARM_HOME,
SUPPORT_ALARM_ARM_NIGHT,
SUPPORT_ALARM_TRIGGER,
)

ACTION_TYPES = {"arm_away", "arm_home", "arm_night", "disarm", "trigger"}

Expand All @@ -42,31 +50,42 @@ async def async_get_actions(hass: HomeAssistant, device_id: str) -> List[dict]:
if entry.domain != DOMAIN:
continue

state = hass.states.get(entry.entity_id)

# We need a state or else we can't populate the HVAC and preset modes.
if state is None:
continue

supported_features = state.attributes["supported_features"]

# Add actions for each entity that belongs to this integration
actions.append(
{
CONF_DEVICE_ID: device_id,
CONF_DOMAIN: DOMAIN,
CONF_ENTITY_ID: entry.entity_id,
CONF_TYPE: "arm_away",
}
)
actions.append(
{
CONF_DEVICE_ID: device_id,
CONF_DOMAIN: DOMAIN,
CONF_ENTITY_ID: entry.entity_id,
CONF_TYPE: "arm_home",
}
)
actions.append(
{
CONF_DEVICE_ID: device_id,
CONF_DOMAIN: DOMAIN,
CONF_ENTITY_ID: entry.entity_id,
CONF_TYPE: "arm_night",
}
)
if supported_features & SUPPORT_ALARM_ARM_AWAY:
actions.append(
{
CONF_DEVICE_ID: device_id,
CONF_DOMAIN: DOMAIN,
CONF_ENTITY_ID: entry.entity_id,
CONF_TYPE: "arm_away",
}
)
if supported_features & SUPPORT_ALARM_ARM_HOME:
actions.append(
{
CONF_DEVICE_ID: device_id,
CONF_DOMAIN: DOMAIN,
CONF_ENTITY_ID: entry.entity_id,
CONF_TYPE: "arm_home",
}
)
if supported_features & SUPPORT_ALARM_ARM_NIGHT:
actions.append(
{
CONF_DEVICE_ID: device_id,
CONF_DOMAIN: DOMAIN,
CONF_ENTITY_ID: entry.entity_id,
CONF_TYPE: "arm_night",
}
)
actions.append(
{
CONF_DEVICE_ID: device_id,
Expand All @@ -75,14 +94,15 @@ async def async_get_actions(hass: HomeAssistant, device_id: str) -> List[dict]:
CONF_TYPE: "disarm",
}
)
actions.append(
{
CONF_DEVICE_ID: device_id,
CONF_DOMAIN: DOMAIN,
CONF_ENTITY_ID: entry.entity_id,
CONF_TYPE: "trigger",
}
)
if supported_features & SUPPORT_ALARM_TRIGGER:
actions.append(
{
CONF_DEVICE_ID: device_id,
CONF_DOMAIN: DOMAIN,
CONF_ENTITY_ID: entry.entity_id,
CONF_TYPE: "trigger",
}
)

return actions

Expand Down
10 changes: 10 additions & 0 deletions homeassistant/components/alarmdecoder/alarm_control_panel.py
Expand Up @@ -4,6 +4,11 @@
import voluptuous as vol

import homeassistant.components.alarm_control_panel as alarm
from homeassistant.components.alarm_control_panel.const import (
SUPPORT_ALARM_ARM_AWAY,
SUPPORT_ALARM_ARM_HOME,
SUPPORT_ALARM_ARM_NIGHT,
)
from homeassistant.const import (
ATTR_CODE,
STATE_ALARM_ARMED_AWAY,
Expand Down Expand Up @@ -122,6 +127,11 @@ def state(self):
"""Return the state of the device."""
return self._state

@property
def supported_features(self) -> int:
"""Return the list of supported features."""
return SUPPORT_ALARM_ARM_HOME | SUPPORT_ALARM_ARM_AWAY | SUPPORT_ALARM_ARM_NIGHT

@property
def device_state_attributes(self):
"""Return the state attributes."""
Expand Down
9 changes: 9 additions & 0 deletions homeassistant/components/alarmdotcom/alarm_control_panel.py
Expand Up @@ -7,6 +7,10 @@

import homeassistant.components.alarm_control_panel as alarm
from homeassistant.components.alarm_control_panel import PLATFORM_SCHEMA
from homeassistant.components.alarm_control_panel.const import (
SUPPORT_ALARM_ARM_AWAY,
SUPPORT_ALARM_ARM_HOME,
)
from homeassistant.const import (
CONF_CODE,
CONF_NAME,
Expand Down Expand Up @@ -95,6 +99,11 @@ def state(self):
return STATE_ALARM_ARMED_AWAY
return None

@property
def supported_features(self) -> int:
"""Return the list of supported features."""
return SUPPORT_ALARM_ARM_HOME | SUPPORT_ALARM_ARM_AWAY

@property
def device_state_attributes(self):
"""Return the state attributes."""
Expand Down
10 changes: 10 additions & 0 deletions homeassistant/components/arlo/alarm_control_panel.py
Expand Up @@ -7,6 +7,11 @@
PLATFORM_SCHEMA,
AlarmControlPanel,
)
from homeassistant.components.alarm_control_panel.const import (
SUPPORT_ALARM_ARM_AWAY,
SUPPORT_ALARM_ARM_HOME,
SUPPORT_ALARM_ARM_NIGHT,
)
from homeassistant.const import (
ATTR_ATTRIBUTION,
STATE_ALARM_ARMED_AWAY,
Expand Down Expand Up @@ -91,6 +96,11 @@ def state(self):
"""Return the state of the device."""
return self._state

@property
def supported_features(self) -> int:
"""Return the list of supported features."""
return SUPPORT_ALARM_ARM_HOME | SUPPORT_ALARM_ARM_AWAY | SUPPORT_ALARM_ARM_NIGHT

def update(self):
"""Update the state of the device."""
_LOGGER.debug("Updating Arlo Alarm Control Panel %s", self.name)
Expand Down
6 changes: 6 additions & 0 deletions homeassistant/components/blink/alarm_control_panel.py
Expand Up @@ -2,6 +2,7 @@
import logging

from homeassistant.components.alarm_control_panel import AlarmControlPanel
from homeassistant.components.alarm_control_panel.const import SUPPORT_ALARM_ARM_AWAY
from homeassistant.const import (
ATTR_ATTRIBUTION,
STATE_ALARM_ARMED_AWAY,
Expand Down Expand Up @@ -52,6 +53,11 @@ def state(self):
"""Return the state of the device."""
return self._state

@property
def supported_features(self) -> int:
"""Return the list of supported features."""
return SUPPORT_ALARM_ARM_AWAY

@property
def name(self):
"""Return the name of the panel."""
Expand Down
10 changes: 10 additions & 0 deletions homeassistant/components/canary/alarm_control_panel.py
Expand Up @@ -4,6 +4,11 @@
from canary.api import LOCATION_MODE_AWAY, LOCATION_MODE_HOME, LOCATION_MODE_NIGHT

from homeassistant.components.alarm_control_panel import AlarmControlPanel
from homeassistant.components.alarm_control_panel.const import (
SUPPORT_ALARM_ARM_AWAY,
SUPPORT_ALARM_ARM_HOME,
SUPPORT_ALARM_ARM_NIGHT,
)
from homeassistant.const import (
STATE_ALARM_ARMED_AWAY,
STATE_ALARM_ARMED_HOME,
Expand Down Expand Up @@ -59,6 +64,11 @@ def state(self):
return STATE_ALARM_ARMED_NIGHT
return None

@property
def supported_features(self) -> int:
"""Return the list of supported features."""
return SUPPORT_ALARM_ARM_HOME | SUPPORT_ALARM_ARM_AWAY | SUPPORT_ALARM_ARM_NIGHT

@property
def device_state_attributes(self):
"""Return the state attributes."""
Expand Down
9 changes: 9 additions & 0 deletions homeassistant/components/concord232/alarm_control_panel.py
Expand Up @@ -8,6 +8,10 @@

import homeassistant.components.alarm_control_panel as alarm
from homeassistant.components.alarm_control_panel import PLATFORM_SCHEMA
from homeassistant.components.alarm_control_panel.const import (
SUPPORT_ALARM_ARM_AWAY,
SUPPORT_ALARM_ARM_HOME,
)
from homeassistant.const import (
CONF_CODE,
CONF_HOST,
Expand Down Expand Up @@ -85,6 +89,11 @@ def state(self):
"""Return the state of the device."""
return self._state

@property
def supported_features(self) -> int:
"""Return the list of supported features."""
return SUPPORT_ALARM_ARM_HOME | SUPPORT_ALARM_ARM_AWAY

def update(self):
"""Update values from API."""
try:
Expand Down

0 comments on commit 1fde0d1

Please sign in to comment.