Add mysensors device tracker and platform discovery (#5781)
* Add mysensors device_tracker platform * Add discovery of device_tracker platforms * Enable discovery of device_tracker platforms that are not DeviceScanner. * Update signature of setup_scanner function in all affected platforms. * Add test. * Use discovery for mysensors device_tracker platform. * Remove gps accuracy * Small change to core like schema * fix depencypull/5795/head
parent
c7fd28c10f
commit
45a7c27280
|
@ -158,10 +158,11 @@ def async_setup(hass: HomeAssistantType, config: ConfigType):
|
|||
None, platform.get_scanner, hass, {DOMAIN: p_config})
|
||||
elif hasattr(platform, 'async_setup_scanner'):
|
||||
setup = yield from platform.async_setup_scanner(
|
||||
hass, p_config, tracker.async_see)
|
||||
hass, p_config, tracker.async_see, disc_info)
|
||||
elif hasattr(platform, 'setup_scanner'):
|
||||
setup = yield from hass.loop.run_in_executor(
|
||||
None, platform.setup_scanner, hass, p_config, tracker.see)
|
||||
None, platform.setup_scanner, hass, p_config, tracker.see,
|
||||
disc_info)
|
||||
else:
|
||||
raise HomeAssistantError("Invalid device_tracker platform.")
|
||||
|
||||
|
@ -193,6 +194,13 @@ def async_setup(hass: HomeAssistantType, config: ConfigType):
|
|||
discovery.async_listen(
|
||||
hass, DISCOVERY_PLATFORMS.keys(), async_device_tracker_discovered)
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_platform_discovered(platform, info):
|
||||
"""Callback to load a platform."""
|
||||
yield from async_setup_platform(platform, {}, disc_info=info)
|
||||
|
||||
discovery.async_listen_platform(hass, DOMAIN, async_platform_discovered)
|
||||
|
||||
# Clean up stale devices
|
||||
async_track_utc_time_change(
|
||||
hass, tracker.async_update_stale, second=range(0, 60, 5))
|
||||
|
|
|
@ -49,7 +49,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|||
})
|
||||
|
||||
|
||||
def setup_scanner(hass, config: dict, see):
|
||||
def setup_scanner(hass, config: dict, see, discovery_info=None):
|
||||
"""Validate the configuration and return an Automatic scanner."""
|
||||
try:
|
||||
AutomaticDeviceScanner(hass, config, see)
|
||||
|
|
|
@ -25,7 +25,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|||
})
|
||||
|
||||
|
||||
def setup_scanner(hass, config, see):
|
||||
def setup_scanner(hass, config, see, discovery_info=None):
|
||||
"""Setup the Bluetooth LE Scanner."""
|
||||
# pylint: disable=import-error
|
||||
from gattlib import DiscoveryService
|
||||
|
|
|
@ -21,7 +21,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|||
})
|
||||
|
||||
|
||||
def setup_scanner(hass, config, see):
|
||||
def setup_scanner(hass, config, see, discovery_info=None):
|
||||
"""Setup the Bluetooth Scanner."""
|
||||
# pylint: disable=import-error
|
||||
import bluetooth
|
||||
|
|
|
@ -4,7 +4,7 @@ import random
|
|||
from homeassistant.components.device_tracker import DOMAIN
|
||||
|
||||
|
||||
def setup_scanner(hass, config, see):
|
||||
def setup_scanner(hass, config, see, discovery_info=None):
|
||||
"""Setup the demo tracker."""
|
||||
def offset():
|
||||
"""Return random offset."""
|
||||
|
|
|
@ -19,7 +19,7 @@ _LOGGER = logging.getLogger(__name__)
|
|||
DEPENDENCIES = ['http']
|
||||
|
||||
|
||||
def setup_scanner(hass, config, see):
|
||||
def setup_scanner(hass, config, see, discovery_info=None):
|
||||
"""Setup an endpoint for the GPSLogger application."""
|
||||
hass.http.register_view(GPSLoggerView(see))
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|||
})
|
||||
|
||||
|
||||
def setup_scanner(hass, config: dict, see):
|
||||
def setup_scanner(hass, config: dict, see, discovery_info=None):
|
||||
"""Set up the iCloud Scanner."""
|
||||
username = config.get(CONF_USERNAME)
|
||||
password = config.get(CONF_PASSWORD)
|
||||
|
|
|
@ -20,7 +20,7 @@ _LOGGER = logging.getLogger(__name__)
|
|||
DEPENDENCIES = ['http']
|
||||
|
||||
|
||||
def setup_scanner(hass, config, see):
|
||||
def setup_scanner(hass, config, see, discovery_info=None):
|
||||
"""Setup an endpoint for the Locative application."""
|
||||
hass.http.register_view(LocativeView(see))
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(mqtt.SCHEMA_BASE).extend({
|
|||
})
|
||||
|
||||
|
||||
def setup_scanner(hass, config, see):
|
||||
def setup_scanner(hass, config, see, discovery_info=None):
|
||||
"""Setup the MQTT tracker."""
|
||||
devices = config[CONF_DEVICES]
|
||||
qos = config[CONF_QOS]
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
"""
|
||||
Support for tracking MySensors devices.
|
||||
|
||||
For more details about this platform, please refer to the documentation at
|
||||
https://home-assistant.io/components/device_tracker.mysensors/
|
||||
"""
|
||||
import logging
|
||||
|
||||
from homeassistant.components import mysensors
|
||||
from homeassistant.util import slugify
|
||||
|
||||
DEPENDENCIES = ['mysensors']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def setup_scanner(hass, config, see, discovery_info=None):
|
||||
"""Setup the MySensors tracker."""
|
||||
def mysensors_callback(gateway, node_id):
|
||||
"""Callback for mysensors platform."""
|
||||
node = gateway.sensors[node_id]
|
||||
if node.sketch_name is None:
|
||||
_LOGGER.info('No sketch_name: node %s', node_id)
|
||||
return
|
||||
|
||||
pres = gateway.const.Presentation
|
||||
set_req = gateway.const.SetReq
|
||||
|
||||
for child in node.children.values():
|
||||
position = child.values.get(set_req.V_POSITION)
|
||||
if child.type != pres.S_GPS or position is None:
|
||||
continue
|
||||
try:
|
||||
latitude, longitude, _ = position.split(',')
|
||||
except ValueError:
|
||||
_LOGGER.error('Payload for V_POSITION %s is not of format '
|
||||
'latitude,longitude,altitude', position)
|
||||
continue
|
||||
name = '{} {} {}'.format(
|
||||
node.sketch_name, node_id, child.id)
|
||||
attr = {
|
||||
mysensors.ATTR_CHILD_ID: child.id,
|
||||
mysensors.ATTR_DESCRIPTION: child.description,
|
||||
mysensors.ATTR_DEVICE: gateway.device,
|
||||
mysensors.ATTR_NODE_ID: node_id,
|
||||
}
|
||||
see(
|
||||
dev_id=slugify(name),
|
||||
host_name=name,
|
||||
gps=(latitude, longitude),
|
||||
battery=node.battery_level,
|
||||
attributes=attr
|
||||
)
|
||||
|
||||
gateways = hass.data.get(mysensors.MYSENSORS_GATEWAYS)
|
||||
|
||||
for gateway in gateways:
|
||||
gateway.platform_callbacks.append(mysensors_callback)
|
||||
|
||||
return True
|
|
@ -71,7 +71,7 @@ def get_cipher():
|
|||
return (KEYLEN, decrypt)
|
||||
|
||||
|
||||
def setup_scanner(hass, config, see):
|
||||
def setup_scanner(hass, config, see, discovery_info=None):
|
||||
"""Set up an OwnTracks tracker."""
|
||||
max_gps_accuracy = config.get(CONF_MAX_GPS_ACCURACY)
|
||||
waypoint_import = config.get(CONF_WAYPOINT_IMPORT)
|
||||
|
|
|
@ -73,7 +73,7 @@ class Host:
|
|||
_LOGGER.debug("ping KO on ip=%s failed=%d", self.ip_address, failed)
|
||||
|
||||
|
||||
def setup_scanner(hass, config, see):
|
||||
def setup_scanner(hass, config, see, discovery_info=None):
|
||||
"""Setup the Host objects and return the update function."""
|
||||
hosts = [Host(ip, dev_id, hass, config) for (dev_id, ip) in
|
||||
config[const.CONF_HOSTS].items()]
|
||||
|
|
|
@ -23,7 +23,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|||
})
|
||||
|
||||
|
||||
def setup_scanner(hass, config: dict, see):
|
||||
def setup_scanner(hass, config: dict, see, discovery_info=None):
|
||||
"""Validate the configuration and return a TrackR scanner."""
|
||||
TrackRDeviceScanner(hass, config, see)
|
||||
return True
|
||||
|
|
|
@ -30,7 +30,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|||
})
|
||||
|
||||
|
||||
def setup_scanner(hass, config, see):
|
||||
def setup_scanner(hass, config, see, discovery_info=None):
|
||||
"""Validate the configuration and return a scanner."""
|
||||
from volvooncall import Connection
|
||||
connection = Connection(
|
||||
|
|
|
@ -234,6 +234,9 @@ def setup(hass, config):
|
|||
'cover']:
|
||||
discovery.load_platform(hass, component, DOMAIN, {}, config)
|
||||
|
||||
discovery.load_platform(
|
||||
hass, 'device_tracker', DOMAIN, {}, config)
|
||||
|
||||
discovery.load_platform(
|
||||
hass, 'notify', DOMAIN, {CONF_NAME: DOMAIN}, config)
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import os
|
|||
from homeassistant.components import zone
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.bootstrap import setup_component
|
||||
from homeassistant.helpers import discovery
|
||||
from homeassistant.loader import get_component
|
||||
from homeassistant.util.async import run_coroutine_threadsafe
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
@ -324,6 +325,23 @@ class TestComponentsDeviceTracker(unittest.TestCase):
|
|||
fire_service_discovered(self.hass, 'test', {})
|
||||
self.assertTrue(mock_scan.called)
|
||||
|
||||
@patch(
|
||||
'homeassistant.components.device_tracker.DeviceTracker.see')
|
||||
@patch(
|
||||
'homeassistant.components.device_tracker.demo.setup_scanner',
|
||||
autospec=True)
|
||||
def test_discover_platform(self, mock_demo_setup_scanner, mock_see):
|
||||
"""Test discovery of device_tracker demo platform."""
|
||||
assert device_tracker.DOMAIN not in self.hass.config.components
|
||||
discovery.load_platform(
|
||||
self.hass, device_tracker.DOMAIN, 'demo', {'test_key': 'test_val'},
|
||||
{})
|
||||
self.hass.block_till_done()
|
||||
assert device_tracker.DOMAIN in self.hass.config.components
|
||||
assert mock_demo_setup_scanner.called
|
||||
assert mock_demo_setup_scanner.call_args[0] == (
|
||||
self.hass, {}, mock_see, {'test_key': 'test_val'})
|
||||
|
||||
def test_update_stale(self):
|
||||
"""Test stalled update."""
|
||||
scanner = get_component('device_tracker.test').SCANNER
|
||||
|
|
|
@ -33,7 +33,7 @@ class TestComponentsDeviceTrackerMQTT(unittest.TestCase):
|
|||
def test_ensure_device_tracker_platform_validation(self): \
|
||||
# pylint: disable=invalid-name
|
||||
"""Test if platform validation was done."""
|
||||
def mock_setup_scanner(hass, config, see):
|
||||
def mock_setup_scanner(hass, config, see, discovery_info=None):
|
||||
"""Check that Qos was added by validation."""
|
||||
self.assertTrue('qos' in config)
|
||||
|
||||
|
|
Loading…
Reference in New Issue