mirror of
https://github.com/home-assistant/core.git
synced 2025-07-27 23:27:37 +00:00
Create base entity for SimpliSafe
This commit is contained in:
parent
a39cac765e
commit
179a2eb187
@ -22,7 +22,11 @@ from homeassistant.helpers import (
|
|||||||
config_validation as cv,
|
config_validation as cv,
|
||||||
device_registry as dr,
|
device_registry as dr,
|
||||||
)
|
)
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
from homeassistant.helpers.dispatcher import (
|
||||||
|
async_dispatcher_connect,
|
||||||
|
async_dispatcher_send,
|
||||||
|
)
|
||||||
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.helpers.event import async_track_time_interval
|
from homeassistant.helpers.event import async_track_time_interval
|
||||||
from homeassistant.helpers.service import verify_domain_control
|
from homeassistant.helpers.service import verify_domain_control
|
||||||
|
|
||||||
@ -240,3 +244,73 @@ class SimpliSafe:
|
|||||||
tasks = [self._update_system(system) for system in self.systems.values()]
|
tasks = [self._update_system(system) for system in self.systems.values()]
|
||||||
|
|
||||||
await asyncio.gather(*tasks)
|
await asyncio.gather(*tasks)
|
||||||
|
|
||||||
|
|
||||||
|
class SimpliSafeEntity(Entity):
|
||||||
|
"""Define a base SimpliSafe entity."""
|
||||||
|
|
||||||
|
def __init__(self, system, name, *, serial=None):
|
||||||
|
"""Initialize."""
|
||||||
|
self._async_unsub_dispatcher_connect = None
|
||||||
|
self._attrs = {ATTR_SYSTEM_ID: system.system_id}
|
||||||
|
self._name = name
|
||||||
|
self._online = True
|
||||||
|
self._system = system
|
||||||
|
|
||||||
|
if serial:
|
||||||
|
self._serial = serial
|
||||||
|
else:
|
||||||
|
self._serial = system.serial
|
||||||
|
|
||||||
|
@property
|
||||||
|
def available(self):
|
||||||
|
"""Return whether the entity is available."""
|
||||||
|
# We can easily detect if the V3 system is offline, but no simple check exists
|
||||||
|
# for the V2 system. Therefore, we mark the entity as available if:
|
||||||
|
# 1. We can verify that the system is online (assuming True if we can't)
|
||||||
|
# 2. We can verify that the entity is online
|
||||||
|
system_offline = self._system.version == 3 and self._system.offline
|
||||||
|
return not system_offline and self._online
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device_info(self):
|
||||||
|
"""Return device registry information for this entity."""
|
||||||
|
return {
|
||||||
|
"identifiers": {(DOMAIN, self._system.system_id)},
|
||||||
|
"manufacturer": "SimpliSafe",
|
||||||
|
"model": self._system.version,
|
||||||
|
"name": self._name,
|
||||||
|
"via_device": (DOMAIN, self._system.serial),
|
||||||
|
}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device_state_attributes(self):
|
||||||
|
"""Return the state attributes."""
|
||||||
|
return self._attrs
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
"""Return the name of the entity."""
|
||||||
|
return f"{self._system.address} {self._name}"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def unique_id(self):
|
||||||
|
"""Return the unique ID of the entity."""
|
||||||
|
return self._serial
|
||||||
|
|
||||||
|
async def async_added_to_hass(self):
|
||||||
|
"""Register callbacks."""
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def update():
|
||||||
|
"""Update the state."""
|
||||||
|
self.async_schedule_update_ha_state(True)
|
||||||
|
|
||||||
|
self._async_unsub_dispatcher_connect = async_dispatcher_connect(
|
||||||
|
self.hass, TOPIC_UPDATE, update
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
|
"""Disconnect dispatcher listener when removed."""
|
||||||
|
if self._async_unsub_dispatcher_connect:
|
||||||
|
self._async_unsub_dispatcher_connect()
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from simplipy.sensor import SensorTypes
|
from simplipy.entity import EntityTypes
|
||||||
from simplipy.system import SystemStates
|
from simplipy.system import SystemStates
|
||||||
|
|
||||||
from homeassistant.components.alarm_control_panel import (
|
from homeassistant.components.alarm_control_panel import (
|
||||||
@ -16,11 +16,10 @@ from homeassistant.const import (
|
|||||||
STATE_ALARM_ARMED_HOME,
|
STATE_ALARM_ARMED_HOME,
|
||||||
STATE_ALARM_DISARMED,
|
STATE_ALARM_DISARMED,
|
||||||
)
|
)
|
||||||
from homeassistant.core import callback
|
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
|
||||||
from homeassistant.util.dt import utc_from_timestamp
|
from homeassistant.util.dt import utc_from_timestamp
|
||||||
|
|
||||||
from .const import DATA_CLIENT, DOMAIN, TOPIC_UPDATE
|
from . import SimpliSafeEntity
|
||||||
|
from .const import DATA_CLIENT, DOMAIN
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -33,7 +32,6 @@ ATTR_LAST_EVENT_SENSOR_TYPE = "last_event_sensor_type"
|
|||||||
ATTR_LAST_EVENT_TIMESTAMP = "last_event_timestamp"
|
ATTR_LAST_EVENT_TIMESTAMP = "last_event_timestamp"
|
||||||
ATTR_LAST_EVENT_TYPE = "last_event_type"
|
ATTR_LAST_EVENT_TYPE = "last_event_type"
|
||||||
ATTR_RF_JAMMING = "rf_jamming"
|
ATTR_RF_JAMMING = "rf_jamming"
|
||||||
ATTR_SYSTEM_ID = "system_id"
|
|
||||||
ATTR_WALL_POWER_LEVEL = "wall_power_level"
|
ATTR_WALL_POWER_LEVEL = "wall_power_level"
|
||||||
ATTR_WIFI_STRENGTH = "wifi_strength"
|
ATTR_WIFI_STRENGTH = "wifi_strength"
|
||||||
|
|
||||||
@ -55,18 +53,16 @@ async def async_setup_entry(hass, entry, async_add_entities):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class SimpliSafeAlarm(AlarmControlPanel):
|
class SimpliSafeAlarm(SimpliSafeEntity, AlarmControlPanel):
|
||||||
"""Representation of a SimpliSafe alarm."""
|
"""Representation of a SimpliSafe alarm."""
|
||||||
|
|
||||||
def __init__(self, simplisafe, system, code):
|
def __init__(self, simplisafe, system, code):
|
||||||
"""Initialize the SimpliSafe alarm."""
|
"""Initialize the SimpliSafe alarm."""
|
||||||
self._async_unsub_dispatcher_connect = None
|
super().__init__(system, "Alarm Control Panel")
|
||||||
self._attrs = {ATTR_SYSTEM_ID: system.system_id}
|
|
||||||
self._changed_by = None
|
self._changed_by = None
|
||||||
self._code = code
|
self._code = code
|
||||||
self._simplisafe = simplisafe
|
self._simplisafe = simplisafe
|
||||||
self._state = None
|
self._state = None
|
||||||
self._system = system
|
|
||||||
|
|
||||||
# Some properties only exist for V2 or V3 systems:
|
# Some properties only exist for V2 or V3 systems:
|
||||||
for prop in (
|
for prop in (
|
||||||
@ -93,39 +89,11 @@ class SimpliSafeAlarm(AlarmControlPanel):
|
|||||||
return FORMAT_NUMBER
|
return FORMAT_NUMBER
|
||||||
return FORMAT_TEXT
|
return FORMAT_TEXT
|
||||||
|
|
||||||
@property
|
|
||||||
def device_info(self):
|
|
||||||
"""Return device registry information for this entity."""
|
|
||||||
return {
|
|
||||||
"identifiers": {(DOMAIN, self._system.system_id)},
|
|
||||||
"manufacturer": "SimpliSafe",
|
|
||||||
"model": self._system.version,
|
|
||||||
# The name should become more dynamic once we deduce a way to
|
|
||||||
# get various other sensors from SimpliSafe in a reliable manner:
|
|
||||||
"name": "Keypad",
|
|
||||||
"via_device": (DOMAIN, self._system.serial),
|
|
||||||
}
|
|
||||||
|
|
||||||
@property
|
|
||||||
def device_state_attributes(self):
|
|
||||||
"""Return the state attributes."""
|
|
||||||
return self._attrs
|
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self):
|
|
||||||
"""Return the name of the entity."""
|
|
||||||
return self._system.address
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state(self):
|
def state(self):
|
||||||
"""Return the state of the entity."""
|
"""Return the state of the entity."""
|
||||||
return self._state
|
return self._state
|
||||||
|
|
||||||
@property
|
|
||||||
def unique_id(self):
|
|
||||||
"""Return the unique ID of the entity."""
|
|
||||||
return self._system.system_id
|
|
||||||
|
|
||||||
def _validate_code(self, code, state):
|
def _validate_code(self, code, state):
|
||||||
"""Validate given code."""
|
"""Validate given code."""
|
||||||
check = self._code is None or code == self._code
|
check = self._code is None or code == self._code
|
||||||
@ -133,18 +101,6 @@ class SimpliSafeAlarm(AlarmControlPanel):
|
|||||||
_LOGGER.warning("Wrong code entered for %s", state)
|
_LOGGER.warning("Wrong code entered for %s", state)
|
||||||
return check
|
return check
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
|
||||||
"""Register callbacks."""
|
|
||||||
|
|
||||||
@callback
|
|
||||||
def update():
|
|
||||||
"""Update the state."""
|
|
||||||
self.async_schedule_update_ha_state(True)
|
|
||||||
|
|
||||||
self._async_unsub_dispatcher_connect = async_dispatcher_connect(
|
|
||||||
self.hass, TOPIC_UPDATE, update
|
|
||||||
)
|
|
||||||
|
|
||||||
async def async_alarm_disarm(self, code=None):
|
async def async_alarm_disarm(self, code=None):
|
||||||
"""Send disarm command."""
|
"""Send disarm command."""
|
||||||
if not self._validate_code(code, "disarming"):
|
if not self._validate_code(code, "disarming"):
|
||||||
@ -174,6 +130,7 @@ class SimpliSafeAlarm(AlarmControlPanel):
|
|||||||
self._changed_by = event_data["pinName"]
|
self._changed_by = event_data["pinName"]
|
||||||
|
|
||||||
if self._system.state == SystemStates.error:
|
if self._system.state == SystemStates.error:
|
||||||
|
self._online = False
|
||||||
return
|
return
|
||||||
|
|
||||||
if self._system.state == SystemStates.off:
|
if self._system.state == SystemStates.off:
|
||||||
@ -195,15 +152,10 @@ class SimpliSafeAlarm(AlarmControlPanel):
|
|||||||
ATTR_ALARM_ACTIVE: self._system.alarm_going_off,
|
ATTR_ALARM_ACTIVE: self._system.alarm_going_off,
|
||||||
ATTR_LAST_EVENT_INFO: last_event["info"],
|
ATTR_LAST_EVENT_INFO: last_event["info"],
|
||||||
ATTR_LAST_EVENT_SENSOR_NAME: last_event["sensorName"],
|
ATTR_LAST_EVENT_SENSOR_NAME: last_event["sensorName"],
|
||||||
ATTR_LAST_EVENT_SENSOR_TYPE: SensorTypes(last_event["sensorType"]).name,
|
ATTR_LAST_EVENT_SENSOR_TYPE: EntityTypes(last_event["sensorType"]).name,
|
||||||
ATTR_LAST_EVENT_TIMESTAMP: utc_from_timestamp(
|
ATTR_LAST_EVENT_TIMESTAMP: utc_from_timestamp(
|
||||||
last_event["eventTimestamp"]
|
last_event["eventTimestamp"]
|
||||||
),
|
),
|
||||||
ATTR_LAST_EVENT_TYPE: last_event["eventType"],
|
ATTR_LAST_EVENT_TYPE: last_event["eventType"],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self) -> None:
|
|
||||||
"""Disconnect dispatcher listener when removed."""
|
|
||||||
if self._async_unsub_dispatcher_connect:
|
|
||||||
self._async_unsub_dispatcher_connect()
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/simplisafe",
|
"documentation": "https://www.home-assistant.io/integrations/simplisafe",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"simplisafe-python==5.0.1"
|
"simplisafe-python==5.1.0"
|
||||||
],
|
],
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"codeowners": [
|
"codeowners": [
|
||||||
|
@ -1769,7 +1769,7 @@ shodan==1.19.0
|
|||||||
simplepush==1.1.4
|
simplepush==1.1.4
|
||||||
|
|
||||||
# homeassistant.components.simplisafe
|
# homeassistant.components.simplisafe
|
||||||
simplisafe-python==5.0.1
|
simplisafe-python==5.1.0
|
||||||
|
|
||||||
# homeassistant.components.sisyphus
|
# homeassistant.components.sisyphus
|
||||||
sisyphus-control==2.2.1
|
sisyphus-control==2.2.1
|
||||||
|
@ -546,7 +546,7 @@ rxv==0.6.0
|
|||||||
samsungctl[websocket]==0.7.1
|
samsungctl[websocket]==0.7.1
|
||||||
|
|
||||||
# homeassistant.components.simplisafe
|
# homeassistant.components.simplisafe
|
||||||
simplisafe-python==5.0.1
|
simplisafe-python==5.1.0
|
||||||
|
|
||||||
# homeassistant.components.sleepiq
|
# homeassistant.components.sleepiq
|
||||||
sleepyq==0.7
|
sleepyq==0.7
|
||||||
|
Loading…
x
Reference in New Issue
Block a user