""" georide custom conpennt """ from collections import defaultdict import logging from datetime import timedelta import voluptuous as vol import json import jwt from threading import Thread from aiohttp.web import json_response from georideapilib.objects import GeorideAccount import georideapilib.api as GeorideApi from georideapilib.socket import GeorideSocket from homeassistant import config_entries from homeassistant.const import CONF_WEBHOOK_ID from homeassistant.core import callback import homeassistant.helpers.config_validation as cv import homeassistant.helpers.event as ha_event from homeassistant.setup import async_when_setup from .const import ( CONF_EMAIL, CONF_PASSWORD, TRACKER_ID ) DOMAIN = "georide" _LOGGER = logging.getLogger(__name__) CONFIG_SCHEMA = vol.Schema( { vol.Required(DOMAIN, default={}): { vol.Optional(CONF_EMAIL): vol.All(str, vol.Length(min=3)), vol.Optional(CONF_PASSWORD): vol.All(str) } }, extra=vol.ALLOW_EXTRA, ) async def async_setup(hass, config): """Setup Georide component.""" hass.data[DOMAIN] = {"config": config[DOMAIN], "devices": {}, "unsub": None} result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, data={} ) _LOGGER.info("Georide-setup success: %s", result) # Return boolean to indicate that initialization was successful. return True def connect_socket(hass, component): """subscribe to georide socket""" context = hass.data[DOMAIN]["context"] socket = GeorideSocket() socket.subscribe_locked(context.on_lock_callback) socket.subscribe_device(context.on_device_callback) socket.subscribe_position(context.on_position_callback) socket.init() socket.connect(context.async_get_token()) async def async_setup_entry(hass, entry): """Set up Georide entry.""" config = hass.data[DOMAIN]["config"] email = config.get(CONF_EMAIL) or entry.data[CONF_EMAIL] password = config.get(CONF_PASSWORD) or entry.data[CONF_PASSWORD] if email is None or password is None: return False try: account = GeorideApi.get_authorisation_token(email, password) context = GeorideContext( hass, email, password, account.auth_token ) hass.data[DOMAIN]["context"] = context # We add trackers to the context trackers = GeorideApi.get_trackers(account.auth_token) context.georide_trackers = trackers hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, "device_tracker")) hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, "switch")) thread = Thread(target=connect_socket, args=(hass, entry)) thread.start() except: return False return True async def async_unload_entry(hass, entry): """Unload an Georide config entry.""" await hass.config_entries.async_forward_entry_unload(entry, "device_tracker") await hass.config_entries.async_forward_entry_unload(entry, "switch") hass.data[DOMAIN]["unsub"]() return True class GeorideContext: """Hold the current Georide context.""" def __init__(self, hass, email, password, token): """Initialize an Georide context.""" self._hass = hass self._email = email self._password = password self._georide_trackers = defaultdict(set) self._token = token self._pending_msg = [] @property def hass(self): """ hass """ return self._hass @property def email(self): """ current email """ return self._email @property def password(self): """ password """ return self._password @property def token(self): """ current jwt token """ return self._token @property def georide_trackers(self): """ georide tracker list """ return self._georide_trackers @georide_trackers.setter def georide_trackers(self, trackers): """ georide tracker list """ self._georide_trackers = trackers @callback def async_get_token(self): """ here we return the current valid tocken, TODO: add here token expiration control""" jwt_data = jwt.decode(self._token, verify=False) exp_timestamp = jwt_data['exp'] _LOGGER.info("Token exp data: %s", exp_timestamp) return self._token @callback def async_get_tracker(self, tracker_id): """ here we return last tracker by id""" for tracker in self._georide_trackers: if tracker.tracker_id == tracker_id: return tracker return None @callback def async_see(self, **data): """Send a see message to the device tracker.""" _LOGGER.info("sync_see") self._pending_msg.append(data) @callback def on_lock_callback(self, data): """on lock callback""" _LOGGER.info("On lock received") for tracker in self._georide_trackers: if tracker.tracker_id == data['trackerId']: tracker.locked_latitude = data['lockedLatitude'] tracker.locked_longitude = data['lockedLongitude'] tracker.is_locked = data['isLocked'] return @callback def on_device_callback(self, data): """on device callback""" _LOGGER.info("On device received") for tracker in self._georide_trackers: if tracker.tracker_id == data['trackerId']: tracker.status = data['status'] return @callback def on_position_callback(self, data): """on position callback""" _LOGGER.info("On position received") for tracker in self._georide_trackers: if tracker.tracker_id == data['trackerId']: tracker.latitude = data['latitude'] tracker.longitude = data['longitude'] tracker.moving = data['moving'] tracker.speed = data['speed'] tracker.fixtime = data['fixtime'] return