1
mirror of https://github.com/home-assistant/core synced 2024-09-28 03:04:04 +02:00

Remove mychevy component (#59629)

This commit is contained in:
Sean Dague 2021-11-14 05:09:32 -05:00 committed by GitHub
parent f596cb19fd
commit da8bfed793
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 0 additions and 432 deletions

View File

@ -668,7 +668,6 @@ omit =
homeassistant/components/mutesync/binary_sensor.py
homeassistant/components/nest/const.py
homeassistant/components/mvglive/sensor.py
homeassistant/components/mychevy/*
homeassistant/components/mycroft/*
homeassistant/components/mysensors/__init__.py
homeassistant/components/mysensors/binary_sensor.py

View File

@ -1,155 +0,0 @@
"""Support for MyChevy."""
from datetime import timedelta
import logging
import threading
import time
import mychevy.mychevy as mc
import voluptuous as vol
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
from homeassistant.helpers import config_validation as cv, discovery
from homeassistant.util import Throttle
DOMAIN = "mychevy"
UPDATE_TOPIC = DOMAIN
ERROR_TOPIC = f"{DOMAIN}_error"
MYCHEVY_SUCCESS = "success"
MYCHEVY_ERROR = "error"
NOTIFICATION_ID = "mychevy_website_notification"
NOTIFICATION_TITLE = "MyChevy website status"
_LOGGER = logging.getLogger(__name__)
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=30)
ERROR_SLEEP_TIME = timedelta(minutes=30)
CONF_COUNTRY = "country"
DEFAULT_COUNTRY = "us"
CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.Schema(
{
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Optional(CONF_COUNTRY, default=DEFAULT_COUNTRY): vol.All(
cv.string, vol.In(["us", "ca"])
),
}
)
},
extra=vol.ALLOW_EXTRA,
)
class EVSensorConfig:
"""The EV sensor configuration."""
def __init__(
self, name, attr, unit_of_measurement=None, icon=None, extra_attrs=None
):
"""Create new sensor configuration."""
self.name = name
self.attr = attr
self.extra_attrs = extra_attrs or []
self.unit_of_measurement = unit_of_measurement
self.icon = icon
class EVBinarySensorConfig:
"""The EV binary sensor configuration."""
def __init__(self, name, attr, device_class=None):
"""Create new binary sensor configuration."""
self.name = name
self.attr = attr
self.device_class = device_class
def setup(hass, base_config):
"""Set up the mychevy component."""
config = base_config.get(DOMAIN)
email = config.get(CONF_USERNAME)
password = config.get(CONF_PASSWORD)
country = config.get(CONF_COUNTRY)
hass.data[DOMAIN] = MyChevyHub(
mc.MyChevy(email, password, country), hass, base_config
)
hass.data[DOMAIN].start()
return True
class MyChevyHub(threading.Thread):
"""MyChevy Hub.
Connecting to the mychevy website is done through a selenium
webscraping process. That can only run synchronously. In order to
prevent blocking of other parts of Home Assistant the architecture
launches a polling loop in a thread.
When new data is received, sensors are updated, and hass is
signaled that there are updates. Sensors are not created until the
first update, which will be 60 - 120 seconds after the platform
starts.
"""
def __init__(self, client, hass, hass_config):
"""Initialize MyChevy Hub."""
super().__init__()
self._client = client
self.hass = hass
self.hass_config = hass_config
self.cars = []
self.status = None
self.ready = False
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self):
"""Update sensors from mychevy website.
This is a synchronous polling call that takes a very long time
(like 2 to 3 minutes long time)
"""
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, {}, self.hass_config)
discovery.load_platform(
self.hass, "binary_sensor", DOMAIN, {}, self.hass_config
)
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."""
# We add the status device first outside of the loop
# And then busy wait on threads
while True:
try:
_LOGGER.info("Starting mychevy loop")
self.update()
self.hass.helpers.dispatcher.dispatcher_send(UPDATE_TOPIC)
time.sleep(MIN_TIME_BETWEEN_UPDATES.total_seconds())
except Exception: # pylint: disable=broad-except
_LOGGER.exception(
"Error updating mychevy data. "
"This probably means the OnStar link is down again"
)
self.hass.helpers.dispatcher.dispatcher_send(ERROR_TOPIC)
time.sleep(ERROR_SLEEP_TIME.total_seconds())

View File

@ -1,79 +0,0 @@
"""Support for MyChevy binary sensors."""
from homeassistant.components.binary_sensor import (
DOMAIN as BINARY_SENSOR_DOMAIN,
BinarySensorEntity,
)
from homeassistant.core import callback
from homeassistant.util import slugify
from . import DOMAIN as MYCHEVY_DOMAIN, UPDATE_TOPIC, EVBinarySensorConfig
SENSORS = [EVBinarySensorConfig("Plugged In", "plugged_in", "plug")]
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Set up the MyChevy sensors."""
if discovery_info is None:
return
sensors = []
hub = hass.data[MYCHEVY_DOMAIN]
for sconfig in SENSORS:
for car in hub.cars:
sensors.append(EVBinarySensor(hub, sconfig, car.vid))
async_add_entities(sensors)
class EVBinarySensor(BinarySensorEntity):
"""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, 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 = f"{BINARY_SENSOR_DOMAIN}.{MYCHEVY_DOMAIN}_{slugify(self._car.name)}_{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
@property
def _car(self):
"""Return the car."""
return self._conn.get_car(self._car_vid)
async def async_added_to_hass(self):
"""Register callbacks."""
self.async_on_remove(
self.hass.helpers.dispatcher.async_dispatcher_connect(
UPDATE_TOPIC, self.async_update_callback
)
)
@callback
def async_update_callback(self):
"""Update state."""
if self._car is not None:
self._is_on = getattr(self._car, self._attr, None)
self.async_write_ha_state()
@property
def should_poll(self):
"""Return the polling state."""
return False

View File

@ -1,8 +0,0 @@
{
"domain": "mychevy",
"name": "myChevrolet",
"documentation": "https://www.home-assistant.io/integrations/mychevy",
"requirements": ["mychevy==2.1.1"],
"codeowners": [],
"iot_class": "cloud_polling"
}

View File

@ -1,186 +0,0 @@
"""Support for MyChevy sensors."""
import logging
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN, SensorEntity
from homeassistant.const import PERCENTAGE
from homeassistant.core import callback
from homeassistant.helpers.icon import icon_for_battery_level
from homeassistant.util import slugify
from . import (
DOMAIN as MYCHEVY_DOMAIN,
ERROR_TOPIC,
MYCHEVY_ERROR,
MYCHEVY_SUCCESS,
UPDATE_TOPIC,
EVSensorConfig,
)
_LOGGER = logging.getLogger(__name__)
BATTERY_SENSOR = "batteryLevel"
SENSORS = [
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, PERCENTAGE, "mdi:battery", ["charging"]
),
]
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the MyChevy sensors."""
if discovery_info is None:
return
hub = hass.data[MYCHEVY_DOMAIN]
sensors = [MyChevyStatus()]
for sconfig in SENSORS:
for car in hub.cars:
sensors.append(EVSensor(hub, sconfig, car.vid))
add_entities(sensors)
class MyChevyStatus(SensorEntity):
"""A string representing the charge mode."""
_name = "MyChevy Status"
_icon = "mdi:car-connected"
def __init__(self):
"""Initialize sensor with car connection."""
self._state = None
async def async_added_to_hass(self):
"""Register callbacks."""
self.async_on_remove(
self.hass.helpers.dispatcher.async_dispatcher_connect(
UPDATE_TOPIC, self.success
)
)
self.async_on_remove(
self.hass.helpers.dispatcher.async_dispatcher_connect(
ERROR_TOPIC, self.error
)
)
@callback
def success(self):
"""Update state, trigger updates."""
if self._state != MYCHEVY_SUCCESS:
_LOGGER.debug("Successfully connected to mychevy website")
self._state = MYCHEVY_SUCCESS
self.async_write_ha_state()
@callback
def error(self):
"""Update state, trigger updates."""
_LOGGER.error(
"Connection to mychevy website failed. "
"This probably means the mychevy to OnStar link is down"
)
self._state = MYCHEVY_ERROR
self.async_write_ha_state()
@property
def icon(self):
"""Return the icon."""
return self._icon
@property
def name(self):
"""Return the name."""
return self._name
@property
def native_value(self):
"""Return the state."""
return self._state
@property
def should_poll(self):
"""Return the polling state."""
return False
class EVSensor(SensorEntity):
"""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, car_vid):
"""Initialize sensor with car connection."""
self._conn = connection
self._name = config.name
self._attr = config.attr
self._extra_attrs = config.extra_attrs
self._unit_of_measurement = config.unit_of_measurement
self._icon = config.icon
self._state = None
self._state_attributes = {}
self._car_vid = car_vid
self.entity_id = f"{SENSOR_DOMAIN}.{MYCHEVY_DOMAIN}_{slugify(self._car.name)}_{slugify(self._name)}"
async def async_added_to_hass(self):
"""Register callbacks."""
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."""
if self._attr == BATTERY_SENSOR:
charging = self._state_attributes.get("charging", False)
return icon_for_battery_level(self.state, charging)
return self._icon
@property
def name(self):
"""Return the name."""
return self._name
@callback
def async_update_callback(self):
"""Update state."""
if self._car is not None:
self._state = getattr(self._car, self._attr, None)
if self._unit_of_measurement == "miles":
self._state = round(self._state)
for attr in self._extra_attrs:
self._state_attributes[attr] = getattr(self._car, attr)
self.async_write_ha_state()
@property
def native_value(self):
"""Return the state."""
return self._state
@property
def extra_state_attributes(self):
"""Return all the state attributes."""
return self._state_attributes
@property
def native_unit_of_measurement(self):
"""Return the unit of measurement the state is expressed in."""
return self._unit_of_measurement
@property
def should_poll(self):
"""Return the polling state."""
return False

View File

@ -1034,9 +1034,6 @@ mutagen==1.45.1
# homeassistant.components.mutesync
mutesync==0.0.1
# homeassistant.components.mychevy
mychevy==2.1.1
# homeassistant.components.mycroft
mycroftapi==2.0