You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

781 lines
24 KiB
C#

1 month ago
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Threading;
using Mesnac.Equips.BaseInfo;
namespace Mesnac.Equips
{
#region 设备信息类
/// <summary>
/// 设备信息
/// </summary>
public abstract class BaseEquip
{
private readonly string BASE_EQUIP_CLOCKTYPE = System.Configuration.ConfigurationManager.AppSettings["BASE_EQUIP_CLOCKTYPE"]; //设备时钟类型用于决定使用Thread、ThreadPool还是Timer
#region 辅助类型
/// <summary>
/// 线程状态
/// </summary>
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<string, Group>();
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 属性定义
/// <summary>
/// 设备名称
/// </summary>
[Caption("")]
public string Name { get; set; }
/// <summary>
/// 项目名称
/// </summary>
public string Project { get; set; }
/// <summary>
/// 设备主信息
/// </summary>
public Main Main { get; set; }
/// <summary>
/// 设备数据块信息
/// </summary>
public Dictionary<string, Group> Group { get; set; }
/// <summary>
/// 设备状态
/// </summary>
public bool State { get; protected set; }
/// <summary>
/// 是否最小读取频率的设备
/// </summary>
public bool IsMinReadHZ { get; set; }
#endregion
#region 接口方法、事件定义
/// <summary>
/// 打开设备
/// </summary>
/// <returns></returns>
public abstract bool Open();
/// <summary>
/// 读取信息
/// </summary>
/// <param name="block">数据块</param>
/// <param name="start">起始地址</param>
/// <param name="len">长度</param>
/// <param name="buff">读取返回信息</param>
/// <returns></returns>
public abstract bool Read(string block, int start, int len, out object[] buff);
/// <summary>
/// 写入信息
/// </summary>
/// <param name="block">数据块</param>
/// <param name="start">起始地址</param>
/// <param name="buff">长度</param>
/// <returns></returns>
public abstract bool Write(int block, int start, object[] buff);
/// <summary>
/// 关闭设备
/// </summary>
public abstract void Close();
/// <summary>
/// 读取信息委托
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public delegate void ReadDataHandler(object sender, ReadEventArgs e);
/// <summary>
/// 读取信息事件
/// </summary>
public event ReadDataHandler EquipReadData;
/// <summary>
/// 异常委托
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public delegate void ExceptHandler(object sender, Exception e);
/// <summary>
/// 异常事件
/// </summary>
public event ExceptHandler OnExcept;
#endregion
#region 事件参数初始化
/// <summary>
/// 初始化读取信息参数
/// </summary>
private void IniReadEventArgs()
{
try
{
Dictionary<string, object> 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);
}
}
/// <summary>
/// 刷新事件参数值
/// </summary>
/// <param name="d"></param>
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);
}
/// <summary>
/// 读取信息数据更新
/// </summary>
/// <param name="group"></param>
/// <param name="buff"></param>
private int FormatData(Group group, object[] buff)
{
int Result = 0;
IniReadEventArgs();
if (buff == null)
{
return Result;
}
try
{
Dictionary<string, object> 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;
}
/// <summary>
/// 异常时调用
/// </summary>
/// <param name="ex"></param>
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;
}
/// <summary>
/// 数据读取
/// </summary>
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 设备启动、停止方法定义
/// <summary>
/// 线程状态
/// </summary>
private threadState threadstate = threadState.none;
/// <summary>
/// 线程启动
/// </summary>
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));
}
}
/// <summary>
/// 线程结束
/// </summary>
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;
}
}
}
/// <summary>
/// 修改设备
/// </summary>
/// <param name="readHz"></param>
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);
}
}
/// <summary>
/// 线程睡眠,即延迟
/// </summary>
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;
}
/// <summary>
/// 线程运行处理业务
/// </summary>
public void OnReadTimerTick()
{
while (true)
{
if (threadstate != threadState.runing)
{
RunOnExcept(new Exception("线程停止"));
threadstate = threadState.none;
return;
}
try
{
Read();
}
catch (Exception ex)
{
RunOnExcept(ex);
}
Delay();
}
}
/// <summary>
/// 线程运行处理业务
/// </summary>
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 析构方法
/// <summary>
/// 析构方法
/// </summary>
~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 数据读取事件参数类
/// <summary>
/// 数据读取事件参数
/// </summary>
public class ReadEventArgs
{
public ReadEventArgs()
{
this.Data = new Dictionary<string, object>();
}
/// <summary>
/// 读取数据信息
/// </summary>
public Dictionary<string, object> Data { get; set; }
}
#endregion
}