From 06304eb7180960a68194cdced2a4fc7050c70954 Mon Sep 17 00:00:00 2001 From: Daniel Pavel Date: Tue, 25 Sep 2012 14:18:18 +0300 Subject: [PATCH] added API functions for listing and finding devices by name --- logitech/unifying_receiver/api.py | 57 +++++++++++++++++++ logitech/unifying_receiver/base.py | 4 ++ .../unifying_receiver/tests/test_30_base.py | 2 +- .../unifying_receiver/tests/test_50_api.py | 45 ++++++++++++++- 4 files changed, 106 insertions(+), 2 deletions(-) diff --git a/logitech/unifying_receiver/api.py b/logitech/unifying_receiver/api.py index 31873fa0..d1a0a8c7 100644 --- a/logitech/unifying_receiver/api.py +++ b/logitech/unifying_receiver/api.py @@ -13,6 +13,24 @@ from . import base from .unhandled import _publish as _unhandled_publish +# +# +# + + +from collections import namedtuple +"""Tuple returned by list_devices and find_device_by_name.""" +AttachedDeviceInfo = namedtuple('AttachedDeviceInfo', [ + 'number', + 'type', + 'name', + 'features_array']) +del namedtuple + +# +# +# + def open(): """Opens the first Logitech UR found attached to the machine. @@ -119,6 +137,45 @@ def ping(handle, device): return _status(base.read(handle, base.DEFAULT_TIMEOUT * 3)) +def find_device_by_name(handle, device_name): + """Searches for an attached device by name. + + :returns: an AttachedDeviceInfo tuple, or ``None``. + """ + _l.log(_LOG_LEVEL, "(%d:,) searching for device '%s'", handle, device_name) + + for device in range(1, 1 + base.MAX_ATTACHED_DEVICES): + features_array = get_device_features(handle, device) + if features_array: + d_name = get_device_name(handle, device, features_array) + if d_name == device_name: + d_type = get_device_type(handle, device, features_array) + device_info = AttachedDeviceInfo(device, d_type, d_name, features_array) + _l.log(_LOG_LEVEL, "(%d:,%d) found device %s", handle, device, device_info) + return device_info + + +def list_devices(handle): + """List all devices attached to the UR. + + :returns: a list of AttachedDeviceInfo tuples. + """ + _l.log(_LOG_LEVEL, "(%d:,) listing all devices", handle) + + devices = [] + + for device in range(1, 1 + base.MAX_ATTACHED_DEVICES): + features_array = get_device_features(handle, device) + if features_array: + d_type = get_device_type(handle, device, features_array) + d_name = get_device_name(handle, device, features_array) + device_info = AttachedDeviceInfo(device, d_type, d_name, features_array) + _l.log(_LOG_LEVEL, "(%d:,%d) found device %s", handle, device, device_info) + devices.append(device_info) + + return devices + + def get_feature_index(handle, device, feature): """Reads the index of a device's feature. diff --git a/logitech/unifying_receiver/base.py b/logitech/unifying_receiver/base.py index 2b260d75..ccec6ace 100644 --- a/logitech/unifying_receiver/base.py +++ b/logitech/unifying_receiver/base.py @@ -41,6 +41,10 @@ _MAX_REPLY_SIZE = _MAX_CALL_SIZE DEFAULT_TIMEOUT = 1000 +"""Maximum number of devices attached to a UR.""" +MAX_ATTACHED_DEVICES = 6 + + # # # diff --git a/logitech/unifying_receiver/tests/test_30_base.py b/logitech/unifying_receiver/tests/test_30_base.py index cc1961f8..0c63f26c 100644 --- a/logitech/unifying_receiver/tests/test_30_base.py +++ b/logitech/unifying_receiver/tests/test_30_base.py @@ -79,7 +79,7 @@ class Test_UR_Base(unittest.TestCase): devices = [] - for device in range(1, 7): + for device in range(1, 1 + base.MAX_ATTACHED_DEVICES): w = base.write(self.handle, device, b'\x00\x10\x00\x00\xAA') self.assertIsNone(w, "write should have returned None") reply = base.read(self.handle, base.DEFAULT_TIMEOUT * 3) diff --git a/logitech/unifying_receiver/tests/test_50_api.py b/logitech/unifying_receiver/tests/test_50_api.py index c90d1bae..07274d42 100644 --- a/logitech/unifying_receiver/tests/test_50_api.py +++ b/logitech/unifying_receiver/tests/test_50_api.py @@ -29,14 +29,20 @@ class Test_UR_API(unittest.TestCase): self.fail("No receiver found") def test_05_ping_device_zero(self): + if self.handle is None: + self.fail("No receiver found") + ok = api.ping(self.handle, 0) self.assertIsNotNone(ok, "invalid ping reply") self.assertFalse(ok, "device zero replied") def test_10_ping_all_devices(self): + if self.handle is None: + self.fail("No receiver found") + devices = [] - for device in range(1, 7): + for device in range(1, 1 + api.base.MAX_ATTACHED_DEVICES): ok = api.ping(self.handle, device) self.assertIsNotNone(ok, "invalid ping reply") if ok: @@ -46,6 +52,8 @@ class Test_UR_API(unittest.TestCase): Test_UR_API.device = devices[0] def test_30_get_feature_index(self): + if self.handle is None: + self.fail("No receiver found") if self.device is None: self.fail("Found no devices attached.") @@ -54,6 +62,8 @@ class Test_UR_API(unittest.TestCase): self.assertGreater(fs_index, 0, "invalid FEATURE_SET index: " + str(fs_index)) def test_31_bad_feature(self): + if self.handle is None: + self.fail("No receiver found") if self.device is None: self.fail("Found no devices attached.") @@ -62,6 +72,8 @@ class Test_UR_API(unittest.TestCase): self.assertEquals(reply[:5], b'\x00' * 5, "invalid reply") def test_40_get_device_features(self): + if self.handle is None: + self.fail("No receiver found") if self.device is None: self.fail("Found no devices attached.") @@ -72,6 +84,8 @@ class Test_UR_API(unittest.TestCase): Test_UR_API.features_array = features def test_50_get_device_firmware(self): + if self.handle is None: + self.fail("No receiver found") if self.device is None: self.fail("Found no devices attached.") if self.features_array is None: @@ -82,6 +96,8 @@ class Test_UR_API(unittest.TestCase): self.assertGreater(len(d_firmware), 0, "empty device type") def test_52_get_device_type(self): + if self.handle is None: + self.fail("No receiver found") if self.device is None: self.fail("Found no devices attached.") if self.features_array is None: @@ -92,6 +108,8 @@ class Test_UR_API(unittest.TestCase): self.assertGreater(len(d_type), 0, "empty device type") def test_55_get_device_name(self): + if self.handle is None: + self.fail("No receiver found") if self.device is None: self.fail("Found no devices attached.") if self.features_array is None: @@ -102,6 +120,8 @@ class Test_UR_API(unittest.TestCase): self.assertGreater(len(d_name), 0, "empty device name") def test_60_get_battery_level(self): + if self.handle is None: + self.fail("No receiver found") if self.device is None: self.fail("Found no devices attached.") if self.features_array is None: @@ -113,5 +133,28 @@ class Test_UR_API(unittest.TestCase): except FeatureNotSupported: self.fail("BATTERY feature not supported by device " + str(self.device)) + def test_70_list_devices(self): + if self.handle is None: + self.fail("No receiver found") + + all_devices = api.list_devices(self.handle) + if all_devices: + self.assertIsNotNone(self.device) + for device_info in all_devices: + self.assertIsInstance(device_info, api.AttachedDeviceInfo) + else: + self.assertIsNone(self.device) + + def test_70_find_device_by_name(self): + if self.handle is None: + self.fail("No receiver found") + if self.device is None: + self.fail("Found no devices attached.") + + all_devices = api.list_devices(self.handle) + for device_info in all_devices: + device = api.find_device_by_name(self.handle, device_info.name) + self.assertEquals(device, device_info) + if __name__ == '__main__': unittest.main()