$hid.esp32otg - ESP32 OTG HID 操作
更新: 2026/3/2 字数: 0 字 时长: 0 分钟
Stability: 2 - Stable
$hid.esp32otg 模块用于在脚本中通过 ESP32 OTG 模拟 HID 设备,实现对目标设备的按键模拟、文本输入、触控操作、屏幕截图等功能,支持基础操作与高级自定义操作,适用于自动化控制、远程操作等场景。
HID OTG 支持的 ESP32 开发板
ESP32 S2
支持良好,功耗低,成本较低(参考价格约 ¥8.5)ESP32 S3
性能更强,资源更充足,同时支持烧录 蓝牙 模式的固件(参考价格约 ¥26)
HID OTG 固件的烧录教程
设备状态监听
HID 模块支持监听设备状态变化事件,包括 OTG 设备插入、拔出、权限请求、连接和断开等。
可用于自动授权处理、设备连接管理和状态监控。
👉 完整示例请参考:
初始化与OTG管理
$hid.esp32otg.init()
- 返回 {boolean} 初始化成功返回
true,失败返回false
初始化 ESP32 OTG HID 模块,建立本地 OTG 通信环境,所有操作前必须先执行初始化。
$hid.esp32otg.init();$hid.esp32otg.connect()
- 返回 {boolean}
连接 ESP32 OTG HID 设备。
⚠️ 注意:此方法为同步阻塞操作,不能在 UI 线程中执行,建议放在子线程或异步任务中调用,以免界面卡死。
var connectResult = $hid.esp32otg.connect();
console.log("连接: ", connectResult);$hid.esp32otg.restart()
- 返回 {boolean}
重启 ESP32 OTG开发板,用于设备异常时的重置。
var restartResult = $hid.esp32otg.restart();
console.log("重启 ESP32 开发板: ", restartResult);$hid.esp32otg.state()
- 返回 {boolean}
获取当前 ESP32 OTG 设备的连接状态,判断通信通道是否正常。
var state = $hid.esp32otg.state();
console.log("OTG 设备连接状态: ", state);$hid.getModel()
- 返回 {string} 当前 ESP32 HID 模块使用的控制器模式,可能值为
"otg"或"ble"。
获取当前 HID 模块的模式信息,用于区分不同 HID 控制器。通常用于调试或确认模块当前模式。
var model = $hid.getModel();
console.log("当前 HID 模块模式: ", model);
// 输出示例: "otg"$hid.setModel(model)
model{string} 要切换的 HID 模式,可选值:"otg"切换到 OTG HID 模式"ble"切换到 BLE 蓝牙 HID 模式
返回 {boolean} 切换成功返回
true,失败返回false
手动设置 ESP32 HID 模块的连接模式,用于 自动识别失败或本地缓存异常 时恢复正常连接。
注意事项
- ESP32 硬件通常会自动识别 HID 连接模式,并更新本地缓存
- 如果本地缓存的模式信息错误,可能导致连接失败
- 这时可以手动调用
$hid.setModel(model)设置正确的模式,然后再调用$hid.connect()
示例:设置为 OTG 连接模式
$hid.setModel("otg");$hid.esp32otg.destroy()
- 无返回值
销毁 OTG 模块资源,脚本结束前建议执行。
$hid.esp32otg.destroy();按键模拟
$hid.esp32otg.home()
- 返回 {boolean}
模拟按下主页键,返回设备主屏幕。
var homeResult = $hid.esp32otg.home();
console.log("按下主页键: ", homeResult);$hid.esp32otg.back()
- 返回 {boolean}
模拟按下返回键,返回上一个页面。
var backResult = $hid.esp32otg.back();
console.log("按下返回键: ", backResult);$hid.esp32otg.recents()
- 返回 {boolean}
模拟按下最近任务键,打开后台任务列表。
var recentResult = $hid.esp32otg.recents();
console.log("打开最近任务: ", recentResult);屏幕截图
$hid.esp32otg.screenshot()
- 返回 {boolean}
通过 ESP32 OTG HID 模拟系统截图按键,触发设备原生截图行为。
仅触发截图动作,不获取截图内容。
说明
- 等同于手动按下手机截图快捷键
- 截图会保存到系统相册
- 速度取决于设备系统响应
var screenshotResult = $hid.esp32otg.screenshot();
console.log("触发系统截图: ", screenshotResult);$hid.esp32otg.captureScreen()
- 返回 {Image}
通过 ESP32 OTG HID 模拟系统截图按键并读取截图结果。
⚠️ 注意:
- 截图速度较慢,通常约 150 ~ 800 ms。
- 调用限制:同一设备上 1500 ms 内只允许执行一次,否则可能导致截图失败或报错。
若追求高速截图,推荐使用 HID 语音助手方式:
$assistant.captureScreen()(速度接近images.captureScreen())
特点
- 会阻塞当前线程直到截图完成
- 返回 Image 对象,可直接处理
- 适合低频截图场景
var img = $hid.esp32otg.captureScreen();
console.log("截图对象: ", img);
img.saveTo("/sdcard/test.png");
img.recycle();$hid.esp32otg.captureScreen(path)
path{string} 保存路径- 返回 {boolean}
通过 ESP32 OTG HID 模拟系统截图按键并保存截图到指定路径。
⚠️ 注意:
- 截图速度较慢,通常约 150 ~ 800 ms。
- 调用限制:同一设备上 1500 ms 内只允许执行一次,否则可能导致截图失败或报错。
若追求高速截图,推荐使用 HID 语音助手方式:
$assistant.captureScreen(path)(速度接近images.captureScreen(path))
特点
- 会阻塞当前线程直到截图完成
- 返回 Image 对象,可直接处理
- 适合低频截图场景
var saveResult = $hid.esp32otg.captureScreen("/sdcard/test.png");
console.log("截图保存: ", saveResult);剪贴板与文本操作
$hid.esp32otg.setSelection()
- 返回 {boolean}
模拟全选操作。
var setSelectionResult = $hid.esp32otg.setSelection();
console.log("全选内容: ", setSelectionResult);$hid.esp32otg.copy()
- 返回 {boolean}
模拟复制操作,将选中的内容复制到剪贴板。
var copyResult = $hid.esp32otg.copy();
console.log("复制选中内容: ", copyResult);$hid.esp32otg.cut()
- 返回 {boolean}
模拟剪切操作,将选中的内容剪切到剪贴板。
var cutResult = $hid.esp32otg.cut();
console.log("剪切选中内容: ", cutResult);$hid.esp32otg.paste()
- 返回 {boolean}
模拟粘贴操作,将剪贴板内容粘贴到当前焦点位置(支持中文、特殊字符)。
// 先设置剪贴板内容,再粘贴
setClip("这是要粘贴的中文内容");
var pasteResult = $hid.esp32otg.paste();
console.log("粘贴剪贴板内容: ", pasteResult);$hid.esp32otg.input(txt)
txt{string} 要输入的文本(仅支持英文、数字)- 返回 {boolean}
模拟键盘逐个输入字符,不支持中文。
$hid.esp32otg.input("abcdefghijklmnopqrstuvwxyz1234567890"); // ✓ 纯英文数字符号中文输入
- 剪贴板+粘贴方案(推荐):
setClip("你好世界");
sleep(500)
$hid.esp32otg.paste(); // 粘贴$input输入法(复杂场景):
$input.setText("你好世界");$hid.esp32otg.enter()
- 返回 {boolean}
模拟按下回车键,适用于搜索、确认、换行等场景。
var enterResult = $hid.esp32otg.enter();
console.log("按下回车键: ", enterResult);$hid.esp32otg.delete([count])
count{number} 可选,删除的字符数,默认1- 返回 {boolean}
模拟删除键(Delete),删除光标后方的字符,可指定删除数量。
var deleteSingleResult = $hid.esp32otg.delete();
console.log("删除1个字符: ", deleteSingleResult);
var deleteMultipleResult = $hid.esp32otg.delete(3);
console.log("删除3个字符: ", deleteMultipleResult);$hid.esp32otg.backspace([count])
count{number} 可选,退格的字符数,默认1- 返回 {boolean}
模拟退格键(Backspace),删除光标前方的字符,可指定退格数量。
var backspaceSingleResult = $hid.esp32otg.backspace();
console.log("退格1个字符: ", backspaceSingleResult);
var backspaceMultipleResult = $hid.esp32otg.backspace(2);
console.log("退格2个字符: ", backspaceMultipleResult);原生键码操作
$hid.esp32otg.keyPress(keyCode[, modifier])
keyCode{number} 按键对应的原生键码(如截图键70、退格键42)modifier{number} 可选,修饰键码,用于组合键- 返回 {boolean}
模拟按下指定键码的按键,可用于单键操作或组合键操作。
重要说明
- 单独按键(不传 modifier)时,仅执行按下动作,不会自动释放 → 必须手动调用
$hid.esp32otg.keyRelease(keyCode)释放按键 - 若单键按下后未释放,将导致 HID 处于按键锁定状态,后续指令可能全部失效
- 组合键操作(传入 modifier)会自动完成按下并释放
单独按下截图键(需手动释放)
// 按下截图键
$hid.esp32otg.keyPress(70);
// 延迟一段时间
sleep(200);
// 手动释放
$hid.esp32otg.keyRelease(70);任务键组合模拟(自动释放)
var taskKeyCombo = $hid.esp32otg.keyPress(43, 4);
console.log("任务键组合: ", taskKeyCombo);
// LEFT_META + TAB
$hid.esp32otg.keyPress(43, 0x08); //oppo Find x3手机任务键主页键组合模拟(自动释放)
var homeKeyCombo = $hid.esp32otg.keyPress(40, 8);
console.log("主页键组合: ", homeKeyCombo);返回键组合模拟(自动释放)
var backKeyCombo = $hid.esp32otg.keyPress(42, 5);
console.log("返回键组合: ", backKeyCombo);$hid.esp32otg.keyRelease(keyCode)
keyCode{number} 按键对应的原生键码- 返回 {boolean}
模拟释放指定键码的按键,与 keyPress 配合实现长按效果。
$hid.esp32otg.keyRelease()
- 返回 {boolean}
释放所有已按下的按键,用于清空按键状态。
$hid.esp32otg.keyRelease();$hid.esp32otg.keyWrite(keyCode)
keyCode{number} 按键对应的原生键码- 返回 {boolean}
直接写入指定键码到通信通道,模拟单次按键触发(按下+释放一体化)。
模拟截图键
var resultKeyWrite = $hid.esp32otg.keyWrite(70);
console.log("截图键写键结果: " + resultKeyWrite);模拟删除键
var resultKeyWrite = $hid.esp32otg.keyWrite(76);
console.log("删除键写键结果: " + resultKeyWrite);模拟退格键
var resultKeyWrite = $hid.esp32otg.keyWrite(42);
console.log("退格键写键结果: " + resultKeyWrite);触控操作
$hid.esp32otg.click(x, y)
x{number} 触控点横坐标y{number} 触控点纵坐标- 返回 {boolean}
模拟单击操作,点击指定坐标位置,按下的时间为100ms,如果需要点击时间更短,请使用press。
点击指定坐标(示例)
$hid.esp32otg.click(540, 960);点击屏幕中心点(示例)
var x = device.width / 2;
var y = device.height / 2;
$hid.esp32otg.click(x, y);$hid.esp32otg.longClick(x, y)
x{number} 触控点横坐标y{number} 触控点纵坐标- 返回 {boolean}
模拟长按操作,长按指定坐标位置,按下的时间为650ms。
长按指定坐标(示例)
$hid.esp32otg.longClick(540, 960);长按屏幕中心点(示例)
var x = device.width / 2;
var y = device.height / 2;
$hid.esp32otg.longClick(x, y);$hid.esp32otg.press(x, y, duration)
x{number} 触控点横坐标y{number} 触控点纵坐标duration{number} 按住的时长(毫秒)- 返回 {boolean}
自定义按住操作,按住指定坐标并保持指定时长,比 longClick 更灵活。
在指定坐标执行一次持续 2000 毫秒的长按操作(示例)
$hid.esp32otg.press(540, 960, 2000);在屏幕中心位置执行一次持续 2000 毫秒的长按操作(示例)
var x = device.width / 2;
var y = device.height / 2;
$hid.esp32otg.press(x, y, 2000);$hid.esp32otg.touchDown(x, y[, id])
x{number} 触控点横坐标y{number} 触控点纵坐标id{number} 可选,触控点ID(多触点时区分),默认0- 返回 {boolean}
模拟触控按下,手指按下指定坐标(未抬起),用于自定义滑动/拖拽。
$hid.esp32otg.touchMove(x, y[, id])
x{number} 移动后的横坐标y{number} 移动后的纵坐标id{number} 可选,触控点ID,默认0- 返回 {boolean}
模拟触控移动,手指在按下状态下移动到指定坐标,与 touchDown 配合使用。
$hid.esp32otg.touchUp([id])
id{number} 可选,触控点ID,默认0- 返回 {boolean}
模拟触控抬起,手指从按下状态抬起,结束触控操作,与 touchDown/touchMove 配合。
按下→抬起实现模拟点击示例
// 按下→休息200毫秒→抬起
$hid.esp32otg.touchDown(200, 500);
sleep(200);
$hid.esp32otg.touchUp()按下→移动→抬起实现自定义轨迹的滑动示例
// 按下→移动→抬起
$hid.esp32otg.touchDown(200, 500);
sleep(200);
$hid.esp32otg.touchMove(250, 550);
sleep(200);
$hid.esp32otg.touchMove(300, 550);
sleep(200);
$hid.esp32otg.touchMove(350, 550);
sleep(200);
$hid.esp32otg.touchMove(500, 550);
sleep(100);
$hid.esp32otg.touchUp();$hid.esp32otg.swipe(x1, y1, x2, y2, duration)
x1{number} 滑动起点横坐标y1{number} 滑动起点纵坐标x2{number} 滑动终点横坐标y2{number} 滑动终点纵坐标duration{number} 滑动总时长(毫秒)- 返回 {boolean}
基础自定义滑动,指定起点、终点和时长,实现直线滑动。
// 从(500,800)滑动到(500,200),时长1000毫秒(向上滑)
$hid.esp32otg.swipe(500, 800, 500, 200, 1000);$hid.esp32otg.swipe(x1, y1, x2, y2, steps, downTime, duration, upTime)
x1/y1{number} 滑动起点坐标x2/y2{number} 滑动终点坐标steps{number} 滑动步数(步数越多越平滑)downTime{number} 按下后延时(毫秒)duration{number} 滑动核心时长(毫秒)upTime{number} 抬起前延时(毫秒)- 返回 {boolean}
高级自定义滑动,精细控制滑动的平滑度、按下/抬起延时。
// 高平滑度滑动:从(500,850)到(500,200),步数30,按下延时200ms,滑动500ms,抬起延时1000ms
$hid.esp32otg.swipe(500, 850, 500, 200, 30, 200, 500, 1000);$hid.esp32otg.swipe(x1, y1, x2, y2, steps, downTime, duration, upTime, shape)
shape{number} 滑动曲线形状(1~6,不同数值对应不同的速度曲线,如先快后慢、匀速等)- 其余参数同「高级自定义滑动」
- 返回 {boolean}
曲线滑动,在高级滑动基础上增加速度曲线,模拟真人滑动的非匀速效果,仅仅在横向方向滑动有效。
// 曲线向右滑动,形状5(横向曲线)
$hid.esp32otg.swipe(200, 500, 520, 500, 50, 200, 2000, 3000, 5);$hid.esp32otg.swipeUp([width, height])
width{number} 可选,参考屏幕宽度,用于计算滑动起点和终点,默认取本地device.widthheight{number} 可选,参考屏幕高度,用于计算滑动起点和终点,默认取本地device.height- 返回 {boolean}
模拟向上滑动操作,起点位于屏幕底部,终点位于屏幕上方,自动适配指定或本地屏幕尺寸。
基础滑动(使用本地屏幕尺寸)
$hid.esp32otg.swipeUp();自定义屏幕尺寸滑动
$hid.esp32otg.swipeUp(device.width, device.height);$hid.esp32otg.swipeDown([width, height])
width{number} 可选,参考屏幕宽度,用于计算滑动起点和终点,默认取本地device.widthheight{number} 可选,参考屏幕高度,用于计算滑动起点和终点,默认取本地device.height- 返回 {boolean}
模拟向下滑动操作,起点位于屏幕上方,终点位于屏幕底部,自动适配指定或本地屏幕尺寸。
$hid.esp32otg.swipeLeft([width, height])
width{number} 可选,参考屏幕宽度,用于计算滑动起点和终点,默认取本地device.widthheight{number} 可选,参考屏幕高度,用于计算滑动起点和终点,默认取本地device.height- 返回 {boolean}
模拟向左滑动操作,起点位于屏幕右侧,终点位于屏幕左侧,自动适配指定或本地屏幕尺寸。
$hid.esp32otg.swipeRight([width, height])
width{number} 可选,参考屏幕宽度,用于计算滑动起点和终点,默认取本地device.widthheight{number} 可选,参考屏幕高度,用于计算滑动起点和终点,默认取本地device.height- 返回 {boolean}
模拟向右滑动操作,起点位于屏幕左侧,终点位于屏幕右侧,自动适配指定或本地屏幕尺寸。
$hid.esp32otg.zoomIn(targetX, targetY, stride)
targetX{number} 缩放中心横坐标targetY{number} 缩放中心纵坐标stride{number} 缩放步长(步长越大,缩放幅度越大)- 返回 {boolean}
模拟双指放大操作,以指定坐标为中心放大屏幕内容(如图片、页面)。
以屏幕中心为中心,步长20放大
var x = device.width / 2;
var y = device.height / 2;
$hid.esp32otg.zoomIn(x, y, 20);
sleep(1000)
$hid.esp32otg.zoomIn(x, y, 20);
sleep(1000)
$hid.esp32otg.zoomIn(x, y, 20);$hid.esp32otg.zoomOut(targetX, targetY, stride)
targetX/targetY{number} 缩放中心坐标stride{number} 缩放步长- 返回 {boolean}
模拟双指缩小操作,以指定坐标为中心缩小屏幕内容。
以屏幕中心为中心,步长20缩小
var x = device.width / 2;
var y = device.height / 2;
$hid.esp32otg.zoomOut(x, y, 20);
sleep(1000)
$hid.esp32otg.zoomOut(x, y, 20);
sleep(1000)
$hid.esp32otg.zoomOut(x, y, 20);示例
全功能测试脚本
/**
* ESP32 OTG HID 全功能演示
* 流程:初始化 → 连接 → 状态检查 → 操作演示 → 结束
*/
// ==================== 初始化 ====================
toastLog("正在初始化 OTG 模块...");
$hid.esp32otg.init();
// ==================== 连接设备 ====================
toastLog("正在连接 ESP32 设备...");
if (!$hid.esp32otg.connect()) {
toastLog("ESP32 设备连接失败");
console.error("连接失败");
exit();
}
// ==================== 状态检查 ====================
var state = $hid.esp32otg.state();
if (!state) {
toastLog("设备未连接,结束测试");
exit();
}
toastLog("OTG 连接成功!");
console.log("当前状态:", state);
// ==================== 系统按键演示 ====================
toastLog("5秒后执行 返回键");
sleep(5000);
$hid.esp32otg.back();
toastLog("5秒后执行 任务键");
sleep(5000);
$hid.esp32otg.recents();
toastLog("5秒后执行 主页键");
sleep(5000);
$hid.esp32otg.home();
// ==================== 坐标提示 ====================
toastLog("请开启 开发者选项 → 指针位置\n可查看触控坐标");
// ==================== 点击中心点 ====================
var x = device.width / 2;
var y = device.height / 2;
toastLog("5秒后点击屏幕中心点\n(" + x + ", " + y + ")");
sleep(5000);
$hid.esp32otg.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.esp32otg.swipe(x1, y1, x2, y2, 1000);
// ==================== 结束 ====================
toastLog("ESP32 OTG HID 测试完成!");
console.log("测试流程结束");HID 控件节点查找点击
HID 控件请参见
// 初始化 OTG HID 模块(仅需调用一次,阻塞操作,请勿在 UI 线程执行)
$hid.esp32otg.init(context);
// 连接 ESP32 设备(仅需连接一次,建议在脚本启动时执行,阻塞操作,请勿在 UI 线程执行)
$hid.esp32otg.connect();
// ==================== 状态检查 ====================
var state = $hid.esp32otg.state();
if (!state) {
toastLog("设备未连接,结束测试");
exit();
}
toastLog("OTG 连接成功!");
console.log("当前状态:", state);
//然后下面就可以写具体的自动化业务操作逻辑了
var uiObject = selector(1).desc("任务管理").className("android.widget.LinearLayout").visibleToUser(true).findOne(1000);
if (uiObject) {
$hid.esp32otg.click(uiObject.bounds().centerX(), uiObject.bounds().centerY());
sleep(1000);
} else {
toastLog("未找到符合条件的控件");
}HID YOLO目标检测点击
YOLO 基于深度学习目标检测模型进行图像推理,可自动识别画面中的目标对象,不依赖固定分辨率与坐标规则,适用于游戏界面、复杂动画场景等传统找图难以处理的画面环境。
通常可与 OCR 文字识别结合使用,实现对图像目标与文本信息的综合自动化控制。
// 初始化 OTG HID 模块(仅需调用一次,阻塞操作,请勿在 UI 线程执行)
$hid.esp32otg.init(context);
// 连接 ESP32 设备(仅需连接一次,建议在脚本启动时执行,阻塞操作,请勿在 UI 线程执行)
$hid.esp32otg.connect();
// ==================== 状态检查 ====================
var state = $hid.esp32otg.state();
if (!state) {
toastLog("设备未连接,结束测试");
exit();
}
toastLog("OTG 连接成功!");
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.esp32otg.click(yoloObject.bounds().centerX(), yoloObject.bounds().centerY());
sleep(2000);
// 如果只需要点一个目标,可直接跳出循环
break;
}
}
//在不需要时记得释放模型资源
yolo.release();HID 找图查找点击
通过截图获取当前屏幕图像,使用找图算法定位目标位置,获取坐标后通过 HID 模拟点击。
// ==================== 初始化与连接 ====================
// 初始化 OTG HID 模块(仅需调用一次,阻塞操作,请勿在 UI 线程执行)
$hid.esp32otg.init(context);
// 连接 ESP32 设备(仅需连接一次,建议在脚本启动时执行,阻塞操作,请勿在 UI 线程执行)
$hid.esp32otg.connect();
// 等待设备建立连接
sleep(3000);
// ==================== 状态检查 ====================
if (!$hid.esp32otg.state()) {
toastLog("ESP32 OTG HID 未连接");
exit();
}
// 已连接
console.log("ESP32 OTG HID 已连接");
// ==================== 截取当前屏幕(一共有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.esp32otg.click(x, y);
sleep(2000);
} else {
toastLog("未找到目标图片");
}
// 释放小图片资源
targetImg.recycle();HID OCR文字识别找字点击
// ==================== 初始化与连接 ====================
// 初始化
$hid.esp32otg.init();
// 发起连接
$hid.esp32otg.connect();
// 等待设备建立连接
sleep(3000);
// 获取连接状态
if (!$hid.esp32otg.state()) {
toastLog("ESP32 OTG HID 未连接");
exit();
}
// 已连接
console.log("ESP32 OTG HID 已连接");
// 加载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.esp32otg.click(x, y);
sleep(2000);
break;
}
}
}
toastLog(`第${i + 1}次检测: ${end - start}ms`);
sleep(3000);
}
ocr.release();总结
基础流程固定
所有 HID 操作必须遵循统一流程:
初始化 OTG 模块 → 连接 ESP32 设备 → 状态检查 → 业务自动化操作
其中:
$hid.esp32otg.init()与$hid.esp32otg.connect()仅需执行一次- 建议每次操作前通过
$hid.esp32otg.state()确认连接状态
文本输入推荐方案
英文、数字: 使用
$hid.esp32otg.input()直接模拟键盘输入中文、特殊字符: 推荐使用 剪贴板 + 粘贴方案:
jssetClip("需要输入的中文内容"); $hid.esp32otg.paste();复杂输入场景建议配合专业输入模块(如 $input)
权限与稳定性建议
- 使用
$hid.esp32otg.checkPermissions()检查蓝牙相关权限 - 操作前确认蓝牙已开启及设备已连接,避免指令执行失败
- 使用
- 截图方式灵活选择
具体可参阅屏幕截图的 7 种方式
目标定位方式多样
HID 并不限制坐标来源,可结合多种识别方式获取目标位置:
