C#监控设备(PLC)状态仿真模拟器

C#监控设备状态(如PLC),并记录到本地sqlite数据库中。

本文只是一个【设备状态仿真模拟器】

新建winform应用程序DeviceStatusDemo,选择.net framework 4.5.将默认的Form1重命名为FormDeviceStatus。

添加对System.Data.SQLite.dll的引用

窗体FormDeviceStatus设计如下

 一、添加日志处理类Context,Context.cs源程序:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.IO;
using System.Threading;

namespace DeviceStatusDemo
{
    /// <summary>
    /// 上下文实例类
    /// </summary>
    public static class Context
    {
        /// <summary>
        /// 显示普通日志
        /// </summary>
        public static event Action<string> EventInfoLog;
        /// <summary>
        /// 显示错误信息
        /// </summary>
        public static event Action<string, Exception> EventErrorLog;
        /// <summary>
        /// 显示错误日志
        /// </summary>
        /// <param name="strErrorMsg">错误信息</param>
        /// <param name="ex">异常对象</param>
        public static void ShowError(string strErrorMsg, Exception ex = null)
        {
            if (strErrorMsg == "" || strErrorMsg == null)
            {
                return;
            }
            EventErrorLog?.BeginInvoke(strErrorMsg, ex, null, null);
        }
        /// <summary>
        /// 显示日志信息
        /// </summary>
        /// <param name="strErrorMsg"></param>
        public static void ShowInfo(string strErrorMsg)
        {
            EventInfoLog?.BeginInvoke(strErrorMsg, null, null);
        }
    }
}

二、新建 设备状态数据类DeviceStatusData,同时定义设备状态枚举 DeviceStatus,读取设备状态枚举的描述信息。DeviceStatusData.cs源程序如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace DeviceStatusDemo
{
    /// <summary>
    /// 设备状态数据类:待料、堵料、自动、手动、故障
    /// </summary>
    public class DeviceStatusData
    {
        /// <summary>
        /// 日期,格式: yyyy-MM-dd
        /// </summary>
        public string RecordDate { get; set; }
        /// <summary>
        /// 班次:白班、夜班
        /// </summary>
        public string RecordShift { get; set; }
        /// <summary>
        /// 当前设备状态【待料、堵料、自动、手动、故障】中的某一个枚举
        /// </summary>
        public string DeviceStatus { get; set; }
        /// <summary>
        /// 设备状态代码
        /// </summary>
        public short DeviceStatusCode { get; set; }
        /// <summary>
        /// 开始时间
        /// </summary>
        public DateTime BeginTime { get; set; }
        /// <summary>
        /// 结束时间
        /// </summary>
        public DateTime EndTime { get; set; }

        /// <summary>
        /// 状态保持时间(s)
        /// </summary>
        public double Duration { get; set; }

        /// <summary>
        /// 设备工位:如 密封钉A工作台、顶盖焊B工作台
        /// </summary>
        public string DevicePosition { get; set; }

        /// <summary>
        /// 记录设备状态描述信息,比如:设备状态由【自动】切换到【待料】
        /// </summary>
        public string DeviceStatusMessage { get; set; }
    }

    /// <summary>
    /// 设备状态枚举
    /// </summary>
    public enum DeviceStatus : short
    {
        /// <summary>
        /// 自动
        /// </summary>
        [Description("自动")]
        Auto = 1,
        /// <summary>
        /// 手动
        /// </summary>
        [Description("手动")]
        Manual = 2,
        /// <summary>
        /// 待料
        /// </summary>
        [Description("待料")]
        WaitingForMaterial = 3,
        /// <summary>
        /// 堵料
        /// </summary>
        [Description("堵料")]
        Blocking = 4,
        /// <summary>
        /// 故障
        /// </summary>
        [Description("故障")]
        Fault = 5
    }

    public static class Util
    {
        /// <summary>
        /// 根据枚举值得到枚举中文信息
        /// </summary>
        /// <param name="enumType">一种枚举类型</param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string GetEnumDescription(this Type enumType, int? value)
        {
            //如果不是枚举类型,直接返回
            if (!enumType.IsEnum)
            {
                return value == null ? "" : value.ToString();
            }
            FieldInfo[] fields = enumType.GetFields();
            //不考虑枚举默认的第一个元素
            for (int i = 1, count = fields.Length; i < count; i++)
            {
                if (Convert.ToInt32(Enum.Parse(enumType, fields[i].Name)) == value)
                {
                    DescriptionAttribute[] enumAttributes = (DescriptionAttribute[])fields[i].GetCustomAttributes(typeof(DescriptionAttribute), false);
                    if (enumAttributes.Length > 0)
                    {
                        return enumAttributes[0].Description;
                    }
                }
            }
            return value == null ? "" : value.ToString();
        }

    }
}

三、新建sqlite数据库操作类SqliteDbHelper,SqliteDbHelper.cs源程序:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SQLite;
using System.Linq;
using System.Text;

namespace DeviceStatusDemo
{
    /// <summary>
    /// 功能:sqlite数据库操作类
    /// </summary>
    public class SqliteDbHelper
    {
        static object ObjLock = new object();
        /// <summary>
        /// 连接字符串
        /// </summary>
        private string m_strConnectString = string.Empty;

        /// <summary> 
        /// 构造函数 
        /// </summary> 
        /// <param name="strDbPath">SQLite数据库文件路径</param> 
        public SqliteDbHelper(string strDbPath)
        {
            this.m_strConnectString = "Data Source=" + strDbPath + ";Pooling=true;FailIfMissing=false;Journal Mode=WAL";
        }

        /// <summary> 
        /// 创建SQLite数据库文件 
        /// </summary> 
        /// <param name="strDbPath">要创建的SQLite数据库文件路径</param> 
        /// <param name="strdbTableCreateString">要创建的SQLite数据库表格</param> 
        public static void CreateDB(string strDbPath, string strdbTableCreateString)
        {
            using (SQLiteConnection connection = new SQLiteConnection("Data Source=" + strDbPath))
            {
                connection.Open();
                using (SQLiteCommand command = new SQLiteCommand(connection))
                {
                    command.CommandText = strdbTableCreateString;
                    command.ExecuteNonQuery();
                }
            }
        }

        /// <summary> 
        /// 对SQLite数据库执行增删改操作,返回受影响的行数。 
        /// </summary> 
        /// <param name="strSql">要执行的增删改的SQL语句</param> 
        /// <param name="parameters">执行增删改语句所需要的参数,参数必须以它们在SQL语句中的顺序为准</param> 
        /// <returns>返回受影响的行数</returns> 
        public int ExecuteNonQuery(string strSql, SQLiteParameter[] parameters)
        {
            try
            {
                int intAffectedRows = 0;
                using (SQLiteConnection connection = new SQLiteConnection(m_strConnectString))
                {
                    connection.Open();
                    lock (ObjLock)
                    {
                        using (DbTransaction transaction = connection.BeginTransaction())
                        {
                            using (SQLiteCommand command = new SQLiteCommand(connection))
                            {
                                command.CommandText = strSql;
                                if (parameters != null)
                                {
                                    command.Parameters.AddRange(parameters);
                                }
                                intAffectedRows = command.ExecuteNonQuery();
                            }
                            transaction.Commit();
                        }
                    }
                }
                return intAffectedRows;
            }
            catch (Exception ex)
            {
                Context.ShowError("执行sql语句异常," + ex.Message + "\r\n详细sql语句为:" + strSql, ex);
                return -1;
            }
        }

        public int ExecuteNonQueryByDict(string strSql, Dictionary<string, object> dicParams)
        {
            try
            {
                int intAffectedRows = 0;
                using (SQLiteConnection connection = new SQLiteConnection(m_strConnectString))
                {
                    connection.Open();
                    lock (ObjLock)
                    {
                        using (DbTransaction transaction = connection.BeginTransaction())
                        {
                            using (SQLiteCommand command = new SQLiteCommand(connection))
                            {
                                command.CommandText = strSql;
                                if (dicParams != null && dicParams.Count > 0)
                                {
                                    command.Parameters.Clear();
                                    foreach (string parameterName in dicParams.Keys)
                                    {
                                        command.Parameters.AddWithValue(parameterName, dicParams[parameterName]);
                                    }
                                }
                                intAffectedRows = command.ExecuteNonQuery();
                            }
                            transaction.Commit();
                        }
                    }
                }
                return intAffectedRows;
            }
            catch (Exception ex)
            {
                Context.ShowError("执行sql语句异常," + ex.Message + "\r\n详细sql语句为:" + strSql, ex);
                return -1;
            }
        }

        /// <summary> 
        /// 执行一个查询语句,返回一个关联的SQLiteDataReader实例 
        /// </summary> 
        /// <param name="strSql">要执行的查询语句</param> 
        /// <param name="parameters">执行SQL查询语句所需要的参数,参数必须以它们在SQL语句中的顺序为准</param> 
        /// <returns>返回SQLiteDataReader</returns> 
        public SQLiteDataReader ExecuteReader(string strSql, SQLiteParameter[] parameters)
        {
            SQLiteConnection connection = new SQLiteConnection(m_strConnectString);
            SQLiteCommand command = new SQLiteCommand(strSql, connection);
            if (parameters != null)
            {
                command.Parameters.AddRange(parameters);
            }
            connection.Open();
            return command.ExecuteReader(CommandBehavior.CloseConnection);
        }

        /// <summary> 
        /// 执行一个查询语句,返回一个包含查询结果的DataTable 
        /// </summary> 
        /// <param name="strSql">要执行的查询语句</param> 
        /// <param name="parameters">执行SQL查询语句所需要的参数,参数必须以它们在SQL语句中的顺序为准</param> 
        /// <returns>返回数据表</returns> 
        public DataTable ExecuteDataTable(string strSql, SQLiteParameter[] parameters)
        {
            using (SQLiteConnection connection = new SQLiteConnection(m_strConnectString))
            {
                using (SQLiteCommand command = new SQLiteCommand(strSql, connection))
                {
                    if (parameters != null)
                    {
                        command.Parameters.AddRange(parameters);
                    }
                    SQLiteDataAdapter adapter = new SQLiteDataAdapter(command);
                    DataTable data = new DataTable();
                    lock (ObjLock)
                    {
                        adapter.Fill(data);
                    }
                    return data;
                }
            }

        }

        public DataTable GetDataTable(string strSql, Dictionary<string, object> dicParams)
        {
            using (SQLiteConnection connection = new SQLiteConnection(m_strConnectString))
            {
                using (SQLiteCommand command = new SQLiteCommand(strSql, connection))
                {
                    if (dicParams != null && dicParams.Count > 0)
                    {
                        command.Parameters.Clear();
                        foreach (string parameterName in dicParams.Keys)
                        {
                            command.Parameters.AddWithValue(parameterName, dicParams[parameterName]);
                        }
                    }
                    SQLiteDataAdapter adapter = new SQLiteDataAdapter(command);
                    DataTable data = new DataTable();
                    lock (ObjLock)
                    {
                        adapter.Fill(data);
                    }
                    return data;
                }
            }
        }

        public DataSet ExcuteDataSet(string strSql)
        {
            DataSet ds = new DataSet("MyDataSet");
            using (SQLiteConnection connection = new SQLiteConnection(m_strConnectString))
            {
                using (SQLiteCommand command = new SQLiteCommand(strSql, connection))
                {
                    SQLiteDataAdapter adapter = new SQLiteDataAdapter(command);
                    lock (ObjLock)
                    {
                        adapter.Fill(ds);
                    }
                    return ds;
                }
            }
        }

        /// <summary> 
        /// 执行一个查询语句,返回查询结果的第一行第一列 
        /// </summary> 
        /// <param name="strSql">要执行的查询语句</param> 
        /// <returns>返回第一行第一列的值</returns> 
        public object ExecuteScalar(string strSql)
        {
            try
            {
                using (SQLiteConnection connection = new SQLiteConnection(m_strConnectString))
                {
                    connection.Open();
                    lock (ObjLock)
                    {
                        using (SQLiteCommand command = new SQLiteCommand(strSql, connection))
                        {
                            return command.ExecuteScalar();
                        }
                    }
                }
            }
            catch
            {
                throw;
            }
        }

        public int ExecuteScalarInt(string strSql)
        {
            object oRes = ExecuteScalar(strSql);
            return oRes == null ? 0 : Convert.ToInt32(oRes);
        }

        /// <summary> 
        /// 查询数据库中的所有数据类型信息 
        /// </summary> 
        /// <returns>返回数据表</returns> 
        public DataTable GetSchema()
        {
            using (SQLiteConnection connection = new SQLiteConnection(m_strConnectString))
            {
                connection.Open();
                DataTable data = connection.GetSchema("TABLES");
                connection.Close();
                return data;
            }
        }

        public bool DatabaseBetter()
        {
            try
            {
                lock (ObjLock)
                {
                    using (SQLiteConnection connection = new SQLiteConnection(m_strConnectString))
                    {
                        connection.Open();
                        using (SQLiteCommand command = new SQLiteCommand(connection))
                        {
                            command.CommandText = "VACUUM";
                            command.ExecuteNonQuery();
                        }
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                Context.ShowError("使用[VACUUM]命令优化数据库异常 ,详情:" + ex.Message);
                return false;
            }
        }
    }
}

四、新建用于操作数据库的静态类Env,Env.cs源程序

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data;
using System.IO;

namespace DeviceStatusDemo
{
    /// <summary>
    /// 应用程序级别的单例类
    /// </summary>
    public static class Env
    {
        static Env()
        {
            //增加sqlite数据库操作对象
            string strSqliteConnStr = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "deviceStatusDemo.db");
            SqliteDb = new SqliteDbHelper(strSqliteConnStr);
        }

        /// <summary>
        /// Sqlite数据库操作类对象
        /// </summary>
        public static SqliteDbHelper SqliteDb { get; set; }

        /// <summary>
        /// 创建数据库
        /// </summary>
        public static void EnsureDataBaseTables()
        {
            string strFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "deviceStatusDemo.db");
            if (!File.Exists(strFile))
            {
                System.Data.SQLite.SQLiteConnection.CreateFile(strFile);
            }

            string strSql = @"
--创建设备状态记录表
CREATE TABLE IF NOT EXISTS
Hans_DeviceStatus
(
    Id  INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
    RecordDate TEXT,
    RecordShift TEXT,
    DeviceStatus TEXT,
    DeviceStatusCode INTEGER,
    BeginTime TEXT,
    EndTime TEXT,
    Duration TEXT,
    DevicePosition TEXT,
    DeviceStatusMessage TEXT
);";
            SqliteDb.ExecuteNonQueryByDict(strSql, null);
        }
    }
}

五、关键操作设备状态改变的类DeviceStatusUtil.DeviceStatusUtil.cs源程序如下

using System;
using System.Collections.Generic;
using System.Data.SQLite;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DeviceStatusDemo
{
    /// <summary>
    /// 设备状态改变处理
    /// </summary>
    public class DeviceStatusUtil
    {
        /// <summary>
        /// 触发设备状态改变事件
        /// 第一个参数:当前设备状态
        /// 第二个参数:上次的设备状态
        /// 第三个参数:班次
        /// </summary>
        public static event Action<short, short, string> EventDeviceStatusChanged;
        /// <summary>
        /// 比较设备状态是否已改变
        /// </summary>
        /// <param name="buffer">当前设备状态</param>
        /// <param name="bufferLast">上次的设备状态</param>
        /// <returns></returns>
        public static bool CompareStatusChanged(short buffer, short bufferLast)
        {
            DateTime dtNow = DateTime.Now;
            string recordShift = GetShiftNormal(dtNow);
            //是否已改变
            if (bufferLast != -1 && buffer != bufferLast)
            {
                //触发设备状态改变事件
                EventDeviceStatusChanged?.Invoke(buffer, bufferLast, recordShift);
                return true;
            }
            return false;
        }

        /// <summary>
        /// 获得正常情况下的班次
        /// 【8点~20点是白班】
        /// </summary>
        /// <returns></returns>
        public static string GetShiftNormal(DateTime dtNow)
        {
            DateTime dtFrom = new DateTime(dtNow.Year, dtNow.Month, dtNow.Day, 8, 0, 0);
            DateTime dtTo = new DateTime(dtNow.Year, dtNow.Month, dtNow.Day, 20, 0, 0);
            //8点~20点之间为白班
            if (dtNow >= dtFrom && dtNow < dtTo)
            {
                return "白班";
            }
            return "夜班";
        }

        /// <summary>
        /// 获取上一次设备状态的记录开始时间
        /// </summary>
        /// <returns></returns>
        public static DateTime GetLastRecordTime()
        {
            object objResult = Env.SqliteDb.ExecuteScalar("select BeginTime from Hans_DeviceStatus where Id in (select max(Id) from Hans_DeviceStatus)");
            if (objResult == null || string.IsNullOrWhiteSpace(objResult.ToString()))
            {
                return DateTime.Now;
            }
            return DateTime.Parse(objResult.ToString());
        }

        /// <summary>
        /// 获取最后一次的设备状态代码
        /// </summary>
        /// <returns></returns>
        public static short GetLastDeviceStatusCode()
        {
            object objResult = Env.SqliteDb.ExecuteScalar("select DeviceStatusCode from Hans_DeviceStatus where Id in (select max(Id) from Hans_DeviceStatus)");
            if (objResult == null || string.IsNullOrWhiteSpace(objResult.ToString()))
            {
                return -1;
            }
            return Convert.ToInt16(objResult);
        }

        /// <summary>
        /// 保存设备状态改变到数据库
        /// 【类似于工作流的A环节 送出到 B环节】
        /// 先更新上一条数据的结束时间为Now,持续时间,然后增加一条开始时间为Now,结束时间、持续时间为空的记录
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static int SaveDeviceStatus(DeviceStatusData data)
        {
            Dictionary<string, object> dict = new Dictionary<string, object>();
            dict.Add("RecordDate", data.RecordDate);
            dict.Add("RecordShift", data.RecordShift);
            dict.Add("DeviceStatus", data.DeviceStatus);
            dict.Add("DeviceStatusCode", data.DeviceStatusCode);
            dict.Add("BeginTime", data.BeginTime.ToString("yyyy-MM-dd HH:mm:ss"));
            dict.Add("EndTime", data.EndTime.ToString("yyyy-MM-dd HH:mm:ss"));
            dict.Add("Duration", data.Duration.ToString("N2"));
            dict.Add("DevicePosition", data.DevicePosition);
            dict.Add("DeviceStatusMessage", data.DeviceStatusMessage);
            SQLiteParameter[] parameters = new SQLiteParameter[dict.Count];
            for (int i = 0; i < dict.Count; i++)
            {
                KeyValuePair<string, object> keyValue = dict.ElementAt(i);
                parameters[i] = new SQLiteParameter(keyValue.Key, keyValue.Value);
            }
            string sql = @"
update Hans_DeviceStatus set EndTime=@EndTime,Duration=@Duration,DeviceStatusMessage=@DeviceStatusMessage where Id in (select max(Id) from Hans_DeviceStatus);
insert into Hans_DeviceStatus (RecordDate,RecordShift,DeviceStatus,DeviceStatusCode,BeginTime,EndTime,Duration,DevicePosition,DeviceStatusMessage) values (@RecordDate,@RecordShift,@DeviceStatus,@DeviceStatusCode,@BeginTime,'','',@DevicePosition,'')";
            int affectRow = Env.SqliteDb.ExecuteNonQuery(sql, parameters);
            return affectRow;
        }
    }
}

六、设备操作仿真类PlcOperateUtil,PlcOperateUtil.cs源程序

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DeviceStatusDemo
{
    /// <summary>
    /// PLC操作类
    /// 该类只是仿真,实际使用需要读写PLC的相关地址
    /// </summary>
    public class PlcOperateUtil
    {
        /// <summary>
        /// 读取PLC指定地址的值,
        /// 这里只是一个模拟器
        /// </summary>
        /// <param name="address"></param>
        /// <returns></returns>
        public static short ReadInt16(string address)
        {
            return (short)new Random().Next(1, 6);
        }
    }
}

七、窗体FormDeviceStatus的相关主要程序如下(忽略设计器自动生成的部分类代码):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DeviceStatusDemo
{
    public partial class FormDeviceStatus : Form
    {
        /// <summary>
        /// 是否在运行中
        /// </summary>
        public bool IsRunning { get; set; }
        /// <summary>
        /// 上一次的设备状态 
        /// </summary>
        static short bufferLastStatus = -1;
        public FormDeviceStatus()
        {
            InitializeComponent();
            Env.EnsureDataBaseTables();
            Context.EventErrorLog += Context_EventErrorLog;
            Context.EventInfoLog += Context_EventInfoLog;
        }

        private void Context_EventInfoLog(string message)
        {
            DisplayMessage(message);
        }

        private void Context_EventErrorLog(string message, Exception ex)
        {
            DisplayMessage($"{message}\n{(ex == null ? "" : ex.Message)}");
        }

        /// <summary>
        /// 设备状态更改事件
        /// </summary>
        /// <param name="currentDeviceStatus">当前设备状态</param>
        /// <param name="lastDeviceStatus">上次设备状态</param>
        private void DeviceStatusUtil_EventDeviceStatusChanged(short currentDeviceStatus, short lastDeviceStatus, string recordShift)
        {
            //当前设备状态描述、上次设备状态描述
            string currentStatusDesc = typeof(DeviceStatus).GetEnumDescription(currentDeviceStatus);
            string lastStatusDesc = typeof(DeviceStatus).GetEnumDescription(lastDeviceStatus);
            DateTime dtLastTime = DeviceStatusUtil.GetLastRecordTime();
            DateTime dtNow = DateTime.Now;
            DeviceStatusData data = new DeviceStatusData();
            data.RecordDate = dtNow.ToString("yyyy-MM-dd");
            data.RecordShift = recordShift;
            data.DeviceStatus = currentStatusDesc;
            data.DeviceStatusCode = currentDeviceStatus;
            data.BeginTime = dtNow;//当前开始时间
            data.EndTime = dtNow;//上一次的结束时间
            data.Duration = dtNow.Subtract(dtLastTime).TotalSeconds;
            data.DevicePosition = "XX焊接工作台";
            data.DeviceStatusMessage = $"设备状态【{lastStatusDesc}】持续了【{data.Duration.ToString("N2")}】秒.设备状态已由【{lastDeviceStatus}-{lastStatusDesc}】切换到【{currentDeviceStatus}-{currentStatusDesc}】";
            Context.ShowInfo(data.DeviceStatusMessage);
            DeviceStatusUtil.SaveDeviceStatus(data);
        }

        /// <summary>
        /// 启用监控设备状态
        /// </summary>
        private void StartMonitor()
        {
            //从数据库读取最后一次的设备状态代码
            bufferLastStatus = DeviceStatusUtil.GetLastDeviceStatusCode();
            //绑定设备状态更改事件
            DeviceStatusUtil.EventDeviceStatusChanged -= DeviceStatusUtil_EventDeviceStatusChanged;
            DeviceStatusUtil.EventDeviceStatusChanged += DeviceStatusUtil_EventDeviceStatusChanged;
            IsRunning = true;
            Task.Factory.StartNew(() =>
            {
                while (IsRunning)
                {
                    try
                    {
                        #region 设备状态保存日志
                        //读取设备状态
                        short currentDeviceStatus = PlcOperateUtil.ReadInt16("DB500.10");
                        RefreshDeviceStatus(currentDeviceStatus);
                        bool isStatisticFlag = DeviceStatusUtil.CompareStatusChanged(currentDeviceStatus, bufferLastStatus);
                        if (isStatisticFlag)
                        {
                            if (bufferLastStatus != -1 && bufferLastStatus != currentDeviceStatus)
                            {
                                Context.ShowInfo($"设备状态已变更,由【{bufferLastStatus}】转变为【{currentDeviceStatus}】");
                            }
                        }
                        bufferLastStatus = currentDeviceStatus;
                        #endregion
                    }
                    catch (Exception ex)
                    {
                        Context.ShowError("与PLC交互出现异常," + ex.Message, null);
                        break;
                    }
                    finally
                    {
                        Thread.Sleep(2000);
                    }
                }
            });
        }

        /// <summary>
        /// 停止监控
        /// </summary>
        public void StopMonitor()
        {
            IsRunning = false;
            //解除绑定设备状态更改事件 
            DeviceStatusUtil.EventDeviceStatusChanged -= DeviceStatusUtil_EventDeviceStatusChanged;
        }

        /// <summary>
        /// 显示富文本框的消息
        /// </summary>
        /// <param name="message"></param>
        private void DisplayMessage(string message)
        {
            this.BeginInvoke(new Action(() =>
            {
                if (rtxtDisplay.TextLength >= 10240)
                {
                    rtxtDisplay.Clear();
                }
                rtxtDisplay.AppendText($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} --> {message}\n");
                rtxtDisplay.ScrollToCaret();
            }));
        }

        /// <summary>
        /// 刷新设备状态
        /// </summary>
        /// <param name="deviceStatusDesc"></param>
        /// <param name="color"></param>
        private void RefreshDeviceStatus(short currentDeviceStatus)
        {
            string currentStatusDesc = typeof(DeviceStatus).GetEnumDescription(currentDeviceStatus);
            Color color = Color.Green;
            switch (currentDeviceStatus)
            {
                case 1:
                case 3:
                    color = Color.Green;
                    break;
                case 2:
                    color = Color.Yellow;
                    break;
                default:
                    color = Color.Red;
                    break;
            }
            this.BeginInvoke(new Action(() =>
            {
                lblStatus.Text = currentStatusDesc;
                lblStatus.BackColor = color;
            }));
        }

        private void FormDeviceStatus_Load(object sender, EventArgs e)
        {
            btnStartMonitor.Enabled = true;
            btnStopMonitor.Enabled = false;
        }

        private void btnStartMonitor_Click(object sender, EventArgs e)
        {
            btnStartMonitor.Enabled = false;
            btnStopMonitor.Enabled = true;
            Context.ShowInfo("启动监控设备状态...");
            StartMonitor();
        }

        private void btnStopMonitor_Click(object sender, EventArgs e)
        {
            btnStartMonitor.Enabled = true;
            btnStopMonitor.Enabled = false;
            Context.ShowInfo("停止监控设备状态...");
            StopMonitor();
        }
    }
}

八、仿真程序运行如图:

 

猜你喜欢

转载自blog.csdn.net/ylq1045/article/details/119483162