diff options
author | Edi Feschiyan <edi.feschiyan@konsulko.com> | 2020-08-17 20:46:01 +0300 |
---|---|---|
committer | Edi Feschiyan <efeschiyan@pm.me> | 2020-08-17 20:46:01 +0300 |
commit | 2e70875bb3f52fd8ebd231c04a7864699cf14f41 (patch) | |
tree | 36c13b3997b653ce03a2dcf6401aedb964f5b794 | |
parent | baae23ba3271b8f5c053c6a8e0a7ef9562d355f2 (diff) |
bluetooth.py and test_bluetooth.py - adding missing avrcp_controls support and test
mediascanner.py - adding missing agl service mediascanner support and tests
test_network.py - adding missing scan_services test
adding base service and tests files for signal_composer and can_low
-rw-r--r-- | pyagl/conftest.py | 2 | ||||
-rw-r--r-- | pyagl/pytest.ini | 3 | ||||
-rw-r--r-- | pyagl/services/base.py | 1 | ||||
-rw-r--r-- | pyagl/services/bluetooth.py | 5 | ||||
-rw-r--r-- | pyagl/services/can.py | 21 | ||||
-rw-r--r-- | pyagl/services/mediaplayer.py | 3 | ||||
-rw-r--r-- | pyagl/services/mediascanner.py | 52 | ||||
-rw-r--r-- | pyagl/services/signal_composer.py | 38 | ||||
-rw-r--r-- | pyagl/tests/test_bluetooth.py | 33 | ||||
-rw-r--r-- | pyagl/tests/test_mediascanner.py | 49 | ||||
-rw-r--r-- | pyagl/tests/test_network.py | 15 | ||||
-rw-r--r-- | pyagl/tests/test_signal_composer.py | 24 |
12 files changed, 229 insertions, 17 deletions
diff --git a/pyagl/conftest.py b/pyagl/conftest.py index 2176354..25cdb02 100644 --- a/pyagl/conftest.py +++ b/pyagl/conftest.py @@ -14,7 +14,7 @@ def lava_result_convert(pytest_outcome): elif pytest_outcome == 'xfailed': return 'pass' else: - return'fail' + return 'fail' def pytest_report_teststatus(config, report): diff --git a/pyagl/pytest.ini b/pyagl/pytest.ini index 217ef9a..db7257a 100644 --- a/pyagl/pytest.ini +++ b/pyagl/pytest.ini @@ -13,3 +13,6 @@ markers = nfc: agl-service-nfc tests gps: agl-service-gps tests weather: agl-service-weather tests + mediascanner: agl-service-mediascanner tests + sigcomp: agl-service-signal-composer tests + can: agl-service-can-low-level tests diff --git a/pyagl/services/base.py b/pyagl/services/base.py index 39443a1..17dddb8 100644 --- a/pyagl/services/base.py +++ b/pyagl/services/base.py @@ -189,7 +189,6 @@ class AGLBaseService: procnettcp = check_output('cat /proc/net/tcp'.encode(), shell=True) procnettcp = procnettcp.decode().splitlines()[1:] - self.logger.debug(procnettcp) else: async with asyncssh.connect(self.ip, username='root') as c: diff --git a/pyagl/services/bluetooth.py b/pyagl/services/bluetooth.py index 7e413b3..309ff93 100644 --- a/pyagl/services/bluetooth.py +++ b/pyagl/services/bluetooth.py @@ -50,7 +50,6 @@ class BluetoothService(AGLBaseService): else: return await self.request('default_adapter') - async def connect(self, device: str = 'hci0'): return await self.request('connect', {'device': device}) @@ -69,8 +68,8 @@ class BluetoothService(AGLBaseService): async def remove_device(self, device): return await self.request('remove_device', {'device': device}) - async def avrcp_controls(self): - pass + async def avrcp_controls(self, action): + return await self.request('avrcp_controls', {'action': action}) async def main(loop): args = BluetoothService.parser.parse_args() diff --git a/pyagl/services/can.py b/pyagl/services/can.py new file mode 100644 index 0000000..f345c92 --- /dev/null +++ b/pyagl/services/can.py @@ -0,0 +1,21 @@ +from pyagl.services.base import AGLBaseService, AFBResponse +import asyncio +import os + + +class CANService(AGLBaseService): + service = 'service-can-low' + parser = AGLBaseService.getparser() + + def __init__(self, ip, port=None, service='service-can-low'): + super().__init__(api='signal-composer', ip=ip, port=port, service=service) + # more init stuff specific to the new service + + +async def main(loop): + args = CANService.parser.parse_args() + svc = await CANService(args.ipaddr) + +if __name__ == '__main__': + loop = asyncio.get_event_loop() + loop.run_until_complete(main(loop)) diff --git a/pyagl/services/mediaplayer.py b/pyagl/services/mediaplayer.py index 31f49dd..2157e02 100644 --- a/pyagl/services/mediaplayer.py +++ b/pyagl/services/mediaplayer.py @@ -29,6 +29,7 @@ class MediaPlayerService(AGLBaseService): parser.add_argument('--volume', help='Volume control - <1-100>', metavar='int') parser.add_argument('--loop', help='Set loop state - <off/track/playlist>', metavar='string') parser.add_argument('--avrcp', help='AVRCP Controls') + def __await__(self): return super()._async_init().__await__() @@ -65,7 +66,7 @@ class MediaPlayerService(AGLBaseService): if name in ['play', 'pause', 'previous', 'next']: msg = {'value': name} elif name in ['seek', 'fast-forward', 'rewind']: - #assert value > 0, "Tried to seek with negative integer" + # assert value > 0, "Tried to seek with negative integer" msg = {'value': name, controls[name]: str(value)} elif name == 'pick-track': assert type(value) is int, "Try picking a song with an integer" diff --git a/pyagl/services/mediascanner.py b/pyagl/services/mediascanner.py new file mode 100644 index 0000000..615b5a9 --- /dev/null +++ b/pyagl/services/mediascanner.py @@ -0,0 +1,52 @@ +from pyagl.services.base import AGLBaseService, AFBResponse +import asyncio +import os + +verbs = ['subscribe', 'unsubscribe', 'media_result'] + + +class MediaScannerService(AGLBaseService): + service = 'service-mediascanner' + parser = AGLBaseService.getparser() + parser.add_argument('--media_result', help='Query media_results verb', action='store_true') + + def __init__(self, ip, port=None, service='service-mediascanner'): + super().__init__(api='mediascanner', ip=ip, port=port, service=service) + # more init stuff specific to the new service + + async def media_result(self): + return await self.request('media_result') + + async def subscribe(self, event='media_added'): + return await super().subscribe(event) + + async def unsubscribe(self, event='media_added'): + return await super().unsubscribe(event) + + +async def main(loop): + args = MediaScannerService.parser.parse_args() + svc = await MediaScannerService(args.ipaddr) + + if args.media_result: + msgid = await svc.media_result() + print(f'Sent media_result request with msgid {msgid}') + print(await svc.afbresponse()) + + if args.subscribe: + for event in args.subscribe: + msgid = await svc.subscribe(event) + print(f"Subscribed for event {event} with messageid {msgid}") + r = await svc.afbresponse() + print(r) + + if args.unsubscribe: + for event in args.subscribe: + msgid = await svc.subscribe(event) + print(f"Subscribed for event {event} with messageid {msgid}") + r = await svc.afbresponse() + print(r) + +if __name__ == '__main__': + loop = asyncio.get_event_loop() + loop.run_until_complete(main(loop)) diff --git a/pyagl/services/signal_composer.py b/pyagl/services/signal_composer.py new file mode 100644 index 0000000..2b0c4a6 --- /dev/null +++ b/pyagl/services/signal_composer.py @@ -0,0 +1,38 @@ +from pyagl.services.base import AGLBaseService, AFBResponse +import asyncio +import os + +verbs = ['subscribe', 'unsubscribe', 'get', 'addObjects', 'list'] + + +class SignalComposerService(AGLBaseService): + service = 'service-signal-composer' + parser = AGLBaseService.getparser() + + def __init__(self, ip, port=None, service='service-signal-composer'): + super().__init__(api='signal-composer', ip=ip, port=port, service=service) + # more init stuff specific to the new service + + async def subscribe(self, event): + return await super().subscribe(event) + + async def unsubscribe(self, event): + return await super().unsubscribe(event) + + async def addObjects(self, objects): + return await self.request('addObjects', objects) + + async def get(self, values): + return await self.request('get', values) + + async def list(self): + return await self.request('list') + + +async def main(loop): + args = SignalComposerService.parser.parse_args() + svc = await SignalComposerService(args.ipaddr) + +if __name__ == '__main__': + loop = asyncio.get_event_loop() + loop.run_until_complete(main(loop)) diff --git a/pyagl/tests/test_bluetooth.py b/pyagl/tests/test_bluetooth.py index 5f9232f..2ae4287 100644 --- a/pyagl/tests/test_bluetooth.py +++ b/pyagl/tests/test_bluetooth.py @@ -150,6 +150,7 @@ async def test_pairing_verb(event_loop, service: BTS, btaddr): @pytest.mark.hwrequired @pytest.mark.bluetooth +@pytest.mark.dependency async def test_connect_verb(event_loop, service: BTS, btaddr): msgid = await service.connect(btaddr) resp = await service.afbresponse() @@ -159,27 +160,39 @@ async def test_connect_verb(event_loop, service: BTS, btaddr): @pytest.mark.hwrequired @pytest.mark.bluetooth -async def test_disconnect_verb(event_loop, service: BTS, btaddr): - msgid = await service.disconnect(btaddr) +@pytest.mark.xfail(reason='This is expected to fail because there has to be an ongoing pairing attempt') +async def test_confirm_pairing_verb(event_loop, service: BTS, btaddr): + msgid = await service.confirm_pairing(pincode='123456') resp = await service.afbresponse() assert msgid == resp.msgid - assert resp.status == 'success', f'disconnect verb failed - {resp.info}' + assert resp.status == 'success', f'confirm_pairing verb failed - {resp.info}' @pytest.mark.hwrequired @pytest.mark.bluetooth -async def test_remove_pairing_verb(event_loop, service: BTS, btaddr): - msgid = await service.remove_device(btaddr) +@pytest.mark.dependency(depends=['test_connect_verb']) +async def test_avrcp_controls(event_loop, service: BTS): + avrcp_actions = ['Play', 'Pause', 'Stop', 'Next', 'Previous'] + for a in avrcp_actions: + msgid = await service.avrcp_controls(a) + resp = await service.afbresponse() + assert msgid == resp.msgid + assert resp.status == 'success', f'avrcp_control verb failed with action {a} - {resp.info}' + + +@pytest.mark.hwrequired +@pytest.mark.bluetooth +async def test_disconnect_verb(event_loop, service: BTS, btaddr): + msgid = await service.disconnect(btaddr) resp = await service.afbresponse() assert msgid == resp.msgid - assert resp.status == 'success' + assert resp.status == 'success', f'disconnect verb failed - {resp.info}' @pytest.mark.hwrequired @pytest.mark.bluetooth -@pytest.mark.xfail(reason='This is expected to fail because there has to be an ongoing pairing attempt') -async def test_confirm_pairing_verb(event_loop, service: BTS, btaddr): - msgid = await service.confirm_pairing(pincode='123456') +async def test_remove_pairing_verb(event_loop, service: BTS, btaddr): + msgid = await service.remove_device(btaddr) resp = await service.afbresponse() assert msgid == resp.msgid - assert resp.status == 'success', f'confirm_pairing verb failed - {resp.info}' + assert resp.status == 'success' diff --git a/pyagl/tests/test_mediascanner.py b/pyagl/tests/test_mediascanner.py new file mode 100644 index 0000000..33ef004 --- /dev/null +++ b/pyagl/tests/test_mediascanner.py @@ -0,0 +1,49 @@ +import asyncio +import os +import pytest +import logging +from pyagl.services.base import AFBResponse, AFBT +from pyagl.services.mediascanner import MediaScannerService as mss + +pytestmark = pytest.mark.asyncio +events = ['media_added', 'media_removed'] + +@pytest.fixture(scope='module') +def event_loop(): + loop = asyncio.get_event_loop() + yield loop + + +@pytest.fixture(scope='module') +async def service(): + address = os.environ.get('AGL_TGT_IP', 'localhost') + port = os.environ.get('AGL_TGT_PORT', None) + ns = await mss(ip=address, port=port) + yield ns + await ns.websocket.close() + + +@pytest.mark.regular +@pytest.mark.mediascanner +async def test_media_result(event_loop, service: mss): + msgid = await service.media_result() + resp = await service.afbresponse() + assert resp.status == 'success' + + +@pytest.mark.regular +@pytest.mark.mediascanner +async def test_subscribe(event_loop, service: mss): + for e in events: + msgid = await service.subscribe(e) + resp = await service.afbresponse() + assert resp.status == 'success' + + +@pytest.mark.regular +@pytest.mark.mediascanner +async def test_unsubscribe(event_loop, service: mss): + for e in events: + msgid = await service.unsubscribe(e) + resp = await service.afbresponse() + assert resp.status == 'success' diff --git a/pyagl/tests/test_network.py b/pyagl/tests/test_network.py index 7efce11..5ac2630 100644 --- a/pyagl/tests/test_network.py +++ b/pyagl/tests/test_network.py @@ -52,6 +52,17 @@ async def test_global_offline(event_loop, service: NS): @pytest.mark.network @pytest.mark.regular +async def test_scan_services(event_loop, service: NS, expected_available_techs): + scannable_techs = ['wifi', 'bluetooth'] + for t in scannable_techs: + if t in expected_available_techs: + msgid = service.scan_services(technology=t) + resp = await service.afbresponse() + assert resp.status == 'success', f'scan_services failed for technology {t} - {resp.info}' + + +@pytest.mark.network +@pytest.mark.regular async def test_global_online(event_loop, service: NS): msgid = await service.offline(False) resp = await service.afbresponse() @@ -117,7 +128,9 @@ async def test_disable_wifi_tethering(event_loop, service: NS, expected_availabl resp = await service.afbresponse() assert resp.status == 'success', resp.info -# + +#@pytest.mark.network +#@pytest.mark.regular # async def test_set_property(event_loop, service: NS, expected_available_techs): # for t in expected_available_techs: # msgid = await service.set_property(t, {'tethering': True}) diff --git a/pyagl/tests/test_signal_composer.py b/pyagl/tests/test_signal_composer.py new file mode 100644 index 0000000..9e294a0 --- /dev/null +++ b/pyagl/tests/test_signal_composer.py @@ -0,0 +1,24 @@ +import asyncio +import os +import pytest +import logging +from pyagl.services.base import AFBResponse, AFBT +from pyagl.services.signal_composer import SignalComposerService as scs + +pytestmark = pytest.mark.asyncio + + +@pytest.fixture(scope='module') +def event_loop(): + loop = asyncio.get_event_loop() + yield loop + + +@pytest.fixture(scope='module') +async def service(): + address = os.environ.get('AGL_TGT_IP', 'localhost') + port = os.environ.get('AGL_TGT_PORT', None) + ns = await scs(ip=address, port=port) + yield ns + await ns.websocket.close() + |