跳到主要内容

Read / Write (C)

前置阅读

DarraUa_Session_ReadNode (单节点便捷)

DARRA_OPCUA_API DarraUa_DataValue* DARRA_OPCUA_CALL DarraUa_Session_ReadNode(
DarraUa_SessionHandle h,
const char* node_id_str,
DarraUa_AttributeId attribute,
DarraUa_Status* out_status);
参数说明
node_id_strNodeId 字符串 (i=2258 / ns=2;s=...)
attributeDARRA_UA_ATTR_VALUE (默认 13) / _DISPLAY_NAME / ...
out_status出参, 写入服务级状态码

返回: DarraUa_DataValue* (失败为 NULL); 用 DarraUa_DataValue_Delete 释放.

DarraUa_Status st = 0;
DarraUa_DataValue* dv = DarraUa_Session_ReadNode(
h, "ns=2;s=Temperature", DARRA_UA_ATTR_VALUE, &st);
if (dv && DARRA_UA_STATUS_IS_GOOD(st)) {
const DarraUa_Variant* v = DarraUa_DataValue_GetValue(dv);
double temp = 0.0;
DarraUa_Variant_GetDouble(v, &temp);
printf("T = %.2f °C\n", temp);
DarraUa_DataValue_Delete(dv);
}

DarraUa_Session_ReadNodes (批量字符串 NodeId)

DARRA_OPCUA_API DarraUa_Status DARRA_OPCUA_CALL DarraUa_Session_ReadNodes(
DarraUa_SessionHandle h,
const char* const* node_id_strs,
const int32_t* attribute_ids, /* NULL = 全部默认 Value(13) */
uint32_t count,
DarraUa_DataValue** out_values); /* 调用方分配 count 个槽 */

out_values[i] 由 Stack 填充, 每个非 NULL 项要单独 DarraUa_DataValue_Delete. 单项失败 → out_values[i] = NULL, 不影响其他项, 顶层返回 Good.

const char* nodes[] = { "ns=2;s=T1", "ns=2;s=T2", "ns=2;s=T3" };
DarraUa_DataValue* dvs[3] = { NULL };
DarraUa_Status st = DarraUa_Session_ReadNodes(h, nodes, NULL, 3, dvs);

for (uint32_t i = 0; i < 3; ++i) {
if (dvs[i]) {
double v = 0.0;
DarraUa_Variant_GetDouble(DarraUa_DataValue_GetValue(dvs[i]), &v);
printf("%s = %g\n", nodes[i], v);
DarraUa_DataValue_Delete(dvs[i]);
}
}

DarraUa_Session_Read (批量结构体)

DARRA_OPCUA_API DarraUa_Status DARRA_OPCUA_CALL DarraUa_Session_Read(
DarraUa_SessionHandle h,
const DarraUa_ReadValueId* nodes,
uint32_t count,
DarraUa_DataValue** out_values);

DarraUa_ReadValueId:

typedef struct {
DarraUa_NodeId node_id;
DarraUa_AttributeId attribute_id;
const char* index_range; /* 可选 "0:9" 切数组; NULL = 全部 */
} DarraUa_ReadValueId;

适合任意 NodeId + AttributeId 组合:

DarraUa_ReadValueId items[] = {
{ /* 解析 "ns=2;s=T1" 得到的 NodeId */ ..., DARRA_UA_ATTR_VALUE, NULL },
{ ..., DARRA_UA_ATTR_DATA_TYPE, NULL },
};
DarraUa_DataValue* dvs[2] = { NULL };
DarraUa_Session_Read(h, items, 2, dvs);
/* ... 释放 ... */

实践中, 绝大多数场景用字符串版 _ReadNodes 即可, 结构体版仅在需要 IndexRange 切数组时使用.


DarraUa_Session_WriteNode (单节点便捷)

DARRA_OPCUA_API DarraUa_Status DARRA_OPCUA_CALL DarraUa_Session_WriteNode(
DarraUa_SessionHandle h,
const char* node_id_str,
DarraUa_AttributeId attribute,
const DarraUa_Variant* value);
返回含义
DARRA_UA_STATUS_GOOD写入成功
DARRA_UA_STATUS_BAD_NOT_WRITABLE该 Attribute 不可写
DARRA_UA_STATUS_BAD_TYPE_MISMATCHVariant 类型与节点 DataType 不符
DARRA_UA_STATUS_BAD_USER_ACCESS_DENIED无权限

Variant 由调用方维护, 函数不负责释放.

DarraUa_Variant* v = DarraUa_Variant_New();
DarraUa_Variant_SetDouble(v, 42.5);

DarraUa_Status st = DarraUa_Session_WriteNode(
h, "ns=2;s=Setpoint", DARRA_UA_ATTR_VALUE, v);

if (!DARRA_UA_STATUS_IS_GOOD(st))
fprintf(stderr, "Write failed: %s\n", DarraUa_StatusName(st));

DarraUa_Variant_Delete(v);
业务级失败不抛错 — 必须检查返回值

C 没有异常机制, 业务级失败统一通过 DarraUa_Status 返回值通知, 不要假定 Good.


DarraUa_Session_Write (批量)

DARRA_OPCUA_API DarraUa_Status DARRA_OPCUA_CALL DarraUa_Session_Write(
DarraUa_SessionHandle h,
const DarraUa_WriteValue* items,
uint32_t count,
DarraUa_Status* out_results); /* 调用方分配 count 个 */

DarraUa_WriteValue:

typedef struct {
DarraUa_NodeId node_id;
DarraUa_AttributeId attribute_id;
const char* index_range;
const DarraUa_Variant* value;
} DarraUa_WriteValue;

每项 status 写入 out_results[i], 顶层返回反映传输级状态.


Variant 构造速查

DarraUa_Variant* v = DarraUa_Variant_New();

DarraUa_Variant_SetBoolean(v, 1);
DarraUa_Variant_SetInt16(v, 42);
DarraUa_Variant_SetInt32(v, 42);
DarraUa_Variant_SetInt64(v, 42);
DarraUa_Variant_SetUInt32(v, 42);
DarraUa_Variant_SetFloat(v, 3.14f);
DarraUa_Variant_SetDouble(v, 3.14);
DarraUa_Variant_SetString(v, "hello");
DarraUa_Variant_SetDateTime(v, /* 100ns ticks since 1601 */ 0);

/* 数组 */
double arr[] = { 1.0, 2.0, 3.0 };
DarraUa_Variant_SetDoubleArray(v, arr, 3);

DarraUa_Variant_Delete(v);

完整清单见 Variant.


DataValue 字段速查

Getter类型说明
DarraUa_DataValue_GetValue(dv)const DarraUa_Variant*实际值 (生命周期 = dv)
DarraUa_DataValue_GetStatus(dv)uint32_tDataValue 自身的 StatusCode
DarraUa_DataValue_GetSourceTimestamp(dv)DarraUa_DateTime数据源时间戳
DarraUa_DataValue_GetServerTimestamp(dv)DarraUa_DateTime服务端打的时间戳
uint32_t dv_status = DarraUa_DataValue_GetStatus(dv);
if (DARRA_UA_STATUS_IS_BAD(dv_status)) {
printf("Bad value: %s\n", DarraUa_StatusName(dv_status));
}

AttributeId 常用值

Id名称说明
1DARRA_UA_ATTR_NODE_ID节点 ID
2DARRA_UA_ATTR_NODE_CLASS节点类别
3DARRA_UA_ATTR_BROWSE_NAME浏览名
4DARRA_UA_ATTR_DISPLAY_NAME显示名
5DARRA_UA_ATTR_DESCRIPTION描述
13DARRA_UA_ATTR_VALUE变量值 (默认)
14DARRA_UA_ATTR_DATA_TYPE数据类型 NodeId
17DARRA_UA_ATTR_ACCESS_LEVEL访问权限位
20DARRA_UA_ATTR_HISTORIZING是否在记录历史
21DARRA_UA_ATTR_EXECUTABLEMethod 是否可执行

最佳实践

  • 批量优先: 监控 100+ Tag 用 _ReadNodes, 不要循环 _ReadNode (省 N-1 次 RPC)
  • 必须 Delete DataValue: 漏 Delete 会泄漏 native 内存
  • Write 检查返回值: 不要假定 Good
  • 实时变化用订阅: 不要 1 秒一次轮询 Read, 改用 Subscription

下一步