diff --git a/homeassistant/components/simplisafe/__init__.py b/homeassistant/components/simplisafe/__init__.py index 63ac0ca973c..52517b7d25f 100644 --- a/homeassistant/components/simplisafe/__init__.py +++ b/homeassistant/components/simplisafe/__init__.py @@ -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 diff --git a/homeassistant/components/simplisafe/alarm_control_panel.py b/homeassistant/components/simplisafe/alarm_control_panel.py index 05dad43955c..2cb6c4b41c5 100644 --- a/homeassistant/components/simplisafe/alarm_control_panel.py +++ b/homeassistant/components/simplisafe/alarm_control_panel.py @@ -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, } diff --git a/homeassistant/components/simplisafe/manifest.json b/homeassistant/components/simplisafe/manifest.json index ccb822e7f45..f7f6fce0c74 100644 --- a/homeassistant/components/simplisafe/manifest.json +++ b/homeassistant/components/simplisafe/manifest.json @@ -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"] } diff --git a/homeassistant/components/simplisafe/services.yaml b/homeassistant/components/simplisafe/services.yaml index d8a4973b49e..6d01dfd8e46 100644 --- a/homeassistant/components/simplisafe/services.yaml +++ b/homeassistant/components/simplisafe/services.yaml @@ -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 diff --git a/requirements_all.txt b/requirements_all.txt index 2210acb3359..073737f6fb9 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -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 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index ff228d57bb3..62b887eb900 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -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