diff --git a/custom_components/georide/__init__.py b/custom_components/georide/__init__.py index 0a830e4..d6d0190 100644 --- a/custom_components/georide/__init__.py +++ b/custom_components/georide/__init__.py @@ -40,7 +40,8 @@ from .const import ( TRACKER_ID, TOKEN_SAFE_DAY, MIN_UNTIL_REFRESH, - DOMAIN + DOMAIN, + SIREN_ACTIVATION_DELAY ) @@ -105,6 +106,8 @@ async def async_setup_entry(hass, entry): hass.config_entries.async_forward_entry_setup(entry, "sensor")) hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, "binary_sensor")) + hass.async_create_task( + hass.config_entries.async_forward_entry_setup(entry, "siren")) return True @@ -115,6 +118,7 @@ async def async_unload_entry(hass, entry): await hass.config_entries.async_forward_entry_unload(entry, "switch") await hass.config_entries.async_forward_entry_unload(entry, "sensor") await hass.config_entries.async_forward_entry_unload(entry, "binary_sensor") + await hass.config_entries.async_forward_entry_unload(entry, "siren") context = hass.data[DOMAIN]["context"] @@ -133,6 +137,8 @@ class GeoRideContext: self._email = email self._password = password self._georide_trackers_coordoned = [] + self._georide_trackers_beacon_coordoned = [] + self._georide_trackers_beacon = [] self._georide_trackers = [] self._token = token self._socket = None @@ -176,7 +182,6 @@ class GeoRideContext: socket.subscribe_device(self.on_device_callback) socket.subscribe_position(self.on_position_callback) socket.subscribe_alarm(self.on_alarm_callback) - self._socket = socket socket.init() @@ -208,17 +213,31 @@ class GeoRideContext: return tracker return {} + async def get_tracker_beacon(self, beacon_id): + """ here we return last tracker_beacon by id""" + for tracker_beacon in self._georide_trackers_beacon: + if tracker_beacon.beacon_id == beacon_id: + return tracker_beacon + return {} + + async def get_tracker_beacon_by_tracker_id(self, tracker_id): + """ here we return last tracker_beacon by id""" + for tracker_beacon in self._georide_trackers_beacon: + if tracker_beacon.linked_tracker_id == tracker_id: + return tracker_beacon + return {} + async def refresh_trackers(self): """ here we return last tracker by id""" _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") - + for tracker in self._georide_trackers: + if tracker.is_siren_on: + if time.time() - SIREN_ACTIVATION_DELAY > tracker.siren_last_on_date: + tracker.is_siren_on = False async def force_refresh_trackers(self): """Used to refresh the tracker list""" @@ -230,16 +249,37 @@ class GeoRideContext: for tracker in self._georide_trackers: if tracker.tracker_id == refreshed_tracker.tracker_id: tracker.update_all_data(refreshed_tracker) + if tracker.version > 2: + await force_refresh_trackers_beacon(tracker.tracker_id) found = True if not found: self._georide_trackers.append(refreshed_tracker) + if refreshed_tracker.version > 2: + await force_refresh_trackers_beacon(tracker.tracker_id) + if not self._thread_started: _LOGGER.info("Start the thread") # We refresh the tracker list each hours self._thread_started = True await self.connect_socket() - + async def force_refresh_trackers_beacon(self, tracker_id): + """Used to refresh the tracker list""" + _LOGGER.info("Tracker beacon refresh") + new_georide_tracker_beacon = await self._hass.async_add_executor_job(GeoRideApi.get_tracker_beacon, + await self.get_token(), tracker_id) + found = False + for tracker_beacon in self._georide_trackers_beacon: + if tracker_beacon.tracker_id == new_georide_tracker_beacon.beacon_id: + tracker_beacon.update_all_data(new_georide_tracker_beacon) + found = True + if not found: + self._georide_trackers_beacon.append(new_georide_tracker_beacon) + if not self._thread_started: + _LOGGER.info("Start the thread") + # We refresh the tracker list each hours + self._thread_started = True + await self.connect_socket() async def init_context(self, hass): """Used to refresh the tracker list""" @@ -255,16 +295,37 @@ class GeoRideContext: update_method=self.refresh_trackers, update_interval=update_interval ) - self._georide_trackers_coordoned.append({ - "tracker_device": Device(tracker), + + coordoned_tracker = { + "tracker_device": Device(tracker), + "coordinator": coordinator + } + if tracker.version > 2: + tracker_beacon = await get_tracker_beacon_by_tracker_id(tracker.tracker_id) + beacon_coordinator = DataUpdateCoordinator[Mapping[str, Any]]( + hass, + _LOGGER, + name=tracker_beacon.name + ) + coordoned_beacon = { + "beacon_device": DeviceBeacon(tracker_beacon), "coordinator": coordinator - }) + } + self._georide_trackers_beacon_coordoned(coordoned_beacon) + self._georide_trackers_coordoned.append(coordoned_tracker) - def get_coordoned_trackers(self): + @property + def georide_trackers_coordoned(self): """Return coordoned trackers""" return self._georide_trackers_coordoned + + @property + def georide_trackers_beacon_coordoned(self): + """Return coordoned trackers""" + + return self._georide_trackers_beacon_coordoned @property def socket(self): @@ -281,7 +342,8 @@ class GeoRideContext: """on lock callback""" _LOGGER.info("On lock received") for coordoned_tracker in self._georide_trackers_coordoned: - tracker = coordoned_tracker['tracker_device'].tracker + tracker_device = coordoned_tracker['tracker_device'] + tracker = tracker_device.tracker coordinator = coordoned_tracker['coordinator'] if tracker.tracker_id == data['trackerId']: tracker.locked_latitude = data['lockedLatitude'] @@ -289,8 +351,8 @@ class GeoRideContext: tracker.is_locked = data['isLocked'] event_data = { - "device_id": tracker.tracker_id, - "device_name": tracker.tracker_name + "device_id": tracker_device.unique_id, + "device_name": tracker_device.name, } self._hass.bus.async_fire(f"{DOMAIN}_lock_event", event_data) @@ -299,23 +361,21 @@ class GeoRideContext: ).result() break - @callback def on_device_callback(self, data): """on device callback""" _LOGGER.info("On device received") for coordoned_tracker in self._georide_trackers_coordoned: - tracker = coordoned_tracker['tracker_device'].tracker + tracker_device = coordoned_tracker['tracker_device'] + tracker = tracker_device.tracker coordinator = coordoned_tracker['coordinator'] if tracker.tracker_id == data['trackerId']: tracker.status = data['status'] - event_data = { - "device_id": tracker.tracker_id, - "device_name": tracker.tracker_name, + "device_id": tracker_device.unique_id, + "device_name": tracker_device.name, } self._hass.bus.async_fire(f"{DOMAIN}_device_event", event_data) - asyncio.run_coroutine_threadsafe( coordinator.async_request_refresh(), self._hass.loop ).result() @@ -326,7 +386,9 @@ class GeoRideContext: """on device callback""" _LOGGER.info("On alarm received") for coordoned_tracker in self._georide_trackers_coordoned: - tracker = coordoned_tracker['tracker_device'].tracker + tracker_device = coordoned_tracker['tracker_device'] + tracker = tracker_device.tracker + coordinator = coordoned_tracker['coordinator'] if tracker.tracker_id == data['trackerId']: if data['name'] == 'vibration': @@ -355,12 +417,13 @@ class GeoRideContext: _LOGGER.info("magnetOff detected") elif data['name'] == 'sonorAlarmOn': _LOGGER.info("sonorAlarmOn detected") + tracker.is_siren_on = True else: _LOGGER.warning("Unmanaged alarm: %s", data["name"]) event_data = { - "device_id": tracker.tracker_id, - "device_name": tracker.tracker_name, + "device_id": tracker_device.unique_id, + "device_name": tracker_device.name, "type": f"alarm_{data['name']}" } self._hass.bus.async_fire(f"{DOMAIN}_alarm_event", event_data) @@ -384,8 +447,8 @@ class GeoRideContext: tracker.fixtime = data['fixtime'] event_data = { - "device_id": tracker.tracker_id, - "device_name": tracker.tracker_name + "device_id": tracker_device.unique_id, + "device_name": tracker_device.name, } self._hass.bus.async_fire(f"{DOMAIN}_position_event", event_data) asyncio.run_coroutine_threadsafe( diff --git a/custom_components/georide/binary_sensor.py b/custom_components/georide/binary_sensor.py index a733420..623bd4c 100644 --- a/custom_components/georide/binary_sensor.py +++ b/custom_components/georide/binary_sensor.py @@ -14,14 +14,14 @@ from homeassistant.helpers.update_coordinator import ( from .const import DOMAIN as GEORIDE_DOMAIN -from .device import Device +from .device import Device, DeviceBeacon _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"] entities = [] - coordoned_trackers = georide_context.get_coordoned_trackers() + coordoned_trackers = georide_context.georide_trackers_coordoned for coordoned_tracker in coordoned_trackers: tracker_device = coordoned_tracker['tracker_device'] coordinator = coordoned_tracker['coordinator'] @@ -33,7 +33,15 @@ async def async_setup_entry(hass, config_entry, async_add_entities): # pylint: d entities.append(GeoRideNetworkBinarySensorEntity(coordinator, tracker_device)) entities.append(GeoRideMovingBinarySensorEntity(coordinator, tracker_device)) - hass.data[GEORIDE_DOMAIN]["devices"][tracker_device.tracker.tracker_id] = coordinator + hass.data[GEORIDE_DOMAIN]["devices"][tracker_device.unique_id] = coordinator + + coordoned_beacons = georide_context.georide_trackers_beacon_coordoned + for coordoned_beacon in coordoned_beacons: + tracker_beacon = coordoned_tracker['tracker_beacon'] + coordinator = coordoned_tracker['coordinator'] + entities.append(GeoRideBeaconUpdatedBinarySensorEntity(coordinator, tracker_beacon)) + hass.data[GEORIDE_DOMAIN]["devices"][tracker_beacon.unique_id] = coordinator + async_add_entities(entities, True) @@ -57,6 +65,22 @@ class GeoRideBinarySensorEntity(CoordinatorEntity, BinarySensorEntity): """Return the device info.""" return self._tracker_device.device_info +class GeoRideBeaconBinarySensorEntity(CoordinatorEntity, BinarySensorEntity): + """Represent a tracked device.""" + def __init__(self, coordinator: DataUpdateCoordinator[Mapping[str, Any]], + tracker_device_beacon: DeviceBeacon): + """Set up Georide entity.""" + super().__init__(coordinator) + self._tracker_device_beacon = tracker_device_beacon + self._name = tracker_device_beacon.beacon.name + self.entity_id = f"{ENTITY_ID_FORMAT.format('binary_sensor')}.{tracker_device.beacon.beacon_id}"# pylint: disable=C0301 + self._is_on = False + + @property + def device_info(self): + """Return the device info.""" + return self._tracker_device.device_info + class GeoRideStolenBinarySensorEntity(GeoRideBinarySensorEntity): """Represent a tracked device.""" def __init__(self, coordinator: DataUpdateCoordinator[Mapping[str, Any]], @@ -83,7 +107,7 @@ class GeoRideStolenBinarySensorEntity(GeoRideBinarySensorEntity): @property def name(self): """ GeoRide odometer name """ - return f"{self._name} is stolen" + return f"{self._name} is not stolen" class GeoRideCrashedBinarySensorEntity(GeoRideBinarySensorEntity): @@ -132,9 +156,15 @@ class GeoRideActiveSubscriptionBinarySensorEntity(GeoRideBinarySensorEntity): @property def is_on(self): """state value property""" - if self._tracker_device.tracker.subscription_id is not None: - return True - return False + tracker = self._tracker_device.tracker + if tracker.is_oldsubscription: + if .tracker.subscription_id is not None: + return True + return False + else: + if tracker.subscription is not None and tracker.subscription.subscription_id is not None: + return True + return False @property def name(self): @@ -226,3 +256,32 @@ class GeoRideMovingBinarySensorEntity(GeoRideBinarySensorEntity): def name(self): """ GeoRide name """ return f"{self._name} is moving" + +class GeoRideBeaconUpdatedBinarySensorEntity(GeoRideBeaconBinarySensorEntity): + """Represent a tracked device.""" + + def __init__(self, coordinator: DataUpdateCoordinator[Mapping[str, Any]], + tracker_beacon_device: DeviceBeacon): + """Set up Georide entity.""" + super().__init__(coordinator, tracker_device) + self.entity_id = f"{ENTITY_ID_FORMAT.format('update')}.{tracker_beacon_device.tracker_beacon.beacon_id}"# pylint: disable=C0301 + + @property + def unique_id(self): + """Return the unique ID.""" + return f"update_{self._tracker_beacon_device.beacon.beacon_id}" + + @property + def device_class(self): + """Return the device class.""" + return "update" + + @property + def is_on(self): + """state value property""" + return not self._tracker_beacon_device.beacon.is_updated + + @property + def name(self): + """ GeoRide name """ + return f"{self._name} have an update" \ No newline at end of file diff --git a/custom_components/georide/const.py b/custom_components/georide/const.py index abe697b..03e11ee 100644 --- a/custom_components/georide/const.py +++ b/custom_components/georide/const.py @@ -10,4 +10,6 @@ TRACKER_ID = "trackerId" MIN_UNTIL_REFRESH = 10 +SIREN_ACTIVATION_DELAY = 30 + TOKEN_SAFE_DAY = 432000 # five days diff --git a/custom_components/georide/device.py b/custom_components/georide/device.py index b3137e9..cc3821b 100644 --- a/custom_components/georide/device.py +++ b/custom_components/georide/device.py @@ -1,5 +1,5 @@ """Home Assistant representation of an GeoRide Tracker device.""" -import georideapilib.objects as GeoRideTracker +import georideapilib.objects as GeoRideTracker, GeoRideTrackerBeacon from .const import DOMAIN as GEORIDE_DOMAIN @@ -28,11 +28,15 @@ class Device: @property def model_name(self) -> str: """Get the model name.""" - name = "GeoRide 1" - if self._tracker.is_old_tracker: - name = "Prototype / GeoRide 1" - elif self._tracker.is_second_gen: - name = "GeoRide 2 / GeoRide 3" + name = None + if self._tracker.version == 1: + name = "GeoRide 1" + elif self._tracker.version == 2: + name = "GeoRide 2" + elif self._tracker.version == 3: + name = "GeoRide 3" + else: + name = "Prototype / Unknown" return name @property @@ -54,4 +58,53 @@ class Device: def __str__(self) -> str: """Get string representation.""" - return f"GeoRide Device: {self.name}::{self.model_name}::self.unique_id" + return f"GeoRide Device: {self.name}::{self.model_name}::{self.unique_id}" + +class DeviceBeacon: + """Home Assistant representation of a GeoRide Tracker device.""" + + def __init__(self, beacon): + """Initialize GeoRideTracker device.""" + self._beacon: GeoRideTrackerBeacon = beacon + + @property + def beacon(self): + """return the tracker beacon""" + return self._beacon + + @property + def name(self) -> str: + """Get the name.""" + return self._beacon.name + + @property + def manufacturer(self) -> str: + """Get the manufacturer.""" + return "GeoRide" + + @property + def model_name(self) -> str: + """Get the model name.""" + name = "GeoRide Beacon" + return name + + @property + def device_info(self): + """Return the device info.""" + return { + "name": self.name, + "identifiers": {(GEORIDE_DOMAIN, self._beacon.beacon_id)}, + "manufacturer": "GeoRide", + "model": self.model_name, + "suggested_area": "Garage" + } + + + @property + def unique_id(self) -> str: + """Get the unique id.""" + return {(GEORIDE_DOMAIN, "beacon", self._beacon.beacon_id)} + + def __str__(self) -> str: + """Get string representation.""" + return f"GeoRide Device: {self.name}::{self.model_name}::{self.unique_id}" \ No newline at end of file diff --git a/custom_components/georide/device_tracker.py b/custom_components/georide/device_tracker.py index 8a5fc03..73ac313 100644 --- a/custom_components/georide/device_tracker.py +++ b/custom_components/georide/device_tracker.py @@ -20,14 +20,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"] - coordoned_trackers = georide_context.get_coordoned_trackers() + coordoned_trackers = georide_context.georide_trackers_coordoned entities = [] for coordoned_tracker in coordoned_trackers: tracker_device = coordoned_tracker['tracker_device'] coordinator = coordoned_tracker['coordinator'] entity = GeoRideTrackerEntity(coordinator, tracker_device, hass) - hass.data[GEORIDE_DOMAIN]["devices"][tracker_device.tracker.tracker_id] = coordinator + hass.data[GEORIDE_DOMAIN]["devices"][tracker_device.unique_id] = coordinator entities.append(entity) async_add_entities(entities) diff --git a/custom_components/georide/manifest.json b/custom_components/georide/manifest.json index 800ea0d..0c3bf1d 100644 --- a/custom_components/georide/manifest.json +++ b/custom_components/georide/manifest.json @@ -6,7 +6,7 @@ "issue_tracker": "https://github.com/ptimatth/GeorideHA/issues", "iot_class": "cloud_polling", "requirements": [ - "georideapilib>=0.7.0", + "georideapilib>=0.8.0", "pyjwt==2.1.0" ], "dependencies": [], diff --git a/custom_components/georide/sensor.py b/custom_components/georide/sensor.py index d02f732..818ef46 100644 --- a/custom_components/georide/sensor.py +++ b/custom_components/georide/sensor.py @@ -21,20 +21,28 @@ _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() + coordoned_trackers = georide_context.georide_trackers_coordoned entities = [] for coordoned_tracker in coordoned_trackers: tracker_device = coordoned_tracker['tracker_device'] coordinator = coordoned_tracker['coordinator'] - hass.data[GEORIDE_DOMAIN]["devices"][tracker_device.tracker.tracker_id] = coordinator + hass.data[GEORIDE_DOMAIN]["devices"][tracker_device.unique_id] = coordinator entities.append(GeoRideOdometerSensorEntity(coordinator, tracker_device, hass)) entities.append(GeoRideOdometerKmSensorEntity(coordinator, tracker_device, hass)) - entities.append(GeoRideInternalBatterySensorEntity(coordinator, tracker_device)) - entities.append(GeoRideExternalBatterySensorEntity(coordinator, tracker_device)) entities.append(GeoRideFixtimeSensorEntity(coordinator, tracker_device)) + if tracker_device.tracker.version > 2: + entities.append(GeoRideInternalBatterySensorEntity(coordinator, tracker_device)) + entities.append(GeoRideExternalBatterySensorEntity(coordinator, tracker_device)) + + coordoned_beacons = georide_context.georide_trackers_beacon_coordoned + for coordoned_beacon in coordoned_beacons: + tracker_beacon = coordoned_tracker['tracker_beacon'] + coordinator = coordoned_tracker['coordinator'] + entities.append(GeoRideBeaconUpdatedBinarySensorEntity(coordinator, tracker_beacon)) + hass.data[GEORIDE_DOMAIN]["devices"][tracker_beacon.unique_id] = coordinator - async_add_entities(entities) + await async_add_entities(entities) return True @@ -185,7 +193,6 @@ class GeoRideExternalBatterySensorEntity(CoordinatorEntity, SensorEntity): self._name = tracker_device.tracker.tracker_name self._unit_of_measurement = "V" self.entity_id = f"{ENTITY_ID_FORMAT.format('external_battery_voltage')}.{tracker_device.tracker.tracker_id}"# pylint: disable=C0301 - self._state = 0 @property @@ -256,3 +263,46 @@ class GeoRideFixtimeSensorEntity(CoordinatorEntity, SensorEntity): def device_info(self): """Return the device info.""" return self._tracker_device.device_info + +class GeoRideBeaconBatterySensorEntity(CoordinatorEntity, SensorEntity): + """Represent a tracked device.""" + + def __init__(self, coordinator: DataUpdateCoordinator[Mapping[str, Any]], + tracker_beacon:DeviceBeacon): + """Set up GeoRide entity.""" + super().__init__(coordinator) + self._tracker_device = tracker_device + self._name = tracker_device.tracker.tracker_name + self._unit_of_measurement = "%" + self.entity_id = f"{ENTITY_ID_FORMAT.format('battery_percent')}.{tracker_beacon.beacon.beacon_id}"# pylint: disable=C0301 + self._state = 0 + + @property + def unique_id(self): + """Return the unique ID.""" + return f"battery_percent_{self._tracker_device.beacon.beacon_id}" + + @property + def state(self): + """state property""" + return self._tracker_device.beacon.battery_level + + @property + def unit_of_measurement(self): + """unit of mesurment property""" + return self._unit_of_measurement + + @property + def name(self): + """ GeoRide internal_battery_voltage name """ + return f"{self._name} battery percent" + + @property + def icon(self): + """icon getter""" + return "mdi:battery" + + @property + def device_info(self): + """Return the device info.""" + return self._tracker_device.device_info \ No newline at end of file diff --git a/custom_components/georide/siren.py b/custom_components/georide/siren.py new file mode 100644 index 0000000..16c23fd --- /dev/null +++ b/custom_components/georide/siren.py @@ -0,0 +1,91 @@ +""" device tracker for GeoRide object """ + +import logging + + +from typing import Any, Mapping + +from homeassistant.components.siren import SirenEntity +from homeassistant.components.siren import ENTITY_ID_FORMAT + +from homeassistant.helpers.update_coordinator import ( + CoordinatorEntity, + DataUpdateCoordinator, +) + +import georideapilib.api as GeoRideApi + +from .const import DOMAIN as GEORIDE_DOMAIN +from .device import Device + +_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.georide_trackers_coordoned + + entities = [] + for coordoned_tracker in coordoned_trackers: + tracker_device = coordoned_tracker['tracker_device'] + coordinator = coordoned_tracker['coordinator'] + hass.data[GEORIDE_DOMAIN]["devices"][tracker_device.unique_id] = coordinator + if tracker_device.tracker.version > 2: + entities.append(GeoRideSirenEntity(coordinator, tracker_device, hass)) + + await async_add_entities(entities) + + return True + +class GeoRideSirenEntity(CoordinatorEntity, SirenEntity): + """Represent a tracked device.""" + + def __init__(self, coordinator: DataUpdateCoordinator[Mapping[str, Any]], + tracker_device:Device, hass): + """Set up GeoRide entity.""" + super().__init__(coordinator) + self._tracker_device = tracker_device + self._name = tracker_device.tracker.tracker_name + self.entity_id = f"{ENTITY_ID_FORMAT.format('eco_mode')}.{tracker_device.tracker.tracker_id}"# pylint: disable=C0301 + self._hass = hass + + async def async_turn_on(self, **kwargs): + """ lock the GeoRide tracker """ + _LOGGER.info('async_turn_on eco %s', kwargs) + georide_context = self._hass.data[GEORIDE_DOMAIN]["context"] + token = await georide_context.get_token() + success = await self._hass.async_add_executor_job(GeoRideApi.change_tracker_siren_state, + token, self._tracker_device.tracker.tracker_id, True) + if success: + self._tracker_device.tracker.is_siren_on = True + + async def async_turn_off(self, **kwargs): + """ unlock the GeoRide tracker """ + _LOGGER.info('async_turn_off eco %s', kwargs) + georide_context = self._hass.data[GEORIDE_DOMAIN]["context"] + token = await georide_context.get_token() + success = await self._hass.async_add_executor_job(GeoRideApi.change_tracker_siren_state, + token, self._tracker_device.tracker.tracker_id, False) + if success: + self._tracker_device.tracker.is_siren_on = False + + @property + def unique_id(self): + """Return the unique ID.""" + return f"siren_{self._tracker_device.tracker.tracker_id}" + + @property + def name(self): + """ GeoRide odometer name """ + return f"{self._name} siren" + + @property + def is_on(self): + """ GeoRide switch status """ + return self._tracker_device.tracker.is_siren_on + + @property + def device_info(self): + """Return the device info.""" + return self._tracker_device.device_info \ No newline at end of file diff --git a/custom_components/georide/switch.py b/custom_components/georide/switch.py index 79f0a0b..191cafd 100644 --- a/custom_components/georide/switch.py +++ b/custom_components/georide/switch.py @@ -24,17 +24,18 @@ _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() + coordoned_trackers = georide_context.georide_trackers_coordoned - lock_switch_entities = [] + entities = [] for coordoned_tracker in coordoned_trackers: tracker_device = coordoned_tracker['tracker_device'] coordinator = coordoned_tracker['coordinator'] - entity = GeoRideLockSwitchEntity(coordinator, tracker_device, hass) - hass.data[GEORIDE_DOMAIN]["devices"][tracker_device.tracker.tracker_id] = coordinator - lock_switch_entities.append(entity) + hass.data[GEORIDE_DOMAIN]["devices"][tracker_device.unique_id] = coordinator + entities.append(GeoRideLockSwitchEntity(coordinator, tracker_device, hass)) + if tracker_device.tracker.version > 2: + entities.append(GeoRideEcoModeSwitchEntity(coordinator, tracker_device, hass)) - async_add_entities(lock_switch_entities) + async_add_entities(entities) return True @@ -105,3 +106,62 @@ class GeoRideLockSwitchEntity(CoordinatorEntity, SwitchEntity): def device_info(self): """Return the device info.""" return self._tracker_device.device_info + +class GeoRideEcoModeSwitchEntity(CoordinatorEntity, SwitchEntity): + """Represent a tracked device.""" + + def __init__(self, coordinator: DataUpdateCoordinator[Mapping[str, Any]], + tracker_device:Device, hass): + """Set up GeoRide entity.""" + super().__init__(coordinator) + self._tracker_device = tracker_device + self._name = tracker_device.tracker.tracker_name + self.entity_id = f"{ENTITY_ID_FORMAT.format('eco_mode')}.{tracker_device.tracker.tracker_id}"# pylint: disable=C0301 + self._hass = hass + + async def async_turn_on(self, **kwargs): + """ lock the GeoRide tracker """ + _LOGGER.info('async_turn_on eco %s', kwargs) + georide_context = self._hass.data[GEORIDE_DOMAIN]["context"] + token = await georide_context.get_token() + success = await self._hass.async_add_executor_job(GeoRideApi.change_tracker_eco_mode_state, + token, self._tracker_device.tracker.tracker_id, True) + if success: + self._tracker_device.tracker.is_in_eco = True + + async def async_turn_off(self, **kwargs): + """ unlock the GeoRide tracker """ + _LOGGER.info('async_turn_off eco %s', kwargs) + georide_context = self._hass.data[GEORIDE_DOMAIN]["context"] + token = await georide_context.get_token() + success = await self._hass.async_add_executor_job(GeoRideApi.change_tracker_eco_mode_state, + token, self._tracker_device.tracker.tracker_id, False) + if success: + self._tracker_device.tracker.is_in_eco = False + + @property + def unique_id(self): + """Return the unique ID.""" + return f"eco_mode_{self._tracker_device.tracker.tracker_id}" + + @property + def name(self): + """ GeoRide odometer name """ + return f"{self._name} eco mode" + + @property + def is_on(self): + """ GeoRide switch status """ + return self._tracker_device.tracker.is_in_eco + + @property + def icon(self): + """return the entity icon""" + if self._tracker_device.tracker.is_in_eco: + return "mdi:battery-heart-variant" + return "mdi:battery" + + @property + def device_info(self): + """Return the device info.""" + return self._tracker_device.device_info \ No newline at end of file