aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--aglbaseservice.py33
-rw-r--r--bluetooth.py2
-rw-r--r--gps.py14
-rw-r--r--mediaplayer.py24
-rw-r--r--requirements.txt18
5 files changed, 73 insertions, 18 deletions
diff --git a/aglbaseservice.py b/aglbaseservice.py
index 8c4814b..ff35df4 100644
--- a/aglbaseservice.py
+++ b/aglbaseservice.py
@@ -12,6 +12,7 @@ import json
import sys
import os
import re
+from contextlib import asynccontextmanager
logging.getLogger('AGLBaseService')
logging.basicConfig(level=logging.DEBUG)
@@ -31,6 +32,7 @@ def addresponse(msgid, msg):
if msgid in msgq.keys():
msgq[msgid]['response'] = msg
+
class AGLBaseService:
api: str
url: str
@@ -85,7 +87,7 @@ class AGLBaseService:
exit(1)
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._conn = connect(close_timeout=0, uri=URL, subprotocols=['x-afb-ws-json1'], ping_interval=None, timeout=2)
self.websocket = await self._conn.__aenter__()
return self
@@ -102,7 +104,11 @@ class AGLBaseService:
return await self.websocket.recv()
async def portfinder(self):
+ # TODO:handle ssh timeouts, asyncssh does not support it apparently, and connect returns context_manager which
+ # cannot be used with asyncio.wait_for
+
async with asyncssh.connect(self.ip, username='root') as c:
+
servicename = await c.run(f"systemctl --all | grep {self.service}-- | awk '{{print $1}}'", check=False)
if self.service not in servicename.stdout:
logging.error(f"Service matching pattern - '{self.service}' - NOT FOUND")
@@ -168,6 +174,31 @@ class AGLBaseService:
except Exception as e:
self.logger.error("Unhandled seal: " + str(e))
+ async def response(self, stdout: bool = False):
+ try:
+ msg = await self.websocket.recv()
+ try:
+ data = json.loads(msg)
+ yield data
+ 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:
+ addresponse(msgid, data)
+ yield data
+ except JSONDecodeError:
+ self.logger.warning("Not decoding a non-json message")
+
+ except KeyboardInterrupt:
+ self.logger.debug("Received keyboard interrupt, exiting")
+ except asyncio.CancelledError:
+ self.logger.warning("Websocket listener coroutine stopped")
+ except Exception as 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):
l = json.dumps([AFBT.REQUEST, str(msgid), f'{self.api}/{verb}', values])
diff --git a/bluetooth.py b/bluetooth.py
index caef235..a28bc3c 100644
--- a/bluetooth.py
+++ b/bluetooth.py
@@ -64,4 +64,4 @@ async def main(loop):
if __name__ == '__main__':
loop = asyncio.get_event_loop()
- loop.run_until_complete(main(loop)) \ No newline at end of file
+ loop.run_until_complete(main(loop))
diff --git a/gps.py b/gps.py
index 82f1545..2fd1c36 100644
--- a/gps.py
+++ b/gps.py
@@ -2,6 +2,8 @@ from aglbaseservice import AGLBaseService
import asyncio
import os
+from concurrent import futures
+xc = futures.ThreadPoolExecutor(1)
class GPSService(AGLBaseService):
service = 'agl-service-gps'
@@ -25,10 +27,20 @@ async def main(loop):
args = GPSService.parser.parse_args()
gpss = await GPSService(args.ipaddr)
+ r = await loop.run_in_executor(xc, gpss.response)
+
if args.loglevel:
GPSService.logger.setLevel(args.loglevel)
if args.location:
- print(await gpss.location(waitresponse=True))
+ await gpss.location()
+ async for response in r:
+ await gpss.location()
+ print(await r.__anext__())
+
+
+ # loc = await l
+ # print(loc)
+
if args.subscribe:
await gpss.subscribe(args.subscribe)
diff --git a/mediaplayer.py b/mediaplayer.py
index e7059b6..b916dd8 100644
--- a/mediaplayer.py
+++ b/mediaplayer.py
@@ -1,8 +1,6 @@
-import os
-import asyncio
-import json
-
from aglbaseservice import AGLBaseService
+import asyncio
+import os
class MediaPlayerService(AGLBaseService):
@@ -13,19 +11,15 @@ class MediaPlayerService(AGLBaseService):
super().__init__(api='mediaplayer', ip=ip, port=port, service='agl-service-mediaplayer')
async def playlist(self, waitresponse=False):
- if waitresponse:
- return await self.request('playlist', waitresponse=waitresponse)
- else:
- await self.request('playlist')
+ return await self.request('playlist', waitresponse=waitresponse)
- async def subscribe(self, event='metadata'):
- await super().subscribe(event=event)
+ async def subscribe(self, event='metadata', waitresponse=False):
+ await super().subscribe(event=event, waitresponse=waitresponse)
- async def unsubscribe(self, event='metadata'):
- await super().subscribe(event=event)
+ async def unsubscribe(self, event='metadata', waitresponse=False):
+ await super().subscribe(event=event, waitresponse=waitresponse)
- async def control(self, name, value=None):
- verb = 'controls'
+ async def control(self, name, value=None, waitresponse=False):
loopstate = ['off', 'playlist', 'track']
controls = {
'play': None,
@@ -59,7 +53,7 @@ class MediaPlayerService(AGLBaseService):
assert value in loopstate, f'Tried to set invalid loopstate - {value}, use "off", "playlist" or "track"'
msg = {'value': name, controls[name]: str(value)}
- await self.request(verb, msg)
+ await self.request('controls', msg, waitresponse=waitresponse)
async def main(loop):
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..3d1f9db
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,18 @@
+asyncssh==2.2.0
+attrs==19.3.0
+cffi==1.14.0
+cryptography==2.8
+importlib-metadata==1.6.0
+more-itertools==8.2.0
+packaging==20.3
+parse==1.15.0
+pluggy==0.13.1
+py==1.8.1
+pycparser==2.20
+pyparsing==2.4.7
+pytest==5.4.1
+pytest-asyncio==0.11.0
+six==1.14.0
+wcwidth==0.1.9
+websockets==8.1
+zipp==3.1.0