Add suport for new device beacon, siren control, eco_mode control, better device event

develop
Matthieu DUVAL 3 years ago
parent af12cd70e4
commit adb6cef3c7

@ -40,7 +40,8 @@ from .const import (
TRACKER_ID, TRACKER_ID,
TOKEN_SAFE_DAY, TOKEN_SAFE_DAY,
MIN_UNTIL_REFRESH, 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.config_entries.async_forward_entry_setup(entry, "sensor"))
hass.async_create_task( hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, "binary_sensor")) 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 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, "switch")
await hass.config_entries.async_forward_entry_unload(entry, "sensor") 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, "binary_sensor")
await hass.config_entries.async_forward_entry_unload(entry, "siren")
context = hass.data[DOMAIN]["context"] context = hass.data[DOMAIN]["context"]
@ -133,6 +137,8 @@ class GeoRideContext:
self._email = email self._email = email
self._password = password self._password = password
self._georide_trackers_coordoned = [] self._georide_trackers_coordoned = []
self._georide_trackers_beacon_coordoned = []
self._georide_trackers_beacon = []
self._georide_trackers = [] self._georide_trackers = []
self._token = token self._token = token
self._socket = None self._socket = None
@ -176,7 +182,6 @@ class GeoRideContext:
socket.subscribe_device(self.on_device_callback) socket.subscribe_device(self.on_device_callback)
socket.subscribe_position(self.on_position_callback) socket.subscribe_position(self.on_position_callback)
socket.subscribe_alarm(self.on_alarm_callback) socket.subscribe_alarm(self.on_alarm_callback)
self._socket = socket self._socket = socket
socket.init() socket.init()
@ -208,17 +213,31 @@ class GeoRideContext:
return tracker return tracker
return {} 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): async def refresh_trackers(self):
""" here we return last tracker by id""" """ here we return last tracker by id"""
_LOGGER.debug("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 != 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: for tracker in self._georide_trackers:
# _LOGGER.debug("We wil dont refresh the tracker list") 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): async def force_refresh_trackers(self):
"""Used to refresh the tracker list""" """Used to refresh the tracker list"""
@ -230,16 +249,37 @@ class GeoRideContext:
for tracker in self._georide_trackers: for tracker in self._georide_trackers:
if tracker.tracker_id == refreshed_tracker.tracker_id: if tracker.tracker_id == refreshed_tracker.tracker_id:
tracker.update_all_data(refreshed_tracker) tracker.update_all_data(refreshed_tracker)
if tracker.version > 2:
await force_refresh_trackers_beacon(tracker.tracker_id)
found = True found = True
if not found: if not found:
self._georide_trackers.append(refreshed_tracker) self._georide_trackers.append(refreshed_tracker)
if refreshed_tracker.version > 2:
await force_refresh_trackers_beacon(tracker.tracker_id)
if not self._thread_started: if not self._thread_started:
_LOGGER.info("Start the thread") _LOGGER.info("Start the thread")
# We refresh the tracker list each hours # We refresh the tracker list each hours
self._thread_started = True self._thread_started = True
await self.connect_socket() 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): async def init_context(self, hass):
"""Used to refresh the tracker list""" """Used to refresh the tracker list"""
@ -255,16 +295,37 @@ class GeoRideContext:
update_method=self.refresh_trackers, update_method=self.refresh_trackers,
update_interval=update_interval 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 "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 coordoned trackers"""
return self._georide_trackers_coordoned return self._georide_trackers_coordoned
@property
def georide_trackers_beacon_coordoned(self):
"""Return coordoned trackers"""
return self._georide_trackers_beacon_coordoned
@property @property
def socket(self): def socket(self):
@ -281,7 +342,8 @@ class GeoRideContext:
"""on lock callback""" """on lock callback"""
_LOGGER.info("On lock received") _LOGGER.info("On lock received")
for coordoned_tracker in self._georide_trackers_coordoned: 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'] coordinator = coordoned_tracker['coordinator']
if tracker.tracker_id == data['trackerId']: if tracker.tracker_id == data['trackerId']:
tracker.locked_latitude = data['lockedLatitude'] tracker.locked_latitude = data['lockedLatitude']
@ -289,8 +351,8 @@ class GeoRideContext:
tracker.is_locked = data['isLocked'] tracker.is_locked = data['isLocked']
event_data = { event_data = {
"device_id": tracker.tracker_id, "device_id": tracker_device.unique_id,
"device_name": tracker.tracker_name "device_name": tracker_device.name,
} }
self._hass.bus.async_fire(f"{DOMAIN}_lock_event", event_data) self._hass.bus.async_fire(f"{DOMAIN}_lock_event", event_data)
@ -299,23 +361,21 @@ class GeoRideContext:
).result() ).result()
break break
@callback @callback
def on_device_callback(self, data): def on_device_callback(self, data):
"""on device callback""" """on device callback"""
_LOGGER.info("On device received") _LOGGER.info("On device received")
for coordoned_tracker in self._georide_trackers_coordoned: 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'] coordinator = coordoned_tracker['coordinator']
if tracker.tracker_id == data['trackerId']: if tracker.tracker_id == data['trackerId']:
tracker.status = data['status'] tracker.status = data['status']
event_data = { event_data = {
"device_id": tracker.tracker_id, "device_id": tracker_device.unique_id,
"device_name": tracker.tracker_name, "device_name": tracker_device.name,
} }
self._hass.bus.async_fire(f"{DOMAIN}_device_event", event_data) self._hass.bus.async_fire(f"{DOMAIN}_device_event", event_data)
asyncio.run_coroutine_threadsafe( asyncio.run_coroutine_threadsafe(
coordinator.async_request_refresh(), self._hass.loop coordinator.async_request_refresh(), self._hass.loop
).result() ).result()
@ -326,7 +386,9 @@ class GeoRideContext:
"""on device callback""" """on device callback"""
_LOGGER.info("On alarm received") _LOGGER.info("On alarm received")
for coordoned_tracker in self._georide_trackers_coordoned: 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'] coordinator = coordoned_tracker['coordinator']
if tracker.tracker_id == data['trackerId']: if tracker.tracker_id == data['trackerId']:
if data['name'] == 'vibration': if data['name'] == 'vibration':
@ -355,12 +417,13 @@ class GeoRideContext:
_LOGGER.info("magnetOff detected") _LOGGER.info("magnetOff detected")
elif data['name'] == 'sonorAlarmOn': elif data['name'] == 'sonorAlarmOn':
_LOGGER.info("sonorAlarmOn detected") _LOGGER.info("sonorAlarmOn detected")
tracker.is_siren_on = True
else: else:
_LOGGER.warning("Unmanaged alarm: %s", data["name"]) _LOGGER.warning("Unmanaged alarm: %s", data["name"])
event_data = { event_data = {
"device_id": tracker.tracker_id, "device_id": tracker_device.unique_id,
"device_name": tracker.tracker_name, "device_name": tracker_device.name,
"type": f"alarm_{data['name']}" "type": f"alarm_{data['name']}"
} }
self._hass.bus.async_fire(f"{DOMAIN}_alarm_event", event_data) self._hass.bus.async_fire(f"{DOMAIN}_alarm_event", event_data)
@ -384,8 +447,8 @@ class GeoRideContext:
tracker.fixtime = data['fixtime'] tracker.fixtime = data['fixtime']
event_data = { event_data = {
"device_id": tracker.tracker_id, "device_id": tracker_device.unique_id,
"device_name": tracker.tracker_name "device_name": tracker_device.name,
} }
self._hass.bus.async_fire(f"{DOMAIN}_position_event", event_data) self._hass.bus.async_fire(f"{DOMAIN}_position_event", event_data)
asyncio.run_coroutine_threadsafe( asyncio.run_coroutine_threadsafe(

@ -14,14 +14,14 @@ from homeassistant.helpers.update_coordinator import (
from .const import DOMAIN as GEORIDE_DOMAIN from .const import DOMAIN as GEORIDE_DOMAIN
from .device import Device from .device import Device, DeviceBeacon
_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"]
entities = [] entities = []
coordoned_trackers = georide_context.get_coordoned_trackers() coordoned_trackers = georide_context.georide_trackers_coordoned
for coordoned_tracker in coordoned_trackers: for coordoned_tracker in coordoned_trackers:
tracker_device = coordoned_tracker['tracker_device'] tracker_device = coordoned_tracker['tracker_device']
coordinator = coordoned_tracker['coordinator'] 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(GeoRideNetworkBinarySensorEntity(coordinator, tracker_device))
entities.append(GeoRideMovingBinarySensorEntity(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) async_add_entities(entities, True)
@ -57,6 +65,22 @@ class GeoRideBinarySensorEntity(CoordinatorEntity, BinarySensorEntity):
"""Return the device info.""" """Return the device info."""
return self._tracker_device.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): 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]],
@ -83,7 +107,7 @@ class GeoRideStolenBinarySensorEntity(GeoRideBinarySensorEntity):
@property @property
def name(self): def name(self):
""" GeoRide odometer name """ """ GeoRide odometer name """
return f"{self._name} is stolen" return f"{self._name} is not stolen"
class GeoRideCrashedBinarySensorEntity(GeoRideBinarySensorEntity): class GeoRideCrashedBinarySensorEntity(GeoRideBinarySensorEntity):
@ -132,9 +156,15 @@ class GeoRideActiveSubscriptionBinarySensorEntity(GeoRideBinarySensorEntity):
@property @property
def is_on(self): def is_on(self):
"""state value property""" """state value property"""
if self._tracker_device.tracker.subscription_id is not None: tracker = self._tracker_device.tracker
return True if tracker.is_oldsubscription:
return False 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 @property
def name(self): def name(self):
@ -226,3 +256,32 @@ class GeoRideMovingBinarySensorEntity(GeoRideBinarySensorEntity):
def name(self): def name(self):
""" GeoRide name """ """ GeoRide name """
return f"{self._name} is moving" 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"

@ -10,4 +10,6 @@ TRACKER_ID = "trackerId"
MIN_UNTIL_REFRESH = 10 MIN_UNTIL_REFRESH = 10
SIREN_ACTIVATION_DELAY = 30
TOKEN_SAFE_DAY = 432000 # five days TOKEN_SAFE_DAY = 432000 # five days

@ -1,5 +1,5 @@
"""Home Assistant representation of an GeoRide Tracker device.""" """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 from .const import DOMAIN as GEORIDE_DOMAIN
@ -28,11 +28,15 @@ class Device:
@property @property
def model_name(self) -> str: def model_name(self) -> str:
"""Get the model name.""" """Get the model name."""
name = "GeoRide 1" name = None
if self._tracker.is_old_tracker: if self._tracker.version == 1:
name = "Prototype / GeoRide 1" name = "GeoRide 1"
elif self._tracker.is_second_gen: elif self._tracker.version == 2:
name = "GeoRide 2 / GeoRide 3" name = "GeoRide 2"
elif self._tracker.version == 3:
name = "GeoRide 3"
else:
name = "Prototype / Unknown"
return name return name
@property @property
@ -54,4 +58,53 @@ class Device:
def __str__(self) -> str: def __str__(self) -> str:
"""Get string representation.""" """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}"

@ -20,14 +20,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"]
coordoned_trackers = georide_context.get_coordoned_trackers() coordoned_trackers = georide_context.georide_trackers_coordoned
entities = [] entities = []
for coordoned_tracker in coordoned_trackers: for coordoned_tracker in coordoned_trackers:
tracker_device = coordoned_tracker['tracker_device'] tracker_device = coordoned_tracker['tracker_device']
coordinator = coordoned_tracker['coordinator'] coordinator = coordoned_tracker['coordinator']
entity = GeoRideTrackerEntity(coordinator, tracker_device, hass) 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) entities.append(entity)
async_add_entities(entities) async_add_entities(entities)

@ -6,7 +6,7 @@
"issue_tracker": "https://github.com/ptimatth/GeorideHA/issues", "issue_tracker": "https://github.com/ptimatth/GeorideHA/issues",
"iot_class": "cloud_polling", "iot_class": "cloud_polling",
"requirements": [ "requirements": [
"georideapilib>=0.7.0", "georideapilib>=0.8.0",
"pyjwt==2.1.0" "pyjwt==2.1.0"
], ],
"dependencies": [], "dependencies": [],

@ -21,20 +21,28 @@ _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"]
coordoned_trackers = georide_context.get_coordoned_trackers() coordoned_trackers = georide_context.georide_trackers_coordoned
entities = [] entities = []
for coordoned_tracker in coordoned_trackers: for coordoned_tracker in coordoned_trackers:
tracker_device = coordoned_tracker['tracker_device'] tracker_device = coordoned_tracker['tracker_device']
coordinator = coordoned_tracker['coordinator'] 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(GeoRideOdometerSensorEntity(coordinator, tracker_device, hass))
entities.append(GeoRideOdometerKmSensorEntity(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)) 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 return True
@ -185,7 +193,6 @@ class GeoRideExternalBatterySensorEntity(CoordinatorEntity, SensorEntity):
self._name = tracker_device.tracker.tracker_name self._name = tracker_device.tracker.tracker_name
self._unit_of_measurement = "V" 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.entity_id = f"{ENTITY_ID_FORMAT.format('external_battery_voltage')}.{tracker_device.tracker.tracker_id}"# pylint: disable=C0301
self._state = 0 self._state = 0
@property @property
@ -256,3 +263,46 @@ class GeoRideFixtimeSensorEntity(CoordinatorEntity, SensorEntity):
def device_info(self): def device_info(self):
"""Return the device info.""" """Return the device info."""
return self._tracker_device.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

@ -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

@ -24,17 +24,18 @@ _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"]
coordoned_trackers = georide_context.get_coordoned_trackers() coordoned_trackers = georide_context.georide_trackers_coordoned
lock_switch_entities = [] entities = []
for coordoned_tracker in coordoned_trackers: for coordoned_tracker in coordoned_trackers:
tracker_device = coordoned_tracker['tracker_device'] tracker_device = coordoned_tracker['tracker_device']
coordinator = coordoned_tracker['coordinator'] coordinator = coordoned_tracker['coordinator']
entity = GeoRideLockSwitchEntity(coordinator, tracker_device, hass) hass.data[GEORIDE_DOMAIN]["devices"][tracker_device.unique_id] = coordinator
hass.data[GEORIDE_DOMAIN]["devices"][tracker_device.tracker.tracker_id] = coordinator entities.append(GeoRideLockSwitchEntity(coordinator, tracker_device, hass))
lock_switch_entities.append(entity) 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 return True
@ -105,3 +106,62 @@ class GeoRideLockSwitchEntity(CoordinatorEntity, SwitchEntity):
def device_info(self): def device_info(self):
"""Return the device info.""" """Return the device info."""
return self._tracker_device.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
Loading…
Cancel
Save