Open-AutoGLM如何查看设备列表?list_devices用法详解
Open-AutoGLM 是智谱开源的轻量级手机端 AI Agent 框架,专为在资源受限的本地环境运行多模态智能体而设计。它不依赖云端大模型推理服务也能完成基础屏幕理解与操作规划,但更常见的是作为“控制中枢”,连接远端部署的 AutoGLM-Phone 模型服务,实现自然语言驱动的真机自动化。
AutoGLM-Phone 是一个基于视觉语言模型的 AI 手机智能助理框架。它能以多模态方式理解屏幕内容,并通过 ADB 自动操控设备。用户只需用自然语言下指令,如“打开小红书搜美食”,模型即可解析意图、理解界面并自动规划、执行操作流程,无需手动点击。
Phone Agent 是基于 AutoGLM 构建的手机端智能助理框架,它能够以多模态方式理解手机屏幕内容,并通过自动化操作帮助用户完成任务。系统通过 ADB(Android Debug Bridge)来控制设备,以视觉语言模型进行屏幕感知,再结合智能规划能力生成并执行操作流程。用户只需用自然语言描述需求,如“打开小红书搜索美食”,Phone Agent 即可自动解析意图、理解当前界面、规划下一步动作并完成整个流程。系统还内置敏感操作确认机制,并支持在登录或验证码场景下进行人工接管。同时,它提供远程 ADB 调试能力,可通过 WiFi 或网络连接设备,实现灵活的远程控制与开发。
在实际使用中,“连上哪台设备”是所有操作的第一步。而list_devices()这个函数,就是 Open-AutoGLM 控制端最直接、最可靠的设备发现入口。它不依赖图形界面,不调用外部 shell 命令封装,而是通过 Python 原生逻辑与 ADB 协议深度交互,返回结构化、可编程的设备信息。本文将带你从零开始,彻底搞懂list_devices是什么、怎么用、为什么可靠,以及它在真实工作流中扮演的关键角色。
1. list_devices 是什么?不是 adb devices 的简单包装
list_devices()是 Open-AutoGLM 提供的一个核心工具函数,位于phone_agent.adb模块中。它看起来像adb devices的 Python 封装,但实际远不止于此。
1.1 它返回的是对象,不是字符串
当你在终端输入adb devices,得到的是类似这样的纯文本输出:
List of devices attached 0123456789ABCDEF device 192.168.1.100:5555 device而list_devices()返回的是一个List[Device]—— 每个Device都是一个带属性的 Python 对象,包含:
device_id: 设备唯一标识(如"0123456789ABCDEF"或"192.168.1.100:5555")state: 当前连接状态("device"、"offline"、"unauthorized"等)connection_type: 连接类型(USB、WIFI、UNKNOWN),这是adb devices原生不提供的关键信息is_online: 布尔值,是否真正可通信(会尝试 ping 或握手验证)
这意味着你不用再写正则去解析adb devices输出,也不用担心空格、换行、中文乱码等问题。直接用点号访问属性,代码清晰又健壮。
1.2 它做了三件事:发现 + 分类 + 验证
list_devices()的内部逻辑分三步执行:
- 执行
adb devices -l:获取带详细信息的设备列表(含 USB 序列号、型号、连接方式等) - 解析并归类:根据
transport_id、IP 地址格式、端口是否存在等,自动判断是 USB 还是 WiFi 连接 - 轻量级连通性探测:对每个设备 ID 尝试发送一个极简的
adb get-state命令,过滤掉已断开但未清理的“幽灵设备”
这使得它比裸调adb devices更适合集成进自动化脚本——你拿到的永远是“此刻真正可用”的设备清单。
2. 如何正确调用 list_devices?三种典型用法
list_devices()使用极其简单,但不同场景下调用方式略有差异。下面展示三种最常用、也最实用的用法。
2.1 基础用法:直接列出所有在线设备
这是最直观的方式,适合调试和快速确认环境状态。
from phone_agent.adb import list_devices devices = list_devices() if not devices: print(" 未检测到任何已连接的安卓设备") else: print(f" 发现 {len(devices)} 台在线设备:") for i, dev in enumerate(devices, 1): conn_type = "USB" if dev.connection_type.name == "USB" else "WiFi" status = "🟢 在线" if dev.is_online else "🔴 离线" print(f"{i}. {dev.device_id} | {conn_type} | {status}")运行后你会看到类似这样的输出:
发现 2 台在线设备: 1. 0123456789ABCDEF | USB | 🟢 在线 2. 192.168.1.100:5555 | WiFi | 🟢 在线注意:这里🟢和🔴是为了演示可读性加入的符号,实际生产代码中建议用文字(如[在线]/[离线]),避免终端兼容性问题。
2.2 条件筛选:只取 USB 设备或只取 WiFi 设备
在混合环境中(比如同时插着真机又连着模拟器),你可能只想操作某类设备。list_devices()返回的是标准 Python 列表,筛选非常自然:
from phone_agent.adb import list_devices from phone_agent.adb.enums import ConnectionType # 获取所有 USB 连接的设备 usb_devices = [d for d in list_devices() if d.connection_type == ConnectionType.USB] print(f"USB 设备:{[d.device_id for d in usb_devices]}") # 获取所有 WiFi 连接的设备(常用于远程测试) wifi_devices = [d for d in list_devices() if d.connection_type == ConnectionType.WIFI] print(f"WiFi 设备:{[d.device_id for d in wifi_devices]}") # 获取第一台可用的设备(常用在单设备 CI 流水线中) first_device = next((d for d in list_devices() if d.is_online), None) if first_device: print(f"默认使用设备:{first_device.device_id}") else: raise RuntimeError("没有找到可用设备,请检查 ADB 连接")这种写法完全摆脱了字符串匹配,语义清晰、IDE 可补全、类型安全,是工程化脚本的推荐写法。
2.3 结合 ADBConnection 使用:先连再查,确保上下文一致
list_devices()是独立函数,但它与ADBConnection类高度协同。后者管理连接生命周期,前者提供设备视图。典型配合如下:
from phone_agent.adb import ADBConnection, list_devices # 创建连接管理器(不立即连接任何设备) conn = ADBConnection() # 先列出所有设备,选一个目标 all_devices = list_devices() target_device = next((d for d in all_devices if d.is_online and d.connection_type == ConnectionType.USB), None) if not target_device: raise ValueError("未找到可用的 USB 设备") # 使用该设备 ID 建立连接上下文 success, msg = conn.connect(target_device.device_id) if not success: raise RuntimeError(f"连接失败:{msg}") print(f" 已成功连接至 {target_device.device_id}") # 此时你可以放心调用 conn 的其他方法,如截图、点击、输入等 # conn.screenshot("home.png") # conn.tap(100, 200)这种方式把“发现”、“选择”、“连接”三个步骤解耦又串联,逻辑清晰,便于单元测试和异常处理。
3. list_devices 的底层原理:它到底怎么工作的?
理解原理,才能用得更稳、排错更快。我们拆解list_devices()的执行链条。
3.1 第一步:调用 adb devices -l 并解析
list_devices()内部首先执行:
adb devices -l这个-l参数会输出设备的详细信息,例如:
List of devices attached 0123456789ABCDEF device product:star2 model:Redmi_K30_Ultra device:star2 transport_id:1 192.168.1.100:5555 device product:generic model:Android_SDK_built_for_x86 device:generic transport_id:2它会逐行解析,提取device_id(第一列)、state(第二列),并根据transport_id和 IP 格式推断connection_type。
3.2 第二步:连接类型智能识别
识别规则非常务实:
| device_id 格式 | 推断 connection_type | 依据 |
|---|---|---|
纯十六进制字符串(如0123...) | USB | ADB 默认 USB 设备 ID 格式 |
包含:且符合 IPv4/IPv6 + 端口(如192.168.1.100:5555) | WIFI | ADB over TCP/IP 标准格式 |
其他情况(如emulator-5554) | UNKNOWN | 保留扩展性 |
这个判断不依赖操作系统命令,纯 Python 实现,跨平台稳定。
3.3 第三步:轻量握手验证 is_online
对每个解析出的device_id,list_devices()会执行:
adb -s <device_id> get-state 2>/dev/null如果返回device,则is_online = True;如果超时、返回offline或报错,则设为False。这个过程耗时极短(通常 < 200ms),但能有效剔除adb devices显示为device实际已断开的“假在线”设备。
4. 常见问题与排查指南:为什么 list_devices 有时为空?
list_devices()返回空列表,是新手最常遇到的问题。别急,按以下顺序逐一排查,90% 的情况都能解决。
4.1 检查 ADB 是否真的可用
list_devices()本质依赖adb命令行工具。先确认它在终端中能正常运行:
# Windows/macOS/Linux 统一验证 adb version # 应输出类似:Android Debug Bridge version 1.0.41 adb devices # 应显示设备列表,且状态为 "device"(不是 "unauthorized" 或空白)如果adb version报错“command not found”,说明 ADB 未安装或未加入 PATH,请回看“硬件与环境准备”章节重新配置。
4.2 检查手机 USB 调试是否授权
这是最隐蔽的坑。即使adb devices显示设备 ID,如果手机弹出的“允许 USB 调试”对话框被忽略或点了“拒绝”,ADB 实际无法通信。
正确做法:
- 断开 USB 线
- 关闭手机开发者选项中的“USB 调试”
- 重新开启“USB 调试”
- 重新连接 USB 线
- 手机屏幕上必须出现授权弹窗,并点击“允许”
此时adb devices应显示device,list_devices()也会返回该设备。
4.3 检查 WiFi 连接是否真正生效
WiFi 连接需两步:先 USB 启用tcpip,再adb connect。很多人漏掉第一步:
# 必须先用 USB 连接执行(否则 adb connect 会失败) adb tcpip 5555 # 断开 USB,再连接 WiFi adb connect 192.168.1.100:5555验证 WiFi 连接是否成功:
adb devices # 应显示 IP:port adb -s 192.168.1.100:5555 shell getprop ro.product.model # 应返回手机型号如果list_devices()找不到 WiFi 设备,大概率是adb connect未成功,或手机与电脑不在同一局域网。
4.4 检查 Python 环境是否干净
list_devices()依赖subprocess调用系统adb。如果你在虚拟环境中安装了adb-shell或其他 ADB 封装库,可能造成冲突。
推荐做法:
- 不要
pip install adb(这是另一个同名库,非 Google ADB) - 确保
which adb(macOS/Linux)或where adb(Windows)指向你手动下载的 platform-tools 中的adb - 在 Python 中临时打印路径验证:
import subprocess result = subprocess.run(["adb", "--version"], capture_output=True, text=True) print("ADB 路径与版本:", result.stdout)
5. 进阶技巧:把 list_devices 变成你的自动化“设备管家”
list_devices()的价值不仅在于“看到设备”,更在于它能成为你自动化流程的智能调度起点。以下是两个真实可用的进阶模式。
5.1 多设备轮询:自动选择响应最快的设备
在 CI/CD 或批量测试场景中,你可能有多个设备待命。与其固定写死--device-id,不如让脚本自己选:
import time from phone_agent.adb import list_devices def select_fastest_device(): devices = list_devices() if not devices: raise RuntimeError("无可用设备") # 对每台设备测速:执行一个极简命令(如 get-state),记录耗时 speeds = [] for dev in devices: if not dev.is_online: continue start = time.time() try: # 不捕获输出,只看是否成功 subprocess.run( ["adb", "-s", dev.device_id, "get-state"], timeout=3, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL ) elapsed = time.time() - start speeds.append((dev, elapsed)) except Exception: continue if not speeds: raise RuntimeError("所有设备均无响应") # 返回耗时最短的设备 fastest_dev, _ = min(speeds, key=lambda x: x[1]) return fastest_dev # 使用 target = select_fastest_device() print(f"自动选择最快设备:{target.device_id}")这个技巧让脚本具备了“自适应”能力,特别适合云测平台或实验室多机房环境。
5.2 设备状态监控:做成一个常驻守护进程
你可以把它变成一个简单的设备看门狗,实时监控设备上下线:
import time from phone_agent.adb import list_devices def monitor_devices(interval=5): last_seen = set() print(" 设备监控已启动(Ctrl+C 停止)...") while True: current = {d.device_id for d in list_devices()} # 新增设备 new_devices = current - last_seen if new_devices: print(f" 新设备接入:{', '.join(new_devices)}") # 离线设备 gone_devices = last_seen - current if gone_devices: print(f"❌ 设备离线:{', '.join(gone_devices)}") last_seen = current time.sleep(interval) # 启动监控(在后台线程或单独脚本中运行) # monitor_devices()这种模式可用于无人值守的自动化测试机房,或作为开发调试时的辅助工具。
6. 总结:list_devices 是 Open-AutoGLM 的“设备感知神经”
list_devices()看似只是一个简单的工具函数,但它承载着 Open-AutoGLM 框架对设备连接层的深刻理解:它不只是罗列 ID,而是提供可编程的设备上下文;它不满足于“存在”,而追求“可用”;它不依赖黑盒命令,而通过结构化数据赋能上层逻辑。
掌握它,你就掌握了 Open-AutoGLM 自动化流程的第一把钥匙——从此,设备连接不再是靠人肉adb devices查看、复制、粘贴的繁琐步骤,而是一行代码、一次筛选、一个决策的自然延伸。
无论你是刚接触手机 AI Agent 的新手,还是正在构建企业级自动化平台的工程师,list_devices()都值得你花十分钟真正理解它、信任它、用好它。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。