BLOG

技术拆解 026|esp32-iphone-agent:7 美元 ESP32 让 AI 操作真 iPhone

Kael Zhang
技术拆解esp32-iphone-agent手机 AgentESP32BLE 协议
广告 · Advertisement

10 月 11 日,个人开发者 onehumanbeing 在 GitHub 开源了 esp32-iphone-agent,四天冲到 2418★、322 forks(GitHub API,10-16 快照)。热度几乎全部来自 GitHub trending 和技术社区转发:它在 Hacker News 上的 story 只有 2 个赞、0 条评论(Algolia 核实),传播力很弱,这点先说清楚。项目本身的卖点一句话能讲完:一块约 7 美元的 ESP32-S3 开发板当「眼睛」和「手」,AI 大脑跑在同一部 iPhone 的 app 里,让视觉模型操作一台真实 iPhone,全程不需要电脑、不需要越狱、不需要开发者账号。MIT 许可。本文按老规矩拆六段。

一、它是什么

iPhone 的屏幕镜像列表里会多出一个叫「ESP32 Agent」的接收器,那是板子自己开的 Wi-Fi 热点加板载 AirPlay 接收器。iPhone 把屏幕镜像给板子,板子不解码,把 H.264 流经 BLE 转发回同一部 iPhone 上的 app;app 把截图发给任何 OpenAI 兼容的视觉模型,模型决定动作,指令再经 BLE 回到板子,板子以标准 USB HID 鼠标键盘的身份插回 iPhone,配合系统自带的 AssistiveTouch(辅助触控)完成点击和滑动。眼睛、手、大脑三件套,硬件成本一块 7 美元板子,软件成本一个自建 app。

同类项目对照能看清它的差异化位置。boboabw/phone-agent 最接近:也是 ESP32-S3 蓝牙 HID 加 AssistiveTouch 加 iPhone app 当大脑,但它没有「眼睛」,模型看不到屏幕。VersaiOS 用 UxPlay 在电脑上做镜像,需要一台电脑,且一条指令只点一次。ja1chen/actell 走 Apple CoreDevice 调试通道,需要开发者模式和 Developer Disk Image。mobile-mcp、Midscene 这类 WebDriverAgent 系方案需要 Mac 加代码签名。本项目的独特之处是把 AirPlay 接收也搬到了板子上,从硬件层面把电脑这个环节删掉了。

二、仓库结构

先做一个小考据:GitHub 的语言标签和实际实现主力不符。本地统计(排除 .git,190 个文件)Swift 有 11621 行,是绝对主力,对应 ios/ 目录下的 app,还带 13 个测试文件;C 只有 2793 行,集中在 hardware/,主体是从 UxPlay 移植的 AirPlay 接收器和 playfair 的 FairPlay 认证实现;C++ 800 行是 ESP32 固件的 HID 桥;Python 1793 行在 server/ 目录,但 CHANGELOG 明写「server/ 不再需要」,那是 v0.1.0 电脑端版本的残留,别当成活跃代码。这和 025 期拆 pg_vectorsearch 时遇到的语言标签偏差是同一类现象。

架构演进是这个项目最值得看的叙事。v0.1.0 是电脑端方案:UxPlay 加 Python server 加 web UI,ESP32 只是 Wi-Fi 上的 USB HID 桥,必须有一台 Mac 或 Linux 电脑中转。当前 main 分支完成了「电脑消失」的重构:板子自己当 AirPlay 接收器,自建热点,经 BLE 跟全新的 iPhone app 通信,提示词收进 prompts/ 目录,产品定名 ESP32 Agent。四天冲上 2400 星,冲的就是这个极简形态。

另一个要诚实交代的数字:commit 总数 29,contributors API 返回单一主力贡献者。这是一个单人项目,不是社区工程。

三、机制拆解

三个关键机制逐个拆。

第一是 BLE 视频透传。板子算力弱,硬解 H.264 不现实,作者的取舍是根本不解码:AirPlay 收到的 H.264 流原样切成 chunk,经 BLE notify 转发给手机,解码交给 iPhone 自己。docs/ble-protocol.md 写得相当规范:板子是 BLE peripheral,一个 service 下挂五个特征值,cmd 收命令行、reply 回结果、status 每秒发一条 JSON 心跳(兼作 app 后台保活)、video 传 H.264 chunk、net 走加密通道配网,安全用 LE Secure Connections 加 bonding。video 通道每个 notify 带 16 位序号和标志位,app 数序号缺口判丢包,丢了就等下一个 IDR 关键帧重新对齐;stream 模式下超过 800 毫秒的 P 帧直接跳过,带宽不足时自动退化成只发关键帧而不是越积越延迟。status 那条每秒心跳也值得一看,它一行 JSON 里塞了运行时长、复位原因、堆和 PSRAM 余量、USB 状态、热点连接数、当前码率、实际帧率、BLE 的 MTU 和物理层速率、丢包计数,等于把整条数据通路的健康度实时摊开给 app;MTU 太小时固件自动降级发精简对象,读 status 则总能拿到完整那份。发送优先级也定了规矩:reply 和 status 永远排在 video 前面,video 在控制器里最多压约 8 个 ACL 包,指令不会被视频流饿死。固件里还有 coex 命令调 Wi-Fi 和 BLE 的射频共存偏好,这两者抢同一根天线,是 ESP32-S3 上做这件事绕不开的工程细节,默认每次开机都回到 balance。

第二是指针校准的反馈回路。USB HID 鼠标在 iOS 上是相对定位,模型给的又是截图上的绝对坐标,两者之间隔着一层漂移:指针当前位置只能靠 app 从历史移动量推算,误差会累积。作者的解法是把校准做成例行动作:app 持续跟踪指针并在屏幕角落「归位」,精确点击前先执行 wiggle,晃动指针、在最新截图里用视觉模型找到它、纠正推算偏差,再落点。actor.md 里 tap 命令带一个 precise 参数,小目标和密集排列的元素(列表行、开关、勾选框)走这条慢一秒但更准的路径。每步动作之后等屏幕稳定,把「屏幕有没有变化」喂回模型,没变化就说明这一下没点中,模型被明确要求不得假设成功,要重新瞄准或换方法。板子、热点或镜像掉线则暂停任务,恢复后从同一步继续,README 称之为 self-healing。

第三是提示词工程,这是全项目最有借鉴价值的部分。planner.md 要求模型看目标和当前屏幕写最多 6 步的编号计划,只基于所见,绝不臆造没见过的账户、邮箱或登录页。actor.md 更细:输出固定为 THINK 加 DO 两段,THINK 要用非技术用户能看懂的英文先核对上一步是否生效;坐标是 0 到 1000 的相对整数;核心纪律是「look before you act」,只描述屏幕上真实存在的东西,只点截图上看得见的元素;swipe 没有惯性,偏好 100 到 250 单位的短滑并检查结果;时间滚轮先点中心行再直接键入数字(比如 type 0700);列表查找每次滚动不到一屏、读完每个可见项,滚到两端还没有就 fail 并报告最接近的选项。动作集覆盖 tap、swipe、path(2 到 20 点的连续笔画,用来绘画)、circle、type、key、home、back、wait、replan、done、fail。这套提示词把「视觉 agent 如何可靠操作 GUI」的坑几乎全部前置写死了。

至于板子凭什么能被 iPhone 认作合法 AirPlay 目标:hardware/ 里的 playfair 代码(omg_hax.c、hand_garble.c、sap_hash.c 等)是从 UxPlay 移植的 FairPlay 配对认证的逆向实现,血统和措辞都按「移植/逆向」理解,UxPlay 本身就是知名的开源 AirPlay 接收器项目。

四、数字与验证

硬件清单很短:作者用 Seeed Studio XIAO ESP32S3 普通版做的验证,8MB PSRAM,约 7 美元;README 称任何带原生 USB(USB-C 口)和 PSRAM 的 ESP32-S3 应该都能用。镜像默认 480×1040、5fps,可用 res 和 fps 命令改,存 NVS。BLE 实际带宽约 300 到 500 kbps,这就是分辨率和帧率的上限;agent 每步动作要几秒,大头耗在模型推理上。app 运行时手机 Wi-Fi 连的是板子热点,没有互联网,模型调用走蜂窝数据。

限制清单是 README 原文列的,比卖点清单还长,照录:BLE 带宽导致镜像小、帧率低;iOS 不镜像密码输入、Apple Pay、DRM 视频,锁屏时镜像停止,这些场景 agent 是瞎的;app 用私有 iOS API(suspend)实现后台常驻,自建使用没问题,上架 App Store 前必须替换;键盘输入仅 ASCII;横屏 app 不支持。Roadmap 上未完成的还有:横屏、非 ASCII 输入(比如中文拼音)、单次模型调用输出多动作提速。版本要求 iOS 18 以上,对系统更新敏感。

验证维度再补三个数:HN story 2▲ 0 评论,传播力弱是事实;29 个 commit、单一主力贡献者,可持续性待观察;ios/ 目录带 13 个测试文件,单人项目写到这个份上算克制且认真。README 还有一段 Responsible use:只自动化你拥有或被授权的设备与账户,agent 用你的手行动,运行时要盯着它,停止键放在手边。

五、判断

三处值得说。

第一,这是工程取巧而不是硬破解。整个方案没有碰 iOS 的任何安全边界:AirPlay 镜像是系统功能,USB HID 是标准外设协议,AssistiveTouch 是无障碍特性,把「模型的点击意图」翻译成「iOS 自愿接受的鼠标输入」,每一步都走在系统允许的接口上。playfair 的 FairPlay 逆向来自 UxPlay 的既有公开实现,不是本项目新开的洞。这种「在封闭生态的合法缝隙里搭桥」的思路,比任何越狱方案都更接近可长期维护的形态。

第二,「弱硬件加强模型」的分工值得抄。板子不做任何智能工作,只当带宽有限的管道和忠实的手;解码、视觉、规划全在手机和云端。BLE 透传不解码、wiggle 校准相对指针、每步反馈屏幕是否变化,这三个机制解决的都是同一个问题:如何在不可靠的通道上构建可靠的反馈回路。做设备端 agent 的人可以直接借鉴,prompts/actor.md 甚至可以原样拿去改。

第三,边界要划清楚。单人项目、29 个 commit、HN 上几乎没有水花,star 涨得快靠的是「7 美元操作真 iPhone」这个叙事本身的传播力,不代表工程上有社区或商业支撑。iOS 每个大版本都可能动 AssistiveTouch 或 AirPlay 的行为,私有 API 的后台常驻更是悬着的剑。它是一个精巧的个人工程实验,评价它时应该用这个尺度,而不是「开源基建」的尺度。

顺带一个观察:README 把六条限制写在显眼位置,作者没有把项目吹成通用方案。限制清单比卖点清单长的 README,通常是健康开源项目的信号。

六、谁能用怎么用

适合的画像:手上有 iPhone(iOS 18+)和一块带原生 USB 加 PSRAM 的 ESP32-S3,愿意自己编译 iOS app(需要 Xcode 和免费 Apple ID 侧载,不需要付费开发者账号),想研究「视觉模型操作真机 GUI」这个方向的开发者和爱好者。用它自动化自己的日常操作前,先读一遍 Responsible use:只碰你拥有或被授权的设备与账户,跑任务时人别走开。

动手路径按 README:烧录 hardware/ 固件,板子开热点后在 iPhone 的屏幕镜像里选 ESP32 Agent,插上 USB 线,开启 AssistiveTouch,用 app 扫码或配对连上 BLE,填一个 OpenAI 兼容的视觉模型端点,就能下指令。每次运行会留在手机上,可逐步回放,tap 和 swipe 会画在对应截图上,复盘很方便。后台运行时灵动岛显示进度,还接了 Live Activity、widgets、Siri 和 Shortcuts。

不打算动手的人也值得读两样东西:docs/ble-protocol.md 是一份教科书级的 BLE 私有协议文档,从 UUID 分配、心跳保活到丢包恢复和射频共存都写清楚了;prompts/ 目录是少见的、把 GUI agent 操作纪律写透的公开提示词。这两份文件的价值不随项目本身的可持续性波动。


信息来源

  • 仓库身份(2418★/322 forks/创建与推送时间/MIT/topics):GitHub API repos/onehumanbeing/esp32-iphone-agent,10-16 快照
  • 代码规模(190 文件,Swift 11621 行、C 2793 行、C++ 800 行、Python 1793 行):本地浅 clone /tmp/eia-1016,find+wc 按扩展名统计,非 GitHub 语言标签
  • 架构与数据流、限制清单、Responsible use、硬件 BOM、同类项目对照:README(含中文版 README.zh-CN.md)原文
  • BLE 协议细节(五特征值、序号丢包、800ms P 帧跳过、coex、NVS 存储):docs/ble-protocol.md
  • 提示词纪律:prompts/planner.md、prompts/actor.md 原文
  • 架构演进(v0.1.0 电脑端到 main「电脑消失」):CHANGELOG
  • playfair/UxPlay 血统:hardware/hid_bridge/src/airplay/playfair/ 目录与 CHANGELOG「ported from UxPlay」记载
  • HN 传播力(story 50102527,2▲ 0 评论):HN Algolia 核实
  • 贡献者分布与 commit 总数(29):GitHub contributors API 与 commits Link header
广告 · Advertisement

常见问题

为什么用外接 ESP32 而不是软件方案控制 iPhone?

iOS 封闭生态没有系统级自动化 API,不越狱拿不到屏幕控制权。该方案把「眼睛」(AirPlay 接收+BLE 转发截图)和「手」(USB HID 输入)都放在外接硬件上,绕开全部软件限制,代价是引入 BLE 带宽瓶颈(约 300-500 kbps,决定截图分辨率与帧率上限)。

它怎么保证点击坐标准确?

三重校准回路:开机时的指针位置校准、动作后的截图回读验证、失败重试。USB HID 鼠标是相对定位,漂移不可避免,项目用「点一下-看一眼-再修正」的反馈回路收敛,本质是在不可靠通道上构建可靠操作。

普通用户能拿它做什么?风险是什么?

可用于自动化重复操作、无障碍辅助、真机测试。风险面:AssistiveTouch 校准依赖系统辅助功能,iOS 大版本更新可能破坏兼容性;任何能操作手机的 agent 也意味着新的攻击面,敏感账户操作不建议托管。