using System; using System.Collections.Generic; using System.Text; using System.Data; using System.Threading; using Mesnac.Equips.BaseInfo; namespace Mesnac.Equips { #region 设备信息类 /// /// 设备信息 /// public abstract class BaseEquip { private readonly string BASE_EQUIP_CLOCKTYPE = System.Configuration.ConfigurationManager.AppSettings["BASE_EQUIP_CLOCKTYPE"]; //设备时钟类型,用于决定使用Thread、ThreadPool还是Timer #region 辅助类型 /// /// 线程状态 /// private enum threadState { none = 0, runing = 1, stoping = 2, } #endregion #region 字段定义 private System.Threading.Thread _thisThread = null; //读取设备线程对象,由App.Config中的BaseEquipType的值决定是采用Timer还是Thread,默认采用Thread private System.Timers.Timer _thisTimer = null; //读取设备时钟对象,由App.Config中的BaseEquipType的值决定是采用Timer还是Thread #endregion #region 构造方法 public BaseEquip() { this.Name = string.Empty; this.Project = string.Empty; this.Main = new Main(); this.Group = new Dictionary(); this.State = false; if (!String.IsNullOrEmpty(BASE_EQUIP_CLOCKTYPE) && BASE_EQUIP_CLOCKTYPE == "Timer") { this._thisTimer = new System.Timers.Timer(); this._thisTimer.Elapsed += delegate(object sender, System.Timers.ElapsedEventArgs e) { try { Read(); } catch (Exception ex) { RunOnExcept(ex); } }; } } #endregion #region 属性定义 /// /// 设备名称 /// [Caption("")] public string Name { get; set; } /// /// 项目名称 /// public string Project { get; set; } /// /// 设备主信息 /// public Main Main { get; set; } /// /// 设备数据块信息 /// public Dictionary Group { get; set; } /// /// 设备状态 /// public bool State { get; protected set; } /// /// 是否最小读取频率的设备 /// public bool IsMinReadHZ { get; set; } #endregion #region 接口方法、事件定义 /// /// 打开设备 /// /// public abstract bool Open(); /// /// 读取信息 /// /// 数据块 /// 起始地址 /// 长度 /// 读取返回信息 /// public abstract bool Read(string block, int start, int len, out object[] buff); /// /// 写入信息 /// /// 数据块 /// 起始地址 /// 长度 /// public abstract bool Write(int block, int start, object[] buff); /// /// 关闭设备 /// public abstract void Close(); /// /// 读取信息委托 /// /// /// public delegate void ReadDataHandler(object sender, ReadEventArgs e); /// /// 读取信息事件 /// public event ReadDataHandler EquipReadData; /// /// 异常委托 /// /// /// public delegate void ExceptHandler(object sender, Exception e); /// /// 异常事件 /// public event ExceptHandler OnExcept; #endregion #region 事件参数初始化 /// /// 初始化读取信息参数 /// private void IniReadEventArgs() { try { Dictionary data = Factory.Instance.readEventArgs.Data; if (data.Count == 0) { foreach (Group group in this.Group.Values) { foreach (Data d in group.Data.Values) { if (!data.ContainsKey(d.KeyName)) { data.Add(d.KeyName, 0); } } } } } catch (Exception ex) { RunOnExcept(ex); } } /// /// 刷新事件参数值 /// /// public void RefreshEventArgsValue(Data d) { if (Factory.Instance.readEventArgs.Data.ContainsKey(d.KeyName)) { Factory.Instance.readEventArgs.Data[d.KeyName] = d.Value; return; } Factory.Instance.readEventArgs.Data.Add(d.KeyName, d.Value); } #endregion #region 数据格式化方法 private string FormatMethod(Data fdata) { string Result = fdata.Method; string[] parameters = Mesnac.Maths.Factory.Instance.GetParameters(Mesnac.Maths.Factory.Instance.GetMethodParameter(fdata.Method)); foreach (string ss in parameters) { double d = 0; if (double.TryParse(ss, out d)) { continue; } bool isFind = false; object obj = null; Data data = null; if (Factory.Instance.readEventArgs.Data.TryGetValue(ss, out obj)) { isFind = true; } if (!isFind) { string key = fdata.Group.Equip.Name + "." + ss; if (Factory.Instance.readEventArgs.Data.TryGetValue(key, out obj)) { isFind = true; } } if (!isFind) { string key = fdata.Group.Equip.Name + "." + fdata.Group.Name + "." + ss; if (Factory.Instance.readEventArgs.Data.TryGetValue(key, out obj)) { isFind = true; } } if (!isFind) { foreach (BaseEquip equip in Factory.Instance.AllEquips.Values) { foreach (Group group in equip.Group.Values) { isFind = group.Data.TryGetValue(ss, out data); if (isFind) { break; } } if (isFind) { break; } } } if (isFind && data != null) { obj = data.Value; } if (isFind && obj != null) { Result = Result.Replace(ss, obj.ToString()); } } return Result; } #endregion #region 辅助方法 private object[] GetRowValue(string key, object[] buff) { foreach (DataRow dr in buff) { if (dr["ssKey"].ToString().Equals(key)) { return new object[] { dr["ssValue"] }; } } return null; } private object[] GetDataValue(Data d, object[] buff) { object[] Result = new object[d.Len]; for (int i = 0; i < d.Len; i++) { int index = d.Start + i; Result[i] = buff[index]; } return Result; } private bool BuffEqual(object[] obj1, object[] obj2) { if (obj1 == null || obj2 == null) { if (obj1 == null && obj2 == null) { return true; } if (obj1 != null || obj2 != null) { return false; } } if (obj1.Length != obj2.Length) { return false; } for (int i = 0; i < obj1.Length; i++) { if (obj1[i] == null || obj2[i] == null) { if (obj1[i] != null || obj2[i] != null) { return false; } continue; } if (obj1[i].GetType() != obj2[i].GetType()) { return false; } if (!obj1[i].Equals(obj2[i])) { return false; } } return true; } public object GetValue(Data fdata, object[] buff) { return Mesnac.Maths.Factory.Instance.Execute(FormatMethod(fdata), buff); } /// /// 读取信息数据更新 /// /// /// private int FormatData(Group group, object[] buff) { int Result = 0; IniReadEventArgs(); if (buff == null) { return Result; } try { Dictionary data = Factory.Instance.readEventArgs.Data; foreach (Data d in group.Data.Values) { object[] ss = null; if (buff[0] is DataRow) { string key = d.Name; ss = GetRowValue(key, buff); } else { ss = GetDataValue(d, buff); } d.ReadTime = DateTime.Now; if (BuffEqual(d.LastBeforeMathValue, ss)) { if(d.IsSave) { data.Remove(d.KeyName); } continue; } d.LastBeforeMathValue = ss; Result++; if (ss == null) { d.Value = null; } else { d.Value = GetValue(d, ss); } } } catch (Exception ex) { RunOnExcept(ex); } return Result; } private int FormatData(Data data, object[] buff) { int Result = 0; if (buff == null) { return Result; } try { object[] ss = null; if (buff[0] is DataRow) { string key = data.Name; ss = GetRowValue(key, buff); } else { ss = GetDataValue(data, buff); } data.ReadTime = DateTime.Now; if (BuffEqual(data.LastBeforeMathValue, ss)) { return 1; } data.LastBeforeMathValue = ss; Result++; if (ss == null) { data.Value = null; } else { data.Value = GetValue(data, ss); } } catch (Exception ex) { RunOnExcept(ex); } return Result; } /// /// 异常时调用 /// /// private void RunOnExcept(Exception ex) { if (OnExcept != null) { OnExcept(this, ex); } } #endregion #region 数据读取 public object ReadData(Data data) { Group group = data.Group; if (group.Len > 0 && (group.Access == System.IO.FileAccess.Read || group.Access == System.IO.FileAccess.ReadWrite)) { object[] buff = new object[group.Len]; if (Read(group.Block, group.Start, group.Len, out buff)) { group.Value = buff; FormatData(data, buff); } } return data.Value; } /// /// 数据读取 /// private void Read(bool isReadAll) { try { int iReadGroupCount = 0; //ICSharpCode.Core.LoggingService.Debug("开始设备读取"+DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")); foreach (Group group in this.Group.Values) { if (group.Len > 0 && (group.IsAutoRead || isReadAll) && (group.Access == System.IO.FileAccess.Read || group.Access == System.IO.FileAccess.ReadWrite)) { object[] buff = new object[group.Len]; if (Read(group.Block, group.Start, group.Len, out buff)) { group.Value = buff; if (FormatData(group, buff) > 0) { iReadGroupCount++; } } else { Console.Write(DateTime.Now +":"+ group.Name + group.Block + group.Name + "读取失败\r\n"); } } } //ICSharpCode.Core.LoggingService.Debug("设备读取完成" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")); } catch (Exception ex) { RunOnExcept(ex); } finally { #region 调用事件 if (EquipReadData != null) { try { EquipReadData(this, Factory.Instance.readEventArgs); } catch (Exception ex) { ICSharpCode.Core.LoggingService.Error("触发设备读取事件失败:" + ex.Message, ex); } } #endregion } } public void Read() { Read(false); } public void ReadAll() { Read(true); } private object getRowValue(DataTable dt, string key) { object Result = null; foreach (DataRow row in dt.Rows) { if (row["ssKey"].ToString() == key) { return row["ssValue"]; } } return Result; } #endregion #region 设备启动、停止方法定义 /// /// 线程状态 /// private threadState threadstate = threadState.none; /// /// 线程启动 /// public void Start() { if (!String.IsNullOrEmpty(BASE_EQUIP_CLOCKTYPE) && BASE_EQUIP_CLOCKTYPE == "Timer") { //定时器启动 threadstate = threadState.runing; if (this.IsMinReadHZ == false) { try { Read(); //提前执行一次设备读取 } catch (Exception ex) { RunOnExcept(ex); } } this._thisTimer.Interval = this.Main.ReadHz; this._thisTimer.Start(); } else if (!String.IsNullOrEmpty(BASE_EQUIP_CLOCKTYPE) && BASE_EQUIP_CLOCKTYPE == "Thread") { //线程启动 if (threadstate == threadState.runing) { return; } for (int i = 0; i < 100; i++) { if (threadstate == threadState.none) { break; } Thread.Sleep(200); } threadstate = threadState.runing; //ThreadPool.QueueUserWorkItem(new WaitCallback(OnReadTimerTick)); try { Read(); } catch (Exception ex) { RunOnExcept(ex); } this._thisThread = new Thread(new ThreadStart(OnReadTimerTick)); this._thisThread.Start(); } else { if (threadstate == threadState.runing) { return; } for (int i = 0; i < 100; i++) { if (threadstate == threadState.none) { break; } Thread.Sleep(200); } threadstate = threadState.runing; ThreadPool.QueueUserWorkItem(new WaitCallback(OnReadTimerTick)); } } /// /// 线程结束 /// public void Stop() { if (threadstate == threadState.runing) { threadstate = threadState.stoping; } if (!String.IsNullOrEmpty(BASE_EQUIP_CLOCKTYPE) && BASE_EQUIP_CLOCKTYPE == "Timer") { try { this._thisTimer.Stop(); } catch (Exception ex) { ICSharpCode.Core.LoggingService.Error(String.Format("设备{0}停止失败:{1}", this.Name, ex.Message)); } } else if (!String.IsNullOrEmpty(BASE_EQUIP_CLOCKTYPE) && BASE_EQUIP_CLOCKTYPE == "Thread") { try { if (this._thisThread != null && this._thisThread.ThreadState == ThreadState.Running) { this._thisThread.Abort(); this._thisThread = null; } else if (this._thisThread != null && this._thisThread.ThreadState == ThreadState.Suspended) { this._thisThread.Resume(); this._thisThread.Abort(); this._thisThread = null; } } catch (Exception ex) { ICSharpCode.Core.LoggingService.Error(String.Format("设备{0}停止失败:{1}", this.Name, ex.Message)); } } else { if (threadstate == threadState.runing) { threadstate = threadState.stoping; } } } /// /// 修改设备 /// /// public void SetMainReadHZ(int readHz) { if (!String.IsNullOrEmpty(BASE_EQUIP_CLOCKTYPE) && BASE_EQUIP_CLOCKTYPE == "Timer") { this._thisTimer.Interval = readHz; } this.Main.ReadHz = readHz; try { Read(); } catch (Exception ex) { RunOnExcept(ex); } } /// /// 线程睡眠,即延迟 /// private void Delay() { DateTime now = DateTime.Now; while (true) { if (this.Main.ReadHz != int.MaxValue) { break; } Thread.Sleep(200); } Thread.Sleep(this.Main.ReadHz); return; } /// /// 线程运行处理业务 /// public void OnReadTimerTick() { while (true) { if (threadstate != threadState.runing) { RunOnExcept(new Exception("线程停止")); threadstate = threadState.none; return; } try { Read(); } catch (Exception ex) { RunOnExcept(ex); } Delay(); } } /// /// 线程运行处理业务 /// public void OnReadTimerTick(object sender) { while (true) { if (threadstate != threadState.runing) { RunOnExcept(new Exception("线程停止")); threadstate = threadState.none; return; } try { Read(); } catch (Exception ex) { RunOnExcept(ex); } Delay(); } } #endregion #region 析构方法 /// /// 析构方法 /// ~BaseEquip() { try { this.Stop(); this.Close(); System.GC.Collect(); } catch (Exception ex) { ICSharpCode.Core.LoggingService.Error(String.Format("销毁设备{0}错误:{1}", this.Name, ex.Message)); } } #endregion } #endregion #region 数据读取事件参数类 /// /// 数据读取事件参数 /// public class ReadEventArgs { public ReadEventArgs() { this.Data = new Dictionary(); } /// /// 读取数据信息 /// public Dictionary Data { get; set; } } #endregion }