def test_reading_broken_yaml_config(self): """Test when known devices contains invalid data.""" with tempfile.NamedTemporaryFile() as fp: # file is empty assert device_tracker.load_config(fp.name, None, False, 0) == [] fp.write('100'.encode('utf-8')) fp.flush() # file contains a non-dict format assert device_tracker.load_config(fp.name, None, False, 0) == []
def test_reading_broken_yaml_config(self): # pylint: disable=no-self-use """Test when known devices contains invalid data.""" files = {'empty.yaml': '', 'bad.yaml': '100', 'ok.yaml': 'my_device:\n name: Device'} with patch_yaml_files(files): # File is empty assert device_tracker.load_config('empty.yaml', None, False) == [] # File contains a non-dict format assert device_tracker.load_config('bad.yaml', None, False) == [] # A file that works fine assert len(device_tracker.load_config('ok.yaml', None, False)) == 1
def test_not_allow_invalid_dev_id(self): # pylint: disable=invalid-name """Test that the device tracker will not allow invalid dev ids.""" self.assertTrue(setup_component(self.hass, device_tracker.DOMAIN, TEST_PLATFORM)) device_tracker.see(self.hass, dev_id="hello-world") config = device_tracker.load_config(self.yaml_devices, self.hass, timedelta(seconds=0)) assert len(config) == 0
def test_not_allow_invalid_dev_id(self): """Test that the device tracker will not allow invalid dev ids.""" self.assertTrue(device_tracker.setup(self.hass, {})) device_tracker.see(self.hass, dev_id='hello-world') config = device_tracker.load_config(self.yaml_devices, self.hass, timedelta(seconds=0), 0) assert len(config) == 0
def test_adding_unknown_device_to_config(self): scanner = get_component('device_tracker.test').SCANNER scanner.reset() scanner.come_home('DEV1') self.assertTrue(device_tracker.setup(self.hass, { device_tracker.DOMAIN: {CONF_PLATFORM: 'test'}})) config = device_tracker.load_config(self.yaml_devices, self.hass, timedelta(seconds=0))[0] self.assertEqual('dev1', config.dev_id) self.assertEqual(True, config.track)
def test_picture_and_icon_on_see_discovery(self): """Test that picture and icon are set in initial see.""" tracker = device_tracker.DeviceTracker( self.hass, timedelta(seconds=60), False, {}, []) tracker.see(dev_id=11, picture='pic_url', icon='mdi:icon') self.hass.block_till_done() config = device_tracker.load_config(self.yaml_devices, self.hass, timedelta(seconds=0)) assert len(config) == 1 assert config[0].icon == 'mdi:icon' assert config[0].entity_picture == 'pic_url'
def test_default_hide_if_away_is_used(self): """Test that default track_new is used.""" tracker = device_tracker.DeviceTracker( self.hass, timedelta(seconds=60), False, {device_tracker.CONF_AWAY_HIDE: True}, []) tracker.see(dev_id=12) self.hass.block_till_done() config = device_tracker.load_config(self.yaml_devices, self.hass, timedelta(seconds=0)) assert len(config) == 1 self.assertTrue(config[0].hidden)
def test_not_allow_invalid_dev_id(self): """Test that the device tracker will not allow invalid dev ids.""" with assert_setup_component(1, device_tracker.DOMAIN): assert setup_component(self.hass, device_tracker.DOMAIN, TEST_PLATFORM) device_tracker.see(self.hass, dev_id='hello-world') config = device_tracker.load_config(self.yaml_devices, self.hass, timedelta(seconds=0)) assert len(config) == 0
def test_adding_unknown_device_to_config(self): scanner = get_component('device_tracker.test').SCANNER scanner.reset() scanner.come_home('DEV1') self.assertTrue(device_tracker.setup(self.hass, { device_tracker.DOMAIN: {CONF_PLATFORM: 'test'}})) config = device_tracker.load_config(self.yaml_devices, self.hass, timedelta(seconds=0), 0) assert len(config) == 1 assert config[0].dev_id == 'dev1' assert config[0].track
def test_not_write_duplicate_yaml_keys(self): """Test that the device tracker will not generate invalid YAML.""" self.assertTrue(device_tracker.setup(self.hass, {})) device_tracker.see(self.hass, 'mac_1', host_name='hello') device_tracker.see(self.hass, 'mac_2', host_name='hello') self.hass.pool.block_till_done() config = device_tracker.load_config(self.yaml_devices, self.hass, timedelta(seconds=0), 0) assert len(config) == 2
def test_reading_broken_yaml_config(self): # pylint: disable=no-self-use """Test when known devices contains invalid data.""" files = { "empty.yaml": "", "nodict.yaml": "100", "badkey.yaml": "@:\n name: Device", "noname.yaml": "my_device:\n", "allok.yaml": "My Device:\n name: Device", "oneok.yaml": ("My Device!:\n name: Device\n" "bad_device:\n nme: Device"), } args = {"hass": self.hass, "consider_home": timedelta(seconds=60)} with patch_yaml_files(files): assert device_tracker.load_config("empty.yaml", **args) == [] assert device_tracker.load_config("nodict.yaml", **args) == [] assert device_tracker.load_config("noname.yaml", **args) == [] assert device_tracker.load_config("badkey.yaml", **args) == [] res = device_tracker.load_config("allok.yaml", **args) assert len(res) == 1 assert res[0].name == "Device" assert res[0].dev_id == "my_device" res = device_tracker.load_config("oneok.yaml", **args) assert len(res) == 1 assert res[0].name == "Device" assert res[0].dev_id == "my_device"
def test_reading_broken_yaml_config(self): """Test when known devices contains invalid data.""" files = {'empty.yaml': '', 'nodict.yaml': '100', 'badkey.yaml': '@:\n name: Device', 'noname.yaml': 'my_device:\n', 'allok.yaml': 'My Device:\n name: Device', 'oneok.yaml': ('My Device!:\n name: Device\n' 'bad_device:\n nme: Device')} args = {'hass': self.hass, 'consider_home': timedelta(seconds=60)} with patch_yaml_files(files): assert device_tracker.load_config('empty.yaml', **args) == [] assert device_tracker.load_config('nodict.yaml', **args) == [] assert device_tracker.load_config('noname.yaml', **args) == [] assert device_tracker.load_config('badkey.yaml', **args) == [] res = device_tracker.load_config('allok.yaml', **args) assert len(res) == 1 assert res[0].name == 'Device' assert res[0].dev_id == 'my_device' res = device_tracker.load_config('oneok.yaml', **args) assert len(res) == 1 assert res[0].name == 'Device' assert res[0].dev_id == 'my_device'
def test_not_write_duplicate_yaml_keys(self): # pylint: disable=invalid-name """Test that the device tracker will not generate invalid YAML.""" self.assertTrue(setup_component(self.hass, device_tracker.DOMAIN, TEST_PLATFORM)) device_tracker.see(self.hass, "mac_1", host_name="hello") device_tracker.see(self.hass, "mac_2", host_name="hello") self.hass.block_till_done() config = device_tracker.load_config(self.yaml_devices, self.hass, timedelta(seconds=0)) assert len(config) == 2
def test_not_write_duplicate_yaml_keys(self): """Test that the device tracker will not generate invalid YAML.""" with assert_setup_component(1, device_tracker.DOMAIN): assert setup_component(self.hass, device_tracker.DOMAIN, TEST_PLATFORM) device_tracker.see(self.hass, 'mac_1', host_name='hello') device_tracker.see(self.hass, 'mac_2', host_name='hello') self.hass.block_till_done() config = device_tracker.load_config(self.yaml_devices, self.hass, timedelta(seconds=0)) assert len(config) == 2
def test_adding_unknown_device_to_config(self): \ # pylint: disable=invalid-name """Test the adding of unknown devices to configuration file.""" scanner = get_component('device_tracker.test').SCANNER scanner.reset() scanner.come_home('DEV1') self.assertTrue(device_tracker.setup(self.hass, { device_tracker.DOMAIN: {CONF_PLATFORM: 'test'}})) config = device_tracker.load_config(self.yaml_devices, self.hass, timedelta(seconds=0)) assert len(config) == 1 assert config[0].dev_id == 'dev1' assert config[0].track
def test_reading_yaml_config(self): dev_id = 'test' device = device_tracker.Device( self.hass, timedelta(seconds=180), True, dev_id, 'AB:CD:EF:GH:IJ', 'Test name', 'http://test.picture', True) device_tracker.update_config(self.yaml_devices, dev_id, device) self.assertTrue(device_tracker.setup(self.hass, {})) config = device_tracker.load_config(self.yaml_devices, self.hass, device.consider_home)[0] self.assertEqual(device.dev_id, config.dev_id) self.assertEqual(device.track, config.track) self.assertEqual(device.mac, config.mac) self.assertEqual(device.config_picture, config.config_picture) self.assertEqual(device.away_hide, config.away_hide) self.assertEqual(device.consider_home, config.consider_home)
def test_reading_yaml_config(self): """Test the rendering of the YAML configuration.""" dev_id = 'test' device = device_tracker.Device( self.hass, timedelta(seconds=180), True, dev_id, 'AB:CD:EF:GH:IJ', 'Test name', picture='http://test.picture', away_hide=True) device_tracker.update_config(self.yaml_devices, dev_id, device) self.assertTrue(device_tracker.setup(self.hass, TEST_PLATFORM)) config = device_tracker.load_config(self.yaml_devices, self.hass, device.consider_home)[0] self.assertEqual(device.dev_id, config.dev_id) self.assertEqual(device.track, config.track) self.assertEqual(device.mac, config.mac) self.assertEqual(device.config_picture, config.config_picture) self.assertEqual(device.away_hide, config.away_hide) self.assertEqual(device.consider_home, config.consider_home)
def test_adding_unknown_device_to_config(self): """Test the adding of unknown devices to configuration file.""" scanner = get_component('device_tracker.test').SCANNER scanner.reset() scanner.come_home('DEV1') with assert_setup_component(1, device_tracker.DOMAIN): assert setup_component(self.hass, device_tracker.DOMAIN, { device_tracker.DOMAIN: {CONF_PLATFORM: 'test'}}) # wait for async calls (macvendor) to finish self.hass.block_till_done() config = device_tracker.load_config(self.yaml_devices, self.hass, timedelta(seconds=0)) assert len(config) == 1 assert config[0].dev_id == 'dev1' assert config[0].track
def test_reading_yaml_config(self): """Test the rendering of the YAML configuration.""" dev_id = 'test' device = device_tracker.Device( self.hass, timedelta(seconds=180), True, dev_id, 'AB:CD:EF:GH:IJ', 'Test name', picture='http://test.picture', hide_if_away=True, icon='mdi:kettle') device_tracker.update_config(self.yaml_devices, dev_id, device) with assert_setup_component(1, device_tracker.DOMAIN): assert setup_component(self.hass, device_tracker.DOMAIN, TEST_PLATFORM) config = device_tracker.load_config(self.yaml_devices, self.hass, device.consider_home)[0] assert device.dev_id == config.dev_id assert device.track == config.track assert device.mac == config.mac assert device.config_picture == config.config_picture assert device.away_hide == config.away_hide assert device.consider_home == config.consider_home assert device.icon == config.icon
def test_see_failures(self, mock_warning): """Test that the device tracker see failures.""" tracker = device_tracker.DeviceTracker(self.hass, timedelta(seconds=60), 0, []) # MAC is not a string (but added) tracker.see(mac=567, host_name="Number MAC") # No device id or MAC(not added) with self.assertRaises(HomeAssistantError): tracker.see() assert mock_warning.call_count == 0 # Ignore gps on invalid GPS (both added & warnings) tracker.see(mac="mac_1_bad_gps", gps=1) tracker.see(mac="mac_2_bad_gps", gps=[1]) tracker.see(mac="mac_3_bad_gps", gps="gps") config = device_tracker.load_config(self.yaml_devices, self.hass, timedelta(seconds=0)) assert mock_warning.call_count == 3 assert len(config) == 4
def test_see_state(self): """Test device tracker see records state correctly.""" assert setup_component(self.hass, device_tracker.DOMAIN, TEST_PLATFORM) params = { 'mac': 'AA:BB:CC:DD:EE:FF', 'dev_id': 'some_device', 'host_name': 'example.com', 'location_name': 'Work', 'gps': [.3, .8], 'gps_accuracy': 1, 'battery': 100, 'attributes': { 'test': 'test', 'number': 1, }, } device_tracker.see(self.hass, **params) self.hass.block_till_done() config = device_tracker.load_config(self.yaml_devices, self.hass, timedelta(seconds=0)) assert len(config) == 1 state = self.hass.states.get('device_tracker.examplecom') attrs = state.attributes assert state.state == 'Work' assert state.object_id == 'examplecom' assert state.name == 'example.com' assert attrs['friendly_name'] == 'example.com' assert attrs['battery'] == 100 assert attrs['latitude'] == 0.3 assert attrs['longitude'] == 0.8 assert attrs['test'] == 'test' assert attrs['gps_accuracy'] == 1 assert attrs['source_type'] == 'gps' assert attrs['number'] == 1
def test_reading_yaml_config(self): """Test the rendering of the YAML configuration.""" dev_id = "test" device = device_tracker.Device( self.hass, timedelta(seconds=180), True, dev_id, "AB:CD:EF:GH:IJ", "Test name", picture="http://test.picture", hide_if_away=True, ) device_tracker.update_config(self.yaml_devices, dev_id, device) self.assertTrue(setup_component(self.hass, device_tracker.DOMAIN, TEST_PLATFORM)) config = device_tracker.load_config(self.yaml_devices, self.hass, device.consider_home)[0] self.assertEqual(device.dev_id, config.dev_id) self.assertEqual(device.track, config.track) self.assertEqual(device.mac, config.mac) self.assertEqual(device.config_picture, config.config_picture) self.assertEqual(device.away_hide, config.away_hide) self.assertEqual(device.consider_home, config.consider_home)
def test_see_failures(self, mock_warning): """Test that the device tracker see failures.""" tracker = device_tracker.DeviceTracker( self.hass, timedelta(seconds=60), 0, {}, []) # MAC is not a string (but added) tracker.see(mac=567, host_name="Number MAC") # No device id or MAC(not added) with pytest.raises(HomeAssistantError): run_coroutine_threadsafe( tracker.async_see(), self.hass.loop).result() assert mock_warning.call_count == 0 # Ignore gps on invalid GPS (both added & warnings) tracker.see(mac='mac_1_bad_gps', gps=1) tracker.see(mac='mac_2_bad_gps', gps=[1]) tracker.see(mac='mac_3_bad_gps', gps='gps') self.hass.block_till_done() config = device_tracker.load_config(self.yaml_devices, self.hass, timedelta(seconds=0)) assert mock_warning.call_count == 3 assert len(config) == 4
def setup_scanner(hass, config, see, discovery_info=None): """Set up the Bluetooth Scanner.""" # pylint: disable=import-error import bluetooth from bt_proximity import BluetoothRSSI def see_device(mac, name, rssi=None): """Mark a device as seen.""" attributes = {} if rssi is not None: attributes['rssi'] = rssi see(mac="{}_{}".format(BT_PREFIX, mac), host_name=name, attributes=attributes, source_type=SOURCE_TYPE_BLUETOOTH) def discover_devices(): """Discover Bluetooth devices.""" result = bluetooth.discover_devices( duration=8, lookup_names=True, flush_cache=True, lookup_class=False) _LOGGER.debug("Bluetooth devices discovered = %d", len(result)) return result yaml_path = hass.config.path(YAML_DEVICES) devs_to_track = [] devs_donot_track = [] # Load all known devices. # We just need the devices so set consider_home and home range # to 0 for device in load_config(yaml_path, hass, 0): # Check if device is a valid bluetooth device if device.mac and device.mac[:3].upper() == BT_PREFIX: if device.track: devs_to_track.append(device.mac[3:]) else: devs_donot_track.append(device.mac[3:]) # If track new devices is true discover new devices on startup. track_new = config.get(CONF_TRACK_NEW, DEFAULT_TRACK_NEW) if track_new: for dev in discover_devices(): if dev[0] not in devs_to_track and \ dev[0] not in devs_donot_track: devs_to_track.append(dev[0]) see_device(dev[0], dev[1]) interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) request_rssi = config.get(CONF_REQUEST_RSSI, False) def update_bluetooth(now): """Lookup Bluetooth device and update status.""" try: if track_new: for dev in discover_devices(): if dev[0] not in devs_to_track and \ dev[0] not in devs_donot_track: devs_to_track.append(dev[0]) for mac in devs_to_track: _LOGGER.debug("Scanning %s", mac) result = bluetooth.lookup_name(mac, timeout=5) rssi = None if request_rssi: rssi = BluetoothRSSI(mac).request_rssi() if result is None: # Could not lookup device name continue see_device(mac, result, rssi) except bluetooth.BluetoothError: _LOGGER.exception("Error looking up Bluetooth device") track_point_in_utc_time( hass, update_bluetooth, dt_util.utcnow() + interval) update_bluetooth(dt_util.utcnow()) return True
def setup_scanner(hass, config, see, discovery_info=None): """Set up the Bluetooth Scanner.""" # pylint: disable=import-error import bluetooth import bluetooth._bluetooth as bluez hass.states.set(DOMAIN + '.' + ENTITY_ID, STATE_ON) def turn_on(call): """Turn Bluetooth tracker on.""" _LOGGER.info("Turning on Bluetooth") hass.states.set(DOMAIN + '.' + ENTITY_ID, STATE_ON) def turn_off(call): """Turn Bluetooth tracker off.""" _LOGGER.info("Turning off Bluetooth") try: sock = bluez.hci_open_dev(0) bluez.hci_send_cmd(sock, bluez.OGF_LINK_CTL, bluez.OCF_INQUIRY_CANCEL) sock.close() _LOGGER.info("Turned off Bluetooth") hass.states.set(DOMAIN + '.' + ENTITY_ID, STATE_OFF) except Exception as err: _LOGGER.error("Error turning off Bluetooth: %s", err) sock.close() def see_device(device): """Mark a device as seen.""" see(mac=BT_PREFIX + device[0], host_name=device[1]) def discover_devices(): if hass.states.get(DOMAIN + '.' + ENTITY_ID).state != STATE_ON: return [] _LOGGER.debug("Discovering Bluetooth devices") """Discover Bluetooth devices.""" result = bluetooth.discover_devices(duration=8, lookup_names=True, flush_cache=True, lookup_class=False) _LOGGER.debug("Bluetooth devices discovered = " + str(len(result))) return result hass.services.register(DOMAIN, BLUETOOTH_TRACKER_SERVICE_TURN_ON, turn_on, schema=BLUETOOTH_TRACKER_SERVICE_SCHEMA) hass.services.register(DOMAIN, BLUETOOTH_TRACKER_SERVICE_TURN_OFF, turn_off, schema=BLUETOOTH_TRACKER_SERVICE_SCHEMA) # Ensure the Bluetooth tracker is on (if that state has been set) if hass.states.get(DOMAIN + '.' + ENTITY_ID).state == STATE_ON: turn_on(None) yaml_path = hass.config.path(YAML_DEVICES) devs_to_track = [] devs_donot_track = [] # Load all known devices. # We just need the devices so set consider_home and home range # to 0 for device in load_config(yaml_path, hass, 0): # Check if device is a valid bluetooth device if device.mac and device.mac[:3].upper() == BT_PREFIX: if device.track: devs_to_track.append(device.mac[3:]) else: devs_donot_track.append(device.mac[3:]) # If track new devices is true discover new devices on startup. track_new = config.get(CONF_TRACK_NEW, DEFAULT_TRACK_NEW) if track_new: for dev in discover_devices(): if dev[0] not in devs_to_track and \ dev[0] not in devs_donot_track: devs_to_track.append(dev[0]) see_device(dev) interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) def update_bluetooth(now): """Lookup Bluetooth device and update status.""" try: if track_new: for dev in discover_devices(): if dev[0] not in devs_to_track and \ dev[0] not in devs_donot_track: devs_to_track.append(dev[0]) for mac in devs_to_track: if hass.states.get(DOMAIN + '.' + ENTITY_ID).state != STATE_ON: continue _LOGGER.debug("Scanning %s", mac) result = bluetooth.lookup_name(mac, timeout=5) if not result: # Could not lookup device name continue see_device((mac, result)) except bluetooth.BluetoothError: _LOGGER.exception("Error looking up Bluetooth device") track_point_in_utc_time(hass, update_bluetooth, dt_util.utcnow() + interval) update_bluetooth(dt_util.utcnow()) return True
def setup_scanner(hass, config, see, discovery_info=None): """Setup the Bluetooth LE Scanner.""" # pylint: disable=import-error from gattlib import DiscoveryService new_devices = {} def see_device(address, name, new_device=False): """Mark a device as seen.""" if new_device: if address in new_devices: _LOGGER.debug("Seen %s %s times", address, new_devices[address]) new_devices[address] += 1 if new_devices[address] >= MIN_SEEN_NEW: _LOGGER.debug("Adding %s to tracked devices", address) devs_to_track.append(address) else: return else: _LOGGER.debug("Seen %s for the first time", address) new_devices[address] = 1 return see(mac=BLE_PREFIX + address, host_name=name.strip("\x00")) def discover_ble_devices(): """Discover Bluetooth LE devices.""" _LOGGER.debug("Discovering Bluetooth LE devices") try: service = DiscoveryService(ble_dev_id) devices = service.discover(duration) _LOGGER.debug("Bluetooth LE devices discovered = %s", devices) except RuntimeError as error: _LOGGER.error("Error during Bluetooth LE scan: %s", error) devices = [] return devices yaml_path = hass.config.path(YAML_DEVICES) duration = config.get(CONF_SCAN_DURATION) ble_dev_id = config.get(CONF_BLUETOOTH_DEVICE) devs_to_track = [] devs_donot_track = [] # Load all known devices. # We just need the devices so set consider_home and home range # to 0 for device in load_config(yaml_path, hass, 0): # check if device is a valid bluetooth device if device.mac and device.mac[:4].upper() == BLE_PREFIX: if device.track: _LOGGER.debug("Adding %s to BLE tracker", device.mac) devs_to_track.append(device.mac[4:]) else: _LOGGER.debug("Adding %s to BLE do not track", device.mac) devs_donot_track.append(device.mac[4:]) # if track new devices is true discover new devices # on every scan. track_new = config.get(CONF_TRACK_NEW) if not devs_to_track and not track_new: _LOGGER.warning("No Bluetooth LE devices to track!") return False interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) def update_ble(now): """Lookup Bluetooth LE devices and update status.""" devs = discover_ble_devices() for mac in devs_to_track: _LOGGER.debug("Checking " + mac) result = mac in devs if not result: # Could not lookup device name continue see_device(mac, devs[mac]) if track_new: for address in devs: if address not in devs_to_track and \ address not in devs_donot_track: _LOGGER.info("Discovered Bluetooth LE device %s", address) see_device(address, devs[address], new_device=True) track_point_in_utc_time(hass, update_ble, now + interval) update_ble(dt_util.utcnow()) return True
def setup_scanner(hass, config, see, discovery_info=None): """Set up the Bluetooth LE Scanner.""" # pylint: disable=import-error import pygatt new_devices = {} hass.data.setdefault(DATA_BLE, {DATA_BLE_ADAPTER: None}) async def async_stop(event): """Try to shut down the bluetooth child process nicely.""" # These should never be unset at the point this runs, but just for # safety's sake, use `get`. adapter = hass.data.get(DATA_BLE, {}).get(DATA_BLE_ADAPTER) if adapter is not None: adapter.kill() hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, async_stop) def see_device(address, name, new_device=False): """Mark a device as seen.""" if new_device: if address in new_devices: _LOGGER.debug( "Seen %s %s times", address, new_devices[address]) new_devices[address] += 1 if new_devices[address] >= MIN_SEEN_NEW: _LOGGER.debug("Adding %s to tracked devices", address) devs_to_track.append(address) else: return else: _LOGGER.debug("Seen %s for the first time", address) new_devices[address] = 1 return if name is not None: name = name.strip("\x00") see(mac=BLE_PREFIX + address, host_name=name, source_type=SOURCE_TYPE_BLUETOOTH_LE) def discover_ble_devices(): """Discover Bluetooth LE devices.""" _LOGGER.debug("Discovering Bluetooth LE devices") try: adapter = pygatt.GATTToolBackend() hass.data[DATA_BLE][DATA_BLE_ADAPTER] = adapter devs = adapter.scan() devices = {x['address']: x['name'] for x in devs} _LOGGER.debug("Bluetooth LE devices discovered = %s", devices) except RuntimeError as error: _LOGGER.error("Error during Bluetooth LE scan: %s", error) return {} return devices yaml_path = hass.config.path(YAML_DEVICES) devs_to_track = [] devs_donot_track = [] # Load all known devices. # We just need the devices so set consider_home and home range # to 0 for device in load_config(yaml_path, hass, 0): # check if device is a valid bluetooth device if device.mac and device.mac[:4].upper() == BLE_PREFIX: if device.track: _LOGGER.debug("Adding %s to BLE tracker", device.mac) devs_to_track.append(device.mac[4:]) else: _LOGGER.debug("Adding %s to BLE do not track", device.mac) devs_donot_track.append(device.mac[4:]) # if track new devices is true discover new devices # on every scan. track_new = config.get(CONF_TRACK_NEW) if not devs_to_track and not track_new: _LOGGER.warning("No Bluetooth LE devices to track!") return False interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) def update_ble(now): """Lookup Bluetooth LE devices and update status.""" devs = discover_ble_devices() for mac in devs_to_track: if mac not in devs: continue if devs[mac] is None: devs[mac] = mac see_device(mac, devs[mac]) if track_new: for address in devs: if address not in devs_to_track and \ address not in devs_donot_track: _LOGGER.info("Discovered Bluetooth LE device %s", address) see_device(address, devs[address], new_device=True) track_point_in_utc_time(hass, update_ble, dt_util.utcnow() + interval) update_ble(dt_util.utcnow()) return True
def setup_scanner(hass, config, see, discovery_info=None): """Setup the Sleep Cycle Scanner.""" # pylint: disable=import-error def see_device(device): """Mark a device as seen.""" see(mac=SS_PREFIX + device[0], host_name=device[1]) def discover_devices(): """Discover bluetooth devices.""" result = SleepCycleHosts.find() _LOGGER.debug("Sleep Cycle discovered = " + str(len(result))) return list(result) yaml_path = hass.config.path(YAML_DEVICES) devs_to_track = [] devs_donot_track = [] # Load all known devices. # We just need the devices so set consider_home and home range # to 0 for device in load_config(yaml_path, hass, 0): # check if device is a valid bluetooth device if device.mac and device.mac[:3].upper() == SS_PREFIX: if device.track: devs_to_track.append(device.mac[3:]) else: devs_donot_track.append(device.mac[3:]) # if track new devices is true discover new devices on startup. track_new = config.get(CONF_TRACK_NEW, DEFAULT_TRACK_NEW) if track_new: for dev in discover_devices(): if dev[0] not in devs_to_track and \ dev[0] not in devs_donot_track: devs_to_track.append(dev[0]) see_device(dev) interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) def update_sleepcycle(now): """Look for Sleep Cycle hosts and update status.""" if track_new: for dev in discover_devices(): if dev[0] not in devs_to_track and \ dev[0] not in devs_donot_track: devs_to_track.append(dev[0]) for mac in devs_to_track: _LOGGER.debug("Scanning " + mac) result = bluetooth.lookup_name(mac, timeout=5) if not result: # Could not lookup device name continue see_device((mac, result)) track_point_in_utc_time(hass, update_bluetooth, dt_util.utcnow() + interval) update_sleepcycle(dt_util.utcnow()) return True
def setup_scanner(hass, config, see): """Setup the Bluetooth Scanner.""" # pylint: disable=import-error import bluetooth def see_device(device): """Mark a device as seen.""" see(mac=BT_PREFIX + device[0], host_name=device[1]) def discover_devices(): """Discover bluetooth devices.""" result = bluetooth.discover_devices(duration=8, lookup_names=True, flush_cache=True, lookup_class=False) _LOGGER.debug("Bluetooth devices discovered = " + str(len(result))) return result yaml_path = hass.config.path(YAML_DEVICES) devs_to_track = [] devs_donot_track = [] # Load all known devices. # We just need the devices so set consider_home and home range # to 0 for device in load_config(yaml_path, hass, 0): # check if device is a valid bluetooth device if device.mac and device.mac[:3].upper() == BT_PREFIX: if device.track: devs_to_track.append(device.mac[3:]) else: devs_donot_track.append(device.mac[3:]) # if track new devices is true discover new devices # on startup. track_new = util.convert(config.get(CONF_TRACK_NEW), bool, len(devs_to_track) == 0) if track_new: for dev in discover_devices(): if dev[0] not in devs_to_track and \ dev[0] not in devs_donot_track: devs_to_track.append(dev[0]) see_device(dev) if not devs_to_track: _LOGGER.warning("No bluetooth devices to track!") return False interval = util.convert(config.get(CONF_SCAN_INTERVAL), int, DEFAULT_SCAN_INTERVAL) def update_bluetooth(now): """Lookup bluetooth device and update status.""" try: for mac in devs_to_track: _LOGGER.debug("Scanning " + mac) result = bluetooth.lookup_name(mac, timeout=5) if not result: # Could not lookup device name continue see_device((mac, result)) except bluetooth.BluetoothError: _LOGGER.exception('Error looking up bluetooth device!') track_point_in_utc_time(hass, update_bluetooth, now + timedelta(seconds=interval)) update_bluetooth(dt_util.utcnow()) return True
def setup_scanner(hass, config, see, discovery_info=None): """Set up the Bluetooth Scanner.""" # pylint: disable=import-error import bluetooth import bluetooth._bluetooth as bluez hass.states.set(DOMAIN + '.' + ENTITY_ID, STATE_ON) def turn_on(call): """Turn Bluetooth tracker on.""" _LOGGER.info("Turning on Bluetooth") hass.states.set(DOMAIN + '.' + ENTITY_ID, STATE_ON) def turn_off(call): """Turn Bluetooth tracker off.""" _LOGGER.info("Turning off Bluetooth") try: sock = bluez.hci_open_dev(0) bluez.hci_send_cmd(sock, bluez.OGF_LINK_CTL, bluez.OCF_INQUIRY_CANCEL) sock.close() _LOGGER.info("Turned off Bluetooth") hass.states.set(DOMAIN + '.' + ENTITY_ID, STATE_OFF) except Exception as err: _LOGGER.error("Error turning off Bluetooth: %s", err) sock.close() def see_device(device): """Mark a device as seen.""" see(mac=BT_PREFIX + device[0], host_name=device[1]) def discover_devices(): if hass.states.get(DOMAIN + '.' + ENTITY_ID).state != STATE_ON: return [] _LOGGER.debug("Discovering Bluetooth devices") """Discover Bluetooth devices.""" result = bluetooth.discover_devices( duration=8, lookup_names=True, flush_cache=True, lookup_class=False) _LOGGER.debug("Bluetooth devices discovered = " + str(len(result))) return result hass.services.register( DOMAIN, BLUETOOTH_TRACKER_SERVICE_TURN_ON, turn_on, schema=BLUETOOTH_TRACKER_SERVICE_SCHEMA) hass.services.register( DOMAIN, BLUETOOTH_TRACKER_SERVICE_TURN_OFF, turn_off, schema=BLUETOOTH_TRACKER_SERVICE_SCHEMA) # Ensure the Bluetooth tracker is on (if that state has been set) if hass.states.get(DOMAIN + '.' + ENTITY_ID).state == STATE_ON: turn_on(None) yaml_path = hass.config.path(YAML_DEVICES) devs_to_track = [] devs_donot_track = [] # Load all known devices. # We just need the devices so set consider_home and home range # to 0 for device in load_config(yaml_path, hass, 0): # Check if device is a valid bluetooth device if device.mac and device.mac[:3].upper() == BT_PREFIX: if device.track: devs_to_track.append(device.mac[3:]) else: devs_donot_track.append(device.mac[3:]) # If track new devices is true discover new devices on startup. track_new = config.get(CONF_TRACK_NEW, DEFAULT_TRACK_NEW) if track_new: for dev in discover_devices(): if dev[0] not in devs_to_track and \ dev[0] not in devs_donot_track: devs_to_track.append(dev[0]) see_device(dev) interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) def update_bluetooth(now): """Lookup Bluetooth device and update status.""" try: if track_new: for dev in discover_devices(): if dev[0] not in devs_to_track and \ dev[0] not in devs_donot_track: devs_to_track.append(dev[0]) for mac in devs_to_track: if hass.states.get(DOMAIN + '.' + ENTITY_ID).state != STATE_ON: continue _LOGGER.debug("Scanning %s", mac) result = bluetooth.lookup_name(mac, timeout=5) if not result: # Could not lookup device name continue see_device((mac, result)) except bluetooth.BluetoothError: _LOGGER.exception("Error looking up Bluetooth device") track_point_in_utc_time( hass, update_bluetooth, dt_util.utcnow() + interval) update_bluetooth(dt_util.utcnow()) return True
def setup_scanner(hass, config, see, discovery_info=None): """Set up the Bluetooth LE Scanner.""" # pylint: disable=import-error import pygatt from pygatt.exceptions import BLEError new_devices = {} def see_device(address, name, new_device=False): """Mark a device as seen.""" if new_device: if address in new_devices: _LOGGER.debug( "Seen %s %s times", address, new_devices[address]) new_devices[address] += 1 if new_devices[address] >= MIN_SEEN_NEW: _LOGGER.debug("Adding %s to tracked devices", address) devs_to_track.append(address) else: return else: _LOGGER.debug("Seen %s for the first time", address) new_devices[address] = 1 return if name is not None: name = name.strip("\x00") see(mac=BLE_PREFIX + address, host_name=name, source_type=SOURCE_TYPE_BLUETOOTH_LE) def discover_ble_devices(): """Discover Bluetooth LE devices.""" _LOGGER.debug("Discovering Bluetooth LE devices") try: adapter = pygatt.GATTToolBackend() devs = adapter.scan() devices = {x['address']: x['name'] for x in devs} _LOGGER.debug("Bluetooth LE devices discovered = %s", devices) except BLEError as error: _LOGGER.error("Caught pygatt BLE Error: %s - will try again later", error) return {} except RuntimeError as error: _LOGGER.error("Error during Bluetooth LE scan: %s", error) return {} return devices yaml_path = hass.config.path(YAML_DEVICES) devs_to_track = [] devs_donot_track = [] # Load all known devices. # We just need the devices so set consider_home and home range # to 0 for device in load_config(yaml_path, hass, 0): # check if device is a valid bluetooth device if device.mac and device.mac[:4].upper() == BLE_PREFIX: if device.track: _LOGGER.debug("Adding %s to BLE tracker", device.mac) devs_to_track.append(device.mac[4:]) else: _LOGGER.debug("Adding %s to BLE do not track", device.mac) devs_donot_track.append(device.mac[4:]) # if track new devices is true discover new devices # on every scan. track_new = config.get(CONF_TRACK_NEW) if not devs_to_track and not track_new: _LOGGER.warning("No Bluetooth LE devices to track!") return False interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) def update_ble(now): """Lookup Bluetooth LE devices and update status.""" devs = discover_ble_devices() for mac in devs_to_track: if mac not in devs: continue if devs[mac] is None: devs[mac] = mac see_device(mac, devs[mac]) if track_new: for address in devs: if address not in devs_to_track and \ address not in devs_donot_track: _LOGGER.info("Discovered Bluetooth LE device %s", address) see_device(address, devs[address], new_device=True) track_point_in_utc_time(hass, update_ble, dt_util.utcnow() + interval) update_ble(dt_util.utcnow()) return True
def setup_scanner(hass, config, see, discovery_info=None): """Set up the Bluetooth Scanner.""" # pylint: disable=import-error import bluetooth from bt_proximity import BluetoothRSSI def see_device(mac, name, rssi=None): """Mark a device as seen.""" attributes = {} if rssi is not None: attributes['rssi'] = rssi see(mac="{}{}".format(BT_PREFIX, mac), host_name=name, attributes=attributes, source_type=SOURCE_TYPE_BLUETOOTH) device_id = config.get(CONF_DEVICE_ID) def discover_devices(): """Discover Bluetooth devices.""" result = bluetooth.discover_devices(duration=8, lookup_names=True, flush_cache=True, lookup_class=False, device_id=device_id) _LOGGER.debug("Bluetooth devices discovered = %d", len(result)) return result yaml_path = hass.config.path(YAML_DEVICES) devs_to_track = [] devs_donot_track = [] # Load all known devices. # We just need the devices so set consider_home and home range # to 0 for device in load_config(yaml_path, hass, 0): # Check if device is a valid bluetooth device if device.mac and device.mac[:3].upper() == BT_PREFIX: if device.track: devs_to_track.append(device.mac[3:]) else: devs_donot_track.append(device.mac[3:]) # If track new devices is true discover new devices on startup. track_new = config.get(CONF_TRACK_NEW, DEFAULT_TRACK_NEW) if track_new: for dev in discover_devices(): if dev[0] not in devs_to_track and \ dev[0] not in devs_donot_track: devs_to_track.append(dev[0]) see_device(dev[0], dev[1]) interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) request_rssi = config.get(CONF_REQUEST_RSSI, False) def update_bluetooth(_): """Update Bluetooth and set timer for the next update.""" update_bluetooth_once() track_point_in_utc_time(hass, update_bluetooth, dt_util.utcnow() + interval) def update_bluetooth_once(): """Lookup Bluetooth device and update status.""" try: if track_new: for dev in discover_devices(): if dev[0] not in devs_to_track and \ dev[0] not in devs_donot_track: devs_to_track.append(dev[0]) for mac in devs_to_track: _LOGGER.debug("Scanning %s", mac) result = bluetooth.lookup_name(mac, timeout=5) rssi = None if request_rssi: rssi = BluetoothRSSI(mac).request_rssi() if result is None: # Could not lookup device name continue see_device(mac, result, rssi) except bluetooth.BluetoothError: _LOGGER.exception("Error looking up Bluetooth device") def handle_update_bluetooth(call): """Update bluetooth devices on demand.""" update_bluetooth_once() update_bluetooth(dt_util.utcnow()) hass.services.register(DOMAIN, "bluetooth_tracker_update", handle_update_bluetooth) return True
def setup_scanner(hass, config, see): """Setup the Bluetooth LE Scanner.""" # pylint: disable=import-error from gattlib import DiscoveryService new_devices = {} def see_device(address, name, new_device=False): """Mark a device as seen.""" if new_device: if address in new_devices: _LOGGER.debug("Seen %s %s times", address, new_devices[address]) new_devices[address] += 1 if new_devices[address] >= MIN_SEEN_NEW: _LOGGER.debug("Adding %s to tracked devices", address) devs_to_track.append(address) else: return else: _LOGGER.debug("Seen %s for the first time", address) new_devices[address] = 1 return see(mac=BLE_PREFIX + address, host_name=name.strip("\x00")) def discover_ble_devices(): """Discover Bluetooth LE devices.""" _LOGGER.debug("Discovering Bluetooth LE devices") service = DiscoveryService() devices = service.discover(duration) _LOGGER.debug("Bluetooth LE devices discovered = %s", devices) return devices yaml_path = hass.config.path(YAML_DEVICES) duration = config.get(CONF_SCAN_DURATION) devs_to_track = [] devs_donot_track = [] # Load all known devices. # We just need the devices so set consider_home and home range # to 0 for device in load_config(yaml_path, hass, 0): # check if device is a valid bluetooth device if device.mac and device.mac[:4].upper() == BLE_PREFIX: if device.track: _LOGGER.debug("Adding %s to BLE tracker", device.mac) devs_to_track.append(device.mac[4:]) else: _LOGGER.debug("Adding %s to BLE do not track", device.mac) devs_donot_track.append(device.mac[4:]) # if track new devices is true discover new devices # on every scan. track_new = util.convert(config.get(CONF_TRACK_NEW), bool, len(devs_to_track) == 0) if not devs_to_track and not track_new: _LOGGER.warning("No Bluetooth LE devices to track!") return False interval = util.convert(config.get(CONF_SCAN_INTERVAL), int, DEFAULT_SCAN_INTERVAL) def update_ble(now): """Lookup Bluetooth LE devices and update status.""" devs = discover_ble_devices() for mac in devs_to_track: _LOGGER.debug("Checking " + mac) result = mac in devs if not result: # Could not lookup device name continue see_device(mac, devs[mac]) if track_new: for address in devs: if address not in devs_to_track and \ address not in devs_donot_track: _LOGGER.info("Discovered Bluetooth LE device %s", address) see_device(address, devs[address], new_device=True) track_point_in_utc_time(hass, update_ble, now + timedelta(seconds=interval)) update_ble(dt_util.utcnow()) return True
def setup_scanner(hass, config, see): """Setup the Bluetooth Scanner.""" # pylint: disable=import-error import bluetooth def see_device(device): """Mark a device as seen.""" see(mac=BT_PREFIX + device[0], host_name=device[1]) def discover_devices(): """Discover bluetooth devices.""" result = bluetooth.discover_devices(duration=8, lookup_names=True, flush_cache=True, lookup_class=False) _LOGGER.debug("Bluetooth devices discovered = " + str(len(result))) return result yaml_path = hass.config.path(YAML_DEVICES) devs_to_track = [] devs_donot_track = [] # Load all known devices. # We just need the devices so set consider_home and home range # to 0 for device in load_config(yaml_path, hass, 0, 0): # check if device is a valid bluetooth device if device.mac and device.mac[:3].upper() == BT_PREFIX: if device.track: devs_to_track.append(device.mac[3:]) else: devs_donot_track.append(device.mac[3:]) # if track new devices is true discover new devices # on startup. track_new = util.convert(config.get(CONF_TRACK_NEW), bool, len(devs_to_track) == 0) if track_new: for dev in discover_devices(): if dev[0] not in devs_to_track and \ dev[0] not in devs_donot_track: devs_to_track.append(dev[0]) see_device(dev) if not devs_to_track: _LOGGER.warning("No bluetooth devices to track!") return False interval = util.convert(config.get(CONF_SCAN_INTERVAL), int, DEFAULT_SCAN_INTERVAL) def update_bluetooth(now): """Lookup bluetooth device and update status.""" try: for mac in devs_to_track: _LOGGER.debug("Scanning " + mac) result = bluetooth.lookup_name(mac, timeout=5) if not result: # Could not lookup device name continue see_device((mac, result)) except bluetooth.BluetoothError: _LOGGER.exception('Error looking up bluetooth device!') track_point_in_utc_time(hass, update_bluetooth, now + timedelta(seconds=interval)) update_bluetooth(dt_util.utcnow()) return True
def setup_scanner(hass, config, see, discovery_info=None): """Set up the Bluetooth Scanner.""" # pylint: disable=import-error import bluetooth def see_device(device): """Mark a device as seen.""" see(mac=BT_PREFIX + device[0], host_name=device[1], source_type=SOURCE_TYPE_BLUETOOTH) def discover_devices(): """Discover Bluetooth devices.""" result = bluetooth.discover_devices(duration=8, lookup_names=True, flush_cache=True, lookup_class=False) _LOGGER.debug("Bluetooth devices discovered = " + str(len(result))) return result yaml_path = hass.config.path(YAML_DEVICES) devs_to_track = [] devs_donot_track = [] # Load all known devices. # We just need the devices so set consider_home and home range # to 0 for device in load_config(yaml_path, hass, 0): # Check if device is a valid bluetooth device if device.mac and device.mac[:3].upper() == BT_PREFIX: if device.track: devs_to_track.append(device.mac[3:]) else: devs_donot_track.append(device.mac[3:]) # If track new devices is true discover new devices on startup. track_new = config.get(CONF_TRACK_NEW, DEFAULT_TRACK_NEW) if track_new: for dev in discover_devices(): if dev[0] not in devs_to_track and \ dev[0] not in devs_donot_track: devs_to_track.append(dev[0]) see_device(dev) interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) def update_bluetooth(now): """Lookup Bluetooth device and update status.""" try: if track_new: for dev in discover_devices(): if dev[0] not in devs_to_track and \ dev[0] not in devs_donot_track: devs_to_track.append(dev[0]) for mac in devs_to_track: _LOGGER.debug("Scanning %s", mac) result = bluetooth.lookup_name(mac, timeout=5) if not result: # Could not lookup device name continue see_device((mac, result)) except bluetooth.BluetoothError: _LOGGER.exception("Error looking up Bluetooth device") track_point_in_utc_time(hass, update_bluetooth, dt_util.utcnow() + interval) update_bluetooth(dt_util.utcnow()) return True
def setup_scanner(hass, config, see, discovery_info=None): """Set up the Bluetooth LE Scanner.""" # pylint: disable=import-error import pygatt new_devices = {} def see_device(address, name, new_device=False): """Mark a device as seen.""" if new_device: if address in new_devices: _LOGGER.debug( "Seen %s %s times", address, new_devices[address]) new_devices[address] += 1 if new_devices[address] >= MIN_SEEN_NEW: _LOGGER.debug("Adding %s to tracked devices", address) devs_to_track.append(address) else: return else: _LOGGER.debug("Seen %s for the first time", address) new_devices[address] = 1 return if name is not None: name = name.strip("\x00") see(mac=BLE_PREFIX + address, host_name=name, source_type=SOURCE_TYPE_BLUETOOTH_LE) def discover_ble_devices(): """Discover Bluetooth LE devices.""" _LOGGER.debug("Discovering Bluetooth LE devices") try: adapter = pygatt.GATTToolBackend() devs = adapter.scan() devices = {x['address']: x['name'] for x in devs} _LOGGER.debug("Bluetooth LE devices discovered = %s", devices) except RuntimeError as error: _LOGGER.error("Error during Bluetooth LE scan: %s", error) return {} return devices yaml_path = hass.config.path(YAML_DEVICES) devs_to_track = [] devs_donot_track = [] # Load all known devices. # We just need the devices so set consider_home and home range # to 0 for device in load_config(yaml_path, hass, 0): # check if device is a valid bluetooth device if device.mac and device.mac[:4].upper() == BLE_PREFIX: if device.track: _LOGGER.debug("Adding %s to BLE tracker", device.mac) devs_to_track.append(device.mac[4:]) else: _LOGGER.debug("Adding %s to BLE do not track", device.mac) devs_donot_track.append(device.mac[4:]) # if track new devices is true discover new devices # on every scan. track_new = config.get(CONF_TRACK_NEW) if not devs_to_track and not track_new: _LOGGER.warning("No Bluetooth LE devices to track!") return False interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) def update_ble(now): """Lookup Bluetooth LE devices and update status.""" devs = discover_ble_devices() for mac in devs_to_track: if mac not in devs: continue if devs[mac] is None: devs[mac] = mac see_device(mac, devs[mac]) if track_new: for address in devs: if address not in devs_to_track and \ address not in devs_donot_track: _LOGGER.info("Discovered Bluetooth LE device %s", address) see_device(address, devs[address], new_device=True) track_point_in_utc_time(hass, update_ble, dt_util.utcnow() + interval) update_ble(dt_util.utcnow()) return True
def setup_scanner(hass, config, see, discovery_info): """Setup the Bluetooth LE Scanner.""" import pygatt class Monitor(threading.Thread): """Connection handling.""" def __init__(self, hass, see): """Construct interface object.""" threading.Thread.__init__(self) self.daemon = False self.hass = hass self.keep_going = True self.event = threading.Event() def mycallback(self, address): print("device %s" % address) see_device(address) def run(self): """Thread that keeps connection alive.""" import pygatt adapter = pygatt.backends.GATTToolBackend() adapter.passive_scan(1, callback=self.mycallback) def terminate(self): """Signal runner to stop and join thread.""" self.keep_going = False self.event.set() self.join() def see_device(address): """Mark a device as seen.""" if address in devs_donot_track: return if track_new and address not in devs_to_track and address not in devs_donot_track: if address in new_devices: _LOGGER.debug("Seen %s %s times", address, new_devices[address]) new_devices[address] += 1 if new_devices[address] >= MIN_SEEN_NEW: _LOGGER.debug("Adding %s to tracked devices", address) devs_to_track.append(address) else: return else: _LOGGER.debug("Seen %s for the first time", address) new_devices[address] = 1 return if address in devs_to_track: see(mac=BLE_PREFIX + address) def discover_ble_devices(): """Discover Bluetooth LE devices.""" _LOGGER.debug("Discovering Bluetooth LE devices") try: service = DiscoveryService(ble_dev_id) devices = service.discover(duration) _LOGGER.debug("Bluetooth LE devices discovered = %s", devices) except RuntimeError as error: _LOGGER.error("Error during Bluetooth LE scan: %s", error) devices = [] return devices def monitor_stop(_service_or_event): """Stop the monitor thread.""" _LOGGER.info("Stopping monitor for") mon.terminate() new_devices = {} yaml_path = hass.config.path(YAML_DEVICES) ble_dev_id = config.get(CONF_BLUETOOTH_DEVICE) devs_to_track = [] devs_donot_track = [] # Load all known devices. for device in load_config(yaml_path, hass, 0): # check if device is a valid bluetooth device if device.mac and device.mac[:4].upper() == BLE_PREFIX: if device.track: _LOGGER.debug("Adding %s to BLE tracker", device.mac) devs_to_track.append(device.mac[4:]) else: _LOGGER.debug("Adding %s to BLE do not track", device.mac) devs_donot_track.append(device.mac[4:]) # if track new devices is true discover new devices # on every scan. track_new = util.convert(config.get(CONF_TRACK_NEW), bool, DEFAULT_TRACK_NEW) if not devs_to_track and not track_new: _LOGGER.warning("No Bluetooth LE devices to track!") return False mon = Monitor(hass, see) mon.start() hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, monitor_stop) return True