DataValue (C)
DarraUa_DataValue* 包装一次 Read 返回的全部信息: 值 + 状态 + 时间戳.
配套
- 内部值容器请看 Variant.
- 标准节点常量请看 WellKnownNodes.
公共 API
| 类别 | 属性 | 类型 | 访问 | 说明 |
|---|---|---|---|---|
| 生命周期 | DarraUa_DataValue_New() | DarraUa_DataValue* | RW | 新建空 DataValue (HistoryUpdate 才用) |
DarraUa_DataValue_Delete(dv) | void | W | 释放; dv 为 NULL 时安全 | |
| 字段 | DarraUa_DataValue_GetValue(dv) | const DarraUa_Variant* | R | 实际值, 生命周期 = dv, 不要 Delete |
DarraUa_DataValue_GetStatus(dv) | uint32_t | R | 数据质量 StatusCode | |
DarraUa_DataValue_GetSourceTimestamp(dv) | DarraUa_DateTime | R | 数据源时间戳 (100ns since 1601) | |
DarraUa_DataValue_GetServerTimestamp(dv) | DarraUa_DateTime | R | 服务端时间戳 |
用法
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_DateTime 是 int64_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 / _Processed | DarraUa_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);