Updated volvooncall library + support sensors, heater and lock (#6052)
This commit is contained in:
parent
beb8b4b11f
commit
9e73115337
8 changed files with 375 additions and 80 deletions
|
@ -88,6 +88,9 @@ omit =
|
|||
homeassistant/components/verisure.py
|
||||
homeassistant/components/*/verisure.py
|
||||
|
||||
homeassistant/components/volvooncall.py
|
||||
homeassistant/components/*/volvooncall.py
|
||||
|
||||
homeassistant/components/*/webostv.py
|
||||
|
||||
homeassistant/components/wemo.py
|
||||
|
@ -183,7 +186,6 @@ omit =
|
|||
homeassistant/components/device_tracker/tplink.py
|
||||
homeassistant/components/device_tracker/trackr.py
|
||||
homeassistant/components/device_tracker/ubus.py
|
||||
homeassistant/components/device_tracker/volvooncall.py
|
||||
homeassistant/components/device_tracker/xiaomi.py
|
||||
homeassistant/components/discovery.py
|
||||
homeassistant/components/downloader.py
|
||||
|
|
59
homeassistant/components/binary_sensor/volvooncall.py
Normal file
59
homeassistant/components/binary_sensor/volvooncall.py
Normal file
|
@ -0,0 +1,59 @@
|
|||
"""
|
||||
Support for VOC.
|
||||
|
||||
For more details about this platform, please refer to the documentation at
|
||||
https://home-assistant.io/components/binary_sensor.volvooncall/
|
||||
|
||||
"""
|
||||
import logging
|
||||
|
||||
from homeassistant.components.volvooncall import VolvoEntity
|
||||
from homeassistant.components.binary_sensor import BinarySensorDevice
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
SENSORS = [('washer_fluid_level', 'Washer fluid'),
|
||||
('brake_fluid', 'Brake Fluid'),
|
||||
('service_warning_status', 'Service'),
|
||||
('bulb_failures', 'Bulbs'),
|
||||
('doors', 'Doors'),
|
||||
('windows', 'Windows')]
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Setup Volvo sensors."""
|
||||
if discovery_info is None:
|
||||
return
|
||||
add_devices(VolvoSensor(hass, discovery_info, sensor)
|
||||
for sensor in SENSORS)
|
||||
|
||||
|
||||
class VolvoSensor(VolvoEntity, BinarySensorDevice):
|
||||
"""Representation of a Volvo sensor."""
|
||||
|
||||
def __init__(self, hass, vehicle, sensor):
|
||||
"""Initialize the sensor."""
|
||||
super().__init__(hass, vehicle)
|
||||
self._sensor = sensor
|
||||
|
||||
@property
|
||||
def _name(self):
|
||||
"""Name of sensor."""
|
||||
return self._sensor[1]
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return True if the binary sensor is on."""
|
||||
attr = self._sensor[0]
|
||||
val = getattr(self.vehicle, attr)
|
||||
if attr == 'bulb_failures':
|
||||
return len(val) > 0
|
||||
elif attr in ['doors', 'windows']:
|
||||
return any([val[key] for key in val if 'Open' in key])
|
||||
else:
|
||||
return val != 'Normal'
|
||||
|
||||
@property
|
||||
def device_class(self):
|
||||
"""Return the class of this sensor, from SENSOR_CLASSES."""
|
||||
return 'safety'
|
|
@ -1,97 +1,35 @@
|
|||
"""
|
||||
Support for Volvo On Call.
|
||||
Support for tracking a Volvo.
|
||||
|
||||
http://www.volvocars.com/intl/own/owner-info/volvo-on-call
|
||||
For more details about this platform, please refer to the documentation at
|
||||
https://home-assistant.io/components/device_tracker.volvooncall/
|
||||
"""
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
import voluptuous as vol
|
||||
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.event import track_point_in_utc_time
|
||||
from homeassistant.util.dt import utcnow
|
||||
from homeassistant.util import slugify
|
||||
from homeassistant.const import (
|
||||
CONF_PASSWORD, CONF_SCAN_INTERVAL, CONF_USERNAME)
|
||||
from homeassistant.components.device_tracker import (
|
||||
DEFAULT_SCAN_INTERVAL, PLATFORM_SCHEMA)
|
||||
|
||||
MIN_TIME_BETWEEN_SCANS = timedelta(minutes=1)
|
||||
from homeassistant.components.volvooncall import DOMAIN
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
REQUIREMENTS = ['volvooncall==0.1.1']
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
vol.Required(CONF_USERNAME): cv.string,
|
||||
vol.Required(CONF_PASSWORD): cv.string,
|
||||
})
|
||||
|
||||
|
||||
def setup_scanner(hass, config, see, discovery_info=None):
|
||||
"""Validate the configuration and return a scanner."""
|
||||
from volvooncall import Connection
|
||||
connection = Connection(
|
||||
config.get(CONF_USERNAME),
|
||||
config.get(CONF_PASSWORD))
|
||||
"""Setup Volvo tracker."""
|
||||
if discovery_info is None:
|
||||
return
|
||||
|
||||
interval = max(MIN_TIME_BETWEEN_SCANS,
|
||||
config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL))
|
||||
vin = discovery_info
|
||||
vehicle = hass.data[DOMAIN].vehicles[vin]
|
||||
|
||||
def _see_vehicle(vehicle):
|
||||
position = vehicle["position"]
|
||||
dev_id = "volvo_" + slugify(vehicle["registrationNumber"])
|
||||
host_name = "%s (%s/%s)" % (
|
||||
vehicle["registrationNumber"],
|
||||
vehicle["vehicleType"],
|
||||
vehicle["modelYear"])
|
||||
|
||||
def any_opened(door):
|
||||
"""True if any door/window is opened."""
|
||||
return any([door[key] for key in door if "Open" in key])
|
||||
|
||||
attributes = dict(
|
||||
unlocked=not vehicle["carLocked"],
|
||||
tank_volume=vehicle["fuelTankVolume"],
|
||||
average_fuel_consumption=round(
|
||||
vehicle["averageFuelConsumption"] / 10, 1), # l/100km
|
||||
washer_fluid_low=vehicle["washerFluidLevel"] != "Normal",
|
||||
brake_fluid_low=vehicle["brakeFluid"] != "Normal",
|
||||
service_warning=vehicle["serviceWarningStatus"] != "Normal",
|
||||
bulb_failures=len(vehicle["bulbFailures"]) > 0,
|
||||
doors_open=any_opened(vehicle["doors"]),
|
||||
windows_open=any_opened(vehicle["windows"]),
|
||||
fuel=vehicle["fuelAmount"],
|
||||
odometer=round(vehicle["odometer"] / 1000), # km
|
||||
range=vehicle["distanceToEmpty"])
|
||||
|
||||
if "heater" in vehicle and \
|
||||
"status" in vehicle["heater"]:
|
||||
attributes.update(heater_on=vehicle["heater"]["status"] != "off")
|
||||
host_name = vehicle.registration_number
|
||||
dev_id = 'volvo_' + slugify(host_name)
|
||||
|
||||
def see_vehicle(vehicle):
|
||||
"""Callback for reporting vehicle position."""
|
||||
see(dev_id=dev_id,
|
||||
host_name=host_name,
|
||||
gps=(position["latitude"],
|
||||
position["longitude"]),
|
||||
attributes=attributes)
|
||||
gps=(vehicle.position['latitude'],
|
||||
vehicle.position['longitude']))
|
||||
|
||||
def update(now):
|
||||
"""Update status from the online service."""
|
||||
_LOGGER.info("Updating")
|
||||
try:
|
||||
res, vehicles = connection.update()
|
||||
if not res:
|
||||
_LOGGER.error("Could not query server")
|
||||
return False
|
||||
hass.data[DOMAIN].entities[vin].append(see_vehicle)
|
||||
|
||||
for vehicle in vehicles:
|
||||
_see_vehicle(vehicle)
|
||||
|
||||
return True
|
||||
finally:
|
||||
track_point_in_utc_time(hass, update, now + interval)
|
||||
|
||||
_LOGGER.info('Logging in to service')
|
||||
return update(utcnow())
|
||||
return True
|
||||
|
|
42
homeassistant/components/lock/volvooncall.py
Normal file
42
homeassistant/components/lock/volvooncall.py
Normal file
|
@ -0,0 +1,42 @@
|
|||
"""
|
||||
Support for Volvo locks.
|
||||
|
||||
For more details about this platform, please refer to the documentation at
|
||||
https://home-assistant.io/components/lock.volvooncall/
|
||||
"""
|
||||
import logging
|
||||
|
||||
from homeassistant.components.lock import LockDevice
|
||||
from homeassistant.components.volvooncall import VolvoEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Setup the lock."""
|
||||
if discovery_info is None:
|
||||
return
|
||||
add_devices([VolvoLock(hass, discovery_info)])
|
||||
|
||||
|
||||
class VolvoLock(VolvoEntity, LockDevice):
|
||||
"""Represents a car lock."""
|
||||
|
||||
@property
|
||||
def is_locked(self):
|
||||
"""Return true if lock is locked."""
|
||||
return self.vehicle.is_locked
|
||||
|
||||
def lock(self, **kwargs):
|
||||
"""Lock the car."""
|
||||
self.vehicle.lock()
|
||||
|
||||
def unlock(self, **kwargs):
|
||||
"""Unlock the car."""
|
||||
self.vehicle.unlock()
|
||||
|
||||
@property
|
||||
def _name(self):
|
||||
"""Return name."""
|
||||
return 'Lock'
|
59
homeassistant/components/sensor/volvooncall.py
Normal file
59
homeassistant/components/sensor/volvooncall.py
Normal file
|
@ -0,0 +1,59 @@
|
|||
"""
|
||||
Support for VOC.
|
||||
|
||||
For more details about this platform, please refer to the documentation at
|
||||
https://home-assistant.io/components/sensor.volvooncall/
|
||||
|
||||
"""
|
||||
import logging
|
||||
|
||||
from homeassistant.components.volvooncall import VolvoEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
SENSORS = [('odometer', 'Odometer', 'km', 'mdi:speedometer'),
|
||||
('fuel_amount', 'Fuel', 'L', 'mdi:gas-station'),
|
||||
('fuel_amount_level', 'Fuel', '%', 'mdi:water-percent'),
|
||||
('distance_to_empty', 'Range', 'km', 'mdi:ruler')]
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Setup Volvo sensors."""
|
||||
if discovery_info is None:
|
||||
return
|
||||
add_devices(VolvoSensor(hass, discovery_info, sensor)
|
||||
for sensor in SENSORS)
|
||||
|
||||
|
||||
class VolvoSensor(VolvoEntity):
|
||||
"""Representation of a Volvo sensor."""
|
||||
|
||||
def __init__(self, hass, vehicle, sensor):
|
||||
"""Initialize sensor."""
|
||||
super().__init__(hass, vehicle)
|
||||
self._sensor = sensor
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
"""Return the state of the sensor."""
|
||||
attr = self._sensor[0]
|
||||
val = getattr(self.vehicle, attr)
|
||||
if attr == 'odometer':
|
||||
return round(val / 1000) # km
|
||||
else:
|
||||
return val
|
||||
|
||||
@property
|
||||
def _name(self):
|
||||
"""Name of quantity."""
|
||||
return self._sensor[1]
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
"""Return the unit of measurement."""
|
||||
return self._sensor[2]
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
"""Return the icon."""
|
||||
return self._sensor[3]
|
47
homeassistant/components/switch/volvooncall.py
Normal file
47
homeassistant/components/switch/volvooncall.py
Normal file
|
@ -0,0 +1,47 @@
|
|||
"""
|
||||
Support for Volvo heater.
|
||||
|
||||
This platform uses the Telldus Live online service.
|
||||
|
||||
For more details about this platform, please refer to the documentation at
|
||||
https://home-assistant.io/components/switch.volvooncall/
|
||||
"""
|
||||
import logging
|
||||
|
||||
from homeassistant.components.volvooncall import VolvoEntity
|
||||
from homeassistant.helpers.entity import ToggleEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Setup Tellstick switches."""
|
||||
if discovery_info is None:
|
||||
return
|
||||
add_devices([VolvoSwitch(hass, discovery_info)])
|
||||
|
||||
|
||||
class VolvoSwitch(VolvoEntity, ToggleEntity):
|
||||
"""Representation of a Volvo switch."""
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return true if switch is on."""
|
||||
return self.vehicle.is_heater_on
|
||||
|
||||
def turn_on(self, **kwargs):
|
||||
"""Turn the switch on."""
|
||||
self.vehicle.start_heater()
|
||||
|
||||
def turn_off(self, **kwargs):
|
||||
"""Turn the switch off."""
|
||||
self.vehicle.stop_heater()
|
||||
|
||||
@property
|
||||
def _name(self):
|
||||
"""Return the name of the switch."""
|
||||
return 'Heater'
|
||||
|
||||
def icon(self):
|
||||
"""Return the icon."""
|
||||
return 'mdi:radiator'
|
148
homeassistant/components/volvooncall.py
Normal file
148
homeassistant/components/volvooncall.py
Normal file
|
@ -0,0 +1,148 @@
|
|||
"""
|
||||
Support for Volvo On Call.
|
||||
|
||||
For more details about this component, please refer to the documentation at
|
||||
https://home-assistant.io/components/volvooncall/
|
||||
"""
|
||||
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
from homeassistant.const import (CONF_USERNAME, CONF_PASSWORD)
|
||||
from homeassistant.helpers import discovery
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.event import track_point_in_utc_time
|
||||
from homeassistant.util.dt import utcnow
|
||||
import voluptuous as vol
|
||||
|
||||
DOMAIN = 'volvooncall'
|
||||
|
||||
REQUIREMENTS = ['volvooncall==0.3.0']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CONF_UPDATE_INTERVAL = 'update_interval'
|
||||
MIN_UPDATE_INTERVAL = timedelta(minutes=1)
|
||||
DEFAULT_UPDATE_INTERVAL = timedelta(minutes=1)
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
DOMAIN: vol.Schema({
|
||||
vol.Required(CONF_USERNAME): cv.string,
|
||||
vol.Required(CONF_PASSWORD): cv.string,
|
||||
vol.Optional(CONF_UPDATE_INTERVAL, default=DEFAULT_UPDATE_INTERVAL): (
|
||||
vol.All(cv.time_period, vol.Clamp(min=MIN_UPDATE_INTERVAL)))
|
||||
}),
|
||||
}, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
|
||||
def setup(hass, config):
|
||||
"""Setup the VOC component."""
|
||||
from volvooncall import Connection
|
||||
connection = Connection(
|
||||
config[DOMAIN].get(CONF_USERNAME),
|
||||
config[DOMAIN].get(CONF_PASSWORD))
|
||||
|
||||
interval = config[DOMAIN].get(CONF_UPDATE_INTERVAL)
|
||||
|
||||
class state: # pylint:disable=invalid-name
|
||||
"""Namespace to hold state for each vehicle."""
|
||||
|
||||
entities = {}
|
||||
vehicles = {}
|
||||
|
||||
hass.data[DOMAIN] = state
|
||||
|
||||
def discover_vehicle(vehicle):
|
||||
"""Load relevant platforms."""
|
||||
state.entities[vehicle.vin] = []
|
||||
components = ['sensor', 'binary_sensor']
|
||||
|
||||
if getattr(vehicle, 'position'):
|
||||
components.append('device_tracker')
|
||||
|
||||
if vehicle.heater_supported:
|
||||
components.append('switch')
|
||||
|
||||
if vehicle.lock_supported:
|
||||
components.append('lock')
|
||||
|
||||
for component in components:
|
||||
discovery.load_platform(hass,
|
||||
component,
|
||||
DOMAIN,
|
||||
vehicle.vin,
|
||||
config)
|
||||
|
||||
def update_vehicle(vehicle):
|
||||
"""Updated information on vehicle received."""
|
||||
state.vehicles[vehicle.vin] = vehicle
|
||||
if vehicle.vin not in state.entities:
|
||||
discover_vehicle(vehicle)
|
||||
|
||||
for entity in state.entities[vehicle.vin]:
|
||||
if isinstance(entity, Entity):
|
||||
entity.schedule_update_ha_state()
|
||||
else:
|
||||
entity(vehicle) # device tracker
|
||||
|
||||
def update(now):
|
||||
"""Update status from the online service."""
|
||||
try:
|
||||
if not connection.update():
|
||||
_LOGGER.warning('Could not query server')
|
||||
return False
|
||||
|
||||
for vehicle in connection.vehicles:
|
||||
update_vehicle(vehicle)
|
||||
|
||||
return True
|
||||
finally:
|
||||
track_point_in_utc_time(hass, update, now + interval)
|
||||
|
||||
_LOGGER.info('Logging in to service')
|
||||
return update(utcnow())
|
||||
|
||||
|
||||
class VolvoEntity(Entity):
|
||||
"""Base class for all VOC entities."""
|
||||
|
||||
def __init__(self, hass, vin):
|
||||
"""Initialize the entity."""
|
||||
self._hass = hass
|
||||
self._vin = vin
|
||||
self._hass.data[DOMAIN].entities[self._vin].append(self)
|
||||
|
||||
@property
|
||||
def vehicle(self):
|
||||
"""Return vehicle."""
|
||||
return self._hass.data[DOMAIN].vehicles[self._vin]
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the sensor."""
|
||||
return '%s %s' % (
|
||||
self.vehicle.registration_number,
|
||||
self._name)
|
||||
|
||||
@property
|
||||
def _name(self):
|
||||
"""Overridden by subclasses."""
|
||||
return None
|
||||
|
||||
@property
|
||||
def should_poll(self):
|
||||
"""Polling is not needed."""
|
||||
return False
|
||||
|
||||
@property
|
||||
def assumed_state(self):
|
||||
"""Return true if unable to access real state of entity."""
|
||||
return True
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return device specific state attributes."""
|
||||
return dict(model='%s/%s' % (
|
||||
self.vehicle.vehicle_type,
|
||||
self.vehicle.model_year))
|
|
@ -710,8 +710,8 @@ urllib3
|
|||
# homeassistant.components.camera.uvc
|
||||
uvcclient==0.10.0
|
||||
|
||||
# homeassistant.components.device_tracker.volvooncall
|
||||
volvooncall==0.1.1
|
||||
# homeassistant.components.volvooncall
|
||||
volvooncall==0.3.0
|
||||
|
||||
# homeassistant.components.verisure
|
||||
vsure==0.11.1
|
||||
|
|
Loading…
Add table
Reference in a new issue