4.13 로봇 구독 및 게시 인터페이스
개요
SubPub 클래스는 로봇 컨트롤러에 대한 WebSocket 구독/publish 채널 관리를 제공합니다. 연결을 설정하고, 로봇 status/register/IO 주제를 구독하고, 콜백 또는 차단 API를 통해 실시간 데이터를 수신하는 데 사용됩니다.
핵심 기능
- WebSocket 서버 연결 및 연결 해제 지원
- 로봇 상태 데이터 구독 지원
- 데이터 등록 구독 지원
- IO 신호 데이터 구독 지원
- 콜백 기능을 통한 지속적인 메시지 수신 지원
- 다음 메시지 수신 차단 지원
- 지원 설정 구독 빈도
- 메시지 수신 중 예외 처리 및 문제 해결 지원
사용 사례
- 호스트 측 로봇 작동 상태 실시간 모니터링
- 로봇 데이터 시각화 구현
- 외부 시스템과의 데이터 연계 실현
- 레지스터 및 IO 상태의 실시간 모니터링
- 로봇 모니터링 및 제어 시스템 구축
- 로봇 상태에 대한 실시간 알람 및 알림 구현
4.13.1 WebSocket 서버에 연결
| 메서드 이름 | SubPub.Connect() |
|---|---|
| 설명 | 로봇 컨트롤러 WebSocket 서버에 연결합니다. |
| 요청 매개변수 | 없음 |
| 반환 값 | 작업: 비동기 연결 작업 결과 |
| 호환 로봇 소프트웨어 버전 | 협업(Copper): v7.7.0.0+ 산업용(Bronze): v7.7.0.0+ |
4.13.2 WebSocket 서버에서 연결 끊기
| 메서드 이름 | SubPub.Disconnect() |
|---|---|
| 설명 | 로봇 컨트롤러 WebSocket 서버와의 연결을 끊습니다. |
| 요청 매개변수 | 없음 |
| 반환 값 | 작업: 비동기 연결 해제 작업 결과 |
| 호환 로봇 소프트웨어 버전 | 협업(Copper): v7.7.0.0+ 산업용(Bronze): v7.7.0.0+ |
4.13.3 로봇 상태 구독 추가
| 메서드 이름 | SubPub.SubscribeStatus(RobotTopicType[] topicTypes , int frequency = 200) |
|---|---|
| 설명 | 로봇 상태 데이터 구독을 추가합니다. |
| 요청 매개변수 | topicTypes : RobotTopicType[] 로봇 토픽 유형 목록 frequency : int 구독 빈도(단위:Hz, 기본값 200) |
| 반환 값 | 작업: 비동기 구독 작업 결과 |
| 호환 로봇 소프트웨어 버전 | 협업(Copper): v7.7.0.0+ 산업용(Bronze): v7.7.0.0+ |
4.13.4 등록 구독 추가
| 메서드 이름 | SubPub.SubscribeRegister(RegTopicType regType , int[] regIds , int frequency = 200) |
|---|---|
| 설명 | 등록 데이터 구독을 추가합니다. |
| 요청 매개변수 | regType : RegTopicType 레지스터 유형 regIds : int[] 레지스터 ID 목록 frequency : int 구독 빈도(단위:Hz, 기본값 200) |
| 반환 값 | 작업: 비동기 구독 작업 결과 |
| 호환 로봇 소프트웨어 버전 | 협업(Copper): v7.7.0.0+ 산업용(Bronze): v7.7.0.0+ |
4.13.5 IO 구독 추가
| 메서드 이름 | SubPub.SubscribeIO((IOTopicType, int)[] ioList , int frequency = 200) |
|---|---|
| 설명 | 디지털 입력/output, 등을 포함한 IO 신호 데이터를 구독합니다. |
| 요청 매개변수 | ioList : (IOTopicType, int)[] IO 목록 (각 요소는 (IO Type, IO ID) 입니다) frequency : int 구독 주파수 (단위:Hz, 기본값 200) |
| 반환 값 | 작업: 비동기 구독 작업 결과 |
| 호환 로봇 소프트웨어 버전 | 협업(Copper): v7.7.0.0+ 산업용(Bronze): v7.7.0.0+ |
4.13.6 메시지 수신 시작
| 메서드 이름 | SubPub.StartReceiving(Func<Dictionary<string, object>, Task> onMessageReceived ) |
|---|---|
| 설명 | 구독 메시지 수신을 시작하고 콜백 함수를 통해 수신된 데이터를 처리합니다. |
| 요청 매개변수 | onMessageReceived : Func<Dictionary<string, object>, Task> 메시지 수신 콜백 함수 |
| 반환 값 | 작업: 비동기 수신 작업 |
| 메모 | 콜백에서 예외가 발생하면 수신 루프가 중지될 수 있습니다. 콜백 내에서 예외를 포착하고 기록하는 것이 좋습니다. |
| 호환 로봇 소프트웨어 버전 | 협업(Copper): v7.7.0.0+ 산업용(Bronze): v7.7.0.0+ |
예제 코드
cs
using Agilebot.IR;
using Agilebot.IR.SubPub;
using Agilebot.IR.Types;
public class CallbackReceiving
{
public static StatusCode Run(string controllerIP, bool useLocalProxy = true)
{
// [ZH] 初始化捷勃特机器人
// [EN] Initialize the Agilebot robot
Arm controller = new Arm(controllerIP, useLocalProxy);
// [ZH] 连接捷勃特机器人
// [EN] Connect to the Agilebot robot
StatusCode code = controller.ConnectSync();
Console.WriteLine(code != StatusCode.OK ? code.GetDescription() : "连接成功/Successfully connected.");
// [ZH] 初始化捷勃特机器人SubPub
// [EN] Initialize the Agilebot robot SubPub
var subPub = controller.SubPub;
try
{
Console.WriteLine("开始回调方式接收消息测试/Starting Callback Receiving Test");
// [ZH] 连接到WebSocket服务器
// [EN] Connect to WebSocket server
subPub.Connect().Wait();
Console.WriteLine("WebSocket连接成功/WebSocket Connected Successfully");
// [ZH] 订阅机器人状态
// [EN] Subscribe to robot status
var topicTypes = new RobotTopicType[] { RobotTopicType.TopicCurrentJoint, RobotTopicType.TopicRobotStatus };
subPub.SubscribeStatus(topicTypes, frequency: 100).Wait();
Console.WriteLine("机器人状态订阅成功/Robot Status Subscription Successful");
// [ZH] 订阅寄存器
// [EN] Subscribe to registers
var regIds = new int[] { 1, 2, 3 };
subPub.SubscribeRegister(RegTopicType.R, regIds, frequency: 100).Wait();
Console.WriteLine("寄存器订阅成功/Register Subscription Successful");
// [ZH] 订阅IO
// [EN] Subscribe to IO
var ioList = new (IOTopicType, int)[] { (IOTopicType.DI, 0), (IOTopicType.DO, 1) };
subPub.SubscribeIO(ioList, frequency: 100).Wait();
Console.WriteLine("IO订阅成功/IO Subscription Successful");
int messageCount = 0;
int maxMessages = 10; // 接收10条消息后停止
Console.WriteLine("开始接收消息/Starting to receive messages...");
// [ZH] 开始接收消息(回调方式)
// [EN] Start receiving messages (callback method)
subPub
.StartReceiving(async message =>
{
messageCount++;
Console.WriteLine($"\n=== 收到第{messageCount}条消息/Received Message #{messageCount} ===");
foreach (var kv in message)
{
Console.WriteLine($"{kv.Key}: {kv.Value}");
}
// [ZH] 接收指定数量消息后主动断开
// [EN] Disconnect after receiving specified number of messages
if (messageCount >= maxMessages)
{
Console.WriteLine(
$"已接收{maxMessages}条消息,准备断开连接/Received {maxMessages} messages, preparing to disconnect"
);
subPub.Disconnect().Wait();
Console.WriteLine("WebSocket断开成功/WebSocket Disconnected Successfully");
}
await Task.CompletedTask;
})
.Wait();
Console.WriteLine("回调方式接收消息测试完成/Callback Receiving Test Completed");
return StatusCode.OK;
}
catch (Exception ex)
{
Console.WriteLine($"执行过程中发生异常/Exception occurred during execution: {ex.Message}");
return StatusCode.OtherReason;
}
finally
{
// [ZH] 关闭连接
// [EN] Close the connection
StatusCode disconnectCode = controller.Disconnect();
if (disconnectCode != StatusCode.OK)
{
Console.WriteLine(disconnectCode.GetDescription());
if (code == StatusCode.OK)
code = disconnectCode;
}
}
}
}4.13.7 다음 메시지 수신
| 메서드 이름 | SubPub.Receive() |
|---|---|
| 설명 | 다음 메시지 수신을 차단하고 이를 반환합니다. |
| 요청 매개변수 | 없음 |
| 반환 값 | Task<Dictionary<string, object>>: 수신된 메시지 사전 |
| 메모 | 연결이 설정되지 않거나, 연결이 닫히거나, 메시지 형식이 비정상적인 경우 예외가 발생할 수 있습니다. |
| 호환 로봇 소프트웨어 버전 | 협업(Copper): v7.7.0.0+ 산업용(Bronze): v7.7.0.0+ |
예제 코드
cs
using Agilebot.IR;
using Agilebot.IR.SubPub;
using Agilebot.IR.Types;
public class PollingReceiving
{
public static StatusCode Run(string controllerIP, bool useLocalProxy = true)
{
// [ZH] 初始化捷勃特机器人
// [EN] Initialize the Agilebot robot
Arm controller = new Arm(controllerIP, useLocalProxy);
// [ZH] 连接捷勃特机器人
// [EN] Connect to the Agilebot robot
StatusCode code = controller.ConnectSync();
Console.WriteLine(code != StatusCode.OK ? code.GetDescription() : "连接成功/Successfully connected.");
// [ZH] 初始化捷勃特机器人SubPub
// [EN] Initialize the Agilebot robot SubPub
var subPub = controller.SubPub;
try
{
Console.WriteLine("开始轮询方式接收消息测试/Starting Polling Receiving Test");
// [ZH] 连接到WebSocket服务器
// [EN] Connect to WebSocket server
subPub.Connect().Wait();
Console.WriteLine("WebSocket连接成功/WebSocket Connected Successfully");
// [ZH] 订阅机器人状态
// [EN] Subscribe to robot status
var topicTypes = new RobotTopicType[] { RobotTopicType.TopicCurrentJoint, RobotTopicType.TopicRobotStatus };
subPub.SubscribeStatus(topicTypes, frequency: 100).Wait();
Console.WriteLine("机器人状态订阅成功/Robot Status Subscription Successful");
// [ZH] 订阅寄存器
// [EN] Subscribe to registers
var regIds = new int[] { 1, 2, 3 };
subPub.SubscribeRegister(RegTopicType.R, regIds, frequency: 100).Wait();
Console.WriteLine("寄存器订阅成功/Register Subscription Successful");
// [ZH] 订阅IO
// [EN] Subscribe to IO
var ioList = new (IOTopicType, int)[] { (IOTopicType.DI, 0), (IOTopicType.DO, 1) };
subPub.SubscribeIO(ioList, frequency: 100).Wait();
Console.WriteLine("IO订阅成功/IO Subscription Successful");
int messageCount = 0;
int maxMessages = 10; // 接收10条消息后停止
Console.WriteLine("开始轮询接收消息/Starting to poll messages...");
// [ZH] 循环接收消息直到达到期望数量
// [EN] Loop to receive messages until reaching desired count
do
{
messageCount++;
try
{
// [ZH] 接收单条消息
// [EN] Receive single message
var message = subPub.Receive().Result;
Console.WriteLine($"\n=== 收到第{messageCount}条消息/Received Message #{messageCount} ===");
foreach (var kv in message)
{
Console.WriteLine($"{kv.Key}: {kv.Value}");
}
}
catch (Exception ex)
{
Console.WriteLine($"接收消息时发生异常/Exception while receiving message: {ex.Message}");
break;
}
} while (messageCount < maxMessages);
// [ZH] 断开连接
// [EN] Disconnect
subPub.Disconnect().Wait();
Console.WriteLine("WebSocket断开成功/WebSocket Disconnected Successfully");
Console.WriteLine("轮询方式接收消息测试完成/Polling Receiving Test Completed");
return StatusCode.OK;
}
catch (Exception ex)
{
Console.WriteLine($"执行过程中发生异常/Exception occurred during execution: {ex.Message}");
return StatusCode.OtherReason;
}
finally
{
// [ZH] 关闭连接
// [EN] Close the connection
StatusCode disconnectCode = controller.Disconnect();
if (disconnectCode != StatusCode.OK)
{
Console.WriteLine(disconnectCode.GetDescription());
if (code == StatusCode.OK)
code = disconnectCode;
}
}
}
}