using Bro.Common.Base; using Bro.Common.Helper; using Bro.Common.Interface; using Bro.Common.Model; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO.Ports; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using static Bro.Common.Helper.EnumHelper; namespace Bro.Device.DAMModule { [Device("DAMModule", "DAM模块", EnumHelper.DeviceAttributeType.Device)] public class DAMDriver : DeviceBase, IMonitor { #region IMonitor public List InputIOs { get; set; } = new List(); public List OutputIOs { get; set; } = new List(); public event Action OnMonitorInvoke; public event Action OnMonitorAlarm; public void Monitor() { while (CurrentState == EnumHelper.DeviceState.DSOpen) { if (!IConfig.IsEnableMonitor) return; _writeHandle.WaitOne(); lock (_writeLock) { sp.Write(byteReadAllInput, 0, byteReadAllInput.Length); Thread.Sleep(IConfig.ReadWaitTime); byte[] recBuffer = new byte[2048]; int recNum = sp.Read(recBuffer, 0, recBuffer.Length); if (recNum > 0) { var data = AnalysisRcv(recBuffer.Take(recNum).ToArray()).ToList(); List temp = new List(); data.ForEach(d => { for (int i = 0; i < 8; i++) { temp.Add((d >> i) & 1); } }); if (temp.Count() == InputIOs.Count()) { MonitorCheckAndInvoke(temp, new List(InputIOs)); } InputIOs = new List(temp); } if (IConfig.IsMonitorOutput) { sp.Write(byteReadAllOutput, 0, byteReadAllOutput.Length); Thread.Sleep(IConfig.ReadWaitTime); recBuffer = new byte[2048]; recNum = sp.Read(recBuffer, 0, recBuffer.Length); if (recNum > 0) { var data = AnalysisRcv(recBuffer.Take(recNum).ToArray()).ToList(); List temp = new List(); data.ForEach(d => { for (int i = 0; i < 8; i++) { temp.Add((d >> i) & 1); } }); OutputIOs = new List(temp); } } } if (IConfig.MonitorInterval > 0) Thread.Sleep(IConfig.MonitorInterval); } } private async void MonitorCheckAndInvoke(List tempNew, List tempOld) { await Task.Run(() => { Parallel.ForEach(IConfig.MonitorSetCollection, set => { MonitorSet monitorSet = set as MonitorSet; if (monitorSet.TriggerIndex < 0 || monitorSet.TriggerIndex >= tempNew.Count) { return; } int newValue = tempNew[monitorSet.TriggerIndex]; int oldValue = tempOld[monitorSet.TriggerIndex]; if (newValue != oldValue) { if (monitorSet.TriggerValue == -999 || newValue == monitorSet.TriggerValue) { if (monitorSet.OpConfig == null) { monitorSet.OpConfig = new OperationConfigBase(); } monitorSet.OpConfig.InputPara = monitorSet.InputDataIndex.ConvertAll(index => { return tempNew[index]; }).ToList(); OnMonitorInvoke?.BeginInvoke(DateTime.Now, monitorSet.InvokeDevice, this, monitorSet, OnMethodInvoked, monitorSet); } } }); }); } private void OnMethodInvoked(IAsyncResult ar) { MonitorSet monitorSet = ar.AsyncState as MonitorSet; ProcessResponse resValues = monitorSet.Response; if (resValues.ResultValue == (int)PLCReplyValue.IGNORE) { return; } Stopwatch sw = new Stopwatch(); sw.Start(); //if (monitorSet.ReplyDataAddress != -1 && resValues.DataList.Count > 0) //{ // PLCItem item = new PLCItem // { // ItemLength = resValues.DataList.Count, // Address = monitorSet.ReplyDataAddress.ToString(), // ItemValues = resValues.DataList.ConvertAll(s => int.Parse(s.ToString())).ToList() // }; // WriteItem(item, false); //} if (monitorSet.NoticeAddress != -1) { int repeatTime = 5; do { try { WriteOutput(monitorSet.NoticeAddress, resValues.ResultValue == 1); repeatTime = 0; } catch (Exception ex) { repeatTime--; if (repeatTime <= 0) { new ProcessException($"{Name}反馈写入异常", ex, ExceptionLevel.Warning); } } } while (repeatTime > 0); } sw.Stop(); LogAsync(DateTime.Now, $"{Name}反馈完成,耗时{sw.ElapsedMilliseconds}ms", $"{resValues.GetDisplayText()}"); } private byte[] AnalysisRcv(byte[] src) { if (src.Length < 6) return null; if (src[0] != Convert.ToInt16(IConfig.UnitNum)) return null; switch (src[1]) { case 0x01: if (CMBRTU.CalculateCrc(src, src[2] + 5) == 0x00) { byte[] dst = new byte[src[2]]; for (int i = 0; i < src[2]; i++) dst[i] = src[3 + i]; return dst; } break; case 0x02: if (CMBRTU.CalculateCrc(src, src[2] + 5) == 0x00) { byte[] dst = new byte[src[2]]; for (int i = 0; i < src[2]; i++) dst[i] = src[3 + i]; return dst; } break; case 0x04: if (CMBRTU.CalculateCrc(src, src[2] + 5) == 0x00) { byte[] dst = new byte[src[2]]; for (int i = 0; i < src[2]; i++) dst[i] = src[3 + i]; return dst; } break; case 0x05: if (CMBRTU.CalculateCrc(src, 8) == 0x00) { byte[] dst = new byte[1]; dst[0] = src[4]; return dst; } break; case 0x0f: if (CMBRTU.CalculateCrc(src, 8) == 0x00) { byte[] dst = new byte[1]; dst[0] = 1; return dst; } break; } return null; } public void ResetAlarm() { } ManualResetEvent _writeHandle = new ManualResetEvent(true); object _writeLock = new object(); public void WriteOutput(int index, bool isOpen, bool isShortSingal = true, int elaspedTime = 0) { _writeHandle.Reset(); lock (_writeLock) { try { if (index < 0 || index > IConfig.OutputNums) { LogAsync(DateTime.Now, $"写入索引{index}超限,写入失败", ""); } byte[] byteData = CModbusDll.WriteDO(IConfig.UnitNum, index, isOpen); sp.Write(byteData, 0, byteData.Length); if (isShortSingal) { if (elaspedTime == 0) { elaspedTime = IConfig.SignalElasped; } Thread.Sleep(elaspedTime); byteData = CModbusDll.WriteDO(IConfig.UnitNum, index, !isOpen); sp.Write(byteData, 0, byteData.Length); } Thread.Sleep(IConfig.ReadWaitTime); sp.ReadExisting(); } catch (Exception ex) { throw ex; } finally { _writeHandle.Set(); } } } #endregion #region DeviceBase SerialPort sp = null; byte[] byteCloseAll = null; byte[] byteOpenAll = null; byte[] byteReadAllOutput = null; byte[] byteReadAllInput = null; DAMInitialConfig IConfig { get => InitialConfig as DAMInitialConfig; } protected override void Init() { sp = new SerialPort(IConfig.PortName); sp.BaudRate = int.Parse(IConfig.BaudRate); sp.Parity = IConfig.Parity; sp.DataBits = IConfig.DataBits; sp.StopBits = IConfig.StopBits; byteCloseAll = CModbusDll.WriteAllDO(IConfig.UnitNum, IConfig.OutputNums, false); byteOpenAll = CModbusDll.WriteAllDO(IConfig.UnitNum, IConfig.OutputNums, true); byteReadAllOutput = CModbusDll.ReadDO(IConfig.UnitNum, IConfig.OutputNums); byteReadAllInput = CModbusDll.ReadDI(IConfig.UnitNum, IConfig.InputNums); } protected override void Pause() { } protected override void Resume() { } protected override void Start() { sp.Open(); _writeHandle = new ManualResetEvent(true); } protected override void Stop() { if (sp != null && sp.IsOpen) { sp.Close(); } _writeHandle.Set(); _writeHandle.Dispose(); } #endregion } }