Create base entity for SimpliSafe

This commit is contained in:
Aaron Bach 2019-11-09 15:41:02 -07:00 committed by Martin Hjelmare
parent a39cac765e
commit 179a2eb187
5 changed files with 85 additions and 59 deletions

View File

@ -22,7 +22,11 @@ from homeassistant.helpers import (
config_validation as cv,
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.service import verify_domain_control
@ -240,3 +244,73 @@ class SimpliSafe:
tasks = [self._update_system(system) for system in self.systems.values()]
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()

View File

@ -2,7 +2,7 @@
import logging
import re
from simplipy.sensor import SensorTypes
from simplipy.entity import EntityTypes
from simplipy.system import SystemStates
from homeassistant.components.alarm_control_panel import (
@ -16,11 +16,10 @@ from homeassistant.const import (
STATE_ALARM_ARMED_HOME,
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 .const import DATA_CLIENT, DOMAIN, TOPIC_UPDATE
from . import SimpliSafeEntity
from .const import DATA_CLIENT, DOMAIN
_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_TYPE = "last_event_type"
ATTR_RF_JAMMING = "rf_jamming"
ATTR_SYSTEM_ID = "system_id"
ATTR_WALL_POWER_LEVEL = "wall_power_level"
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."""
def __init__(self, simplisafe, system, code):
"""Initialize the SimpliSafe alarm."""
self._async_unsub_dispatcher_connect = None
self._attrs = {ATTR_SYSTEM_ID: system.system_id}
super().__init__(system, "Alarm Control Panel")
self._changed_by = None
self._code = code
self._simplisafe = simplisafe
self._state = None
self._system = system
# Some properties only exist for V2 or V3 systems:
for prop in (
@ -93,39 +89,11 @@ class SimpliSafeAlarm(AlarmControlPanel):
return FORMAT_NUMBER
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
def state(self):
"""Return the state of the entity."""
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):
"""Validate given 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)
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):
"""Send disarm command."""
if not self._validate_code(code, "disarming"):
@ -174,6 +130,7 @@ class SimpliSafeAlarm(AlarmControlPanel):
self._changed_by = event_data["pinName"]
if self._system.state == SystemStates.error:
self._online = False
return
if self._system.state == SystemStates.off:
@ -195,15 +152,10 @@ class SimpliSafeAlarm(AlarmControlPanel):
ATTR_ALARM_ACTIVE: self._system.alarm_going_off,
ATTR_LAST_EVENT_INFO: last_event["info"],
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(
last_event["eventTimestamp"]
),
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()

View File

@ -4,7 +4,7 @@
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/simplisafe",
"requirements": [
"simplisafe-python==5.0.1"
"simplisafe-python==5.1.0"
],
"dependencies": [],
"codeowners": [

View File

@ -1769,7 +1769,7 @@ shodan==1.19.0
simplepush==1.1.4
# homeassistant.components.simplisafe
simplisafe-python==5.0.1
simplisafe-python==5.1.0
# homeassistant.components.sisyphus
sisyphus-control==2.2.1

View File

@ -546,7 +546,7 @@ rxv==0.6.0
samsungctl[websocket]==0.7.1
# homeassistant.components.simplisafe
simplisafe-python==5.0.1
simplisafe-python==5.1.0
# homeassistant.components.sleepiq
sleepyq==0.7