Skip to content

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根据机器人本体侧运行环境推断机器人 IPstd::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 前置条件与连接依赖

规则
ConnectGetList / Get / Toggle / CallService 都需要先完成 Arm::Connect()
teachPanelIpExtensionClient 使用 Arm::Connect() 后的示教器地址;连接未完成或绑定失败时,以上四个接口返回 NOT_CONNECTED
GetRobotIp机器人本体侧非 Linux 环境直接返回空字符串;Linux 环境下若尚未连接,也会返回空字符串

3.12.3 GetRobotIp() 行为

  • 非 Linux 环境直接返回空字符串。
  • 机器人本体侧 Linux 容器环境中,若主机名匹配 tp-connect-robot* ,会尝试读取 eth0 IPv4。
  • 机器人本体侧 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 / Togglename 非法时返回 INVALID_PARAMETER
CallServicename / command 任一非法时返回 INVALID_PARAMETER

3.12.5 行为约定

  • GetRobotIp() 可以直接调用,但并不保证在所有环境下都能在 Connect() 前拿到有效 IP。
  • GetList() / Get() 在 HTTP 非 200 、JSON 解析失败或返回结构不匹配时返回 OTHER_ERR
  • GetList() / Get() 对缺失字段按默认值补齐,结构口径见 2.4-extension-types。
  • Toggle() 使用 180s HTTP 超时;其余插件查询沿用默认超时。
  • 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);  // 切换插件启用状态会影响插件运行,确认后再执行

示例代码

cpp17/extension_basic/src/main.cpp
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();
}
c99/extension_basic/src/main.cpp
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;
}