SciTech-ICEE-Embeded-Automation-Simulation-HID-自动化交互: USB+OTG+HID模拟鼠标🖱️键盘⌨️指南→参考"Bot.js Pro 文档"

SciTech-ICEE-Embeded-Automation-Simulation-HID


市售完全硬件USB HID(鼠标/键盘/触摸板TouchPad) to TTL(UART)的解决方案:
CH9329

CH9329
1000134177 1000134176
1000134173 1000134174

参考教程:STM32 USB HID: Emulate a Mouse and Keyboard with STM32

https://controllerstech.com/stm32-usb-hid-mouse-keyboard/
https://controllerstech.com/about/

Home ▸ STM32 Tutorials ▸ USB Tutorials ▸ STM32 as USB Mouse and Keyboard
Updated On: August 5, 2026

STM32 USB HID: Emulate a Mouse and Keyboard with STM32

https://controllerstech.com/stm32-usb-hid-mouse-keyboard/


自动化交互: USB+OTG+HID模拟鼠标🖱️键盘⌨️指南

参考: HID 自动化控制指南

  • hid.stm32otg - STM32 OTG
  • hid.stm32ble - STM32 蓝牙
  • hid - STM32 通用API
  • hid.multi - 多模 HID 硬件
  • hid.http - 通用服务端

HID 自动化控制指南

【BLE】HID设备的实现(蓝牙自拍杆、蓝牙键盘、蓝牙鼠标、HID复合设备)

基于物理级硬件的 零权限 / 强隔离 / 高一致性 自动化方案

HID(Human Interface Device)自动化是一种完全符合国际标准的完整硬件层IO模拟+软化可编程的方案。先通过 MCU/专用HID硬件在 USB/OTG/蓝牙 硬件协议层模拟标准交互设备(如键盘、鼠标、触控板等),对手机、电脑、平板、智能手表或其他智能终端进行自动化的操作控制。
👉 在硬件、操作系统和应用的视角看,这些行为与真实外设输入完全一致。


核心优势

  • 零权限运行,完全符合国际标准。
  • HID 模拟基于外置硬件IO实现,不要求任何系统级能力或高权限接口,包括但不限于:
    • 无障碍 / 辅助功能
    • ADB 调试通道 / 开发人员选项
    • Root 或系统修改能力
    • 无需授权、不占用系统权限,插入即生效。
  • 强系统完整性
    HID 方案的操作路径,完全位于系统输入链路最前端:
    • 输入事件来源为: 外部物理设备
    • 行为由 OS操作系统 的 "Input SubSystem(输入子系统)" 统一接收
    • 不通过应用层 API、不注入进程、不修改系统状态
    • 不产生额外的调用痕迹或运行特征
    • 在系统、应用和硬件的角度看👉 这些操作就是真实用户使用键盘、鼠标或触控设备完成的输入行为。

全功能覆盖,适配多种业务形态

支持完整的输入与控制能力,包括:

  • 按键与组合键模拟
  • 文本输入与粘贴
  • 精准触控与多点手势
  • 滑动、缩放、长按等交互
  • 屏幕截图与视觉联动
  • 同时兼容国际标准的 BLE 蓝牙 / OTG / USB 多种连接方式,满足不同部署环境。

高稳定性 & 低时延表现

指标 HID 硬件方案 传统软件方案
输入延迟 5–50ms 50–200ms
连续运行稳定性 ≈99.9% 依赖系统状态
系统适配 Android 7.0+ 强依赖版本与厂商
长时间运行 ✅ ❌ 易受系统影响

HID 工作原理

HID 不是“模拟点击” 而是 作为国际标准的 硬件级IO(输入输出)设备接入系统工作

系统处理流程如下:

[程序化交互的源文件]
↓
[Programmable HMI(可编程人机交互) 自动化系统]
↓
[MCU/HID 硬件]
↓
[USB / OTG / BLE 协议]
↓
[系统输入子系统]
↓
[应用接收标准输入事件]

👉 对应用而言,输入来源不可区分,行为一致。


支持的连接方式

连接方式 特点 适用场景
BLE 蓝牙 无线、部署灵活 移动设备、远程或分布式环境
OTG / USB 极低延迟、稳定 固定工位、高频交互场景

硬件支持列表

硬件类型 支持型号 说明
MCU开发板 STM32集成蓝牙+USB系列 成本低,支持单一连接模式
多模二合一 蓝牙 + OTG 支持模式切换与供电控制
多模三合一 蓝牙 + OTG + USB 全模式覆盖,即插即用



【BLE】HID设备的实现(蓝牙自拍杆、蓝牙键盘、蓝牙鼠标、HID复合设备)

https://blog.csdn.net/qq_34254642/article/details/126672201
The Human Interface Device (HID) ,即人机交互设备。
定义了蓝牙在人机接口设备方面的协议、特征和使用规程。
典型的应用包括蓝牙鼠标、蓝牙键盘、蓝牙游戏手柄等。

USB HID Protocol

HID协议改编自USB HID Protocol。
host和device是USB协议的角色概念:

  • HOST类似于PC主机,
  • device类似于鼠标、键盘这些USB外设ble hid,

蓝牙设备连接手机时,可视为蓝牙设备就是device,手机就是host。
Device通过结构化Report Descriptor(报告描述符)向Host主机声明数据格式与语义。

HID是USB/Bluetooth标准定义键盘、鼠标等输入设备的核心协议框架,
理解HID 协议,涉及 GATT服务组织、Input Report特征值及其通信机制,及修饰键/普通键的8字节报告构造原理。
HID协议有PnP(即插即用)、跨平台兼容、免Driver(驱动)识别(依赖Appearance值0x03c0)等技术优势,广泛应用于嵌入式交互终端、定制外设与IoT控制面板。

Bluetooth HID Protocol

HID Protocol是计算机与键盘、鼠标等外设通信的通用标准,其核心在于通过描述符定义设备功能。
Bluetooth HID Protocol协议则在此基础上实现了无线化,允许嵌入式设备通过蓝牙模拟标准输入设备。
其技术价值在于能以低成本、高灵活性的方式,将任意Physical Input(物理输入)映射为计算机可识别的指令,极大拓展了人机交互的边界。
在物联网和自动化领域,它常用于快速原型开发、创意交互及无障碍设备。
STM32是热门的物联网平台,有丰富的网络资源深入解析其蓝牙HID映射能力,及演示如何将其变为可编程的宏键盘与模拟鼠标。

  • Bluetooth HID Protocol 是 Bluetooth Protocol 的一个Profile
  • Bluetooth Protocol的每个版本都有HID Profile, 不管版本是2.0、2.1、3.0、4.0、5.0还是6.0。
    • HID设备的协议广播包数据,要有HID设备的Service UUID(0x1812) 和 Device Appearance(0x03C1, 设备外观, 协议术语, 例如Keyboard)。
    • Bluetooth Service(蓝牙服务)方面,要有Human Interface Device服务和Battery Service服务。
    • Connection Management(连接的建立、绑定和管理):
      Host连接上Device后,手机需要能够与蓝牙自拍杆进行连接和绑定,
      并且在连接完成后,Device的 Bluetooth Broadcast(蓝牙广播)可能消失后,随时激活。
      所以要能将绑定Connection及Device,以区分出Connection过的多个Devices的激活。
    • Reporting 机制:
      Device通过Bluetooth Protocol 的 Reporting,Notify有关的数据到Host, 同步数据。
  • HOG(HID OVER GATT Profile)也就是低功耗HID
    4.0以上的Bluetooth Protocol还多了一个BLE(Bluetooth Low Energy)的HOG(HID OVER GATT)。
    HID规范规定基本的键盘和指示功能使用固定格式的数据包,
    在HID Host端不要HID剖析器(约占70kB)。
    允许用固定的PSM,和其它设备类,控制FHS数据包作为服务发现协议的定位,以及键盘与指示设备的连接。
  • BLE(蓝牙低功耗)版本的HID协议
    BLE(Bluetooth Low Energy)实现无线交互的核心协议之一就是HID(人机交互设备)。
    • BLE(蓝牙低功耗)版本的HID协议:
      专为低功耗设备设计。适用于需要长时间待机设备(如无线键盘、遥控器)的场景。
      从日常办公到游戏娱乐,其低功耗、高兼容性的特点使其成为智能设备生态不可少缺少的一环。
  • HOG(HID OVER GATT)协议
    HOG(HID over GATT)是最常用的BLE(蓝牙低功耗)版本的HID协议之一。
    HOG定义标准化的数据格式和通信流程,确保Device(设备, 协议术语)与Host(主机, 协议术语, 如手机、电脑)之间的兼容性和低延迟交互。
    例如有定义统一的数据格式(如按键码、坐标偏移量),确保不同厂商设备的兼容性。
    HOG(HID OVER GATT)通过GATT服务, 将USB HID语义映射到BLE链路。
    理解Report Descriptor(蓝牙报告描述符)的语法结构与Usage Table规范,是构建兼容Android/iOS的键盘、鼠标及多媒体控制器的前提;该描述符定义了输入数据的逻辑含义、位域布局与用途分类,直接影响主机解析正确性。
    结合STM32-IDF的Bluedroid协议栈,需严格遵循HID Service(0x1812)、Report Map(0x2A4B) 和Protocol Mo

Bluetooth Protocol Debugging

从单一功能设备(如蓝牙自拍杆), 到复杂复合设备(如集成键盘鼠标的遥控器), 开发过程的核心就是要有调试经验。
涉及 Broadcast(广播)配置、hid report map(报告描述符编写与自动化生成)、Host(主机)缓存、复合设备特征值冲突 等关键问题的解决。利用nRF Connect等程序进行抓包和问题定位,可帮助开发者高效解决BLE HID开发。



BLE HID Protocol实例: 蓝牙自拍杆

  1. 蓝牙自拍杆实现拍照的原理
    手机在拍照模式下按音量调节键就可以触发快门按下拍照,蓝牙自拍杆的原理也是通过模拟音量键触发,从而实现远程控制拍照。

  2. 蓝牙自拍杆的蓝牙服务
    对于HID设备,广播包数据要有HID设备的服务UUID(0x1812) 和 设备外观(0x03C1, Keyboard)。
    蓝牙服务过程要有Human Interface Device服务和Battery Service服务。
    蓝牙自拍杆通过Report特性,Notify有关数据到手机。
    同时还注意到,连接上蓝牙自拍杆后,手机需要能够与蓝牙自拍杆进行连接和绑定,
    并且在连接后自拍杆的蓝牙广播消失,即功能上只能被一个设备连接。

    蓝牙协议的调试和验证: 首先用nrf connect看下手上的蓝牙自拍杆的蓝牙协议广播包和服务,如下:

    • 广播:
      1000134147
    • 服务:
      1000134148
  3. 代码
    广播和服务这些是定好的蓝牙标准,请查阅。
    hid report map部分:
    HID设备被连接上后,HOST会通过获取hid report map,来确定这个设备具有哪些功能。
    比如每次上报数据,有几个字节,有什么按键,每个按键对应上报数据的哪个字节和实现什么功能等。
    重点就是hid report map,有Script/程序可以自动生成对应的"C语言头文件",并且网上肯定有人已经公开过生成好的标准键盘⌨️和鼠标🖱️的hid report map的C语言头文件(也可能是MCU厂商的官方SDK就有提供)。

// 蓝牙自拍杆
static const uint8_t hids_report_descriptor[] =
{
    // Report ID 1: Advanced buttons
    0x05, 0x0C,         // Usage Page (Consumer)
    0x09, 0x01,         // Usage (Consumer Control)
    0xA1, 0x01,         // Collection (Application)
    0x85, 0x01,         //      Report Id (1)
    0x15, 0x00,         //      Logical minimum (0)
    0x25, 0x01,         //      Logical maximum (1)
    0x75, 0x01,         //      Report Size (1)
    0x95, 0x01,         //      Report Count (1)
    0x09, 0x94,         //      (Quit)
    0x81, 0x06,         //      Input (Data,Value,Relative,Bit Field)
    0x09, 0x95,         //      (Help)
    0x81, 0x06,         //      Input (Data,Value,Relative,Bit Field)
    0x09, 0xEA,         //      (Volume Down)
    0x81, 0x06,         //      Input (Data,Value,Relative,Bit Field)
    0x09, 0xE9,         //      (Volume Up)
    0x81, 0x06,         //      Input (Data,Value,Relative,Bit Field)
    0x09, 0xCB,         //      (Tracking Decrement)
    0x81, 0x06,         //      Input (Data,Value,Relative,Bit Field)
    0x09, 0xCA,         //      (tracking Increment)
    0x81, 0x06,         //      Input (Data,Value,Relative,Bit Field)
    0x09, 0xB6,         //      (Scan Previous Track)
    0x81, 0x06,         //      Input (Data,Value,Relative,Bit Field)
    0x09, 0xB5,         //      (Scan Next Track)
    0x81, 0x06,         //      Input (Data,Value,Relative,Bit Field)
    0x09, 0xB1,         //      (Pause)
    0x81, 0x06,         //      Input (Data,Value,Relative,Bit Field)
    0x09, 0xB0,         //      (Play)
    0x81, 0x06,         //      Input (Data,Value,Relative,Bit Field)
    0x75, 0x01,         //      Report Size (1)
    0x95, 0x06,         //      Report Count (6)
    ...
}



硬件方案之一是: "STM32H743IIT6+USB3300: USB_HS高速双向HID通讯开发"


另一款HID模拟设备的核心 API 模块说明

  • $hid —— STM32 通用控制模块
    统一封装 STM32 OTG / 蓝牙 HID 能力,自动识别当前连接方式,提供一致的调用接口,适用于大多数场景。
  • $hid.stm32ble —— 蓝牙专用模块
    针对 STM32 BLE HID 优化,支持指定设备地址、蓝牙连接管理,适合无线部署环境。
  • $hid.stm32otg —— OTG 专用模块
    专注 MCU OTG 有线 HID 输入,具备更低时延与更高输入一致性,适合高频或精细操作。
  • $hid.multi —— 多模硬件模块
    适配二合一 / 三合一 HID 设备,支持在连接状态下切换工作模式,适合规模化或长期部署。
  • $hid.http —— HTTP 控制模块
    通过本地 HTTP 服务调用 HID 能力,便于跨进程、跨语言或远程系统集成。

HID 设备状态监听

用于监听 HID 设备的状态变化,包括设备插入、拔出、权限请求、权限结果、连接和断开等事件。
支持以下事件类型:

  • device_attached
    OTG HID 设备插入时触发
  • device_detached
    OTG HID 设备拔出时触发
  • permission_request
    请求 USB 或 OTG 管理权限时触发
  • permission_result
    用户确认或拒绝权限请求后触发
  • connected
    HID 设备连接时触发
  • disconnected
    HID 设备断开连接时触发

基础监听示例

var receiverHID = new JavaAdapter(android.content.BroadcastReceiver, {
  onReceive: function (context, intent) {
    threads.start(function () {
      try {
        console.log("监听到消息");
        // 单 ACTION 广播
        if (intent.getAction() === "hid.action.EVENT") {
          // 获取事件类型
          var event = intent.getStringExtra("event");

          // 获取设备(UsbDevice / UsbAccessory / BluetoothDevice)
          var device = intent.getParcelableExtra("device");
          console.log(device);
          // 根据事件类型处理
          switch (event) {
            case "device_attached":
              console.log("设备插入");
              break;
            case "device_detached":
              console.log("设备拔出");
              break;
            case "permission_request":
              console.log("请求OTG/USB管理权限");
              break;
            case "permission_result":
              var granted = intent.getBooleanExtra("granted", false);
              console.log("用户处理权限结果: " + granted);
              break;
            case "connected":
              console.log("设备 HID 已连接");
              break;
            case "disconnected":
              console.log("设备 HID 已断开");
              break;
          }
        }
      } catch (error) {
        /* 处理异常的代码块 */
        console.error(error);
      }
    });
  },
});

var filterHID = new android.content.IntentFilter("hid.action.EVENT");

if (android.os.Build.VERSION.SDK_INT >= 33) {
  context.registerReceiver(receiverHID, filterHID, android.content.Context.RECEIVER_EXPORTED);
} else {
  context.registerReceiver(receiverHID, filterHID);
}

// 脚本退出时注销广播接收器
events.on("exit", function () {
  try {
    if (receiverHID) {
      context.unregisterReceiver(receiverHID);
    }
  } catch (error) {
    /* 处理异常的代码块 */
    console.error(error);
  }
});

$hid.stm32otg.init();

$hid.stm32otg.connect();

////////////////
// 在此处编写你的业务逻辑

// 用于测试 HID 广播监听,防止脚本执行完毕后退出,
// 保持脚本常驻运行,确保 HID 事件监听持续有效
setInterval(() => {}, 1000);

自动授权与界面辅助处理

在 HID 设备连接或权限请求过程,系统可能会显示权限确认界面。
通过临时启用无障碍服务,可以自动完成权限确认或其他界面操作,实现 HID 设备的自动授权与异常恢复。
无障碍服务仅在需要时启用,完成操作后可自动关闭,不影响系统正常使用。
适用场景:

  • USB / OTG HID 自动授权
  • HID 重连恢复
  • 系统权限确认自动处理

无障碍服务的启用与关闭方法请参考:
自启动无障碍服务
关闭无障碍服务

/** 启用无障碍服务 **/
function enableAccessibilityService() {
  const SERVICE_PATH = ":" + context.getPackageName() + "/com.google.android.accessibility.selecttospeak.SelectToSpeakService";

  var Settings = android.provider.Settings;
  let enabledServices = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);

  // 移除重复服务,防止写入冲突
  enabledServices = enabledServices ? enabledServices.replace(new RegExp(SERVICE_PATH, "gi"), "") : "";

  // 清空并写入服务,确保生效
  Settings.Secure.putString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, "");
  Settings.Secure.putString(
    context.getContentResolver(),
    Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
    enabledServices + SERVICE_PATH
  );
}

/**
 * 检查应用是否拥有指定权限
 * @param {string} permission 权限名称
 * @returns {boolean} 是否已授权
 */
function checkPermission(permission) {
  var pm = context.getPackageManager();
  return android.content.pm.PackageManager.PERMISSION_GRANTED == pm.checkPermission(permission, context.getPackageName());
}

/**
 * HID 设备连接后的自动处理逻辑
 *
 * 功能说明:
 * 1. 检查并启用无障碍服务(支持 WRITE_SECURE_SETTINGS 自动开启)
 * 2. 自动处理 USB/HID 权限授权弹窗(点击“确定”)
 * 3. 授权完成后自动关闭无障碍服务,避免长期占用
 *
 * 使用场景:
 * - ESP32 HID
 * - OTG HID 键鼠
 * - USB HID 自动授权
 *
 */
function handleHidConnected() {
  console.log("HID 设备已连接,开始执行自动授权流程: ");

  // =========================
  // 第一步:检查无障碍自动开启权限
  // =========================

  if (checkPermission("android.permission.WRITE_SECURE_SETTINGS")) {
    console.log("已获得 WRITE_SECURE_SETTINGS 权限,正在自动启用无障碍服务");

    enableAccessibilityService();
  } else {
    console.warn(
      "\n⚠️ 未授予 WRITE_SECURE_SETTINGS 权限,无法自动开启无障碍服务" +
        "\n请使用 ADB 授权或手动开启无障碍服务" +
        "\n授权命令已复制到剪贴板"
    );

    // 复制授权命令
    var cmd = "adb shell pm grant " + context.getPackageName() + " android.permission.WRITE_SECURE_SETTINGS";

    setClip(cmd);

    console.info("已复制 ADB 授权命令");

    // 打开无障碍设置页面
    app.startActivity({
      action: "android.settings.ACCESSIBILITY_SETTINGS",
    });

    console.info("等待用户手动开启无障碍服务...");

    // 阻塞等待无障碍开启
    auto.waitFor();
  }

  // =========================
  // 第二步:检测无障碍状态
  // =========================

  if (auto.service == null) {
    toastLog("❌ 无障碍服务启动失败,无法执行自动授权");

    return;
  }

  console.log("无障碍服务已启用");

  // =========================
  // 第三步:等待 USB 权限弹窗出现
  // =========================

  sleep(2000);

  console.log("正在查找 USB 授权确认按钮...");

  // =========================
  // 第四步:点击“确定”
  // =========================

  var confirmBtn = selector().text("确定").className("android.widget.Button").visibleToUser(true).clickable(true).findOne(2000);

  if (confirmBtn) {
    var result = confirmBtn.click();

    console.log("USB 授权确认点击结果: " + result);
  } else {
    toastLog("⚠️ 未找到 USB 授权确认按钮");

    return;
  }

  // =========================
  // 第五步:自动关闭无障碍服务
  // =========================

  sleep(2000);

  if (auto.service != null) {
    auto.service.disableSelf();

    console.log("无障碍服务已关闭(自动授权流程完成)");
  }
}

// 监听 HID 广播
var receiverHID = new JavaAdapter(android.content.BroadcastReceiver, {
  onReceive: function (context, intent) {
    threads.start(function () {
      try {
        console.log("监听到消息");
        // 单 ACTION 广播
        if (intent.getAction() === "hid.action.EVENT") {
          // 获取事件类型
          var event = intent.getStringExtra("event");

          // 获取设备(UsbDevice / UsbAccessory / BluetoothDevice)
          var device = intent.getParcelableExtra("device");
          console.log(device);
          // 根据事件类型处理
          switch (event) {
            case "device_attached":
              console.log("设备插入");

              break;

            case "device_detached":
              console.log("设备拔出");
              break;

            case "permission_request":
              console.log("请求OTG/USB管理权限");
              break;

            case "permission_result":
              var granted = intent.getBooleanExtra("granted", false);
              console.log("用户处理权限结果: " + granted);
              break;

            case "connected":
              console.log("设备 HID 已连接");
              // 对于 OTG 类型的 HID 设备:
              // 1. 系统会弹出“是否允许应用访问 USB 设备”提示
              // 2. 可通过无障碍服务查找控件并点击“确定”,或点击指定坐标,实现自动授权
              // 3. 等待 "permission_result" 广播后,可延迟 2000ms 再关闭无障碍服务
              // 4. 也可以在点击“确定”后直接关闭无障碍服务
              handleHidConnected(device);

              break;

            case "disconnected":
              console.log("设备 HID 已断开");

              break;
          }
        }
      } catch (error) {
        /* 处理异常的代码块 */
        console.error(error);
      }
    });
  },
});


var filterHID = new android.content.IntentFilter("hid.action.EVENT");

if (android.os.Build.VERSION.SDK_INT >= 33) {
  context.registerReceiver(receiverHID, filterHID, android.content.Context.RECEIVER_EXPORTED);
} else {
  context.registerReceiver(receiverHID, filterHID);
}


// 脚本退出时注销广播接收器
events.on("exit", function () {
  try {
    if (receiverHID) {
      context.unregisterReceiver(receiverHID);
    }
  } catch (error) {
    /* 处理异常的代码块 */
    console.error(error);
  }
});

$hid.stm32otg.init();

$hid.stm32otg.connect();

// 在此处编写你的业务逻辑

// 用于测试 HID 广播监听,防止脚本执行完毕后退出,保持脚本常驻运行,确保 HID 事件监听持续有效
setInterval(() => {}, 1000);


总结

核心价值

  • 输入层一致性:所有操作等价于真实外设输入
  • 系统完整性强:不依赖系统权限或应用接口
  • 稳定可控:不受系统更新、权限策略变化影响
  • 组合能力强:可与 YOLO / OCR / 找图找色等视觉方案协同工作

选择建议

  • 快速上应用 / 通用需求 → $hid
  • 无线部署 → $hid.stm32ble
  • 低延迟有线 → $hid.stn32otg
  • 复杂环境 → $hid.multi
  • 跨语言控制 → $hid.http

如需进一步扩展协议或进行深度定制,请参考开发文档。

posted @ 2026-09-11 11:02  abaelhe  阅读(28)  评论(0)    收藏  举报