From 0113102a7f909dff5a751d859449b41751b7441f Mon Sep 17 00:00:00 2001 From: Matthieu Date: Sat, 10 Apr 2021 23:48:29 +0200 Subject: [PATCH] Centralize update loop --- custom_components/georide/__init__.py | 38 ++++++++++++-- custom_components/georide/binary_sensor.py | 35 +++++-------- custom_components/georide/device_tracker.py | 51 +++++++++--------- custom_components/georide/sensor.py | 58 ++++++++++----------- custom_components/georide/switch.py | 17 ++---- 5 files changed, 106 insertions(+), 93 deletions(-) diff --git a/custom_components/georide/__init__.py b/custom_components/georide/__init__.py index 255ae0f..5a3b930 100644 --- a/custom_components/georide/__init__.py +++ b/custom_components/georide/__init__.py @@ -2,6 +2,7 @@ from collections import defaultdict import logging +from typing import Any, Mapping from datetime import timedelta import math import time @@ -24,7 +25,10 @@ import homeassistant.helpers.event as ha_event from homeassistant.setup import async_when_setup from homeassistant.helpers.typing import HomeAssistantType - +from homeassistant.helpers.update_coordinator import ( + CoordinatorEntity, + DataUpdateCoordinator, +) from .const import ( CONF_EMAIL, @@ -88,7 +92,7 @@ async def async_setup_entry(hass, entry): hass.data[DOMAIN]["context"] = context # We add trackers to the context - await context.force_refresh_trackers() + await context.init_context(hass) hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, "device_tracker")) @@ -127,6 +131,7 @@ class GeoRideContext: self._hass = hass self._email = email self._password = password + self._georide_trackers_coordoned = [] self._georide_trackers = [] self._token = token self._socket = None @@ -204,12 +209,14 @@ class GeoRideContext: async def refresh_trackers(self): """ here we return last tracker by id""" - _LOGGER.info("Call refresh tracker") + _LOGGER.debug("Call refresh tracker") epoch_min = math.floor(time.time()/60) if (epoch_min % MIN_UNTIL_REFRESH) == 0: if epoch_min != self._previous_refresh: self._previous_refresh = epoch_min await self.force_refresh_trackers() + else: + _LOGGER.debug("We wil dont refresh the tracker list") if not self._thread_started: _LOGGER.info("Start the thread") @@ -235,6 +242,31 @@ class GeoRideContext: self._georide_trackers.append(refreshed_tracker) + async def init_context(self, hass): + """Used to refresh the tracker list""" + _LOGGER.info("Init_context") + await self.force_refresh_trackers() + update_interval = timedelta(seconds=10) + + for tracker in self._georide_trackers: + coordinator = DataUpdateCoordinator[Mapping[str, Any]]( + hass, + _LOGGER, + name=tracker.tracker_name, + update_method=self.refresh_trackers, + update_interval=update_interval + ) + self._georide_trackers_coordoned.append({ + "tracker": tracker, + "coordinator": coordinator + }) + + + def get_coordoned_trackers(self): + """Return coordoned trackers""" + + return self._georide_trackers_coordoned + @property def socket(self): """ hold the GeoRide socket """ diff --git a/custom_components/georide/binary_sensor.py b/custom_components/georide/binary_sensor.py index d54d9a0..ad7b1ef 100644 --- a/custom_components/georide/binary_sensor.py +++ b/custom_components/georide/binary_sensor.py @@ -8,38 +8,27 @@ from typing import Any, Mapping from homeassistant.core import callback from homeassistant.components.binary_sensor import BinarySensorEntity from homeassistant.components.binary_sensor import ENTITY_ID_FORMAT - from homeassistant.helpers.update_coordinator import ( CoordinatorEntity, - DataUpdateCoordinator, + DataUpdateCoordinator ) import georideapilib.api as GeoRideApi import georideapilib.objects as GeoRideTracker from .const import DOMAIN as GEORIDE_DOMAIN -from .const import MIN_UNTIL_REFRESH _LOGGER = logging.getLogger(__name__) async def async_setup_entry(hass, config_entry, async_add_entities): # pylint: disable=W0613 """Set up GeoRide tracker based off an entry.""" - georide_context = hass.data[GEORIDE_DOMAIN]["context"] - token = await georide_context.get_token() - if token is None: - return False - - update_interval = timedelta(seconds=1) - trackers = await hass.async_add_executor_job(GeoRideApi.get_trackers,token) + georide_context = hass.data[GEORIDE_DOMAIN]["context"] entities = [] - for tracker in trackers: - coordinator = DataUpdateCoordinator[Mapping[str, Any]]( - hass, - _LOGGER, - name=tracker.tracker_name, - update_method=georide_context.refresh_trackers, - update_interval=update_interval - ) + coordoned_trackers = georide_context.get_coordoned_trackers() + for coordoned_tracker in coordoned_trackers: + tracker = coordoned_tracker['tracker'] + coordinator = coordoned_tracker['coordinator'] + stolen_entity = GeoRideStolenBinarySensorEntity(coordinator, tracker) crashed_entity = GeoRideCrashedBinarySensorEntity(coordinator, tracker) entities.append(stolen_entity) @@ -53,7 +42,8 @@ async def async_setup_entry(hass, config_entry, async_add_entities): # pylint: d class GeoRideBinarySensorEntity(CoordinatorEntity, BinarySensorEntity): """Represent a tracked device.""" - def __init__(self, coordinator: DataUpdateCoordinator[Mapping[str, Any]], tracker: GeoRideTracker): + def __init__(self, coordinator: DataUpdateCoordinator[Mapping[str, Any]], + tracker: GeoRideTracker): """Set up Georide entity.""" super().__init__(coordinator) self._tracker = tracker @@ -89,8 +79,8 @@ class GeoRideBinarySensorEntity(CoordinatorEntity, BinarySensorEntity): class GeoRideStolenBinarySensorEntity(GeoRideBinarySensorEntity): """Represent a tracked device.""" - - def __init__(self, coordinator: DataUpdateCoordinator[Mapping[str, Any]], tracker: GeoRideTracker): + def __init__(self, coordinator: DataUpdateCoordinator[Mapping[str, Any]], + tracker: GeoRideTracker): """Set up Georide entity.""" super().__init__(coordinator, tracker) self.entity_id = ENTITY_ID_FORMAT.format("is_stolen") + "." + str(tracker.tracker_id) @@ -113,7 +103,8 @@ class GeoRideStolenBinarySensorEntity(GeoRideBinarySensorEntity): class GeoRideCrashedBinarySensorEntity(GeoRideBinarySensorEntity): """Represent a tracked device.""" - def __init__(self, coordinator: DataUpdateCoordinator[Mapping[str, Any]], tracker: GeoRideTracker): + def __init__(self, coordinator: DataUpdateCoordinator[Mapping[str, Any]], + tracker: GeoRideTracker): """Set up Georide entity.""" super().__init__(coordinator, tracker) self.entity_id = ENTITY_ID_FORMAT.format("is_crashed") + "." + str(tracker.tracker_id) diff --git a/custom_components/georide/device_tracker.py b/custom_components/georide/device_tracker.py index f0467d7..dc1feb3 100644 --- a/custom_components/georide/device_tracker.py +++ b/custom_components/georide/device_tracker.py @@ -1,9 +1,14 @@ """ device tracker for GeoRide object """ import logging +from typing import Any, Mapping from homeassistant.components.device_tracker.const import DOMAIN, SOURCE_TYPE_GPS from homeassistant.components.device_tracker.config_entry import TrackerEntity +from homeassistant.helpers.update_coordinator import ( + CoordinatorEntity, + DataUpdateCoordinator, +) import georideapilib.api as GeoRideApi @@ -14,34 +19,31 @@ _LOGGER = logging.getLogger(__name__) async def async_setup_entry(hass, config_entry, async_add_entities): # pylint: disable=W0613 """Set up Georide tracker based off an entry.""" + georide_context = hass.data[GEORIDE_DOMAIN]["context"] + coordoned_trackers = georide_context.get_coordoned_trackers() - georide_context = hass.data[GEORIDE_DOMAIN]["context"] - trackers = georide_context.get_trackers() - tracker_entities = [] - for tracker in trackers: - entity = GeoRideTrackerEntity(hass, tracker.tracker_id, georide_context.get_token, - georide_context.get_tracker, tracker) + entities = [] + for coordoned_tracker in coordoned_trackers: + tracker = coordoned_tracker['tracker'] + coordinator = coordoned_tracker['coordinator'] + entity = GeoRideTrackerEntity(coordinator, tracker, hass) + hass.data[GEORIDE_DOMAIN]["devices"][tracker.tracker_id] = coordinator + entities.append(entity) - - hass.data[GEORIDE_DOMAIN]["devices"][tracker.tracker_id] = entity - tracker_entities.append(entity) - - async_add_entities(tracker_entities) + async_add_entities(entities) return True -class GeoRideTrackerEntity(TrackerEntity): +class GeoRideTrackerEntity(CoordinatorEntity, TrackerEntity): """Represent a tracked device.""" - def __init__(self, hass, tracker_id, get_token_callback, get_tracker_callback, tracker): + def __init__(self, coordinator: DataUpdateCoordinator[Mapping[str, Any]], tracker, hass): """Set up GeoRide entity.""" - self._tracker_id = tracker_id - self._get_token_callback = get_token_callback - self._get_tracker_callback = get_tracker_callback + super().__init__(coordinator) self._name = tracker.tracker_name self._tracker = tracker - self.entity_id = DOMAIN + ".{}".format(tracker_id) + self.entity_id = DOMAIN + ".{}".format(tracker.tracker_id) self._hass = hass @property @@ -51,20 +53,21 @@ class GeoRideTrackerEntity(TrackerEntity): @property def name(self): + """ame property""" return self._name @property def latitude(self): """Return latitude value of the device.""" if self._data.latitude: - return self._data.latitude + return self._tracker.latitude return None @property def longitude(self): """Return longitude value of the device.""" if self._data.longitude: - return self._data.longitude + return self._tracker.longitude return None @@ -89,9 +92,9 @@ class GeoRideTrackerEntity(TrackerEntity): """Return the device info.""" return { "name": self.name, - "identifiers": {(GEORIDE_DOMAIN, self._tracker_id)}, + "identifiers": {(GEORIDE_DOMAIN, self._tracker.tracker_id)}, "manufacturer": "GeoRide", - "odometer": "{} km".format(self.tracker.odometer) + "odometer": "{} km".format(self._tracker.odometer) } @property @@ -109,10 +112,4 @@ class GeoRideTrackerEntity(TrackerEntity): def should_poll(self): """No polling needed.""" return True - - async def async_update(self): - """ update the current tracker""" - _LOGGER.debug('update') - self._data = await self._get_tracker_callback(self._tracker_id) - self._name = self.tracker.tracker_name diff --git a/custom_components/georide/sensor.py b/custom_components/georide/sensor.py index d34d18b..44369cc 100644 --- a/custom_components/georide/sensor.py +++ b/custom_components/georide/sensor.py @@ -1,10 +1,15 @@ """ odometter sensor for GeoRide object """ import logging +from typing import Any, Mapping from homeassistant.core import callback from homeassistant.components.switch import SwitchEntity from homeassistant.components.switch import ENTITY_ID_FORMAT +from homeassistant.helpers.update_coordinator import ( + CoordinatorEntity, + DataUpdateCoordinator, +) import georideapilib.api as GeoRideApi @@ -16,37 +21,31 @@ _LOGGER = logging.getLogger(__name__) async def async_setup_entry(hass, config_entry, async_add_entities): # pylint: disable=W0613 """Set up GeoRide tracker based off an entry.""" - georide_context = hass.data[GEORIDE_DOMAIN]["context"] - token = await georide_context.get_token() - if token is None: - return False + georide_context = hass.data[GEORIDE_DOMAIN]["context"] + coordoned_trackers = georide_context.get_coordoned_trackers() - trackers = await hass.async_add_executor_job(GeoRideApi.get_trackers,token) + entities = [] + for coordoned_tracker in coordoned_trackers: + tracker = coordoned_tracker['tracker'] + coordinator = coordoned_tracker['coordinator'] + entity = GeoRideOdometerSensorEntity(coordinator, tracker, hass) + hass.data[GEORIDE_DOMAIN]["devices"][tracker.tracker_id] = coordinator + entities.append(entity) - odometer_switch_entities = [] - for tracker in trackers: - entity = GeoRideOdometerSensorEntity(hass, tracker.tracker_id, georide_context.get_token, - georide_context.get_tracker, data=tracker) - hass.data[GEORIDE_DOMAIN]["devices"][tracker.tracker_id] = entity - odometer_switch_entities.append(entity) - - async_add_entities(odometer_switch_entities) + async_add_entities(entities) return True -class GeoRideOdometerSensorEntity(SwitchEntity): +class GeoRideOdometerSensorEntity(CoordinatorEntity, SwitchEntity): """Represent a tracked device.""" - def __init__(self, hass, tracker_id, get_token_callback, get_tracker_callback, data): - """Set up Georide entity.""" - self._tracker_id = tracker_id - self._data = data or {} - self._get_token_callback = get_token_callback - self._get_tracker_callback = get_tracker_callback - self._name = data.tracker_name + def __init__(self, coordinator: DataUpdateCoordinator[Mapping[str, Any]], tracker, hass): + """Set up GeoRide entity.""" + super().__init__(coordinator) + self._tracker = tracker + self._name = tracker.tracker_name self._unit_of_measurement = "m" - - self.entity_id = ENTITY_ID_FORMAT.format("odometer") + "." + str(tracker_id) + self.entity_id = ENTITY_ID_FORMAT.format("odometer") + "." + str(tracker.tracker_id) self._state = 0 self._hass = hass @@ -54,14 +53,13 @@ class GeoRideOdometerSensorEntity(SwitchEntity): async def async_update(self): """ update the current tracker""" _LOGGER.debug('update') - self._data = await self._get_tracker_callback(self._tracker_id) - self._name = self._data.tracker_name - self._state = self._data.odometer + self._name = self._tracker.tracker_name + self._state = self._tracker.odometer @property def unique_id(self): """Return the unique ID.""" - return self._tracker_id + return self._tracker.tracker_id @property def name(self): @@ -70,10 +68,12 @@ class GeoRideOdometerSensorEntity(SwitchEntity): @property def state(self): + """state property""" return self._state @property def unit_of_measurement(self): + """unit of mesurment property""" return self._unit_of_measurement @property @@ -88,15 +88,15 @@ class GeoRideOdometerSensorEntity(SwitchEntity): @property def icon(self): + """icon getter""" return "mdi:counter" - @property def device_info(self): """Return the device info.""" return { "name": self.name, - "identifiers": {(GEORIDE_DOMAIN, self._tracker_id)}, + "identifiers": {(GEORIDE_DOMAIN, self._tracker.tracker_id)}, "manufacturer": "GeoRide" } diff --git a/custom_components/georide/switch.py b/custom_components/georide/switch.py index c03c3bb..f972f12 100644 --- a/custom_components/georide/switch.py +++ b/custom_components/georide/switch.py @@ -26,21 +26,14 @@ _LOGGER = logging.getLogger(__name__) async def async_setup_entry(hass, config_entry, async_add_entities): # pylint: disable=W0613 """Set up GeoRide tracker based off an entry.""" georide_context = hass.data[GEORIDE_DOMAIN]["context"] - trackers = georide_context.get_trackers() - update_interval = timedelta(seconds=1) + coordoned_trackers = georide_context.get_coordoned_trackers() lock_switch_entities = [] - for tracker in trackers: - coordinator = DataUpdateCoordinator[Mapping[str, Any]]( - hass, - _LOGGER, - name=tracker.tracker_name, - update_method=georide_context.refresh_trackers, - update_interval=update_interval - ) - + for coordoned_tracker in coordoned_trackers: + tracker = coordoned_tracker['tracker'] + coordinator = coordoned_tracker['coordinator'] entity = GeoRideLockSwitchEntity(coordinator, tracker, hass) - hass.data[GEORIDE_DOMAIN]["devices"][tracker.tracker_id] = entity + hass.data[GEORIDE_DOMAIN]["devices"][tracker.tracker_id] = coordinator lock_switch_entities.append(entity) async_add_entities(lock_switch_entities)