using Bro.Common.Base; using Bro.Common.Helper; using Bro.Common.Interface; using Bro.Common.Model; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using static Bro.Common.Helper.EnumHelper; namespace Bro.Device.GTSCard { [Device("GTSCard", "固高板卡", EnumHelper.DeviceAttributeType.Device)] public class GTSCardDriver : MotionCardBase { // 异常事件 public Action OnExceptionRaised; public GTSCardInitialConfig IIConfig { get { return InitialConfig as GTSCardInitialConfig; } } static object moveLock = new object(); /// /// 是否复位标志 /// bool _isResetting = false; public void SetResetFlag(bool isReset) { _isResetting = isReset; } public override List GetCurrentAxisInfo(params string[] axisName) { throw new NotImplementedException(); } #region DeviceBase protected override void Init() { InitialMotionCard(); } protected override void Pause() { throw new NotImplementedException(); } protected override void Resume() { throw new NotImplementedException(); } protected override void Start() { AllAxisOn(); } protected override void Stop() { AllMoveStop(); AllAxisOff(); } /// /// 设备 运行(执行 板卡系列的操作的 集合) /// /// /// public override ResponseMessage Run(IOperationConfig config) { ResponseMessage responseMessage = new ResponseMessage(); var motionCardOperationConfig = config as MotionCardOperationConfigBase; foreach (var operationSet in motionCardOperationConfig.OperationCollection) { responseMessage = RunOperationSet(operationSet); if (!responseMessage.Result) { return responseMessage; } } return responseMessage; } /// /// 执行 一个系列的操作 /// private ResponseMessage RunOperationSet(MotionCardOperationSet operationSet) { ResponseMessage responseMessage = new ResponseMessage(); // 1.预检查 if (CurrentState == DeviceState.DSOpen) { foreach (var preCheck in operationSet.PreCheckIOCollection) { int timeout = operationSet.PreCheckIOTimeout; IOValue? ioData = null; while (CurrentState == DeviceState.DSOpen) { Thread.Sleep(10); ioData = MonitorValues.FirstOrDefault(u => u.IONum == preCheck.IOItem.IONum && u.IOType == preCheck.IOItem.IOType)?.Value;//IO 是开、关 从MonitorValues 获取 timeout -= 10; if (preCheck.CheckValue == ioData || (operationSet.PreCheckIOTimeout > 0 && timeout < 0)) { break; } } if (preCheck.CheckValue != ioData) { responseMessage.Result = false; responseMessage.Message = $"预检查不通过,配置:{preCheck.GetDisplayText()},当前值:{ioData}"; return responseMessage; } } } // 2.板卡运动 if (CurrentState == DeviceState.DSOpen) { responseMessage = MoveToPoint(operationSet.MotionOperationCollection); if (!responseMessage.Result) { return responseMessage; } } // 3.IO输出 不需要超时 if (CurrentState == DeviceState.DSOpen) { foreach (var ioOutput in operationSet.IOOutputCollection) { var ioData = MonitorValues.FirstOrDefault(u => u.IONum == ioOutput.IOItem.IONum && u.IOType == ioOutput.IOItem.IOType)?.Value;//IO 是开、关 从MonitorValues 获取 if (ioOutput.CheckValue != ioData) { responseMessage.Result = false; responseMessage.Message = $"IO输出不通过,配置:{ioOutput.GetDisplayText()},当前值:{ioData}"; return responseMessage; } } } // 4.IO确认 if (CurrentState == DeviceState.DSOpen) { foreach (var ioConfirm in operationSet.IOConfirmCollection) { int timeout = operationSet.IOConfirmTimeout; IOValue? ioData = null; while (CurrentState == DeviceState.DSOpen) { Thread.Sleep(10); ioData = MonitorValues.FirstOrDefault(u => u.IONum == ioConfirm.IOItem.IONum && u.IOType == ioConfirm.IOItem.IOType)?.Value;//IO 是开、关 从MonitorValues 获取 timeout -= 10; if (ioConfirm.CheckValue == ioData || (operationSet.IOConfirmTimeout > 0 && timeout < 0)) { break; } } if (ioConfirm.CheckValue != ioData) { responseMessage.Result = false; responseMessage.Message = $"IO确认不通过,配置:{ioConfirm.GetDisplayText()},当前值:{ioData}"; return responseMessage; } } } return responseMessage; } #endregion #region GTSCard /// /// Load Motion Card parameter from file /// /// Invalid Parameter /// public void InitialMotionCard() { var res = GTSCardAPI.GT_Open((short)IConfig.CardNum, 0, 1); //打开运动控制器。参数必须为(0,1),不能修改。 res += GTSCardAPI.GT_LoadConfig((short)IConfig.CardNum, IConfig.InitialConfigFilePath); res += GTSCardAPI.GT_ClrSts(0, 1, 8); if (res != (short)GTSRetCode.GRCRunOK) { throw new Exception("板卡载入配置文件异常,错误码:" + res); } } public bool AllAxisOn() { List> taskList = new List>(); ; // 如果是多个轴的运动 等每个轴开启 IConfig.AxisSettings.Where(a => a.IsAxisEnabled).ToList().ForEach(axisNum => { var task = AxisOnAsync((short)IConfig.CardNum, (short)axisNum.AxisIndex); taskList.Add(task); }); Task.WaitAll(taskList.ToArray()); var resultOK = taskList.All(u => u.GetAwaiter().GetResult()); return resultOK; } public bool AllAxisOff() { List> taskList = new List>(); ; // 如果是多个轴的运动 等每个轴关闭 IConfig.AxisSettings.Where(a => a.IsAxisEnabled).ToList().ForEach(axisNum => { var task = AxisOffAsync((short)IConfig.CardNum, (short)axisNum.AxisIndex); taskList.Add(task); }); Task.WaitAll(taskList.ToArray()); var resultOK = taskList.All(u => u.GetAwaiter().GetResult()); return resultOK; } /// /// 单个轴开启 /// /// public async Task AxisOnAsync(short cardNum, short axisNum) { return await Task.Run(() => { var ret = GTSCardAPI.GT_AxisOn(cardNum, axisNum); return ret == (short)GTSRetCode.GRCRunOK; }); } /// /// 单个轴关闭 /// /// public async Task AxisOffAsync(short cardNum, short axisNum) { return await Task.Run(() => { var ret = GTSCardAPI.GT_AxisOff(cardNum, axisNum); return ret == (short)GTSRetCode.GRCRunOK; }); } /// /// 点位到点位运动 /// /// 运动对象 /// 运动控制+停止判断 public override ResponseMessage MoveToPoint(IOperationConfig opConfig) { ResponseMessage responseMessage = new ResponseMessage(); var gtsOperationCollection = opConfig as MotionOperationCollection; List> taskList = new List>(); foreach (var movingOp in gtsOperationCollection.MovingOps) { var task = SingleAxisMoving(movingOp); taskList.Add(task); } Task.WaitAll(taskList.ToArray()); responseMessage.Result = taskList.All(u => u.GetAwaiter().GetResult()); if (!responseMessage.Result) { responseMessage.Message = $"点位运动异常"; } return responseMessage; } /// /// 点到点运动设置参数 /// /// 运动参数对象 /// private bool SetAxisParam(MovingOption optionPara) { List resultCode = new List() { 0 }; GTSCardAPI.TTrapPrm trapprm = new GTSCardAPI.TTrapPrm(); resultCode.Add(GTSCardAPI.GT_PrfTrap((short)IConfig.CardNum, (short)optionPara.AxisIndex)); resultCode.Add(GTSCardAPI.GT_GetTrapPrm((short)IConfig.CardNum, (short)optionPara.AxisIndex, out trapprm)); trapprm.smoothTime = 1; trapprm.acc = optionPara.VelocityPara.Acc != 0 ? optionPara.VelocityPara.Acc : 1; trapprm.dec = optionPara.VelocityPara.Dec != 0 ? optionPara.VelocityPara.Dec : 1; resultCode.Add(GTSCardAPI.GT_SetTrapPrm((short)IConfig.CardNum, (short)optionPara.AxisIndex, ref trapprm)); resultCode.Add(GTSCardAPI.GT_SetVel((short)IConfig.CardNum, (short)optionPara.AxisIndex, optionPara.VelocityPara.Velocity * IConfig.AxisVelocityRatio)); var resultOK = resultCode.All(u => u == (short)GTSRetCode.GRCRunOK); if (!resultOK) { throw new Exception("轴" + optionPara.AxisIndex + "设置参数异常,错误码:" + string.Join(",", resultCode)); } return resultOK; } /// /// 单个轴 运动(点到点 jog 回零...) /// /// 运动参数对象 public async Task SingleAxisMoving(MovingOption optionPara) { return await Task.Run(() => { bool isSuccessAndStop = false; try { if (IConfig.AxisSettings.FirstOrDefault(a => a.AxisIndex == optionPara.AxisIndex)?.IsAxisEnabled ?? false) { string _position = ""; string motionType = optionPara.MoveMode == EnumHelper.MotionMode.Normal ? (optionPara.IsAbsolute ? "Abs" : "Rel") : optionPara.MoveMode.ToString(); _position = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff},{optionPara.AxisIndex},{motionType},{GetPosition(optionPara.AxisIndex)},{GetPrfPosition(optionPara.AxisIndex)},{optionPara.Destination},"; switch (optionPara.MoveMode) { case MotionMode.Normal: { if (_isResetting) { LogAsync(DateTime.Now, "复位中启动运动异常", optionPara.AxisIndex + "启动运动异常"); return false; } if (optionPara.IsAbsolute) { isSuccessAndStop = P2PMoveAbs(optionPara); } else { isSuccessAndStop = P2PMoveRel(optionPara); } } break; case MotionMode.FindOri: { isSuccessAndStop = GoHome(optionPara); } break; case MotionMode.Jog: { isSuccessAndStop = JogMove(optionPara); } break; } _position += $"{GetPosition(optionPara.AxisIndex)},"; _position += $"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}"; LogAsync(DateTime.Now, "", _position); } } catch (Exception ex) { isSuccessAndStop = false; LogAsync(DateTime.Now, $"轴{optionPara.AxisIndex}运动异常", ex.GetExceptionMessage()); } return isSuccessAndStop; }); } /// /// 获取规划位置(要去的位置) /// /// Axis number /// public double GetPrfPosition(int axisNum) { double position = 0; double prfpos = 0; uint pclock = 0; var ret = GTSCardAPI.GT_GetPrfPos((short)IConfig.CardNum, (short)axisNum, out prfpos, 1, out pclock); if (ret != (short)GTSRetCode.GRCRunOK) { throw new Exception("轴" + axisNum + "获取规划位置异常,错误码:" + ret); } position = prfpos / IConfig.AxisVelocityRatio; return position; } /// /// 获取目前当前位置 /// /// Axis number /// public double GetPosition(int axisNum) { lock (moveLock) { double position = 0; int pPos = 0; var ret = GTSCardAPI.GT_GetPos((short)IConfig.CardNum, (short)axisNum, out pPos); if (ret != (short)GTSRetCode.GRCRunOK) { throw new Exception("轴" + axisNum + "获取目标位置异常,错误码:" + ret); } position = pPos / IConfig.AxisVelocityRatio; return position; } } /// /// 获取规划速度 /// /// Axis number /// public double GetPrfVelocity(int axisNum) { double prfVel = 0; uint pclock = 0; var ret = GTSCardAPI.GT_GetPrfVel((short)IConfig.CardNum, (short)axisNum, out prfVel, 1, out pclock); if (ret != (short)GTSRetCode.GRCRunOK) { throw new Exception("轴" + axisNum + "获取规划速度异常,错误码:" + ret); } prfVel = prfVel / IConfig.AxisVelocityRatio; return prfVel; } /// /// 获取当前速度 /// /// Axis number /// public double GetVelocity(int axisNum) { double vel = 0; var ret = GTSCardAPI.GT_GetVel((short)IConfig.CardNum, (short)axisNum, out vel); if (ret != (short)GTSRetCode.GRCRunOK) { throw new Exception("轴" + axisNum + "获取当前速度异常,错误码:" + ret); } vel = vel / IConfig.AxisVelocityRatio; return vel; } /// /// Set Single Axis Do Jog Move /// /// AxisNo /// Motion Direction 0: Negative, 1: Positive /// max velocity /// public bool JogMove(MovingOption optionPara) { try { GTSCardAPI.TJogPrm jogprm = new GTSCardAPI.TJogPrm(); short ret = 0; int repeatTime = 100; do { ret = GTSCardAPI.GT_PrfJog((short)IConfig.CardNum, (short)optionPara.AxisIndex); jogprm.acc = optionPara.VelocityPara.Acc; jogprm.dec = optionPara.VelocityPara.Dec; ret = GTSCardAPI.GT_SetJogPrm((short)IConfig.CardNum, (short)optionPara.AxisIndex, ref jogprm);//设置jog运动参数 ret = GTSCardAPI.GT_SetVel((short)IConfig.CardNum, (short)optionPara.AxisIndex, optionPara.VelocityPara.Velocity);//设置目标速度 ret = GTSCardAPI.GT_Update((short)IConfig.CardNum, 1 << (optionPara.AxisIndex - 1));//更新轴运动 if (ret != (short)GTSRetCode.GRCRunOK) { LogAsync(DateTime.Now, "轴" + optionPara.AxisIndex + "APS_absolute_move异常", "错误码:" + ret + ";" + "重试次数:" + repeatTime); Thread.Sleep(10); } repeatTime--; } while (ret != (short)GTSRetCode.GRCRunOK && repeatTime > 0); return (ret == (short)GTSRetCode.GRCRunOK); } catch (Exception ex) { AllMoveStop(true); OnExceptionRaised?.Invoke(ex); return false; } } /// /// 相对位置运动 /// /// AxisNo /// run distance /// public bool P2PMoveRel(MovingOption optionPara) { try { if (_isResetting) { LogAsync(DateTime.Now, "复位过程异常", "轴" + optionPara.AxisIndex + "试图在复位过程中运动"); throw new Exception("轴" + optionPara.AxisIndex + "试图在复位过程中运动"); } int repeatTime = 30; while (CurrentState != EnumHelper.DeviceState.DSOpen && repeatTime > 0) { Thread.Sleep(10); repeatTime--; } if (CurrentState == EnumHelper.DeviceState.DSExcept) { LogAsync(DateTime.Now, "板卡异常状态", "轴" + optionPara.AxisIndex + "试图异常状态运动"); return false; } if (CurrentState != EnumHelper.DeviceState.DSOpen) { LogAsync(DateTime.Now, "非正常状态异常", "轴" + optionPara.AxisIndex + "试图在非正常状态运动"); throw new Exception("轴" + optionPara.AxisIndex + "试图在非正常状态运动", null); } LogAsync(DateTime.Now, "轴" + optionPara.AxisIndex + "开始运动", "目标坐标:" + optionPara.Destination); short ret = 0; bool isSuccessSetAxisParam = false; int currentPosition = (int)GetPosition(optionPara.AxisIndex); int dPosition = optionPara.Destination + currentPosition; int timeout = optionPara.MovingTimeout; while (CurrentState == DeviceState.DSOpen) { //设置 运动参数 isSuccessSetAxisParam = SetAxisParam(optionPara); ret = GTSCardAPI.GT_SetPrfPos((short)IConfig.CardNum, (short)optionPara.AxisIndex, (int)(dPosition * IConfig.AxisVelocityRatio));// 设置规划位置 ret = GTSCardAPI.GT_Update((short)IConfig.CardNum, 1 << (optionPara.AxisIndex - 1));//更新运动 if (ret != (short)GTSRetCode.GRCRunOK) { LogAsync(DateTime.Now, "轴" + optionPara.AxisIndex + "APS_absolute_move异常", "错误码:" + ret + ";" + "重试次数:" + repeatTime); Thread.Sleep(50); } timeout -= 50; if ((ret == (short)GTSRetCode.GRCRunOK && isSuccessSetAxisParam) || (optionPara.MovingTimeout > 0 && timeout < 0)) { break; } } //运动开始后 检查运动是否停止 bool isStop = false; repeatTime = 1000; do { isStop = IsStop((short)IConfig.CardNum, (short)optionPara.AxisIndex); Thread.Sleep(50); repeatTime--; } while (!isStop && repeatTime > 0); return (ret == (short)GTSRetCode.GRCRunOK) && isStop; } catch (Exception ex) { AllMoveStop(true); OnExceptionRaised?.Invoke(ex); return false; } } /// /// 绝对位置运动 /// /// 运动参数对象 public bool P2PMoveAbs(MovingOption optionPara) { try { if (_isResetting) { LogAsync(DateTime.Now, "复位过程异常", "轴" + optionPara.AxisIndex + "试图在复位过程中运动"); throw new Exception("轴" + optionPara.AxisIndex + "试图在复位过程中运动"); } int repeatTime = 30; while (CurrentState != EnumHelper.DeviceState.DSOpen && repeatTime > 0) { Thread.Sleep(10); repeatTime--; } if (CurrentState == EnumHelper.DeviceState.DSExcept) { LogAsync(DateTime.Now, "板卡异常状态", "轴" + optionPara.AxisIndex + "试图异常状态运动"); return false; } if (CurrentState != EnumHelper.DeviceState.DSOpen) { LogAsync(DateTime.Now, "非正常状态异常", "轴" + optionPara.AxisIndex + "试图在非正常状态运动"); throw new Exception("轴" + optionPara.AxisIndex + "试图在非正常状态运动", null); } LogAsync(DateTime.Now, "轴" + optionPara.AxisIndex + "开始运动", "目标坐标:" + optionPara.Destination); short ret = 0; bool isSuccessSetAxisParam = false; int timeout = optionPara.MovingTimeout; while (CurrentState == DeviceState.DSOpen) { //设置 运动参数 isSuccessSetAxisParam = SetAxisParam(optionPara); ret = GTSCardAPI.GT_SetPrfPos((short)IConfig.CardNum, (short)optionPara.AxisIndex, (int)(optionPara.Destination * IConfig.AxisVelocityRatio));// 设置规划位置 ret = GTSCardAPI.GT_Update((short)IConfig.CardNum, 1 << (optionPara.AxisIndex - 1));//更新运动 if (ret != (short)GTSRetCode.GRCRunOK) { LogAsync(DateTime.Now, "轴" + optionPara.AxisIndex + "APS_absolute_move异常", "错误码:" + ret + ";" + "重试次数:" + repeatTime); Thread.Sleep(50); } timeout -= 50; if ((ret == (short)GTSRetCode.GRCRunOK && isSuccessSetAxisParam) || (optionPara.MovingTimeout > 0 && timeout < 0)) { break; } } bool isStop = false; repeatTime = 1000; do { isStop = IsStop((short)IConfig.CardNum, (short)optionPara.AxisIndex); Thread.Sleep(50); repeatTime--; } while (!isStop && repeatTime > 0); return (ret == (short)GTSRetCode.GRCRunOK) && isStop; } catch (Exception ex) { AllMoveStop(true); OnExceptionRaised?.Invoke(ex); return false; } } /// /// 某个轴运动停止 /// /// axisNo /// 0表示平滑停止,1表示紧急停止 /// public async Task MoveStop(int axisNum, int option) { return await Task.Run(() => { bool isStop = false; if (option == 1) { StateChange(EnumHelper.DeviceState.DSExcept); } var ret = GTSCardAPI.GT_Stop((short)IConfig.CardNum, 1 << (axisNum - 1), option); if (ret != (short)GTSRetCode.GRCRunOK) { LogAsync(DateTime.Now, "轴" + axisNum + "运动停止异常", "错误码:" + ret); throw new Exception("轴" + axisNum + "运动停止异常,错误码:" + ret); } else { LogAsync(DateTime.Now, "轴" + axisNum + "运动停止", ""); } int repeatTime = 100; do { isStop = IsStop((short)IConfig.CardNum, (short)axisNum); Thread.Sleep(10); repeatTime--; } while (!isStop && repeatTime > 0); return (ret == (short)GTSRetCode.GRCRunOK) && isStop; }); } /// /// 所有开启的轴停止 /// /// public void AllMoveStop(bool emergencyStop = false) { int option = emergencyStop ? 1 : 0; List> taskList = new List>(); ; // 如果是多个轴的运动 等每个轴运动结束 IConfig.AxisSettings.Where(a => a.IsAxisEnabled).ToList().ForEach(axisNum => { var task = MoveStop(axisNum.AxisIndex, option); taskList.Add(task); }); Task.WaitAll(taskList.ToArray()); var resultOK = taskList.All(u => u.GetAwaiter().GetResult()); } /// /// 回原点 /// /// 卡号 /// 轴号 /// 轴回原点状态 public bool GoHome(MovingOption movingOption) { try { GTSCardAPI.GT_ZeroPos((short)IConfig.CardNum, (short)movingOption.AxisIndex, 1); GTSCardAPI.THomePrm thomeprm; GTSCardAPI.THomeStatus homests; short rtn = GTSCardAPI.GT_GetHomePrm((short)IConfig.CardNum, (short)movingOption.AxisIndex, out thomeprm); thomeprm.mode = movingOption.GoHomePara.HomeMode;//回零方式 thomeprm.moveDir = movingOption.GoHomePara.HomeDir;//回零方向 thomeprm.edge = movingOption.GoHomePara.Edge; thomeprm.velHigh = movingOption.GoHomePara.HighVelocity; thomeprm.velLow = movingOption.GoHomePara.LowVelocity; thomeprm.acc = movingOption.VelocityPara.Acc; thomeprm.dec = movingOption.VelocityPara.Dec; thomeprm.searchHomeDistance = movingOption.GoHomePara.SearchHomeDistance;//搜搜距离 thomeprm.homeOffset = movingOption.GoHomePara.HomeOffset; //偏移距离 thomeprm.escapeStep = movingOption.GoHomePara.EscapeStep; rtn = GTSCardAPI.GT_GoHome((short)IConfig.CardNum, (short)movingOption.AxisIndex, ref thomeprm); //启动回零 bool isStop = false; int repeatTime = 1000; do { Thread.Sleep(10); GTSCardAPI.GT_GetHomeStatus((short)IConfig.CardNum, (short)movingOption.AxisIndex, out homests); isStop = homests.run == 0; if (isStop && homests.error == 0) { Thread.Sleep(200); GTSCardAPI.GT_ZeroPos((short)IConfig.CardNum, (short)movingOption.AxisIndex, 1); } repeatTime--; } while (!isStop && repeatTime > 0); return isStop; } catch (Exception ex) { AllMoveStop(true); OnExceptionRaised?.Invoke(ex); return false; } } /// /// 读取IO输入 /// /// 卡号 /// 输入口 /// 有输入返回true,无输入返回false public bool GetDi(short cardNum, short index) { int value; GTSCardAPI.GT_GetDi(cardNum, GTSCardAPI.MC_GPI, out value); if ((value & (1 << index)) == 0) return true;//有输入返回true else return false; //无输入返回false } /// /// 读取IO输出 /// /// io索引 /// public bool GetDoSts(short index) { int outSts; short outNum = (short)(index % 100); GTSCardAPI.GT_GetDo((short)IConfig.CardNum, GTSCardAPI.MC_GPO, out outSts); if ((outSts & (1 << outNum)) == 0) return true; else return false; } /// /// 按位设置数字 IO 输出状态 /// /// 输出口,返回1-16 /// false表示输出,true表示关闭 public override void WriteOutput(short index, IOValue value) { short outNum = (short)(index % 100 + 1); if ((int)value <= 1) { GTSCardAPI.GT_SetDoBit((short)IConfig.CardNum, GTSCardAPI.MC_GPO, outNum, (short)value); } else { var currentValue = (int)MonitorValues.FirstOrDefault(u => u.IONum == outNum && u.IOType == IOType.OUTPUT).Value; GTSCardAPI.GT_SetDoBit((short)IConfig.CardNum, GTSCardAPI.MC_GPO, outNum, (short)(currentValue == 1 ? 0 : 1)); } } /// /// 读取轴状态,判断电机是否停止 /// /// 板卡号 /// 轴号 /// public bool IsStop(short cardNum, short axisNum) { lock (moveLock) { int sts = 0; uint pclock = 0; GTSCardAPI.GT_GetSts(cardNum, axisNum, out sts, 1, out pclock); if ((sts & 0x400) == 0) return true;//停止返回true else return false; //运行中返回false } } #endregion #region IMonitor public List GetAxisMovingStatus() { List axisMovingStatusesList = new List(); foreach (var axisConfig in IConfig.AxisSettings.FindAll(u => u.IsAxisEnabled)) { AxisMovingStatus axisMovingStatus = new AxisMovingStatus(); axisMovingStatus.AxisIndex = axisConfig.AxisIndex; axisMovingStatus.AxisName = axisConfig.AxisName; axisMovingStatus.CurPosition = Convert.ToInt32(GetPosition(axisMovingStatus.AxisIndex)); axisMovingStatus.Destination = Convert.ToInt32(GetPrfPosition(axisMovingStatus.AxisIndex)); axisMovingStatus.CurVelocity = GetVelocity(axisMovingStatus.AxisIndex); axisMovingStatus.PrfVelocity = GetPrfVelocity(axisMovingStatus.AxisIndex); axisMovingStatusesList.Add(axisMovingStatus); } return axisMovingStatusesList; } public List GetMonitorValues() { var result = new List(); //读取IO输入 int inValue; GTSCardAPI.GT_GetDi((short)IConfig.CardNum, GTSCardAPI.MC_GPI, out inValue); //读取IO输出 int outValue; GTSCardAPI.GT_GetDo((short)IConfig.CardNum, GTSCardAPI.MC_GPO, out outValue); //解析结果 for (var index = 1; index <= 16; index++) { IOItem inItem = new IOItem() { IONum = index, Value = (inValue & (1 << index)) == 0 ? IOValue.TRUE : IOValue.FALSE, IOType = IOType.INPUT }; IOItem outItem = new IOItem() { IONum = index, Value = (outValue & (1 << index)) == 0 ? IOValue.TRUE : IOValue.FALSE, IOType = IOType.OUTPUT }; result.Add(inItem); result.Add(outItem); } return result; } public async override void Monitor() { await Task.Run(() => { while (CurrentState != EnumHelper.DeviceState.DSClose && CurrentState != EnumHelper.DeviceState.DSExcept && CurrentState != EnumHelper.DeviceState.DSUninit) { try { if (!IConfig.IsEnableMonitor) return; var newValues = GetMonitorValues(); var newAxisMovingStatus = GetAxisMovingStatus(); if (newValues == null || newValues.Count == 0 || newAxisMovingStatus == null || newAxisMovingStatus.Count == 0) continue; Stopwatch sw = new Stopwatch(); sw.Start(); if (MonitorValues.Count == newValues.Count) { var tempNew = newValues.DeepSerializeClone();//clone var tempOld = MonitorValues.DeepSerializeClone(); MonitorCheckAndInvoke(tempNew, tempOld); } AxisMovingOptionValues = new List(newAxisMovingStatus); MonitorValues = new List(newValues); sw.Stop(); if (sw.ElapsedMilliseconds > 20) { LogAsync(DateTime.Now, $"{this.Name}轮询时间:{sw.ElapsedMilliseconds}", ""); } if (IConfig.MonitorInterval > 0) { Thread.Sleep(IConfig.MonitorInterval); } } catch (Exception ex) { if (CurrentState == DeviceState.DSOpen) { LogAsync(DateTime.Now, $"{this.Name}监听异常", ex.GetExceptionMessage()); } } } }); } public override void OnMethodInvoked(IAsyncResult ar) { MotionCardMonitorSet monitorSet = ar.AsyncState as MotionCardMonitorSet; ProcessResponse resValues = monitorSet.Response; if (resValues.ResultValue == (int)ReplyValue.IGNORE) { return; } Stopwatch sw = new Stopwatch(); sw.Start(); // 将指定IOItem写入板卡 foreach (var replyIOData in monitorSet.ReplyIODatas) { //写入IO输出 if (replyIOData.IOType == IOType.OUTPUT) { GTSCardAPI.GT_SetDoBit((short)IConfig.CardNum, GTSCardAPI.MC_GPI, (short)replyIOData.IONum, (short)replyIOData.Value); } // in只读不能写 } sw.Stop(); LogAsync(DateTime.Now, $"{Name}反馈完成,耗时{sw.ElapsedMilliseconds}ms", $"{resValues.GetDisplayText()}"); } protected void MonitorCheckAndInvoke(List tempNew, List tempOld) { #region 警报信息 Parallel.ForEach(IConfig.WarningSetCollection, wSet => { MotionCardWarningSet warningSet = wSet as MotionCardWarningSet; bool isOn = (((int)((tempNew.FirstOrDefault(u => u.IONum == warningSet.TriggerIndex && u.IOType == warningSet.WarningIOModel)?.Value)) >> warningSet.TriggerIndex) & 1) == (warningSet.TriggerValue ? 1 : 0); if (warningSet.CurrentStatus != isOn) { warningSet.CurrentStatus = isOn; warningSet.TriggerTime = DateTime.Now; SaveAlarmCSVAsync(DateTime.Now, this.Name, warningSet); ExcuteMonitorAlarm(DateTime.Now, this, warningSet); } }); #endregion #region 监听信息 Parallel.ForEach(IConfig.MonitorSetCollection, mSet => { MotionCardMonitorSet monitorSet = mSet as MotionCardMonitorSet; if (monitorSet.TriggerIndex < 0 || monitorSet.TriggerIndex > tempNew.Count) { return; } var newIOItem = tempNew.FirstOrDefault(u => u.IONum == monitorSet.TriggerIndex); var oldIOItem = tempOld.FirstOrDefault(u => u.IONum == monitorSet.TriggerIndex); if (newIOItem?.Value != oldIOItem?.Value) { if (monitorSet.TriggerValue == -999 || (int)newIOItem.Value == monitorSet.TriggerValue) { if (monitorSet.OpConfig == null) { monitorSet.OpConfig = new OperationConfigBase(); } //monitorSet.OpConfig.InputPara = monitorSet.InputDataIndex.ConvertAll(index => //{ // return tempNew[index].Value; //}).ToList(); ExcuteMonitorInvoke(DateTime.Now, monitorSet.InvokeDevice, this, monitorSet); } } }); #endregion } public override void ResetAlarm() { int axis_sts; uint clk; var axisSettings = IConfig.AxisSettings.FindAll(u => u.IsAxisEnabled); GTSCardAPI.GT_ClrSts((short)IConfig.CardNum, 1, (short)axisSettings.Count); foreach (var axisSetting in axisSettings) { GTSCardAPI.GT_GetSts((short)IConfig.CardNum, (short)axisSetting.AxisIndex, out axis_sts, 1, out clk); if ((axis_sts & 0x200) == 0) { var rst = GTSCardAPI.GT_AxisOn((short)IConfig.CardNum, (short)axisSetting.AxisIndex); } // 位置请零 GTSCardAPI.GT_ZeroPos((short)IConfig.CardNum, 1, (short)axisSettings.Count); // 正极限报警 if ((axis_sts & 0x20) != 0) { // 负向移动 MovingOption movingOption = new MovingOption(); movingOption.AxisIndex = (short)axisSetting.AxisIndex; movingOption.Destination = -50; // 负向移动 movingOption.VelocityPara.Velocity = 50; P2PMoveAbs(movingOption); } // 负极限报警 if ((axis_sts & 0x40) != 0) { // 正向移动 MovingOption movingOption = new MovingOption(); movingOption.AxisIndex = (short)axisSetting.AxisIndex; movingOption.Destination = 50; // 负向移动 movingOption.VelocityPara.Velocity = 50; P2PMoveAbs(movingOption); } } // 清除状态 GTSCardAPI.GT_ClrSts((short)IConfig.CardNum, 1, (short)IConfig.AxisSettings.FindAll(u => u.IsAxisEnabled).Count); } object _alarmLock = new object(); private async void SaveAlarmCSVAsync(DateTime now, string plcName, IWarningSet ws) { await Task.Run(() => { lock (_alarmLock) { DirectoryInfo dir = new DirectoryInfo(this.IConfig.LogPath); if (!dir.Exists) { dir.Create(); } string path = Path.Combine(IConfig.LogPath, $"Alarm_{Name}_{now.ToString("yyyyMMdd")}.csv"); bool fileExist = File.Exists(path); using (StreamWriter writer = new StreamWriter(path, true, System.Text.Encoding.UTF8)) { if (!fileExist) { writer.WriteLine("Time,Source,AlarmCode,AlarmDescription,AlarmStatus"); } writer.WriteLine($"{now.ToString("HH:mm:ss.fff")},{plcName},{ws.WarningCode},{ws.WarningDescription},{(ws.CurrentStatus ? "报警" : "停止")}"); writer.Flush(); writer.Close(); } } }); } #endregion } }