From 5ef7f0b592e609775352ad41c3fd656b10f86d24 Mon Sep 17 00:00:00 2001 From: Edi Feschiyan Date: Mon, 9 Mar 2020 15:28:38 +0200 Subject: Writing abstract class, adding geoclue --- abstractaglbaseservice.py | 81 ----------------------------------- aglbaseservice.py | 107 ++++++++++++++++++++++++++++++++++++++++++++++ geoclue.py | 33 ++++++++++++++ 3 files changed, 140 insertions(+), 81 deletions(-) delete mode 100644 abstractaglbaseservice.py create mode 100644 aglbaseservice.py create mode 100644 geoclue.py diff --git a/abstractaglbaseservice.py b/abstractaglbaseservice.py deleted file mode 100644 index d229cc0..0000000 --- a/abstractaglbaseservice.py +++ /dev/null @@ -1,81 +0,0 @@ -from enum import IntEnum -import json -from json import JSONDecodeError -from random import randint -import sys -import asyncio -from random import randint -from websockets import connect -from os import environ -from argparse import ArgumentParser - -import abc -import inspect -# https://stackoverflow.com/questions/47555934/how-require-that-an-abstract-method-is-a-coroutine - -IPADDR = '127.0.0.1' -PORT = '30000' -TOKEN = 'HELLO' -UUID = 'magic' -URL = f'ws://{IPADDR}:{PORT}/api?token={TOKEN}&uuid={UUID}' - -class AFBT(IntEnum): - REQUEST = 2, - RESPONSE = 3, - ERROR = 4, - EVENT = 5 - -msgq = {} - -def addrequest(msgid, msg): - msgq[msgid] = {'request': msg, 'response': None} - -def addresponse(msgid, msg): - if msgid in msgq.keys(): - msgq[msgid]['response'] = msg - -class AbstractAGLBaseService: - def __await__(self): - return self._async_init().__await__() - - async def __aenter__(self): - return self._async_init() - - async def _async_init(self): - self._conn = connect(close_timeout=0, uri=URL, subprotocols=['x-afb-ws-json1']) - self.websocket = await self._conn.__aenter__() - return self - - async def __aexit__(self, *args, **kwargs): - await self._conn.__aexit__(*args, **kwargs) - - async def close(self): - await self._conn.__aexit__(*sys.exc_info()) - - async def send(self, message): - await self.websocket.send(message) - - async def receive(self): - return await self.websocket.recv() - - async def listener(self): - try: - while True: - msg = await self.receive() - print(f"received {msg}") - try: - data = json.loads(msg) - if isinstance(data,list): - if data[0] == AFBT.RESPONSE and str.isnumeric(data[1]): - msgid = int(data[1]) - if msgid in msgq: - addresponse(msgid, data) - - - except JSONDecodeError: - print("not decoding a non-json message") - - except KeyboardInterrupt: - pass - except asyncio.CancelledError: - print("websocket listener coroutine stopped") diff --git a/aglbaseservice.py b/aglbaseservice.py new file mode 100644 index 0000000..3c5f907 --- /dev/null +++ b/aglbaseservice.py @@ -0,0 +1,107 @@ +from enum import IntEnum +import json +from json import JSONDecodeError +from random import randint +import sys +import asyncio +from random import randint +from websockets import connect +from os import environ +from argparse import ArgumentParser + + +IPADDR = '127.0.0.1' +PORT = '30000' +TOKEN = 'HELLO' +UUID = 'magic' +URL = f'ws://{IPADDR}:{PORT}/api?token={TOKEN}&uuid={UUID}' + +class AFBT(IntEnum): + REQUEST = 2, + RESPONSE = 3, + ERROR = 4, + EVENT = 5 + +msgq = {} + +def addrequest(msgid, msg): + msgq[msgid] = {'request': msg, 'response': None} + +def addresponse(msgid, msg): + if msgid in msgq.keys(): + msgq[msgid]['response'] = msg + +class AGLBaseService: + api = None + url = None + ip = None + port = None + token = None + uuid = None + + def __init__(self, api, ip, port, url=None, token='HELLO', uuid='magic'): + self.api = api + self.url = url + self.ip = ip + self.port = port + self.token = token + self.uuid = uuid + + def __await__(self): + return self._async_init().__await__() + + async def __aenter__(self): + return self._async_init() + + async def _async_init(self): + # setting ping_interval to None because AFB does not support websocket ping + # if set to !None, the library will close the socket after the default timeout + URL = f'ws://{self.ip}:{self.port}/api?token={self.token}&uuid={self.uuid}' + self._conn = connect(close_timeout=0, uri=URL, subprotocols=['x-afb-ws-json1'], ping_interval=None) + self.websocket = await self._conn.__aenter__() + return self + + async def __aexit__(self, *args, **kwargs): + await self._conn.__aexit__(*args, **kwargs) + + async def close(self): + await self._conn.__aexit__(*sys.exc_info()) + + async def send(self, message): + await self.websocket.send(message) + + async def receive(self): + return await self.websocket.recv() + + async def listener(self): + try: + while True: + msg = await self.receive() + print(f"Received {msg}") + try: + data = json.loads(msg) + if isinstance(data, list): + if data[0] == AFBT.RESPONSE and str.isnumeric(data[1]): + msgid = int(data[1]) + if msgid in msgq: + addresponse(msgid, data) + + except JSONDecodeError: + print("Not decoding a non-json message") + + except KeyboardInterrupt: + print("Received keyboard interrupt, exiting") + except asyncio.CancelledError: + print("Websocket listener coroutine stopped") + + async def subscribe(self, event): + msgid = randint(0, 999999) + msg = f'["{AFBT.REQUEST}","{msgid}","{self.api}/subscribe",{{"value": "{event}"}}]' + await self.send(msg) + + async def unsubscribe(self, event): + verb = 'unsubscribe' + msgid = randint(0, 999999) + msg = f'[2,"{msgid}","{self.api}/{verb}",{{"value": "{event}"}}]' + addrequest(msgid, msg) + await self.send(msg) diff --git a/geoclue.py b/geoclue.py new file mode 100644 index 0000000..d296397 --- /dev/null +++ b/geoclue.py @@ -0,0 +1,33 @@ +import asyncio +from random import randint +from aglbaseservice import AGLBaseService, AFBT + + +class GeoClueService(AGLBaseService): + def __init__(self): + super().__init__(api='geoclue', ip='192.168.234.202', port='30009') + + async def location(self): + verb = 'location' + msgid = randint(0, 999999) + + await self.send(f'[2,"{msgid}","{self.api}/{verb}",""]') + return await self.receive() + + async def subscribe(self, event='location'): + super().subscribe(event=event) + + async def unsubscribe(self, event='location'): + super().unsubscribe(event=event) + + +async def main(loop): + GCS = await GeoClueService() + print(await GCS.location()) + listener = loop.create_task(GCS.listener()) + await listener + + +if __name__ == '__main__': + loop = asyncio.get_event_loop() + loop.run_until_complete(main(loop)) -- cgit 1.2.3-korg