Move details to docs and update docstrings/comments

This commit is contained in:
Fabian Affolter 2016-02-07 12:00:35 +01:00
parent 757946293e
commit e311f89056

View File

@ -1,55 +1,12 @@
"""
custom_components.proximity
~~~~~~~~~~~~~~~~~~~~~~~~~
homeassistant.components.proximity
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Component to monitor the proximity of devices to a particular zone and the
direction of travel. The result is an entity created in HA which maintains
the proximity data
direction of travel.
This component is useful to reduce the number of automation rules required
when wanting to perform automations based on locations outside a particular
zone. The standard HA zone and state based triggers allow similar control
but the number of rules grows exponentially when factors such as direction
of travel need to be taken into account. Some examples of its use include:
- Increase thermostat temperature as you near home
- Decrease temperature the further away from home you travel
The Proximity entity which is created has the following values:
state = distance from the monitored zone (in km)
dir_of_travel = direction of the closest device to the monitoed zone. Values
are:
'not set'
'arrived'
'towards'
'away_from'
'unknown'
'stationary'
dist_to_zone = distance from the monitored zone (in km)
Use configuration.yaml to enable the user to easily tune a number of settings:
- Zone: the zone to which this component is measuring the distance to. Default
is the home zone
- Ignored Zones: where proximity is not calculated for a device (either the
device being monitored or ones being compared (e.g. work or school)
- Devices: a list of devices to compare location against to check closeness to
the configured zone
- Tolerance: the tolerance used to calculate the direction of travel in metres
(to filter out small GPS co-ordinate changes
Logging levels debug, info and error are in use
Example configuration.yaml entry:
proximity:
zone: home
ignored_zones:
- twork
- elschool
devices:
- device_tracker.nwaring_nickmobile
- device_tracker.eleanorsiphone
- device_tracker.tsiphone
tolerance: 50
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/proximity/
"""
import logging
from homeassistant.helpers.event import track_state_change
from homeassistant.helpers.entity import Entity
@ -57,33 +14,31 @@ from homeassistant.util.location import distance
DEPENDENCIES = ['zone', 'device_tracker']
# domain for the component
DOMAIN = 'proximity'
# default tolerance
# Default tolerance
DEFAULT_TOLERANCE = 1
# default zone
# Default zone
DEFAULT_PROXIMITY_ZONE = 'home'
# entity attributes
# Entity attributes
ATTR_DIST_FROM = 'dist_to_zone'
ATTR_DIR_OF_TRAVEL = 'dir_of_travel'
ATTR_NEAREST = 'nearest'
ATTR_FRIENDLY_NAME = 'friendly_name'
# Shortcut for the logger
_LOGGER = logging.getLogger(__name__)
def setup(hass, config): # pylint: disable=too-many-locals,too-many-statements
""" get the zones and offsets from configuration.yaml"""
""" Get the zones and offsets from configuration.yaml. """
ignored_zones = []
if 'ignored_zones' in config[DOMAIN]:
for variable in config[DOMAIN]['ignored_zones']:
ignored_zones.append(variable)
# get the devices from configuration.yaml
# Get the devices from configuration.yaml
if 'devices' not in config[DOMAIN]:
_LOGGER.error('devices not found in config')
return False
@ -92,10 +47,10 @@ def setup(hass, config): # pylint: disable=too-many-locals,too-many-statements
for variable in config[DOMAIN]['devices']:
proximity_devices.append(variable)
# get the direction of travel tolerance from configuration.yaml
# Gget the direction of travel tolerance from configuration.yaml
tolerance = config[DOMAIN].get('tolerance', DEFAULT_TOLERANCE)
# get the zone to monitor proximity to from configuration.yaml
# Get the zone to monitor proximity to from configuration.yaml
proximity_zone = config[DOMAIN].get('zone', DEFAULT_PROXIMITY_ZONE)
entity_id = DOMAIN + '.' + proximity_zone
@ -116,7 +71,7 @@ def setup(hass, config): # pylint: disable=too-many-locals,too-many-statements
proximity.update_ha_state()
# main command to monitor proximity of devices
# Main command to monitor proximity of devices
track_state_change(hass, proximity_devices,
proximity.check_proximity_state_change)
@ -125,7 +80,7 @@ def setup(hass, config): # pylint: disable=too-many-locals,too-many-statements
class Proximity(Entity): # pylint: disable=too-many-instance-attributes
""" Represents a Proximity in Home Assistant. """
""" Represents a Proximity. """
def __init__(self, hass, zone_friendly_name, dist_to, dir_of_travel,
nearest, ignored_zones, proximity_devices, tolerance,
proximity_zone):
@ -142,6 +97,7 @@ class Proximity(Entity): # pylint: disable=too-many-instance-attributes
@property
def state(self):
""" Returns the state. """
return self.dist_to
@property
@ -151,6 +107,7 @@ class Proximity(Entity): # pylint: disable=too-many-instance-attributes
@property
def state_attributes(self):
""" Returns the state attributes. """
return {
ATTR_DIR_OF_TRAVEL: self.dir_of_travel,
ATTR_NEAREST: self.nearest,
@ -159,7 +116,7 @@ class Proximity(Entity): # pylint: disable=too-many-instance-attributes
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 """
""" Function to perform the proximity checking. """
entity_name = new_state.name
devices_to_calculate = False
devices_in_zone = ''
@ -168,21 +125,21 @@ class Proximity(Entity): # pylint: disable=too-many-instance-attributes
proximity_latitude = zone_state.attributes.get('latitude')
proximity_longitude = zone_state.attributes.get('longitude')
# check for devices in the monitored zone
# Check for devices in the monitored zone
for device in self.proximity_devices:
device_state = self.hass.states.get(device)
if device_state.state not in self.ignored_zones:
devices_to_calculate = True
# check the location of all devices
# Check the location of all devices
if (device_state.state).lower() == (self.friendly_name).lower():
device_friendly = device_state.name
if devices_in_zone != '':
devices_in_zone = devices_in_zone + ', '
devices_in_zone = devices_in_zone + device_friendly
# no-one to track so reset the entity
# No-one to track so reset the entity
if not devices_to_calculate:
self.dist_to = 'not set'
self.dir_of_travel = 'not set'
@ -190,7 +147,7 @@ class Proximity(Entity): # pylint: disable=too-many-instance-attributes
self.update_ha_state()
return
# at least one device is in the monitored zone so update the entity
# 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'
@ -198,32 +155,32 @@ class Proximity(Entity): # pylint: disable=too-many-instance-attributes
self.update_ha_state()
return
# we can't check proximity because latitude and longitude don't exist
# 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
# Collect distances to the zone for all devices
distances_to_zone = {}
for device in self.proximity_devices:
# ignore devices in an ignored zone
# Ignore devices in an ignored zone
device_state = self.hass.states.get(device)
if device_state.state in self.ignored_zones:
continue
# ignore devices if proximity cannot be calculated
# Ignore devices if proximity cannot be calculated
if 'latitude' not in device_state.attributes:
continue
# calculate the distance to the proximity zone
# Calculate the distance to the proximity zone
dist_to_zone = distance(proximity_latitude,
proximity_longitude,
device_state.attributes['latitude'],
device_state.attributes['longitude'])
# add the device and distance to a dictionary
# 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
# Loop through each of the distances collected and work out the closest
closest_device = ''
dist_to_zone = 1000000
@ -232,7 +189,7 @@ class Proximity(Entity): # pylint: disable=too-many-instance-attributes
closest_device = device
dist_to_zone = distances_to_zone[device]
# if the closest device is one of the other devices
# 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'
@ -241,7 +198,7 @@ class Proximity(Entity): # pylint: disable=too-many-instance-attributes
self.update_ha_state()
return
# stop if we cannot calculate the direction of travel (i.e. we don't
# 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])
@ -250,10 +207,10 @@ class Proximity(Entity): # pylint: disable=too-many-instance-attributes
self.update_ha_state()
return
# reset the variables
# Reset the variables
distance_travelled = 0
# calculate the distance travelled
# Calculate the distance travelled
old_distance = distance(proximity_latitude, proximity_longitude,
old_state.attributes['latitude'],
old_state.attributes['longitude'])
@ -262,7 +219,7 @@ class Proximity(Entity): # pylint: disable=too-many-instance-attributes
new_state.attributes['longitude'])
distance_travelled = round(new_distance - old_distance, 1)
# check for tolerance
# Check for tolerance
if distance_travelled < self.tolerance * -1:
direction_of_travel = 'towards'
elif distance_travelled > self.tolerance:
@ -270,7 +227,7 @@ class Proximity(Entity): # pylint: disable=too-many-instance-attributes
else:
direction_of_travel = 'stationary'
# update the proximity entity
# Update the proximity entity
self.dist_to = round(dist_to_zone)
self.dir_of_travel = direction_of_travel
self.nearest = entity_name