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") @WEBHOOK_COMMANDS.register("update_location")
@validate_schema( @validate_schema(
vol.Schema(
cv.key_dependency(ATTR_GPS, ATTR_GPS_ACCURACY),
{ {
vol.Optional(ATTR_LOCATION_NAME): cv.string, vol.Optional(ATTR_LOCATION_NAME): cv.string,
vol.Required(ATTR_GPS): cv.gps, vol.Optional(ATTR_GPS): cv.gps,
vol.Required(ATTR_GPS_ACCURACY): cv.positive_int, vol.Optional(ATTR_GPS_ACCURACY): cv.positive_int,
vol.Optional(ATTR_BATTERY): cv.positive_int, vol.Optional(ATTR_BATTERY): cv.positive_int,
vol.Optional(ATTR_SPEED): cv.positive_int, vol.Optional(ATTR_SPEED): cv.positive_int,
vol.Optional(ATTR_ALTITUDE): vol.Coerce(float), vol.Optional(ATTR_ALTITUDE): vol.Coerce(float),
vol.Optional(ATTR_COURSE): cv.positive_int, vol.Optional(ATTR_COURSE): cv.positive_int,
vol.Optional(ATTR_VERTICAL_ACCURACY): cv.positive_int, vol.Optional(ATTR_VERTICAL_ACCURACY): cv.positive_int,
} },
)
) )
async def webhook_update_location(hass, config_entry, data): async def webhook_update_location(hass, config_entry, data):
"""Handle an update location webhook.""" """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.camera import SUPPORT_STREAM as CAMERA_SUPPORT_STREAM
from homeassistant.components.mobile_app.const import CONF_SECRET from homeassistant.components.mobile_app.const import CONF_SECRET
from homeassistant.components.zone import DOMAIN as ZONE_DOMAIN 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.core import callback
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import entity_registry as er 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" 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.""" """Test that location can be updated."""
resp = await webhook_client.post( resp = await webhook_client.post(
"/api/webhook/{}".format(create_registrations[1]["webhook_id"]), "/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 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): async def test_webhook_enable_encryption(hass, webhook_client, create_registrations):
"""Test that encryption can be added to a reg initially created without.""" """Test that encryption can be added to a reg initially created without."""
webhook_id = create_registrations[1]["webhook_id"] webhook_id = create_registrations[1]["webhook_id"]