This commit is contained in:
Paulus Schoutsen 2019-07-31 12:25:30 -07:00
parent da05dfe708
commit 4de97abc3a
2676 changed files with 163166 additions and 140084 deletions

View file

@ -9,11 +9,19 @@ import voluptuous as vol
from homeassistant.config_entries import SOURCE_IMPORT
from homeassistant.const import (
CONF_CODE, CONF_PASSWORD, CONF_SCAN_INTERVAL, CONF_TOKEN, CONF_USERNAME)
CONF_CODE,
CONF_PASSWORD,
CONF_SCAN_INTERVAL,
CONF_TOKEN,
CONF_USERNAME,
)
from homeassistant.core import callback
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import (
aiohttp_client, config_validation as cv, device_registry as dr)
aiohttp_client,
config_validation as cv,
device_registry as dr,
)
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers.event import async_track_time_interval
from homeassistant.helpers.service import verify_domain_control
@ -23,48 +31,58 @@ from .const import DATA_CLIENT, DEFAULT_SCAN_INTERVAL, DOMAIN, TOPIC_UPDATE
_LOGGER = logging.getLogger(__name__)
ATTR_PIN_LABEL = 'label'
ATTR_PIN_LABEL_OR_VALUE = 'label_or_pin'
ATTR_PIN_VALUE = 'pin'
ATTR_SYSTEM_ID = 'system_id'
ATTR_PIN_LABEL = "label"
ATTR_PIN_LABEL_OR_VALUE = "label_or_pin"
ATTR_PIN_VALUE = "pin"
ATTR_SYSTEM_ID = "system_id"
CONF_ACCOUNTS = 'accounts'
CONF_ACCOUNTS = "accounts"
DATA_LISTENER = 'listener'
DATA_LISTENER = "listener"
SERVICE_REMOVE_PIN_SCHEMA = vol.Schema({
vol.Required(ATTR_SYSTEM_ID): cv.string,
vol.Required(ATTR_PIN_LABEL_OR_VALUE): cv.string,
})
SERVICE_REMOVE_PIN_SCHEMA = vol.Schema(
{
vol.Required(ATTR_SYSTEM_ID): cv.string,
vol.Required(ATTR_PIN_LABEL_OR_VALUE): cv.string,
}
)
SERVICE_SET_PIN_SCHEMA = vol.Schema({
vol.Required(ATTR_SYSTEM_ID): cv.string,
vol.Required(ATTR_PIN_LABEL): cv.string,
vol.Required(ATTR_PIN_VALUE): cv.string,
})
SERVICE_SET_PIN_SCHEMA = vol.Schema(
{
vol.Required(ATTR_SYSTEM_ID): cv.string,
vol.Required(ATTR_PIN_LABEL): cv.string,
vol.Required(ATTR_PIN_VALUE): cv.string,
}
)
ACCOUNT_CONFIG_SCHEMA = vol.Schema({
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Optional(CONF_CODE): cv.string,
vol.Optional(CONF_SCAN_INTERVAL, default=DEFAULT_SCAN_INTERVAL):
cv.time_period,
})
ACCOUNT_CONFIG_SCHEMA = vol.Schema(
{
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Optional(CONF_CODE): cv.string,
vol.Optional(CONF_SCAN_INTERVAL, default=DEFAULT_SCAN_INTERVAL): cv.time_period,
}
)
CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Optional(CONF_ACCOUNTS):
vol.All(cv.ensure_list, [ACCOUNT_CONFIG_SCHEMA]),
}),
}, extra=vol.ALLOW_EXTRA)
CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.Schema(
{
vol.Optional(CONF_ACCOUNTS): vol.All(
cv.ensure_list, [ACCOUNT_CONFIG_SCHEMA]
)
}
)
},
extra=vol.ALLOW_EXTRA,
)
@callback
def _async_save_refresh_token(hass, config_entry, token):
hass.config_entries.async_update_entry(
config_entry, data={
**config_entry.data, CONF_TOKEN: token
})
config_entry, data={**config_entry.data, CONF_TOKEN: token}
)
async def async_register_base_station(hass, system, config_entry_id):
@ -72,10 +90,8 @@ async def async_register_base_station(hass, system, config_entry_id):
device_registry = await dr.async_get_registry(hass)
device_registry.async_get_or_create(
config_entry_id=config_entry_id,
identifiers={
(DOMAIN, system.serial)
},
manufacturer='SimpliSafe',
identifiers={(DOMAIN, system.serial)},
manufacturer="SimpliSafe",
model=system.version,
name=system.address,
)
@ -99,13 +115,15 @@ async def async_setup(hass, config):
hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN,
context={'source': SOURCE_IMPORT},
context={"source": SOURCE_IMPORT},
data={
CONF_USERNAME: account[CONF_USERNAME],
CONF_PASSWORD: account[CONF_PASSWORD],
CONF_CODE: account.get(CONF_CODE),
CONF_SCAN_INTERVAL: account[CONF_SCAN_INTERVAL],
}))
},
)
)
return True
@ -117,13 +135,12 @@ async def async_setup_entry(hass, config_entry):
websession = aiohttp_client.async_get_clientsession(hass)
try:
api = await API.login_via_token(
config_entry.data[CONF_TOKEN], websession)
api = await API.login_via_token(config_entry.data[CONF_TOKEN], websession)
except InvalidCredentialsError:
_LOGGER.error('Invalid credentials provided')
_LOGGER.error("Invalid credentials provided")
return False
except SimplipyError as err:
_LOGGER.error('Config entry failed: %s', err)
_LOGGER.error("Config entry failed: %s", err)
raise ConfigEntryNotReady
_async_save_refresh_token(hass, config_entry, api.refresh_token)
@ -135,25 +152,25 @@ async def async_setup_entry(hass, config_entry):
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(
config_entry, 'alarm_control_panel'))
config_entry, "alarm_control_panel"
)
)
async def refresh(event_time):
"""Refresh data from the SimpliSafe account."""
await simplisafe.async_update()
_LOGGER.debug('Updated data for all SimpliSafe systems')
_LOGGER.debug("Updated data for all SimpliSafe systems")
async_dispatcher_send(hass, TOPIC_UPDATE)
hass.data[DOMAIN][DATA_LISTENER][
config_entry.entry_id] = async_track_time_interval(
hass,
refresh,
timedelta(seconds=config_entry.data[CONF_SCAN_INTERVAL]))
hass.data[DOMAIN][DATA_LISTENER][config_entry.entry_id] = async_track_time_interval(
hass, refresh, timedelta(seconds=config_entry.data[CONF_SCAN_INTERVAL])
)
# Register the base station for each system:
for system in systems.values():
hass.async_create_task(
async_register_base_station(
hass, system, config_entry.entry_id))
async_register_base_station(hass, system, config_entry.entry_id)
)
@_verify_domain_control
async def remove_pin(call):
@ -165,12 +182,11 @@ async def async_setup_entry(hass, config_entry):
async def set_pin(call):
"""Set a PIN."""
system = systems[int(call.data[ATTR_SYSTEM_ID])]
await system.set_pin(
call.data[ATTR_PIN_LABEL], call.data[ATTR_PIN_VALUE])
await system.set_pin(call.data[ATTR_PIN_LABEL], call.data[ATTR_PIN_VALUE])
for service, method, schema in [
('remove_pin', remove_pin, SERVICE_REMOVE_PIN_SCHEMA),
('set_pin', set_pin, SERVICE_SET_PIN_SCHEMA),
("remove_pin", remove_pin, SERVICE_REMOVE_PIN_SCHEMA),
("set_pin", set_pin, SERVICE_SET_PIN_SCHEMA),
]:
hass.services.async_register(DOMAIN, service, method, schema=schema)
@ -179,8 +195,7 @@ async def async_setup_entry(hass, config_entry):
async def async_unload_entry(hass, entry):
"""Unload a SimpliSafe config entry."""
await hass.config_entries.async_forward_entry_unload(
entry, 'alarm_control_panel')
await hass.config_entries.async_forward_entry_unload(entry, "alarm_control_panel")
hass.data[DOMAIN][DATA_CLIENT].pop(entry.entry_id)
remove_listener = hass.data[DOMAIN][DATA_LISTENER].pop(entry.entry_id)
@ -206,24 +221,22 @@ class SimpliSafe:
latest_event = await system.get_latest_event()
except SimplipyError as err:
_LOGGER.error(
'SimpliSafe error while updating "%s": %s',
system.address, err)
'SimpliSafe error while updating "%s": %s', system.address, err
)
return
except Exception as err: # pylint: disable=broad-except
_LOGGER.error(
'Unknown error while updating "%s": %s', system.address, err)
_LOGGER.error('Unknown error while updating "%s": %s', system.address, err)
return
self.last_event_data[system.system_id] = latest_event
if system.api.refresh_token_dirty:
_async_save_refresh_token(
self._hass, self._config_entry, system.api.refresh_token)
self._hass, self._config_entry, system.api.refresh_token
)
async def async_update(self):
"""Get updated data from 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)