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#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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
}