diff --git a/examples/tracker/__init__.py b/examples/tracker/__init__.py index 6aa07d9..a60d307 100644 --- a/examples/tracker/__init__.py +++ b/examples/tracker/__init__.py @@ -115,7 +115,7 @@ class FaceTracker(MoveHub): pyplot.ion() pyplot.show() - while thr.isAlive(): + while thr.isAlive() and self.connection.is_alive(): # bodies, weights = self._find_color() bodies, weights = self._find_faces() diff --git a/pylgbst/comms/__init__.py b/pylgbst/comms/__init__.py index 567c0a9..bb53315 100644 --- a/pylgbst/comms/__init__.py +++ b/pylgbst/comms/__init__.py @@ -22,6 +22,10 @@ class Connection(object): def connect(self, hub_mac=None): pass + @abstractmethod + def is_alive(self): + pass + def disconnect(self): pass @@ -61,7 +65,7 @@ class DebugServer(object): 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) + self.connection.set_notify_handler(lambda x, y: self._notify(conn, x, y)) try: self._handle_conn(conn) except KeyboardInterrupt: @@ -69,7 +73,7 @@ class DebugServer(object): except BaseException: log.error("Problem handling incoming connection: %s", traceback.format_exc()) finally: - self.connection.requester.notification_sink = self._notify_dummy + self.connection.set_notify_handler(self._notify_dummy) conn.close() def __del__(self): diff --git a/pylgbst/comms/cgatt.py b/pylgbst/comms/cgatt.py index 7e676c0..a75d3d0 100644 --- a/pylgbst/comms/cgatt.py +++ b/pylgbst/comms/cgatt.py @@ -79,21 +79,22 @@ class GattConnection(Connection): super(GattConnection, self).__init__() self._device = None self._iface = bt_iface_name - - def connect(self, hub_mac=None): try: - dev_manager = gatt.DeviceManager(adapter_name=self._iface) + self._manager = gatt.DeviceManager(adapter_name=self._iface) except TypeError: raise NotImplementedError("Gatt is not implemented for this platform") - dman_thread = threading.Thread(target=dev_manager.run) - dman_thread.setDaemon(True) + + self._manager_thread = threading.Thread(target=self._manager.run) + self._manager_thread.setDaemon(False) log.debug('Starting DeviceManager...') - dman_thread.start() - dev_manager.start_discovery() + + def connect(self, hub_mac=None): + self._manager_thread.start() + self._manager.start_discovery() while not self._device: log.info("Discovering devices...") - devices = dev_manager.devices() + devices = self._manager.devices() log.debug("Devices: %s", devices) for dev in devices: @@ -101,7 +102,7 @@ class GattConnection(Connection): name = dev.alias() if name == LEGO_MOVE_HUB or hub_mac == address: logging.info("Found %s at %s", name, address) - self._device = CustomDevice(address, dev_manager) + self._device = CustomDevice(address, self._manager) break if not self._device: @@ -121,3 +122,6 @@ class GattConnection(Connection): def enable_notifications(self): self._device.enable_notifications() + + def is_alive(self): + return self._manager_thread.isAlive() diff --git a/pylgbst/comms/cgattlib.py b/pylgbst/comms/cgattlib.py index 8f69548..56b8f51 100644 --- a/pylgbst/comms/cgattlib.py +++ b/pylgbst/comms/cgattlib.py @@ -1,9 +1,10 @@ # noinspection PyMethodOverriding import logging import traceback -from gattlib import DiscoveryService, GATTRequester from threading import Thread +from gattlib import DiscoveryService, GATTRequester + from pylgbst.comms import Connection, LEGO_MOVE_HUB from pylgbst.utilities import queue, str2hex @@ -21,10 +22,10 @@ class Requester(GATTRequester): self.notification_sink = None self._notify_queue = queue.Queue() # this queue is to minimize time spent in gattlib C code - thr = Thread(target=self._dispatch_notifications) - thr.setDaemon(True) - thr.setName("Notify queue dispatcher") - thr.start() + self.notify_thread = Thread(target=self._dispatch_notifications) + self.notify_thread.setDaemon(True) + self.notify_thread.setName("Notify queue dispatcher") + self.notify_thread.start() def on_notification(self, handle, data): # log.debug("requester notified, sink: %s", self.notification_sink) @@ -89,3 +90,6 @@ class GattLibConnection(Connection): def write(self, handle, data): log.debug("Writing to %s: %s", handle, str2hex(data)) return self.requester.write_by_handle(handle, data) + + def is_alive(self): + return self.requester.notify_thread.isAlive() diff --git a/pylgbst/comms/cpygatt.py b/pylgbst/comms/cpygatt.py index bb91088..1c412b8 100644 --- a/pylgbst/comms/cpygatt.py +++ b/pylgbst/comms/cpygatt.py @@ -54,6 +54,9 @@ class GattoolConnection(Connection): def set_notify_handler(self, handler): self._conn_hnd.subscribe(MOVE_HUB_HW_UUID_CHAR, handler) + def is_alive(self): + return True + class BlueGigaConnection(GattoolConnection): def __init__(self): diff --git a/pylgbst/peripherals.py b/pylgbst/peripherals.py index a1c9cea..7e4160a 100644 --- a/pylgbst/peripherals.py +++ b/pylgbst/peripherals.py @@ -14,7 +14,7 @@ log = logging.getLogger('peripherals') class Peripheral(object): """ - :type parent: MoveHub + :type parent: pylgbst.movehub.MoveHub :type _incoming_port_data: queue.Queue """ @@ -110,6 +110,9 @@ class Peripheral(object): if not async: log.debug("Waiting for sync command work to finish...") while self.in_progress(): + if not self.parent.connection.is_alive(): + log.debug("Connection is not alive anymore: %s", self.parent.connection) + break time.sleep(0.001) log.debug("Command has finished.")