From 25970027c6c294978cd7b312d4140ed978d6e552 Mon Sep 17 00:00:00 2001 From: Sean Dague Date: Fri, 18 May 2018 13:37:43 -0400 Subject: [PATCH] Update mychevy to 0.4.0 (#14372) After 2 months of being offline, the my.chevy website seems to be working again. Some data structures changed in the mean time. The new library will handle multiple cars. This involves a breaking change in slug urls for devices where these now include the car make, model, and year in them. Discovery has to be delayed until after the initial site login to get the car metadata. --- .../components/binary_sensor/mychevy.py | 20 ++++++++---- homeassistant/components/mychevy.py | 25 +++++++++++---- homeassistant/components/sensor/mychevy.py | 32 ++++++++++++------- requirements_all.txt | 2 +- 4 files changed, 55 insertions(+), 24 deletions(-) diff --git a/homeassistant/components/binary_sensor/mychevy.py b/homeassistant/components/binary_sensor/mychevy.py index a89395ed86f..905e60c34d9 100644 --- a/homeassistant/components/binary_sensor/mychevy.py +++ b/homeassistant/components/binary_sensor/mychevy.py @@ -31,7 +31,8 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): sensors = [] hub = hass.data[MYCHEVY_DOMAIN] for sconfig in SENSORS: - sensors.append(EVBinarySensor(hub, sconfig)) + for car in hub.cars: + sensors.append(EVBinarySensor(hub, sconfig, car.vid)) async_add_devices(sensors) @@ -45,16 +46,18 @@ class EVBinarySensor(BinarySensorDevice): """ - def __init__(self, connection, config): + def __init__(self, connection, config, car_vid): """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._car_vid = car_vid self.entity_id = ENTITY_ID_FORMAT.format( - '{}_{}'.format(MYCHEVY_DOMAIN, slugify(self._name))) + '{}_{}_{}'.format(MYCHEVY_DOMAIN, + slugify(self._car.name), + slugify(self._name))) @property def name(self): @@ -66,6 +69,11 @@ class EVBinarySensor(BinarySensorDevice): """Return if on.""" return self._is_on + @property + def _car(self): + """Return the car.""" + return self._conn.get_car(self._car_vid) + @asyncio.coroutine def async_added_to_hass(self): """Register callbacks.""" @@ -75,8 +83,8 @@ class EVBinarySensor(BinarySensorDevice): @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) + if self._car is not None: + self._is_on = getattr(self._car, self._attr, None) self.async_schedule_update_ha_state() @property diff --git a/homeassistant/components/mychevy.py b/homeassistant/components/mychevy.py index 678cdf10c56..3531c6b4919 100644 --- a/homeassistant/components/mychevy.py +++ b/homeassistant/components/mychevy.py @@ -16,7 +16,7 @@ from homeassistant.helpers import config_validation as cv from homeassistant.helpers import discovery from homeassistant.util import Throttle -REQUIREMENTS = ["mychevy==0.1.1"] +REQUIREMENTS = ["mychevy==0.4.0"] DOMAIN = 'mychevy' UPDATE_TOPIC = DOMAIN @@ -73,9 +73,6 @@ def setup(hass, base_config): hass.data[DOMAIN] = MyChevyHub(mc.MyChevy(email, password), hass) hass.data[DOMAIN].start() - discovery.load_platform(hass, 'sensor', DOMAIN, {}, config) - discovery.load_platform(hass, 'binary_sensor', DOMAIN, {}, config) - return True @@ -98,8 +95,9 @@ class MyChevyHub(threading.Thread): super().__init__() self._client = client self.hass = hass - self.car = None + self.cars = [] self.status = None + self.ready = False @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): @@ -109,7 +107,22 @@ class MyChevyHub(threading.Thread): (like 2 to 3 minutes long time) """ - self.car = self._client.data() + self._client.login() + self._client.get_cars() + self.cars = self._client.cars + if self.ready is not True: + discovery.load_platform(self.hass, 'sensor', DOMAIN, {}, {}) + discovery.load_platform(self.hass, 'binary_sensor', DOMAIN, {}, {}) + self.ready = True + self.cars = self._client.update_cars() + + def get_car(self, vid): + """Compatibility to work with one car.""" + if self.cars: + for car in self.cars: + if car.vid == vid: + return car + return None def run(self): """Thread run loop.""" diff --git a/homeassistant/components/sensor/mychevy.py b/homeassistant/components/sensor/mychevy.py index bdbffc46ca8..ef7c7ba8608 100644 --- a/homeassistant/components/sensor/mychevy.py +++ b/homeassistant/components/sensor/mychevy.py @@ -17,14 +17,15 @@ from homeassistant.helpers.entity import Entity from homeassistant.helpers.icon import icon_for_battery_level from homeassistant.util import slugify -BATTERY_SENSOR = "percent" +BATTERY_SENSOR = "batteryLevel" SENSORS = [ - EVSensorConfig("Mileage", "mileage", "miles", "mdi:speedometer"), - EVSensorConfig("Range", "range", "miles", "mdi:speedometer"), - EVSensorConfig("Charging", "charging"), - EVSensorConfig("Charge Mode", "charge_mode"), - EVSensorConfig("EVCharge", BATTERY_SENSOR, "%", "mdi:battery") + EVSensorConfig("Mileage", "totalMiles", "miles", "mdi:speedometer"), + EVSensorConfig("Electric Range", "electricRange", "miles", + "mdi:speedometer"), + EVSensorConfig("Charged By", "estimatedFullChargeBy"), + EVSensorConfig("Charge Mode", "chargeMode"), + EVSensorConfig("Battery Level", BATTERY_SENSOR, "%", "mdi:battery") ] _LOGGER = logging.getLogger(__name__) @@ -38,7 +39,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None): hub = hass.data[MYCHEVY_DOMAIN] sensors = [MyChevyStatus()] for sconfig in SENSORS: - sensors.append(EVSensor(hub, sconfig)) + for car in hub.cars: + sensors.append(EVSensor(hub, sconfig, car.vid)) add_devices(sensors) @@ -112,7 +114,7 @@ class EVSensor(Entity): """ - def __init__(self, connection, config): + def __init__(self, connection, config, car_vid): """Initialize sensor with car connection.""" self._conn = connection self._name = config.name @@ -120,9 +122,12 @@ class EVSensor(Entity): self._unit_of_measurement = config.unit_of_measurement self._icon = config.icon self._state = None + self._car_vid = car_vid self.entity_id = ENTITY_ID_FORMAT.format( - '{}_{}'.format(MYCHEVY_DOMAIN, slugify(self._name))) + '{}_{}_{}'.format(MYCHEVY_DOMAIN, + slugify(self._car.name), + slugify(self._name))) @asyncio.coroutine def async_added_to_hass(self): @@ -130,6 +135,11 @@ class EVSensor(Entity): self.hass.helpers.dispatcher.async_dispatcher_connect( UPDATE_TOPIC, self.async_update_callback) + @property + def _car(self): + """Return the car.""" + return self._conn.get_car(self._car_vid) + @property def icon(self): """Return the icon.""" @@ -145,8 +155,8 @@ class EVSensor(Entity): @callback def async_update_callback(self): """Update state.""" - if self._conn.car is not None: - self._state = getattr(self._conn.car, self._attr, None) + if self._car is not None: + self._state = getattr(self._car, self._attr, None) self.async_schedule_update_ha_state() @property diff --git a/requirements_all.txt b/requirements_all.txt index ffcbc6001cc..78efe76dce6 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -543,7 +543,7 @@ motorparts==1.0.2 mutagen==1.40.0 # homeassistant.components.mychevy -mychevy==0.1.1 +mychevy==0.4.0 # homeassistant.components.mycroft mycroftapi==2.0