2.1. Device

2.1.1. Device types

The DeviceManager supports different types of devices. At the time of writing this example, these are the supported device types:

  • USB: USBDevice

  • Ethernet/LAN: LANDevice

All currently supported device types can be found in the DeviceType enumeration. If you want to extend the DeviceManager-project by another device type, it is absolutely essential, to add this type to the DeviceType-enumeration. Otherwise the device scanners and manager will not support that device type.

[1]:
from device_manager import DeviceType

list(DeviceType)
[1]:
[<DeviceType.USB: 'usb'>, <DeviceType.LAN: 'lan'>]

The USB-devices are represented by the class USBDevice and ethernet-devices are represented by the LANDevice-class. Both are subclasses of the abstract base class Device.

[2]:
from device_manager import USBDevice, LANDevice

usb_device = USBDevice()
lan_device = LANDevice()

The DeviceType enumeration is used at different places in the code, especially in from of DeviceTypeDicts. Those are dictionaries, that are using a DeviceType as key. You can find them in the classes DeviceScanner or DeviceManager. Using a DeviceTypeDict is very easy, because you do not have to pass a DeviceTpe-object as key, you could also use a string, a Device-type or Device-object. Internally the DeviceType-constructor is used for this feature:

[3]:
print("'usb'       :=", DeviceType("usb"))
print("USBDevice   :=", DeviceType(USBDevice))
print("USBDevice() :=", DeviceType(USBDevice()))
'usb'       := DeviceType.USB
USBDevice   := DeviceType.USB
USBDevice() := DeviceType.USB

If you already have a Device-object, you could also use its device_type-property, to get the corresponding DeviceType-object:

[4]:
usb_device.device_type
[4]:
<DeviceType.USB: 'usb'>

2.1.2. Basic functionality

Device properties

As already mentioned above, all device types are based on the abstract class Device. All Device-objects have proprties for its main address/port and for additional aliases, if any.

[5]:
lan_device.address = "192.168.10.12"
lan_device.address_aliases = ["192.168.10.13", "mydevice.domain.com"]

usb_device.address = "/devices/pci0000:00/0000:00:02.0/usb1"
usb_device.address_aliases = "/dev/bus/usb/001/001"

All devices have a property returning their corresponding DeviceType.

[6]:
print("lan_device.device_type:", lan_device.device_type)
print("usb_device.device_type:", usb_device.device_type)
lan_device.device_type: DeviceType.LAN
usb_device.device_type: DeviceType.USB

Additionally, each device has a unique_identifier-property, which contains the device’s unique identifiers, as the name suggests. This property can be used, to compare different Device-objects. If their unique_identifiers are equal, you can be sure it is the same device, which may have multiple connections.

Serialization functions

All devices are serializable into a python dictionary. This is used by the DeviceManager, for example, which uses those dictionaries to serialize its devices into a JSON file.

The serialization functions can also be used, to have a look into the Device-objects. All relevant properties of the device, that are not None, are contained by the dictionary:

[7]:
usb_device.to_dict()
[7]:
{'type': 'usb',
 'address': '/devices/pci0000:00/0000:00:02.0/usb1',
 'address_aliases': ['/dev/bus/usb/001/001']}

2.1.3. Proper device types

USB devices

USB devices are represented by the USBDevice-class. Besides the inherited attributes, the USBDevice contains further attributes:

  • vendor_id (int): The manufacturer code, assigned by the USB committee (USB-IF)

  • product_id (int): The product/model code, assigned by the device’s manufacturer

  • revision_id (int): The revision code

  • serial (str): The device’s serial number

[8]:
usb_device.vendor_id = 0x3923
usb_device.product_id = 0x12d0
usb_device.revision_id = 0x0100
usb_device.serial = "0123456789AB"

usb_device.to_dict()
[8]:
{'type': 'usb',
 'address': '/devices/pci0000:00/0000:00:02.0/usb1',
 'address_aliases': ['/dev/bus/usb/001/001'],
 'vendor_id': 14627,
 'product_id': 4816,
 'revision_id': 256,
 'serial': '0123456789AB'}

Because the USBDevice is an usb device, the device_type-property always returns DeviceType.USB. As unique_identifier the USBDevice-class uses its vendor_id, product_id and serial.

[9]:
usb_device.unique_identifier
[9]:
{'vendor_id': 14627, 'product_id': 4816, 'serial': '0123456789AB'}

To easily recognize the connected usb devices, you can look at the attributes vendor_name and product_name. These properties look up the vendor_id and product_id of the device to get the manufacturer and model name:

[10]:
print("Vendor  (0x{:04X}):".format(usb_device.vendor_id), usb_device.vendor_name)
print("Product (0x{:04X}):".format(usb_device.product_id), usb_device.product_name)
Vendor  (0x3923): National Instruments Corp.
Product (0x12D0): DAQPad-6507

Ethernet/LAN devices

Ethernet devices are represented by the class LANDevice. It only has one additional attribute, which is the mac_address (the device’s physical address). This is also the device’s unique_identifier.

[11]:
lan_device.mac_address = "01-23-45-67-89-ab"

lan_device.to_dict()
[11]:
{'type': 'lan',
 'address': '192.168.10.12',
 'address_aliases': ['192.168.10.13', 'mydevice.domain.com'],
 'mac_address': '01:23:45:67:89:AB'}

As seen in the code lines above, the device automatically converts the device’s mac address into a standardized format. This is done, to keep the devices comparable. The mac address is always stored with colon-seperators (:) and uppercase-hexadecimal components.

[12]:
lan_device.unique_identifier
[12]:
{'mac_address': '01:23:45:67:89:AB'}