Add discovery for MQTT device tracker (#42327)
This commit is contained in:
parent
1d0b4290fe
commit
727b1d37b6
5 changed files with 602 additions and 7 deletions
7
homeassistant/components/mqtt/device_tracker/__init__.py
Normal file
7
homeassistant/components/mqtt/device_tracker/__init__.py
Normal file
|
@ -0,0 +1,7 @@
|
|||
"""Support for tracking MQTT enabled devices."""
|
||||
from .schema_discovery import async_setup_entry_from_discovery
|
||||
from .schema_yaml import PLATFORM_SCHEMA_YAML, async_setup_scanner_from_yaml
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA_YAML
|
||||
async_setup_scanner = async_setup_scanner_from_yaml
|
||||
async_setup_entry = async_setup_entry_from_discovery
|
229
homeassistant/components/mqtt/device_tracker/schema_discovery.py
Normal file
229
homeassistant/components/mqtt/device_tracker/schema_discovery.py
Normal file
|
@ -0,0 +1,229 @@
|
|||
"""Support for tracking MQTT enabled devices identified through discovery."""
|
||||
import logging
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components import device_tracker, mqtt
|
||||
from homeassistant.components.device_tracker import SOURCE_TYPES
|
||||
from homeassistant.components.device_tracker.config_entry import TrackerEntity
|
||||
from homeassistant.const import (
|
||||
ATTR_GPS_ACCURACY,
|
||||
ATTR_LATITUDE,
|
||||
ATTR_LONGITUDE,
|
||||
CONF_DEVICE,
|
||||
CONF_ICON,
|
||||
CONF_NAME,
|
||||
CONF_UNIQUE_ID,
|
||||
CONF_VALUE_TEMPLATE,
|
||||
STATE_HOME,
|
||||
STATE_NOT_HOME,
|
||||
)
|
||||
from homeassistant.core import callback
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
|
||||
from .. import (
|
||||
MqttAttributes,
|
||||
MqttAvailability,
|
||||
MqttDiscoveryUpdate,
|
||||
MqttEntityDeviceInfo,
|
||||
subscription,
|
||||
)
|
||||
from ..const import ATTR_DISCOVERY_HASH, CONF_QOS, CONF_STATE_TOPIC
|
||||
from ..debug_info import log_messages
|
||||
from ..discovery import MQTT_DISCOVERY_NEW, clear_discovery_hash
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CONF_PAYLOAD_HOME = "payload_home"
|
||||
CONF_PAYLOAD_NOT_HOME = "payload_not_home"
|
||||
CONF_SOURCE_TYPE = "source_type"
|
||||
|
||||
PLATFORM_SCHEMA_DISCOVERY = (
|
||||
mqtt.MQTT_RO_PLATFORM_SCHEMA.extend(
|
||||
{
|
||||
vol.Optional(CONF_DEVICE): mqtt.MQTT_ENTITY_DEVICE_INFO_SCHEMA,
|
||||
vol.Optional(CONF_ICON): cv.icon,
|
||||
vol.Optional(CONF_NAME): cv.string,
|
||||
vol.Optional(CONF_PAYLOAD_HOME, default=STATE_HOME): cv.string,
|
||||
vol.Optional(CONF_PAYLOAD_NOT_HOME, default=STATE_NOT_HOME): cv.string,
|
||||
vol.Optional(CONF_SOURCE_TYPE): vol.In(SOURCE_TYPES),
|
||||
vol.Optional(CONF_UNIQUE_ID): cv.string,
|
||||
}
|
||||
)
|
||||
.extend(mqtt.MQTT_AVAILABILITY_SCHEMA.schema)
|
||||
.extend(mqtt.MQTT_JSON_ATTRS_SCHEMA.schema)
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry_from_discovery(hass, config_entry, async_add_entities):
|
||||
"""Set up MQTT device tracker dynamically through MQTT discovery."""
|
||||
|
||||
async def async_discover(discovery_payload):
|
||||
"""Discover and add an MQTT device tracker."""
|
||||
discovery_data = discovery_payload.discovery_data
|
||||
try:
|
||||
config = PLATFORM_SCHEMA_DISCOVERY(discovery_payload)
|
||||
await _async_setup_entity(
|
||||
hass, config, async_add_entities, config_entry, discovery_data
|
||||
)
|
||||
except Exception:
|
||||
clear_discovery_hash(hass, discovery_data[ATTR_DISCOVERY_HASH])
|
||||
raise
|
||||
|
||||
async_dispatcher_connect(
|
||||
hass, MQTT_DISCOVERY_NEW.format(device_tracker.DOMAIN, "mqtt"), async_discover
|
||||
)
|
||||
|
||||
|
||||
async def _async_setup_entity(
|
||||
hass, config, async_add_entities, config_entry=None, discovery_data=None
|
||||
):
|
||||
"""Set up the MQTT Device Tracker entity."""
|
||||
async_add_entities([MqttDeviceTracker(hass, config, config_entry, discovery_data)])
|
||||
|
||||
|
||||
class MqttDeviceTracker(
|
||||
MqttAttributes,
|
||||
MqttAvailability,
|
||||
MqttDiscoveryUpdate,
|
||||
MqttEntityDeviceInfo,
|
||||
TrackerEntity,
|
||||
):
|
||||
"""Representation of a device tracker using MQTT."""
|
||||
|
||||
def __init__(self, hass, config, config_entry, discovery_data):
|
||||
"""Initialize the tracker."""
|
||||
self.hass = hass
|
||||
self._location_name = None
|
||||
self._sub_state = None
|
||||
self._unique_id = config.get(CONF_UNIQUE_ID)
|
||||
|
||||
# Load config
|
||||
self._setup_from_config(config)
|
||||
|
||||
device_config = config.get(CONF_DEVICE)
|
||||
|
||||
MqttAttributes.__init__(self, config)
|
||||
MqttAvailability.__init__(self, config)
|
||||
MqttDiscoveryUpdate.__init__(self, discovery_data, self.discovery_update)
|
||||
MqttEntityDeviceInfo.__init__(self, device_config, config_entry)
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""Subscribe to MQTT events."""
|
||||
await super().async_added_to_hass()
|
||||
await self._subscribe_topics()
|
||||
|
||||
async def discovery_update(self, discovery_payload):
|
||||
"""Handle updated discovery message."""
|
||||
config = PLATFORM_SCHEMA_DISCOVERY(discovery_payload)
|
||||
self._setup_from_config(config)
|
||||
await self.attributes_discovery_update(config)
|
||||
await self.availability_discovery_update(config)
|
||||
await self.device_info_discovery_update(config)
|
||||
await self._subscribe_topics()
|
||||
self.async_write_ha_state()
|
||||
|
||||
def _setup_from_config(self, config):
|
||||
"""(Re)Setup the entity."""
|
||||
self._config = config
|
||||
|
||||
value_template = self._config.get(CONF_VALUE_TEMPLATE)
|
||||
if value_template is not None:
|
||||
value_template.hass = self.hass
|
||||
|
||||
async def _subscribe_topics(self):
|
||||
"""(Re)Subscribe to topics."""
|
||||
|
||||
@callback
|
||||
@log_messages(self.hass, self.entity_id)
|
||||
def message_received(msg):
|
||||
"""Handle new MQTT messages."""
|
||||
payload = msg.payload
|
||||
value_template = self._config.get(CONF_VALUE_TEMPLATE)
|
||||
if value_template is not None:
|
||||
payload = value_template.async_render_with_possible_json_value(payload)
|
||||
if payload == self._config[CONF_PAYLOAD_HOME]:
|
||||
self._location_name = STATE_HOME
|
||||
elif payload == self._config[CONF_PAYLOAD_NOT_HOME]:
|
||||
self._location_name = STATE_NOT_HOME
|
||||
else:
|
||||
self._location_name = msg.payload
|
||||
|
||||
self.async_write_ha_state()
|
||||
|
||||
self._sub_state = await subscription.async_subscribe_topics(
|
||||
self.hass,
|
||||
self._sub_state,
|
||||
{
|
||||
"state_topic": {
|
||||
"topic": self._config[CONF_STATE_TOPIC],
|
||||
"msg_callback": message_received,
|
||||
"qos": self._config[CONF_QOS],
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
async def async_will_remove_from_hass(self):
|
||||
"""Unsubscribe when removed."""
|
||||
self._sub_state = await subscription.async_unsubscribe_topics(
|
||||
self.hass, self._sub_state
|
||||
)
|
||||
await MqttAttributes.async_will_remove_from_hass(self)
|
||||
await MqttAvailability.async_will_remove_from_hass(self)
|
||||
await MqttDiscoveryUpdate.async_will_remove_from_hass(self)
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
"""Return the icon of the device."""
|
||||
return self._config.get(CONF_ICON)
|
||||
|
||||
@property
|
||||
def latitude(self):
|
||||
"""Return latitude if provided in device_state_attributes or None."""
|
||||
if (
|
||||
self.device_state_attributes is not None
|
||||
and ATTR_LATITUDE in self.device_state_attributes
|
||||
):
|
||||
return self.device_state_attributes[ATTR_LATITUDE]
|
||||
return None
|
||||
|
||||
@property
|
||||
def location_accuracy(self):
|
||||
"""Return location accuracy if provided in device_state_attributes or None."""
|
||||
if (
|
||||
self.device_state_attributes is not None
|
||||
and ATTR_GPS_ACCURACY in self.device_state_attributes
|
||||
):
|
||||
return self.device_state_attributes[ATTR_GPS_ACCURACY]
|
||||
return None
|
||||
|
||||
@property
|
||||
def longitude(self):
|
||||
"""Return longitude if provided in device_state_attributes or None."""
|
||||
if (
|
||||
self.device_state_attributes is not None
|
||||
and ATTR_LONGITUDE in self.device_state_attributes
|
||||
):
|
||||
return self.device_state_attributes[ATTR_LONGITUDE]
|
||||
return None
|
||||
|
||||
@property
|
||||
def location_name(self):
|
||||
"""Return a location name for the current location of the device."""
|
||||
return self._location_name
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the device tracker."""
|
||||
return self._config.get(CONF_NAME)
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
"""Return a unique ID."""
|
||||
return self._unique_id
|
||||
|
||||
@property
|
||||
def source_type(self):
|
||||
"""Return the source type, eg gps or router, of the device."""
|
||||
return self._config.get(CONF_SOURCE_TYPE)
|
|
@ -1,5 +1,4 @@
|
|||
"""Support for tracking MQTT enabled devices."""
|
||||
import logging
|
||||
"""Support for tracking MQTT enabled devices defined in YAML."""
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
|
@ -9,15 +8,13 @@ from homeassistant.const import CONF_DEVICES, STATE_HOME, STATE_NOT_HOME
|
|||
from homeassistant.core import callback
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
from . import CONF_QOS
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
from ..const import CONF_QOS
|
||||
|
||||
CONF_PAYLOAD_HOME = "payload_home"
|
||||
CONF_PAYLOAD_NOT_HOME = "payload_not_home"
|
||||
CONF_SOURCE_TYPE = "source_type"
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(mqtt.SCHEMA_BASE).extend(
|
||||
PLATFORM_SCHEMA_YAML = PLATFORM_SCHEMA.extend(mqtt.SCHEMA_BASE).extend(
|
||||
{
|
||||
vol.Required(CONF_DEVICES): {cv.string: mqtt.valid_subscribe_topic},
|
||||
vol.Optional(CONF_PAYLOAD_HOME, default=STATE_HOME): cv.string,
|
||||
|
@ -27,7 +24,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(mqtt.SCHEMA_BASE).extend(
|
|||
)
|
||||
|
||||
|
||||
async def async_setup_scanner(hass, config, async_see, discovery_info=None):
|
||||
async def async_setup_scanner_from_yaml(hass, config, async_see, discovery_info=None):
|
||||
"""Set up the MQTT tracker."""
|
||||
devices = config[CONF_DEVICES]
|
||||
qos = config[CONF_QOS]
|
|
@ -34,6 +34,7 @@ SUPPORTED_COMPONENTS = [
|
|||
"climate",
|
||||
"cover",
|
||||
"device_automation",
|
||||
"device_tracker",
|
||||
"fan",
|
||||
"light",
|
||||
"lock",
|
||||
|
|
361
tests/components/mqtt/test_device_tracker_discovery.py
Normal file
361
tests/components/mqtt/test_device_tracker_discovery.py
Normal file
|
@ -0,0 +1,361 @@
|
|||
"""The tests for the MQTT device_tracker discovery platform."""
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.mqtt.discovery import ALREADY_DISCOVERED
|
||||
from homeassistant.const import STATE_HOME, STATE_NOT_HOME, STATE_UNKNOWN
|
||||
|
||||
from tests.common import async_fire_mqtt_message, mock_device_registry, mock_registry
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def device_reg(hass):
|
||||
"""Return an empty, loaded, registry."""
|
||||
return mock_device_registry(hass)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def entity_reg(hass):
|
||||
"""Return an empty, loaded, registry."""
|
||||
return mock_registry(hass)
|
||||
|
||||
|
||||
async def test_discover_device_tracker(hass, mqtt_mock, caplog):
|
||||
"""Test discovering an MQTT device tracker component."""
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"homeassistant/device_tracker/bla/config",
|
||||
'{ "name": "test", "state_topic": "test_topic" }',
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("device_tracker.test")
|
||||
|
||||
assert state is not None
|
||||
assert state.name == "test"
|
||||
assert ("device_tracker", "bla") in hass.data[ALREADY_DISCOVERED]
|
||||
|
||||
|
||||
@pytest.mark.no_fail_on_log_exception
|
||||
async def test_discovery_broken(hass, mqtt_mock, caplog):
|
||||
"""Test handling of bad discovery message."""
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"homeassistant/device_tracker/bla/config",
|
||||
'{ "name": "Beer" }',
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("device_tracker.beer")
|
||||
assert state is None
|
||||
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"homeassistant/device_tracker/bla/config",
|
||||
'{ "name": "Beer", "state_topic": "required-topic" }',
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("device_tracker.beer")
|
||||
assert state is not None
|
||||
assert state.name == "Beer"
|
||||
|
||||
|
||||
async def test_non_duplicate_device_tracker_discovery(hass, mqtt_mock, caplog):
|
||||
"""Test for a non duplicate component."""
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"homeassistant/device_tracker/bla/config",
|
||||
'{ "name": "Beer", "state_topic": "test-topic" }',
|
||||
)
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"homeassistant/device_tracker/bla/config",
|
||||
'{ "name": "Beer", "state_topic": "test-topic" }',
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("device_tracker.beer")
|
||||
state_duplicate = hass.states.get("device_tracker.beer1")
|
||||
|
||||
assert state is not None
|
||||
assert state.name == "Beer"
|
||||
assert state_duplicate is None
|
||||
assert "Component has already been discovered: device_tracker bla" in caplog.text
|
||||
|
||||
|
||||
async def test_device_tracker_removal(hass, mqtt_mock, caplog):
|
||||
"""Test removal of component through empty discovery message."""
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"homeassistant/device_tracker/bla/config",
|
||||
'{ "name": "Beer", "state_topic": "test-topic" }',
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("device_tracker.beer")
|
||||
assert state is not None
|
||||
|
||||
async_fire_mqtt_message(hass, "homeassistant/device_tracker/bla/config", "")
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("device_tracker.beer")
|
||||
assert state is None
|
||||
|
||||
|
||||
async def test_device_tracker_rediscover(hass, mqtt_mock, caplog):
|
||||
"""Test rediscover of removed component."""
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"homeassistant/device_tracker/bla/config",
|
||||
'{ "name": "Beer", "state_topic": "test-topic" }',
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("device_tracker.beer")
|
||||
assert state is not None
|
||||
|
||||
async_fire_mqtt_message(hass, "homeassistant/device_tracker/bla/config", "")
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("device_tracker.beer")
|
||||
assert state is None
|
||||
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"homeassistant/device_tracker/bla/config",
|
||||
'{ "name": "Beer", "state_topic": "test-topic" }',
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("device_tracker.beer")
|
||||
assert state is not None
|
||||
|
||||
|
||||
async def test_duplicate_device_tracker_removal(hass, mqtt_mock, caplog):
|
||||
"""Test for a non duplicate component."""
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"homeassistant/device_tracker/bla/config",
|
||||
'{ "name": "Beer", "state_topic": "test-topic" }',
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
async_fire_mqtt_message(hass, "homeassistant/device_tracker/bla/config", "")
|
||||
await hass.async_block_till_done()
|
||||
assert "Component has already been discovered: device_tracker bla" in caplog.text
|
||||
caplog.clear()
|
||||
async_fire_mqtt_message(hass, "homeassistant/device_tracker/bla/config", "")
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert (
|
||||
"Component has already been discovered: device_tracker bla" not in caplog.text
|
||||
)
|
||||
|
||||
|
||||
async def test_device_tracker_discovery_update(hass, mqtt_mock, caplog):
|
||||
"""Test for a discovery update event."""
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"homeassistant/device_tracker/bla/config",
|
||||
'{ "name": "Beer", "state_topic": "test-topic" }',
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("device_tracker.beer")
|
||||
assert state is not None
|
||||
assert state.name == "Beer"
|
||||
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"homeassistant/device_tracker/bla/config",
|
||||
'{ "name": "Cider", "state_topic": "test-topic" }',
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("device_tracker.beer")
|
||||
assert state is not None
|
||||
assert state.name == "Cider"
|
||||
|
||||
|
||||
async def test_cleanup_device_tracker(hass, device_reg, entity_reg, mqtt_mock):
|
||||
"""Test discvered device is cleaned up when removed from registry."""
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"homeassistant/device_tracker/bla/config",
|
||||
'{ "device":{"identifiers":["0AFFD2"]},'
|
||||
' "state_topic": "foobar/tracker",'
|
||||
' "unique_id": "unique" }',
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Verify device and registry entries are created
|
||||
device_entry = device_reg.async_get_device({("mqtt", "0AFFD2")}, set())
|
||||
assert device_entry is not None
|
||||
entity_entry = entity_reg.async_get("device_tracker.mqtt_unique")
|
||||
assert entity_entry is not None
|
||||
|
||||
state = hass.states.get("device_tracker.mqtt_unique")
|
||||
assert state is not None
|
||||
|
||||
device_reg.async_remove_device(device_entry.id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Verify device and registry entries are cleared
|
||||
device_entry = device_reg.async_get_device({("mqtt", "0AFFD2")}, set())
|
||||
assert device_entry is None
|
||||
entity_entry = entity_reg.async_get("device_tracker.mqtt_unique")
|
||||
assert entity_entry is None
|
||||
|
||||
# Verify state is removed
|
||||
state = hass.states.get("device_tracker.mqtt_unique")
|
||||
assert state is None
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Verify retained discovery topic has been cleared
|
||||
mqtt_mock.async_publish.assert_called_once_with(
|
||||
"homeassistant/device_tracker/bla/config", "", 0, True
|
||||
)
|
||||
|
||||
|
||||
async def test_setting_device_tracker_value_via_mqtt_message(hass, mqtt_mock, caplog):
|
||||
"""Test the setting of the value via MQTT."""
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"homeassistant/device_tracker/bla/config",
|
||||
'{ "name": "test", "state_topic": "test-topic" }',
|
||||
)
|
||||
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("device_tracker.test")
|
||||
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
async_fire_mqtt_message(hass, "test-topic", "home")
|
||||
state = hass.states.get("device_tracker.test")
|
||||
assert state.state == STATE_HOME
|
||||
|
||||
async_fire_mqtt_message(hass, "test-topic", "not_home")
|
||||
state = hass.states.get("device_tracker.test")
|
||||
assert state.state == STATE_NOT_HOME
|
||||
|
||||
|
||||
async def test_setting_device_tracker_value_via_mqtt_message_and_template(
|
||||
hass, mqtt_mock, caplog
|
||||
):
|
||||
"""Test the setting of the value via MQTT."""
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"homeassistant/device_tracker/bla/config",
|
||||
"{"
|
||||
'"name": "test", '
|
||||
'"state_topic": "test-topic", '
|
||||
'"value_template": "{% if value is equalto \\"proxy_for_home\\" %}home{% else %}not_home{% endif %}" '
|
||||
"}",
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
async_fire_mqtt_message(hass, "test-topic", "proxy_for_home")
|
||||
state = hass.states.get("device_tracker.test")
|
||||
assert state.state == STATE_HOME
|
||||
|
||||
async_fire_mqtt_message(hass, "test-topic", "anything_for_not_home")
|
||||
state = hass.states.get("device_tracker.test")
|
||||
assert state.state == STATE_NOT_HOME
|
||||
|
||||
|
||||
async def test_setting_device_tracker_value_via_mqtt_message_and_template2(
|
||||
hass, mqtt_mock, caplog
|
||||
):
|
||||
"""Test the setting of the value via MQTT."""
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"homeassistant/device_tracker/bla/config",
|
||||
"{"
|
||||
'"name": "test", '
|
||||
'"state_topic": "test-topic", '
|
||||
'"value_template": "{{ value | lower }}" '
|
||||
"}",
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("device_tracker.test")
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
async_fire_mqtt_message(hass, "test-topic", "HOME")
|
||||
state = hass.states.get("device_Tracker.test")
|
||||
assert state.state == STATE_HOME
|
||||
|
||||
async_fire_mqtt_message(hass, "test-topic", "NOT_HOME")
|
||||
state = hass.states.get("device_tracker.test")
|
||||
assert state.state == STATE_NOT_HOME
|
||||
|
||||
|
||||
async def test_setting_device_tracker_location_via_mqtt_message(
|
||||
hass, mqtt_mock, caplog
|
||||
):
|
||||
"""Test the setting of the location via MQTT."""
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"homeassistant/device_tracker/bla/config",
|
||||
'{ "name": "test", "state_topic": "test-topic" }',
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("device_tracker.test")
|
||||
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
async_fire_mqtt_message(hass, "test-topic", "test-location")
|
||||
state = hass.states.get("device_tracker.test")
|
||||
assert state.state == "test-location"
|
||||
|
||||
|
||||
async def test_setting_device_tracker_location_via_lat_lon_message(
|
||||
hass, mqtt_mock, caplog
|
||||
):
|
||||
"""Test the setting of the latitude and longitude via MQTT."""
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"homeassistant/device_tracker/bla/config",
|
||||
"{ "
|
||||
'"name": "test", '
|
||||
'"state_topic": "test-topic", '
|
||||
'"json_attributes_topic": "attributes-topic" '
|
||||
"}",
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("device_tracker.test")
|
||||
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
hass.config.latitude = 32.87336
|
||||
hass.config.longitude = -117.22743
|
||||
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"attributes-topic",
|
||||
'{"latitude":32.87336,"longitude": -117.22743, "gps_accuracy":1.5}',
|
||||
)
|
||||
state = hass.states.get("device_tracker.test")
|
||||
assert state.attributes["latitude"] == 32.87336
|
||||
assert state.attributes["longitude"] == -117.22743
|
||||
assert state.attributes["gps_accuracy"] == 1.5
|
||||
assert state.state == STATE_HOME
|
||||
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"attributes-topic",
|
||||
'{"latitude":50.1,"longitude": -2.1, "gps_accuracy":1.5}',
|
||||
)
|
||||
state = hass.states.get("device_tracker.test")
|
||||
assert state.attributes["latitude"] == 50.1
|
||||
assert state.attributes["longitude"] == -2.1
|
||||
assert state.attributes["gps_accuracy"] == 1.5
|
||||
assert state.state == STATE_NOT_HOME
|
||||
|
||||
async_fire_mqtt_message(hass, "attributes-topic", '{"longitude": -117.22743}')
|
||||
state = hass.states.get("device_tracker.test")
|
||||
assert state.attributes["longitude"] == -117.22743
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
async_fire_mqtt_message(hass, "attributes-topic", '{"latitude":32.87336}')
|
||||
state = hass.states.get("device_tracker.test")
|
||||
assert state.attributes["latitude"] == 32.87336
|
||||
assert state.state == STATE_NOT_HOME
|
Loading…
Add table
Reference in a new issue