Skip to content

4.13 Robot Subscription & Publish Interface

Overview

The SubPub class provides WebSocket subscription/publish channel management for the robot controller. It is used to establish connections, subscribe to robot status/register/IO topics, and receive real-time data through callback or blocking APIs.

Core Features

  • Support connecting to and disconnecting from WebSocket server
  • Support subscribing to robot status data
  • Support subscribing to register data
  • Support subscribing to IO signal data
  • Support continuously receiving messages via callback function
  • Support blocking reception of the next message
  • Support setting subscription frequency
  • Support handling exceptions and troubleshooting during message reception

Use Cases

  • Host-side real-time monitoring of robot operating status
  • Implementing robot data visualization
  • Achieving data linkage with external systems
  • Real-time monitoring of register and IO states
  • Building robot monitoring and control systems
  • Implementing real-time alarm and notification for robot status

4.13.1 Connect to WebSocket Server

Method NameSubPub.Connect()
DescriptionConnects to the robot controller WebSocket server
Request ParametersNone
Return ValueTask: Asynchronous connection operation result
Compatible robot software versionCollaborative (Copper): v7.7.0.0+
Industrial (Bronze): v7.7.0.0+

4.13.2 Disconnect from WebSocket Server

Method NameSubPub.Disconnect()
DescriptionDisconnects from the robot controller WebSocket server
Request ParametersNone
Return ValueTask: Asynchronous disconnect operation result
Compatible robot software versionCollaborative (Copper): v7.7.0.0+
Industrial (Bronze): v7.7.0.0+

4.13.3 Add Robot Status Subscription

Method NameSubPub.SubscribeStatus(RobotTopicType[] topicTypes , int frequency = 200)
DescriptionAdds robot status data subscription
Request ParameterstopicTypes : RobotTopicType[] Robot topic type list
frequency : int Subscription frequency (unit: Hz, default 200)
Return ValueTask: Asynchronous subscription operation result
Compatible robot software versionCollaborative (Copper): v7.7.0.0+
Industrial (Bronze): v7.7.0.0+

4.13.4 Add Register Subscription

Method NameSubPub.SubscribeRegister(RegTopicType regType , int[] regIds , int frequency = 200)
DescriptionAdds register data subscription
Request ParametersregType : RegTopicType Register type
regIds : int[] Register ID list
frequency : int Subscription frequency (unit: Hz, default 200)
Return ValueTask: Asynchronous subscription operation result
Compatible robot software versionCollaborative (Copper): v7.7.0.0+
Industrial (Bronze): v7.7.0.0+

4.13.5 Add IO Subscription

Method NameSubPub.SubscribeIO((IOTopicType, int)[] ioList , int frequency = 200)
DescriptionSubscribes to IO signal data, including digital input/output, etc.
Request ParametersioList : (IOTopicType, int)[] IO list (each element is (IO Type, IO ID) )
frequency : int Subscription frequency (unit: Hz, default 200)
Return ValueTask: Asynchronous subscription operation result
Compatible robot software versionCollaborative (Copper): v7.7.0.0+
Industrial (Bronze): v7.7.0.0+

4.13.6 Start Receiving Messages

Method NameSubPub.StartReceiving(Func<Dictionary<string, object>, Task> onMessageReceived )
DescriptionStarts receiving subscription messages and processes the received data via callback function.
Request ParametersonMessageReceived : Func<Dictionary<string, object>, Task> Message receiving callback function
Return ValueTask: Asynchronous receiving task
NoteIf the callback throws an exception, the receiving loop may stop. It is recommended to catch and log exceptions inside the callback.
Compatible robot software versionCollaborative (Copper): v7.7.0.0+
Industrial (Bronze): v7.7.0.0+

Example Code

SubPub/CallbackReceiving.cs
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 Receive Next Message

Method NameSubPub.Receive()
DescriptionBlocks to receive the next message and returns it.
Request ParametersNone
Return ValueTask<Dictionary<string, object>>: Received message dictionary
NoteExceptions may be thrown when the connection is not established, when the connection is closed, or when message format is abnormal.
Compatible robot software versionCollaborative (Copper): v7.7.0.0+
Industrial (Bronze): v7.7.0.0+

Example Code

SubPub/PollingReceiving.cs
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;
            }
        }
    }
}