using HslCommunication; using OfficeOpenXml.FormulaParsing.Excel.Functions.Text; using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; using WIDESEAWCS_Communicator; using WIDESEAWCS_QuartzJob.DeviceBase; using WIDESEAWCS_QuartzJob.DTO; using WIDESEAWCS_QuartzJob.StackerCrane; using WIDESEAWCS_QuartzJob.StackerCrane.Enum; namespace WIDESEAWCS_QuartzJob { /// /// 自定义堆垛机 /// /// 堆垛机状态1泛型 /// 堆垛机状态2泛型 /// 堆垛机状态3泛型 [Description("堆垛机")] public class SpeStackerCrane : IStackerCrane { #region Private Member /// /// 堆垛机通讯对象 /// private BaseCommunicator _communicator; /// /// 堆垛机协议信息 /// private readonly List _deviceProDTOs; /// /// 堆垛机协议明细信息 /// private readonly List _deviceProtocolDetailDTOs; /// /// 设备编号 /// public readonly string _deviceCode; /// /// 设备名称 /// public readonly string _deviceName; /// /// 上一次任务号 /// private int _lastTaskNum; private bool _isChecked = false; private bool _heartStatr = true; private bool _isConnected = true; #endregion Private Member #region Public Member public BaseCommunicator Communicator => _communicator; public List DeviceProDTOs => _deviceProDTOs; public List DeviceProtocolDetailDTOs => _deviceProtocolDetailDTOs; public int LastTaskNum => _lastTaskNum; public int CurrentTaskNum => GetCurrentTaskNum(); public int? LastTaskType { get; set; } = null; public string DeviceCode => _deviceCode; public string DeviceName => _deviceName; public bool IsFault => throw new NotImplementedException(); public bool IsConnected => Communicator.IsConnected && _isConnected; public DeviceStatus Status => throw new NotImplementedException(); /// /// 无用 /// public event EventHandler StackerCraneTaskCompletedEventHandler; public object StackerCraneTaskCommand { get; set; } #endregion #region Constructor Function /// /// 构造函数 /// /// 堆垛机通讯对象 /// 堆垛机协议信息 /// 堆垛机协议明细信息 /// 设备编号 /// 设备名称 public SpeStackerCrane(BaseCommunicator communicator, List deviceProDTOs, List deviceProtocolDetailDTOs, string deviceCode, string deviceName) { _communicator = communicator; _deviceProDTOs = deviceProDTOs; _deviceProtocolDetailDTOs = deviceProtocolDetailDTOs; _deviceCode = deviceCode; _deviceName = deviceName; CheckConnect(); } #endregion #region Private Method private object GetStatus(string protocolParamType) { if (Communicator.IsConnected) { List devicePros = _deviceProDTOs.Where(x => x.DeviceProParamType == protocolParamType).ToList(); if (devicePros.Count == 0) { throw new Exception("未获取到协议信息"); } for (int i = 0; i < devicePros.Count; i++) { object readStatus = Communicator.ReadAsObj(devicePros[i].DeviceProAddress, devicePros[i].DeviceDataType); //todo 协议明细信息未获取到时抛出异常 DeviceProtocolDetailDTO? deviceProtocolDetail = _deviceProtocolDetailDTOs.FirstOrDefault(x => x.DeviceProParamName == devicePros[i].DeviceProParamName) ?? throw new Exception(); deviceProtocolDetail = _deviceProtocolDetailDTOs.FirstOrDefault(x => x.DeviceProParamName == devicePros[i].DeviceProParamType && x.ProtocalDetailValue.Equals(readStatus.ToString())); if (deviceProtocolDetail != null) { return Convert.ToInt32(readStatus); } return -1; } } //todo 通讯未连接时抛出异常 return -1; } private int GetCurrentTaskNum() { DeviceProDTO? devicePro = _deviceProDTOs.FirstOrDefault(x => x.DeviceProParamName == nameof(CurrentTaskNum)); return devicePro == null ? throw new Exception() : (int)Communicator.ReadAsObj(devicePro.DeviceProAddress, devicePro.DeviceDataType); } private void CheckConnect() { Task.Run(() => { while (_heartStatr) { try { DeviceProDTO? devicePro = _deviceProDTOs.FirstOrDefault(); if (devicePro == null) _isConnected = false; else Communicator.ReadAsObj(devicePro.DeviceProAddress, devicePro.DeviceDataType); _isConnected = true; } catch (Exception ex) { _isConnected = false; } Thread.Sleep(500); } }); } #endregion #region Public Method public T GetStackerCraneStatus() where T : notnull, Enum { return (T)GetStatus(typeof(T).Name); } public void Dispose() { _heartStatr = false; _communicator.Dispose(); GC.SuppressFinalize(this); } public TRsult GetValue(TEnum value) where TEnum : Enum { if (!IsConnected) throw new Exception($"通讯连接错误,请检查网络"); DeviceProDTO? devicePro = _deviceProDTOs.FirstOrDefault(x => x.DeviceProParamName == value.ToString()); return devicePro == null ? throw new Exception() : (TRsult)Communicator.ReadAsObj(devicePro.DeviceProAddress, devicePro.DeviceDataType); } public void Heartbeat() { } public bool SendCommand(T command) where T : IDataTransfer, new() { if (!IsConnected) throw new Exception($"通讯连接错误,请检查网络"); DeviceProDTO? devicePro = _deviceProDTOs.Where(x => x.DeviceProParamType == nameof(DeviceCommand)).OrderBy(x => x.DeviceProOffset).FirstOrDefault(); if (devicePro == null) { return false; } if (Communicator.WriteCustomer(devicePro.DeviceProAddress, command)) { StackerCraneTaskCommand = command; //CheckStackerCraneTaskCompleted(); return true; } return false; } /// /// 监测堆垛机任务是否完成(防止任务完成事件监测超时,定义手动触发功能) /// void CheckStackerCraneTaskCompleted() { if (_isChecked) return; Task.Run(() => { _isChecked = true; try { DeviceProDTO? devicePro = _deviceProDTOs.FirstOrDefault(x => x.DeviceProParamName == nameof(StackerCraneWorkStatus)); if (devicePro != null) { DeviceProtocolDetailDTO? deviceProtocolDetail = _deviceProtocolDetailDTOs.FirstOrDefault(x => x.DeviceProParamName == devicePro.DeviceProParamName && x.ProtocolDetailType == StackerCraneWorkStatus.WorkCompleted.ToString()); if (deviceProtocolDetail != null) { OperateResult operateResult = new OperateResult(); TypeCode typeCode = SiemensDBDataType.GetTypeCode(devicePro.DeviceDataType); switch (typeCode) { case TypeCode.Boolean: operateResult = Communicator.Wait(devicePro.DeviceProAddress, 500, 10 * 6000, Convert.ToBoolean(deviceProtocolDetail.ProtocalDetailValue)); break; case TypeCode.Byte: operateResult = Communicator.Wait(devicePro.DeviceProAddress, 500, 10 * 6000, Convert.ToByte(deviceProtocolDetail.ProtocalDetailValue)); break; case TypeCode.Int16: operateResult = Communicator.Wait(devicePro.DeviceProAddress, 500, 10 * 6000, Convert.ToInt16(deviceProtocolDetail.ProtocalDetailValue)); break; case TypeCode.Int32: operateResult = Communicator.Wait(devicePro.DeviceProAddress, 500, 10 * 6000, Convert.ToInt32(deviceProtocolDetail.ProtocalDetailValue)); break; case TypeCode.UInt16: operateResult = Communicator.Wait(devicePro.DeviceProAddress, 500, 10 * 6000, Convert.ToUInt16(deviceProtocolDetail.ProtocalDetailValue)); break; case TypeCode.UInt32: operateResult = Communicator.Wait(devicePro.DeviceProAddress, 500, 10 * 6000, Convert.ToUInt32(deviceProtocolDetail.ProtocalDetailValue)); break; default: break; } int taskNum = CurrentTaskNum; if (operateResult.IsSuccess /*&& LastTaskNum != taskNum*/) { StackerCraneTaskCompletedEventArgs args = new(taskNum); StackerCraneTaskCompletedEventHandler?.Invoke(this, args); _lastTaskNum = taskNum; } } } } catch (Exception ex) { } finally { _isChecked = false; } }); } public bool SetValue(TEnum @enum, TValue value) where TEnum : Enum where TValue : notnull { if (!IsConnected) throw new Exception($"通讯连接错误,请检查网络"); DeviceProDTO? devicePro = _deviceProDTOs.FirstOrDefault(x => x.DeviceProParamName == @enum.ToString()); return devicePro == null ? throw new Exception() : Communicator.WriteObj(devicePro.DeviceProAddress, devicePro.DeviceDataType, value); } #endregion } }