跳到主要内容

通信报文追踪

每个 IChannel 都会在收发原始字节时触发 PacketTraced。它不解析协议,只记录通道实际提交的 TX 字节和底层收到的 RX 字节,适合现场调试、通信窗口和故障快照。

直接订阅事件

var meter = app.Channels.Get("meter");
meter.PacketTraced += (_, e) =>
{
var direction = e.Direction == ChannelTraceDirection.Sent ? "TX" : "RX";
Console.WriteLine($"{e.Timestamp:O} {meter.Name} {direction} {e.Hex}");
};

Hex 是连续大写十六进制字符串。如果需要带空格的显示,可以自己格式化 e.Data.Span

保留最近 N 条

如果只想保留最近一段通信记录,使用 ChannelTraceBuffer

var meter = app.Channels.Get("meter");
using var trace = new ChannelTraceBuffer(meter, capacity: 200);

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

foreach (var entry in trace.Entries)
{
Console.WriteLine($"{entry.Timestamp:HH:mm:ss.fff} {entry.ChannelName} {entry.Direction} {entry.Hex}");
}

Entries 返回的是快照,顺序从旧到新。容量满后会自动丢弃最旧记录。

写入文件

现场复盘或长时间抓包时,使用 ChannelTraceFileLogger 把后续报文写入文本文件:

var meter = app.Channels.Get("meter");
using var traceFile = new ChannelTraceFileLogger(meter, "logs/meter-trace.log", append: true);

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

每行是制表符分隔的四列:UTC 时间、通道名、方向和连续大写十六进制载荷。例如:

2026-08-14T01:23:45.6789012+00:00 meter Sent 01030000

释放 ChannelTraceFileLogger 后会自动退订通道事件。父目录不存在时会自动创建;append: false 可以覆盖重建日志文件。

和 DataReceived 的区别

API用途
DataReceived业务或协议层消费收到的数据
PacketTraced诊断层记录发送和接收的原始字节
ChannelTraceBuffer在内存中滚动保留最近 N 条追踪记录
ChannelTraceFileLogger把后续追踪记录持续写入文本文件

这些能力可以同时使用。PacketTracedDataReceived 可能在 IO 线程触发,如果要更新 WinForms 或 WPF 控件,请仍然通过对应 UI 适配器或调度器切回界面线程。

下一步:看 虚拟通道 快速模拟收发,或看 自定义帧 在追踪之上做协议解析。