跳到主要内容

DataValue (C)

DarraUa_DataValue* 包装一次 Read 返回的全部信息: 值 + 状态 + 时间戳.

配套

公共 API

类别属性类型访问说明
生命周期DarraUa_DataValue_New()DarraUa_DataValue*RW新建空 DataValue (HistoryUpdate 才用)
DarraUa_DataValue_Delete(dv)voidW释放; dv 为 NULL 时安全
字段DarraUa_DataValue_GetValue(dv)const DarraUa_Variant*R实际值, 生命周期 = dv, 不要 Delete
DarraUa_DataValue_GetStatus(dv)uint32_tR数据质量 StatusCode
DarraUa_DataValue_GetSourceTimestamp(dv)DarraUa_DateTimeR数据源时间戳 (100ns since 1601)
DarraUa_DataValue_GetServerTimestamp(dv)DarraUa_DateTimeR服务端时间戳

用法

DarraUa_Status st = 0;
DarraUa_DataValue* dv = DarraUa_Session_ReadNode(
h, "ns=2;s=Temperature", DARRA_UA_ATTR_VALUE, &st);
if (!dv) return;

/* 1. 检查质量 */
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));
DarraUa_DataValue_Delete(dv);
return;
}

/* 2. 检查值非空 */
const DarraUa_Variant* v = DarraUa_DataValue_GetValue(dv);
if (!v || DarraUa_Variant_GetType(v) == DARRA_UA_TYPE_NULL) {
printf("Null value\n");
DarraUa_DataValue_Delete(dv);
return;
}

/* 3. 取值 + 时间戳 */
double t = 0.0;
DarraUa_Variant_GetDouble(v, &t);
DarraUa_DateTime src = DarraUa_DataValue_GetSourceTimestamp(dv);
printf("%.2f °C @ ft=%lld\n", t, (long long)src);

/* 4. 释放 */
DarraUa_DataValue_Delete(dv);

StatusCode 重点值

含义
DARRA_UA_STATUS_GOOD (0x00000000)一切正常
0x40000000+ (Uncertain*)不确定但可用
0x80000000+ (Bad*)数据无效
DARRA_UA_STATUS_BAD_COMMUNICATION_ERROR通讯失败
DARRA_UA_STATUS_BAD_NODE_ID_UNKNOWN节点不存在
DARRA_UA_STATUS_BAD_NOT_READABLE该 Attribute 不可读

判断宏:

DARRA_UA_STATUS_IS_GOOD(code)
DARRA_UA_STATUS_IS_UNCERTAIN(code)
DARRA_UA_STATUS_IS_BAD(code)

业务代码必须检查 DataValue.Status, 不能假设 Good.


时间戳含义

DarraUa_DateTimeint64_t, 单位 100ns 自 1601-01-01 UTC. 与 Windows FILETIME 同, 与 time_t 转换公式:

/* DateTime → Unix epoch (秒) */
double unix_sec = (ft - 116444736000000000LL) / 10000000.0;

/* Unix epoch (秒) → DateTime */
DarraUa_DateTime ft = (DarraUa_DateTime)(unix_sec * 10000000.0) + 116444736000000000LL;
时间戳含义
SourceTimestamp数据真实产生时间 (传感器采样时刻 / 计算时刻). 历史 / 趋势 / 同步用这个
ServerTimestamp服务端收到 / 处理时间. 用于诊断网络延迟, 一般不用于业务

如果服务端没设 SourceTimestamp, 它就是 ServerTimestamp 的副本.


内存所有权

来源释放
DarraUa_Session_ReadNode(...) 单条DarraUa_DataValue_Delete(dv)
DarraUa_Session_ReadNodes(...) / _Read 数组每项每个非 NULL 项 DarraUa_DataValue_Delete
DarraUa_Session_HistoryReadRaw / _Modified / _AtTime / _ProcessedDarraUa_DataValueArray_Delete(arr, count) (一次性)
DarraUa_DataValue_New()DarraUa_DataValue_Delete(dv)

漏 Delete 会泄漏 native 内存, 长跑 100k 次 Read 后明显涨内存.

最佳实践:

/* 单条 */
DarraUa_DataValue* dv = DarraUa_Session_ReadNode(h, id, attr, &st);
if (dv) {
/* ... */
DarraUa_DataValue_Delete(dv);
}

/* 批量 */
DarraUa_DataValue* dvs[100] = { NULL };
DarraUa_Session_ReadNodes(h, ids, NULL, 100, dvs);
for (int i = 0; i < 100; ++i) {
if (dvs[i]) DarraUa_DataValue_Delete(dvs[i]);
}

/* 历史 (一次性释放) */
DarraUa_DataValue** hist = NULL; uint32_t cnt = 0;
DarraUa_Session_HistoryReadRaw(h, id, t1, t2, 0, 0, &hist, &cnt);
DarraUa_DataValueArray_Delete(hist, cnt);

下一步