mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 01:08:12 +00:00
Validate MQTT device tracker location data before assigning (#141980)
* Validate MQTT device tracker location data before assigning * Log warning for invalid gps_accuracy
This commit is contained in:
parent
bf0d2e9bd2
commit
ea38639395
@ -28,7 +28,12 @@ from homeassistant.helpers.typing import ConfigType, VolSchemaType
|
||||
|
||||
from . import subscription
|
||||
from .config import MQTT_BASE_SCHEMA
|
||||
from .const import CONF_JSON_ATTRS_TOPIC, CONF_PAYLOAD_RESET, CONF_STATE_TOPIC
|
||||
from .const import (
|
||||
CONF_JSON_ATTRS_TEMPLATE,
|
||||
CONF_JSON_ATTRS_TOPIC,
|
||||
CONF_PAYLOAD_RESET,
|
||||
CONF_STATE_TOPIC,
|
||||
)
|
||||
from .entity import MqttEntity, async_setup_entity_entry_helper
|
||||
from .models import MqttValueTemplate, ReceiveMessage
|
||||
from .schemas import MQTT_ENTITY_COMMON_SCHEMA
|
||||
@ -151,16 +156,54 @@ class MqttDeviceTracker(MqttEntity, TrackerEntity):
|
||||
self, extra_state_attributes: dict[str, Any]
|
||||
) -> None:
|
||||
"""Extract the location from the extra state attributes."""
|
||||
self._attr_latitude = extra_state_attributes.get(ATTR_LATITUDE)
|
||||
self._attr_longitude = extra_state_attributes.get(ATTR_LONGITUDE)
|
||||
if (
|
||||
ATTR_LATITUDE in extra_state_attributes
|
||||
or ATTR_LONGITUDE in extra_state_attributes
|
||||
):
|
||||
# Reset manual set location
|
||||
latitude: float | None
|
||||
longitude: float | None
|
||||
gps_accuracy: int
|
||||
# Reset manually set location to allow automatic zone detection
|
||||
self._attr_location_name = None
|
||||
if isinstance(
|
||||
latitude := extra_state_attributes.get(ATTR_LATITUDE), (int, float)
|
||||
) and isinstance(
|
||||
longitude := extra_state_attributes.get(ATTR_LONGITUDE), (int, float)
|
||||
):
|
||||
self._attr_latitude = latitude
|
||||
self._attr_longitude = longitude
|
||||
else:
|
||||
# Invalid or incomplete coordinates, reset location
|
||||
self._attr_latitude = None
|
||||
self._attr_longitude = None
|
||||
_LOGGER.warning(
|
||||
"Extra state attributes received at % and template %s "
|
||||
"contain invalid or incomplete location info. Got %s",
|
||||
self._config.get(CONF_JSON_ATTRS_TEMPLATE),
|
||||
self._config.get(CONF_JSON_ATTRS_TOPIC),
|
||||
extra_state_attributes,
|
||||
)
|
||||
|
||||
if ATTR_GPS_ACCURACY in extra_state_attributes:
|
||||
if isinstance(
|
||||
gps_accuracy := extra_state_attributes[ATTR_GPS_ACCURACY],
|
||||
(int, float),
|
||||
):
|
||||
self._attr_location_accuracy = gps_accuracy
|
||||
else:
|
||||
_LOGGER.warning(
|
||||
"Extra state attributes received at % and template %s "
|
||||
"contain invalid GPS accuracy setting, "
|
||||
"gps_accuracy was set to 0 as the default. Got %s",
|
||||
self._config.get(CONF_JSON_ATTRS_TEMPLATE),
|
||||
self._config.get(CONF_JSON_ATTRS_TOPIC),
|
||||
extra_state_attributes,
|
||||
)
|
||||
self._attr_location_accuracy = 0
|
||||
|
||||
else:
|
||||
self._attr_location_accuracy = 0
|
||||
|
||||
self._attr_location_accuracy = extra_state_attributes.get(ATTR_GPS_ACCURACY, 0)
|
||||
self._attr_extra_state_attributes = {
|
||||
attribute: value
|
||||
for attribute, value in extra_state_attributes.items()
|
||||
|
@ -450,14 +450,82 @@ async def test_setting_device_tracker_location_via_lat_lon_message(
|
||||
assert state.attributes["latitude"] == 50.1
|
||||
assert state.attributes["longitude"] == -2.1
|
||||
assert state.attributes["gps_accuracy"] == 0
|
||||
assert state.attributes["source_type"] == "gps"
|
||||
assert state.state == STATE_NOT_HOME
|
||||
|
||||
# incomplete coordinates results in unknown state
|
||||
async_fire_mqtt_message(hass, "attributes-topic", '{"longitude": -117.22743}')
|
||||
state = hass.states.get("device_tracker.test")
|
||||
assert "latitude" not in state.attributes
|
||||
assert "longitude" not in state.attributes
|
||||
assert state.attributes["source_type"] == "gps"
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
async_fire_mqtt_message(hass, "attributes-topic", '{"latitude":32.87336}')
|
||||
state = hass.states.get("device_tracker.test")
|
||||
assert "latitude" not in state.attributes
|
||||
assert "longitude" not in state.attributes
|
||||
assert state.attributes["source_type"] == "gps"
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
# invalid coordinates results in unknown state
|
||||
async_fire_mqtt_message(
|
||||
hass, "attributes-topic", '{"longitude": -117.22743, "latitude":null}'
|
||||
)
|
||||
state = hass.states.get("device_tracker.test")
|
||||
assert "latitude" not in state.attributes
|
||||
assert "longitude" not in state.attributes
|
||||
assert state.attributes["source_type"] == "gps"
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
# Test number validation
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"attributes-topic",
|
||||
'{"latitude": "32.87336","longitude": "-117.22743", "gps_accuracy": "1.5", "source_type": "router"}',
|
||||
)
|
||||
state = hass.states.get("device_tracker.test")
|
||||
assert "latitude" not in state.attributes
|
||||
assert "longitude" not in state.attributes
|
||||
assert "gps_accuracy" not in state.attributes
|
||||
# assert source_type is overridden by discovery
|
||||
assert state.attributes["source_type"] == "router"
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
# Test with invalid GPS accuracy should default to 0,
|
||||
# but location updates as expected
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"attributes-topic",
|
||||
'{"latitude": 32.871234,"longitude": -117.21234, "gps_accuracy": "invalid", "source_type": "router"}',
|
||||
)
|
||||
state = hass.states.get("device_tracker.test")
|
||||
assert state.state == STATE_NOT_HOME
|
||||
assert state.attributes["latitude"] == 32.871234
|
||||
assert state.attributes["longitude"] == -117.21234
|
||||
assert state.attributes["gps_accuracy"] == 0
|
||||
assert state.attributes["source_type"] == "router"
|
||||
|
||||
# Test with invalid latitude
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"attributes-topic",
|
||||
'{"latitude": null,"longitude": "-117.22743", "gps_accuracy": 1, "source_type": "router"}',
|
||||
)
|
||||
state = hass.states.get("device_tracker.test")
|
||||
assert "latitude" not in state.attributes
|
||||
assert "longitude" not in state.attributes
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
# Test with invalid longitude
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"attributes-topic",
|
||||
'{"latitude": 32.87336,"longitude": "unknown", "gps_accuracy": 1, "source_type": "router"}',
|
||||
)
|
||||
state = hass.states.get("device_tracker.test")
|
||||
assert "latitude" not in state.attributes
|
||||
assert "longitude" not in state.attributes
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user