超视距遥操(Teleop)示例
超视距遥操(Teleop)示例
⚠️ 尚未上线:本能力为 v1.5.0-SNAPSHOT 开发中特性,接口与协议可能调整,正式发布前请勿用于生产环境。
v1.5.0 新增。完整的 Java 端最小示例,展示
enter → startAudio → appendAudioDelta → doneAudio → exit全流程。示例源码位于仓库agentsdk_for_java/example/src/main/java/com/agibot/aiem/teleop/TeleopExample.java。
最小示例:TeleopExample.java
java
package com.agibot.aiem.teleop;
import com.agibot.aiem.sdk.AgentAuthCallback;
import com.agibot.aiem.sdk.AgentParam;
import com.agibot.aiem.sdk.AgentSdk;
import com.agibot.aiem.sdk.IdGenerator;
import com.agibot.aiem.sdk.teleop.TeleopEnterCallback;
import com.agibot.aiem.sdk.teleop.TeleopExitCallback;
import com.agibot.aiem.sdk.teleop.TeleopKeepaliveCallback;
import com.agibot.aiem.sdk.teleop.TeleopRequest;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class TeleopExample {
public static void main(String[] args) throws InterruptedException {
String url = "wss://open.agibot.com/api/V1/open-portal/app/wss/agent-sdk";
String appId = "您通过灵心开放平台创建的应用获取的appId";
String appKey = "您通过灵心开放平台创建的应用获取的appKey";
String appSecret = "您通过灵心开放平台创建的应用获取的appSecret";
String agentId = "您通过灵心平台创建的二开智能体获取的agentId";
// 第一步:创建 SDK 实例
AgentSdk agentSdk = AgentSdk.create(url, appId, appKey, appSecret);
// 第二步:注册验签回调接口
agentSdk.registerAuth(new AgentAuthCallback() {
@Override
public void onAuthState(String appId, int code, String msg) {
System.out.println("onAuthState => appId: " + appId
+ ", code: " + code + ", msg: " + msg);
}
});
// 第三步:初始化
agentSdk.initialize();
Thread.sleep(2000);
// 注册遥操请求实例
String teleopId = IdGenerator.generateTeleopId();
TeleopRequest teleopRequest = new TeleopRequest(agentSdk, agentId, teleopId);
agentSdk.registerTeleop(teleopRequest);
// 进入遥操
AgentParam enterParam = AgentParam.create();
teleopRequest.enter(enterParam, new TeleopEnterCallback() {
@Override
public void onEnterAck(String teleopId, String eventId, int code, String msg) {
log.info("onEnterAck => teleopId {}, eventId {}, code {}, msg {}", teleopId, eventId, code, msg);
}
}, 2000);
// 开始说话
AgentParam startParam = AgentParam.create();
startParam.setString("role", "male"); // male/female
startParam.setInteger("threshold", 0); // -14 - 14
String eventId = teleopRequest.startAudio(startParam);
// 持续说话(这里以空字符串占位,实际传 base64 编码后的 PCM/Opus 分片)
teleopRequest.appendAudioDelta(eventId, "");
// 结束说话
teleopRequest.doneAudio(eventId);
// 检查机器人是否在线(详见「定时探活」小节,遥操期间应每 10s 探活一次)
teleopRequest.keepalive(new TeleopKeepaliveCallback() {
@Override
public void onKeepaliveAck(String teleopId, String eventId, int code, String msg) {
log.info("onKeepaliveAck => teleopId {}, eventId {}, code {}, msg {}", teleopId, eventId, code, msg);
}
}, 2000);
// 退出遥操
teleopRequest.exit(new TeleopExitCallback() {
@Override
public void onExitAck(String teleopId, String eventId, int code, String msg) {
log.info("onExitAck => teleopId {}, eventId {}, code {}, msg {}", teleopId, eventId, code, msg);
}
}, 2000);
// 注销并释放(示例省略)
// agentSdk.unregisterTeleop(teleopId);
// agentSdk.release();
}
}
定时探活(keepalive)
enter 拿到 code == 0 之后,业务侧应每 10 秒发起一次 keepalive 探活;onKeepaliveAck 收到 code != 0 即视为机器人离线,需停止定时、退出遥操、注销资源。
java
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
ScheduledExecutorService keepaliveScheduler = Executors.newSingleThreadScheduledExecutor(r -> {
Thread t = new Thread(r, "teleop-keepalive");
t.setDaemon(true);
return t;
});
AtomicBoolean robotOnline = new AtomicBoolean(true);
keepaliveScheduler.scheduleAtFixedRate(() -> {
if (!robotOnline.get()) return;
teleopRequest.keepalive(new TeleopKeepaliveCallback() {
@Override
public void onKeepaliveAck(String teleopId, String eventId, int code, String msg) {
if (code == 0) return;
if (!robotOnline.compareAndSet(true, false)) return;
log.warn("robot offline => code={}, msg={}", code, msg);
keepaliveScheduler.shutdown();
teleopRequest.exit(new TeleopExitCallback() {
@Override
public void onExitAck(String teleopId, String eventId, int code, String msg) {
agentSdk.unregisterTeleop(teleopId);
}
}, 2000);
}
}, 2000);
}, 10, 10, TimeUnit.SECONDS);
业务侧主动 exit 后,也应 keepaliveScheduler.shutdown() 停止发送探活。
常见改写要点
| 想做 | 改哪里 |
|---|---|
| 一次遥操中间多次讲话 | 每次讲话都重新 startAudio(startParam) 拿到新的 eventId,appendAudioDelta / doneAudio 使用该 eventId,无需 exit 再 enter |
| 切换音色 / 灵敏度 | 每一段 startAudio 时重新填 AgentParam.role / threshold;不影响前一段音频 |
| 中途取消遥操 | 直接 exit(...),不再补发 doneAudio |
| 感知 SDK 鉴权 / 断连 | 在 AgentAuthCallback.onAuthState 里维护一个 authed 标志,enter 前 double check;或在 onEnterAck 收到 code == 1000 后触发重连 |
| 多机器人同时遥操 | 每个 agentId 建一个 TeleopRequest;SDK 按 teleopId 索引,互不冲突 |