318 lines
8.8 KiB
C#
318 lines
8.8 KiB
C#
using Newtonsoft.Json;
|
|||
|
|
using System;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using System.Diagnostics;
|
||
|
|
using System.Threading;
|
||
|
|
|
||
|
|
namespace JinYuan.Models
|
||
|
|
{
|
||
|
|
/// <summary>
|
||
|
|
/// 通信设备实体类
|
||
|
|
/// </summary>
|
||
|
|
public class Device
|
||
|
|
{
|
||
|
|
/// <summary>
|
||
|
|
/// IP地址
|
||
|
|
/// </summary>
|
||
|
|
public string IPAddress { get; set; }
|
||
|
|
/// <summary>
|
||
|
|
/// 端口
|
||
|
|
/// </summary>
|
||
|
|
public int Port { get; set; }
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// PLC类型
|
||
|
|
/// </summary>
|
||
|
|
public string PLCType { get; set; }
|
||
|
|
/// <summary>
|
||
|
|
/// 当前设备的连接状态
|
||
|
|
/// </summary>
|
||
|
|
|
||
|
|
public bool IsConnected { get; set; }
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 是否是首次连接
|
||
|
|
/// </summary>
|
||
|
|
|
||
|
|
public bool IsFirstConnect { get; set; } = true;
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 重连周期
|
||
|
|
/// </summary>
|
||
|
|
|
||
|
|
public int ReConnectTime { get; set; } = 2000;
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 休眠时间
|
||
|
|
/// </summary>
|
||
|
|
|
||
|
|
public int SleepTime { get; set; } = 10;
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 大小端
|
||
|
|
/// </summary>
|
||
|
|
[JsonIgnore]
|
||
|
|
public int DataFormat { get; set; } = 0;
|
||
|
|
/// <summary>
|
||
|
|
/// 出错次数
|
||
|
|
/// </summary>
|
||
|
|
public int ErrorTimes { get; set; }
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 容错次数
|
||
|
|
/// </summary>
|
||
|
|
public int AllowErrorTimes { get; set; } = 3;
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 多线程取消源标志位
|
||
|
|
/// </summary>
|
||
|
|
public CancellationTokenSource Cts { get; set; }
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 计时器
|
||
|
|
/// </summary>
|
||
|
|
|
||
|
|
public Stopwatch Stopwatch { get; set; }
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 所有归档变量的集合
|
||
|
|
/// </summary>
|
||
|
|
|
||
|
|
public List<Variable> StoreVarList { get; set; } = new List<Variable>();
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 按工位读取
|
||
|
|
/// </summary>
|
||
|
|
|
||
|
|
public List<Group> WorkVarList { get; set; } = new List<Group>();
|
||
|
|
/// <summary>
|
||
|
|
/// 通信组集合
|
||
|
|
/// </summary>
|
||
|
|
public List<Group> GroupList { get; set; } = new List<Group>();
|
||
|
|
/// <summary>
|
||
|
|
/// 所有变量的集合
|
||
|
|
/// </summary>
|
||
|
|
public List<Variable> VarList { get; set; } = new List<Variable>();
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 所有变量名称与值的集合
|
||
|
|
/// </summary>
|
||
|
|
public Dictionary<string, object> CurrentValue { get; set; } = new Dictionary<string, object>();
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 定义报警触发和消除事件
|
||
|
|
/// </summary>
|
||
|
|
public event Action<bool, Variable> AlarmTrigEvent;
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 变量初始化
|
||
|
|
/// </summary>
|
||
|
|
public void Init()
|
||
|
|
{
|
||
|
|
foreach (var gp in GroupList)
|
||
|
|
{
|
||
|
|
|
||
|
|
if (gp.IsTiggerRead)
|
||
|
|
{
|
||
|
|
WorkVarList.Add(gp);
|
||
|
|
}
|
||
|
|
foreach (var variable in gp.VarList)
|
||
|
|
{
|
||
|
|
if (!gp.IsTiggerRead)
|
||
|
|
{
|
||
|
|
VarList.Add(variable);
|
||
|
|
|
||
|
|
|
||
|
|
if (CurrentValue.ContainsKey(variable.VarName))
|
||
|
|
{
|
||
|
|
CurrentValue[variable.VarName] = "NA";
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
CurrentValue.Add(variable.VarName, "NA");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 索引器,通过键名获取到数据
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="key"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
[JsonIgnore]
|
||
|
|
public object this[string key]
|
||
|
|
{
|
||
|
|
get
|
||
|
|
{
|
||
|
|
if (CurrentValue.ContainsKey(key))
|
||
|
|
{
|
||
|
|
return CurrentValue[key];
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 实时更新
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="variable"></param>
|
||
|
|
public void Update(Variable variable)
|
||
|
|
{
|
||
|
|
//更新处理
|
||
|
|
if (CurrentValue.ContainsKey(variable.VarName))
|
||
|
|
{
|
||
|
|
CurrentValue[variable.VarName] = variable.VarValue;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
CurrentValue.Add(variable.VarName, variable.VarValue);
|
||
|
|
}
|
||
|
|
|
||
|
|
//报警处理
|
||
|
|
if (variable.HighAlarmEnable || variable.LowAlarmEnable)
|
||
|
|
{
|
||
|
|
float compareValue = 0.0f;
|
||
|
|
|
||
|
|
if (variable.DataType.ToLower() == "bool")
|
||
|
|
{
|
||
|
|
compareValue = Convert.ToBoolean(variable.VarValue) ? 1.0f : 0.0f;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
compareValue = Convert.ToSingle(variable.VarValue);
|
||
|
|
}
|
||
|
|
|
||
|
|
int compareResult = 0;
|
||
|
|
//高报警时,触发事件
|
||
|
|
if (variable.HighAlarmEnable)
|
||
|
|
{
|
||
|
|
compareResult = Compare(compareValue, variable.HighAlarmValue, variable.HighAlarmCacheValue, true);
|
||
|
|
|
||
|
|
if (compareResult != 0)
|
||
|
|
{
|
||
|
|
//通过事件做通知
|
||
|
|
|
||
|
|
OnAlarmAckEvent(variable, new AlarmEventArgs()
|
||
|
|
{
|
||
|
|
Name = variable.VarName,
|
||
|
|
CurrentValue = variable.VarValue.ToString(),
|
||
|
|
SetValue = variable.HighAlarmValue.ToString(),
|
||
|
|
AlarmNote = variable.HighAlarmNote,
|
||
|
|
IsTrigger = compareResult == 1
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
variable.HighAlarmCacheValue = compareValue;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
compareResult = Compare(compareValue, variable.LowAlarmValue, variable.LowAlarmCacheValue, false);
|
||
|
|
|
||
|
|
if (compareResult != 0)
|
||
|
|
{
|
||
|
|
//通过事件做通知
|
||
|
|
|
||
|
|
OnAlarmAckEvent(variable, new AlarmEventArgs()
|
||
|
|
{
|
||
|
|
Name = variable.VarName,
|
||
|
|
CurrentValue = variable.VarValue.ToString(),
|
||
|
|
SetValue = variable.LowAlarmValue.ToString(),
|
||
|
|
AlarmNote = variable.LowAlarmNote,
|
||
|
|
IsTrigger = compareResult == 1
|
||
|
|
});
|
||
|
|
|
||
|
|
}
|
||
|
|
variable.LowAlarmCacheValue = compareValue;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 报警触发的事件
|
||
|
|
/// </summary>
|
||
|
|
//public event AlarmTriggerEventDelegate AlarmTriggerEvent;
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 触发事件
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="sender"></param>
|
||
|
|
/// <param name="e"></param>
|
||
|
|
private void OnAlarmAckEvent(object sender, AlarmEventArgs e)
|
||
|
|
{
|
||
|
|
//AlarmTriggerEvent?.Invoke(sender, e);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 报警比较
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="current">当前值</param>
|
||
|
|
/// <param name="set">设置值</param>
|
||
|
|
/// <param name="last">缓存值</param>
|
||
|
|
/// <param name="isPositive">上升沿还是下降沿</param>
|
||
|
|
/// <returns>比较结果,1表示触发,-1表示消除,0表示无变化</returns>
|
||
|
|
private int Compare(float current, float set, float last, bool isPositive)
|
||
|
|
{
|
||
|
|
if (isPositive)
|
||
|
|
{
|
||
|
|
if (current >= set && last < set)
|
||
|
|
{
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
if (current < set && last >= set)
|
||
|
|
{
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (current <= set && last > set)
|
||
|
|
{
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
if (current > set && last <= set)
|
||
|
|
{
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public class AlarmEventArgs : EventArgs
|
||
|
|
{
|
||
|
|
/// <summary>
|
||
|
|
/// 变量名称
|
||
|
|
/// </summary>
|
||
|
|
public string Name { get; set; }
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 当前值
|
||
|
|
/// </summary>
|
||
|
|
public string CurrentValue { get; set; }
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 报警说明
|
||
|
|
/// </summary>
|
||
|
|
public string AlarmNote { get; set; }
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 报警设定值
|
||
|
|
/// </summary>
|
||
|
|
public string SetValue { get; set; }
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 是否为触发
|
||
|
|
/// </summary>
|
||
|
|
public bool IsTrigger { get; set; }
|
||
|
|
}
|
||
|
|
}
|