Merge pull request #1314 from balloob/fix_own_tracks_mobile_beacon

Fix own tracks mobile beacon race condition
This commit is contained in:
Paulus Schoutsen 2016-02-20 00:27:07 -08:00
commit 22b47ce9c6
2 changed files with 60 additions and 20 deletions

View File

@ -62,7 +62,7 @@ def setup_scanner(hass, config, see):
see_beacons(dev_id, kwargs)
def owntracks_event_update(topic, payload, qos):
# pylint: disable=too-many-branches
# pylint: disable=too-many-branches, too-many-statements
""" MQTT event (geofences) received. """
# Docs on available data:
@ -92,7 +92,10 @@ def setup_scanner(hass, config, see):
if zone is None:
if data['t'] == 'b':
# Not a HA zone, and a beacon so assume mobile
MOBILE_BEACONS_ACTIVE[dev_id].append(location)
beacons = MOBILE_BEACONS_ACTIVE[dev_id]
if location not in beacons:
beacons.append(location)
_LOGGER.info("Added beacon %s", location)
else:
# Normal region
if not zone.attributes.get('passive'):
@ -108,6 +111,7 @@ def setup_scanner(hass, config, see):
see_beacons(dev_id, kwargs)
elif data['event'] == 'leave':
with LOCK:
regions = REGIONS_ENTERED[dev_id]
if location in regions:
regions.remove(location)
@ -119,7 +123,7 @@ def setup_scanner(hass, config, see):
if not zone.attributes.get('passive'):
kwargs['location_name'] = new_region
_set_gps_from_zone(kwargs, zone)
_LOGGER.info("Exit from to %s", new_region)
_LOGGER.info("Exit to %s", new_region)
else:
_LOGGER.info("Exit to GPS")
@ -130,6 +134,7 @@ def setup_scanner(hass, config, see):
beacons = MOBILE_BEACONS_ACTIVE[dev_id]
if location in beacons:
beacons.remove(location)
_LOGGER.info("Remove beacon %s", location)
else:
_LOGGER.error(
@ -141,6 +146,8 @@ def setup_scanner(hass, config, see):
""" Set active beacons to the current location """
kwargs = kwargs_param.copy()
# the battery state applies to the tracking device, not the beacon
kwargs.pop('battery', None)
for beacon in MOBILE_BEACONS_ACTIVE[dev_id]:
kwargs['dev_id'] = "{}_{}".format(BEACON_DEV_ID, beacon)
kwargs['host_name'] = beacon

View File

@ -379,3 +379,36 @@ class TestDeviceTrackerOwnTracks(unittest.TestCase):
message['lat'] = "4.0"
self.send_message(LOCATION_TOPIC, LOCATION_MESSAGE)
self.assert_tracker_latitude(3.0)
def test_mobile_multiple_async_enter_exit(self):
# Test race condition
enter_message = REGION_ENTER_MESSAGE.copy()
enter_message['desc'] = IBEACON_DEVICE
exit_message = REGION_LEAVE_MESSAGE.copy()
exit_message['desc'] = IBEACON_DEVICE
for i in range(0, 20):
fire_mqtt_message(
self.hass, EVENT_TOPIC, json.dumps(enter_message))
fire_mqtt_message(
self.hass, EVENT_TOPIC, json.dumps(exit_message))
fire_mqtt_message(
self.hass, EVENT_TOPIC, json.dumps(enter_message))
self.hass.pool.block_till_done()
self.send_message(EVENT_TOPIC, exit_message)
self.assertEqual(owntracks.MOBILE_BEACONS_ACTIVE['greg_phone'], [])
def test_mobile_multiple_enter_exit(self):
# Should only happen if the iphone dies
enter_message = REGION_ENTER_MESSAGE.copy()
enter_message['desc'] = IBEACON_DEVICE
exit_message = REGION_LEAVE_MESSAGE.copy()
exit_message['desc'] = IBEACON_DEVICE
self.send_message(EVENT_TOPIC, enter_message)
self.send_message(EVENT_TOPIC, enter_message)
self.send_message(EVENT_TOPIC, exit_message)
self.assertEqual(owntracks.MOBILE_BEACONS_ACTIVE['greg_phone'], [])