Battery attribute & accuracy filter (#24277)

* Extract const to a const file, Add battery as tracker attribute, add accuracy filter option

* Update homeassistant/components/traccar/device_tracker.py

Co-Authored-By: Otto Winter <otto@otto-winter.com>

* Update homeassistant/components/traccar/device_tracker.py

Co-Authored-By: Otto Winter <otto@otto-winter.com>

* Update homeassistant/components/traccar/device_tracker.py

Use [] syntax for keys that are in the validated data.

Co-Authored-By: Otto Winter <otto@otto-winter.com>

* Fix indentation
This commit is contained in:
GoNzCiD 2019-06-17 07:44:11 +02:00 committed by Joakim Sørensen
parent 08eca4a237
commit ddeb6b6baa
3 changed files with 68 additions and 36 deletions

View file

@ -631,6 +631,7 @@ omit =
homeassistant/components/tplink/switch.py homeassistant/components/tplink/switch.py
homeassistant/components/tplink_lte/* homeassistant/components/tplink_lte/*
homeassistant/components/traccar/device_tracker.py homeassistant/components/traccar/device_tracker.py
homeassistant/components/traccar/const.py
homeassistant/components/trackr/device_tracker.py homeassistant/components/trackr/device_tracker.py
homeassistant/components/tradfri/* homeassistant/components/tradfri/*
homeassistant/components/tradfri/light.py homeassistant/components/tradfri/light.py

View file

@ -0,0 +1,31 @@
"""Constants for Traccar integration."""
CONF_MAX_ACCURACY = 'max_accuracy'
CONF_SKIP_ACCURACY_ON = 'skip_accuracy_filter_on'
ATTR_ADDRESS = 'address'
ATTR_CATEGORY = 'category'
ATTR_GEOFENCE = 'geofence'
ATTR_MOTION = 'motion'
ATTR_SPEED = 'speed'
ATTR_TRACKER = 'tracker'
ATTR_TRACCAR_ID = 'traccar_id'
ATTR_STATUS = 'status'
EVENT_DEVICE_MOVING = 'device_moving'
EVENT_COMMAND_RESULT = 'command_result'
EVENT_DEVICE_FUEL_DROP = 'device_fuel_drop'
EVENT_GEOFENCE_ENTER = 'geofence_enter'
EVENT_DEVICE_OFFLINE = 'device_offline'
EVENT_DRIVER_CHANGED = 'driver_changed'
EVENT_GEOFENCE_EXIT = 'geofence_exit'
EVENT_DEVICE_OVERSPEED = 'device_overspeed'
EVENT_DEVICE_ONLINE = 'device_online'
EVENT_DEVICE_STOPPED = 'device_stopped'
EVENT_MAINTENANCE = 'maintenance'
EVENT_ALARM = 'alarm'
EVENT_TEXT_MESSAGE = 'text_message'
EVENT_DEVICE_UNKNOWN = 'device_unknown'
EVENT_IGNITION_OFF = 'ignition_off'
EVENT_IGNITION_ON = 'ignition_on'
EVENT_ALL_EVENTS = 'all_events'

View file

@ -7,44 +7,25 @@ import voluptuous as vol
from homeassistant.components.device_tracker import PLATFORM_SCHEMA from homeassistant.components.device_tracker import PLATFORM_SCHEMA
from homeassistant.const import ( from homeassistant.const import (
CONF_HOST, CONF_PORT, CONF_SSL, CONF_VERIFY_SSL, CONF_HOST, CONF_PORT, CONF_SSL, CONF_VERIFY_SSL,
CONF_PASSWORD, CONF_USERNAME, ATTR_BATTERY_LEVEL, CONF_PASSWORD, CONF_USERNAME, CONF_SCAN_INTERVAL,
CONF_SCAN_INTERVAL, CONF_MONITORED_CONDITIONS, CONF_MONITORED_CONDITIONS, CONF_EVENT)
CONF_EVENT)
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.event import async_track_time_interval from homeassistant.helpers.event import async_track_time_interval
from homeassistant.util import slugify from homeassistant.util import slugify
from .const import (
ATTR_ADDRESS, ATTR_CATEGORY, ATTR_GEOFENCE,
ATTR_MOTION, ATTR_SPEED, ATTR_TRACKER, ATTR_TRACCAR_ID, ATTR_STATUS,
EVENT_DEVICE_MOVING, EVENT_COMMAND_RESULT, EVENT_DEVICE_FUEL_DROP,
EVENT_GEOFENCE_ENTER, EVENT_DEVICE_OFFLINE, EVENT_DRIVER_CHANGED,
EVENT_GEOFENCE_EXIT, EVENT_DEVICE_OVERSPEED, EVENT_DEVICE_ONLINE,
EVENT_DEVICE_STOPPED, EVENT_MAINTENANCE, EVENT_ALARM, EVENT_TEXT_MESSAGE,
EVENT_DEVICE_UNKNOWN, EVENT_IGNITION_OFF, EVENT_IGNITION_ON,
EVENT_ALL_EVENTS, CONF_MAX_ACCURACY, CONF_SKIP_ACCURACY_ON)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
ATTR_ADDRESS = 'address'
ATTR_CATEGORY = 'category'
ATTR_GEOFENCE = 'geofence'
ATTR_MOTION = 'motion'
ATTR_SPEED = 'speed'
ATTR_TRACKER = 'tracker'
ATTR_TRACCAR_ID = 'traccar_id'
ATTR_STATUS = 'status'
EVENT_DEVICE_MOVING = 'device_moving'
EVENT_COMMAND_RESULT = 'command_result'
EVENT_DEVICE_FUEL_DROP = 'device_fuel_drop'
EVENT_GEOFENCE_ENTER = 'geofence_enter'
EVENT_DEVICE_OFFLINE = 'device_offline'
EVENT_DRIVER_CHANGED = 'driver_changed'
EVENT_GEOFENCE_EXIT = 'geofence_exit'
EVENT_DEVICE_OVERSPEED = 'device_overspeed'
EVENT_DEVICE_ONLINE = 'device_online'
EVENT_DEVICE_STOPPED = 'device_stopped'
EVENT_MAINTENANCE = 'maintenance'
EVENT_ALARM = 'alarm'
EVENT_TEXT_MESSAGE = 'text_message'
EVENT_DEVICE_UNKNOWN = 'device_unknown'
EVENT_IGNITION_OFF = 'ignition_off'
EVENT_IGNITION_ON = 'ignition_on'
EVENT_ALL_EVENTS = 'all_events'
DEFAULT_SCAN_INTERVAL = timedelta(seconds=30) DEFAULT_SCAN_INTERVAL = timedelta(seconds=30)
SCAN_INTERVAL = DEFAULT_SCAN_INTERVAL SCAN_INTERVAL = DEFAULT_SCAN_INTERVAL
@ -55,6 +36,10 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_PORT, default=8082): cv.port, vol.Optional(CONF_PORT, default=8082): cv.port,
vol.Optional(CONF_SSL, default=False): cv.boolean, vol.Optional(CONF_SSL, default=False): cv.boolean,
vol.Optional(CONF_VERIFY_SSL, default=True): cv.boolean, vol.Optional(CONF_VERIFY_SSL, default=True): cv.boolean,
vol.Required(CONF_MAX_ACCURACY, default=0): vol.All(vol.Coerce(int),
vol.Range(min=0)),
vol.Optional(CONF_SKIP_ACCURACY_ON,
default=[]): vol.All(cv.ensure_list, [cv.string]),
vol.Optional(CONF_MONITORED_CONDITIONS, vol.Optional(CONF_MONITORED_CONDITIONS,
default=[]): vol.All(cv.ensure_list, [cv.string]), default=[]): vol.All(cv.ensure_list, [cv.string]),
vol.Optional(CONF_EVENT, vol.Optional(CONF_EVENT,
@ -91,6 +76,7 @@ async def async_setup_scanner(hass, config, async_see, discovery_info=None):
scanner = TraccarScanner( scanner = TraccarScanner(
api, hass, async_see, api, hass, async_see,
config.get(CONF_SCAN_INTERVAL, SCAN_INTERVAL), config.get(CONF_SCAN_INTERVAL, SCAN_INTERVAL),
config[CONF_MAX_ACCURACY], config[CONF_SKIP_ACCURACY_ON],
config[CONF_MONITORED_CONDITIONS], config[CONF_EVENT]) config[CONF_MONITORED_CONDITIONS], config[CONF_EVENT])
return await scanner.async_init() return await scanner.async_init()
@ -99,9 +85,8 @@ async def async_setup_scanner(hass, config, async_see, discovery_info=None):
class TraccarScanner: class TraccarScanner:
"""Define an object to retrieve Traccar data.""" """Define an object to retrieve Traccar data."""
def __init__(self, api, hass, async_see, scan_interval, def __init__(self, api, hass, async_see, scan_interval, max_accuracy,
custom_attributes, skip_accuracy_on, custom_attributes, event_types):
event_types):
"""Initialize.""" """Initialize."""
from stringcase import camelcase from stringcase import camelcase
self._event_types = {camelcase(evt): evt for evt in event_types} self._event_types = {camelcase(evt): evt for evt in event_types}
@ -111,6 +96,8 @@ class TraccarScanner:
self._api = api self._api = api
self.connected = False self.connected = False
self._hass = hass self._hass = hass
self._max_accuracy = max_accuracy
self._skip_accuracy_on = skip_accuracy_on
async def async_init(self): async def async_init(self):
"""Further initialize connection to Traccar.""" """Further initialize connection to Traccar."""
@ -148,6 +135,8 @@ class TraccarScanner:
device_info = self._api.device_info[device_unique_id] device_info = self._api.device_info[device_unique_id]
device = None device = None
attr = {} attr = {}
skip_accuracy_filter = False
attr[ATTR_TRACKER] = 'traccar' attr[ATTR_TRACKER] = 'traccar'
if device_info.get('address') is not None: if device_info.get('address') is not None:
attr[ATTR_ADDRESS] = device_info['address'] attr[ATTR_ADDRESS] = device_info['address']
@ -157,8 +146,6 @@ class TraccarScanner:
attr[ATTR_CATEGORY] = device_info['category'] attr[ATTR_CATEGORY] = device_info['category']
if device_info.get('speed') is not None: if device_info.get('speed') is not None:
attr[ATTR_SPEED] = device_info['speed'] attr[ATTR_SPEED] = device_info['speed']
if device_info.get('battery') is not None:
attr[ATTR_BATTERY_LEVEL] = device_info['battery']
if device_info.get('motion') is not None: if device_info.get('motion') is not None:
attr[ATTR_MOTION] = device_info['motion'] attr[ATTR_MOTION] = device_info['motion']
if device_info.get('traccar_id') is not None: if device_info.get('traccar_id') is not None:
@ -172,11 +159,24 @@ class TraccarScanner:
for custom_attr in self._custom_attributes: for custom_attr in self._custom_attributes:
if device_info.get(custom_attr) is not None: if device_info.get(custom_attr) is not None:
attr[custom_attr] = device_info[custom_attr] attr[custom_attr] = device_info[custom_attr]
if custom_attr in self._skip_accuracy_on:
skip_accuracy_filter = True
accuracy = 0.0
if device_info.get('accuracy') is not None:
accuracy = device_info['accuracy']
if (not skip_accuracy_filter and self._max_accuracy > 0 and
accuracy > self._max_accuracy):
_LOGGER.debug('Excluded position by accuracy filter: %f (%s)',
accuracy, attr[ATTR_TRACCAR_ID])
continue
await self._async_see( await self._async_see(
dev_id=slugify(device_info['device_id']), dev_id=slugify(device_info['device_id']),
gps=(device_info.get('latitude'), gps=(device_info.get('latitude'),
device_info.get('longitude')), device_info.get('longitude')),
gps_accuracy=(device_info.get('accuracy')), gps_accuracy=accuracy,
battery=device_info.get('battery'),
attributes=attr) attributes=attr)
async def import_events(self): async def import_events(self):