3.12 ExtensionClient 插件
概述
Arm::extensionClient 提供插件查询、详情读取、启停切换和 EasyService 调用能力。
3.12.1 公开方法
cpp
GetRobotIp() -> std::string
GetList() -> std::pair<std::vector<ExtensionInfo>, STATUS_CODE>
Get(const std::string& name) -> std::pair<ExtensionInfo, STATUS_CODE>
Toggle(const std::string& name) -> STATUS_CODE
CallService(const std::string& name, const std::string& command, const Json::Value& params = {}) -> std::pair<std::string, STATUS_CODE>| 方法 | 说明 | 返回 |
|---|---|---|
GetRobotIp | 根据机器人本体侧运行环境推断机器人 IP | std::string |
GetList | 获取插件列表 | std::pair<std::vector<ExtensionInfo>, STATUS_CODE> |
Get | 获取单个插件详情 | std::pair<ExtensionInfo, STATUS_CODE> |
Toggle | 切换插件启用状态 | STATUS_CODE |
CallService | 调用 EasyService 插件服务 | std::pair<std::string, STATUS_CODE> |
3.12.2 前置条件与连接依赖
| 项 | 规则 |
|---|---|
Connect | GetList / Get / Toggle / CallService 都需要先完成 Arm::Connect() |
teachPanelIp | ExtensionClient 使用 Arm::Connect() 后的示教器地址;连接未完成或绑定失败时,以上四个接口返回 NOT_CONNECTED |
GetRobotIp | 机器人本体侧非 Linux 环境直接返回空字符串;Linux 环境下若尚未连接,也会返回空字符串 |
3.12.3 GetRobotIp() 行为
- 非 Linux 环境直接返回空字符串。
- 机器人本体侧 Linux 容器环境中,若主机名匹配
tp-connect-robot*,会尝试读取eth0IPv4。 - 机器人本体侧 Linux
teachbox/forlinx环境中,会通过机器人本体侧 Pure Web 服务查询控制器地址;若连接信息未绑定、HTTP 失败或返回内容不合法,返回空字符串。 - 其他未识别环境返回空字符串。
- 该接口没有状态码返回,调用方应把空字符串视为 “当前环境不可推断”。
3.12.4 参数校验
| 项 | 规则 |
|---|---|
name / command | 不能为空,且只允许 A-Z a-z 0-9 . _ - |
params | 只接受 JSON 对象 |
params 值类型 | 仅支持字符串、有限数字、布尔;数组、 null 、嵌套对象、 NaN/Inf 返回 INVALID_PARAMETER |
Get / Toggle | name 非法时返回 INVALID_PARAMETER |
CallService | name / command 任一非法时返回 INVALID_PARAMETER |
3.12.5 行为约定
GetRobotIp()可以直接调用,但并不保证在所有环境下都能在Connect()前拿到有效 IP。GetList()/Get()在 HTTP 非200、JSON 解析失败或返回结构不匹配时返回OTHER_ERR。GetList()/Get()对缺失字段按默认值补齐,结构口径见 2.4-extension-types。Toggle()使用180sHTTP 超时;其余插件查询沿用默认超时。CallService()成功时返回result的紧凑 JSON 文本: 字符串结果会保留引号。result缺失或为null时,CallService()返回OTHER_ERR。params为空对象{}时,请求路径为不带 query string 的GET /{name}/{command}。params中的键值会被平铺成 query string,不支持数组或嵌套对象。
3.12.6 服务端端口
| 端口 | 用途 |
|---|---|
5613 | 机器人本体侧 Pure Web 服务,用于 GetRobotIp() 环境探测 |
5615 | 机器人本体侧插件列表与详情服务 |
5616 | 机器人本体侧 EasyService 调用服务 |
3.12.7 最小调用示例
cpp
#include <iostream> // 引入标准输出流,用于打印插件查询结果
#include "arm_api.h" // 引入 Arm 主入口,连接后通过 arm.extensionClient 访问插件接口
#include "json/json.h" // 引入 Json::Value,用于构造 EasyService 参数
#include "status_code.h" // 引入 STATUS_CODE,用于检查 SDK 调用结果
int main() // 示例程序入口
{ // 进入示例主函数
Arm arm; // 创建机器人会话对象
STATUS_CODE connectRet = arm.Connect("192.168.110.2", ""); // 连接控制器,示教器地址留空表示使用默认规则
if (connectRet != STATUS_CODE::OK) { // 判断连接是否失败
return 1; // 连接失败时直接退出
} // 结束连接结果判断
const std::string robotIp = arm.extensionClient.GetRobotIp(); // 根据当前运行环境推断机器人 IP
auto [items, listRet] = arm.extensionClient.GetList(); // 获取机器人本体上的插件列表
if (listRet != STATUS_CODE::OK) { // 判断插件列表查询是否失败
return 1; // 查询失败时返回错误码
} // 结束插件列表查询判断
std::cout << "robot_ip=" << robotIp << "\n"; // 打印推断出的机器人 IP
std::cout << "extension_count=" << items.size() << "\n"; // 打印插件数量
if (items.empty()) { // 判断当前是否没有插件
return 0; // 没有插件时示例直接正常结束
} // 结束插件空列表判断
Json::Value params(Json::objectValue); // 创建 EasyService 调用参数对象
params["example"] = "sdk"; // 写入一个示例字符串参数
auto [result, callRet] = arm.extensionClient.CallService( // 调用第一个插件的 EasyService 服务
items[0].extension.name, // 使用插件列表里第一项的插件名
"echo", // 调用名为 echo 的服务命令
params // 传入 JSON 对象参数
); // 结束 EasyService 调用
if (callRet != STATUS_CODE::OK) { // 判断服务调用是否失败
return 1; // 调用失败时返回错误码
} // 结束服务调用结果判断
std::cout << "echo_result=" << result << "\n"; // 打印 EasyService 返回的结果文本
return 0; // 示例正常结束;Toggle 会修改插件状态,最小示例不主动执行
} // 结束示例主函数场景化示例
下面几组片段按 “环境信息、列表详情、服务调用、启停插件” 交叉覆盖本页 API。片段默认承接最小调用示例里已经连接成功的 arm 对象; Toggle 会改变插件启用状态,确认后再执行。
查询机器人 IP 和插件列表
cpp
std::string robotIp = arm.extensionClient.GetRobotIp(); // 推断当前环境下的机器人 IP
auto [extensions, listRet] = arm.extensionClient.GetList(); // 获取插件列表
if (listRet == STATUS_CODE::OK) { // 判断插件列表查询是否成功
std::cout << "robot_ip=" << robotIp << " extension_count=" << extensions.size() << "\n"; // 打印机器人 IP 和插件数量
} // 结束插件列表查询判断查询插件详情并调用服务
cpp
const std::string name = "demo_extension"; // 准备插件名称,实际使用时替换为 GetList 返回的插件名
auto [detail, getRet] = arm.extensionClient.Get(name); // 查询单个插件详情
Json::Value params(Json::objectValue); // 准备 CallService 使用的 JSON 参数对象
params["example"] = "sdk"; // 写入示例参数
auto [result, callRet] = arm.extensionClient.CallService(name, "echo", params); // 调用 EasyService 服务
if (getRet == STATUS_CODE::OK || callRet == STATUS_CODE::OK) { // 判断详情查询或服务调用是否成功
std::cout << "extension_name=" << detail.extension.name << " service_result=" << result << "\n"; // 打印详情和服务结果摘要
} // 结束插件接口结果判断切换插件启用状态
cpp
const std::string name = "demo_extension"; // 准备插件名称,实际使用时替换为目标插件名
// STATUS_CODE toggleRet = arm.extensionClient.Toggle(name); // 切换插件启用状态会影响插件运行,确认后再执行示例代码
cpp
#include "query_extension_info/run.h"
#include "call_extension_service/run.h"
int main(void)
{
// [ZH] 默认只调用一个门面方法;如需体验其他接口,请把下一行替换成下面任意一行。
// [EN] The main function calls only one facade by default. Replace the next line with any line below to try other APIs.
return RunExtensionBasicQueryExtensionInfo();
// return RunExtensionBasicCallExtensionService();
}cpp
#include <stdio.h>
extern "C" {
#include "c_arm_api.h"
}
int main(void)
{
// [ZH] 本示例直接在源码中写死连接地址,不解析命令行参数。
// [EN] This example hard-codes the connection addresses in the source code and does not parse command-line arguments.
// [ZH] 创建并连接 SDK 句柄。
// [EN] Create the SDK handle and connect to the robot.
ArmHandle* handle = Arm_Create();
if (handle == NULL) {
printf("[c99_extension] 创建句柄失败 / Failed to create the handle\n");
return 1;
}
int ret = Arm_Connect(handle, "10.27.1.2", "10.27.1.102");
if (ret != 0) {
printf("[c99_extension] 连接失败 / Connect failed, 状态码 / Status code: %d\n", ret);
Arm_Destroy(handle);
return 1;
}
printf("[c99_extension] 机器人连接成功 / Robot connected successfully\n");
// [ZH] 顺序执行全部插件接口。
// [EN] Execute all extension APIs in sequence.
char robotIp[256] = {0};
char listJson[4096] = {0};
char detailJson[4096] = {0};
char resultJson[4096] = {0};
ret = Arm_Extension_GetRobotIp(handle, robotIp, sizeof(robotIp));
printf("[c99_extension] GetRobotIp 状态码 / GetRobotIp status code: %d, 机器人 IP / Robot IP: %s\n", ret, robotIp);
ret = Arm_Extension_GetList(handle, listJson, sizeof(listJson));
printf("[c99_extension] GetList 状态码 / GetList status code: %d, 列表 JSON / List JSON: %s\n", ret, listJson);
ret = Arm_Extension_Get(handle, "demo", detailJson, sizeof(detailJson));
printf("[c99_extension] Get 状态码 / Get status code: %d, 详情 JSON / Detail JSON: %s\n", ret, detailJson);
ret = Arm_Extension_CallService(handle, "demo", "echo", "{\"example\":\"sdk\",\"count\":1}", resultJson, sizeof(resultJson));
printf("[c99_extension] CallService 状态码 / CallService status code: %d, 返回值 / Result: %s\n", ret, resultJson);
ret = Arm_Extension_Toggle(handle, "demo");
printf("[c99_extension] Toggle 状态码 / Toggle status code: %d\n", ret);
// [ZH] 断开连接并销毁句柄。
// [EN] Disconnect and destroy the handle.
Arm_Disconnect(handle);
Arm_Destroy(handle);
printf("[c99_extension] 示例结束 / Example finished\n");
return 0;
}