diff --git a/homeassistant/components/device_tracker/mqtt.py b/homeassistant/components/device_tracker/mqtt.py index a93263fada9..1f7fa9c1b84 100644 --- a/homeassistant/components/device_tracker/mqtt.py +++ b/homeassistant/components/device_tracker/mqtt.py @@ -4,11 +4,13 @@ Support for tracking MQTT enabled devices. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/device_tracker.mqtt/ """ +import asyncio import logging import voluptuous as vol import homeassistant.components.mqtt as mqtt +from homeassistant.core import callback from homeassistant.const import CONF_DEVICES from homeassistant.components.mqtt import CONF_QOS from homeassistant.components.device_tracker import PLATFORM_SCHEMA @@ -23,19 +25,23 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(mqtt.SCHEMA_BASE).extend({ }) -def setup_scanner(hass, config, see, discovery_info=None): +@asyncio.coroutine +def async_setup_scanner(hass, config, async_see, discovery_info=None): """Setup the MQTT tracker.""" devices = config[CONF_DEVICES] qos = config[CONF_QOS] dev_id_lookup = {} - def device_tracker_message_received(topic, payload, qos): + @callback + def async_tracker_message_received(topic, payload, qos): """MQTT message received.""" - see(dev_id=dev_id_lookup[topic], location_name=payload) + hass.async_add_job( + async_see(dev_id=dev_id_lookup[topic], location_name=payload)) for dev_id, topic in devices.items(): dev_id_lookup[topic] = dev_id - mqtt.subscribe(hass, topic, device_tracker_message_received, qos) + yield from mqtt.async_subscribe( + hass, topic, async_tracker_message_received, qos) return True diff --git a/homeassistant/components/device_tracker/owntracks.py b/homeassistant/components/device_tracker/owntracks.py index f4737fd26da..156e9d6a08a 100644 --- a/homeassistant/components/device_tracker/owntracks.py +++ b/homeassistant/components/device_tracker/owntracks.py @@ -55,7 +55,6 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ }) -@callback def get_cipher(): """Return decryption function and length of key. @@ -81,7 +80,6 @@ def async_setup_scanner(hass, config, async_see, discovery_info=None): mobile_beacons_active = defaultdict(list) regions_entered = defaultdict(list) - @callback def decrypt_payload(topic, ciphertext): """Decrypt encrypted payload.""" try: @@ -119,7 +117,6 @@ def async_setup_scanner(hass, config, async_see, discovery_info=None): return None # pylint: disable=too-many-return-statements - @callback def validate_payload(topic, payload, data_type): """Validate the OwnTracks payload.""" try: @@ -201,7 +198,6 @@ def async_setup_scanner(hass, config, async_see, discovery_info=None): dev_id, kwargs = _parse_see_args(topic, data) - @callback def enter_event(): """Execute enter event.""" zone = hass.states.get("zone.{}".format(slugify(location))) @@ -222,7 +218,6 @@ def async_setup_scanner(hass, config, async_see, discovery_info=None): hass.async_add_job(async_see(**kwargs)) async_see_beacons(dev_id, kwargs) - @callback def leave_event(): """Execute leave event.""" regions = regions_entered[dev_id] @@ -336,7 +331,6 @@ def async_setup_scanner(hass, config, async_see, discovery_info=None): return True -@callback def parse_topic(topic, pretty=False): """Parse an MQTT topic owntracks/user/dev, return (user, dev) tuple. @@ -353,7 +347,6 @@ def parse_topic(topic, pretty=False): return (host_name, dev_id) -@callback def _parse_see_args(topic, data): """Parse the OwnTracks location parameters, into the format see expects. @@ -372,7 +365,6 @@ def _parse_see_args(topic, data): return dev_id, kwargs -@callback def _set_gps_from_zone(kwargs, location, zone): """Set the see parameters from the zone parameters. diff --git a/homeassistant/components/sensor/arwn.py b/homeassistant/components/sensor/arwn.py index 834efa1b415..0bf68e68b0d 100644 --- a/homeassistant/components/sensor/arwn.py +++ b/homeassistant/components/sensor/arwn.py @@ -4,11 +4,13 @@ Support for collecting data from the ARWN project. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/sensor.arwn/ """ +import asyncio import json import logging import homeassistant.components.mqtt as mqtt -from homeassistant.const import (TEMP_FAHRENHEIT, TEMP_CELSIUS) +from homeassistant.core import callback +from homeassistant.const import TEMP_FAHRENHEIT, TEMP_CELSIUS from homeassistant.helpers.entity import Entity from homeassistant.util import slugify @@ -17,13 +19,15 @@ _LOGGER = logging.getLogger(__name__) DEPENDENCIES = ['mqtt'] DOMAIN = 'arwn' -SENSORS = {} - +DATA_ARWN = 'arwn' TOPIC = 'arwn/#' def discover_sensors(topic, payload): - """Given a topic, dynamically create the right sensor type.""" + """Given a topic, dynamically create the right sensor type. + + Async friendly. + """ parts = topic.split('/') unit = payload.get('units', '') domain = parts[1] @@ -47,9 +51,11 @@ def _slug(name): return 'sensor.arwn_{}'.format(slugify(name)) -def setup_platform(hass, config, add_devices, discovery_info=None): +@asyncio.coroutine +def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Set up the ARWN platform.""" - def sensor_event_received(topic, payload, qos): + @callback + def async_sensor_event_received(topic, payload, qos): """Process events as sensors. When a new event on our topic (arwn/#) is received we map it @@ -67,6 +73,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None): if not sensors: return + store = hass.data.get(DATA_ARWN) + if store is None: + store = hass.data[DATA_ARWN] = {} + if isinstance(sensors, ArwnSensor): sensors = (sensors, ) @@ -74,18 +84,18 @@ def setup_platform(hass, config, add_devices, discovery_info=None): del event['timestamp'] for sensor in sensors: - if sensor.name not in SENSORS: + if sensor.name not in store: sensor.hass = hass sensor.set_event(event) - SENSORS[sensor.name] = sensor + store[sensor.name] = sensor _LOGGER.debug("Registering new sensor %(name)s => %(event)s", dict(name=sensor.name, event=event)) - add_devices((sensor,)) + async_add_devices((sensor,), True) else: - SENSORS[sensor.name].set_event(event) - SENSORS[sensor.name].update_ha_state() + store[sensor.name].set_event(event) - mqtt.subscribe(hass, TOPIC, sensor_event_received, 0) + yield from mqtt.async_subscribe( + hass, TOPIC, async_sensor_event_received, 0) return True diff --git a/tests/components/device_tracker/test_mqtt.py b/tests/components/device_tracker/test_mqtt.py index 583b9b86383..08aab93a5a5 100644 --- a/tests/components/device_tracker/test_mqtt.py +++ b/tests/components/device_tracker/test_mqtt.py @@ -1,4 +1,5 @@ """The tests for the MQTT device tracker platform.""" +import asyncio import unittest from unittest.mock import patch import logging @@ -33,12 +34,13 @@ class TestComponentsDeviceTrackerMQTT(unittest.TestCase): def test_ensure_device_tracker_platform_validation(self): \ # pylint: disable=invalid-name """Test if platform validation was done.""" + @asyncio.coroutine def mock_setup_scanner(hass, config, see, discovery_info=None): """Check that Qos was added by validation.""" self.assertTrue('qos' in config) with patch('homeassistant.components.device_tracker.mqtt.' - 'setup_scanner', autospec=True, + 'async_setup_scanner', autospec=True, side_effect=mock_setup_scanner) as mock_sp: dev_id = 'paulus'