Allow name-only location updates for mobile_app device_tracker (#62243)

This commit is contained in:
Zac West 2022-01-13 12:30:36 -05:00 committed by GitHub
parent 06fd75be7e
commit 2df8ab865f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 139 additions and 12 deletions

View file

@ -311,16 +311,19 @@ async def webhook_render_template(hass, config_entry, data):
@WEBHOOK_COMMANDS.register("update_location")
@validate_schema(
{
vol.Optional(ATTR_LOCATION_NAME): cv.string,
vol.Required(ATTR_GPS): cv.gps,
vol.Required(ATTR_GPS_ACCURACY): cv.positive_int,
vol.Optional(ATTR_BATTERY): cv.positive_int,
vol.Optional(ATTR_SPEED): cv.positive_int,
vol.Optional(ATTR_ALTITUDE): vol.Coerce(float),
vol.Optional(ATTR_COURSE): cv.positive_int,
vol.Optional(ATTR_VERTICAL_ACCURACY): cv.positive_int,
}
vol.Schema(
cv.key_dependency(ATTR_GPS, ATTR_GPS_ACCURACY),
{
vol.Optional(ATTR_LOCATION_NAME): cv.string,
vol.Optional(ATTR_GPS): cv.gps,
vol.Optional(ATTR_GPS_ACCURACY): cv.positive_int,
vol.Optional(ATTR_BATTERY): cv.positive_int,
vol.Optional(ATTR_SPEED): cv.positive_int,
vol.Optional(ATTR_ALTITUDE): vol.Coerce(float),
vol.Optional(ATTR_COURSE): cv.positive_int,
vol.Optional(ATTR_VERTICAL_ACCURACY): cv.positive_int,
},
)
)
async def webhook_update_location(hass, config_entry, data):
"""Handle an update location webhook."""

View file

@ -7,7 +7,12 @@ import pytest
from homeassistant.components.camera import SUPPORT_STREAM as CAMERA_SUPPORT_STREAM
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.const import (
CONF_WEBHOOK_ID,
STATE_HOME,
STATE_NOT_HOME,
STATE_UNKNOWN,
)
from homeassistant.core import callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import entity_registry as er
@ -283,7 +288,46 @@ async def test_webhook_requires_encryption(webhook_client, create_registrations)
assert webhook_json["error"]["code"] == "encryption_required"
async def test_webhook_update_location(hass, webhook_client, create_registrations):
async def test_webhook_update_location_without_locations(
hass, webhook_client, create_registrations
):
"""Test that location can be updated."""
# start off with a location set by name
resp = await webhook_client.post(
"/api/webhook/{}".format(create_registrations[1]["webhook_id"]),
json={
"type": "update_location",
"data": {"location_name": STATE_HOME},
},
)
assert resp.status == HTTPStatus.OK
state = hass.states.get("device_tracker.test_1_2")
assert state is not None
assert state.state == STATE_HOME
# set location to an 'unknown' state
resp = await webhook_client.post(
"/api/webhook/{}".format(create_registrations[1]["webhook_id"]),
json={
"type": "update_location",
"data": {"altitude": 123},
},
)
assert resp.status == HTTPStatus.OK
state = hass.states.get("device_tracker.test_1_2")
assert state is not None
assert state.state == STATE_UNKNOWN
assert state.attributes["altitude"] == 123
async def test_webhook_update_location_with_gps(
hass, webhook_client, create_registrations
):
"""Test that location can be updated."""
resp = await webhook_client.post(
"/api/webhook/{}".format(create_registrations[1]["webhook_id"]),
@ -303,6 +347,86 @@ async def test_webhook_update_location(hass, webhook_client, create_registration
assert state.attributes["altitude"] == -10
async def test_webhook_update_location_with_gps_without_accuracy(
hass, webhook_client, create_registrations
):
"""Test that location can be updated."""
resp = await webhook_client.post(
"/api/webhook/{}".format(create_registrations[1]["webhook_id"]),
json={
"type": "update_location",
"data": {"gps": [1, 2]},
},
)
assert resp.status == HTTPStatus.OK
state = hass.states.get("device_tracker.test_1_2")
assert state.state == STATE_UNKNOWN
async def test_webhook_update_location_with_location_name(
hass, webhook_client, create_registrations
):
"""Test that location can be updated."""
with patch(
"homeassistant.config.load_yaml_config_file",
autospec=True,
return_value={
ZONE_DOMAIN: [
{
"name": "zone_name",
"latitude": 1.23,
"longitude": -4.56,
"radius": 200,
"icon": "mdi:test-tube",
},
]
},
):
await hass.services.async_call(ZONE_DOMAIN, "reload", blocking=True)
resp = await webhook_client.post(
"/api/webhook/{}".format(create_registrations[1]["webhook_id"]),
json={
"type": "update_location",
"data": {"location_name": "zone_name"},
},
)
assert resp.status == HTTPStatus.OK
state = hass.states.get("device_tracker.test_1_2")
assert state.state == "zone_name"
resp = await webhook_client.post(
"/api/webhook/{}".format(create_registrations[1]["webhook_id"]),
json={
"type": "update_location",
"data": {"location_name": STATE_HOME},
},
)
assert resp.status == HTTPStatus.OK
state = hass.states.get("device_tracker.test_1_2")
assert state.state == STATE_HOME
resp = await webhook_client.post(
"/api/webhook/{}".format(create_registrations[1]["webhook_id"]),
json={
"type": "update_location",
"data": {"location_name": STATE_NOT_HOME},
},
)
assert resp.status == HTTPStatus.OK
state = hass.states.get("device_tracker.test_1_2")
assert state.state == STATE_NOT_HOME
async def test_webhook_enable_encryption(hass, webhook_client, create_registrations):
"""Test that encryption can be added to a reg initially created without."""
webhook_id = create_registrations[1]["webhook_id"]