使用 PyUSB(不是 HIDAPI)读写 HID 设备
Read and Write HID device with PyUSB (not HIDAPI)
我想在 pysub 中实现 python hidapi 的读写调用。
使用 python hidapi 的示例代码如下所示:
import hid
hdev = hid.device()
h = hdev.open_path( path )
h.write( send_buffer )
res = h.read( 64 )
receive_buffer = bytearray( res )
我遇到的主要问题是 python hidapi read() returns 一个整数列表(从接收到的缓冲区中的每个字节都有一个 python 整数硬件),我需要缓冲区作为字节并忠实于接收到的内容。(*)
第二个问题是打开、读取和写入是我唯一需要的东西,我需要让系统尽可能轻。因此我想避免额外的依赖。
(*) bytearray() 在这种情况下不是一个好的解决方案,原因超出了这个问题的范围。
这是一个似乎有效的最简单的代码示例。 HID 设备是一个 Teensy 板,它使用其 RAWHID.recv() 和 RAWHID.send() 与主机交换文本和二进制文件。
#!/usr/bin/python
import usb.core
import usb.util
dev = usb.core.find(idVendor=0x16C0, idProduct=0x0486)
try:
dev.reset()
except Exception as e:
print( 'reset', e)
if dev.is_kernel_driver_active(0):
print( 'detaching kernel driver')
dev.detach_kernel_driver(0)
endpoint_in = dev[0][(0,0)][0]
endpoint_out = dev[0][(0,0)][1]
# Send a command to the Teensy
endpoint_out.write( "version".encode() + bytes([0]) )
# Read the response, an array of byte, .tobytes() gives us a bytearray.
buffer = dev.read(endpoint_in.bEndpointAddress, 64, 1000).tobytes()
# Decode and print the zero terminated string response
n = buffer.index(0)
print( buffer[:n].decode() )
我已经完成了一些快速基准测试,看起来 在 array
s 上的工作肯定是朝着正确的方向前进,但是有一个稍微更好的转换选项。以下是在 64 字节数据缓冲区上运行 1000 万次迭代的结果。
使用
data_list = [30] * 64
data_array = array('B', data_list)
我在几秒钟内得到了以下 运行 次:
Technique
Time (seconds, 10 million iterations)
bytearray(data_list)
12.7
bytearray(data_array)
3.0
data_array.tobytes()
2.0
struct.pack('%uB' % len(data_list), *data_list)
18.6
struct.pack('%uB' % len(data_array), *data_array)
22.5
似乎使用 array.tobytes
方法是最快的,其次是使用 array
作为参数调用 bytearray
。
显然,我在每次迭代中都重复使用了相同的缓冲区,可能还有其他不切实际的因素,所以 YMMV。这些应该是相对于彼此的指示性结果,即使不是绝对值。此外,这显然没有考虑 bytearray
与 bytes
.
的性能
我想在 pysub 中实现 python hidapi 的读写调用。
使用 python hidapi 的示例代码如下所示:
import hid
hdev = hid.device()
h = hdev.open_path( path )
h.write( send_buffer )
res = h.read( 64 )
receive_buffer = bytearray( res )
我遇到的主要问题是 python hidapi read() returns 一个整数列表(从接收到的缓冲区中的每个字节都有一个 python 整数硬件),我需要缓冲区作为字节并忠实于接收到的内容。(*)
第二个问题是打开、读取和写入是我唯一需要的东西,我需要让系统尽可能轻。因此我想避免额外的依赖。
(*) bytearray() 在这种情况下不是一个好的解决方案,原因超出了这个问题的范围。
这是一个似乎有效的最简单的代码示例。 HID 设备是一个 Teensy 板,它使用其 RAWHID.recv() 和 RAWHID.send() 与主机交换文本和二进制文件。
#!/usr/bin/python
import usb.core
import usb.util
dev = usb.core.find(idVendor=0x16C0, idProduct=0x0486)
try:
dev.reset()
except Exception as e:
print( 'reset', e)
if dev.is_kernel_driver_active(0):
print( 'detaching kernel driver')
dev.detach_kernel_driver(0)
endpoint_in = dev[0][(0,0)][0]
endpoint_out = dev[0][(0,0)][1]
# Send a command to the Teensy
endpoint_out.write( "version".encode() + bytes([0]) )
# Read the response, an array of byte, .tobytes() gives us a bytearray.
buffer = dev.read(endpoint_in.bEndpointAddress, 64, 1000).tobytes()
# Decode and print the zero terminated string response
n = buffer.index(0)
print( buffer[:n].decode() )
我已经完成了一些快速基准测试,看起来 array
s 上的工作肯定是朝着正确的方向前进,但是有一个稍微更好的转换选项。以下是在 64 字节数据缓冲区上运行 1000 万次迭代的结果。
使用
data_list = [30] * 64
data_array = array('B', data_list)
我在几秒钟内得到了以下 运行 次:
Technique | Time (seconds, 10 million iterations) |
---|---|
bytearray(data_list) |
12.7 |
bytearray(data_array) |
3.0 |
data_array.tobytes() |
2.0 |
struct.pack('%uB' % len(data_list), *data_list) |
18.6 |
struct.pack('%uB' % len(data_array), *data_array) |
22.5 |
似乎使用 array.tobytes
方法是最快的,其次是使用 array
作为参数调用 bytearray
。
显然,我在每次迭代中都重复使用了相同的缓冲区,可能还有其他不切实际的因素,所以 YMMV。这些应该是相对于彼此的指示性结果,即使不是绝对值。此外,这显然没有考虑 bytearray
与 bytes
.