Skip to content

4.13 C99 SubPub APIs

Overview

The C99 SubPub APIs provide WebSocket subscribe/publish capabilities, including connect, disconnect, raw text send, background receiving, synchronous receiving, and status/register/IO subscription.

Header file:

  • include/c_arm_sub_pub.h
StepAPIDescription
1Arm_ConnectEstablishes the robot session.
2Arm_SubPub_ConnectEstablishes the SubPub WebSocket connection; it always uses proxy port 5609 .
3Arm_SubPub_StartReceivingStarts background receiving and registers the message callback.
4Arm_SubPub_SubscribeStatus / Arm_SubPub_SubscribeRegister / Arm_SubPub_SubscribeIoStarts status, register, or IO subscriptions.
5Arm_SubPub_ReceivePulls messages synchronously from the SDK receive queue as needed.
6Arm_SubPub_DisconnectDisconnects the SubPub WebSocket connection.

API Signatures

Arm_SubPub_Connect

c
int Arm_SubPub_Connect(ArmHandle* h, const char* teachPanelIp, int timeoutSecs);
ItemDescription
DescriptionEstablishes the SubPub WebSocket connection.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
teachPanelIp : const char* , teach pendant address; when NULL or an empty string is passed, the address bound to the current Arm session is used
timeoutSecs : int , connection timeout in seconds
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions
NotesWhen teachPanelIp is empty, the address bound through the current Arm session is used. If the same instance is already connected, calling this again returns success without rebuilding the connection.

Arm_SubPub_Disconnect

c
int Arm_SubPub_Disconnect(ArmHandle* h);
ItemDescription
DescriptionDisconnects the SubPub WebSocket connection.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Arm_SubPub_IsConnected

c
int Arm_SubPub_IsConnected(ArmHandle* h);
ItemDescription
DescriptionQueries whether SubPub is connected.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
Return valueReturns non-zero when connected, and 0 when not connected
NotesThis only indicates the SubPub WebSocket state, not the Arm HTTP session state.

Arm_SubPub_SendText

c
int Arm_SubPub_SendText(ArmHandle* h, const char* text);
ItemDescription
DescriptionSends a raw text message.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
text : const char* , raw text to send
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Arm_SubPub_StartReceiving

c
int Arm_SubPub_StartReceiving(ArmHandle* h, ArmSubPubMessageCallback callback);
ItemDescription
DescriptionStarts background message receiving.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
callback : ArmSubPubMessageCallback , message callback invoked when WebSocket text is received
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions
NotesOne SubPub instance keeps only one active callback. A later call replaces the earlier callback.

Arm_SubPub_RemoveMessageHandler

c
int Arm_SubPub_RemoveMessageHandler(ArmHandle* h);
ItemDescription
DescriptionRemoves the message callback.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions
NotesRemoves the current active callback but does not clear the SDK receive queue. Calling it while disconnected is also treated as success.

Arm_SubPub_Receive

c
int Arm_SubPub_Receive(ArmHandle* h, int timeoutMs, char* outBuf, size_t bufSize, size_t* outLen);
ItemDescription
DescriptionReceives one message synchronously.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
timeoutMs : int , receive timeout in milliseconds
outBuf : char* , string output buffer allocated by the caller
bufSize : size_t , output buffer size, including space for the trailing \0
outLen : size_t* , total bytes required for the output message, including the trailing \0
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions
NotesA timeout returns the receive-timeout status code. A disconnected state returns the not-connected status code. If the buffer is too small, outLen receives the required byte count.

Arm_SubPub_SubscribeStatus

c
int Arm_SubPub_SubscribeStatus(ArmHandle* h, const int* topics, size_t count, int frequency);
ItemDescription
DescriptionSubscribes to robot status topics.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
topics : const int* , status-topic array
count : size_t , number of array elements
frequency : int , subscription frequency parameter
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Arm_SubPub_SubscribeRegister

c
int Arm_SubPub_SubscribeRegister(ArmHandle* h, int regType, const int* regIds, size_t count, int frequency);
ItemDescription
DescriptionSubscribes to register topics.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
regType : int , register-topic type
regIds : const int* , register-ID array
count : size_t , number of array elements
frequency : int , subscription frequency parameter
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Arm_SubPub_SubscribeIo

c
int Arm_SubPub_SubscribeIo(ArmHandle* h, const int* ioTypes, const int* ioIds, size_t count, int frequency);
ItemDescription
DescriptionSubscribes to IO topics.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
ioTypes : const int* , IO-topic type array
ioIds : const int* , IO-ID array
count : size_t , number of array elements
frequency : int , subscription frequency parameter
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Callback and Topics

c
typedef void (*ArmSubPubMessageCallback)(const char* jsonStr, size_t len);
TypeDescription
ArmRobotTopicTypeRobot status topics, for example ARM_ROBOT_TOPIC_JOINT_POSITION and ARM_ROBOT_TOPIC_SERVO_STATUS
ArmRegTopicTypeRegister topics, including ARM_REG_TOPIC_R , ARM_REG_TOPIC_MR , ARM_REG_TOPIC_SR , and ARM_REG_TOPIC_PR
ArmIoTopicTypeIO topics, including ARM_IO_TOPIC_DI , ARM_IO_TOPIC_DO , ARM_IO_TOPIC_AI , ARM_IO_TOPIC_AO , and others
ItemRule
jsonStrUTF-8 JSON text
lenText length, excluding the trailing \0
Callback threadWebSocket message-arrival thread
ReceiveoutLen writes back the required total byte count, including the trailing \0
Buffer too smallArm_SubPub_Receive returns BUFFER_TOO_SMALL
Receive queueThe SDK receive queue is capped at 100 messages; when the cap is exceeded, the oldest message is dropped
Callback replacementA later callback registered on the same instance replaces the earlier callback
Callback reentrancyAvoid directly calling connect, disconnect, start-receiving, or remove-callback APIs from inside the callback

Keep callback work lightweight, and hand time-consuming logic off to a business thread.

Connection and Subscription Rules

ItemDescription
WebSocket portSubPub always uses proxy port 5609 .
Empty address connectionWhen teachPanelIp is NULL or an empty string, the address bound by Arm_Connect() is used.
Multiple instancesMultiple ArmHandle* instances can each establish a SubPub connection. Disconnecting one keeps the other instances in their own connection states.
Subscription frequencyfrequency is in Hz; status, register, and IO subscriptions all use this frequency field.
Raw textArm_SubPub_SendText is for debugging or custom protocols; for routine status, register, and IO data, prefer the subscription APIs.

Minimal Example

c
#include <stdio.h>  // Provides printf for printing SubPub connection state.
#include "c_arm_api.h"  // Includes the aggregate C99 SDK header.
int main(void)  // Example program entry point.
{  // Enters the example main function.
    ArmHandle* h = Arm_Create();  // Creates a C99 session handle.
    if (h == NULL) {  // Checks whether handle creation failed.
        return 1;  // Exits when creation fails.
    }  // Ends the handle check.
    if (Arm_Connect(h, "10.27.1.2", "10.27.1.102") != 0) {  // Connects to the controller.
        Arm_Destroy(h);  // Releases the handle after connection failure.
        return 1;  // Returns an error.
    }  // Ends the connection check.
    int ret = Arm_SubPub_Connect(h, "10.27.1.102", 10);  // Establishes the SubPub connection.
    printf("sub_pub_connected=%d\n", Arm_SubPub_IsConnected(h));  // Prints the SubPub connection state.
    Arm_SubPub_Disconnect(h);  // Disconnects the SubPub connection.
    Arm_Disconnect(h);  // Disconnects the robot session.
    Arm_Destroy(h);  // Destroys the handle.
    return ret == 0 ? 0 : 1;  // Returns according to the connection result.
}  // Ends the example main function.

Scenario Examples

c
void OnMessage(const char* jsonStr, size_t len)  // Defines the message callback.
{  // Enters the message callback.
    (void)jsonStr;  // Keeps the JSON text in this example.
    (void)len;  // Keeps the text length in this example.
}  // Ends the message callback.
int topics[1] = {ARM_ROBOT_TOPIC_JOINT_POSITION};  // Prepares the robot status-topic list.
int regIds[2] = {1, 2};  // Prepares the register-ID list.
int ioTypes[1] = {ARM_IO_TOPIC_DI};  // Prepares the IO-type list.
int ioIds[1] = {1};  // Prepares the IO-ID list.
char msg[2048] = {0};  // Prepares the synchronous receive buffer.
size_t msgLen = 0U;  // Prepares the received-message length.
int connectRet = Arm_SubPub_Connect(h, NULL, 10);  // Establishes the SubPub connection.
int receiveRet = Arm_SubPub_StartReceiving(h, OnMessage);  // Starts background receiving.
int statusRet = Arm_SubPub_SubscribeStatus(h, topics, 1, 200);  // Subscribes to the joint-position topic.
int regRet = Arm_SubPub_SubscribeRegister(h, ARM_REG_TOPIC_R, regIds, 2, 100);  // Subscribes to R1 / R2.
int ioRet = Arm_SubPub_SubscribeIo(h, ioTypes, ioIds, 1, 50);  // Subscribes to DI1.
int textRet = Arm_SubPub_SendText(h, "{\"cmd\":\"ping\"}");  // Sends raw text.
int syncRet = Arm_SubPub_Receive(h, 1000, msg, sizeof(msg), &msgLen);  // Synchronously receives one message.
int removeRet = Arm_SubPub_RemoveMessageHandler(h);  // Removes the message callback.
int disconnectRet = Arm_SubPub_Disconnect(h);  // Disconnects the SubPub connection.
(void)connectRet;  // Keeps the status code in this example.
(void)receiveRet;  // Keeps the status code in this example.
(void)statusRet;  // Keeps the status code in this example.
(void)regRet;  // Keeps the status code in this example.
(void)ioRet;  // Keeps the status code in this example.
(void)textRet;  // Keeps the status code in this example.
(void)syncRet;  // Keeps the status code in this example.
(void)removeRet;  // Keeps the status code in this example.
(void)disconnectRet;  // Keeps the status code in this example.

Sample code

c99/sub_pub_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_sub_pub] 创建句柄失败 / 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_sub_pub] 连接失败 / Connect failed, 状态码 / Status code: %d\n", ret);
        Arm_Destroy(handle);
        return 1;
    }
    printf("[c99_sub_pub] 机器人连接成功 / Robot connected successfully\n");

    // [ZH] 建立订阅连接并打印连接状态。
    // [EN] Establish the subscription connection and print the connection state.
    ret = Arm_SubPub_Connect(handle, "10.27.1.102", 10);
    printf("[c99_sub_pub] Connect 状态码 / Connect status code: %d\n", ret);
    printf("[c99_sub_pub] 当前连接状态 / Current connection state: %d\n", Arm_SubPub_IsConnected(handle));

    // [ZH] 顺序执行回调注册、主题订阅、发送和接收接口。
    // [EN] Execute the callback registration, subscriptions, send, and receive APIs in sequence.
    ret = Arm_SubPub_StartReceiving(handle, NULL);
    printf("[c99_sub_pub] StartReceiving 状态码 / StartReceiving status code: %d\n", ret);
    int statusTopics[1] = {ARM_ROBOT_TOPIC_JOINT_POSITION};
    ret = Arm_SubPub_SubscribeStatus(handle, statusTopics, 1U, 200);
    printf("[c99_sub_pub] SubscribeStatus 状态码 / SubscribeStatus status code: %d\n", ret);
    int regIds[2] = {1, 2};
    ret = Arm_SubPub_SubscribeRegister(handle, ARM_REG_TOPIC_R, regIds, 2U, 200);
    printf("[c99_sub_pub] SubscribeRegister 状态码 / SubscribeRegister status code: %d\n", ret);
    int ioTypes[1] = {ARM_IO_TOPIC_DI};
    int ioIds[1] = {1};
    ret = Arm_SubPub_SubscribeIo(handle, ioTypes, ioIds, 1U, 200);
    printf("[c99_sub_pub] SubscribeIo 状态码 / SubscribeIo status code: %d\n", ret);
    ret = Arm_SubPub_SendText(handle, "{\"cmd\":\"ping\",\"param\":{\"source\":\"c99_example\"}}");
    printf("[c99_sub_pub] SendText 状态码 / SendText status code: %d\n", ret);
    char message[2048] = {0};
    size_t messageLen = 0U;
    ret = Arm_SubPub_Receive(handle, 5000, message, sizeof(message), &messageLen);
    printf("[c99_sub_pub] Receive 状态码 / Receive status code: %d, 长度 / Length: %zu, 消息 / Message: %s\n", ret, messageLen, message);
    ret = Arm_SubPub_RemoveMessageHandler(handle);
    printf("[c99_sub_pub] RemoveMessageHandler 状态码 / RemoveMessageHandler status code: %d\n", ret);
    ret = Arm_SubPub_Disconnect(handle);
    printf("[c99_sub_pub] Disconnect 状态码 / Disconnect status code: %d\n", ret);

    // [ZH] 断开机器人连接并销毁句柄。
    // [EN] Disconnect the robot and destroy the handle.
    Arm_Disconnect(handle);
    Arm_Destroy(handle);
    printf("[c99_sub_pub] 示例结束 / Example finished\n");
    return 0;
}