夜雨聆风学习资料网

ARTICLE · 979415

DeMate插件开发(三)- 实时波形MatePlot

DeMate插件开发(三)- 实时波形MatePlot

DeMate 是一个支持插件的上位机软件,各种分析工具可以像插件一样灵活挂载、按需组合。MatePlot是在这个体系下沉淀出来的实时波形处理插件,作为 DeMate 的功能模块快速集成,把"数据通信和解析、波形显示、谐波分析、平均值和有效值计算"这些能力开箱即用(文后有演示视频)。

一、MatePlot 简介

MatePlot插件接收设备发送的高速采样的原始字节流,解析成多通道波形,按示波器的方式实时渲染出来。

DeMate 宿主启动时扫描插件目录,加载 dll 插件,并将平台服务接口注入 dll;用户点开菜单时DeMate就把插件的窗口展开显示在 Dock 面板里,也可以设置成普通的窗口。

二、整体架构

MatePlot 内部是一条三级流水线,通信、解析、处理各占一级,显示层复用封装的一个外部控件PlotControl,每一级的线程模型都不一样:

通信层的网络回调线程只把接收到的数据拷贝入队,解析线程只做字节搬运,处理线程只做数值解码,UI 层(PlotControl)只做渲染。某一级卡住了,不会顺着流水线往上传。

三、插件接口

DeMate 的插件体系的契约就是一个接口:

public interface IPlugInBase{    string Title { get; }              // 菜单标题    string Author { get; }    string Description { get; }    string Version { get; }            // 直接取程序集版本号    void Init(IMateService service);   // 宿主注入平台服务    void ShowForm(DockPanel panel);    // 在 Dock 面板中展示主窗体    void ShowForm(Control container);}

MatePlot 的入口类 MatePlotBase 实现了这个接口,Init 保存宿主传入的 IMateService,获得宿主的所有能力(配置、通信、数据,等),ShowForm 将窗口停靠为文档页或普通窗口。

插件并不关心数据长什么样,通道数量、通道名称、每个采样点的数据类型全都由点表配置文件定义,换一套设备、换一份点表,不用修改插件代码。

四、架构分层

1. 通信层

网络通信层基于 SuperSocket 的 AsyncTcpSession。Socket 收到的每个数据包都会被完整拷贝后放进 ConcurrentQueue< DataEventArgs>,防止数据被覆盖。

2. 解析层

解析层是一条专属的监听线程,从ConcurrentQueue< DataEventArgs>队列里取出字节流,交给 PlotDataReceiver 里的逐字节状态机拼帧。状态机在字节流里滑动找帧头,锁定后按有效数据长度收满 Payload,可配置地校验 CRC16-Modbus,然后交付一帧,上一帧丢了或者错位,下一帧还能重新对上。

3. 处理层

完整帧通过 OnFrameReceived 进入 FormPlot 的队列ConcurrentQueue< PlotDataFrame>实,队列超限后删除最旧的PlotDataFrame对象,实时波形插件选择断流也不能把内存吃爆。

后台线程FrameHandlerThread 以固定的节拍清空队列,核心逻辑是"点表驱动解码":

// 伪代码:按点表中每个通道的数据类型切分字节foreach (var item in currentRTGroup.Items){    switch (item.DataType)    {case DataTypeEnum.Uint16: data = BitConverter.ToUInt16(frame.Data, offset); offset += 2; break;case DataTypeEnum.Int16:  data = BitConverter.ToInt16(frame.Data, offset);  offset += 2; break;case DataTypeEnum.Float:   data = BitConverter.ToSingle(frame.Data, offset); offset += 4; break;    }    dataArray[i][sample] = data;}scope1.AddData(dataArray);   // 一次性灌入显示层

一帧字节的物理含义,全由点表定义。

4.显示层

MatePlot 没有把画图代码写死在插件里,画图能力来自独立的 PlotControl 项目,用的是其中的 Scope 控件(IScope 接口)。

绘图区是双区视图:上面主视图,下面全量概览,量程各自独立调整。在数据处理方面,RealTimeDataManager 给每个通道配一个 CircularBuffer 环形缓冲,写入 O(1),渲染时 ReadToLinearArray 取快照。刷新由 UpdateInterval 控制,默认 200ms。数据可以每秒几十万点地灌进来,显示层只按自己的节奏重绘,两边互不干扰。

五、设计亮点

1. 最小契约的插件机制

一个接口换整个平台的扩展性。PluginLoadContext做依赖隔离加载,插件之间互不污染。

2. 三级流水线,四种角色

网络回调、解析线程、处理线程、UI 定时器各司其职,靠 ConcurrentQueue 串联,无锁,背压可控。

3.点表驱动

协议写进配置而非代码,换设备零改动。

4.防御性设计

帧头重同步、CRC 校验、队列上限丢帧、字节拷贝防缓冲区复用。单拎出来哪个都不新鲜,凑齐了就稳了。

5. 控件级复用

示波器能力沉淀在 PlotControl 独立项目,插件薄。环形缓冲加定时刷新,吞吐和帧率独自控制,达到渲染频率与数据频率解耦的目的。

演示视频:

相关学习资料

返回首页浏览学习资料