通信报文追踪
每个 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 | 把后续追踪记录持续写入文本文件 |
这些能力可以同时使用。PacketTraced 和 DataReceived 可能在 IO 线程触发,如果要更新 WinForms 或 WPF 控件,请仍然通过对应 UI 适配器或调度器切回界面线程。