跳到主要内容

点表与采集

点表就是把设备里的寄存器、线圈或其它数据,命名成业务能理解的点。比如把 Modbus 地址 0 命名为 temperature

采集循环就是 Zeus 按固定间隔帮你读取这些点。你不需要自己写 while trueTask.Delay、重试和界面刷新。

先看完整例子

var memory = new ModbusSlaveMemory();
memory.HoldingRegisters[0] = 185;
memory.HoldingRegisters[1] = 200;

await using var app = ZeusHost.Create(builder =>
{
builder.AddAcquisition(TimeSpan.FromMilliseconds(500));
builder.AddVirtualChannel("bus", new ModbusSlaveResponder(1, ModbusTransport.Rtu, memory));
builder.AddModbusRtu("oven", "bus", unitId: 1, points: map =>
{
map.HoldingRegister("temperature", 0, raw => raw * 0.1);
map.HoldingRegister("setpoint", 1, raw => raw * 0.1);
map.Coil("heater", 2);
});
});

app.Points.Changed += (_, e) =>
{
Console.WriteLine($"{e.Current.QualifiedName} = {e.Current.Value}");
};

await app.StartAsync();
var temperature = app.Points.Get<double>("temperature");

这段代码怎么理解

代码含义
AddAcquisition(500ms)每 500 ms 采集一轮
HoldingRegister("temperature", 0, raw => raw * 0.1)地址 0 的保持寄存器叫 temperature,原始值乘以 0.1
Coil("heater", 2)地址 2 的线圈叫 heater
app.Points.Changed点值或错误变化时触发
app.Points.Get<double>("temperature")读取当前最新温度

为什么不要自己写循环

你当然可以自己写:

while (true)
{
var values = await oven.ReadHoldingRegistersAsync(0, 2);
await Task.Delay(500);
}

但实际项目很快会遇到:

  • 多个点地址连续,应该合并读取。
  • 某轮读取失败,界面还要保留上一次成功值。
  • 多个设备需要统一间隔。
  • UI 要订阅变化,而不是到处主动拉取。

Zeus 的点表采集就是为这些场景准备的。

点名怎么查

如果整个宿主里只有一个 temperature,可以直接写:

var value = app.Points.Get<double>("temperature");

如果多台设备都有 temperature,使用完整名:

var ovenTemperature = app.Points.Get<double>("oven.temperature");
var tankTemperature = app.Points.Get<double>("tank.temperature");

尚无有效值怎么办

StartAsync 返回后,第一轮采集可能还在进行。稳妥写法是订阅变化:

app.Points.Changed += (_, e) =>
{
if (e.Current.Error is null)
{
Console.WriteLine($"{e.Current.QualifiedName} = {e.Current.Value}");
}
else
{
Console.WriteLine($"{e.Current.QualifiedName} 采集失败:{e.Current.Error.Message}");
}
};

或者使用 TryGet

if (app.Points.TryGet<double>("temperature", out var value))
{
Console.WriteLine(value);
}

绑定到界面

WinForms / WPF 都可以直接绑定点:

app.Points.BindTo("temperature", temperatureLabel, value => $"{value:F1} ℃");

这样界面只关心显示格式,不需要关心采集线程和设备协议。

采集优化

Zeus 会尽量把同一设备上连续的地址合并读取。

点声明读取效果
地址 0、1、2 连续可以合并成一次读取
地址 0、100 分散通常需要分开读取
不同设备分别按设备读取

总线较慢时,优先让常用点地址连续,并适当加大采集间隔。

常见问题

现象原因处理
尚无有效值第一轮采集还没成功订阅 Changed,或稍后再 Get
点名冲突多台设备有同名点使用 设备名.点名
界面值不更新没声明点,或采集循环没启用确认 AddAcquisitionpoints 都写了
某轮失败但界面还有旧值Zeus 保留上一次成功值查看点快照里的 Error
总线被采集打满间隔太短或地址太分散加大间隔,合并连续地址

下一步:把点表写进文件看 JSON 配置