mirror of
https://github.com/home-assistant/core.git
synced 2025-07-13 08:17:08 +00:00
Use shorthand attributes for MQTT device tracker entity (#142671)
This commit is contained in:
parent
7cbcb21e80
commit
505dfcbcd9
@ -4,7 +4,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
import logging
|
import logging
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
@ -28,8 +28,8 @@ from homeassistant.helpers.typing import ConfigType, VolSchemaType
|
|||||||
|
|
||||||
from . import subscription
|
from . import subscription
|
||||||
from .config import MQTT_BASE_SCHEMA
|
from .config import MQTT_BASE_SCHEMA
|
||||||
from .const import CONF_PAYLOAD_RESET, CONF_STATE_TOPIC
|
from .const import CONF_JSON_ATTRS_TOPIC, CONF_PAYLOAD_RESET, CONF_STATE_TOPIC
|
||||||
from .entity import CONF_JSON_ATTRS_TOPIC, MqttEntity, async_setup_entity_entry_helper
|
from .entity import MqttEntity, async_setup_entity_entry_helper
|
||||||
from .models import MqttValueTemplate, ReceiveMessage
|
from .models import MqttValueTemplate, ReceiveMessage
|
||||||
from .schemas import MQTT_ENTITY_COMMON_SCHEMA
|
from .schemas import MQTT_ENTITY_COMMON_SCHEMA
|
||||||
from .util import valid_subscribe_topic
|
from .util import valid_subscribe_topic
|
||||||
@ -111,6 +111,7 @@ class MqttDeviceTracker(MqttEntity, TrackerEntity):
|
|||||||
self._value_template = MqttValueTemplate(
|
self._value_template = MqttValueTemplate(
|
||||||
config.get(CONF_VALUE_TEMPLATE), entity=self
|
config.get(CONF_VALUE_TEMPLATE), entity=self
|
||||||
).async_render_with_possible_json_value
|
).async_render_with_possible_json_value
|
||||||
|
self._attr_source_type = self._config[CONF_SOURCE_TYPE]
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _tracker_message_received(self, msg: ReceiveMessage) -> None:
|
def _tracker_message_received(self, msg: ReceiveMessage) -> None:
|
||||||
@ -124,72 +125,44 @@ class MqttDeviceTracker(MqttEntity, TrackerEntity):
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
if payload == self._config[CONF_PAYLOAD_HOME]:
|
if payload == self._config[CONF_PAYLOAD_HOME]:
|
||||||
self._location_name = STATE_HOME
|
self._attr_location_name = STATE_HOME
|
||||||
elif payload == self._config[CONF_PAYLOAD_NOT_HOME]:
|
elif payload == self._config[CONF_PAYLOAD_NOT_HOME]:
|
||||||
self._location_name = STATE_NOT_HOME
|
self._attr_location_name = STATE_NOT_HOME
|
||||||
elif payload == self._config[CONF_PAYLOAD_RESET]:
|
elif payload == self._config[CONF_PAYLOAD_RESET]:
|
||||||
self._location_name = None
|
self._attr_location_name = None
|
||||||
else:
|
else:
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
assert isinstance(msg.payload, str)
|
assert isinstance(msg.payload, str)
|
||||||
self._location_name = msg.payload
|
self._attr_location_name = msg.payload
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _prepare_subscribe_topics(self) -> None:
|
def _prepare_subscribe_topics(self) -> None:
|
||||||
"""(Re)Subscribe to topics."""
|
"""(Re)Subscribe to topics."""
|
||||||
self.add_subscription(
|
self.add_subscription(
|
||||||
CONF_STATE_TOPIC, self._tracker_message_received, {"_location_name"}
|
CONF_STATE_TOPIC, self._tracker_message_received, {"_attr_location_name"}
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
|
||||||
def force_update(self) -> bool:
|
|
||||||
"""Do not force updates if the state is the same."""
|
|
||||||
return False
|
|
||||||
|
|
||||||
async def _subscribe_topics(self) -> None:
|
async def _subscribe_topics(self) -> None:
|
||||||
"""(Re)Subscribe to topics."""
|
"""(Re)Subscribe to topics."""
|
||||||
subscription.async_subscribe_topics_internal(self.hass, self._sub_state)
|
subscription.async_subscribe_topics_internal(self.hass, self._sub_state)
|
||||||
|
|
||||||
@property
|
@callback
|
||||||
def latitude(self) -> float | None:
|
def _process_update_extra_state_attributes(
|
||||||
"""Return latitude if provided in extra_state_attributes or None."""
|
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 (
|
if (
|
||||||
self.extra_state_attributes is not None
|
ATTR_LATITUDE in extra_state_attributes
|
||||||
and ATTR_LATITUDE in self.extra_state_attributes
|
or ATTR_LONGITUDE in extra_state_attributes
|
||||||
):
|
):
|
||||||
latitude: float = self.extra_state_attributes[ATTR_LATITUDE]
|
# Reset manual set location
|
||||||
return latitude
|
self._attr_location_name = None
|
||||||
return None
|
|
||||||
|
|
||||||
@property
|
self._attr_location_accuracy = extra_state_attributes.get(ATTR_GPS_ACCURACY, 0)
|
||||||
def location_accuracy(self) -> int:
|
self._attr_extra_state_attributes = {
|
||||||
"""Return location accuracy if provided in extra_state_attributes or None."""
|
attribute: value
|
||||||
if (
|
for attribute, value in extra_state_attributes.items()
|
||||||
self.extra_state_attributes is not None
|
if attribute not in {ATTR_GPS_ACCURACY, ATTR_LATITUDE, ATTR_LONGITUDE}
|
||||||
and ATTR_GPS_ACCURACY in self.extra_state_attributes
|
}
|
||||||
):
|
|
||||||
accuracy: int = self.extra_state_attributes[ATTR_GPS_ACCURACY]
|
|
||||||
return accuracy
|
|
||||||
return 0
|
|
||||||
|
|
||||||
@property
|
|
||||||
def longitude(self) -> float | None:
|
|
||||||
"""Return longitude if provided in extra_state_attributes or None."""
|
|
||||||
if (
|
|
||||||
self.extra_state_attributes is not None
|
|
||||||
and ATTR_LONGITUDE in self.extra_state_attributes
|
|
||||||
):
|
|
||||||
longitude: float = self.extra_state_attributes[ATTR_LONGITUDE]
|
|
||||||
return longitude
|
|
||||||
return None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def location_name(self) -> str | None:
|
|
||||||
"""Return a location name for the current location of the device."""
|
|
||||||
return self._location_name
|
|
||||||
|
|
||||||
@property
|
|
||||||
def source_type(self) -> SourceType:
|
|
||||||
"""Return the source type, eg gps or router, of the device."""
|
|
||||||
source_type: SourceType = self._config[CONF_SOURCE_TYPE]
|
|
||||||
return source_type
|
|
||||||
|
@ -402,6 +402,7 @@ class MqttAttributesMixin(Entity):
|
|||||||
_message_callback: Callable[
|
_message_callback: Callable[
|
||||||
[MessageCallbackType, set[str] | None, ReceiveMessage], None
|
[MessageCallbackType, set[str] | None, ReceiveMessage], None
|
||||||
]
|
]
|
||||||
|
_process_update_extra_state_attributes: Callable[[dict[str, Any]], None]
|
||||||
|
|
||||||
def __init__(self, config: ConfigType) -> None:
|
def __init__(self, config: ConfigType) -> None:
|
||||||
"""Initialize the JSON attributes mixin."""
|
"""Initialize the JSON attributes mixin."""
|
||||||
@ -438,7 +439,13 @@ class MqttAttributesMixin(Entity):
|
|||||||
"msg_callback": partial(
|
"msg_callback": partial(
|
||||||
self._message_callback,
|
self._message_callback,
|
||||||
self._attributes_message_received,
|
self._attributes_message_received,
|
||||||
{"_attr_extra_state_attributes"},
|
{
|
||||||
|
"_attr_extra_state_attributes",
|
||||||
|
"_attr_gps_accuracy",
|
||||||
|
"_attr_latitude",
|
||||||
|
"_attr_location_name",
|
||||||
|
"_attr_longitude",
|
||||||
|
},
|
||||||
),
|
),
|
||||||
"entity_id": self.entity_id,
|
"entity_id": self.entity_id,
|
||||||
"qos": self._attributes_config.get(CONF_QOS),
|
"qos": self._attributes_config.get(CONF_QOS),
|
||||||
@ -477,7 +484,11 @@ class MqttAttributesMixin(Entity):
|
|||||||
if k not in MQTT_ATTRIBUTES_BLOCKED
|
if k not in MQTT_ATTRIBUTES_BLOCKED
|
||||||
and k not in self._attributes_extra_blocked
|
and k not in self._attributes_extra_blocked
|
||||||
}
|
}
|
||||||
self._attr_extra_state_attributes = filtered_dict
|
if hasattr(self, "_process_update_extra_state_attributes"):
|
||||||
|
self._process_update_extra_state_attributes(filtered_dict)
|
||||||
|
else:
|
||||||
|
self._attr_extra_state_attributes = filtered_dict
|
||||||
|
|
||||||
else:
|
else:
|
||||||
_LOGGER.warning("JSON result was not a dictionary")
|
_LOGGER.warning("JSON result was not a dictionary")
|
||||||
|
|
||||||
|
@ -454,12 +454,10 @@ async def test_setting_device_tracker_location_via_lat_lon_message(
|
|||||||
|
|
||||||
async_fire_mqtt_message(hass, "attributes-topic", '{"longitude": -117.22743}')
|
async_fire_mqtt_message(hass, "attributes-topic", '{"longitude": -117.22743}')
|
||||||
state = hass.states.get("device_tracker.test")
|
state = hass.states.get("device_tracker.test")
|
||||||
assert state.attributes["longitude"] == -117.22743
|
|
||||||
assert state.state == STATE_UNKNOWN
|
assert state.state == STATE_UNKNOWN
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "attributes-topic", '{"latitude":32.87336}')
|
async_fire_mqtt_message(hass, "attributes-topic", '{"latitude":32.87336}')
|
||||||
state = hass.states.get("device_tracker.test")
|
state = hass.states.get("device_tracker.test")
|
||||||
assert state.attributes["latitude"] == 32.87336
|
|
||||||
assert state.state == STATE_UNKNOWN
|
assert state.state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user