宿主
宿主就是 Zeus 程序的总开关。它负责创建通道、打开通道、启动采集循环、停止时释放资源。
最小写法
await using var app = ZeusHost.Create(builder =>
{
builder.AddVirtualChannel("meter");
});
await app.StartAsync();
var meter = app.Channels.Get("meter");
await meter.WriteAsync(new byte[] { 0x01 });
await app.StopAsync();
读法是:
ZeusHost.Create:声明“这个程序有哪些通道、设备和服务”。StartAsync:真正打开通道并启动后台服务。Channels.Get:拿到运行中的通道。StopAsync:关闭通道并释放资源。
Create 阶段只声明,不打开
这段代码只是在登记通道:
await using var app = ZeusHost.Create(builder =>
{
builder.AddSerialPort("meter", "COM3", 9600);
});
此时串口还没有打开。真正打开是在:
await app.StartAsync();
所以如果你在 StartAsync 前调用 WriteAsync,会看到“当前为 Created,无法写入”。
注册顺序怎么写
一般按这个顺序:
await using var app = ZeusHost.Create(builder =>
{
builder.AddAcquisition(TimeSpan.FromMilliseconds(500));
builder.AddSerialPort("bus", "COM3", 9600);
builder.AddModbusRtu("oven", "bus", unitId: 1, points: map =>
{
map.HoldingRegister("temperature", 0, raw => raw * 0.1);
});
});
| 顺序 | 为什么 |
|---|---|
| 先配置采集 | 采集间隔是宿主级设置 |
| 再注册通道 | 设备需要绑定已有通道 |
| 再注册设备 | 设备会引用通道名 |
| 最后启动宿主 | 所有东西都声明完再打开 |
运行时可以查什么
var channel = app.Channels.Get("bus");
var device = app.Devices.Get<ModbusDevice>("oven");
var temperature = app.Points.Get<double>("temperature");
| 目录 | 用途 |
|---|---|
app.Channels | 查通道,例如串口、TCP、虚拟通道 |
app.Devices | 查设备,例如 Modbus 设备 |
app.Points | 查点表,例如温度、压力、开关量 |
找不到名称时,异常会列出当前已经注册的名称,方便你对照拼写。
在宿主里注册自己的服务
Zeus 使用 .NET 依赖注入。你可以把自己的业务服务放进去:
await using var app = ZeusHost.Create(builder =>
{
builder.Services.AddSingleton<MyBusinessService>();
builder.AddVirtualChannel("meter");
});
这适合把采集后的业务处理、报警判断、数据库写入等逻辑拆出窗体类。
常见问题
| 现象 | 原因 | 处理 |
|---|---|---|
通道名称已存在 | 注册了两个同名通道 | 给通道改名,例如 ovenBus、plcBus |
当前为 Created,无法写入 | 还没启动宿主 | 先 await app.StartAsync() |
| 某个通道启动失败 | 串口被占用、TCP 连不上或参数错误 | 其它通道会继续启动,查看日志和通道 State |
| 关闭程序后端口仍被占用 | 没释放宿主 | 使用 await using,或在关闭窗口时调用释放逻辑 |