跳到主要内容

虚拟通道

虚拟通道是没有真实硬件时用来联调的通道。它不占用 COM 口,也不连接网络,但状态、写入、接收事件都和真实通道使用同一套 API。

最小用法

await using var app = ZeusHost.Create(builder =>
{
builder.AddVirtualChannel("meter");
});

var meter = app.Channels.Get("meter");
meter.DataReceived += (_, e) =>
{
Console.WriteLine(Convert.ToHexString(e.Data.Span));
};

await app.StartAsync();
await meter.WriteAsync(new byte[] { 0x01, 0x02 });

默认虚拟通道会回显写入内容。你写入 01 02,就会收到 01 02

它解决什么问题

没有虚拟通道时使用虚拟通道后
必须等仪表到货才能写界面先把界面、按钮、绑定和日志写完
单元测试依赖本机 COM 口测试可以在任意机器和 CI 上跑
不确定 bug 在硬件还是程序先用虚拟通道确认程序结构
演示时必须带设备可以直接演示收发流程

从虚拟通道换到真实串口

先写成:

builder.AddVirtualChannel("meter");

等界面和业务流程跑通后,再改成:

builder.AddSerialPort("meter", "COM3", 9600);

后面的代码不变:

var meter = app.Channels.Get("meter");
await meter.WriteAsync(payload);

这能帮你把问题分开:如果虚拟通道能跑、真实串口不能跑,大概率是端口、波特率、接线或设备协议问题。

模拟一个从站

虚拟通道也可以挂一个应答器,不只是简单回显。比如模拟 Modbus 从站:

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

builder.AddVirtualChannel(
"bus",
new ModbusSlaveResponder(1, ModbusTransport.Rtu, memory));

这样你的主站代码可以先读到虚拟寄存器,等真实仪表到位后再把 AddVirtualChannel 换成 AddSerialPort

自定义应答器

如果你的私有协议不是 Modbus,可以实现 IVirtualResponder

public sealed class EchoWithAckResponder : IVirtualResponder
{
public ReadOnlyMemory<byte>? Respond(ReadOnlyMemory<byte> request)
{
return new byte[] { 0x06 }; // 例如返回 ACK
}
}

注册:

builder.AddVirtualChannel("meter", new EchoWithAckResponder());

常见问题

现象原因处理
收不到回显没启动宿主,或写入前没订阅事件StartAsync,再 WriteAsync;事件最好在启动前订阅
状态不是 Open宿主还没启动查看是否调用了 await app.StartAsync()
想模拟慢速设备当前内置虚拟通道是立即应答在自定义 IVirtualResponder 外层自行加入业务等待逻辑
换真实串口后行为不同真实设备不会自动回显按设备手册发送正确协议帧

下一步:接真实串口看 串口,读 Modbus 看 Modbus