* mychevy: added basic mychevy component This implements a component using the mychevy library (which utilizes selenium to webscrape the mychevy website for onstar for your car). The architecture works by having a background thread doing periodic polling of the website, and updating the sensors when new data is found. This requires rather more setup than most platforms, as you need working selenium. Instructions will be provided on the component list. All the sensors are spawned and coordinated from a single "hub" as they are really just attributes of the same web scraping session. * mychevy: only poll every 30 minutes * mychevy: update sensors * mychevy: better error handling * mychevy: tweaking for refactor * mychevy: bump version to handle odometer > 1000 * mychevy: great sensor reorg * mychevy: add binary sensors * mychevy: bump mychevy requirement * mychevy: use dispatcher Instead of directly modifying the sensors, this lets us use a dispatcher to have sensors pull information from the car object when there is a relevant update for them. * mychevy: remove from coverage * mychevy: dedicated constants for dispatch signals This makes the dispatch signals dedicated topics, and fixes updating the state on the sensors so that they are correctly updated. * mychevy: updated with comments from martinhjelmare * mychevy: set battery icon based with helper function * Address additional review feedback * Address additional review comments
85 lines
2.3 KiB
Python
85 lines
2.3 KiB
Python
"""Support for MyChevy sensors.
|
|
|
|
For more details about this platform, please refer to the documentation at
|
|
https://home-assistant.io/components/binary_sensor.mychevy/
|
|
"""
|
|
|
|
import asyncio
|
|
import logging
|
|
|
|
from homeassistant.components.mychevy import (
|
|
EVBinarySensorConfig, DOMAIN as MYCHEVY_DOMAIN, UPDATE_TOPIC
|
|
)
|
|
from homeassistant.components.binary_sensor import (
|
|
ENTITY_ID_FORMAT, BinarySensorDevice)
|
|
from homeassistant.core import callback
|
|
from homeassistant.util import slugify
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
SENSORS = [
|
|
EVBinarySensorConfig("Plugged In", "plugged_in", "plug")
|
|
]
|
|
|
|
|
|
@asyncio.coroutine
|
|
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|
"""Set up the MyChevy sensors."""
|
|
if discovery_info is None:
|
|
return
|
|
|
|
sensors = []
|
|
hub = hass.data[MYCHEVY_DOMAIN]
|
|
for sconfig in SENSORS:
|
|
sensors.append(EVBinarySensor(hub, sconfig))
|
|
|
|
async_add_devices(sensors)
|
|
|
|
|
|
class EVBinarySensor(BinarySensorDevice):
|
|
"""Base EVSensor class.
|
|
|
|
The only real difference between sensors is which units and what
|
|
attribute from the car object they are returning. All logic can be
|
|
built with just setting subclass attributes.
|
|
|
|
"""
|
|
|
|
def __init__(self, connection, config):
|
|
"""Initialize sensor with car connection."""
|
|
self._conn = connection
|
|
self._name = config.name
|
|
self._attr = config.attr
|
|
self._type = config.device_class
|
|
self._is_on = None
|
|
|
|
self.entity_id = ENTITY_ID_FORMAT.format(
|
|
'{}_{}'.format(MYCHEVY_DOMAIN, slugify(self._name)))
|
|
|
|
@property
|
|
def name(self):
|
|
"""Return the name."""
|
|
return self._name
|
|
|
|
@property
|
|
def is_on(self):
|
|
"""Return if on."""
|
|
return self._is_on
|
|
|
|
@asyncio.coroutine
|
|
def async_added_to_hass(self):
|
|
"""Register callbacks."""
|
|
self.hass.helpers.dispatcher.async_dispatcher_connect(
|
|
UPDATE_TOPIC, self.async_update_callback)
|
|
|
|
@callback
|
|
def async_update_callback(self):
|
|
"""Update state."""
|
|
if self._conn.car is not None:
|
|
self._is_on = getattr(self._conn.car, self._attr, None)
|
|
self.async_schedule_update_ha_state()
|
|
|
|
@property
|
|
def should_poll(self):
|
|
"""Return the polling state."""
|
|
return False
|