From 3c8e6b4cbb68af197865f17777405856a5d36690 Mon Sep 17 00:00:00 2001 From: Andrey Pohilko Date: Mon, 30 Jul 2018 12:51:11 +0300 Subject: [PATCH] Refactor --- pylgbst/__init__.py | 8 +- pylgbst/comms.py | 190 ------------------ pylgbst/comms/__init__.py | 190 ++++++++++++++++++ pylgbst/{comms_gatt.py => comms/cgatt.py} | 0 .../{comms_gattlib.py => comms/cgattlib.py} | 0 pylgbst/{comms_pygatt.py => comms/cpygatt.py} | 0 tests/test_gatt.py | 2 +- tests/test_pygatt.py | 2 +- 8 files changed, 196 insertions(+), 196 deletions(-) create mode 100644 pylgbst/comms/__init__.py rename pylgbst/{comms_gatt.py => comms/cgatt.py} (100%) rename pylgbst/{comms_gattlib.py => comms/cgattlib.py} (100%) rename pylgbst/{comms_pygatt.py => comms/cpygatt.py} (100%) diff --git a/pylgbst/__init__.py b/pylgbst/__init__.py index 3edca7c..59601e6 100644 --- a/pylgbst/__init__.py +++ b/pylgbst/__init__.py @@ -7,25 +7,25 @@ log = logging.getLogger('pylgbst') def get_connection_bluegiga(controller=None, hub_mac=None): - from pylgbst.comms_pygatt import BlueGigaConnection + from pylgbst.comms.cpygatt import BlueGigaConnection return BlueGigaConnection().connect(hub_mac) def get_connection_gattool(controller='hci0', hub_mac=None): - from pylgbst.comms_pygatt import GattoolConnection + from pylgbst.comms.cpygatt import GattoolConnection return GattoolConnection(controller).connect(hub_mac) def get_connection_gatt(controller='hci0', hub_mac=None): - from pylgbst.comms_gatt import GattConnection + from pylgbst.comms.cgatt import GattConnection return GattConnection(controller).connect(hub_mac) def get_connection_gattlib(controller='hci0', hub_mac=None): - from pylgbst.comms_gattlib import GattLibConnection + from pylgbst.comms.cgattlib import GattLibConnection return GattLibConnection(controller).connect(hub_mac) diff --git a/pylgbst/comms.py b/pylgbst/comms.py index 567c0a9..e69de29 100644 --- a/pylgbst/comms.py +++ b/pylgbst/comms.py @@ -1,190 +0,0 @@ -""" -This package holds communication aspects -""" -import binascii -import json -import logging -import socket -import traceback -from abc import abstractmethod -from binascii import unhexlify -from threading import Thread - -from pylgbst.constants import MSG_DEVICE_SHUTDOWN, ENABLE_NOTIFICATIONS_HANDLE, ENABLE_NOTIFICATIONS_VALUE -from pylgbst.utilities import str2hex - -log = logging.getLogger('comms') - -LEGO_MOVE_HUB = "LEGO Move Hub" - - -class Connection(object): - def connect(self, hub_mac=None): - pass - - def disconnect(self): - pass - - @abstractmethod - def write(self, handle, data): - pass - - @abstractmethod - def set_notify_handler(self, handler): - pass - - def enable_notifications(self): - self.write(ENABLE_NOTIFICATIONS_HANDLE, ENABLE_NOTIFICATIONS_VALUE) - - -class DebugServer(object): - """ - Starts TCP server to be used with DebugServerConnection to speed-up development process - It holds BLE connection to Move Hub, so no need to re-start it every time - Usage: DebugServer(BLEConnection().connect()).start() - - :type connection: BLEConnection - """ - - def __init__(self, connection): - self._running = False - self.sock = socket.socket() - self.connection = connection - - def start(self, port=9090): - self.sock.bind(('', port)) - self.sock.listen(1) - - self._running = True - while self._running: - log.info("Accepting MoveHub debug connections at %s", port) - conn, addr = self.sock.accept() - if not self._running: - raise KeyboardInterrupt("Shutdown") - self.connection.requester.notification_sink = lambda x, y: self._notify(conn, x, y) - try: - self._handle_conn(conn) - except KeyboardInterrupt: - raise - except BaseException: - log.error("Problem handling incoming connection: %s", traceback.format_exc()) - finally: - self.connection.requester.notification_sink = self._notify_dummy - conn.close() - - def __del__(self): - self.sock.close() - - def _notify_dummy(self, handle, data): - log.debug("Dropped notification from handle %s: %s", handle, binascii.hexlify(data)) - self._check_shutdown(data) - - def _notify(self, conn, handle, data): - payload = {"type": "notification", "handle": handle, "data": str2hex(data)} - log.debug("Send notification: %s", payload) - try: - conn.send(json.dumps(payload) + "\n") - except KeyboardInterrupt: - raise - except BaseException: - log.error("Problem sending notification: %s", traceback.format_exc()) - - self._check_shutdown(data) - - def _check_shutdown(self, data): - if data[5] == MSG_DEVICE_SHUTDOWN: - log.warning("Device shutdown") - self._running = False - - def _handle_conn(self, conn): - """ - :type conn: socket._socketobject - """ - buf = "" - while True: - data = conn.recv(1024) - log.debug("Recv: %s", data.strip()) - if not data: - break - - buf += data - - if "\n" in buf: - line = buf[:buf.index("\n")] - buf = buf[buf.index("\n") + 1:] - - if line: - log.info("Cmd line: %s", line) - try: - self._handle_cmd(json.loads(line)) - except KeyboardInterrupt: - raise - except BaseException: - log.error("Failed to handle cmd: %s", traceback.format_exc()) - - def _handle_cmd(self, cmd): - if cmd['type'] == 'write': - self.connection.write(cmd['handle'], unhexlify(cmd['data'])) - else: - raise ValueError("Unhandled cmd: %s", cmd) - - -class DebugServerConnection(Connection): - """ - Connection type to be used with DebugServer, replaces BLEConnection - """ - - def __init__(self, port=9090): - super(DebugServerConnection, self).__init__() - self.notify_handler = None - self.buf = "" - self.sock = socket.socket() - self.sock.connect(('localhost', port)) - self.incoming = [] - - self.reader = Thread(target=self._recv) - self.reader.setName("Debug connection reader") - self.reader.setDaemon(True) - self.reader.start() - - def __del__(self): - self.sock.close() - - def write(self, handle, data): - payload = { - "type": "write", - "handle": handle, - "data": str2hex(data) - } - self._send(payload) - - def _send(self, payload): - log.debug("Sending to debug server: %s", payload) - self.sock.send(json.dumps(payload) + "\n") - - def _recv(self): - while True: - data = self.sock.recv(1024) - log.debug("Recv from debug server: %s", data.strip()) - if not data: - raise KeyboardInterrupt("Server has closed connection") - - self.buf += data - - while "\n" in self.buf: - line = self.buf[:self.buf.index("\n")] - self.buf = self.buf[self.buf.index("\n") + 1:] - if line: - item = json.loads(line) - if item['type'] == 'notification' and self.notify_handler: - try: - self.notify_handler(item['handle'], unhexlify(item['data'])) - except BaseException: - log.error("Failed to notify handler: %s", traceback.format_exc()) - elif item['type'] == 'response': - self.incoming.append(item) - else: - log.warning("Dropped inbound: %s", item) - - def set_notify_handler(self, handler): - self.notify_handler = handler diff --git a/pylgbst/comms/__init__.py b/pylgbst/comms/__init__.py new file mode 100644 index 0000000..567c0a9 --- /dev/null +++ b/pylgbst/comms/__init__.py @@ -0,0 +1,190 @@ +""" +This package holds communication aspects +""" +import binascii +import json +import logging +import socket +import traceback +from abc import abstractmethod +from binascii import unhexlify +from threading import Thread + +from pylgbst.constants import MSG_DEVICE_SHUTDOWN, ENABLE_NOTIFICATIONS_HANDLE, ENABLE_NOTIFICATIONS_VALUE +from pylgbst.utilities import str2hex + +log = logging.getLogger('comms') + +LEGO_MOVE_HUB = "LEGO Move Hub" + + +class Connection(object): + def connect(self, hub_mac=None): + pass + + def disconnect(self): + pass + + @abstractmethod + def write(self, handle, data): + pass + + @abstractmethod + def set_notify_handler(self, handler): + pass + + def enable_notifications(self): + self.write(ENABLE_NOTIFICATIONS_HANDLE, ENABLE_NOTIFICATIONS_VALUE) + + +class DebugServer(object): + """ + Starts TCP server to be used with DebugServerConnection to speed-up development process + It holds BLE connection to Move Hub, so no need to re-start it every time + Usage: DebugServer(BLEConnection().connect()).start() + + :type connection: BLEConnection + """ + + def __init__(self, connection): + self._running = False + self.sock = socket.socket() + self.connection = connection + + def start(self, port=9090): + self.sock.bind(('', port)) + self.sock.listen(1) + + self._running = True + while self._running: + log.info("Accepting MoveHub debug connections at %s", port) + conn, addr = self.sock.accept() + if not self._running: + raise KeyboardInterrupt("Shutdown") + self.connection.requester.notification_sink = lambda x, y: self._notify(conn, x, y) + try: + self._handle_conn(conn) + except KeyboardInterrupt: + raise + except BaseException: + log.error("Problem handling incoming connection: %s", traceback.format_exc()) + finally: + self.connection.requester.notification_sink = self._notify_dummy + conn.close() + + def __del__(self): + self.sock.close() + + def _notify_dummy(self, handle, data): + log.debug("Dropped notification from handle %s: %s", handle, binascii.hexlify(data)) + self._check_shutdown(data) + + def _notify(self, conn, handle, data): + payload = {"type": "notification", "handle": handle, "data": str2hex(data)} + log.debug("Send notification: %s", payload) + try: + conn.send(json.dumps(payload) + "\n") + except KeyboardInterrupt: + raise + except BaseException: + log.error("Problem sending notification: %s", traceback.format_exc()) + + self._check_shutdown(data) + + def _check_shutdown(self, data): + if data[5] == MSG_DEVICE_SHUTDOWN: + log.warning("Device shutdown") + self._running = False + + def _handle_conn(self, conn): + """ + :type conn: socket._socketobject + """ + buf = "" + while True: + data = conn.recv(1024) + log.debug("Recv: %s", data.strip()) + if not data: + break + + buf += data + + if "\n" in buf: + line = buf[:buf.index("\n")] + buf = buf[buf.index("\n") + 1:] + + if line: + log.info("Cmd line: %s", line) + try: + self._handle_cmd(json.loads(line)) + except KeyboardInterrupt: + raise + except BaseException: + log.error("Failed to handle cmd: %s", traceback.format_exc()) + + def _handle_cmd(self, cmd): + if cmd['type'] == 'write': + self.connection.write(cmd['handle'], unhexlify(cmd['data'])) + else: + raise ValueError("Unhandled cmd: %s", cmd) + + +class DebugServerConnection(Connection): + """ + Connection type to be used with DebugServer, replaces BLEConnection + """ + + def __init__(self, port=9090): + super(DebugServerConnection, self).__init__() + self.notify_handler = None + self.buf = "" + self.sock = socket.socket() + self.sock.connect(('localhost', port)) + self.incoming = [] + + self.reader = Thread(target=self._recv) + self.reader.setName("Debug connection reader") + self.reader.setDaemon(True) + self.reader.start() + + def __del__(self): + self.sock.close() + + def write(self, handle, data): + payload = { + "type": "write", + "handle": handle, + "data": str2hex(data) + } + self._send(payload) + + def _send(self, payload): + log.debug("Sending to debug server: %s", payload) + self.sock.send(json.dumps(payload) + "\n") + + def _recv(self): + while True: + data = self.sock.recv(1024) + log.debug("Recv from debug server: %s", data.strip()) + if not data: + raise KeyboardInterrupt("Server has closed connection") + + self.buf += data + + while "\n" in self.buf: + line = self.buf[:self.buf.index("\n")] + self.buf = self.buf[self.buf.index("\n") + 1:] + if line: + item = json.loads(line) + if item['type'] == 'notification' and self.notify_handler: + try: + self.notify_handler(item['handle'], unhexlify(item['data'])) + except BaseException: + log.error("Failed to notify handler: %s", traceback.format_exc()) + elif item['type'] == 'response': + self.incoming.append(item) + else: + log.warning("Dropped inbound: %s", item) + + def set_notify_handler(self, handler): + self.notify_handler = handler diff --git a/pylgbst/comms_gatt.py b/pylgbst/comms/cgatt.py similarity index 100% rename from pylgbst/comms_gatt.py rename to pylgbst/comms/cgatt.py diff --git a/pylgbst/comms_gattlib.py b/pylgbst/comms/cgattlib.py similarity index 100% rename from pylgbst/comms_gattlib.py rename to pylgbst/comms/cgattlib.py diff --git a/pylgbst/comms_pygatt.py b/pylgbst/comms/cpygatt.py similarity index 100% rename from pylgbst/comms_pygatt.py rename to pylgbst/comms/cpygatt.py diff --git a/tests/test_gatt.py b/tests/test_gatt.py index 434f2a3..1d23636 100644 --- a/tests/test_gatt.py +++ b/tests/test_gatt.py @@ -4,7 +4,7 @@ import unittest import dbus from gatt import DeviceManager -from pylgbst.comms_gatt import CustomDevice, GattConnection +from pylgbst.comms.cgatt import CustomDevice, GattConnection from tests import log, str2hex diff --git a/tests/test_pygatt.py b/tests/test_pygatt.py index ad604dc..6a87505 100644 --- a/tests/test_pygatt.py +++ b/tests/test_pygatt.py @@ -6,7 +6,7 @@ from pygatt import BLEAddressType from pygatt.backends.bgapi.bgapi import MAX_CONNECTION_ATTEMPTS from pygatt.backends.bgapi.device import BGAPIBLEDevice -from pylgbst.comms_pygatt import GattoolConnection +from pylgbst.comms.cpygatt import GattoolConnection from tests import log