跳到主要内容

NumericRange — 数组 / 矩阵子段读写

概述

OPC UA Part 4 §7.27 NumericRange 表示 Value 属性的数组 / 矩阵子范围, 用于 Read / Write 时只取 / 写部分元素, 不传整段。常见编码:

字符串含义
""整段 (All)
"5"第 5 个元素
"3:7"第 3-7 个 (含端点)
"1:3,2:4"二维矩阵: 第一维 [1..3], 第二维 [2..4]
"0:5,10"二维: 第一维 [0..5], 第二维仅第 10 个

API

成员类别读写说明
NumericRange.All静态整段
NumericRange.Single(int)工厂单一索引
NumericRange.Span(start, end)工厂区间
NumericRange.Multi(params NumericRange[])工厂多维
NumericRange.Parse(string)静态解析字符串
NumericRange.TryParse(s, out r)静态安全解析
range.ToString()方法序列化为 OPC UA 字符串
range.Start / End属性起止下标 (-1 = 整段)
range.SubRanges属性多维子范围
range.IsAll属性是否整段
ua.ReadRange(nid, range, attr)扩展读子段, 返回 DataValue
ua.WriteRange(nid, range, value)扩展写子段, 返回 StatusCode

代码示例

using DarraOpcUa_Client;

using var ua = new DarraOpcUa("opc.tcp://localhost:4840");
ua.Connect();

// 1) 读单个元素
using (var dv = ua.ReadRange("ns=2;s=Arr", NumericRange.Single(3)))
Console.WriteLine($"Arr[3] = {dv.Value}");

// 2) 读区间
using (var dv = ua.ReadRange("ns=2;s=Arr", NumericRange.Span(0, 99)))
foreach (var v in dv.Value.AsArray<double>())
Console.WriteLine(v);

// 3) 读二维矩阵子段
var range2D = NumericRange.Multi(NumericRange.Span(0, 9), NumericRange.Span(0, 9));
using (var dv = ua.ReadRange("ns=2;s=Matrix", range2D))
Console.WriteLine($"10×10 子矩阵, 共 {dv.Value.AsArray<double>().Length} 元素");

// 4) 写单个元素
var rc = ua.WriteRange("ns=2;s=Arr", NumericRange.Single(0), new Variant(42.5));
if (rc != StatusCode.Good) Console.WriteLine($"写失败: {rc}");

// 5) 字符串解析
var r = NumericRange.Parse("3:7");
Console.WriteLine(r.ToString()); // "3:7"

if (NumericRange.TryParse("0:5,10", out var r2D))
Console.WriteLine($"维度数 = {r2D.SubRanges.Length}");

// 6) 整段 — 等价于不带 range 的 Read
using (var dv = ua.ReadRange("ns=2;s=Arr", NumericRange.All))
Console.WriteLine($"全部 {dv.Value.AsArray<double>().Length} 元素");

实现说明

  • Stack 不提供 *WithRange PInvoke 时, ReadRange / WriteRangeNotImplementedException 并打 Warn 日志 (不做"假装成功"兜底)
  • range.IsAll 时, ReadRange 直接转发 Read, 不依赖 Stack 扩展
  • WriteRange 只支持服务端 Value 是数组 / 矩阵的节点, 写 scalar 节点服务端返回 BadIndexRangeInvalid

错误处理

StatusCode含义
Good成功
BadIndexRangeInvalidrange 字符串非法 / 节点非数组
BadIndexRangeNoDatarange 在节点数据范围外
BadTypeMismatch写入值与节点 DataType 不符

最佳实践

  • 大数组只取片 — 1 万元素曲线只看尾部 100 点, 用 Span(9900, 9999) 省 99% 流量
  • 矩阵按行 / 列拆NumericRange.Multi(Span(i, i), Span(0, cols-1)) 取第 i 行
  • 写入只动改了的索引 — 不要把整数组重传一遍, 用 Single(i) 写单点
  • 不要每次都 ParseNumericRange.Span(0, 99)NumericRange.Parse("0:99")

跨语言对照

C#PythonJavaC++RustC
NumericRangeNumericRangeNumericRangeNumericRangeNumericRangeDarraUa_NumericRange
ReadRangeread_rangereadRangeReadRangeread_rangeDarraUa_Session_ReadRange
WriteRangewrite_rangewriteRangeWriteRangewrite_rangeDarraUa_Session_WriteRange

下一步