以下是源码地址
GitCode - 全球开发者的开源社区,开源代码托管平台
GitHub - Heerkog/MicroPythonBLEHID: Human Interface Device (HID) over Bluetooth Low Energy (BLE) GATT library for MicroPython.
本篇主要讲解mouse类使用
class Mouse(HumanInterfaceDevice):
def __init__(self, name="Bluetooth Mouse"):
super(Mouse, self).__init__(name) # Set up the general HID services in super.
self.device_appearance = 962 # 962 是 HID 设备的外观 ID,代表鼠标
self.HIDS = ( # Service description: describes the service and how we communicate.
UUID(0x1812), # 0x1812 = Human Interface Device.
(
(UUID(0x2A4A), F_READ), # 0x2A4A = HID 信息特性(只读).
(UUID(0x2A4B), F_READ), # 0x2A4B = HID 报告映射(只读).
(UUID(0x2A4C), F_READ_WRITE_NORESPONSE), # 0x2A4C = HID 控制点(读/写).
(UUID(0x2A4D), F_READ_NOTIFY, ( # 0x2A4D = HID 报告(读/通知).
(UUID(0x2902), ATT_F_READ_WRITE), # 0x2902 = Client Characteristic Configuration.
(UUID(0x2908), ATT_F_READ_WRITE), # 0x2908 = HID reference, to be read by client (allow write because MicroPython v1.20+ bug).
)),
(UUID(0x2A4E), F_READ_WRITE_NORESPONSE), # 0x2A4E = HID 协议模式(读/写).
),
)
# fmt: off
# 描述 HID 输入报告:
# 定义了鼠标输入报告的结构,包括鼠标按钮(3 个按钮)和 X、Y 轴的位移。
# 使用字节码定义了鼠标的功能,如按钮输入、X 和 Y 轴的逻辑范围(-127 到 127)。
self.HID_INPUT_REPORT = bytes([ # Report Description: describes what we communicate.
0x05, 0x01, # USAGE_PAGE (Generic Desktop)
0x09, 0x02, # USAGE (Mouse)
0xa1, 0x01, # COLLECTION (Application)
0x85, 0x01, # REPORT_ID (1)
0x09, 0x01, # USAGE (Pointer)
0xa1, 0x00, # COLLECTION (Physical)
0x05, 0x09, # Usage Page (Buttons)
0x19, 0x01, # Usage Minimum (1)
0x29, 0x03, # Usage Maximum (3)
0x15, 0x00, # Logical Minimum (0)
0x25, 0x01, # Logical Maximum (1)
0x95, 0x03, # Report Count (3)
0x75, 0x01, # Report Size (1)
0x81, 0x02, # Input(Data, Variable, Absolute); 3 button bits
0x95, 0x01, # Report Count(1)
0x75, 0x05, # Report Size(5)
0x81, 0x03, # Input(Constant); 5 bit padding
0x05, 0x01, # Usage Page (Generic Desktop)
0x09, 0x30, # Usage (X)
0x09, 0x31, # Usage (Y)
0x09, 0x38, # Usage (Wheel)
0x15, 0x81, # Logical Minimum (-127)
0x25, 0x7F, # Logical Maximum (127)
0x75, 0x08, # Report Size (8)
0x95, 0x03, # Report Count (3)
0x81, 0x06, # Input(Data, Variable, Relative); 3 position bytes (X,Y,Wheel)
0xc0, # END_COLLECTION
0xc0 # END_COLLECTION
])
# fmt: on
# 初始化鼠标的 X、Y 坐标、滚轮状态(w)和三个按钮的状态。
self.x = 0
self.y = 0
self.w = 0
self.button1 = 0
self.button2 = 0
self.button3 = 0
self.services = [self.DIS, self.BAS, self.HIDS] # Override list of service descriptions.
# Overwrite super to register HID specific service.
def start(self):
super(Mouse, self).start() # 注册服务:调用父类的 start 方法,注册设备信息(DIS)和电池信息(BAS)服务。
print("Registering services")
handles = self._ble.gatts_register_services(self.services) #注册 HID 服务 # Register services and get read/write handles for all services.
self.write_service_characteristics(handles) # Write the values for the characteristics.
self.adv = Advertiser(self._ble, [UUID(0x1812)], self.device_appearance, self.device_name) # 创建广告对象 Advertiser,用于蓝牙广播. Only advertise the top level service, i.e., the HIDS.
print("Server started")
# Overwrite super to write HID specific characteristics.
# 写入服务特性
def write_service_characteristics(self, handles):
super(Mouse, self).write_service_characteristics(handles) # Call super to write DIS and BAS characteristics.
(h_info, h_hid, h_ctrl, self.h_rep, _, h_d1, h_proto) = handles[2] # 获取 HID 特性句柄(handles[2])并写入初始特性值. These correspond directly to self.HIDS. Position 2 because of the order of self.services.
# 包括 HID 信息、HID 输入报告、HID 参考和 HID 协议模式。
print("h_info =", h_info, "h_hid =", h_hid, "h_ctrl =", h_ctrl, "h_rep =", self.h_rep, "h_d1ref =", h_d1, "h_proto =", h_proto)
b = self.button1 + self.button2 * 2 + self.button3 * 4
state = struct.pack("Bbbb", b, self.x, self.y, self.w) # Pack the initial mouse state as described by the input report.
print("Writing hid service characteristics")
# Write service characteristics.
self._ble.gatts_write(h_info, b"\x01\x01\x00\x02") # HID info: ver=1.1, country=0, flags=normal.
self._ble.gatts_write(h_hid, self.HID_INPUT_REPORT) # HID input report map.
self._ble.gatts_write(self.h_rep, state) # HID report.
self._ble.gatts_write(h_d1, struct.pack("<BB", 1, 1)) # HID reference: id=1, type=input.
self._ble.gatts_write(h_proto, b"\x01") # HID protocol mode: report.
# Overwrite super to notify central of a hid report
# 通知 HID 报告
def notify_hid_report(self):
# 如果设备已连接,则调用 self._ble.gatts_notify 发送 HID 报告给连接的主设备
if self.is_connected():
b = self.button1 + self.button2 * 2 + self.button3
state = struct.pack("Bbbb", b, self.x, self.y, self.w) # 将按钮状态(b)、X、Y 和滚轮状态(w)打包成字节
self._ble.gatts_notify(self.conn_handle, self.h_rep, state) # Notify central by writing to the report handle.
print("Notify with report: ", struct.unpack("Bbbb", state))
# 设置鼠标轴坐标
def set_axes(self, x=0, y=0):
if x > 127:
x = 127
elif x < -127:
x = -127
if y > 127:
y = 127
elif y < -127:
y = -127
self.x = x
self.y = y
# 设置滚轮
def set_wheel(self, w=0):
if w > 127:
w = 127
elif w < -127:
w = -127
self.w = w
# 设置按钮
def set_buttons(self, b1=0, b2=0, b3=0): # 更新按钮状态:设置三个按钮的状态(0 表示未按下,1 表示按下)
self.button1 = b1
self.button2 = b2
self.button3 = b3
总结
这个 Mouse
类用于实现 BLE 蓝牙鼠标设备,并通过 BLE HID 协议与主设备(如手机、电脑等)通信。它能够:
- 广播 BLE 服务,使主设备可以发现和连接。
- 通过 BLE HID 报告发送鼠标的按键状态、坐标变化和滚轮滚动。
- 支持鼠标按钮(最多三个)、X/Y 坐标位移和滚轮操作。
应用场景
这段代码可以应用在各种嵌入式设备中,特别是使用 ESP32 等支持 BLE 的开发板,实现一个无线 BLE 鼠标设备。例如,可以将该代码与物理按键结合,实现自制蓝牙遥控鼠标设备。