跳到主要内容

设备模型

设备把「寄存器地址」或 PLC 地址变成业务含义,例如炉温。界面和业务应使用点表、ModbusDevice、McDevice、S7Device、FinsDevice、HostLinkDevice、MewtocolDevice 或 EtherNetIpDevice 的读写方法,而不是在窗口里拼十六进制。

登记​

先注册通道,再注册设备:

builder.AddAcquisition(TimeSpan.FromMilliseconds(500));
builder.AddVirtualChannel("bus", new ModbusSlaveResponder(1, ModbusTransport.Rtu));
builder.AddModbusRtu("oven", "bus", unitId: 1, points: map =>
{
map.HoldingRegister("temperature", 0, 0.1);
map.HoldingRegister("setpoint", 1, 0.1).Writable("setpoint");
});

自定义设备必须实现 IDevice.Channel(继承 DeviceBase 即可)。卸载通道时,宿主靠这个属性级联移除设备。

自定义设备:

public sealed class TemperatureMeter : DeviceBase, IAcquisitionSource
{
public TemperatureMeter(string name, IChannel channel)
: base(name, channel)
{
Points = [new PointDefinition("temperature", name, PointValueKind.Double)];
// 需要按点名写回时,再实现 IPointWriter,并把对应点标为 writable: true。
}

public IReadOnlyList<PointDefinition> Points { get; }

public async Task<IReadOnlyList<PointReadResult>> ReadAsync(CancellationToken cancellationToken)
{
// 读取通道、换算后返回结果;点表发布和报警由宿主统一处理。
var value = await ReadTemperatureAsync(cancellationToken);
return [PointReadResult.Success(Name + ".temperature", value)];
}
}

builder.AddDevice("oven", "bus", (name, channel) => new TemperatureMeter(name, channel));

运行时:

  • app.Points.Get<double>("temperature") 读取采集循环维护的当前值
  • await app.Points.WriteAsync("setpoint", 80.0) 按点名写回可写点
  • app.Devices.Get<ModbusDevice>("oven")、app.Devices.Get<S7Device>("plc")、app.Devices.Get<HostLinkDevice>("plc")、app.Devices.Get<MewtocolDevice>("plc")、app.Devices.Get<EtherNetIpDevice>("plc")、app.Devices.Get<Dlt645Device>("meter")、app.Devices.Get<Iec104Device>("station")、app.Devices.Get<OpcUaDevice>("plc") 做一次性或批量协议读写

自定义设备若要支持点名写回,除了 IAcquisitionSource 再实现 IPointWriter。

约定​

  • 一台设备绑定一条通道。多台设备共用通道时,宿主会按通道协调协议事务,避免同一物理通道上交错请求。
  • 设备名在宿主内唯一,查找时不区分大小写。
  • 点名在设备内唯一;不同设备出现同名点时,使用 设备.点。
  • 设备类型不要引用 WinForms 或 WPF。
  • 实现了 IAcquisitionSource 且声明了点的设备,会自动进入采集循环;采集源只返回 PointReadResult,不要直接写点表。