Centralize update loop

develop
Matthieu DUVAL 4 years ago
parent 093bebc391
commit 0113102a7f

@ -2,6 +2,7 @@
from collections import defaultdict from collections import defaultdict
import logging import logging
from typing import Any, Mapping
from datetime import timedelta from datetime import timedelta
import math import math
import time import time
@ -24,7 +25,10 @@ import homeassistant.helpers.event as ha_event
from homeassistant.setup import async_when_setup from homeassistant.setup import async_when_setup
from homeassistant.helpers.typing import HomeAssistantType from homeassistant.helpers.typing import HomeAssistantType
from homeassistant.helpers.update_coordinator import (
CoordinatorEntity,
DataUpdateCoordinator,
)
from .const import ( from .const import (
CONF_EMAIL, CONF_EMAIL,
@ -88,7 +92,7 @@ async def async_setup_entry(hass, entry):
hass.data[DOMAIN]["context"] = context hass.data[DOMAIN]["context"] = context
# We add trackers to the context # We add trackers to the context
await context.force_refresh_trackers() await context.init_context(hass)
hass.async_create_task( hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, "device_tracker")) hass.config_entries.async_forward_entry_setup(entry, "device_tracker"))
@ -127,6 +131,7 @@ class GeoRideContext:
self._hass = hass self._hass = hass
self._email = email self._email = email
self._password = password self._password = password
self._georide_trackers_coordoned = []
self._georide_trackers = [] self._georide_trackers = []
self._token = token self._token = token
self._socket = None self._socket = None
@ -204,12 +209,14 @@ class GeoRideContext:
async def refresh_trackers(self): async def refresh_trackers(self):
""" here we return last tracker by id""" """ here we return last tracker by id"""
_LOGGER.info("Call refresh tracker") _LOGGER.debug("Call refresh tracker")
epoch_min = math.floor(time.time()/60) epoch_min = math.floor(time.time()/60)
if (epoch_min % MIN_UNTIL_REFRESH) == 0: if (epoch_min % MIN_UNTIL_REFRESH) == 0:
if epoch_min != self._previous_refresh: if epoch_min != self._previous_refresh:
self._previous_refresh = epoch_min self._previous_refresh = epoch_min
await self.force_refresh_trackers() await self.force_refresh_trackers()
else:
_LOGGER.debug("We wil dont refresh the tracker list")
if not self._thread_started: if not self._thread_started:
_LOGGER.info("Start the thread") _LOGGER.info("Start the thread")
@ -235,6 +242,31 @@ class GeoRideContext:
self._georide_trackers.append(refreshed_tracker) 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 @property
def socket(self): def socket(self):
""" hold the GeoRide socket """ """ hold the GeoRide socket """

@ -8,38 +8,27 @@ from typing import Any, Mapping
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.components.binary_sensor import BinarySensorEntity from homeassistant.components.binary_sensor import BinarySensorEntity
from homeassistant.components.binary_sensor import ENTITY_ID_FORMAT from homeassistant.components.binary_sensor import ENTITY_ID_FORMAT
from homeassistant.helpers.update_coordinator import ( from homeassistant.helpers.update_coordinator import (
CoordinatorEntity, CoordinatorEntity,
DataUpdateCoordinator, DataUpdateCoordinator
) )
import georideapilib.api as GeoRideApi import georideapilib.api as GeoRideApi
import georideapilib.objects as GeoRideTracker import georideapilib.objects as GeoRideTracker
from .const import DOMAIN as GEORIDE_DOMAIN from .const import DOMAIN as GEORIDE_DOMAIN
from .const import MIN_UNTIL_REFRESH
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
async def async_setup_entry(hass, config_entry, async_add_entities): # pylint: disable=W0613 async def async_setup_entry(hass, config_entry, async_add_entities): # pylint: disable=W0613
"""Set up GeoRide tracker based off an entry.""" """Set up GeoRide tracker based off an entry."""
georide_context = hass.data[GEORIDE_DOMAIN]["context"] 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)
entities = [] entities = []
for tracker in trackers: coordoned_trackers = georide_context.get_coordoned_trackers()
coordinator = DataUpdateCoordinator[Mapping[str, Any]]( for coordoned_tracker in coordoned_trackers:
hass, tracker = coordoned_tracker['tracker']
_LOGGER, coordinator = coordoned_tracker['coordinator']
name=tracker.tracker_name,
update_method=georide_context.refresh_trackers,
update_interval=update_interval
)
stolen_entity = GeoRideStolenBinarySensorEntity(coordinator, tracker) stolen_entity = GeoRideStolenBinarySensorEntity(coordinator, tracker)
crashed_entity = GeoRideCrashedBinarySensorEntity(coordinator, tracker) crashed_entity = GeoRideCrashedBinarySensorEntity(coordinator, tracker)
entities.append(stolen_entity) 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): class GeoRideBinarySensorEntity(CoordinatorEntity, BinarySensorEntity):
"""Represent a tracked device.""" """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.""" """Set up Georide entity."""
super().__init__(coordinator) super().__init__(coordinator)
self._tracker = tracker self._tracker = tracker
@ -89,8 +79,8 @@ class GeoRideBinarySensorEntity(CoordinatorEntity, BinarySensorEntity):
class GeoRideStolenBinarySensorEntity(GeoRideBinarySensorEntity): class GeoRideStolenBinarySensorEntity(GeoRideBinarySensorEntity):
"""Represent a tracked device.""" """Represent a tracked device."""
def __init__(self, coordinator: DataUpdateCoordinator[Mapping[str, Any]],
def __init__(self, coordinator: DataUpdateCoordinator[Mapping[str, Any]], tracker: GeoRideTracker): tracker: GeoRideTracker):
"""Set up Georide entity.""" """Set up Georide entity."""
super().__init__(coordinator, tracker) super().__init__(coordinator, tracker)
self.entity_id = ENTITY_ID_FORMAT.format("is_stolen") + "." + str(tracker.tracker_id) self.entity_id = ENTITY_ID_FORMAT.format("is_stolen") + "." + str(tracker.tracker_id)
@ -113,7 +103,8 @@ class GeoRideStolenBinarySensorEntity(GeoRideBinarySensorEntity):
class GeoRideCrashedBinarySensorEntity(GeoRideBinarySensorEntity): class GeoRideCrashedBinarySensorEntity(GeoRideBinarySensorEntity):
"""Represent a tracked device.""" """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.""" """Set up Georide entity."""
super().__init__(coordinator, tracker) super().__init__(coordinator, tracker)
self.entity_id = ENTITY_ID_FORMAT.format("is_crashed") + "." + str(tracker.tracker_id) self.entity_id = ENTITY_ID_FORMAT.format("is_crashed") + "." + str(tracker.tracker_id)

@ -1,9 +1,14 @@
""" device tracker for GeoRide object """ """ device tracker for GeoRide object """
import logging import logging
from typing import Any, Mapping
from homeassistant.components.device_tracker.const import DOMAIN, SOURCE_TYPE_GPS from homeassistant.components.device_tracker.const import DOMAIN, SOURCE_TYPE_GPS
from homeassistant.components.device_tracker.config_entry import TrackerEntity from homeassistant.components.device_tracker.config_entry import TrackerEntity
from homeassistant.helpers.update_coordinator import (
CoordinatorEntity,
DataUpdateCoordinator,
)
import georideapilib.api as GeoRideApi 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 async def async_setup_entry(hass, config_entry, async_add_entities): # pylint: disable=W0613
"""Set up Georide tracker based off an entry.""" """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"] entities = []
trackers = georide_context.get_trackers() for coordoned_tracker in coordoned_trackers:
tracker_entities = [] tracker = coordoned_tracker['tracker']
for tracker in trackers: coordinator = coordoned_tracker['coordinator']
entity = GeoRideTrackerEntity(hass, tracker.tracker_id, georide_context.get_token, entity = GeoRideTrackerEntity(coordinator, tracker, hass)
georide_context.get_tracker, tracker) hass.data[GEORIDE_DOMAIN]["devices"][tracker.tracker_id] = coordinator
entities.append(entity)
async_add_entities(entities)
hass.data[GEORIDE_DOMAIN]["devices"][tracker.tracker_id] = entity
tracker_entities.append(entity)
async_add_entities(tracker_entities)
return True return True
class GeoRideTrackerEntity(TrackerEntity): class GeoRideTrackerEntity(CoordinatorEntity, TrackerEntity):
"""Represent a tracked device.""" """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.""" """Set up GeoRide entity."""
self._tracker_id = tracker_id super().__init__(coordinator)
self._get_token_callback = get_token_callback
self._get_tracker_callback = get_tracker_callback
self._name = tracker.tracker_name self._name = tracker.tracker_name
self._tracker = tracker self._tracker = tracker
self.entity_id = DOMAIN + ".{}".format(tracker_id) self.entity_id = DOMAIN + ".{}".format(tracker.tracker_id)
self._hass = hass self._hass = hass
@property @property
@ -51,20 +53,21 @@ class GeoRideTrackerEntity(TrackerEntity):
@property @property
def name(self): def name(self):
"""ame property"""
return self._name return self._name
@property @property
def latitude(self): def latitude(self):
"""Return latitude value of the device.""" """Return latitude value of the device."""
if self._data.latitude: if self._data.latitude:
return self._data.latitude return self._tracker.latitude
return None return None
@property @property
def longitude(self): def longitude(self):
"""Return longitude value of the device.""" """Return longitude value of the device."""
if self._data.longitude: if self._data.longitude:
return self._data.longitude return self._tracker.longitude
return None return None
@ -89,9 +92,9 @@ class GeoRideTrackerEntity(TrackerEntity):
"""Return the device info.""" """Return the device info."""
return { return {
"name": self.name, "name": self.name,
"identifiers": {(GEORIDE_DOMAIN, self._tracker_id)}, "identifiers": {(GEORIDE_DOMAIN, self._tracker.tracker_id)},
"manufacturer": "GeoRide", "manufacturer": "GeoRide",
"odometer": "{} km".format(self.tracker.odometer) "odometer": "{} km".format(self._tracker.odometer)
} }
@property @property
@ -109,10 +112,4 @@ class GeoRideTrackerEntity(TrackerEntity):
def should_poll(self): def should_poll(self):
"""No polling needed.""" """No polling needed."""
return True 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

@ -1,10 +1,15 @@
""" odometter sensor for GeoRide object """ """ odometter sensor for GeoRide object """
import logging import logging
from typing import Any, Mapping
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.components.switch import SwitchEntity from homeassistant.components.switch import SwitchEntity
from homeassistant.components.switch import ENTITY_ID_FORMAT from homeassistant.components.switch import ENTITY_ID_FORMAT
from homeassistant.helpers.update_coordinator import (
CoordinatorEntity,
DataUpdateCoordinator,
)
import georideapilib.api as GeoRideApi 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 async def async_setup_entry(hass, config_entry, async_add_entities): # pylint: disable=W0613
"""Set up GeoRide tracker based off an entry.""" """Set up GeoRide tracker based off an entry."""
georide_context = hass.data[GEORIDE_DOMAIN]["context"] georide_context = hass.data[GEORIDE_DOMAIN]["context"]
token = await georide_context.get_token() coordoned_trackers = georide_context.get_coordoned_trackers()
if token is None:
return False
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 = [] async_add_entities(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)
return True return True
class GeoRideOdometerSensorEntity(SwitchEntity): class GeoRideOdometerSensorEntity(CoordinatorEntity, SwitchEntity):
"""Represent a tracked device.""" """Represent a tracked device."""
def __init__(self, hass, tracker_id, get_token_callback, get_tracker_callback, data): def __init__(self, coordinator: DataUpdateCoordinator[Mapping[str, Any]], tracker, hass):
"""Set up Georide entity.""" """Set up GeoRide entity."""
self._tracker_id = tracker_id super().__init__(coordinator)
self._data = data or {} self._tracker = tracker
self._get_token_callback = get_token_callback self._name = tracker.tracker_name
self._get_tracker_callback = get_tracker_callback
self._name = data.tracker_name
self._unit_of_measurement = "m" self._unit_of_measurement = "m"
self.entity_id = ENTITY_ID_FORMAT.format("odometer") + "." + str(tracker.tracker_id)
self.entity_id = ENTITY_ID_FORMAT.format("odometer") + "." + str(tracker_id)
self._state = 0 self._state = 0
self._hass = hass self._hass = hass
@ -54,14 +53,13 @@ class GeoRideOdometerSensorEntity(SwitchEntity):
async def async_update(self): async def async_update(self):
""" update the current tracker""" """ update the current tracker"""
_LOGGER.debug('update') _LOGGER.debug('update')
self._data = await self._get_tracker_callback(self._tracker_id) self._name = self._tracker.tracker_name
self._name = self._data.tracker_name self._state = self._tracker.odometer
self._state = self._data.odometer
@property @property
def unique_id(self): def unique_id(self):
"""Return the unique ID.""" """Return the unique ID."""
return self._tracker_id return self._tracker.tracker_id
@property @property
def name(self): def name(self):
@ -70,10 +68,12 @@ class GeoRideOdometerSensorEntity(SwitchEntity):
@property @property
def state(self): def state(self):
"""state property"""
return self._state return self._state
@property @property
def unit_of_measurement(self): def unit_of_measurement(self):
"""unit of mesurment property"""
return self._unit_of_measurement return self._unit_of_measurement
@property @property
@ -88,15 +88,15 @@ class GeoRideOdometerSensorEntity(SwitchEntity):
@property @property
def icon(self): def icon(self):
"""icon getter"""
return "mdi:counter" return "mdi:counter"
@property @property
def device_info(self): def device_info(self):
"""Return the device info.""" """Return the device info."""
return { return {
"name": self.name, "name": self.name,
"identifiers": {(GEORIDE_DOMAIN, self._tracker_id)}, "identifiers": {(GEORIDE_DOMAIN, self._tracker.tracker_id)},
"manufacturer": "GeoRide" "manufacturer": "GeoRide"
} }

@ -26,21 +26,14 @@ _LOGGER = logging.getLogger(__name__)
async def async_setup_entry(hass, config_entry, async_add_entities): # pylint: disable=W0613 async def async_setup_entry(hass, config_entry, async_add_entities): # pylint: disable=W0613
"""Set up GeoRide tracker based off an entry.""" """Set up GeoRide tracker based off an entry."""
georide_context = hass.data[GEORIDE_DOMAIN]["context"] georide_context = hass.data[GEORIDE_DOMAIN]["context"]
trackers = georide_context.get_trackers() coordoned_trackers = georide_context.get_coordoned_trackers()
update_interval = timedelta(seconds=1)
lock_switch_entities = [] lock_switch_entities = []
for tracker in trackers: for coordoned_tracker in coordoned_trackers:
coordinator = DataUpdateCoordinator[Mapping[str, Any]]( tracker = coordoned_tracker['tracker']
hass, coordinator = coordoned_tracker['coordinator']
_LOGGER,
name=tracker.tracker_name,
update_method=georide_context.refresh_trackers,
update_interval=update_interval
)
entity = GeoRideLockSwitchEntity(coordinator, tracker, hass) 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) lock_switch_entities.append(entity)
async_add_entities(lock_switch_entities) async_add_entities(lock_switch_entities)

Loading…
Cancel
Save