Session 会话 (C)
C SDK 的 Session 不是对象, 而是 由 DarraUa_SessionHandle (uint32_t) 标识的内部上下文. 所有 DarraUa_Session_* 函数第一个参数都是这个 handle.
声明位于 <darra_opcua/darra_opcua_session.h>, 已被主头 darra_opcua.h 包含.
子页跳转
- 配置结构体字段与默认值请参考 构造与配置.
- 建链 / 断开 / 状态码请参考 Connect / Disconnect.
- 单节点 / 批量读写请参考 Read / Write.
- 状态变更回调请参考 事件回调.
- 命名空间反查请参考 Namespaces.
- 心跳与会话保活请参考 KeepAlive.
句柄类型
typedef uint32_t DarraUa_SessionHandle;
#define DARRA_UA_INVALID_SESSION_HANDLE 0u
0 是非法值, 所有 _Create 类函数失败时把出参置零, 上层用比较法判失败.
公共配置字段 (DarraUa_SessionConfig)
| 类别 | 属性 | 类型 | 访问 | 说明 |
|---|---|---|---|---|
| 连接 | endpoint_url | const char* | in | OPC UA endpoint, 如 opc.tcp://host:4840 |
security_mode | DarraUa_MessageSecurityMode | in | None / Sign / SignAndEncrypt | |
security_policy_uri | const char* | in | SecurityPolicy URI (#None / #Basic256Sha256) | |
| 登录 | user_token_type | DarraUa_UserTokenType | in | Anonymous / Username / Certificate / Issued |
username | const char* | in | user_token_type=USERNAME 时使用 | |
password | const char* | in | 配 username 用 | |
| 证书 | client_cert_path | const char* | in | 客户端 PFX 路径 (Sign 必填) |
client_key_path | const char* | in | PFX 密码 (字段复用) | |
server_cert_path | const char* | in | 服务端 DER, NULL = TOFU | |
| 超时 | session_timeout_ms | uint32_t | in | 服务端 Session 超时, 默认 600000 (10 分钟) |
connect_timeout_ms | uint32_t | in | 建链超时, 默认 10000 (10 秒) | |
request_timeout_ms | uint32_t | in | 单 RPC 超时, 默认 10000 (10 秒) | |
keepalive_interval_ms | uint32_t | in | 心跳周期, 默认 10000, 0 = 禁用 | |
| 重连 | auto_reconnect | uint32_t | in | 1 = 启用, 0 = 不重连 |
reconnect_max_retries | uint32_t | in | 默认 3 | |
reconnect_delay_ms | uint32_t | in | 默认 2000 |
务必先调 DarraUa_SessionConfig_Init(&cfg) 把所有字段填默认值, 再覆写需要的字段.
完整 API 速查
生命周期
| 函数 | 说明 |
|---|---|
DarraUa_SessionConfig_Init(&cfg) | 填默认值 |
DarraUa_Session_Create(&cfg, &h) | 创建句柄 (尚未连接) |
DarraUa_Session_Connect(h) | Hello → SecureChannel → Session → Activate |
DarraUa_Session_Disconnect(h) | 主动断开, 句柄保留可重连 |
DarraUa_Session_Close(h) | 关闭并释放句柄 |
状态
| 函数 | 说明 |
|---|---|
DarraUa_Session_GetState(h) | 返回 DarraUa_SessionState 枚举 |
DarraUa_Session_SetStateCallback(h, cb, ctx) | 注册状态变更回调 |
读 / 写
浏览 / 路径解析
命名空间
| 函数 | 说明 |
|---|---|
DarraUa_Session_LoadNamespaceArray(h) | 强制重读 i=2255 |
DarraUa_Session_GetNamespaceCount(h) | 命名空间数 |
DarraUa_Session_GetNamespaceUri(h, idx) | URI 查询 |
DarraUa_Session_FindNamespaceIndex(h, uri) | 反查 URI → Index |
订阅
| 函数 | 说明 |
|---|---|
DarraUa_Subscription_Create(h, &cfg, &sub) | 创建数据订阅 |
DarraUa_Session_Publish(h, timeout_ms) | 手动 Pump |
DarraUa_Session_StartAutoPublish(h) / _Stop | 后台 Publish 线程 |
DarraUa_Session_TransferSubscriptions(...) | 跨 Session 迁移订阅 |
方法 / 历史
| 函数 | 说明 |
|---|---|
DarraUa_Session_Call(h, &obj, &method, args, n, &out, &nout, &st) | Call OPC UA Method |
DarraUa_Session_HistoryRead*(...) | 5 模式 HistoryRead |
DarraUa_Session_HistoryUpdateData / HistoryDeleteRange | 写 / 删历史 |
控制
| 函数 | 说明 |
|---|---|
DarraUa_Session_Cancel(h, request_handle, &cancelled_count) | 取消未完成请求 |
状态机
typedef enum {
DARRA_UA_SESSION_DISCONNECTED = 0,
DARRA_UA_SESSION_CONNECTING = 1,
DARRA_UA_SESSION_CONNECTED = 2,
DARRA_UA_SESSION_RECONNECTING = 3,
DARRA_UA_SESSION_CLOSING = 4,
DARRA_UA_SESSION_FAILED = 5
} DarraUa_SessionState;
调用流向:
Disconnected
↓ Session_Connect
Connecting
↓
Connected
↓ (网络异常 + auto_reconnect=1)
Reconnecting
├── 成功 → Connected
└── 失败 → Failed → Closing → Disconnected
完整示例
#include <darra_opcua/darra_opcua.h>
#include <stdio.h>
#if defined(_WIN32)
# include <windows.h>
# define OPCUA_SLEEP_SEC(s) Sleep((s) * 1000)
#else
# include <unistd.h>
# define OPCUA_SLEEP_SEC(s) sleep(s)
#endif
static void on_state(DarraUa_SessionHandle h, DarraUa_SessionState st,
DarraUa_Status code, void* ctx)
{
(void)h; (void)ctx;
printf("Session state -> %d (status 0x%08X)\n", (int)st, (unsigned)code);
}
int main(int argc, char** argv)
{
const char* endpoint = (argc >= 2) ? argv[1] : "opc.tcp://localhost:4840";
DarraUa_Initialize();
DarraUa_SessionConfig cfg;
DarraUa_SessionConfig_Init(&cfg);
cfg.endpoint_url = endpoint;
cfg.security_mode = DARRA_UA_MSG_SECURITY_MODE_NONE;
cfg.security_policy_uri = "http://opcfoundation.org/UA/SecurityPolicy#None";
cfg.user_token_type = DARRA_UA_USER_TOKEN_ANONYMOUS;
DarraUa_SessionHandle h = DARRA_UA_INVALID_SESSION_HANDLE;
if (!DARRA_UA_STATUS_IS_GOOD(DarraUa_Session_Create(&cfg, &h))) goto cleanup;
DarraUa_Session_SetStateCallback(h, on_state, NULL);
if (!DARRA_UA_STATUS_IS_GOOD(DarraUa_Session_Connect(h))) goto cleanup;
/* Read */
DarraUa_Status st = 0;
DarraUa_DataValue* dv = DarraUa_Session_ReadNode(
h, "i=2258", DARRA_UA_ATTR_VALUE, &st);
if (dv) {
DarraUa_DateTime ft = DarraUa_Variant_GetDateTime(
DarraUa_DataValue_GetValue(dv));
printf("CurrentTime ft=%lld\n", (long long)ft);
DarraUa_DataValue_Delete(dv);
}
cleanup:
if (h) {
DarraUa_Session_Disconnect(h);
DarraUa_Session_Close(h);
}
DarraUa_Shutdown();
return 0;
}