Add new mobile_app webhook command: get_zones (#22604)
## Description: Adds a new `mobile_app` webhook command, `get_zones`, which just returns all zones. ## 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
734a67ede0
commit
7bd8c0d39a
5 changed files with 55 additions and 15 deletions
|
@ -65,6 +65,7 @@ ERR_SENSOR_DUPLICATE_UNIQUE_ID = 'duplicate_unique_id'
|
|||
|
||||
WEBHOOK_TYPE_CALL_SERVICE = 'call_service'
|
||||
WEBHOOK_TYPE_FIRE_EVENT = 'fire_event'
|
||||
WEBHOOK_TYPE_GET_ZONES = 'get_zones'
|
||||
WEBHOOK_TYPE_REGISTER_SENSOR = 'register_sensor'
|
||||
WEBHOOK_TYPE_RENDER_TEMPLATE = 'render_template'
|
||||
WEBHOOK_TYPE_UPDATE_LOCATION = 'update_location'
|
||||
|
@ -72,8 +73,8 @@ WEBHOOK_TYPE_UPDATE_REGISTRATION = 'update_registration'
|
|||
WEBHOOK_TYPE_UPDATE_SENSOR_STATES = 'update_sensor_states'
|
||||
|
||||
WEBHOOK_TYPES = [WEBHOOK_TYPE_CALL_SERVICE, WEBHOOK_TYPE_FIRE_EVENT,
|
||||
WEBHOOK_TYPE_REGISTER_SENSOR, WEBHOOK_TYPE_RENDER_TEMPLATE,
|
||||
WEBHOOK_TYPE_UPDATE_LOCATION,
|
||||
WEBHOOK_TYPE_GET_ZONES, WEBHOOK_TYPE_REGISTER_SENSOR,
|
||||
WEBHOOK_TYPE_RENDER_TEMPLATE, WEBHOOK_TYPE_UPDATE_LOCATION,
|
||||
WEBHOOK_TYPE_UPDATE_REGISTRATION,
|
||||
WEBHOOK_TYPE_UPDATE_SENSOR_STATES]
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ from typing import Callable, Dict, Tuple
|
|||
from aiohttp.web import json_response, Response
|
||||
|
||||
from homeassistant.core import Context
|
||||
from homeassistant.helpers.json import JSONEncoder
|
||||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
|
||||
from .const import (ATTR_APP_DATA, ATTR_APP_ID, ATTR_APP_NAME,
|
||||
|
@ -133,9 +134,9 @@ def savable_state(hass: HomeAssistantType) -> Dict:
|
|||
def webhook_response(data, *, registration: Dict, status: int = 200,
|
||||
headers: Dict = None) -> Response:
|
||||
"""Return a encrypted response if registration supports it."""
|
||||
data = json.dumps(data)
|
||||
data = json.dumps(data, cls=JSONEncoder)
|
||||
|
||||
if CONF_SECRET in registration:
|
||||
if registration[ATTR_SUPPORTS_ENCRYPTION]:
|
||||
keylen, encrypt = setup_encrypt()
|
||||
|
||||
key = registration[CONF_SECRET].encode("utf-8")
|
||||
|
|
|
@ -9,6 +9,8 @@ from homeassistant.components.device_tracker import (ATTR_ATTRIBUTES,
|
|||
DOMAIN as DT_DOMAIN,
|
||||
SERVICE_SEE as DT_SEE)
|
||||
|
||||
from homeassistant.components.zone.const import DOMAIN as ZONE_DOMAIN
|
||||
|
||||
from homeassistant.const import (ATTR_DOMAIN, ATTR_SERVICE, ATTR_SERVICE_DATA,
|
||||
CONF_WEBHOOK_ID, HTTP_BAD_REQUEST,
|
||||
HTTP_CREATED)
|
||||
|
@ -33,9 +35,10 @@ from .const import (ATTR_ALTITUDE, ATTR_BATTERY, ATTR_COURSE, ATTR_DEVICE_ID,
|
|||
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_REGISTER_SENSOR,
|
||||
WEBHOOK_TYPE_RENDER_TEMPLATE, WEBHOOK_TYPE_UPDATE_LOCATION,
|
||||
WEBHOOK_SCHEMAS, WEBHOOK_TYPES, WEBHOOK_TYPE_CALL_SERVICE,
|
||||
WEBHOOK_TYPE_FIRE_EVENT, WEBHOOK_TYPE_GET_ZONES,
|
||||
WEBHOOK_TYPE_REGISTER_SENSOR, WEBHOOK_TYPE_RENDER_TEMPLATE,
|
||||
WEBHOOK_TYPE_UPDATE_LOCATION,
|
||||
WEBHOOK_TYPE_UPDATE_REGISTRATION,
|
||||
WEBHOOK_TYPE_UPDATE_SENSOR_STATES)
|
||||
|
||||
|
@ -87,16 +90,19 @@ 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:
|
||||
if webhook_type not in WEBHOOK_TYPES:
|
||||
_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:
|
||||
err = vol.humanize.humanize_error(webhook_payload, ex)
|
||||
_LOGGER.error('Received invalid webhook payload: %s', err)
|
||||
return empty_okay_response(headers=headers)
|
||||
data = webhook_payload
|
||||
|
||||
if webhook_type in WEBHOOK_SCHEMAS:
|
||||
try:
|
||||
data = WEBHOOK_SCHEMAS[webhook_type](webhook_payload)
|
||||
except vol.Invalid as ex:
|
||||
err = vol.humanize.humanize_error(webhook_payload, ex)
|
||||
_LOGGER.error('Received invalid webhook payload: %s', err)
|
||||
return empty_okay_response(headers=headers)
|
||||
|
||||
context = registration_context(registration)
|
||||
|
||||
|
@ -261,3 +267,9 @@ async def handle_webhook(hass: HomeAssistantType, webhook_id: str,
|
|||
|
||||
return webhook_response(resp, registration=registration,
|
||||
headers=headers)
|
||||
|
||||
if webhook_type == WEBHOOK_TYPE_GET_ZONES:
|
||||
zones = (hass.states.get(entity_id) for entity_id
|
||||
in sorted(hass.states.async_entity_ids(ZONE_DOMAIN)))
|
||||
return webhook_response(list(zones), registration=registration,
|
||||
headers=headers)
|
||||
|
|
|
@ -14,7 +14,7 @@ from .const import CONF_PASSIVE, DOMAIN, HOME_ZONE
|
|||
|
||||
@callback
|
||||
def configured_zones(hass):
|
||||
"""Return a set of the configured hosts."""
|
||||
"""Return a set of the configured zones."""
|
||||
return set((slugify(entry.data[CONF_NAME])) for
|
||||
entry in hass.config_entries.async_entries(DOMAIN))
|
||||
|
||||
|
|
|
@ -4,8 +4,10 @@ import logging
|
|||
import pytest
|
||||
|
||||
from homeassistant.components.mobile_app.const import CONF_SECRET
|
||||
from homeassistant.components.zone import DOMAIN as ZONE_DOMAIN
|
||||
from homeassistant.const import CONF_WEBHOOK_ID
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.common import async_mock_service
|
||||
|
||||
|
@ -100,6 +102,30 @@ async def test_webhook_update_registration(webhook_client, hass_client): # noqa
|
|||
assert CONF_SECRET not in update_json
|
||||
|
||||
|
||||
async def test_webhook_handle_get_zones(hass, create_registrations, # noqa: F401, F811, E501
|
||||
webhook_client): # noqa: F811
|
||||
"""Test that we can get zones properly."""
|
||||
await async_setup_component(hass, ZONE_DOMAIN, {
|
||||
ZONE_DOMAIN: {
|
||||
'name': 'test',
|
||||
'latitude': 32.880837,
|
||||
'longitude': -117.237561,
|
||||
'radius': 250,
|
||||
}
|
||||
})
|
||||
|
||||
resp = await webhook_client.post(
|
||||
'/api/webhook/{}'.format(create_registrations[1]['webhook_id']),
|
||||
json={'type': 'get_zones'}
|
||||
)
|
||||
|
||||
assert resp.status == 200
|
||||
|
||||
json = await resp.json()
|
||||
assert len(json) == 1
|
||||
assert json[0]['entity_id'] == 'zone.home'
|
||||
|
||||
|
||||
async def test_webhook_returns_error_incorrect_json(webhook_client, # noqa: F401, F811, E501
|
||||
create_registrations, # noqa: F401, F811, E501
|
||||
caplog): # noqa: E501 F811
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue