diff --git a/cflib/crazyflie/syncCrazyflie.py b/cflib/crazyflie/syncCrazyflie.py index 12dfdcefcf7f69942843ed7a892d92f7b8bcab04..cfd9589064b84766b2c935f24e933ec9ac6391bf 100644 --- a/cflib/crazyflie/syncCrazyflie.py +++ b/cflib/crazyflie/syncCrazyflie.py @@ -50,18 +50,17 @@ class SyncCrazyflie: self._is_link_open = False self._error_message = None - self.cf.connected.add_callback(self._connected) - self.cf.connection_failed.add_callback(self._connection_failed) - self.cf.disconnected.add_callback(self._disconnected) - def open_link(self): if (self.is_link_open()): raise Exception('Link already open') + self._add_callbacks() + print('Connecting to %s' % self._link_uri) self.cf.open_link(self._link_uri) self._connect_event.wait() if not self._is_link_open: + self._remove_callbacks() raise Exception(self._error_message) def __enter__(self): @@ -70,6 +69,7 @@ class SyncCrazyflie: def close_link(self): self.cf.close_link() + self._remove_callbacks() self._is_link_open = False def __exit__(self, exc_type, exc_val, exc_tb): @@ -94,4 +94,21 @@ class SyncCrazyflie: self._connect_event.set() def _disconnected(self, link_uri): + self._remove_callbacks() self._is_link_open = False + + def _add_callbacks(self): + self.cf.connected.add_callback(self._connected) + self.cf.connection_failed.add_callback(self._connection_failed) + self.cf.disconnected.add_callback(self._disconnected) + + def _remove_callbacks(self): + def remove_callback(container, callback): + try: + container.remove_callback(callback) + except ValueError: + pass + + remove_callback(self.cf.connected, self._connected) + remove_callback(self.cf.connection_failed, self._connection_failed) + remove_callback(self.cf.disconnected, self._disconnected) diff --git a/test/crazyflie/test_syncCrazyflie.py b/test/crazyflie/test_syncCrazyflie.py index 9f84a897d5afec268d0bd5e7e2f43859acb7137f..22e2337403c0584f992e017d7b6c2b593fe14fac 100644 --- a/test/crazyflie/test_syncCrazyflie.py +++ b/test/crazyflie/test_syncCrazyflie.py @@ -91,6 +91,7 @@ class SyncCrazyflieTest(unittest.TestCase): # Assert self.assertEqual(expected, actual) + self._assertAllCallbacksAreRemoved() def test_open_link_of_already_open_link_raises_exception(self): # Fixture @@ -111,6 +112,7 @@ class SyncCrazyflieTest(unittest.TestCase): # Assert self.cf_mock.close_link.assert_called_once_with() self.assertFalse(self.sut.is_link_open()) + self._assertAllCallbacksAreRemoved() def test_close_link_that_is_not_open(self): # Fixture @@ -132,6 +134,7 @@ class SyncCrazyflieTest(unittest.TestCase): # Assert self.assertFalse(self.sut.is_link_open()) + self._assertAllCallbacksAreRemoved() def test_open_close_with_context_mangement(self): # Fixture @@ -142,3 +145,9 @@ class SyncCrazyflieTest(unittest.TestCase): # Assert self.cf_mock.close_link.assert_called_once_with() + self._assertAllCallbacksAreRemoved() + + def _assertAllCallbacksAreRemoved(self): + self.assertEqual(0, len(self.cf_mock.connected.callbacks)) + self.assertEqual(0, len(self.cf_mock.connection_failed.callbacks)) + self.assertEqual(0, len(self.cf_mock.disconnected.callbacks))