1- """
2- A Device Tracker platform that combines one or more device trackers.
3- """
1+ """A Device Tracker platform that combines one or more device trackers."""
42from datetime import datetime , timedelta
53import logging
64import threading
1614from homeassistant .components .zone import ENTITY_ID_HOME
1715from homeassistant .components .zone import async_active_zone
1816from homeassistant .const import (
19- ATTR_BATTERY_CHARGING , ATTR_BATTERY_LEVEL ,
20- ATTR_ENTITY_ID , ATTR_GPS_ACCURACY , ATTR_LATITUDE , ATTR_LONGITUDE ,
21- ATTR_STATE , CONF_ENTITY_ID , CONF_NAME , EVENT_HOMEASSISTANT_START ,
22- STATE_HOME , STATE_NOT_HOME , STATE_ON , STATE_UNKNOWN )
17+ ATTR_BATTERY_CHARGING , ATTR_BATTERY_LEVEL , ATTR_ENTITY_ID ,
18+ ATTR_GPS_ACCURACY , ATTR_LATITUDE , ATTR_LONGITUDE , CONF_ENTITY_ID ,
19+ CONF_NAME , EVENT_HOMEASSISTANT_START , STATE_HOME , STATE_NOT_HOME , STATE_ON ,
20+ STATE_UNKNOWN )
2321import homeassistant .helpers .config_validation as cv
2422from homeassistant .helpers .event import track_state_change
2523from homeassistant .util .async_ import run_callback_threadsafe
6765
6866
6967def setup_scanner (hass , config , see , discovery_info = None ):
68+ """Set up a device scanner."""
7069 CompositeScanner (hass , config , see )
7170 return True
7271
@@ -78,7 +77,10 @@ def nearest_second(time):
7877
7978
8079class CompositeScanner :
80+ """Composite device scanner."""
81+
8182 def __init__ (self , hass , config , see ):
83+ """Initialize CompositeScanner."""
8284 self ._hass = hass
8385 self ._see = see
8486 entities = config [CONF_ENTITY_ID ]
@@ -140,16 +142,15 @@ def _use_non_gps_data(self, state):
140142 if state == STATE_HOME :
141143 return True
142144 entities = self ._entities .values ()
143- if any (entity [SOURCE_TYPE ] == SOURCE_TYPE_GPS
144- for entity in entities ):
145+ if any (entity [SOURCE_TYPE ] == SOURCE_TYPE_GPS for entity in entities ):
145146 return False
146147 return all (entity [DATA ] != STATE_HOME
147- for entity in entities
148- if entity [SOURCE_TYPE ] in SOURCE_TYPE_NON_GPS )
148+ for entity in entities
149+ if entity [SOURCE_TYPE ] in SOURCE_TYPE_NON_GPS )
149150
150- def _dt_attr_from_utc (self , utc , tz ):
151- if self ._time_as in [TZ_DEVICE_UTC , TZ_DEVICE_LOCAL ] and tz :
152- return utc .astimezone (tz )
151+ def _dt_attr_from_utc (self , utc , tzone ):
152+ if self ._time_as in [TZ_DEVICE_UTC , TZ_DEVICE_LOCAL ] and tzone :
153+ return utc .astimezone (tzone )
153154 if self ._time_as in [TZ_LOCAL , TZ_DEVICE_LOCAL ]:
154155 return dt_util .as_local (utc )
155156 return utc
@@ -218,9 +219,12 @@ def _update_info(self, entity_id, old_state, new_state):
218219 old_gps , old_acc = old_data
219220 self ._good_entity (entity_id , last_seen , source_type , new_data )
220221
221- if (self ._req_movement and old_data and
222- distance (gps [0 ], gps [1 ], old_gps [0 ], old_gps [1 ]) <=
223- gps_accuracy + old_acc ):
222+ if (
223+ self ._req_movement and old_data
224+ and distance (
225+ gps [0 ], gps [1 ], old_gps [0 ], old_gps [1 ]
226+ ) <= gps_accuracy + old_acc
227+ ):
224228 _LOGGER .debug (
225229 'For {} skipping update from {}: '
226230 'not enough movement'
@@ -280,7 +284,10 @@ def _update_info(self, entity_id, old_state, new_state):
280284 # Otherwise, if new state is 'home' and old state is not 'home'
281285 # and no GPS data, then use HA's configured Home location and
282286 # make source_type gps.
283- elif state == STATE_HOME and cur_state .state != STATE_HOME :
287+ elif (
288+ state == STATE_HOME
289+ and (cur_state is None or cur_state .state != STATE_HOME )
290+ ):
284291 gps = (
285292 self ._hass .config .latitude ,
286293 self ._hass .config .longitude )
@@ -303,19 +310,19 @@ def _update_info(self, entity_id, old_state, new_state):
303310 'For {} skipping update from {}: '
304311 'last_seen not newer than previous update ({} <= {})'
305312 .format (self ._entity_id , entity_id , last_seen ,
306- self ._prev_seen ))
313+ self ._prev_seen ))
307314 return
308315
309316 _LOGGER .debug ('Updating %s from %s' , self ._entity_id , entity_id )
310317
311- tz = None
318+ tzone = None
312319 if self ._time_as in [TZ_DEVICE_UTC , TZ_DEVICE_LOCAL ]:
313320 tzname = None
314321 if gps :
315322 # timezone_at will return a string or None.
316323 tzname = self ._tf .timezone_at (lng = gps [1 ], lat = gps [0 ])
317324 # get_time_zone will return a tzinfo or None.
318- tz = dt_util .get_time_zone (tzname )
325+ tzone = dt_util .get_time_zone (tzname )
319326 attrs = {ATTR_TIME_ZONE : tzname or STATE_UNKNOWN }
320327 else :
321328 attrs = {}
@@ -326,12 +333,12 @@ def _update_info(self, entity_id, old_state, new_state):
326333 if entity [ATTR_SOURCE_TYPE ] is not None ),
327334 ATTR_LAST_ENTITY_ID : entity_id ,
328335 ATTR_LAST_SEEN :
329- self ._dt_attr_from_utc (nearest_second (last_seen ), tz )
336+ self ._dt_attr_from_utc (nearest_second (last_seen ), tzone )
330337 })
331338 if charging is not None :
332339 attrs [ATTR_BATTERY_CHARGING ] = charging
333340 self ._see (dev_id = self ._dev_id , location_name = location_name ,
334- gps = gps , gps_accuracy = gps_accuracy , battery = battery ,
335- attributes = attrs , source_type = source_type )
341+ gps = gps , gps_accuracy = gps_accuracy , battery = battery ,
342+ attributes = attrs , source_type = source_type )
336343
337344 self ._prev_seen = last_seen
0 commit comments