def zone(hass, zone_ent, entity): """Test if zone-condition matches. Async friendly. """ if isinstance(zone_ent, str): zone_ent = hass.states.get(zone_ent) if zone_ent is None: return False if isinstance(entity, str): entity = hass.states.get(entity) if entity is None: return False latitude = entity.attributes.get(ATTR_LATITUDE) longitude = entity.attributes.get(ATTR_LONGITUDE) if latitude is None or longitude is None: return False return zone_cmp.in_zone(zone_ent, latitude, longitude, entity.attributes.get(ATTR_GPS_ACCURACY, 0))
def zone(hass, zone_ent, entity): """Test if zone-condition matches. Can be run async. """ if isinstance(zone_ent, str): zone_ent = hass.states.get(zone_ent) if zone_ent is None: return False if isinstance(entity, str): entity = hass.states.get(entity) if entity is None: return False latitude = entity.attributes.get(ATTR_LATITUDE) longitude = entity.attributes.get(ATTR_LONGITUDE) if latitude is None or longitude is None: return False return zone_cmp.in_zone(zone_ent, latitude, longitude, entity.attributes.get(ATTR_GPS_ACCURACY, 0))
async def test_unavailable_zone(hass): """Test active zone with unavailable zones.""" assert await setup.async_setup_component(hass, DOMAIN, {"zone": {}}) hass.states.async_set("zone.bla", "unavailable", {"restored": True}) assert zone.async_active_zone(hass, 0.0, 0.01) is None assert zone.in_zone(hass.states.get("zone.bla"), 0, 0) is False
def test_device_tracker_test1_in_zone(self): assert proximity_zones.setup( self.hass, { 'proximity_zones': { 'home': { 'zone': 'home', 'ignored_zones': {'work'}, 'devices': {'test1'}, 'tolerance': 1 }, 'work': { 'zone': 'work', 'ignored_zones': {'home'}, 'devices': {'test1', 'test2'}, 'tolerance': 1 } } }) self.hass.states.set('device_tracker.test1', 'not_home', { 'friendly_name': 'test1', 'latitude': 50, 'longitude': 50 }) self.hass.pool.block_till_done() state = self.hass.states.get('device_tracker.test1') assert state.state == 'not_home' self.hass.states.set('device_tracker.test1', 'home', { 'friendly_name': 'test1', 'latitude': 2.1, 'longitude': 1.1 }) self.hass.pool.block_till_done() device_state = self.hass.states.get('device_tracker.test1') assert device_state.state == 'home' device_state_lat = device_state.attributes['latitude'] assert device_state_lat == 2.1 device_state_lon = device_state.attributes['longitude'] assert device_state_lon == 1.1 zone_state = self.hass.states.get('zone.home') assert zone_state.state == 'zoning' proximity_latitude = zone_state.attributes.get('latitude') assert proximity_latitude == 2.1 proximity_longitude = zone_state.attributes.get('longitude') assert proximity_longitude == 1.1 assert zone.in_zone(zone_state, device_state_lat, device_state_lon) state = self.hass.states.get('proximity_zones.home') assert state.state == '0' assert state.attributes.get('nearest') == 'test1' assert state.attributes.get('dir_of_travel') == 'arrived'
def _in_zone(hass, zone_entity_id, state): """ Check if state is in zone. """ if not state or None in (state.attributes.get(ATTR_LATITUDE), state.attributes.get(ATTR_LONGITUDE)): return False zone_state = hass.states.get(zone_entity_id) return zone_state and zone.in_zone( zone_state, state.attributes.get(ATTR_LATITUDE), state.attributes.get(ATTR_LONGITUDE), state.attributes.get(ATTR_GPS_ACCURACY, 0))
def test_in_zone_works_for_passive_zones(self): latitude = 32.880600 longitude = -117.237561 assert zone.setup(self.hass, { 'zone': [ { 'name': 'Passive Zone', 'latitude': latitude, 'longitude': longitude, 'radius': 250, 'passive': True }, ] }) assert zone.in_zone(self.hass.states.get('zone.passive_zone'), latitude, longitude)
def test_in_zone_works_for_passive_zones(self): """Test working in passive zones.""" latitude = 32.880600 longitude = -117.237561 assert bootstrap.setup_component(self.hass, zone.DOMAIN, { 'zone': [ { 'name': 'Passive Zone', 'latitude': latitude, 'longitude': longitude, 'radius': 250, 'passive': True }, ] }) assert zone.in_zone(self.hass.states.get('zone.passive_zone'), latitude, longitude)
def test_in_zone_works_for_passive_zones(self): """Test working in passive zones.""" latitude = 32.880600 longitude = -117.237561 assert setup.setup_component(self.hass, zone.DOMAIN, { 'zone': [ { 'name': 'Passive Zone', 'latitude': latitude, 'longitude': longitude, 'radius': 250, 'passive': True }, ] }) assert zone.in_zone(self.hass.states.get('zone.passive_zone'), latitude, longitude)
async def test_in_zone_works_for_passive_zones(hass): """Test working in passive zones.""" latitude = 32.880600 longitude = -117.237561 assert await setup.async_setup_component( hass, zone.DOMAIN, { "zone": [{ "name": "Passive Zone", "latitude": latitude, "longitude": longitude, "radius": 250, "passive": True, }] }, ) assert zone.in_zone(hass.states.get("zone.passive_zone"), latitude, longitude)
def check_proximity_initial_state(self): # pylint: disable=too-many-branches,too-many-statements,too-many-locals """ Function to perform the proximity checking in the initial state """ devices_to_calculate = self.ignored_zones == [] devices_have_coordinates = False devices_in_zone = '' zone_state = self.hass.states.get(self.proximity_zone) proximity_latitude = zone_state.attributes.get('latitude') proximity_longitude = zone_state.attributes.get('longitude') # check for devices in the monitored zone for device in self.proximity_devices: device_state = self.hass.states.get(device) if 'latitude' not in device_state.attributes: continue devices_have_coordinates = True device_state_lat = device_state.attributes['latitude'] device_state_lon = device_state.attributes['longitude'] for ignored_zone in self.ignored_zones: ignored_zone_state = self.hass.states.get('zone.' + ignored_zone) if not zone.in_zone(ignored_zone_state, device_state_lat, device_state_lon): devices_to_calculate = True # check the location of all devices if zone.in_zone(zone_state, device_state_lat, device_state_lon): device_friendly = device_state.name if devices_in_zone != '': devices_in_zone = devices_in_zone + ', ' devices_in_zone = devices_in_zone + device_friendly # at least one device is in the monitored zone so update the entity if devices_in_zone != '': self.dist_to = 0 self.dir_of_travel = 'arrived' self.nearest = devices_in_zone self.update_ha_state() return # no-one to track so reset the entity if not devices_to_calculate or not devices_have_coordinates: self.dist_to = 'not set' self.dir_of_travel = 'not set' self.nearest = 'not set' self.update_ha_state() return # collect distances to the zone for all devices distances_to_zone = {} for device in self.proximity_devices: # ignore devices in an ignored zone device_state = self.hass.states.get(device) # ignore devices if proximity cannot be calculated if 'latitude' not in device_state.attributes: continue device_state_lat = device_state.attributes['latitude'] device_state_lon = device_state.attributes['longitude'] device_in_ignored_zone = False for ignored_zone in self.ignored_zones: ignored_zone_state = self.hass.states.get('zone.' + ignored_zone) if zone.in_zone(ignored_zone_state, device_state_lat, device_state_lon): device_in_ignored_zone = True continue if device_in_ignored_zone: continue # calculate the distance to the proximity zone dist_to_zone = distance(proximity_latitude, proximity_longitude, device_state_lat, device_state_lon) # add the device and distance to a dictionary distances_to_zone[device] = round(dist_to_zone / 1000, 1) # loop through each of the distances collected and work out the closest closest_device = '' dist_to_zone = 1000000 for device in distances_to_zone: if distances_to_zone[device] < dist_to_zone: closest_device = device dist_to_zone = distances_to_zone[device] self.dist_to = round(distances_to_zone[closest_device]) self.dir_of_travel = 'unknown' device_state = self.hass.states.get(closest_device) self.nearest = device_state.name self.update_ha_state()
def check_proximity_state_change(self, entity, old_state, new_state): # pylint: disable=too-many-branches,too-many-statements,too-many-locals """ Function to perform the proximity checking """ entity_name = new_state.name devices_to_calculate = self.ignored_zones == [] devices_have_coordinates = False devices_in_zone = '' zone_state = self.hass.states.get(self.proximity_zone) proximity_latitude = zone_state.attributes.get('latitude') proximity_longitude = zone_state.attributes.get('longitude') # check for devices in the monitored zone for device in self.proximity_devices: device_state = self.hass.states.get(device) if 'latitude' not in device_state.attributes: continue devices_have_coordinates = True device_state_lat = device_state.attributes['latitude'] device_state_lon = device_state.attributes['longitude'] for ignored_zone in self.ignored_zones: ignored_zone_state = self.hass.states.get('zone.' + ignored_zone) if not zone.in_zone(ignored_zone_state, device_state_lat, device_state_lon): devices_to_calculate = True # check the location of all devices if zone.in_zone(zone_state, device_state_lat, device_state_lon): device_friendly = device_state.name if devices_in_zone != '': devices_in_zone = devices_in_zone + ', ' devices_in_zone = devices_in_zone + device_friendly # at least one device is in the monitored zone so update the entity if devices_in_zone != '': self.dist_to = 0 self.dir_of_travel = 'arrived' self.nearest = devices_in_zone self.update_ha_state() return # no-one to track so reset the entity if not devices_to_calculate or not devices_have_coordinates: self.dist_to = 'not set' self.dir_of_travel = 'not set' self.nearest = 'not set' self.update_ha_state() return # we can't check proximity because latitude and longitude don't exist if 'latitude' not in new_state.attributes: return # collect distances to the zone for all devices distances_to_zone = {} for device in self.proximity_devices: # ignore devices in an ignored zone device_state = self.hass.states.get(device) # ignore devices if proximity cannot be calculated if 'latitude' not in device_state.attributes: continue device_state_lat = device_state.attributes['latitude'] device_state_lon = device_state.attributes['longitude'] device_in_ignored_zone = False for ignored_zone in self.ignored_zones: ignored_zone_state = self.hass.states.get('zone.' + ignored_zone) if zone.in_zone(ignored_zone_state, device_state_lat, device_state_lon): device_in_ignored_zone = True continue if device_in_ignored_zone: continue # calculate the distance to the proximity zone dist_to_zone = distance(proximity_latitude, proximity_longitude, device_state_lat, device_state_lon) # add the device and distance to a dictionary distances_to_zone[device] = round(dist_to_zone / 1000, 1) # loop through each of the distances collected and work out the closest closest_device = '' dist_to_zone = 1000000 for device in distances_to_zone: if distances_to_zone[device] < dist_to_zone: closest_device = device dist_to_zone = distances_to_zone[device] # if the closest device is one of the other devices if closest_device != entity: self.dist_to = round(distances_to_zone[closest_device]) self.dir_of_travel = 'unknown' device_state = self.hass.states.get(closest_device) self.nearest = device_state.name self.update_ha_state() return # stop if we cannot calculate the direction of travel (i.e. we don't # have a previous state and a current LAT and LONG) if old_state is None or 'latitude' not in old_state.attributes: self.dist_to = round(distances_to_zone[entity]) self.dir_of_travel = 'unknown' self.nearest = entity_name self.update_ha_state() return # reset the variables distance_travelled = 0 # calculate the distance travelled old_distance = distance(proximity_latitude, proximity_longitude, old_state.attributes['latitude'], old_state.attributes['longitude']) new_distance = distance(proximity_latitude, proximity_longitude, new_state.attributes['latitude'], new_state.attributes['longitude']) distance_travelled = round(new_distance - old_distance, 1) # check for tolerance if distance_travelled < self.tolerance * -1: direction_of_travel = 'towards' elif distance_travelled > self.tolerance: direction_of_travel = 'away_from' else: direction_of_travel = 'stationary' # update the proximity entity self.dist_to = round(dist_to_zone) self.dir_of_travel = direction_of_travel self.nearest = entity_name self.update_ha_state() _LOGGER.debug( 'proximity.%s update entity: distance=%s: direction=%s: ' 'device=%s', self.friendly_name, round(dist_to_zone), direction_of_travel, entity_name) _LOGGER.info('%s: proximity calculation complete', entity_name)
def test_device_tracker_test1_in_zone(self): assert proximity_zones.setup(self.hass, { 'proximity_zones': { 'home': { 'zone': 'home', 'ignored_zones': { 'work' }, 'devices': { 'test1' }, 'tolerance': 1 }, 'work': { 'zone': 'work', 'ignored_zones': { 'home' }, 'devices': { 'test1', 'test2' }, 'tolerance': 1 } } }) self.hass.states.set( 'device_tracker.test1', 'not_home', { 'friendly_name': 'test1', 'latitude': 50, 'longitude': 50 }) self.hass.pool.block_till_done() state = self.hass.states.get('device_tracker.test1') assert state.state == 'not_home' self.hass.states.set( 'device_tracker.test1', 'home', { 'friendly_name': 'test1', 'latitude': 2.1, 'longitude': 1.1 }) self.hass.pool.block_till_done() device_state = self.hass.states.get('device_tracker.test1') assert device_state.state == 'home' device_state_lat = device_state.attributes['latitude'] assert device_state_lat == 2.1 device_state_lon = device_state.attributes['longitude'] assert device_state_lon == 1.1 zone_state = self.hass.states.get('zone.home') assert zone_state.state == 'zoning' proximity_latitude = zone_state.attributes.get('latitude') assert proximity_latitude == 2.1 proximity_longitude = zone_state.attributes.get('longitude') assert proximity_longitude == 1.1 assert zone.in_zone(zone_state, device_state_lat, device_state_lon) state = self.hass.states.get('proximity_zones.home') assert state.state == '0' assert state.attributes.get('nearest') == 'test1' assert state.attributes.get('dir_of_travel') == 'arrived'
def check_proximity_initial_state(self): # pylint: disable=too-many-branches,too-many-statements,too-many-locals """ Function to perform the proximity checking in the initial state """ devices_to_calculate = self.ignored_zones == [] devices_have_coordinates = False devices_in_zone = '' zone_state = self.hass.states.get(self.proximity_zone) proximity_latitude = zone_state.attributes.get('latitude') proximity_longitude = zone_state.attributes.get('longitude') # check for devices in the monitored zone for device in self.proximity_devices: device_state = self.hass.states.get(device) if 'latitude' not in device_state.attributes: continue devices_have_coordinates = True device_state_lat = device_state.attributes['latitude'] device_state_lon = device_state.attributes['longitude'] for ignored_zone in self.ignored_zones: ignored_zone_state = self.hass.states.get('zone.' + ignored_zone) if not zone.in_zone(ignored_zone_state, device_state_lat, device_state_lon): devices_to_calculate = True # check the location of all devices if zone.in_zone(zone_state, device_state_lat, device_state_lon): device_friendly = device_state.name if devices_in_zone != '': devices_in_zone = devices_in_zone + ', ' devices_in_zone = devices_in_zone + device_friendly # at least one device is in the monitored zone so update the entity if devices_in_zone != '': self.dist_to = 0 self.dir_of_travel = 'arrived' self.nearest = devices_in_zone self.update_ha_state() return # no-one to track so reset the entity if not devices_to_calculate or not devices_have_coordinates: self.dist_to = 'not set' self.dir_of_travel = 'not set' self.nearest = 'not set' self.update_ha_state() return # collect distances to the zone for all devices distances_to_zone = {} for device in self.proximity_devices: # ignore devices in an ignored zone device_state = self.hass.states.get(device) # ignore devices if proximity cannot be calculated if 'latitude' not in device_state.attributes: continue device_state_lat = device_state.attributes['latitude'] device_state_lon = device_state.attributes['longitude'] device_in_ignored_zone = False for ignored_zone in self.ignored_zones: ignored_zone_state = self.hass.states.get('zone.' + ignored_zone) if zone.in_zone(ignored_zone_state, device_state_lat, device_state_lon): device_in_ignored_zone = True continue if device_in_ignored_zone: continue # calculate the distance to the proximity zone dist_to_zone = distance(proximity_latitude, proximity_longitude, device_state_lat, device_state_lon) # add the device and distance to a dictionary distances_to_zone[device] = round(dist_to_zone / 1000, 1) # loop through each of the distances collected and work out the closest closest_device = '' dist_to_zone = 1000000 for device in distances_to_zone: if distances_to_zone[device] < dist_to_zone: closest_device = device dist_to_zone = distances_to_zone[device] self.dist_to = round(distances_to_zone[closest_device]) self.dir_of_travel = 'unknown' device_state = self.hass.states.get(closest_device) self.nearest = device_state.name self.update_ha_state()
def check_proximity_state_change(self, entity, old_state, new_state): # pylint: disable=too-many-branches,too-many-statements,too-many-locals """ Function to perform the proximity checking """ entity_name = new_state.name devices_to_calculate = self.ignored_zones == [] devices_have_coordinates = False devices_in_zone = '' zone_state = self.hass.states.get(self.proximity_zone) proximity_latitude = zone_state.attributes.get('latitude') proximity_longitude = zone_state.attributes.get('longitude') # check for devices in the monitored zone for device in self.proximity_devices: device_state = self.hass.states.get(device) if 'latitude' not in device_state.attributes: continue devices_have_coordinates = True device_state_lat = device_state.attributes['latitude'] device_state_lon = device_state.attributes['longitude'] for ignored_zone in self.ignored_zones: ignored_zone_state = self.hass.states.get('zone.' + ignored_zone) if not zone.in_zone(ignored_zone_state, device_state_lat, device_state_lon): devices_to_calculate = True # check the location of all devices if zone.in_zone(zone_state, device_state_lat, device_state_lon): device_friendly = device_state.name if devices_in_zone != '': devices_in_zone = devices_in_zone + ', ' devices_in_zone = devices_in_zone + device_friendly # at least one device is in the monitored zone so update the entity if devices_in_zone != '': self.dist_to = 0 self.dir_of_travel = 'arrived' self.nearest = devices_in_zone self.update_ha_state() return # no-one to track so reset the entity if not devices_to_calculate or not devices_have_coordinates: self.dist_to = 'not set' self.dir_of_travel = 'not set' self.nearest = 'not set' self.update_ha_state() return # we can't check proximity because latitude and longitude don't exist if 'latitude' not in new_state.attributes: return # collect distances to the zone for all devices distances_to_zone = {} for device in self.proximity_devices: # ignore devices in an ignored zone device_state = self.hass.states.get(device) # ignore devices if proximity cannot be calculated if 'latitude' not in device_state.attributes: continue device_state_lat = device_state.attributes['latitude'] device_state_lon = device_state.attributes['longitude'] device_in_ignored_zone = False for ignored_zone in self.ignored_zones: ignored_zone_state = self.hass.states.get('zone.' + ignored_zone) if zone.in_zone(ignored_zone_state, device_state_lat, device_state_lon): device_in_ignored_zone = True continue if device_in_ignored_zone: continue # calculate the distance to the proximity zone dist_to_zone = distance(proximity_latitude, proximity_longitude, device_state_lat, device_state_lon) # add the device and distance to a dictionary distances_to_zone[device] = round(dist_to_zone / 1000, 1) # loop through each of the distances collected and work out the closest closest_device = '' dist_to_zone = 1000000 for device in distances_to_zone: if distances_to_zone[device] < dist_to_zone: closest_device = device dist_to_zone = distances_to_zone[device] # if the closest device is one of the other devices if closest_device != entity: self.dist_to = round(distances_to_zone[closest_device]) self.dir_of_travel = 'unknown' device_state = self.hass.states.get(closest_device) self.nearest = device_state.name self.update_ha_state() return # stop if we cannot calculate the direction of travel (i.e. we don't # have a previous state and a current LAT and LONG) if old_state is None or 'latitude' not in old_state.attributes: self.dist_to = round(distances_to_zone[entity]) self.dir_of_travel = 'unknown' self.nearest = entity_name self.update_ha_state() return # reset the variables distance_travelled = 0 # calculate the distance travelled old_distance = distance(proximity_latitude, proximity_longitude, old_state.attributes['latitude'], old_state.attributes['longitude']) new_distance = distance(proximity_latitude, proximity_longitude, new_state.attributes['latitude'], new_state.attributes['longitude']) distance_travelled = round(new_distance - old_distance, 1) # check for tolerance if distance_travelled < self.tolerance * -1: direction_of_travel = 'towards' elif distance_travelled > self.tolerance: direction_of_travel = 'away_from' else: direction_of_travel = 'stationary' # update the proximity entity self.dist_to = round(dist_to_zone) self.dir_of_travel = direction_of_travel self.nearest = entity_name self.update_ha_state() _LOGGER.debug('proximity.%s update entity: distance=%s: direction=%s: ' 'device=%s', self.friendly_name, round(dist_to_zone), direction_of_travel, entity_name) _LOGGER.info('%s: proximity calculation complete', entity_name)