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
Recommended Call Order
| Step | API | Description |
|---|---|---|
| 1 | Arm_Connect | Establishes the robot session. |
| 2 | Arm_SubPub_Connect | Establishes the SubPub WebSocket connection; it always uses proxy port 5609 . |
| 3 | Arm_SubPub_StartReceiving | Starts background receiving and registers the message callback. |
| 4 | Arm_SubPub_SubscribeStatus / Arm_SubPub_SubscribeRegister / Arm_SubPub_SubscribeIo | Starts status, register, or IO subscriptions. |
| 5 | Arm_SubPub_Receive | Pulls messages synchronously from the SDK receive queue as needed. |
| 6 | Arm_SubPub_Disconnect | Disconnects the SubPub WebSocket connection. |
API Signatures
Arm_SubPub_Connect
c
int Arm_SubPub_Connect(ArmHandle* h, const char* teachPanelIp, int timeoutSecs);| Item | Description |
|---|---|
| Description | Establishes the SubPub WebSocket connection. |
| Request parameters | h : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection firstteachPanelIp : const char* , teach pendant address; when NULL or an empty string is passed, the address bound to the current Arm session is usedtimeoutSecs : int , connection timeout in seconds |
| Return value | Integer STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions |
| Notes | When 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);| Item | Description |
|---|---|
| Description | Disconnects the SubPub WebSocket connection. |
| Request parameters | h : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first |
| Return value | Integer 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);| Item | Description |
|---|---|
| Description | Queries whether SubPub is connected. |
| Request parameters | h : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first |
| Return value | Returns non-zero when connected, and 0 when not connected |
| Notes | This 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);| Item | Description |
|---|---|
| Description | Sends a raw text message. |
| Request parameters | h : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection firsttext : const char* , raw text to send |
| Return value | Integer 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);| Item | Description |
|---|---|
| Description | Starts background message receiving. |
| Request parameters | h : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection firstcallback : ArmSubPubMessageCallback , message callback invoked when WebSocket text is received |
| Return value | Integer STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions |
| Notes | One SubPub instance keeps only one active callback. A later call replaces the earlier callback. |
Arm_SubPub_RemoveMessageHandler
c
int Arm_SubPub_RemoveMessageHandler(ArmHandle* h);| Item | Description |
|---|---|
| Description | Removes the message callback. |
| Request parameters | h : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first |
| Return value | Integer STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions |
| Notes | Removes 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);| Item | Description |
|---|---|
| Description | Receives one message synchronously. |
| Request parameters | h : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection firsttimeoutMs : int , receive timeout in millisecondsoutBuf : char* , string output buffer allocated by the callerbufSize : 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 value | Integer STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions |
| Notes | A 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);| Item | Description |
|---|---|
| Description | Subscribes to robot status topics. |
| Request parameters | h : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection firsttopics : const int* , status-topic arraycount : size_t , number of array elementsfrequency : int , subscription frequency parameter |
| Return value | Integer 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);| Item | Description |
|---|---|
| Description | Subscribes to register topics. |
| Request parameters | h : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection firstregType : int , register-topic typeregIds : const int* , register-ID arraycount : size_t , number of array elementsfrequency : int , subscription frequency parameter |
| Return value | Integer 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);| Item | Description |
|---|---|
| Description | Subscribes to IO topics. |
| Request parameters | h : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection firstioTypes : const int* , IO-topic type arrayioIds : const int* , IO-ID arraycount : size_t , number of array elementsfrequency : int , subscription frequency parameter |
| Return value | Integer 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);| Type | Description |
|---|---|
ArmRobotTopicType | Robot status topics, for example ARM_ROBOT_TOPIC_JOINT_POSITION and ARM_ROBOT_TOPIC_SERVO_STATUS |
ArmRegTopicType | Register topics, including ARM_REG_TOPIC_R , ARM_REG_TOPIC_MR , ARM_REG_TOPIC_SR , and ARM_REG_TOPIC_PR |
ArmIoTopicType | IO topics, including ARM_IO_TOPIC_DI , ARM_IO_TOPIC_DO , ARM_IO_TOPIC_AI , ARM_IO_TOPIC_AO , and others |
| Item | Rule |
|---|---|
jsonStr | UTF-8 JSON text |
len | Text length, excluding the trailing \0 |
| Callback thread | WebSocket message-arrival thread |
Receive | outLen writes back the required total byte count, including the trailing \0 |
| Buffer too small | Arm_SubPub_Receive returns BUFFER_TOO_SMALL |
| Receive queue | The SDK receive queue is capped at 100 messages; when the cap is exceeded, the oldest message is dropped |
| Callback replacement | A later callback registered on the same instance replaces the earlier callback |
| Callback reentrancy | Avoid 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
| Item | Description |
|---|---|
| WebSocket port | SubPub always uses proxy port 5609 . |
| Empty address connection | When teachPanelIp is NULL or an empty string, the address bound by Arm_Connect() is used. |
| Multiple instances | Multiple ArmHandle* instances can each establish a SubPub connection. Disconnecting one keeps the other instances in their own connection states. |
| Subscription frequency | frequency is in Hz; status, register, and IO subscriptions all use this frequency field. |
| Raw text | Arm_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
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;
}