Add new component: BMW connected drive (#12277)

* first working version of BMW connected drive sensor

* extended coveragerc

* fixed blank line

* fixed pylint

* major refactoring after major refactoring in bimmer_connected

* Update are now triggered from BMWConnectedDriveVehicle.
* removed polling from sensor and device_tracker
* backend URL is not detected automatically based on current country
* vehicles are discovered automatically
* updates are async now

resolves:
* https://github.com/ChristianKuehnel/bimmer_connected/issues/3
* https://github.com/ChristianKuehnel/bimmer_connected/issues/5

* improved exception handing

* fixed static analysis findings

* fixed review comments from @MartinHjelmare

* improved startup, data is updated right after sensors were created.

* fixed pylint issue

* updated to latest release of the bimmer_connected library

* updated requirements-all.txt

* fixed comments from @MartinHjelmare

* calling self.update from async_add_job

* removed unused attribute "account"
This commit is contained in:
ChristianKuehnel 2018-02-20 23:02:08 +01:00 committed by Martin Hjelmare
parent 5d29d88888
commit 316eb59de2
6 changed files with 263 additions and 0 deletions

View file

@ -0,0 +1,99 @@
"""
Reads vehicle status from BMW connected drive portal.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/sensor.bmw_connected_drive/
"""
import logging
import asyncio
from homeassistant.components.bmw_connected_drive import DOMAIN as BMW_DOMAIN
from homeassistant.helpers.entity import Entity
DEPENDENCIES = ['bmw_connected_drive']
_LOGGER = logging.getLogger(__name__)
LENGTH_ATTRIBUTES = [
'remaining_range_fuel',
'mileage',
]
VALID_ATTRIBUTES = LENGTH_ATTRIBUTES + [
'remaining_fuel',
]
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the BMW sensors."""
accounts = hass.data[BMW_DOMAIN]
_LOGGER.debug('Found BMW accounts: %s',
', '.join([a.name for a in accounts]))
devices = []
for account in accounts:
for vehicle in account.account.vehicles:
for sensor in VALID_ATTRIBUTES:
device = BMWConnectedDriveSensor(account, vehicle, sensor)
devices.append(device)
add_devices(devices)
class BMWConnectedDriveSensor(Entity):
"""Representation of a BMW vehicle sensor."""
def __init__(self, account, vehicle, attribute: str):
"""Constructor."""
self._vehicle = vehicle
self._account = account
self._attribute = attribute
self._state = None
self._unit_of_measurement = None
self._name = '{} {}'.format(self._vehicle.modelName, self._attribute)
@property
def should_poll(self) -> bool:
"""Data update is triggered from BMWConnectedDriveEntity."""
return False
@property
def name(self) -> str:
"""Return the name of the sensor."""
return self._name
@property
def state(self):
"""Return the state of the sensor.
The return type of this call depends on the attribute that
is configured.
"""
return self._state
@property
def unit_of_measurement(self) -> str:
"""Get the unit of measurement."""
return self._unit_of_measurement
def update(self) -> None:
"""Read new state data from the library."""
_LOGGER.debug('Updating %s', self.entity_id)
vehicle_state = self._vehicle.state
self._state = getattr(vehicle_state, self._attribute)
if self._attribute in LENGTH_ATTRIBUTES:
self._unit_of_measurement = vehicle_state.unit_of_length
elif self._attribute == 'remaining_fuel':
self._unit_of_measurement = vehicle_state.unit_of_volume
else:
self._unit_of_measurement = None
self.schedule_update_ha_state()
@asyncio.coroutine
def async_added_to_hass(self):
"""Add callback after being added to hass.
Show latest data after startup.
"""
self._account.add_update_listener(self.update)
yield from self.hass.async_add_job(self.update)