跳转到内容

$hid.http - ESP32 HID HTTP 自动化控制

Stability: 2 - Stable

$hid.http 模块用于通过 ESP32 HID 硬件内置的 HTTP 本地服务,在脚本中实现对目标设备的 按键模拟、文本输入、触控操作、手势控制、屏幕截图 等操作。

该模块将 HID 物理控制能力 通过 HTTP 接口暴露出来,适用于:

  • 跨进程 / 跨语言自动化
  • 远程控制
  • 多端联动控制
  • 与现有 Web / 服务端系统集成的自动化场景

使用前必读

  • 本模块 完全基于 HID 硬件实现,不依赖无障碍、ADB、Root 等系统权限
  • 所有操作必须在成功执行 init() + connect() 之后
  • $hid.http 的所有方法均为 同步阻塞调用,禁止在 UI 线程中执行
  • HTTP 服务由 HID 硬件自动维护,脚本仅负责调用接口

HTTP 本地服务启动条件说明

在满足以下 任意一种硬件连接条件 后,系统会 自动启动 HID HTTP 本地服务,无需手动配置:

支持的硬件与连接方式

  • ESP32 OTG 开发板

    • ESP32-S2
    • ESP32-S3
  • ESP32 蓝牙 HID 开发板

    • ESP32-C3
    • ESP32-S3
  • 多模三合一 HID 硬件

    • 蓝牙 / OTG / USB
  • 多模二合一 HID 硬件

    • 蓝牙 / OTG

工作机制说明(重要)

  1. HID 硬件成功连接后
  2. 硬件端 自动启动本地 HTTP 服务
  3. $hid.http 模块通过 HTTP 接口向 HID 硬件发送控制指令
  4. HID 硬件将指令转换为真实的 物理级 HID 行为

换句话说: 你操作的是 HTTP 接口,实际生效的是“真实键鼠 / 触控硬件行为”


适用场景举例

  • 不方便直接使用 $hid.multi$hid.esp32otg$hid.esp32ble 的场景
  • 需要通过网络 / Web / 后端服务控制 HID 的场景
  • 多设备、多进程共享同一 HID 控制通道
  • 将 HID 能力开放给非 Bot.js 生态(如 Web、Python、Node.js)

设备状态监听

HID 模块支持监听设备状态变化事件,包括 HID 设备插入、拔出、权限请求、连接和断开等。

可用于自动授权处理、设备连接管理和状态监控。

👉 完整示例请参考:

HID 设备状态监听指南

初始化与蓝牙管理

$hid.http.init([port])

  • port {number} 可选,服务端口号,默认 9123
  • 无返回值

初始化 HID http 模块,建立 HTTP 通信通道,所有操作前必须先执行初始化

js
$hid.http.init(9123);

$hid.http.connect()

  • 返回 {boolean}

连接 HID 设备。

js
var connectResult = $hid.http.connect();
console.log("自动连接: ", connectResult);

$hid.http.restart()

  • 返回 {boolean}

重启 HID 设备,用于设备异常时的重置。

js
var restartResult = $hid.http.restart();
console.log("重启: ", restartResult);

$hid.http.state()

  • 返回 {boolean}

获取当前 HID 设备的连接状态,判断通信通道是否正常。

js
var state = $hid.http.state();
console.log("HID 设备连接状态: ", state);

$hid.getModel()

  • 返回 {string} 当前 ESP32 HID 模块使用的控制器模式,可能值为 "otg""usb""ble"

获取当前 HID 模块的模式信息,用于区分不同 HID 控制器。通常用于调试或确认模块当前模式。

js
var model = $hid.getModel();
console.log("当前 HID 模块模式: ", model);

// 输出示例: "ble"

$hid.setModel(model)

  • model {string} 要切换的 HID 模式,可选值:

    • "usb" 切换到 USB HID 模式
    • "otg" 切换到 OTG HID 模式
    • "ble" 切换到 BLE 蓝牙 HID 模式
  • 返回 {boolean} 切换成功返回 true,失败返回 false

手动设置 HID 设备的连接模式,用于在 自动识别失败、本地缓存异常或连接方式错误 时,强制指定正确的 HID 模式以恢复连接。


行为说明(非常重要)

  • ESP32 开发板

    • 该方法用于修正自动识别结果
    • 设置成功后,需要重新调用 $hid.connect() 建立连接
  • 多模二合一 / 三合一 HID 硬件

    • 必须处于已连接状态($hid.state() === true
    • 才能通过该方法在不同 HID 模式之间在线切换
    • 若未连接,则需要通过 硬件上的物理切换按钮 手动切换模式

js
$hid.setModel("otg");

$hid.http.checkPermission()

  • 返回 {boolean}

检查当前应用的蓝牙相关权限(位置信息、蓝牙 扫描、连接、通信),确保模块正常运行。

js
var permissionsCheck = $hid.http.checkPermission();
console.log("蓝牙权限检查结果: ", permissionsCheck);

$hid.http.requestPermission([activity])

  • activity {Activity} 用于发起运行时权限请求的 Activity 实例,可选 用于引导用户授予 HID 相关所需权限。
  • 当传入 activity
    将通过该 Activity 发起运行时权限请求(如蓝牙、位置等),适用于前台交互场景。

  • 当未传入 activity
    将直接跳转至当前应用的系统权限设置页面,由用户手动开启所需权限,适用于后台或无界面场景。

该方法仅负责权限引导,不保证权限一定被授予,调用方需在后续逻辑中自行校验权限状态。

在 UI 页面中请求权限(推荐)

js
"ui";
$hid.multi.requestPermission(activity);
setTimeout(function () {
  ui.finish(); //关闭UI
}, 2000);

无 Activity 时跳转到系统权限设置页

js
$hid.http.requestPermission();

$hid.http.open()

  • 返回 {boolean}

打开本地设备的蓝牙开关(若未开启)。

js
var openResult = $hid.http.open();
console.log("打开本地蓝牙: ", openResult);

$hid.http.close()

  • 返回 {boolean}

关闭本地设备的蓝牙开关。

js
var closeResult = $hid.http.close();
console.log("关闭本地蓝牙: ", closeResult);

$hid.http.isEnabled()

  • 返回 {boolean}

本地设备的蓝牙开关是否已启用。

js
if (!$hid.http.isEnabled()) {
  toastLog("蓝牙未开启,正在尝试开启");
  $hid.http.open();
} else {
  toastLog("蓝牙已开启");
}

$hid.http.destroy()

  • 无返回值

销毁 模块资源,释放通信通道,脚本结束前建议执行。

js
$hid.http.destroy();

按键模拟

$hid.http.home()

  • 返回 {boolean}

模拟按下主页键,返回设备主屏幕。

js
var homeResult = $hid.http.home();
console.log("按下主页键: ", homeResult);

$hid.http.back()

  • 返回 {boolean}

模拟按下返回键,返回上一个页面。

js
var backResult = $hid.http.back();
console.log("按下返回键: ", backResult);

$hid.http.recents()

  • 返回 {boolean}

模拟按下最近任务键,打开后台任务列表。

js
var recentResult = $hid.http.recents();
console.log("打开最近任务: ", recentResult);

屏幕截图

$hid.http.screenshot()

  • 返回 {boolean}

通过 ESP32 蓝牙 HID 模拟系统截图按键,触发设备原生截图行为。

仅触发截图动作,不获取截图内容。

说明

  • 等同于手动按下手机截图快捷键
  • 截图会保存到系统相册
  • 速度取决于设备系统响应
js
var screenshotResult = $hid.http.screenshot();
console.log("触发系统截图: ", screenshotResult);

$hid.http.captureScreen()

通过 ESP32 蓝牙 HID 模拟系统截图按键并读取截图结果

⚠️ 注意

  • 截图速度较慢,通常约 150 ~ 800 ms
  • 调用限制:同一设备上 1500 ms 内只允许执行一次,否则可能导致截图失败或报错。

若追求高速截图,推荐使用 HID 语音助手方式: $assistant.captureScreen()(速度接近 images.captureScreen()

特点

  • 会阻塞当前线程直到截图完成
  • 返回 Image 对象,可直接处理
  • 适合低频截图场景
js
var img = $hid.http.captureScreen();
console.log("截图对象: ", img);
img.saveTo("/sdcard/test.png");
img.recycle();

$hid.http.captureScreen(path)

  • path {string} 保存路径
  • 返回 {boolean}

通过 ESP32 蓝牙 HID 模拟系统截图按键并保存截图到指定路径

⚠️ 注意

  • 截图速度较慢,通常约 150 ~ 800 ms
  • 调用限制:同一设备上 1500 ms 内只允许执行一次,否则可能导致截图失败或报错。

若追求高速截图,推荐使用 HID 语音助手方式: $assistant.captureScreen(path)(速度接近 images.captureScreen(path)

特点

  • 会阻塞当前线程直到截图完成
  • 返回 Image 对象,可直接处理
  • 适合低频截图场景
js
var saveResult = $hid.http.captureScreen("/sdcard/test.png");
console.log("截图保存: ", saveResult);

剪贴板与文本操作

$hid.http.setSelection()

  • 返回 {boolean}

模拟全选操作。

js
var setSelectionResult = $hid.http.setSelection();
console.log("全选内容: ", setSelectionResult);

$hid.http.copy()

  • 返回 {boolean}

模拟复制操作,将选中的内容复制到剪贴板。

js
var copyResult = $hid.http.copy();
console.log("复制选中内容: ", copyResult);

$hid.http.cut()

  • 返回 {boolean}

模拟剪切操作,将选中的内容剪切到剪贴板。

js
var cutResult = $hid.http.cut();
console.log("剪切选中内容: ", cutResult);

$hid.http.paste()

  • 返回 {boolean}

模拟粘贴操作,将剪贴板内容粘贴到当前焦点位置(支持中文、特殊字符)。

js
// 先设置剪贴板内容,再粘贴
setClip("这是要粘贴的中文内容");
var pasteResult = $hid.http.paste();
console.log("粘贴剪贴板内容: ", pasteResult);

$hid.http.input(txt)

  • txt {string} 要输入的文本(仅支持英文、数字)
  • 返回 {boolean}

模拟键盘逐个输入字符,不支持中文

js
$hid.http.input("abcdefghijklmnopqrstuvwxyz1234567890");  // ✓ 纯英文数字符号

中文输入

  1. 剪贴板+粘贴方案(推荐):
js
setClip("你好世界");
sleep(500)
$hid.http.paste();  // 粘贴
  1. $input 输入法(复杂场景):
js
$input.setText("你好世界");

$hid.http.enter()

  • 返回 {boolean}

模拟按下回车键,适用于搜索、确认、换行等场景。

js
var enterResult = $hid.http.enter();
console.log("按下回车键: ", enterResult);

$hid.http.delete([count])

  • count {number} 可选,删除的字符数,默认 1
  • 返回 {boolean}

模拟删除键(Delete),删除光标后方的字符,可指定删除数量。

js
var deleteSingleResult = $hid.http.delete();
console.log("删除1个字符: ", deleteSingleResult);

var deleteMultipleResult = $hid.http.delete(3);
console.log("删除3个字符: ", deleteMultipleResult);

$hid.http.backspace([count])

  • count {number} 可选,退格的字符数,默认 1
  • 返回 {boolean}

模拟退格键(Backspace),删除光标前方的字符,可指定退格数量。

js
var backspaceSingleResult = $hid.http.backspace();
console.log("退格1个字符: ", backspaceSingleResult);

var backspaceMultipleResult = $hid.http.backspace(2);
console.log("退格2个字符: ", backspaceMultipleResult);

原生键码操作

$hid.http.keyPress(keyCode[, modifier])

  • keyCode {number} 按键对应的原生键码
  • modifier {number} 可选,修饰键码,用于组合键
  • 返回 {boolean}

模拟按下指定键码的按键,可用于单键操作或组合键操作。

⚠ 键码兼容性说明(重要)

不同 HID 硬件及连接模式 使用的原生键码并不完全一致,即使按键功能相同,其 keyCode 也可能不同。

具体差异如下:

  • ESP32 OTG HID
  • ESP32 BLE HID
  • 多模二合一 / 三合一 HID(OTG / USB / BLE)

在使用本方法前,必须确认当前设备类型与连接模式所对应的键码表,否则可能出现:

  • 按键无响应
  • 触发错误功能
  • 与预期不符的系统行为

键码示例参考文档

请根据当前使用的 HID 类型,查阅对应的键码说明:


$hid.http.keyRelease(keyCode)

  • keyCode {number} 按键对应的原生键码
  • 返回 {boolean}

模拟释放指定键码的按键,与 keyPress 配合实现长按效果。

该方法主要用于 ESP32 HID 开发板,需要与 keyPress() 配合使用,才能精确控制按键的 按下 / 保持 / 释放 行为。

键码示例参考文档

请根据当前使用的 HID 类型,查阅对应的键码说明:


$hid.http.keyRelease()

  • 返回 {boolean}

释放所有已按下的按键,用于清空按键状态。

该方法主要用于 ESP32 HID 开发板,需要与 keyPress() 配合使用,才能精确控制按键的 按下 / 保持 / 释放 行为。

$hid.http.keyWrite(keyCode)

  • keyCode {number} 按键对应的原生键码
  • 返回 {boolean}

直接写入指定键码到通信通道,模拟单次按键触发(按下+释放一体化)。

该方法主要用于 ESP32 HID 开发板

触控操作

$hid.http.click(x, y)

  • x {number} 触控点横坐标
  • y {number} 触控点纵坐标
  • 返回 {boolean}

模拟单击操作,点击指定坐标位置,按下的时间为100ms,如果需要点击时间更短,请使用press

点击指定坐标(示例)

js
$hid.http.click(540, 960);

点击屏幕中心点(示例)

js
var x = device.width / 2;
var y = device.height / 2;
$hid.http.click(x, y);

$hid.http.longClick(x, y)

  • x {number} 触控点横坐标
  • y {number} 触控点纵坐标
  • 返回 {boolean}

模拟长按操作,长按指定坐标位置,按下的时间为650ms。

长按指定坐标(示例)

js
$hid.http.longClick(540, 960);

长按屏幕中心点(示例)

js
var x = device.width / 2;
var y = device.height / 2;
$hid.http.longClick(x, y);

$hid.http.press(x, y, duration)

  • x {number} 触控点横坐标
  • y {number} 触控点纵坐标
  • duration {number} 按住的时长(毫秒)
  • 返回 {boolean}

自定义按住操作,按住指定坐标并保持指定时长,比 longClick 更灵活。

在指定坐标执行一次持续 2000 毫秒的长按操作(示例)

js
$hid.http.press(540, 960, 2000);

在屏幕中心位置执行一次持续 2000 毫秒的长按操作(示例)

js
var x = device.width / 2;
var y = device.height / 2;
$hid.http.press(x, y, 2000);

$hid.http.touchDown(x, y[, id])

  • x {number} 触控点横坐标
  • y {number} 触控点纵坐标
  • id {number} 可选,触控点ID(多触点时区分),默认 0
  • 返回 {boolean}

模拟触控按下,手指按下指定坐标(未抬起),用于自定义滑动/拖拽。

$hid.http.touchMove(x, y[, id])

  • x {number} 移动后的横坐标
  • y {number} 移动后的纵坐标
  • id {number} 可选,触控点ID,默认 0
  • 返回 {boolean}

模拟触控移动,手指在按下状态下移动到指定坐标,与 touchDown 配合使用。

$hid.http.touchUp([id])

  • id {number} 可选,触控点ID,默认 0
  • 返回 {boolean}

模拟触控抬起,手指从按下状态抬起,结束触控操作,与 touchDown/touchMove 配合。

按下→抬起实现模拟点击示例

js
// 按下→休息200毫秒→抬起
$hid.http.touchDown(200, 500);
sleep(200);
$hid.http.touchUp()

按下→移动→抬起实现自定义轨迹的滑动示例

js
// 按下→移动→抬起
$hid.http.touchDown(200, 500);
sleep(200);
$hid.http.touchMove(250, 550);
sleep(200);
$hid.http.touchMove(300, 550);
sleep(200);
$hid.http.touchMove(350, 550);
sleep(200);
$hid.http.touchMove(500, 550);
sleep(100);
$hid.http.touchUp();

多指触控示例

具体可参阅$hid.multi

$hid.http.swipe(x1, y1, x2, y2, duration)

  • x1 {number} 滑动起点横坐标
  • y1 {number} 滑动起点纵坐标
  • x2 {number} 滑动终点横坐标
  • y2 {number} 滑动终点纵坐标
  • duration {number} 滑动总时长(毫秒)
  • 返回 {boolean}

基础自定义滑动,指定起点、终点和时长,实现直线滑动。

js
// 从(500,800)滑动到(500,200),时长1000毫秒(向上滑)
$hid.http.swipe(500, 800, 500, 200, 1000);

$hid.http.swipe(x1, y1, x2, y2, steps, downTime, duration, upTime)

  • x1/y1 {number} 滑动起点坐标
  • x2/y2 {number} 滑动终点坐标
  • steps {number} 滑动步数(步数越多越平滑)
  • downTime {number} 按下后延时(毫秒)
  • duration {number} 滑动核心时长(毫秒)
  • upTime {number} 抬起前延时(毫秒)
  • 返回 {boolean}

高级自定义滑动,精细控制滑动的平滑度、按下/抬起延时。

js
// 高平滑度滑动:从(500,850)到(500,200),步数30,按下延时200ms,滑动500ms,抬起延时1000ms
$hid.http.swipe(500, 850, 500, 200, 30, 200, 500, 1000);

$hid.http.swipe(x1, y1, x2, y2, steps, downTime, duration, upTime, shape)

  • shape {number} 滑动曲线形状(1~6,不同数值对应不同的速度曲线,如先快后慢、匀速等)
  • 其余参数同「高级自定义滑动」
  • 返回 {boolean}

曲线滑动,在高级滑动基础上增加速度曲线,模拟真人滑动的非匀速效果,仅仅在横向方向滑动有效。

js
// 曲线向右滑动,形状5(横向曲线)
$hid.http.swipe(200, 500, 520, 500, 50, 200, 2000, 3000, 5);

$hid.http.swipeUp([width, height])

  • width {number} 可选,参考屏幕宽度,用于计算滑动起点和终点,默认取本地 device.width
  • height {number} 可选,参考屏幕高度,用于计算滑动起点和终点,默认取本地 device.height
  • 返回 {boolean}

模拟向上滑动操作,起点位于屏幕底部,终点位于屏幕上方,自动适配指定或本地屏幕尺寸。

基础滑动(使用本地屏幕尺寸)

js
$hid.http.swipeUp();

自定义屏幕尺寸滑动

js
$hid.http.swipeUp(device.width, device.height);

$hid.http.swipeDown([width, height])

  • width {number} 可选,参考屏幕宽度,用于计算滑动起点和终点,默认取本地 device.width
  • height {number} 可选,参考屏幕高度,用于计算滑动起点和终点,默认取本地 device.height
  • 返回 {boolean}

模拟向下滑动操作,起点位于屏幕上方,终点位于屏幕底部,自动适配指定或本地屏幕尺寸。

$hid.http.swipeLeft([width, height])

  • width {number} 可选,参考屏幕宽度,用于计算滑动起点和终点,默认取本地 device.width
  • height {number} 可选,参考屏幕高度,用于计算滑动起点和终点,默认取本地 device.height
  • 返回 {boolean}

模拟向左滑动操作,起点位于屏幕右侧,终点位于屏幕左侧,自动适配指定或本地屏幕尺寸。

$hid.http.swipeRight([width, height])

  • width {number} 可选,参考屏幕宽度,用于计算滑动起点和终点,默认取本地 device.width
  • height {number} 可选,参考屏幕高度,用于计算滑动起点和终点,默认取本地 device.height
  • 返回 {boolean}

模拟向右滑动操作,起点位于屏幕左侧,终点位于屏幕右侧,自动适配指定或本地屏幕尺寸。

$hid.http.zoomIn(targetX, targetY, stride)

  • targetX {number} 缩放中心横坐标
  • targetY {number} 缩放中心纵坐标
  • stride {number} 缩放步长(步长越大,缩放幅度越大)
  • 返回 {boolean}

模拟双指放大操作,以指定坐标为中心放大屏幕内容(如图片、页面)。

以屏幕中心为中心,步长20放大

js
var x = device.width / 2;
var y = device.height / 2;
$hid.http.zoomIn(x, y, 20);
sleep(1000)
$hid.http.zoomIn(x, y, 20);
sleep(1000)
$hid.http.zoomIn(x, y, 20);

$hid.http.zoomOut(targetX, targetY, stride)

  • targetX/targetY {number} 缩放中心坐标
  • stride {number} 缩放步长
  • 返回 {boolean}

模拟双指缩小操作,以指定坐标为中心缩小屏幕内容。

以屏幕中心为中心,步长20缩小

js
var x = device.width / 2;
var y = device.height / 2;
$hid.http.zoomOut(x, y, 20);
sleep(1000)
$hid.http.zoomOut(x, y, 20);
sleep(1000)
$hid.http.zoomOut(x, y, 20);

示例

全功能测试脚本

js
/**
 * HID 全功能演示
 * 流程:初始化 → 连接 → 状态检查 → 操作演示 → 结束
 */

// ==================== 初始化 ====================
toastLog("正在初始化 模块...");
$hid.http.init()


// ==================== 连接设备 ====================
toastLog("正在连接 ESP32 设备...");
if (!$hid.http.connect()) {
    toastLog("ESP32 设备连接失败");
    console.error("连接失败");
    exit();
}

// ==================== 状态检查 ====================
var state = $hid.http.state();
if (!state) {
    toastLog("设备未连接,结束测试");
    exit();
}

toastLog("连接成功!");
console.log("当前状态:", state);

// ==================== 系统按键演示 ====================

toastLog("5秒后执行 返回键");
sleep(5000);
$hid.http.back();

toastLog("5秒后执行 任务键");
sleep(5000);
$hid.http.recents();

toastLog("5秒后执行 主页键");
sleep(5000);
$hid.http.home();

// ==================== 坐标提示 ====================

toastLog("请开启 开发者选项 → 指针位置\n可查看触控坐标");

// ==================== 点击中心点 ====================

var x = device.width / 2;
var y = device.height / 2;

toastLog("5秒后点击屏幕中心点\n(" + x + ", " + y + ")");
sleep(5000);

$hid.http.click(x, y);

// ==================== 上滑演示 ====================

toastLog("5秒后模拟上滑操作");
sleep(5000);

// 起点与终点(基于屏幕比例)
var x1 = device.width / 2;
var y1 = device.height * 0.8;

var x2 = device.width / 2;
var y2 = device.height * 0.2;

// 使用真实坐标滑动函数
$hid.http.swipe(x1, y1, x2, y2, 1000);

// ==================== 结束 ====================

toastLog("HID 测试完成!");
console.log("测试流程结束");

HID 控件节点查找点击

HID 控件请参见

js
// 初始化 HID 模块(仅需调用一次,阻塞操作,请勿在 UI 线程执行)
$hid.http.init(context);

// 连接 ESP32 设备(仅需连接一次,建议在脚本启动时执行,阻塞操作,请勿在 UI 线程执行)
$hid.http.connect();

// ==================== 状态检查 ====================
var state = $hid.http.state();
if (!state) {
  toastLog("设备未连接,结束测试");
  exit();
}

toastLog("连接成功!");
console.log("当前状态:", state);

//然后下面就可以写具体的自动化业务操作逻辑了

var uiObject = selector(1).desc("任务管理").className("android.widget.LinearLayout").visibleToUser(true).findOne(1000);
if (uiObject) {
  $hid.http.click(uiObject.bounds().centerX(), uiObject.bounds().centerY());
  sleep(1000);
} else {
  toastLog("未找到符合条件的控件");
}

HID YOLO目标检测点击

YOLO 基于深度学习目标检测模型进行图像推理,可自动识别画面中的目标对象,不依赖固定分辨率与坐标规则,适用于游戏界面、复杂动画场景等传统找图难以处理的画面环境。

通常可与 OCR 文字识别结合使用,实现对图像目标与文本信息的综合自动化控制。

js
// 初始化 HID 模块(仅需调用一次,阻塞操作,请勿在 UI 线程执行)
$hid.http.init(context);

// 连接 ESP32 设备(仅需连接一次,建议在脚本启动时执行,阻塞操作,请勿在 UI 线程执行)
$hid.http.connect();

// ==================== 状态检查 ====================
var state = $hid.http.state();
if (!state) {
  toastLog("设备未连接,结束测试");
  exit();
}

toastLog("连接成功!");
console.log("当前状态:", state);

// 加载 ONNX 格式 YOLO 模型
var yolo = $yolo.load(
  {
    binPath: "/sdcard/yolo26n.ncnn.bin",
    paramPath: "/sdcard/yolo26n.ncnn.param",
    classes: [
        "person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat", "traffic light",
        "fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow",
        "elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee",
        "skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard",
        "tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
        "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch",
        "potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse", "remote", "keyboard", "cell phone",
        "microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors", "teddy bear",
        "hair drier", "toothbrush"
    ],
    version: 26,
    task: 0, // 目标检测
    device: 0, // CPU
  },
  {
    onload: function (yolo, success) {
      console.log(success ? "NCNN 模型加载成功" : "NCNN 模型加载失败");
    },
  }
);

if (!yolo) {
  console.error("加载失败");
  exit();
}
// 设置全局配置
yolo.setConfig({
  width: 640,
  height: 640,
  conf: 0.25,
  iou: 0.7,
});

// ==================== 截取当前屏幕(一共有6中截图方式 当前采用系统截图方式) ====================
// 请求截图
if (!requestScreenCapture()) {
  toastLog("请求截图失败");
  exit();
}
var img = images.captureScreen();

var yoloResults = yolo.predict(img);

// 输出结果
console.log("检测到", yoloResults.size(), "个目标");
// 遍历每一个 YOLOObject(目标检测结果)
for (var index = 0; index < yoloResults.size(); index++) {
  var yoloObject = yoloResults.get(index);

  // 类别 ID
  var cls = yoloObject.cls;

  // 类别名称
  var name = yoloResults.names[cls];

  console.log("目标 " + (index + 1));
  console.log("  类别ID:", cls);
  console.log("  类别名称:", name);
  console.log("  置信度:", yoloObject.conf);

  // 位置信息
  console.log("  位置: 左上角x=" + yoloObject.x + ", 左上角y=" + yoloObject.y + ", 宽=" + yoloObject.w + ", 高=" + yoloObject.h);

  // ==================== 仅点击类别为 1 的目标 ====================

  if (cls === 1) {
    $hid.http.click(yoloObject.bounds().centerX(), yoloObject.bounds().centerY());
    sleep(2000);

    // 如果只需要点一个目标,可直接跳出循环
    break;
  }
}

//在不需要时记得释放模型资源
yolo.release();

HID 找图查找点击

通过截图获取当前屏幕图像,使用找图算法定位目标位置,获取坐标后通过 HID 模拟点击。

js
// ==================== 初始化与连接 ====================
$hid.http.init();
$hid.http.connect();

var state = $hid.http.state();
if (!state) {
  toastLog("设备未连接");
  exit();
}

// ==================== 截取当前屏幕(一共有6中截图方式 当前采用系统截图方式) ====================
// 请求截图
if (!requestScreenCapture()) {
  toastLog("请求截图失败");
  exit();
}
var img = images.captureScreen();

// ==================== 查找目标图片 ====================

// 目标小图图片路径
var targetImg = images.read("/sdcard/target.png");

// 在截图中查找目标
var point = images.findImage(img, targetImg, {
  threshold: 0.8,
});

// ==================== 根据结果点击 ====================

if (point) {
  // 获取目标中心坐标
  var x = point.x + targetImg.getWidth() / 2;
  var y = point.y + targetImg.getHeight() / 2;

  toastLog("找到目标,点击坐标: " + x + ", " + y);

  $hid.http.click(x, y);
  sleep(2000);
} else {
  toastLog("未找到目标图片");
}

// 释放小图片资源
targetImg.recycle();

HID OCR文字识别找字点击

js

// ==================== 初始化与连接 ====================
$hid.http.init();
$hid.http.connect();

var state = $hid.http.state();
if (!state) {
  toastLog("设备未连接");
  exit();
}

// 加载OCR插件,需要先下载官方MLKitOCR插件
var MLKitOCR = $plugins.load("org.autojs.autojspro.plugin.mlkit.ocr");
var ocr = new MLKitOCR();

// 请求截图
if (!requestScreenCapture()) {
  toastLog("请求截图失败");
  exit();
}

//循环5次截图
for (var i = 0; i < 5; i++) {
  var capture = captureScreen();

  // 检测截图文字并计算检测时间,首次检测的耗时比较长
  // 检测时间取决于图片大小、内容、文字数量
  var start = Date.now();
  var results = ocr.detect(capture);
  var end = Date.now();

  if (results.length > 0) {
    for (var index = 0; index < results.length; index++) {
      var result = results[index];
      if ("改成要识别的文字".includes(result.text)) {
        var bounds = result.bounds;
        console.log(bounds);
        var x = bounds.centerX();
        var y = bounds.centerY();
        $hid.http.click(x, y);
        sleep(2000);
        break;
      }
    }
  }

  toastLog(`第${i + 1}次检测: ${end - start}ms`);
  sleep(3000);
}

ocr.release();

总结

  1. 基础流程固定

    所有 HID 操作必须遵循统一流程:

    初始化 蓝牙 模块 → 连接 ESP32 设备 → 状态检查 → 业务自动化操作

    其中:

    • $hid.http.init()$hid.http.connect() 仅需执行一次
    • 建议每次操作前通过 $hid.http.state() 确认连接状态

  1. 文本输入推荐方案

    • 英文、数字: 使用 $hid.http.input() 直接模拟键盘输入

    • 中文、特殊字符: 推荐使用 剪贴板 + 粘贴方案

      js
      setClip("需要输入的中文内容");
      $hid.http.paste();
    • 复杂输入场景建议配合专业输入模块(如 $input


  1. 权限与稳定性建议

    • 使用 $hid.http.checkPermissions() 检查蓝牙相关权限
    • 操作前确认蓝牙已开启及设备已连接,避免指令执行失败

  1. 截图方式灵活选择

具体可参阅屏幕截图的 7 种方式


  1. 目标定位方式多样

    HID 并不限制坐标来源,可结合多种识别方式获取目标位置:

    • 控件节点查找(无障碍 | HID / 数字助理 | ADB / XML 模式,具体可参阅选择器
    • YOLO 目标检测(复杂画面、游戏场景推荐),具体可参阅YOLO
    • 找图找色,具体可参阅找图找色
    • OCR 文字识别,具体可参阅OCR 模块OCR 插件

  1. 坐标操作统一

    无论使用哪种识别方式:

    👉 最终统一转换为坐标

    再通过 $hid.http 执行:

    实现完整的自动化控制流程。