2.2. Device Scanner

Device scanners are used to find devices that are connected to the host. For each device type, there is a specific type of device scanner. Currently there are these types of specific device scanners:

  • USBDeviceScanner for USBDevice

  • LANDeviceScanner for LANDevice

In addition to these specific device scanners, there is also a general device scanner. This one contains all specific device scanners and hence searches for each supported type of device. The general device scanner is represented by the class DeviceScanner.

All classes of device scanners inherit from the abstract BaseDeviceScanner-class. Therefore, all device scanners are used the same way.

2.2.1. Platform dependency of device scanners

Each platform uses different ways to manage their connections to external devices. But nevertheless, the DeviceManager package is developed to work as user friendly as possible.

When you are importing a device scanner for a specific type, the device_manager.scanner-module automatically redirects the import-statement to the corresponding device scanner, depending on what platform you are using. The following platforms are supported at the moment:

  • Windows (import-Redirection to device_manager.scanner._win32):

  • USBDeviceScannerdevice_manager.scanner._win32.Win32USBDeviceScanner

  • LANDeviceScannerdevice_manager.scanner._win32.Win32LANDeviceScanner

  • Linux (import-Redirection to device_manager.scanner._linux):

  • USBDeviceScannerdevice_manager.scanner._linux.LinuxUSBDeviceScanner

  • LANDeviceScannerdevice_manager.scanner._linux.LinuxLANDeviceScanner

[3]:
from device_manager import USBDeviceScanner, LANDeviceScanner

print(USBDeviceScanner)
print(LANDeviceScanner)
<class 'device_manager.scanner._win32.Win32USBDeviceScanner'>
<class 'device_manager.scanner._win32.Win32LANDeviceScanner'>

The usage of the platform depending device scanners are exactly the same. Your scripts should be easily portable between those platforms, without any changes to your code. However, the general DeviceScanner is the same for all platforms because it does not contain any platform depending code.

2.2.2. Usage

Basic functionality

The usage of all specific device scanners is the same. Only the general device scanner has some additional abilities which are discussed below.

Each specific device scanner consists of the functions list_devices and find_devices, no more and no less. The implementation behind might be very different, but the usage exactly the same. Both functions scan the for all available devices and store them internally. When you call list_devices you get a list of all found devices.

[5]:
usb_scanner = USBDeviceScanner()

usb_scanner.list_devices()
[5]:
(USBDevice('USB\\VID_413C&PID_5534\\4&3FFD8F2A&0&21'),
 USBDevice('USB\\VID_413C&PID_2513\\6&1FFE1F1B&1&2'),
 USBDevice('USB\\VID_0B15&PID_3401\\0123456789ABCD'),
 USBDevice('USB\\VID_413C&PID_2134\\ABC1234'),
 USBDevice('USB\\VID_1130&PID_1620\\XYZWVUT975310'),
 USBDevice('USB\\VID_0781&PID_5581\\01171114'),
 USBDevice('USB\\VID_1BCF&PID_2B8D\\4C5DDB4'))

The find_devices-function accepts as many filter-parameters as you want to. The parameter names must match the names of the Device-properties you want to compare. All Devices matching each filter you have passed will be returned.

[6]:
# Find all devices with vendor_id == 0x413C
usb_scanner.find_devices(vendor_id=0x413C)
[6]:
(USBDevice('USB\\VID_413C&PID_5534\\4&3FFD8F2A&0&21'),
 USBDevice('USB\\VID_413C&PID_2513\\6&1FFE1F1B&1&2'),
 USBDevice('USB\\VID_413C&PID_2134\\ABC1234'))

After the first successful scan for connected devices, the results are stored internally. Afterwards, the device scanner only retuns those cached devices. If any new device connects in the meantime, it will not make it to the search results. If you want the device scanner to rescan, you have to specify it explicitly with the argument rescan. By calling list_devices(rescan=True) or find_devices(rescan=True, ...) the device scanner is forced to scan again.

Additional functionality of the general device scanner

As already mentioned above, the DeviceScanner-class that combines all specific device scanner, has some additional features. Nevertheless, the functions list_devices and find_devices are used the same way. Internally it simply forwards these calls to all specific device scanners. That leads to the fact, that the DeviceScanner is just a container for all supported specific device scanners. To access their instances, you can use the DeviceScanner as a DeviceType-dictionary:

[7]:
from device_manager import DeviceScanner

scanner = DeviceScanner()

print("scanner[\"usb\"]", scanner["usb"])
print("scanner[\"lan\"]", scanner["lan"])
scanner["usb"] <device_manager.scanner._win32.Win32USBDeviceScanner object at 0x000001BFD1F66B50>
scanner["lan"] <device_manager.scanner._win32.Win32LANDeviceScanner object at 0x000001BFD1F44400>

Because of the flexibility of the DeviceType-enumeration, you can use DeviceType-objects as keys, as well as strings, Device-classes or Device-objects.