You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
GeoRideHA/custom_components/georide/__init__.py

220 lines
6.0 KiB

""" 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}
hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, data={}
)
)
_LOGGER.info("Georide-setup ")
# 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
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()
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