C#上位机实现状态监控系统

在上位机软件开发中,除了向设备发送控制指令之外,还有一个非常常见的功能,就是实时监控设备的运行状态。

例如一台自动化设备,上位机可能需要持续显示:

设备是否在线

当前运行模式

温度

电压

转速

运行时间

当前任务状态

设备是否处于忙碌状态

这些状态通常来自串口、TCP、CAN 或其他通信方式。

如果把所有状态处理都直接写在界面代码中,随着设备参数越来越多,代码会变得比较混乱。因此实际开发中,可以单独设计一个设备状态监控模块,由它统一接收、保存和通知设备状态变化。

本文简单介绍一种 C# 上位机状态监控系统的实现思路。

一、状态监控系统主要做什么

状态监控和设备控制的作用并不完全一样。

设备控制主要是:

上位机

发送指令

设备执行

而状态监控更多是:

设备

周期上传数据

上位机接收

解析状态

更新内存数据

刷新界面

例如设备每隔1秒上传一次:

温度:36.5℃

电压:12.1V

转速:1200 RPM

状态:Running

上位机收到以后,需要将最新数据保存下来。

一个比较简单的结构可以设计成:

Device Communication

Protocol Parser

DeviceStateMonitor

DeviceState

UI

通信模块只负责收发数据。

协议模块负责解析数据。

DeviceStateMonitor 负责维护当前状态。

界面只读取或者监听状态变化。

这样各个模块职责会比较清楚。

二、定义设备状态模型

首先可以定义一个 DeviceState,用于保存设备当前状态。

例如:

public class DeviceState

{

public bool IsOnline { get; set; }

public DeviceRunState RunState { get; set; }

public double Temperature { get; set; }

public double Voltage { get; set; }

public int Speed { get; set; }

public DateTime LastUpdateTime { get; set; }

}

设备运行状态可以使用枚举:

public enum DeviceRunState

{

Unknown,

Idle,

Running,

Paused,

Stopped

}

例如当前设备状态:

DeviceState state = new DeviceState

{

IsOnline = true,

RunState = DeviceRunState.Running,

Temperature = 36.5,

Voltage = 12.1,

Speed = 1200,

LastUpdateTime = DateTime.Now

};

这样相比在程序中到处使用:

double temperature;

double voltage;

bool connected;

int state;

统一使用 DeviceState 会更加方便。

后续如果设备增加:

压力

流量

电流

工作模式

也可以继续在状态模型中扩展。

三、实现设备状态监控器

接下来创建 DeviceStateMonitor。

它主要负责维护当前设备状态。

例如:

public class DeviceStateMonitor

{

private DeviceState currentState =

new DeviceState();

public DeviceState CurrentState

{

    get

    {

        return currentState;

    }

}

public void Update(DeviceState newState)

{

    currentState = newState;

    currentState.LastUpdateTime =

        DateTime.Now;

}

}

设备收到新的数据后:

DeviceState state = new DeviceState

{

IsOnline = true,

RunState = DeviceRunState.Running,

Temperature = 38.2,

Voltage = 12.3,

Speed = 1250

};

monitor.Update(state);

然后其他模块可以读取:

Console.WriteLine(

monitor.CurrentState.Temperature

);

这种实现比较简单。

但在真实上位机软件中,通常还需要解决一个问题:

状态变化以后,如何通知界面刷新?

因此可以增加状态变化事件。

四、设备状态发生变化时通知界面

可以在 DeviceStateMonitor 中增加一个事件:

public class DeviceStateMonitor

{

private DeviceState currentState =

new DeviceState();

public event Action<DeviceState>

    StateChanged;

public DeviceState CurrentState

{

    get

    {

        return currentState;

    }

}

public void Update(DeviceState newState)

{

    currentState = newState;

    currentState.LastUpdateTime =

        DateTime.Now;

    StateChanged?.Invoke(currentState);

}

}

界面或者业务模块进行订阅:

monitor.StateChanged += state =>

{

Console.WriteLine(

$"当前温度:{state.Temperature}"

);

Console.WriteLine(

    $"当前转速:{state.Speed}"

);

};

以后每次收到新的设备数据:

monitor.Update(state);

都会触发 StateChanged。

整体过程变成:

设备上传数据

解析 DeviceState

DeviceStateMonitor.Update

StateChanged

界面刷新

如果使用 WPF,还可以继续结合:

INotifyPropertyChanged

或者 MVVM 数据绑定。

这样状态变化之后,界面可以自动刷新,不需要手动给每一个控件赋值。

五、如何判断设备是否掉线

设备状态监控除了显示温度、电压等数据之外,还有一个比较重要的功能:

判断设备是否在线。

例如设备正常情况下每隔2秒上传一次状态。

如果:

10秒没有收到任何设备数据

通常就可以认为设备已经离线。

前面 DeviceState 中已经保存:

LastUpdateTime

因此可以定时检查:

public bool CheckOnline()

{

TimeSpan timeout =

DateTime.Now -

currentState.LastUpdateTime;

if(timeout.TotalSeconds > 10)

{

    currentState.IsOnline = false;

    return false;

}

currentState.IsOnline = true;

return true;

}

例如:

正常:

12:00:01 收到数据

12:00:03 收到数据

12:00:05 收到数据

设备异常:

12:00:05 最后一次数据

12:00:15 仍然没有新数据

此时:

IsOnline = false

界面可以显示:

设备离线

这种方式比单纯判断:

TcpClient.Connected

更加可靠。

因为 TCP 连接对象显示 Connected,并不一定代表设备当前真的可以正常通信。

实际项目中通常会结合:

TCP连接状态

心跳数据

最后一次收到设备数据的时间

共同判断设备是否在线。

六、状态监控在实际上位机中的扩展

基础的状态监控完成以后,后续通常还会继续增加一些功能。

只通知真正发生变化的状态

例如设备每秒上传一次温度:

36.5

36.5

36.5

36.5

如果数据完全没有变化,没有必要每次都刷新整个界面。

可以比较新旧状态:

if(oldState.RunState != newState.RunState)

{

// 运行状态发生变化

}

对于部分状态,可以只在变化时通知。

保存一定时间的历史数据

例如:

10:01:01 35.2℃

10:01:02 35.5℃

10:01:03 35.7℃

10:01:04 36.0℃

可以保存最近:

100条

或者:

最近10分钟

的数据。

后续就可以用于:

实时曲线

趋势分析

状态回放

不过需要注意不要无限保存。

例如可以使用 Queue:

Queue

超过最大数量后删除最早的数据。

区分快速数据和普通状态

有些设备状态更新频率很高。

例如:

传感器采样数据:100ms一次

设备运行模式:几分钟才变化一次

可以分别管理:

RealtimeData

DeviceState

避免所有数据都使用一个大型 DeviceState 对象频繁刷新。

和报警模块进行配合

状态监控主要负责:

当前设备是什么状态

而异常报警负责:

这个状态是否正常

例如:

DeviceStateMonitor

Temperature = 85℃

AlarmChecker

温度过高报警

这样状态监控和报警系统可以保持独立。

一个相对完整的 C# 上位机结构可以是:

通信模块

协议解析

状态监控

业务逻辑

界面显示

同时:

状态监控

异常检测

报警系统

这种设计在设备越来越复杂以后会比较容易维护,也方便以后增加新的设备参数、状态类型和监控功能。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容