| | |
| | | using HslCommunication; |
| | | using System.ComponentModel; |
| | | using System.Reflection; |
| | | using System.Threading; |
| | | using WIDESEAWCS_Communicator; |
| | | using WIDESEAWCS_QuartzJob.DeviceBase; |
| | | using WIDESEAWCS_QuartzJob.DTO; |
| | | using WIDESEAWCS_QuartzJob.StackerCrane; |
| | | using WIDESEAWCS_QuartzJob.StackerCrane.Common; |
| | | using WIDESEAWCS_QuartzJob.StackerCrane.Enum; |
| | | using WIDESEAWCS_Core.LogHelper; |
| | | |
| | | namespace WIDESEAWCS_QuartzJob |
| | | { |
| | |
| | | /// 一般堆垛机实现类,实现堆垛机接口层 |
| | | /// </summary> |
| | | [Description("堆垛机")] |
| | | public class CommonStackerCrane : IStackerCrane |
| | | public class CommonStackerCrane : StackerCraneBase, IStackerCrane |
| | | { |
| | | #region Private Member |
| | | |
| | |
| | | /// </summary> |
| | | private int _lastTaskNum; |
| | | |
| | | private bool _isChecked = false; |
| | | /// <summary> |
| | | /// 标记是否正在检查任务完成状态(volatile 保证多线程可见性) |
| | | /// </summary> |
| | | private volatile bool _isChecked = false; |
| | | |
| | | private bool _heartStatr = true; |
| | | |
| | |
| | | public bool IsConnected => Communicator.IsConnected && _isConnected; |
| | | |
| | | /// <summary> |
| | | /// 堆垛机完成事件是否已订阅 |
| | | /// </summary> |
| | | public bool IsEventSubscribed => StackerCraneTaskCompletedEventHandler != null; |
| | | |
| | | /// <summary> |
| | | /// 堆垛机任务完成事件 |
| | | /// </summary> |
| | | public event EventHandler<StackerCraneTaskCompletedEventArgs> StackerCraneTaskCompletedEventHandler; |
| | |
| | | /// </summary> |
| | | public object StackerCraneTaskCommand { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 堆垛机完成事件是否已订阅 |
| | | /// </summary> |
| | | public bool IsEventSubscribed => StackerCraneTaskCompletedEventHandler != null; |
| | | |
| | | /// <summary> |
| | | /// 上一次任务的类型 |
| | |
| | | { |
| | | return DeviceStatus.Idle; |
| | | } |
| | | else if (StackerCraneWorkStatusValue == StackerCraneWorkStatus.Putting || StackerCraneWorkStatusValue == StackerCraneWorkStatus.PickUp || StackerCraneWorkStatusValue == StackerCraneWorkStatus.PickUpCompleted || StackerCraneWorkStatusValue == StackerCraneWorkStatus.PutCompleted) |
| | | else if (StackerCraneWorkStatusValue == StackerCraneWorkStatus.Putting || StackerCraneWorkStatusValue == StackerCraneWorkStatus.PickUp || StackerCraneWorkStatusValue == StackerCraneWorkStatus.PutMove || StackerCraneWorkStatusValue == StackerCraneWorkStatus.PutCompleted) |
| | | { |
| | | return DeviceStatus.Working; |
| | | } |
| | |
| | | private int GetCurrentTaskNum() |
| | | { |
| | | DeviceProDTO? devicePro = _deviceProDTOs.FirstOrDefault(x => x.DeviceProParamName == nameof(CurrentTaskNum)); |
| | | return devicePro == null ? throw new Exception($"读取当前任务号错误,未获取到协议信息,请检查配置参数名称是否配置,且配置为为{nameof(CurrentTaskNum)}") : (int)Communicator.ReadAsObj(devicePro.DeviceProAddress, devicePro.DeviceDataType); |
| | | if (devicePro == null) |
| | | throw new Exception($"读取当前任务号错误,未获取到协议信息,请检查配置参数名称是否配置,且配置为{nameof(CurrentTaskNum)}"); |
| | | |
| | | object value = Communicator.ReadAsObj(devicePro.DeviceProAddress, devicePro.DeviceDataType); |
| | | return Convert.ToInt32(value); // 统一转换为 int |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | { |
| | | return deviceProtocolDetail.ProtocolDetailType; |
| | | } |
| | | return StackerCraneStatus.Unkonw.ToString(); |
| | | return StackerCraneStatus.Unknown.ToString(); |
| | | } |
| | | } |
| | | return StackerCraneStatus.Unkonw.ToString(); |
| | | return StackerCraneStatus.Unknown.ToString(); |
| | | } |
| | | |
| | | private void CheckConnect() |
| | |
| | | if (Communicator is SiemensS7) |
| | | { |
| | | if (!IsConnected) throw new Exception($"通讯连接错误,请检查网络"); |
| | | DeviceProDTO? devicePro = _deviceProDTOs.Where(x => x.DeviceProParamType == nameof(DeviceCommand)).OrderBy(x => x.DeviceProOffset).FirstOrDefault(); |
| | | DeviceProDTO? devicePro = _deviceProDTOs.Where(x => x.DeviceProParamType == nameof(DeviceCommand) && x.DeviceProParamName == "InputTaskNum")/*.OrderBy(x=>x.DeviceProOffset)*/.FirstOrDefault(); |
| | | if (devicePro == null) |
| | | { |
| | | return false; |
| | |
| | | _isChecked = true; |
| | | try |
| | | { |
| | | DeviceProDTO? devicePro = _deviceProDTOs.FirstOrDefault(x => x.DeviceProParamName == nameof(StackerCraneWorkStatus)); |
| | | DeviceProDTO? devicePro = _deviceProDTOs.FirstOrDefault(x => x.DeviceProParamName == nameof(StackerCraneCompleted)); |
| | | if (devicePro != null) |
| | | { |
| | | DeviceProtocolDetailDTO? deviceProtocolDetail = _deviceProtocolDetailDTOs.FirstOrDefault(x => x.DeviceProParamName == devicePro.DeviceProParamName && x.ProtocolDetailType == StackerCraneWorkStatus.WorkCompleted.ToString()); |
| | | DeviceProtocolDetailDTO? deviceProtocolDetail = _deviceProtocolDetailDTOs.FirstOrDefault(x => x.DeviceProParamName == devicePro.DeviceProParamName && x.ProtocolDetailType == StackerCraneCompleted.Completed.ToString()); |
| | | if (deviceProtocolDetail != null) |
| | | { |
| | | OperateResult<TimeSpan> operateResult = new OperateResult<TimeSpan>(); |
| | | TypeCode typeCode = SiemensDBDataType.GetTypeCode(devicePro.DeviceDataType); |
| | | |
| | | // 超时从 10*6000ms (60s) 降低到 10*1000ms (10s),防止断连时长时间阻塞 |
| | | int timeout = 10 * 1000; |
| | | switch (typeCode) |
| | | { |
| | | case TypeCode.Boolean: |
| | | operateResult = Communicator.Wait(devicePro.DeviceProAddress, 500, 10 * 6000, Convert.ToBoolean(deviceProtocolDetail.ProtocalDetailValue)); |
| | | operateResult = Communicator.Wait(devicePro.DeviceProAddress, 500, timeout, Convert.ToBoolean(deviceProtocolDetail.ProtocalDetailValue)); |
| | | break; |
| | | |
| | | case TypeCode.Byte: |
| | | operateResult = Communicator.Wait(devicePro.DeviceProAddress, 500, 10 * 6000, Convert.ToByte(deviceProtocolDetail.ProtocalDetailValue)); |
| | | operateResult = Communicator.Wait(devicePro.DeviceProAddress, 500, timeout, Convert.ToByte(deviceProtocolDetail.ProtocalDetailValue)); |
| | | break; |
| | | |
| | | case TypeCode.Int16: |
| | | operateResult = Communicator.Wait(devicePro.DeviceProAddress, 500, 10 * 6000, Convert.ToInt16(deviceProtocolDetail.ProtocalDetailValue)); |
| | | operateResult = Communicator.Wait(devicePro.DeviceProAddress, 500, timeout, Convert.ToInt16(deviceProtocolDetail.ProtocalDetailValue)); |
| | | break; |
| | | |
| | | case TypeCode.Int32: |
| | | operateResult = Communicator.Wait(devicePro.DeviceProAddress, 500, 10 * 6000, Convert.ToInt32(deviceProtocolDetail.ProtocalDetailValue)); |
| | | operateResult = Communicator.Wait(devicePro.DeviceProAddress, 500, timeout, Convert.ToInt32(deviceProtocolDetail.ProtocalDetailValue)); |
| | | break; |
| | | |
| | | case TypeCode.UInt16: |
| | | operateResult = Communicator.Wait(devicePro.DeviceProAddress, 500, 10 * 6000, Convert.ToUInt16(deviceProtocolDetail.ProtocalDetailValue)); |
| | | operateResult = Communicator.Wait(devicePro.DeviceProAddress, 500, timeout, Convert.ToUInt16(deviceProtocolDetail.ProtocalDetailValue)); |
| | | break; |
| | | |
| | | case TypeCode.UInt32: |
| | | operateResult = Communicator.Wait(devicePro.DeviceProAddress, 500, 10 * 6000, Convert.ToUInt32(deviceProtocolDetail.ProtocalDetailValue)); |
| | | operateResult = Communicator.Wait(devicePro.DeviceProAddress, 500, timeout, Convert.ToUInt32(deviceProtocolDetail.ProtocalDetailValue)); |
| | | break; |
| | | |
| | | default: |
| | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | // 记录异常,避免错误被静默吞掉 |
| | | QuartzLogger.Error($"CheckStackerCraneTaskCompleted: 设备 {_deviceCode} 检查异常", "CommonStackerCrane", ex); |
| | | } |
| | | finally |
| | | { |