以下是源码地址
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 bits0x95, 0x01, # Report Count(1)0x75, 0x05, # Report Size(5)0x81, 0x03, # Input(Constant); 5 bit padding0x05, 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_COLLECTION0xc0 # END_COLLECTION])# fmt: on# 初始化鼠标的 X、Y 坐标、滚轮状态(w)和三个按钮的状态。self.x = 0self.y = 0self.w = 0self.button1 = 0self.button2 = 0self.button3 = 0self.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 * 4state = 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.button3state = 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 = 127elif x < -127:x = -127if y > 127:y = 127elif y < -127:y = -127self.x = xself.y = y# 设置滚轮def set_wheel(self, w=0):if w > 127:w = 127elif w < -127:w = -127self.w = w# 设置按钮def set_buttons(self, b1=0, b2=0, b3=0): # 更新按钮状态:设置三个按钮的状态(0 表示未按下,1 表示按下)self.button1 = b1self.button2 = b2self.button3 = b3
总结
这个 Mouse
类用于实现 BLE 蓝牙鼠标设备,并通过 BLE HID 协议与主设备(如手机、电脑等)通信。它能够:
- 广播 BLE 服务,使主设备可以发现和连接。
- 通过 BLE HID 报告发送鼠标的按键状态、坐标变化和滚轮滚动。
- 支持鼠标按钮(最多三个)、X/Y 坐标位移和滚轮操作。
应用场景
这段代码可以应用在各种嵌入式设备中,特别是使用 ESP32 等支持 BLE 的开发板,实现一个无线 BLE 鼠标设备。例如,可以将该代码与物理按键结合,实现自制蓝牙遥控鼠标设备。