Replace SimpliSafe clear_notifications service with a button (#75283)

* Replace SimpliSafe `clear_notifications` service with a button

* Better log message

* Coverage

* Docstring

* Add repairs item

* Better repairs strings

* Mark issue as fixable

* Add issue registry through helper

* Update deprecation version
This commit is contained in:
Aaron Bach 2022-09-16 16:41:17 -06:00 committed by GitHub
parent 84cd0da26b
commit b4356a432e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 155 additions and 34 deletions

View file

@ -1110,6 +1110,7 @@ omit =
homeassistant/components/simplisafe/__init__.py
homeassistant/components/simplisafe/alarm_control_panel.py
homeassistant/components/simplisafe/binary_sensor.py
homeassistant/components/simplisafe/button.py
homeassistant/components/simplisafe/lock.py
homeassistant/components/simplisafe/sensor.py
homeassistant/components/simulated/sensor.py

View file

@ -71,6 +71,7 @@ from homeassistant.helpers.dispatcher import (
async_dispatcher_send,
)
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
from homeassistant.helpers.service import (
async_register_admin_service,
verify_domain_control,
@ -126,6 +127,7 @@ EVENT_SIMPLISAFE_NOTIFICATION = "SIMPLISAFE_NOTIFICATION"
PLATFORMS = [
Platform.ALARM_CONTROL_PANEL,
Platform.BINARY_SENSOR,
Platform.BUTTON,
Platform.LOCK,
Platform.SENSOR,
]
@ -257,6 +259,45 @@ def _async_get_system_for_service_call(
raise ValueError(f"No system for device ID: {device_id}")
@callback
def _async_log_deprecated_service_call(
hass: HomeAssistant,
call: ServiceCall,
alternate_service: str,
alternate_target: str,
breaks_in_ha_version: str,
) -> None:
"""Log a warning about a deprecated service call."""
deprecated_service = f"{call.domain}.{call.service}"
async_create_issue(
hass,
DOMAIN,
f"deprecated_service_{deprecated_service}",
breaks_in_ha_version=breaks_in_ha_version,
is_fixable=True,
is_persistent=True,
severity=IssueSeverity.WARNING,
translation_key="deprecated_service",
translation_placeholders={
"alternate_service": alternate_service,
"alternate_target": alternate_target,
"deprecated_service": deprecated_service,
},
)
LOGGER.warning(
(
'The "%s" service is deprecated and will be removed in %s; use the "%s" '
'service and pass it a target entity ID of "%s"'
),
deprecated_service,
breaks_in_ha_version,
alternate_service,
alternate_target,
)
@callback
def _async_register_base_station(
hass: HomeAssistant, entry: ConfigEntry, system: SystemType
@ -347,6 +388,13 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
@extract_system
async def async_clear_notifications(call: ServiceCall, system: SystemType) -> None:
"""Clear all active notifications."""
_async_log_deprecated_service_call(
hass,
call,
"button.press",
"button.alarm_control_panel_clear_notifications",
"2022.12.0",
)
await system.async_clear_notifications()
@_verify_domain_control
@ -839,9 +887,7 @@ class SimpliSafeEntity(CoordinatorEntity):
@callback
def async_update_from_rest_api(self) -> None:
"""Update the entity when new data comes from the REST API."""
raise NotImplementedError()
@callback
def async_update_from_websocket_event(self, event: WebsocketEvent) -> None:
"""Update the entity when new data comes from the websocket."""
raise NotImplementedError()

View file

@ -0,0 +1,93 @@
"""Buttons for the SimpliSafe integration."""
from __future__ import annotations
from collections.abc import Awaitable, Callable
from dataclasses import dataclass
from simplipy.errors import SimplipyError
from simplipy.system import System
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import SimpliSafe, SimpliSafeEntity
from .const import DOMAIN
from .typing import SystemType
@dataclass
class SimpliSafeButtonDescriptionMixin:
"""Define an entity description mixin for SimpliSafe buttons."""
push_action: Callable[[System], Awaitable]
@dataclass
class SimpliSafeButtonDescription(
ButtonEntityDescription, SimpliSafeButtonDescriptionMixin
):
"""Describe a SimpliSafe button entity."""
BUTTON_KIND_CLEAR_NOTIFICATIONS = "clear_notifications"
async def _async_clear_notifications(system: System) -> None:
"""Reboot the SimpliSafe."""
await system.async_clear_notifications()
BUTTON_DESCRIPTIONS = (
SimpliSafeButtonDescription(
key=BUTTON_KIND_CLEAR_NOTIFICATIONS,
name="Clear notifications",
push_action=_async_clear_notifications,
),
)
async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up SimpliSafe buttons based on a config entry."""
simplisafe = hass.data[DOMAIN][entry.entry_id]
async_add_entities(
[
SimpliSafeButton(simplisafe, system, description)
for system in simplisafe.systems.values()
for description in BUTTON_DESCRIPTIONS
]
)
class SimpliSafeButton(SimpliSafeEntity, ButtonEntity):
"""Define a SimpliSafe button."""
_attr_entity_category = EntityCategory.CONFIG
entity_description: SimpliSafeButtonDescription
def __init__(
self,
simplisafe: SimpliSafe,
system: SystemType,
description: SimpliSafeButtonDescription,
) -> None:
"""Initialize the SimpliSafe alarm."""
super().__init__(simplisafe, system)
self.entity_description = description
async def async_press(self) -> None:
"""Send out a restart command."""
try:
await self.entity_description.push_action(self._system)
except SimplipyError as err:
raise HomeAssistantError(
f'Error while pressing button "{self.entity_id}": {err}'
) from err

View file

@ -1,16 +1,4 @@
# Describes the format for available SimpliSafe services
clear_notifications:
name: Clear notifications
description: Clear any active SimpliSafe notifications
fields:
device_id:
name: System
description: The system to remove the PIN from
required: true
selector:
device:
integration: simplisafe
model: alarm_control_panel
remove_pin:
name: Remove PIN
description: Remove a PIN by its label or value.

View file

@ -29,5 +29,11 @@
}
}
}
},
"issues": {
"deprecated_service": {
"title": "The {deprecated_service} service is being removed",
"description": "Update any automations or scripts that use this service to instead use the `{alternate_service}` service with a target entity ID of `{alternate_target}`. Then, click SUBMIT below to mark this issue as resolved."
}
}
}

View file

@ -2,7 +2,6 @@
"config": {
"abort": {
"already_configured": "This SimpliSafe account is already in use.",
"email_2fa_timed_out": "Timed out while waiting for email-based two-factor authentication.",
"reauth_successful": "Re-authentication was successful",
"wrong_account": "The user credentials provided do not match this SimpliSafe account."
},
@ -12,33 +11,21 @@
"invalid_auth_code_length": "SimpliSafe authorization codes are 45 characters in length",
"unknown": "Unexpected error"
},
"progress": {
"email_2fa": "Check your email for a verification link from Simplisafe."
},
"step": {
"reauth_confirm": {
"data": {
"password": "Password"
},
"description": "Please re-enter the password for {username}.",
"title": "Reauthenticate Integration"
},
"sms_2fa": {
"data": {
"code": "Code"
},
"description": "Input the two-factor authentication code sent to you via SMS."
},
"user": {
"data": {
"auth_code": "Authorization Code",
"password": "Password",
"username": "Username"
"auth_code": "Authorization Code"
},
"description": "SimpliSafe authenticates users via its web app. Due to technical limitations, there is a manual step at the end of this process; please ensure that you read the [documentation](http://home-assistant.io/integrations/simplisafe#getting-an-authorization-code) before starting.\n\nWhen you are ready, click [here]({url}) to open the SimpliSafe web app and input your credentials. If you've already logged into SimpliSafe in your browser, you may want to open a new tab, then copy/paste the above URL into that tab.\n\nWhen the process is complete, return here and input the authorization code from the `com.simplisafe.mobile` URL."
}
}
},
"issues": {
"deprecated_service": {
"description": "Update any automations or scripts that use this service to instead use the `{alternate_service}` service with a target entity ID of `{alternate_target}`. Then, click SUBMIT below to mark this issue as resolved.",
"title": "The {deprecated_service} service is being removed"
}
},
"options": {
"step": {
"init": {