MicroPythonBLEHID使用说明——蓝牙鼠标

以下是源码地址

GitCode - 全球开发者的开源社区,开源代码托管平台

GitHub - Heerkog/MicroPythonBLEHID: Human Interface Device (HID) over Bluetooth Low Energy (BLE) GATT library for MicroPython.

本篇主要讲解mouse类使用

python 复制代码
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 鼠标设备。例如,可以将该代码与物理按键结合,实现自制蓝牙遥控鼠标设备。

相关推荐
码码哈哈0.06 小时前
微软出品的一个鼠标控制多台电脑,还能共享剪切板分享与下载
microsoft·计算机外设
陌夏微秋1 天前
51单片机基础03 矩阵按键读取与外部中断读取
单片机·嵌入式硬件·计算机外设·51单片机·硬件工程·信息与通信·智能硬件
大白要努力!1 天前
狼蛛F87Pro键盘常用快捷键的使用说明
计算机外设
m0_594526301 天前
探索 TraceBoard:统计你的键盘按键使用情况
python·计算机外设·开源软件·fastapi
Code成立2 天前
《Java核心技术 卷I》用户图形界面鼠标事件
java·开发语言·计算机外设
IT技术分享社区2 天前
电脑技巧:推荐一款开源免费的多显示器管理工具Dual Monitor Tools
计算机外设·电脑·硬件知识·屏幕管理
百锦再3 天前
详解基于C#开发Windows API的SendMessage方法的鼠标键盘消息发送
windows·c#·计算机外设
Bruce小鬼3 天前
QT鼠标事件
开发语言·qt·计算机外设
Cici_ovo3 天前
实现一个BLE HID鼠标
计算机外设