Exemplo n.º 1
0
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))
Exemplo n.º 2
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))
Exemplo n.º 3
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
Exemplo n.º 4
0
    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'
Exemplo n.º 5
0
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))
Exemplo n.º 6
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)
Exemplo n.º 7
0
    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)
Exemplo n.º 8
0
    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)
Exemplo n.º 9
0
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)
Exemplo n.º 10
0
    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()
Exemplo n.º 11
0
    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'
Exemplo n.º 13
0
    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()
Exemplo n.º 14
0
    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)