using Bro.Common.Helper;
|
using Bro.Common.Model;
|
using Bro.Common.Model.Interface;
|
using System;
|
using System.Collections.Generic;
|
using System.ComponentModel;
|
using System.Drawing.Design;
|
using System.Linq;
|
using System.Text;
|
using System.Threading;
|
using System.Threading.Tasks;
|
using static Bro.Common.Helper.EnumHelper;
|
|
namespace Bro.Common.Base
|
{
|
public abstract class PLCBase : DeviceBase, IMonitor
|
{
|
public PLCInitialConfigBase PLCIConfig
|
{
|
get => InitialConfig as PLCInitialConfigBase;
|
}
|
|
public abstract void Write(PLCOperationConfigBase config);
|
|
public abstract void Read(PLCOperationConfigBase config);
|
|
public abstract void ReadItem(PLC_ITEM item);
|
|
public abstract void WriteItem(PLC_ITEM item, bool waitForReply = true);
|
|
public abstract void WriteSingleAddress(int address, int writeValue, bool waitForReply = true);
|
|
#region 委托
|
public Action<PLC_ITEM> OnPLCDataChanged;
|
#endregion
|
|
#region IMonitor
|
public event OnMonitorInvokeDelegate OnMonitorInvoke;
|
public event OnMonitorAlarmDelegate OnMonitorAlarm;
|
|
protected List<int> oldValues = new List<int>();
|
|
public abstract List<int> GetMonitorValues(int startAddress, int length);
|
|
public virtual void Monitor()
|
{
|
if (PLCIConfig != null
|
&& PLCIConfig.EventStartAddress > 0
|
&& PLCIConfig.EventLength > 0
|
&& PLCIConfig.ScanInterval > 0)
|
{
|
while (CurrentState != EnumHelper.DeviceState.DSClose && CurrentState != EnumHelper.DeviceState.DSExcept)
|
{
|
try
|
{
|
List<int> newValues = GetMonitorValues(PLCIConfig.EventStartAddress, PLCIConfig.EventLength);
|
|
if (newValues == null || newValues.Count == 0)
|
continue;
|
|
if (oldValues.Count == newValues.Count)
|
{
|
var tempNew = new List<int>(newValues);
|
var tempOld = new List<int>(oldValues);
|
MonitorCheckAndInvoke(tempNew, tempOld);
|
}
|
oldValues = new List<int>(newValues);
|
|
Thread.Sleep(PLCIConfig.ScanInterval);
|
}
|
catch (Exception ex)
|
{
|
OnLog?.Invoke(DateTime.Now, this, $"{Name}监听异常:{ex.GetExceptionMessage()}");
|
}
|
}
|
}
|
}
|
|
protected virtual void MonitorCheckAndInvoke(List<int> tempNew, List<int> tempOld)
|
{
|
#region PLC警报信息
|
PLCIConfig.WarningSetCollection.ForEach(w =>
|
{
|
if (w.WarningIndex_Word < 0 || w.WarningIndex_Word >= tempNew.Count)
|
return;
|
|
if (w.WarningIndex_Bit < 0 || w.WarningIndex_Bit > 16)
|
return;
|
|
bool isOn = ((tempNew[w.WarningIndex_Word] >> w.WarningIndex_Bit) & 1) == 1;
|
|
if (w.CurrentStatus != isOn)
|
{
|
w.CurrentStatus = isOn;
|
OnMonitorAlarm?.BeginInvoke(DateTime.Now, this, w, null, null);
|
}
|
});
|
#endregion
|
|
PLCIConfig.MonitorSetCollection.ForEach(m =>
|
{
|
if (m.TriggerIndex < 0 || m.TriggerIndex >= tempNew.Count)
|
{
|
return;
|
}
|
|
int newValue = tempNew[m.TriggerIndex];
|
int oldValue = tempOld[m.TriggerIndex];
|
|
if (newValue != oldValue)
|
{
|
if (m.TriggerValue == -999 || newValue == m.TriggerValue)
|
{
|
if (m.OpConfig == null)
|
{
|
m.OpConfig = new OperationConfigBase();
|
}
|
|
m.OpConfig.InputPara = m.InputDataIndex.ConvertAll(index =>
|
{
|
return tempNew[index];
|
}).ToList();
|
|
OnMonitorInvoke?.BeginInvoke(DateTime.Now, this, m, OnMethodInvoked, m);
|
}
|
}
|
});
|
}
|
|
protected virtual void OnMethodInvoked(IAsyncResult ar)
|
{
|
MonitorSet monitorSet = ar.AsyncState as MonitorSet;
|
|
ProcessResponse resValues = monitorSet.Response;
|
|
if (resValues.ResultValue == (int)PLCReplyValue.IGNORE)
|
{
|
return;
|
}
|
|
if (monitorSet.ReplyDataAddress != -1 && resValues.DataList.Count > 0)
|
{
|
PLC_ITEM item = new PLC_ITEM();
|
item.OP_TYPE = 2;
|
item.ITEM_LENGTH = resValues.DataList.Count;
|
item.ADDRESS = monitorSet.ReplyDataAddress.ToString();
|
item.ITEM_VALUE = String.Join(",", resValues.DataList);
|
this.WriteItem(item, false);
|
}
|
|
if (monitorSet.NoticeAddress != -1)
|
{
|
int repeatTime = 5;
|
|
//LogAsync(DateTime.Now, methodCode + "开始反馈", "");
|
do
|
{
|
try
|
{
|
this.WriteSingleAddress(monitorSet.NoticeAddress, resValues.ResultValue, false);
|
repeatTime = 0;
|
}
|
catch (Exception ex)
|
{
|
repeatTime--;
|
|
if (repeatTime <= 0)
|
{
|
new ProcessException("PLC反馈写入异常", ExceptionLevel.Info, ex);
|
}
|
}
|
} while (repeatTime > 0);
|
}
|
}
|
|
public virtual void ResetAlarm()
|
{
|
PLCIConfig.WarningSetCollection.ForEach(u => u.CurrentStatus = !u.TriggerValue);
|
}
|
#endregion
|
}
|
|
public abstract class PLCOperationConfigBase : OperationConfigBase
|
{
|
/// <summary>
|
/// 需要操作的PLC项
|
/// </summary>
|
public List<PLC_ITEM> Items { get; set; } = new List<PLC_ITEM>();
|
|
/// <summary>
|
/// 是否循环操作
|
/// </summary>
|
public bool IsCycle { get; set; } = false;
|
}
|
|
public class PLCDeviceConfigBase : DeviceConfigBase
|
{
|
}
|
|
public class PLCInitialConfigBase : InitialMonitorConfigBase
|
{
|
#region 地址设置
|
[Category("事件地址设置")]
|
[Description("事件开始地址,PLC的实际寄存器地址。十进制,不包含功能码。")]
|
public int EventStartAddress { get; set; } = 8000;
|
|
[Category("事件地址设置")]
|
[Description("事件地址长度,最大长度128")]
|
public int EventLength { get; set; } = 120;
|
|
[Category("事件地址设置")]
|
[Description("警报开始索引,从0开始")]
|
public int WarningStartIndex { get; set; } = 0;
|
|
[Category("事件地址设置")]
|
[Description("警报地址长度")]
|
public int WarningLength { get; set; } = 8;
|
#endregion
|
}
|
|
public class PLCInputConfigBase : InputConfigBase
|
{
|
}
|
}
|