From fcccf133ba210b2f4758c1f21cabecbee56f5fcd Mon Sep 17 00:00:00 2001 From: Rohan Kapoor Date: Fri, 1 Feb 2019 21:50:22 -0800 Subject: [PATCH] Split out fastdotcom into a component and a sensor platform (#20341) * Split out fastdotcom into a component and a sensor platform * Update .coveragerc * Switching to async and using a Throttle * Add the async_track_time_interval call * Remove the throttle * Reorder sensor methods and add should_poll property --- .coveragerc | 3 +- .../components/fastdotcom/__init__.py | 76 ++++++++++++ homeassistant/components/fastdotcom/sensor.py | 85 +++++++++++++ .../components/fastdotcom/services.yaml | 2 + homeassistant/components/sensor/fastdotcom.py | 115 ------------------ requirements_all.txt | 2 +- 6 files changed, 166 insertions(+), 117 deletions(-) create mode 100644 homeassistant/components/fastdotcom/__init__.py create mode 100644 homeassistant/components/fastdotcom/sensor.py create mode 100644 homeassistant/components/fastdotcom/services.yaml delete mode 100644 homeassistant/components/sensor/fastdotcom.py diff --git a/.coveragerc b/.coveragerc index 448adfcee3f..d9632103f67 100644 --- a/.coveragerc +++ b/.coveragerc @@ -138,6 +138,8 @@ omit = homeassistant/components/eufy.py homeassistant/components/*/eufy.py + homeassistant/components/fastdotcom/* + homeassistant/components/fibaro/__init__.py homeassistant/components/*/fibaro.py @@ -767,7 +769,6 @@ omit = homeassistant/components/sensor/enphase_envoy.py homeassistant/components/sensor/envirophat.py homeassistant/components/sensor/etherscan.py - homeassistant/components/sensor/fastdotcom.py homeassistant/components/sensor/fedex.py homeassistant/components/sensor/filesize.py homeassistant/components/sensor/fints.py diff --git a/homeassistant/components/fastdotcom/__init__.py b/homeassistant/components/fastdotcom/__init__.py new file mode 100644 index 00000000000..b5df45216e5 --- /dev/null +++ b/homeassistant/components/fastdotcom/__init__.py @@ -0,0 +1,76 @@ +""" +Support for testing internet speed via Fast.com. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/fastdotcom/ +""" + +import logging +from datetime import timedelta + +import voluptuous as vol + +import homeassistant.helpers.config_validation as cv +from homeassistant.const import CONF_UPDATE_INTERVAL +from homeassistant.helpers.discovery import async_load_platform +from homeassistant.helpers.dispatcher import dispatcher_send +from homeassistant.helpers.event import async_track_time_interval + +REQUIREMENTS = ['fastdotcom==0.0.3'] + +DOMAIN = 'fastdotcom' +DATA_UPDATED = '{}_data_updated'.format(DOMAIN) + +_LOGGER = logging.getLogger(__name__) + +CONF_MANUAL = 'manual' + +DEFAULT_INTERVAL = timedelta(hours=1) + +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({ + vol.Optional(CONF_UPDATE_INTERVAL, default=DEFAULT_INTERVAL): + vol.All( + cv.time_period, cv.positive_timedelta + ), + vol.Optional(CONF_MANUAL, default=False): cv.boolean, + }) +}, extra=vol.ALLOW_EXTRA) + + +async def async_setup(hass, config): + """Set up the Fast.com component.""" + conf = config[DOMAIN] + data = hass.data[DOMAIN] = SpeedtestData( + hass, conf[CONF_UPDATE_INTERVAL], conf[CONF_MANUAL] + ) + + def update(call=None): + """Service call to manually update the data.""" + data.update() + + hass.services.async_register(DOMAIN, 'speedtest', update) + + hass.async_create_task( + async_load_platform(hass, 'sensor', DOMAIN, {}, config) + ) + + return True + + +class SpeedtestData: + """Get the latest data from fast.com.""" + + def __init__(self, hass, interval, manual): + """Initialize the data object.""" + self.data = None + self._hass = hass + if not manual: + async_track_time_interval(self._hass, self.update, interval) + + def update(self): + """Get the latest data from fast.com.""" + from fastdotcom import fast_com + _LOGGER.debug("Executing fast.com speedtest") + self.data = {'download': fast_com()} + dispatcher_send(self._hass, DATA_UPDATED) diff --git a/homeassistant/components/fastdotcom/sensor.py b/homeassistant/components/fastdotcom/sensor.py new file mode 100644 index 00000000000..4d105cebf44 --- /dev/null +++ b/homeassistant/components/fastdotcom/sensor.py @@ -0,0 +1,85 @@ +""" +Support for Fast.com internet speed testing sensor. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/sensor.fastdotcom/ +""" +import logging + +from homeassistant.components.fastdotcom import DOMAIN as FASTDOTCOM_DOMAIN, \ + DATA_UPDATED +from homeassistant.core import callback +from homeassistant.helpers.dispatcher import async_dispatcher_connect +from homeassistant.helpers.restore_state import RestoreEntity + +DEPENDENCIES = ['fastdotcom'] + +_LOGGER = logging.getLogger(__name__) + +ICON = 'mdi:speedometer' + +UNIT_OF_MEASUREMENT = 'Mbit/s' + + +async def async_setup_platform(hass, config, async_add_entities, + discovery_info=None): + """Set up the Fast.com sensor.""" + async_add_entities([SpeedtestSensor(hass.data[FASTDOTCOM_DOMAIN])]) + + +class SpeedtestSensor(RestoreEntity): + """Implementation of a FAst.com sensor.""" + + def __init__(self, speedtest_data): + """Initialize the sensor.""" + self._name = 'Fast.com Download' + self.speedtest_client = speedtest_data + self._state = None + + @property + def name(self): + """Return the name of the sensor.""" + return self._name + + @property + def state(self): + """Return the state of the device.""" + return self._state + + @property + def unit_of_measurement(self): + """Return the unit of measurement of this entity, if any.""" + return UNIT_OF_MEASUREMENT + + @property + def icon(self): + """Return icon.""" + return ICON + + @property + def should_poll(self): + """Return the polling requirement for this sensor.""" + return False + + async def async_added_to_hass(self): + """Handle entity which will be added.""" + await super().async_added_to_hass() + state = await self.async_get_last_state() + if not state: + return + self._state = state.state + + async_dispatcher_connect( + self.hass, DATA_UPDATED, self._schedule_immediate_update + ) + + def update(self): + """Get the latest data and update the states.""" + data = self.speedtest_client.data + if data is None: + return + self._state = data['download'] + + @callback + def _schedule_immediate_update(self): + self.async_schedule_update_ha_state(True) diff --git a/homeassistant/components/fastdotcom/services.yaml b/homeassistant/components/fastdotcom/services.yaml new file mode 100644 index 00000000000..fe6cb1ac12d --- /dev/null +++ b/homeassistant/components/fastdotcom/services.yaml @@ -0,0 +1,2 @@ +speedtest: + description: Immediately take a speedest with Fast.com \ No newline at end of file diff --git a/homeassistant/components/sensor/fastdotcom.py b/homeassistant/components/sensor/fastdotcom.py deleted file mode 100644 index 8e975c48574..00000000000 --- a/homeassistant/components/sensor/fastdotcom.py +++ /dev/null @@ -1,115 +0,0 @@ -""" -Support for Fast.com internet speed testing sensor. - -For more details about this platform, please refer to the documentation at -https://home-assistant.io/components/sensor.fastdotcom/ -""" -import logging - -import voluptuous as vol - -from homeassistant.components.sensor import DOMAIN, PLATFORM_SCHEMA -import homeassistant.helpers.config_validation as cv -from homeassistant.helpers.event import track_time_change -from homeassistant.helpers.restore_state import RestoreEntity -import homeassistant.util.dt as dt_util - -REQUIREMENTS = ['fastdotcom==0.0.3'] - -_LOGGER = logging.getLogger(__name__) - -CONF_SECOND = 'second' -CONF_MINUTE = 'minute' -CONF_HOUR = 'hour' -CONF_MANUAL = 'manual' - -ICON = 'mdi:speedometer' - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Optional(CONF_SECOND, default=[0]): - vol.All(cv.ensure_list, [vol.All(vol.Coerce(int), vol.Range(0, 59))]), - vol.Optional(CONF_MINUTE, default=[0]): - vol.All(cv.ensure_list, [vol.All(vol.Coerce(int), vol.Range(0, 59))]), - vol.Optional(CONF_HOUR): - vol.All(cv.ensure_list, [vol.All(vol.Coerce(int), vol.Range(0, 23))]), - vol.Optional(CONF_MANUAL, default=False): cv.boolean, -}) - - -def setup_platform(hass, config, add_entities, discovery_info=None): - """Set up the Fast.com sensor.""" - data = SpeedtestData(hass, config) - sensor = SpeedtestSensor(data) - add_entities([sensor]) - - def update(call=None): - """Update service for manual updates.""" - data.update(dt_util.now()) - sensor.update() - - hass.services.register(DOMAIN, 'update_fastdotcom', update) - - -class SpeedtestSensor(RestoreEntity): - """Implementation of a FAst.com sensor.""" - - def __init__(self, speedtest_data): - """Initialize the sensor.""" - self._name = 'Fast.com Download' - self.speedtest_client = speedtest_data - self._state = None - self._unit_of_measurement = 'Mbit/s' - - @property - def name(self): - """Return the name of the sensor.""" - return self._name - - @property - def state(self): - """Return the state of the device.""" - return self._state - - @property - def unit_of_measurement(self): - """Return the unit of measurement of this entity, if any.""" - return self._unit_of_measurement - - def update(self): - """Get the latest data and update the states.""" - data = self.speedtest_client.data - if data is None: - return - - self._state = data['download'] - - async def async_added_to_hass(self): - """Handle entity which will be added.""" - await super().async_added_to_hass() - state = await self.async_get_last_state() - if not state: - return - self._state = state.state - - @property - def icon(self): - """Return icon.""" - return ICON - - -class SpeedtestData: - """Get the latest data from fast.com.""" - - def __init__(self, hass, config): - """Initialize the data object.""" - self.data = None - if not config.get(CONF_MANUAL): - track_time_change( - hass, self.update, second=config.get(CONF_SECOND), - minute=config.get(CONF_MINUTE), hour=config.get(CONF_HOUR)) - - def update(self, now): - """Get the latest data from fast.com.""" - from fastdotcom import fast_com - _LOGGER.info("Executing fast.com speedtest") - self.data = {'download': fast_com()} diff --git a/requirements_all.txt b/requirements_all.txt index 2d74da98a6c..b0bf06292e8 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -398,7 +398,7 @@ evohomeclient==0.2.8 # homeassistant.components.image_processing.dlib_face_identify # face_recognition==1.0.0 -# homeassistant.components.sensor.fastdotcom +# homeassistant.components.fastdotcom fastdotcom==0.0.3 # homeassistant.components.sensor.fedex