使用PySide2创建一个简单的USB HID测试工具。

1、建立界面

新建项目文件夹 usbhid,然后用VSCode打开并新建ui文件夹,右键使用 New Form 使用QtDesigner建立如下界面:

然后选择菜单 窗体->View Python Code,将代码复制后保存到ui文件夹下 usbhid_ui.py。

2、具体功能实现
  • 显示界面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import sys
from PySide2.QtWidgets import *
from PySide2.QtCore import *
from PySide2.QtGui import *

from ui.usbhid_ui import Ui_MainWindow

class MainWindow(Ui_MainWindow,QMainWindow):
def __init__(self):
super(MainWindow,self).__init__()
self.setupUi(self)



if __name__ == "__main__":
app = QApplication(sys.argv)

mwin = MainWindow()
mwin.show()

sys.exit(app.exec_())
  • 扫描当前电脑USB HID设备
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def __init__(self):
...

devices = hid.enumerate()

index = 0
for devinfo in devices:
product_str = devinfo['product_string']
manu_str = devinfo['manufacturer_string']
vid = devinfo['vendor_id']
pid = devinfo['product_id']

if product_str != '':
self.comboPort.addItem(product_str + f' by {manu_str}')

使用enumerate方法可以扫描所有的hid设备,然后就可以获取每个设备的信息。

  • 打开设备
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def __init__(self):
...

self.dev = hid.device()

index = 0
for devinfo in devices:
...
self.comboPort.addItem(product_str + f' by {manu_str}')
self.comboPort.setItemData(index,pid,Qt.UserRole+1)
self.comboPort.setItemData(index,vid,Qt.UserRole+2)
index +=1

self.btnConnect.clicked.connect(self.open_device)

def open_device(self):
pid = self.comboPort.itemData(self.comboPort.currentIndex(),Qt.UserRole+1)
vid = self.comboPort.itemData(self.comboPort.currentIndex(),Qt.UserRole+2)

if self.btnConnect.text == "连接":
self.btnConnect.setText("断开")
self.dev.open(vid,pid)
else:
self.btnConnect.setText("连接")
self.dev.close()

这里打开设备需要设备的vid和pid号,因此需要在之前扫描设备的时候将vid和pid信息存放在列表框控件中,然后就可以通过选择下拉列表框选择要打开设备的信息。

  • 发送数据
1
2
3
4
5
6
7
8
9
10
def __init__(self):
...
self.btnSend.clicked.connect(self.send_data)

def send_data(self):
str = self.editSend.text()
hex_str = bytes.fromhex(str)

if len(hex_str) != 0:
self.dev.write(hex_str)

这里只实现发送十六进制数据,需要将字符串转换为十六进制。

  • 接收数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def __init__(self):
...
self.read_timer = QTimer()
self.read_timer.setInterval(100)
self.read_timer.timeout.connect(self.read_data)

def open_device(self):
...
if self.btnConnect.text() == "连接":
...
self.dev.open(vid,pid)
self.dev.set_nonblocking(True)
self.read_timer.start()
else:
...
self.read_timer.stop()

def read_data(self):
recv_buf = self.dev.read(32)

if len(recv_buf) != 0:
str = ' '.join([f'{i:#02x}' for i in bytes(recv_buf).rstrip(b'\x00')])
self.editRecv.appendPlainText(str)

读取数据使用一个定时器定时读取,并在连接设备是打开定时器,在关闭设备时候停止,然后将接收的数据转换为十六进制显示在编辑框中。

  • 最后设置界面
1
2
3
4
5
6
7
8
9
10
11
if __name__ == "__main__":
app = QApplication(sys.argv)

dark(app)

mwin = MainWindow()

win = ModernWindow(mwin)
win.show()

sys.exit(app.exec_())
  • 测试效果 :

代码仓库:https://github.com/makerinchina-iot/Monkey-Helper-Tools-py