Virtual Channel
A virtual channel lets you develop and test without real hardware. It does not occupy a COM port or connect to a network, but it uses the same channel state, write, and receive APIs as real channels.
Minimal Usage
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 });
The default virtual channel echoes what you write. Writing 01 02 raises a receive event with 01 02.
Why Use It
| Without a virtual channel | With a virtual channel |
|---|---|
| UI work waits for hardware | Build UI, buttons, bindings, and logs first |
| Tests depend on a local COM port | Tests can run on any machine and CI |
| Hardware/program boundary is unclear | Verify application structure first |
| Demos require devices | Demonstrate the send/receive workflow directly |
Replace with Serial Later
Start with:
builder.AddVirtualChannel("meter");
Then switch to:
builder.AddSerialPort("meter", "COM3", 9600);
The rest of the code can continue to use app.Channels.Get("meter") and WriteAsync.
Simulate a Slave
Virtual channels can use responders instead of plain echo. For example, simulate a Modbus slave:
var memory = new ModbusSlaveMemory();
memory.HoldingRegisters[0] = 185;
builder.AddVirtualChannel(
"bus",
new ModbusSlaveResponder(1, ModbusTransport.Rtu, memory));
Or simulate Siemens S7:
var memory = new S7SlaveMemory();
var db1 = memory.GetDataBlock(1);
db1[0] = 0x41;
db1[1] = 0x48;
db1[2] = 0x00;
db1[3] = 0x00;
builder.AddVirtualChannel("plc-link", new S7SlaveResponder(memory));
builder.AddSiemensS7("plc", "plc-link", points: map =>
{
map.DbReal("temperature", dbNumber: 1, byteOffset: 0);
});
Custom Responder
public sealed class EchoWithAckResponder : IVirtualResponder
{
public ReadOnlyMemory<byte>? Respond(ReadOnlyMemory<byte> request)
{
return new byte[] { 0x06 }; // ACK
}
}
builder.AddVirtualChannel("meter", new EchoWithAckResponder());
Next: Serial Port, Modbus, Siemens S7, or EtherNet/IP.