diff options
author | Edi Feschiyan <edi.feschiyan@konsulko.com> | 2020-04-28 12:20:48 +0300 |
---|---|---|
committer | Edi Feschiyan <edi.feschiyan@konsulko.com> | 2020-04-28 12:21:31 +0300 |
commit | 9da1c8647b233e3a591cc313ebfdac6745806f6d (patch) | |
tree | 1a606d3d4883515b422d6bb9a9c94e8150344da4 | |
parent | 7519a78657685f14f93983f474d75ae0efb4a2ad (diff) |
Refactored bluetooth
-rw-r--r-- | aglbaseservice.py | 73 | ||||
-rw-r--r-- | bluetooth.py | 82 |
2 files changed, 75 insertions, 80 deletions
diff --git a/aglbaseservice.py b/aglbaseservice.py index fb905ca..8c4814b 100644 --- a/aglbaseservice.py +++ b/aglbaseservice.py @@ -1,16 +1,17 @@ -from enum import IntEnum -import json from json import JSONDecodeError +from parse import Result, parse +from websockets import connect from random import randint -import sys +from enum import IntEnum +from typing import Union +import asyncssh +import argparse import asyncio -from random import randint -from websockets import connect import logging -import asyncssh +import json +import sys +import os import re -from parse import Result, parse -from typing import Union logging.getLogger('AGLBaseService') logging.basicConfig(level=logging.DEBUG) @@ -22,7 +23,6 @@ class AFBT(IntEnum): EVENT = 5 msgq = {} -# TODO : Replace prints with logging def addrequest(msgid, msg): msgq[msgid] = {'request': msg, 'response': None} @@ -32,14 +32,29 @@ def addresponse(msgid, msg): msgq[msgid]['response'] = msg class AGLBaseService: - api = None - url = None - ip = None + api: str + url: str + ip : str port = None - token = None - uuid = None + token: str + uuid: str service = None - logger = None + logger = logging.getLogger(service) + + @staticmethod + def getparser(): + parser = argparse.ArgumentParser(description='Utility to interact with agl-service-gps via it\'s websocket') + parser.add_argument('-l', '--loglevel', help='Level of logging verbosity', default='INFO', + choices=list(logging._nameToLevel.keys())) + parser.add_argument('ipaddr', default=os.environ.get('AGL_TGT_IP', 'localhost'), help='AGL host address') + parser.add_argument('--port', default=os.environ.get('AGL_TGT_PORT', None), help=f'AGL service websocket port') + parser.add_argument('--listener', default=False, help='Register a listener for incoming events', action='store_true') + parser.add_argument('--subscribe', type=str, help='Subscribe to event type', metavar='event') + parser.add_argument('--unsubscribe', type=str, help='Unsubscribe from event type', metavar='event') + parser.add_argument('--json', type=str, help='Send your own json string') + parser.add_argument('--verb', type=str, help='Send the json above to specific verb') + parser.add_argument('--api', type=str, help='Send the above two to a specific api') + return parser def __init__(self, api: str, ip: str, port: str = None, url: str = None, token: str = 'HELLO', uuid: str = 'magic', service: str = None): @@ -66,7 +81,7 @@ class AGLBaseService: if serviceport is not None: self.port = serviceport else: - self.logger('Unable to find port') + self.logger.error('Unable to find port') exit(1) URL = f'ws://{self.ip}:{self.port}/api?token={self.token}&uuid={self.uuid}' @@ -98,11 +113,11 @@ class AGLBaseService: logging.warning(f'Service {servicename.stdout.strip()} is stopped') return None else: - logging.debug(f'Service PID: {str(pid)}') + self.logger.debug(f'Service PID: {str(pid)}') sockets = await c.run(f'find /proc/{pid}/fd/ | xargs readlink | grep socket') inodes = frozenset(re.findall('socket:\[(.*)\]', sockets.stdout)) - logging.debug(f"Socket inodes: {inodes}") + self.logger.debug(f"Socket inodes: {inodes}") procnettcp = await c.run('cat /proc/net/tcp') fieldsstr = '{sl}: {local_address} {rem_address} {st} {tx_queue}:{rx_queue} {tr}:{tmwhen} {retrnsmt} {uid}'\ @@ -125,17 +140,19 @@ class AGLBaseService: _, port = tuple(parse('{}:{}', s['local_address'])) port = int(port, 16) if port >= 30000: # the port is above 30000 range, 8080 is some kind of proxy - logging.debug(f'Service running at port {port}') + self.logger.debug(f'Service running at port {port}') return port - async def listener(self): + async def listener(self, stdout: bool = False): try: while True: msg = await self.receive() - # self.logger.debug(f"Received websocket{msg}") try: data = json.loads(msg) + self.logger.debug('[AGL] -> ' + msg) if isinstance(data, list): + if stdout: + print(data) if data[0] == AFBT.RESPONSE and str.isnumeric(data[1]): msgid = int(data[1]) if msgid in msgq: @@ -145,11 +162,11 @@ class AGLBaseService: self.logger.warning("Not decoding a non-json message") except KeyboardInterrupt: - logging.debug("Received keyboard interrupt, exiting") + self.logger.debug("Received keyboard interrupt, exiting") except asyncio.CancelledError: - logging.warning("Websocket listener coroutine stopped") + self.logger.warning("Websocket listener coroutine stopped") except Exception as e: - logging.error("Unhandled seal: " + str(e)) + self.logger.error("Unhandled seal: " + str(e)) async def request(self, verb: str, values: Union[str, dict] = "", msgid: int = randint(0, 9999999), waitresponse: bool = False): @@ -159,8 +176,8 @@ class AGLBaseService: if waitresponse: return await self.receive() - async def subscribe(self, event): - await self.request('subscribe', {'value': f'{event}'}) + async def subscribe(self, event, waitresponse=False): + await self.request('subscribe', {'value': f'{event}'}, waitresponse=waitresponse) - async def unsubscribe(self, event): - await self.request('unsubscribe', {'value': f'{event}'}) + async def unsubscribe(self, event, waitresponse=False): + await self.request('unsubscribe', {'value': f'{event}'}, waitresponse=waitresponse) diff --git a/bluetooth.py b/bluetooth.py index 95aa51d..caef235 100644 --- a/bluetooth.py +++ b/bluetooth.py @@ -1,24 +1,22 @@ +from aglbaseservice import AGLBaseService import asyncio -import json import os -from random import randint -from aglbaseservice import AGLBaseService -import logging Verbs = ['subscribe', 'unsubscribe', 'managed_objects', 'adapter_state', 'default_adapter', 'avrcp_controls', 'connect', 'disconnect', 'pair', 'cancel_pairing', 'confirm_pairing', 'remove_device'] AdapterStateParams = ['discovery', 'discoverable', 'powered', ] BTEventType = ['adapter_changes', 'device_changes', 'media', 'agent'] + class BluetoothService(AGLBaseService): def __init__(self, ip, port=None, service='agl-service-bluetooth'): super().__init__(api='Bluetooth-Manager', ip=ip, port=port, service=service) - async def subscribe(self, event='device_changes'): + async def subscribe(self, event='device_changes', waitresponse=False): await super().subscribe(event=event) - async def unsubscribe(self, event='device_changes'): + async def unsubscribe(self, event='device_changes', waitresponse=False): await super().unsubscribe(event=event) async def managed_objects(self, waitresponse=False): @@ -32,58 +30,38 @@ class BluetoothService(AGLBaseService): p = {**p, **value} return await self.request('adapter_state', p, waitresponse=waitresponse) - if waitresponse: - return await self.request('adapter_state', p) - else: - await self.request('adapter_state', p) - - async def default_adapter(self): - verb = 'default_adapter' - msgid = randint(0, 999999) - msg = f'[2,"{msgid}","{self.api}/{verb}",""]' - # print(msg) - await self.send(msg) - return await self.receive() + + async def default_adapter(self, waitresponse=False): + return await self.request('default_adapter', "", waitresponse=waitresponse) + + async def connect(self, device: str = 'hci0', waitresponse=False): + return await self.request('connect', {'device': device}, waitresponse=waitresponse) + + async def disconnect(self, device: str = 'hci0', waitresponse=False): + return await self.request('disconnect', {'device': device}, waitresponse=waitresponse) + + async def pair(self, device, waitresponse=False): + return await self.request('pair', {'device': device}, waitresponse=waitresponse) + + async def cancel_pairing(self, waitresponse=False): + return await self.request('cancel_pairing', waitresponse=waitresponse) + + async def confirm_pairing(self, pincode, waitresponse=False): + return await self.request('confirm_pairing', {'pincode': pincode}, waitresponse=waitresponse) async def avrcp_controls(self): pass - async def connect(self, device): - verb = 'connect' - msgid = randint(0, 999999) - d = {'device': device} - msg = f'[2,"{msgid}","{self.api}/{verb}","{json.dumps(d)}"]' - - async def disconnect(self, device): - verb = 'disconnect' - msgid = randint(0, 999999) - d = {'device': device} - msg = f'[2,"{msgid}","{self.api}/{verb}","{json.dumps(d)}"]' - - async def pair(self, device): - verb = 'pair' - msgid = randint(0, 999999) - d = {'device': device} - msg = f'[2,"{msgid}","{self.api}/{verb}","{json.dumps(d)}"]' - - async def cancel_pairing(self): - verb = 'cancel_pairing' - msgid = randint(0, 999999) - msg = f'[2,"{msgid}","{self.api}/{verb}",""]' - - async def confirm_pairing(self, pincode): - verb = 'confirm_pairing' - msgid = randint(0, 999999) - d = {'pincode': pincode} - msg = f'[2,"{msgid}","{self.api}/{verb}","{json.dumps(d)}"]' - async def main(loop): addr = os.environ.get('AGL_TGT_IP', 'localhost') - #port = os.environ.get('AGL_TGT_PORT', '30005') - - BTS = await BluetoothService(ip=addr, port=port) - print(await BTS.adapter_state('hci1', {'uuids': ['0000110e-0000-1000-8000-00805f9b34fb']})) - + port = os.environ.get('AGL_TGT_PORT', None) + BTS = await BluetoothService(ip=addr, service='agl-service-bluetooth', port=port) + listener = loop.create_task(BTS.listener()) + await BTS.subscribe() + BTS.logger.debug(await BTS.adapter_state('hci0', {'uuids': ['0000110e-0000-1000-8000-00805f9b34fb']})) + await listener + + if __name__ == '__main__': loop = asyncio.get_event_loop() loop.run_until_complete(main(loop))
\ No newline at end of file |