Consolidate SimpliSafe property services (#30567)

* Consolidate SimpliSafe property services

* Code review comments

* Code review comments

* Ensure all services are admin services

* Code review comments
This commit is contained in:
Aaron Bach 2020-01-12 21:32:08 -07:00 committed by GitHub
parent 123bef4f1e
commit b585feb109
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 96 additions and 139 deletions

View file

@ -5,7 +5,7 @@ import logging
from simplipy import API
from simplipy.errors import InvalidCredentialsError, SimplipyError
from simplipy.system.v3 import LevelMap as V3Volume
from simplipy.system.v3 import VOLUME_HIGH, VOLUME_LOW, VOLUME_MEDIUM, VOLUME_OFF
import voluptuous as vol
from homeassistant.config_entries import SOURCE_IMPORT
@ -15,7 +15,6 @@ from homeassistant.const import (
CONF_SCAN_INTERVAL,
CONF_TOKEN,
CONF_USERNAME,
STATE_HOME,
)
from homeassistant.core import callback
from homeassistant.exceptions import ConfigEntryNotReady
@ -30,7 +29,10 @@ from homeassistant.helpers.dispatcher import (
)
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.event import async_track_time_interval
from homeassistant.helpers.service import verify_domain_control
from homeassistant.helpers.service import (
async_register_admin_service,
verify_domain_control,
)
from .config_flow import configured_instances
from .const import DATA_CLIENT, DEFAULT_SCAN_INTERVAL, DOMAIN, TOPIC_UPDATE
@ -41,24 +43,21 @@ CONF_ACCOUNTS = "accounts"
DATA_LISTENER = "listener"
ATTR_ARMED_LIGHT_STATE = "armed_light_state"
ATTR_ARRIVAL_STATE = "arrival_state"
ATTR_ALARM_DURATION = "alarm_duration"
ATTR_ALARM_VOLUME = "alarm_volume"
ATTR_CHIME_VOLUME = "chime_volume"
ATTR_ENTRY_DELAY_AWAY = "entry_delay_away"
ATTR_ENTRY_DELAY_HOME = "entry_delay_home"
ATTR_EXIT_DELAY_AWAY = "exit_delay_away"
ATTR_EXIT_DELAY_HOME = "exit_delay_home"
ATTR_LIGHT = "light"
ATTR_PIN_LABEL = "label"
ATTR_PIN_LABEL_OR_VALUE = "label_or_pin"
ATTR_PIN_VALUE = "pin"
ATTR_SECONDS = "seconds"
ATTR_SYSTEM_ID = "system_id"
ATTR_TRANSITION = "transition"
ATTR_VOLUME = "volume"
ATTR_VOLUME_PROPERTY = "volume_property"
ATTR_VOICE_PROMPT_VOLUME = "voice_prompt_volume"
STATE_AWAY = "away"
STATE_ENTRY = "entry"
STATE_EXIT = "exit"
VOLUME_PROPERTY_ALARM = "alarm"
VOLUME_PROPERTY_CHIME = "chime"
VOLUME_PROPERTY_VOICE_PROMPT = "voice_prompt"
VOLUMES = [VOLUME_OFF, VOLUME_LOW, VOLUME_MEDIUM, VOLUME_HIGH]
SERVICE_BASE_SCHEMA = vol.Schema({vol.Required(ATTR_SYSTEM_ID): cv.positive_int})
@ -66,28 +65,33 @@ SERVICE_REMOVE_PIN_SCHEMA = SERVICE_BASE_SCHEMA.extend(
{vol.Required(ATTR_PIN_LABEL_OR_VALUE): cv.string}
)
SERVICE_SET_DELAY_SCHEMA = SERVICE_BASE_SCHEMA.extend(
{
vol.Required(ATTR_ARRIVAL_STATE): vol.In((STATE_AWAY, STATE_HOME)),
vol.Required(ATTR_TRANSITION): vol.In((STATE_ENTRY, STATE_EXIT)),
vol.Required(ATTR_SECONDS): cv.positive_int,
}
)
SERVICE_SET_LIGHT_SCHEMA = SERVICE_BASE_SCHEMA.extend(
{vol.Required(ATTR_ARMED_LIGHT_STATE): cv.boolean}
)
SERVICE_SET_PIN_SCHEMA = SERVICE_BASE_SCHEMA.extend(
{vol.Required(ATTR_PIN_LABEL): cv.string, vol.Required(ATTR_PIN_VALUE): cv.string}
)
SERVICE_SET_VOLUME_SCHEMA = SERVICE_BASE_SCHEMA.extend(
SERVICE_SET_SYSTEM_PROPERTIES_SCHEMA = SERVICE_BASE_SCHEMA.extend(
{
vol.Required(ATTR_VOLUME_PROPERTY): vol.In(
(VOLUME_PROPERTY_ALARM, VOLUME_PROPERTY_CHIME, VOLUME_PROPERTY_VOICE_PROMPT)
vol.Optional(ATTR_ALARM_DURATION): vol.All(
cv.time_period, lambda value: value.seconds, vol.Range(min=30, max=480)
),
vol.Optional(ATTR_ALARM_VOLUME): vol.All(vol.Coerce(int), vol.In(VOLUMES)),
vol.Optional(ATTR_CHIME_VOLUME): vol.All(vol.Coerce(int), vol.In(VOLUMES)),
vol.Optional(ATTR_ENTRY_DELAY_AWAY): vol.All(
cv.time_period, lambda value: value.seconds, vol.Range(min=30, max=255)
),
vol.Optional(ATTR_ENTRY_DELAY_HOME): vol.All(
cv.time_period, lambda value: value.seconds, vol.Range(max=255)
),
vol.Optional(ATTR_EXIT_DELAY_AWAY): vol.All(
cv.time_period, lambda value: value.seconds, vol.Range(min=45, max=255)
),
vol.Optional(ATTR_EXIT_DELAY_HOME): vol.All(
cv.time_period, lambda value: value.seconds, vol.Range(max=255)
),
vol.Optional(ATTR_LIGHT): cv.boolean,
vol.Optional(ATTR_VOICE_PROMPT_VOLUME): vol.All(
vol.Coerce(int), vol.In(VOLUMES)
),
vol.Required(ATTR_VOLUME): cv.string,
}
)
@ -246,47 +250,6 @@ async def async_setup_entry(hass, config_entry):
_LOGGER.error("Error during service call: %s", err)
return
@verify_system_exists
@v3_only
@_verify_domain_control
async def set_alarm_duration(call):
"""Set the duration of a running alarm."""
system = systems[call.data[ATTR_SYSTEM_ID]]
try:
await system.set_alarm_duration(call.data[ATTR_SECONDS])
except SimplipyError as err:
_LOGGER.error("Error during service call: %s", err)
return
@verify_system_exists
@v3_only
@_verify_domain_control
async def set_delay(call):
"""Set the delay duration for entry/exit, away/home (any combo)."""
system = systems[call.data[ATTR_SYSTEM_ID]]
coro = getattr(
system,
f"set_{call.data[ATTR_TRANSITION]}_delay_{call.data[ATTR_ARRIVAL_STATE]}",
)
try:
await coro(call.data[ATTR_SECONDS])
except SimplipyError as err:
_LOGGER.error("Error during service call: %s", err)
return
@verify_system_exists
@v3_only
@_verify_domain_control
async def set_armed_light(call):
"""Turn the base station light on/off."""
system = systems[call.data[ATTR_SYSTEM_ID]]
try:
await system.set_light(call.data[ATTR_ARMED_LIGHT_STATE])
except SimplipyError as err:
_LOGGER.error("Error during service call: %s", err)
return
@verify_system_exists
@_verify_domain_control
async def set_pin(call):
@ -301,30 +264,31 @@ async def async_setup_entry(hass, config_entry):
@verify_system_exists
@v3_only
@_verify_domain_control
async def set_volume_property(call):
"""Set a volume parameter in an appropriate service call."""
async def set_system_properties(call):
"""Set one or more system parameters."""
system = systems[call.data[ATTR_SYSTEM_ID]]
try:
volume = V3Volume[call.data[ATTR_VOLUME]]
except KeyError:
_LOGGER.error("Unknown volume string: %s", call.data[ATTR_VOLUME])
return
await system.set_properties(
{
prop: value
for prop, value in call.data.items()
if prop != ATTR_SYSTEM_ID
}
)
except SimplipyError as err:
_LOGGER.error("Error during service call: %s", err)
return
else:
coro = getattr(system, f"set_{call.data[ATTR_VOLUME_PROPERTY]}_volume")
await coro(volume)
for service, method, schema in [
("remove_pin", remove_pin, SERVICE_REMOVE_PIN_SCHEMA),
("set_alarm_duration", set_alarm_duration, SERVICE_SET_DELAY_SCHEMA),
("set_delay", set_delay, SERVICE_SET_DELAY_SCHEMA),
("set_armed_light", set_armed_light, SERVICE_SET_LIGHT_SCHEMA),
("set_pin", set_pin, SERVICE_SET_PIN_SCHEMA),
("set_volume_property", set_volume_property, SERVICE_SET_VOLUME_SCHEMA),
(
"set_system_properties",
set_system_properties,
SERVICE_SET_SYSTEM_PROPERTIES_SCHEMA,
),
]:
hass.services.async_register(DOMAIN, service, method, schema=schema)
async_register_admin_service(hass, DOMAIN, service, method, schema=schema)
return True

View file

@ -4,6 +4,7 @@ import re
from simplipy.entity import EntityTypes
from simplipy.system import SystemStates
from simplipy.system.v3 import VOLUME_HIGH, VOLUME_LOW, VOLUME_MEDIUM, VOLUME_OFF
from homeassistant.components.alarm_control_panel import (
FORMAT_NUMBER,
@ -48,6 +49,13 @@ ATTR_VOICE_PROMPT_VOLUME = "voice_prompt_volume"
ATTR_WALL_POWER_LEVEL = "wall_power_level"
ATTR_WIFI_STRENGTH = "wifi_strength"
VOLUME_STRING_MAP = {
VOLUME_HIGH: "high",
VOLUME_LOW: "low",
VOLUME_MEDIUM: "medium",
VOLUME_OFF: "off",
}
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Set up a SimpliSafe alarm control panel based on existing config."""
@ -82,9 +90,9 @@ class SimpliSafeAlarm(SimpliSafeEntity, AlarmControlPanel):
self._attrs.update(
{
ATTR_ALARM_DURATION: self._system.alarm_duration,
ATTR_ALARM_VOLUME: self._system.alarm_volume.name,
ATTR_ALARM_VOLUME: VOLUME_STRING_MAP[self._system.alarm_volume],
ATTR_BATTERY_BACKUP_POWER_LEVEL: self._system.battery_backup_power_level,
ATTR_CHIME_VOLUME: self._system.chime_volume.name,
ATTR_CHIME_VOLUME: VOLUME_STRING_MAP[self._system.chime_volume],
ATTR_ENTRY_DELAY_AWAY: self._system.entry_delay_away,
ATTR_ENTRY_DELAY_HOME: self._system.entry_delay_home,
ATTR_EXIT_DELAY_AWAY: self._system.exit_delay_away,
@ -92,7 +100,9 @@ class SimpliSafeAlarm(SimpliSafeEntity, AlarmControlPanel):
ATTR_GSM_STRENGTH: self._system.gsm_strength,
ATTR_LIGHT: self._system.light,
ATTR_RF_JAMMING: self._system.rf_jamming,
ATTR_VOICE_PROMPT_VOLUME: self._system.voice_prompt_volume.name,
ATTR_VOICE_PROMPT_VOLUME: VOLUME_STRING_MAP[
self._system.voice_prompt_volume
],
ATTR_WALL_POWER_LEVEL: self._system.wall_power_level,
ATTR_WIFI_STRENGTH: self._system.wifi_strength,
}

View file

@ -3,7 +3,7 @@
"name": "SimpliSafe",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/simplisafe",
"requirements": ["simplisafe-python==5.3.6"],
"requirements": ["simplisafe-python==6.0.0"],
"dependencies": [],
"codeowners": ["@bachya"]
}

View file

@ -10,41 +10,6 @@ remove_pin:
label_or_pin:
description: The label/value to remove.
example: Test PIN
set_alarm_duration:
description: "Set the duration (in seconds) of an active alarm"
fields:
system_id:
description: The SimpliSafe system ID to affect
example: 123987
seconds:
description: The number of seconds to sound the alarm
example: 120
set_delay:
description: >
Set a duration for how long the base station should delay when transitioning
between states
fields:
system_id:
description: The SimpliSafe system ID to affect
example: 123987
arrival_state:
description: The target "arrival" state (away, home)
example: away
transition:
description: The system state transition to affect (entry, exit)
example: exit
seconds:
description: "The number of seconds to delay"
example: 120
set_light:
description: "Turn the base station light on/off"
fields:
system_id:
description: The SimpliSafe system ID to affect
example: 123987
armed_light_state:
description: "True for on, False for off"
example: "True"
set_pin:
description: Set/update a PIN
fields:
@ -57,15 +22,33 @@ set_pin:
pin:
description: The value of the PIN
example: 1256
set_volume_property:
description: Set a level for one of the base station's various volumes
set_system_properties:
description: Set one or more system properties
fields:
system_id:
description: The SimpliSafe system ID to affect
example: 123987
volume_property:
description: The volume property to set (alarm, chime, voice_prompt)
example: voice_prompt
volume:
description: "A volume (off, low, medium, high)"
example: low
alarm_duration:
description: The length of a triggered alarm
example: 300
alarm_volume:
description: The volume level of a triggered alarm
example: 2
chime_volume:
description: The volume level of the door chime
example: 2
entry_delay_away:
description: How long to delay when entering while "away"
example: 45
entry_delay_home:
description: How long to delay when entering while "home"
example: 45
exit_delay_away:
description: How long to delay when exiting while "away"
example: 45
exit_delay_home:
description: How long to delay when exiting while "home"
example: 45
light:
description: Whether the armed light should be visible
example: true
voice_prompt_volume:
description: The volume level of the voice prompt
example: 2

View file

@ -1819,7 +1819,7 @@ shodan==1.21.2
simplepush==1.1.4
# homeassistant.components.simplisafe
simplisafe-python==5.3.6
simplisafe-python==6.0.0
# homeassistant.components.sisyphus
sisyphus-control==2.2.1

View file

@ -582,7 +582,7 @@ samsungctl[websocket]==0.7.1
sentry-sdk==0.13.5
# homeassistant.components.simplisafe
simplisafe-python==5.3.6
simplisafe-python==6.0.0
# homeassistant.components.sleepiq
sleepyq==0.7