Mobile App: Sensors (#21854)
## Description: **Related issue (if applicable):** fixes #21782 ## Checklist: - [x] The code change is tested and works locally. - [x] Local tests pass with `tox`. **Your PR cannot be merged unless tests pass** - [x] There is no commented out code in this PR.
This commit is contained in:
parent
6a80ffa8cc
commit
dcaced1966
9 changed files with 529 additions and 30 deletions
|
@ -10,30 +10,38 @@ from homeassistant.components.device_tracker import (ATTR_ATTRIBUTES,
|
|||
SERVICE_SEE as DT_SEE)
|
||||
|
||||
from homeassistant.const import (ATTR_DOMAIN, ATTR_SERVICE, ATTR_SERVICE_DATA,
|
||||
CONF_WEBHOOK_ID, HTTP_BAD_REQUEST)
|
||||
CONF_WEBHOOK_ID, HTTP_BAD_REQUEST,
|
||||
HTTP_CREATED)
|
||||
from homeassistant.core import EventOrigin
|
||||
from homeassistant.exceptions import (ServiceNotFound, TemplateError)
|
||||
from homeassistant.exceptions import (HomeAssistantError,
|
||||
ServiceNotFound, TemplateError)
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||
from homeassistant.helpers.template import attach
|
||||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
|
||||
from .const import (ATTR_ALTITUDE, ATTR_BATTERY, ATTR_COURSE, ATTR_DEVICE_ID,
|
||||
ATTR_DEVICE_NAME, ATTR_EVENT_DATA, ATTR_EVENT_TYPE,
|
||||
ATTR_GPS, ATTR_GPS_ACCURACY, ATTR_LOCATION_NAME,
|
||||
ATTR_MANUFACTURER, ATTR_MODEL, ATTR_OS_VERSION, ATTR_SPEED,
|
||||
ATTR_MANUFACTURER, ATTR_MODEL, ATTR_OS_VERSION,
|
||||
ATTR_SENSOR_TYPE, ATTR_SENSOR_UNIQUE_ID, ATTR_SPEED,
|
||||
ATTR_SUPPORTS_ENCRYPTION, ATTR_TEMPLATE,
|
||||
ATTR_TEMPLATE_VARIABLES, ATTR_VERTICAL_ACCURACY,
|
||||
ATTR_WEBHOOK_DATA, ATTR_WEBHOOK_ENCRYPTED,
|
||||
ATTR_WEBHOOK_ENCRYPTED_DATA, ATTR_WEBHOOK_TYPE,
|
||||
CONF_SECRET, DATA_CONFIG_ENTRIES, DATA_DELETED_IDS, DOMAIN,
|
||||
ERR_ENCRYPTION_REQUIRED, WEBHOOK_PAYLOAD_SCHEMA,
|
||||
CONF_SECRET, DATA_CONFIG_ENTRIES, DATA_DELETED_IDS,
|
||||
DATA_STORE, DOMAIN, ERR_ENCRYPTION_REQUIRED,
|
||||
ERR_SENSOR_DUPLICATE_UNIQUE_ID, ERR_SENSOR_NOT_REGISTERED,
|
||||
SIGNAL_SENSOR_UPDATE, WEBHOOK_PAYLOAD_SCHEMA,
|
||||
WEBHOOK_SCHEMAS, WEBHOOK_TYPE_CALL_SERVICE,
|
||||
WEBHOOK_TYPE_FIRE_EVENT, WEBHOOK_TYPE_RENDER_TEMPLATE,
|
||||
WEBHOOK_TYPE_UPDATE_LOCATION,
|
||||
WEBHOOK_TYPE_UPDATE_REGISTRATION)
|
||||
WEBHOOK_TYPE_FIRE_EVENT, WEBHOOK_TYPE_REGISTER_SENSOR,
|
||||
WEBHOOK_TYPE_RENDER_TEMPLATE, WEBHOOK_TYPE_UPDATE_LOCATION,
|
||||
WEBHOOK_TYPE_UPDATE_REGISTRATION,
|
||||
WEBHOOK_TYPE_UPDATE_SENSOR_STATES)
|
||||
|
||||
|
||||
from .helpers import (_decrypt_payload, empty_okay_response, error_response,
|
||||
registration_context, safe_registration,
|
||||
registration_context, safe_registration, savable_state,
|
||||
webhook_response)
|
||||
|
||||
|
||||
|
@ -79,6 +87,10 @@ async def handle_webhook(hass: HomeAssistantType, webhook_id: str,
|
|||
enc_data = req_data[ATTR_WEBHOOK_ENCRYPTED_DATA]
|
||||
webhook_payload = _decrypt_payload(registration[CONF_SECRET], enc_data)
|
||||
|
||||
if webhook_type not in WEBHOOK_SCHEMAS:
|
||||
_LOGGER.error('Received invalid webhook type: %s', webhook_type)
|
||||
return empty_okay_response()
|
||||
|
||||
try:
|
||||
data = WEBHOOK_SCHEMAS[webhook_type](webhook_payload)
|
||||
except vol.Invalid as ex:
|
||||
|
@ -172,3 +184,80 @@ async def handle_webhook(hass: HomeAssistantType, webhook_id: str,
|
|||
|
||||
return webhook_response(safe_registration(new_registration),
|
||||
registration=registration, headers=headers)
|
||||
|
||||
if webhook_type == WEBHOOK_TYPE_REGISTER_SENSOR:
|
||||
entity_type = data[ATTR_SENSOR_TYPE]
|
||||
|
||||
unique_id = data[ATTR_SENSOR_UNIQUE_ID]
|
||||
|
||||
unique_store_key = "{}_{}".format(webhook_id, unique_id)
|
||||
|
||||
if unique_store_key in hass.data[DOMAIN][entity_type]:
|
||||
_LOGGER.error("Refusing to re-register existing sensor %s!",
|
||||
unique_id)
|
||||
return error_response(ERR_SENSOR_DUPLICATE_UNIQUE_ID,
|
||||
"{} {} already exists!".format(entity_type,
|
||||
unique_id),
|
||||
status=409)
|
||||
|
||||
data[CONF_WEBHOOK_ID] = webhook_id
|
||||
|
||||
hass.data[DOMAIN][entity_type][unique_store_key] = data
|
||||
|
||||
try:
|
||||
await hass.data[DOMAIN][DATA_STORE].async_save(savable_state(hass))
|
||||
except HomeAssistantError as ex:
|
||||
_LOGGER.error("Error registering sensor: %s", ex)
|
||||
return empty_okay_response()
|
||||
|
||||
register_signal = '{}_{}_register'.format(DOMAIN,
|
||||
data[ATTR_SENSOR_TYPE])
|
||||
async_dispatcher_send(hass, register_signal, data)
|
||||
|
||||
return webhook_response({"status": "registered"},
|
||||
registration=registration, status=HTTP_CREATED,
|
||||
headers=headers)
|
||||
|
||||
if webhook_type == WEBHOOK_TYPE_UPDATE_SENSOR_STATES:
|
||||
resp = {}
|
||||
for sensor in data:
|
||||
entity_type = sensor[ATTR_SENSOR_TYPE]
|
||||
|
||||
unique_id = sensor[ATTR_SENSOR_UNIQUE_ID]
|
||||
|
||||
unique_store_key = "{}_{}".format(webhook_id, unique_id)
|
||||
|
||||
if unique_store_key not in hass.data[DOMAIN][entity_type]:
|
||||
_LOGGER.error("Refusing to update non-registered sensor: %s",
|
||||
unique_store_key)
|
||||
err_msg = '{} {} is not registered'.format(entity_type,
|
||||
unique_id)
|
||||
resp[unique_id] = {
|
||||
'success': False,
|
||||
'error': {
|
||||
'code': ERR_SENSOR_NOT_REGISTERED,
|
||||
'message': err_msg
|
||||
}
|
||||
}
|
||||
continue
|
||||
|
||||
entry = hass.data[DOMAIN][entity_type][unique_store_key]
|
||||
|
||||
new_state = {**entry, **sensor}
|
||||
|
||||
hass.data[DOMAIN][entity_type][unique_store_key] = new_state
|
||||
|
||||
safe = savable_state(hass)
|
||||
|
||||
try:
|
||||
await hass.data[DOMAIN][DATA_STORE].async_save(safe)
|
||||
except HomeAssistantError as ex:
|
||||
_LOGGER.error("Error updating mobile_app registration: %s", ex)
|
||||
return empty_okay_response()
|
||||
|
||||
async_dispatcher_send(hass, SIGNAL_SENSOR_UPDATE, new_state)
|
||||
|
||||
resp[unique_id] = {"status": "okay"}
|
||||
|
||||
return webhook_response(resp, registration=registration,
|
||||
headers=headers)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue