From 5918194fccdb2a2303e713b8d2f3335243b9e2ef Mon Sep 17 00:00:00 2001
From: wells.liu <wells.liu@broconcentric.com>
Date: 星期二, 07 七月 2020 14:53:13 +0800
Subject: [PATCH] 板卡驱动

---
 src/Bro.Device.GTSCard/GTSCardDriver.cs | 1784 +++++++++++++++++++++++++++++------------------------------
 1 files changed, 884 insertions(+), 900 deletions(-)

diff --git a/src/Bro.Device.GTSCard/GTSCardDriver.cs b/src/Bro.Device.GTSCard/GTSCardDriver.cs
index 03b4c15..c2cc8e6 100644
--- a/src/Bro.Device.GTSCard/GTSCardDriver.cs
+++ b/src/Bro.Device.GTSCard/GTSCardDriver.cs
@@ -6,25 +6,24 @@
 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 : DeviceBase, IMonitor, IMotion
+    public class GTSCardDriver : MotionCardBase
     {
-        public event Action<DateTime, string, IDevice, MonitorSet> OnMonitorInvoke;
-        public event Action<DateTime, IDevice, WarningSet> OnMonitorAlarm;
-
-        public delegate bool OnAxisStartToCheckDelegate(int axisIndex, int startPosition, int endPosition);
         // 寮傚父浜嬩欢
         public Action<Exception> OnExceptionRaised;
 
-        public GTSCardInitialConfig IConfig
+        public GTSCardInitialConfig IIConfig
         {
             get
             {
@@ -32,42 +31,25 @@
             }
         }
 
-        static Dictionary<int, object> axisMoveLockDict = new Dictionary<int, object>();
-
-        /// <summary>
-        /// 杞磋繍鍔ㄥ紑濮嬫椂鐨勬娴嬶紝true:鏈夊啿绐� 涓嶅彲缁х画鎵ц false锛氭棤鍐茬獊,鍙户缁墽琛�
-        /// </summary>
-        public event OnAxisStartToCheckDelegate OnAxisStartToCheckConfliction;
-        /// <summary>
-        /// 鏆傚仠锛堢嚎绋嬪悓姝ヤ簨浠讹級
-        /// </summary>
-        Dictionary<int, ManualResetEvent> axisImmediatePauseHandleDict = new Dictionary<int, ManualResetEvent>();
-        Dictionary<int, CancellationTokenSource> axisMoveCancelDict = new Dictionary<int, CancellationTokenSource>();
-        /// <summary>
-        /// 杩愯杩囩▼涓殑绾跨▼绛夊緟
-        /// </summary>
-        private Dictionary<int, ManualResetEvent> runningEventDic = new Dictionary<int, ManualResetEvent>();
-        private Dictionary<int, AutoResetEvent> axisMovingHandleDict = new Dictionary<int, AutoResetEvent>();
-        private ConcurrentDictionary<int, int> axisDestination = new ConcurrentDictionary<int, int>();
-
-        private ObservableCollection<int> _commandAxisList = new ObservableCollection<int>();
-        public Action<bool> CommandAxisCountChangedAction = null;
-        private Dictionary<int, VelocityPara> velIndexDict = new Dictionary<int, VelocityPara>();
-        ManualResetEvent _pauseHandle = new ManualResetEvent(true);
-
-        static object lockObj = new object();
-        static object _commandAxisLock = new object();
+        static object moveLock = new object();
         /// <summary>
         /// 鏄惁澶嶄綅鏍囧織
         /// </summary>
         bool _isResetting = false;
+
+        /// <summary>
+        /// 杩愬姩杞寸珛鍗虫殏鍋�
+        /// </summary>
+        Dictionary<int, ManualResetEvent> axisImmediatePauseHandleDict = new Dictionary<int, ManualResetEvent>();
+
+        Dictionary<int, CancellationTokenSource> axisMoveCancelDict = new Dictionary<int, CancellationTokenSource>();
 
         public void SetResetFlag(bool isReset)
         {
             _isResetting = isReset;
         }
 
-        public List<AxisInfo> GetCurrentAxisInfo(params string[] axisName)
+        public override List<AxisInfo> GetCurrentAxisInfo(params string[] axisName)
         {
             throw new NotImplementedException();
         }
@@ -76,11 +58,7 @@
 
         protected override void Init()
         {
-            InitialMotionCard((short)IConfig.CardNum, IConfig.InitialConfigFilePath);
-
-            axisMoveLockDict = IConfig.AxisSettings.ToDictionary(a => a.AxisIndex, a => new object());
-            runningEventDic = IConfig.AxisSettings.ToDictionary(a => a.AxisIndex, a => new ManualResetEvent(false));
-            axisMovingHandleDict = IConfig.AxisSettings.ToDictionary(a => a.AxisIndex, a => new AutoResetEvent(true));
+            InitialMotionCard();
             axisImmediatePauseHandleDict = IConfig.AxisSettings.ToDictionary(a => a.AxisIndex, a => new ManualResetEvent(true));
             axisMoveCancelDict = IConfig.AxisSettings.ToDictionary(a => a.AxisIndex, a => new CancellationTokenSource());
 
@@ -88,261 +66,445 @@
             {
                 c = new CancellationTokenSource();
             });
-
-            _commandAxisList.CollectionChanged -= CommandAxisList_CollectionChanged;
-            _commandAxisList.CollectionChanged += CommandAxisList_CollectionChanged;
         }
 
-        private void CommandAxisList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
-        {
-            CommandAxisCountChangedAction?.Invoke(_commandAxisList.Count > 0);
-        }
-
+        ManualResetEvent _pauseHandle = new ManualResetEvent(true);
         protected override void Pause()
         {
-            throw new NotImplementedException();
+
         }
 
         protected override void Resume()
         {
-            throw new NotImplementedException();
+
         }
 
         protected override void Start()
         {
-            throw new NotImplementedException();
+            AllAxisOn();
         }
 
         protected override void Stop()
         {
-            throw new NotImplementedException();
+            AllMoveStop();
+            AllAxisOff();
+        }
+
+        /// <summary>
+        /// 璁惧 杩愯锛堟墽琛� 鏉垮崱绯诲垪鐨勬搷浣滅殑 闆嗗悎锛�
+        /// </summary>
+        /// <param name="config"></param>
+        /// <returns></returns>
+        public override ResponseMessage Run(IOperationConfig config)
+        {
+            ResponseMessage responseMessage = new ResponseMessage();
+            if (config is MotionCardOperationConfigBase motionCardOperationConfig)
+            {
+                _pauseHandle.WaitOne();
+                foreach (var operationSet in motionCardOperationConfig.OperationCollection)
+                {
+                    responseMessage = RunOperationSet(operationSet);
+                    if (!responseMessage.Result)
+                    {
+                        return responseMessage;
+                    }
+                }
+            }
+            return responseMessage;
+        }
+
+        /// <summary>
+        /// 鎵ц 涓�涓郴鍒楃殑鎿嶄綔
+        /// </summary>
+        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 鏄紑銆佸叧 浠嶮onitorValues 鑾峰彇
+                        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 鏄紑銆佸叧 浠嶮onitorValues 鑾峰彇
+                    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 鏄紑銆佸叧 浠嶮onitorValues 鑾峰彇
+                        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 ImmediatePause
+        /// <summary>
+        /// 鍚姩绔嬪嵆鏆傚仠
+        /// </summary>
+        public void SetImmediatePause()
+        {
+            if (!_isResetting)
+            {
+                var immediatePauseAxis = IConfig.AxisSettings.Where(u => u.IsImmediatePause).Select(u => u.AxisIndex).ToList();
+
+                immediatePauseAxis.ForEach(async axisIndex =>
+                {
+                    axisImmediatePauseHandleDict[axisIndex].Reset();
+
+                    axisMoveCancelDict[axisIndex].Cancel();
+
+                    await MoveStop(axisIndex, 0);
+                });
+            }
+        }
+
+        /// <summary>
+        /// 鎭㈠绔嬪嵆鏆傚仠
+        /// </summary>
+        public void ResetImmediatePause()
+        {
+            var immediatePauseAxis = IConfig.AxisSettings.Where(u => u.IsImmediatePause).Select(u => u.AxisIndex).ToList();
+
+            immediatePauseAxis.ForEach(axisIndex =>
+            {
+                axisMoveCancelDict[axisIndex] = new CancellationTokenSource();
+
+                axisImmediatePauseHandleDict[axisIndex].Set();
+            });
         }
         #endregion
 
         #region GTSCard
-
-        public void ClearPosition(short cardNum, short axisNum)
-        {
-            int ret = GTSCardAPI.GT_SetPos(cardNum, axisNum, 0);
-        }
 
         /// <summary>
         /// Load Motion Card parameter from file
         /// </summary>
         /// <param name="fileName">Invalid Parameter</param>
         /// <returns></returns>
-        public void InitialMotionCard(short cardNum, string fileName)
+        public void InitialMotionCard()
         {
-            var res = GTSCardAPI.GT_LoadConfig(cardNum, fileName);
-            if (res != GTSCardAPI.ResultSuccess)
+            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<Task<bool>> taskList = new List<Task<bool>>(); ;
+            // 濡傛灉鏄涓酱鐨勮繍鍔� 绛夋瘡涓酱寮�鍚�
+            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<Task<bool>> taskList = new List<Task<bool>>(); ;
+            // 濡傛灉鏄涓酱鐨勮繍鍔� 绛夋瘡涓酱鍏抽棴
+            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;
         }
 
         /// <summary>
-        /// 鍗曚釜杞� 鐐逛綅鍒扮偣浣嶈繍鍔紙寮傛锛�
+        /// 鍗曚釜杞村紑鍚�
         /// </summary>
-        /// <param name="item">杩愬姩瀵硅薄</param>
         /// <returns></returns>
-        public async Task SingleAxisMovingAsync(MovingOption item)
+        public async Task<bool> AxisOnAsync(short cardNum, short axisNum)
         {
-            await Task.Run(() =>
+            return await Task.Run(() =>
             {
-                SingleAxisMoving(item);
+                var ret = GTSCardAPI.GT_AxisOn(cardNum, axisNum);
+                return ret == (short)GTSRetCode.GRCRunOK;
             });
         }
 
         /// <summary>
-        /// 鍗曚釜杞� 鐐逛綅鍒扮偣浣嶈繍鍔紙寮傛锛�
+        /// 鍗曚釜杞村叧闂�
+        /// </summary>
+        /// <returns></returns>
+        public async Task<bool> AxisOffAsync(short cardNum, short axisNum)
+        {
+            return await Task.Run(() =>
+            {
+                var ret = GTSCardAPI.GT_AxisOff(cardNum, axisNum);
+                return ret == (short)GTSRetCode.GRCRunOK;
+            });
+        }
+
+        /// <summary>
+        /// 鐐逛綅鍒扮偣浣嶈繍鍔�
         /// </summary>
         /// <param name="item">杩愬姩瀵硅薄</param>
-        public void SingleAxisMoving(MovingOption item)
+        /// <returns>杩愬姩鎺у埗+鍋滄鍒ゆ柇</returns>
+        public override ResponseMessage MoveToPoint(IOperationConfig opConfig)
         {
-            if (IConfig.AxisSettings.FirstOrDefault(a => a.AxisIndex == item.AxisIndex)?.IsAxisEnabled ?? false)
+            ResponseMessage responseMessage = new ResponseMessage();
+            if (opConfig is MotionOperationCollection gtsOperationCollection)
             {
-                axisImmediatePauseHandleDict[item.AxisIndex].WaitOne();
-                VelocityPara vel = new VelocityPara();
-                if (item.VelocityPara.Velocity != 0)
+                _pauseHandle.WaitOne();
+                List<Task<bool>> taskList = new List<Task<bool>>();
+                foreach (var movingOp in gtsOperationCollection.MovingOps)
                 {
-                    velIndexDict[item.AxisIndex] = vel = item.VelocityPara;
-                }
-                else
-                {
-                    vel = velIndexDict[item.AxisIndex];
+                    var task = SingleAxisMoving(movingOp);
+                    taskList.Add(task);
                 }
 
-                string _position = "";
-                string motionType = item.MoveMode == EnumHelper.MotorMoveMode.Normal ? (item.IsAbsolute ? "Abs" : "Rel") : item.MoveMode.ToString();
-
-                _position = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")},{item.AxisIndex},{motionType},{GetCmdOrPosition(item.AxisIndex, 0).ToString()},{GetCmdOrPosition(item.AxisIndex, 1).ToString()},{item.Destination},";
-
-                lock (axisMoveLockDict[item.AxisIndex])
+                Task.WaitAll(taskList.ToArray());
+                responseMessage.Result = taskList.All(u => u.GetAwaiter().GetResult());
+                if (!responseMessage.Result)
                 {
-                    Task.Run(() =>
-                    {
-                        lock (_commandAxisLock)
-                        {
-                            try
-                            {
-                                if (!_commandAxisList.Contains(item.AxisIndex))
-                                {
-                                    _commandAxisList.Add(item.AxisIndex);
-                                }
-                            }
-                            catch (Exception)
-                            {
-                            }
-                        }
-                    });
-
-                    switch (item.MoveMode)
-                    {
-                        case EnumHelper.MotorMoveMode.Normal:
-                            {
-                                if (_isResetting)
-                                {
-                                    LogAsync(DateTime.Now, "澶嶄綅涓惎鍔ㄨ繍鍔ㄥ紓甯�", item.AxisIndex + "鍚姩杩愬姩寮傚父");
-                                    return;
-                                }
-
-                                SetAxisParam(item.AxisIndex, vel);
-                                if (item.IsAbsolute)
-                                {
-                                    MoveAbs(item.AxisIndex, item.Destination, (int)(vel.Velocity * IConfig.AxisVelocityRatio));
-                                }
-                                else
-                                {
-                                    MoveRel(item.AxisIndex, item.Destination, (int)(vel.Velocity * IConfig.AxisVelocityRatio));
-                                }
-                            }
-                            break;
-                        case EnumHelper.MotorMoveMode.FindOri:
-                            {
-                                AxisSetting setting = IConfig.AxisSettings.FirstOrDefault(u => u.AxisIndex == item.AxisIndex);
-                                StartHoming(item.AxisIndex, setting.HomeMode, setting.IsHomePositive ? 1 : 0, item.VelocityPara.Dec, item.VelocityPara.Acc, item.VelocityPara.Velocity);
-                            }
-                            break;
-                    }
-
-                    Task.Run(() =>
-                    {
-                        lock (_commandAxisLock)
-                        {
-                            try
-                            {
-                                _commandAxisList.Remove(item.AxisIndex);
-                            }
-                            catch (Exception)
-                            {
-                            }
-                        }
-                    });
+                    responseMessage.Message = $"鐐逛綅杩愬姩寮傚父";
                 }
-
-                _position += $"{GetCmdOrPosition(item.AxisIndex, 0).ToString()},";
-                _position += $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}";
-                LogAsync(DateTime.Now, "", _position);
             }
-        }
-
-        public int GetCmdOrPosition(int axisNum, int flag = 0)
-        {
-            int position = 0;
-
-            if (flag == 0)
-            {
-                GetPosition(axisNum, ref position);
-            }
-            else
-            {
-                GetCmdPosition(axisNum, ref position);
-            }
-
-            return position;
+            return responseMessage;
         }
 
         /// <summary>
-        ///Get single Axis Feedback position 
+        /// 鐐瑰埌鐐硅繍鍔ㄨ缃弬鏁�
         /// </summary>
-        /// <param name="axisNum">Axis number</param>
-        /// <param name="nPosition">Feedback/Encorde position </param>
+        /// <param name="optionPara">杩愬姩鍙傛暟瀵硅薄</param>
         /// <returns></returns>
-        public void GetPosition(int axisNum, ref int nPosition)
+        private bool SetAxisParam(MovingOption optionPara)
         {
-            lock (lockObj)
-            {
-                double prfpos = 0; uint pclock = 0;
-                var ret = GTSCardAPI.GT_GetPrfPos((short)IConfig.CardNum, (short)axisNum, out prfpos, 1, out pclock);
-                if (ret != GTSCardAPI.ResultSuccess)
-                {
-                    throw new Exception("杞�" + axisNum + "鑾峰彇褰撳墠浣嶇疆寮傚父锛岄敊璇爜锛�" + ret);
-                }
-                nPosition = prfpos / IConfig.AxisVelocityRatio;
-            }
-        }
-
-        public int GetPosition(int axisNum)
-        {
-            int position = 0;
-
-            if (!IConfig.AxisSettings.FirstOrDefault(u => u.AxisIndex == axisNum).IsUseCmmdPosition)
-            {
-                GetPosition(axisNum, ref position);
-            }
-            else
-            {
-                GetCmdPosition(axisNum, ref position);
-            }
-
-            return position;
-        }
-
-        /// <summary>
-        ///Get single Axis Command position 
-        /// </summary>
-        /// <param name="axisNum">Axis number</param>
-        /// <param name="nPosition">Command position </param>
-        /// <returns></returns>
-        public void GetCmdPosition(int axisNum, ref int nPosition)
-        {
-            var ret = GTSCardAPI.APS_get_command(axisNum, ref nPosition);
-            if (ret != (Int32)GTSCardParameter.ResultSuccess)
-            {
-                throw new Exception("杞�" + axisNum + "鑾峰彇褰撳墠浣嶇疆寮傚父锛岄敊璇爜锛�" + ret);
-            }
-            nPosition = prfpos / IConfig.AxisVelocityRatio;
-        }
-
-        /// <summary>
-        /// Set AxisParam
-        /// </summary>
-        /// <param name="axisNo"></param>
-        /// <param name="param"></param>
-        /// <returns></returns>
-        public void SetAxisParam(int axisNum, VelocityPara param)
-        {
-            int ret = 0;
-            GTSCardAPI.TTrapPrm trapprm;
-            GTSCardAPI.GT_PrfTrap((short)IConfig.CardNum, (short)axisNum);
-            GTSCardAPI.GT_GetTrapPrm((short)IConfig.CardNum, (short)axisNum, out trapprm);
+            List<short> resultCode = new List<short>() { 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;
-            if (param.Acc != 0)
-            {
-                trapprm.acc = param.Acc;
-            }
-            if (param.Dec != 0)
-            {
-                trapprm.dec = param.Dec;
-            }
-            ret += GTSCardAPI.GT_SetTrapPrm((short)IConfig.CardNum, (short)axisNum, ref trapprm);
-            ret += GTSCardAPI.GT_SetVel((short)IConfig.CardNum, (short)axisNum, param.Velocity * IConfig.AxisVelocityRatio);
+            trapprm.acc = optionPara.VelocityPara.Acc != 0 ? optionPara.VelocityPara.Acc : 1;
+            trapprm.dec = optionPara.VelocityPara.Dec != 0 ? optionPara.VelocityPara.Dec : 1;
 
-            if (ret != (int)APS_Define.ResultSuccess)
+            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("杞�" + axisNum + "璁剧疆鍙傛暟寮傚父锛岄敊璇爜锛�" + ret);
+                throw new Exception("杞�" + optionPara.AxisIndex + "璁剧疆鍙傛暟寮傚父锛岄敊璇爜锛�" + string.Join(",", resultCode));
             }
+            return resultOK;
+        }
+
+        /// <summary>
+        /// 鍗曚釜杞� 杩愬姩(鐐瑰埌鐐� jog 鍥為浂...锛�
+        /// </summary>
+        /// <param name="optionPara">杩愬姩鍙傛暟瀵硅薄</param>
+        public async Task<bool> SingleAxisMoving(MovingOption optionPara)
+        {
+            return await Task.Run(() =>
+            {
+                bool isSuccessAndStop = false;
+                try
+                {
+                    if (IConfig.AxisSettings.FirstOrDefault(a => a.AxisIndex == optionPara.AxisIndex)?.IsAxisEnabled ?? false)
+                    {
+                        axisImmediatePauseHandleDict[optionPara.AxisIndex].WaitOne();
+
+                        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;
+            });
+        }
+
+        /// <summary>
+        /// 鑾峰彇瑙勫垝浣嶇疆锛堣鍘荤殑浣嶇疆锛�
+        /// </summary>
+        /// <param name="axisNum">Axis number</param>
+        /// <returns></returns>
+        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;
+        }
+
+        /// <summary>
+        /// 鑾峰彇鐩墠褰撳墠浣嶇疆
+        /// </summary>
+        /// <param name="axisNum">Axis number</param>
+        /// <returns></returns>
+        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;
+            }
+        }
+
+        /// <summary>
+        /// 鑾峰彇瑙勫垝閫熷害
+        /// </summary>
+        /// <param name="axisNum">Axis number</param>
+        /// <returns></returns>
+        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;
+        }
+
+        /// <summary>
+        /// 鑾峰彇褰撳墠閫熷害
+        /// </summary>
+        /// <param name="axisNum">Axis number</param>
+        /// <returns></returns>
+        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;
         }
 
         /// <summary>
@@ -352,643 +514,302 @@
         /// <param name="nDirection">Motion Direction 0: Negative, 1: Positive</param>
         /// <param name="nMaxVel">max velocity</param>
         /// <returns></returns>
-        public bool StartJog(int axisNum, int nDirection, int velocity)
+        public bool JogMove(MovingOption optionPara)
         {
-            GTSCardAPI.TJogPrm jogprm = new GTSCardAPI.TJogPrm();
-            short rtn = GTSCardAPI.GT_PrfJog((short)IConfig.CardNum, (short)axisNum);
-            jogprm.acc = 1;
-            jogprm.dec = 1;
-            GTSCardAPI.GT_SetJogPrm((short)IConfig.CardNum, (short)axisNum, ref jogprm);//璁剧疆jog杩愬姩鍙傛暟
-            GTSCardAPI.GT_SetVel((short)IConfig.CardNum, (short)axisNum, velocity);//璁剧疆鐩爣閫熷害
-            int ret = GTSCardAPI.GT_Update((short)IConfig.CardNum, 1 << (axisNum - 1));//鏇存柊杞磋繍鍔�
-
-            if (ret != (int)APS_Define.ResultSuccess)
+            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 + "JogMove寮傚父", "閿欒鐮侊細" + 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;
             }
-            return true;
         }
 
         /// <summary>
-        /// Set Single Axis Do stop Jog Move  
-        /// </summary>
-        /// <param name="axisNum">AxisNo</param>
-        /// <returns></returns>
-        public bool StopJog(int axisNum)
-        {
-            MoveStop();
-            return IsStop((short)IConfig.CardNum, (short)axisNum);
-        }
-
-        /// <summary>
-        /// Set Single Axis Do Rel Move  
+        /// 鐩稿浣嶇疆杩愬姩 
         /// </summary>
         /// <param name="axisNum">AxisNo</param>
         /// <param name="nDistance">run distance</param>
         /// <returns></returns>
-        public void MoveRel(int axisNum, int nDistance, int nMaxVel)
+        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, "鏉垮崱寮傚父鐘舵��", "杞�" + axisNum + "璇曞浘寮傚父鐘舵�佽繍鍔�");
-                    return;
+                    LogAsync(DateTime.Now, "鏉垮崱寮傚父鐘舵��", "杞�" + optionPara.AxisIndex + "璇曞浘寮傚父鐘舵�佽繍鍔�");
+                    return false;
                 }
 
                 if (CurrentState != EnumHelper.DeviceState.DSOpen)
                 {
-                    return;
+                    LogAsync(DateTime.Now, "闈炴甯哥姸鎬佸紓甯�", "杞�" + optionPara.AxisIndex + "璇曞浘鍦ㄩ潪姝e父鐘舵�佽繍鍔�");
+                    throw new Exception("杞�" + optionPara.AxisIndex + "璇曞浘鍦ㄩ潪姝e父鐘舵�佽繍鍔�", null);
                 }
 
-                int currentPosition = GetPosition(axisNum);
-
-                if (OnAxisStartToCheckConfliction != null && OnAxisStartToCheckConfliction.Invoke(axisNum, currentPosition, currentPosition + nDistance))
+                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)
                 {
-                    return;
+                    //璁剧疆 杩愬姩鍙傛暟
+                    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;
+                    }
                 }
 
-                int ret = GTSCardAPI.GT_SetPos((short)IConfig.CardNum, (short)axisNum, nDistance * IConfig.AxisVelocityRatio);
-
-                ret += GTSCardAPI.GT_Update((short)IConfig.CardNum, 1 << (axisNum - 1));
-                if (ret != (Int32)APS_Define.ResultSuccess)
+                //杩愬姩寮�濮嬪悗 妫�鏌ヨ繍鍔ㄦ槸鍚﹀仠姝�
+                bool isStop = false;
+                repeatTime = 1000;
+                do
                 {
-                    throw new Exception("杞�" + axisNum + "鍚姩鐩稿杩愬姩寮傚父锛岄敊璇爜锛�" + ret);
-                }
+                    isStop = IsStop((short)optionPara.AxisIndex);
+                    Thread.Sleep(50);
+                    repeatTime--;
+                } while (!isStop && repeatTime > 0);
 
-                RunFinish(axisNum, false);
+                return (ret == (short)GTSRetCode.GRCRunOK) && isStop;
             }
             catch (Exception ex)
             {
-                MoveStop();
+                AllMoveStop(true);
                 OnExceptionRaised?.Invoke(ex);
+                return false;
             }
         }
 
         /// <summary>
-        ///  Set Single Axis Do Absolute Move  
+        ///  缁濆浣嶇疆杩愬姩
         /// </summary>
-        /// <param name="axisNum">AxisNo</param>
-        /// <param name="nDistance">run distance</param>
-        /// <param name="nMaxVel">max velocity</param>
-        /// <returns></returns>
-        public void MoveAbs(int axisNum, int nPosition, int nMaxVel)
+        /// <param name="optionPara">杩愬姩鍙傛暟瀵硅薄</param>
+        public bool P2PMoveAbs(MovingOption optionPara)
         {
             try
             {
-            ReMove:
-                MoveAbsAsync(axisNum, nPosition);
+                axisImmediatePauseHandleDict[optionPara.AxisIndex].WaitOne();
 
-                var runFinish = Task.Run(() => RunFinish(axisNum), axisMoveCancelDict[axisNum].Token);
-                try
+                if (_isResetting)
                 {
-                    runFinish.Wait(axisMoveCancelDict[axisNum].Token);
+                    LogAsync(DateTime.Now, "澶嶄綅杩囩▼寮傚父", "杞�" + optionPara.AxisIndex + "璇曞浘鍦ㄥ浣嶈繃绋嬩腑杩愬姩");
+                    throw new Exception("杞�" + optionPara.AxisIndex + "璇曞浘鍦ㄥ浣嶈繃绋嬩腑杩愬姩");
                 }
-                catch (OperationCanceledException ex)
+                int repeatTime = 30;
+                while (CurrentState != EnumHelper.DeviceState.DSOpen && repeatTime > 0)
                 {
-                    goto ReMove;
+                    Thread.Sleep(10);
+                    repeatTime--;
+                }
+                if (CurrentState == EnumHelper.DeviceState.DSExcept)
+                {
+                    LogAsync(DateTime.Now, "鏉垮崱寮傚父鐘舵��", "杞�" + optionPara.AxisIndex + "璇曞浘寮傚父鐘舵�佽繍鍔�");
+                    return false;
                 }
 
-                //// 鍒犻櫎璁板綍
-                //if (currentCommandDic.ContainsKey(axisNum))
-                //{
-                //    currentCommandDic.TryRemove(axisNum, out int[] temp);
-                //}
+                if (CurrentState != EnumHelper.DeviceState.DSOpen)
+                {
+                    LogAsync(DateTime.Now, "闈炴甯哥姸鎬佸紓甯�", "杞�" + optionPara.AxisIndex + "璇曞浘鍦ㄩ潪姝e父鐘舵�佽繍鍔�");
+                    throw new Exception("杞�" + optionPara.AxisIndex + "璇曞浘鍦ㄩ潪姝e父鐘舵�佽繍鍔�", 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)optionPara.AxisIndex);
+                    Thread.Sleep(50);
+                    repeatTime--;
+                } while (!isStop && repeatTime > 0);
+
+                return (ret == (short)GTSRetCode.GRCRunOK) && isStop;
             }
             catch (Exception ex)
             {
-                MoveStop();
+                AllMoveStop(true);
                 OnExceptionRaised?.Invoke(ex);
-            }
-        }
-
-        static object moveLock = new object();
-
-        /// <summary>
-        /// 缁濆杩愬姩锛堝紓姝ワ級
-        /// </summary>
-        /// <param name="axisNum"></param>
-        /// <param name="nPosition"></param>
-        public void MoveAbsAsync(int axisNum, int nPosition)
-        {
-            try
-            {
-                lock (moveLock)
-                {
-                    axisImmediatePauseHandleDict[axisNum].WaitOne();
-                    _pauseHandle.WaitOne();
-
-                    int currentPosition = GetPosition(axisNum);
-                    if (OnAxisStartToCheckConfliction != null && OnAxisStartToCheckConfliction.Invoke(axisNum, currentPosition, nPosition))
-                    {
-                        return;
-                    }
-
-                    if (_isResetting)
-                    {
-                        LogAsync(DateTime.Now, "澶嶄綅杩囩▼寮傚父", "杞�" + axisNum + "璇曞浘鍦ㄥ浣嶈繃绋嬩腑杩愬姩");
-                        throw new Exception("杞�" + axisNum + "璇曞浘鍦ㄥ浣嶈繃绋嬩腑杩愬姩");
-                    }
-
-                    int repeatTime = 30;
-                    while (CurrentState != EnumHelper.DeviceState.DSOpen && repeatTime > 0)
-                    {
-                        Thread.Sleep(10);
-                        repeatTime--;
-                    }
-
-                    if (CurrentState == EnumHelper.DeviceState.DSExcept)
-                    {
-                        LogAsync(DateTime.Now, "鏉垮崱寮傚父鐘舵��", "杞�" + axisNum + "璇曞浘寮傚父鐘舵�佽繍鍔�");
-                        return;
-                    }
-
-                    if (CurrentState != EnumHelper.DeviceState.DSOpen)
-                    {
-                        LogAsync(DateTime.Now, "闈炴甯哥姸鎬佸紓甯�", "杞�" + axisNum + "璇曞浘鍦ㄩ潪姝e父鐘舵�佽繍鍔�");
-                        throw new Exception("杞�" + axisNum + "璇曞浘鍦ㄩ潪姝e父鐘舵�佽繍鍔�", null);
-                    }
-
-                    int ret = 0;
-                    repeatTime = 50;
-                    do
-                    {
-                        LogAsync(DateTime.Now, "杞�" + axisNum + "鍚姩杩愬姩", "鐩爣鍧愭爣锛�" + nPosition);
-                        ret = GTSCardAPI.GT_SetPos((short)IConfig.CardNum, (short)axisNum, nPosition * IConfig.AxisVelocityRatio);
-
-                        ret += GTSCardAPI.GT_Update((short)IConfig.CardNum, 1 << (axisNum - 1));
-                        if (ret != (Int32)APS_Define.ResultSuccess)
-                        {
-                            LogAsync(DateTime.Now, "杞�" + axisNum + "APS_absolute_move寮傚父", "杩斿洖鍊硷細" + ret + "锛涢噸璇曟鏁帮細" + repeatTime);
-                            Thread.Sleep(50);
-                        }
-                        repeatTime--;
-                    } while (ret != (Int32)APS_Define.ResultSuccess && repeatTime > 0);
-
-                    if (ret != (Int32)APS_Define.ResultSuccess)
-                    {
-                        LogAsync(DateTime.Now, "杞�" + axisNum + "鍚姩缁濆杩愬姩寮傚父", "閿欒鐮侊細" + ret);
-                        throw new Exception("杞�" + axisNum + "鍚姩缁濆杩愬姩寮傚父锛岄敊璇爜锛�" + ret);
-                    }
-                }
-            }
-            catch (Exception ex)
-            {
-                MoveStop();
-                OnExceptionRaised?.Invoke(ex);
-            }
-        }
-
-        Dictionary<int, AxisMovingStay> _axisStayDict = new Dictionary<int, AxisMovingStay>();
-
-        private async void MoveAbsStay(int axisNum)
-        {
-            await Task.Run(() =>
-            {
-                while (CurrentState != EnumHelper.DeviceState.DSClose)
-                {
-                    if (!_axisStayDict.ContainsKey(axisNum))
-                    {
-                        _axisStayDict[axisNum] = new AxisMovingStay();
-                    }
-
-                    _axisStayDict[axisNum].MoveHandle.WaitOne();
-                    MoveAbsAsync(axisNum, _axisStayDict[axisNum].Position);
-                    _axisStayDict[axisNum].MoveSendHandle.Set();
-                }
-            });
-        }
-
-        /// <summary>
-        /// 鍔ㄤ綔缁撴潫
-        /// </summary>
-        /// <param name="axisNum"></param>
-        /// <returns></returns>
-        public void RunFinish(int axisNum, bool isAbs = true)
-        {
-            MOTION_IO_STATUS MotionIoSts = new MOTION_IO_STATUS();
-            MOTION_BOOL_STATUS MotionSts = new MOTION_BOOL_STATUS();
-            var axisSetting = IConfig.AxisSettings.FirstOrDefault(a => a.AxisIndex == axisNum);
-            int startTime = System.Environment.TickCount;
-
-            //MDN淇″彿
-            if (axisSetting.IsUseMDNStopSignal)
-            {
-                while (GetMotionIoStatus(axisNum, ref MotionIoSts) && GetMotionStatus(axisNum, ref MotionSts))
-                {
-                    if (MotionIoSts.EMG)
-                    {
-                        LogAsync(DateTime.Now, "杞�" + axisNum + "鎬ュ仠", "");
-                        throw new Exception("杞�" + axisNum + "鎬ュ仠");
-                    }
-
-                    if (MotionSts.MDN)
-                    {
-                        int stopCode = -1;
-                        APS168.APS_get_stop_code(axisNum, ref stopCode);
-
-                        LogAsync(DateTime.Now, "杞�" + axisNum + "StopCode锛�", stopCode.ToString());
-
-                        //0 姝e父鍋滄 4 姝f瀬闄� 5 璐熸瀬闄�
-                        if (new List<int>() { 0, 4, 5 }.Contains(stopCode))
-                        {
-                            if (new List<int>() { 4, 5 }.Contains(stopCode) && axisSetting.IsUseWarning)
-                            {
-                                MoveStop(true);
-                                OnExceptionRaised?.Invoke(new Exception("杞�" + axisNum + "杩愬姩鑷虫瀬闄愪綅缃紝stopCode锛�" + stopCode.ToString(), null));
-                                return;
-                            }
-                            if (IConfig.ActionAfterDelay > 0)
-                            {
-                                Thread.Sleep(IConfig.ActionAfterDelay);
-                            }
-
-                            int feedBack = 0;
-                            GetPosition(axisNum, ref feedBack);
-                            LogAsync(DateTime.Now, "杞�" + axisNum + "杩愬姩缁撴潫", "褰撳墠浣嶇疆锛�" + feedBack);
-                            break;
-                        }
-                    }
-
-                }
-            }
-            else    //INP淇″彿
-            {
-                while (GetMotionIoStatus(axisNum, ref MotionIoSts) && GetMotionStatus(axisNum, ref MotionSts))
-                {
-                    if (MotionIoSts.EMG)
-                    {
-                        LogAsync(DateTime.Now, "杞�" + axisNum + "鎬ュ仠", "");
-                        throw new Exception("杞�" + axisNum + "鎬ュ仠");
-                    }
-
-
-                    if (MotionSts.MDN && MotionIoSts.INP)
-                    {
-                        int stopCode = -1;
-                        APS168.APS_get_stop_code(axisNum, ref stopCode);
-
-                        LogAsync(DateTime.Now, "杞�" + axisNum + "StopCode锛�", stopCode.ToString());
-
-                        //0 姝e父鍋滄 4 姝f瀬闄� 5 璐熸瀬闄�
-                        if (new List<int>() { 0, 4, 5 }.Contains(stopCode))
-                        {
-                            if (new List<int>() { 4, 5 }.Contains(stopCode) && axisSetting.IsUseWarning)
-                            {
-                                MoveStop(true);
-                                OnExceptionRaised?.Invoke(new AMPRunException("杞�" + axisNum + "杩愬姩鑷虫瀬闄愪綅缃紝stopCode锛�" + stopCode.ToString(), null));
-                                return;
-                            }
-
-                            if (IConfig.ActionAfterDelay > 0)
-                            {
-                                Thread.Sleep(IConfig.ActionAfterDelay);
-                            }
-
-                            int feedBack = 0;
-                            GetPosition(axisNum, ref feedBack);
-                            LogAsync(DateTime.Now, "杞�" + axisNum + "杩愬姩缁撴潫", "褰撳墠浣嶇疆锛�" + feedBack);
-                            break;
-                        }
-                    }
-
-                }
+                return false;
             }
         }
 
         /// <summary>
-        /// Stop single axis move 
+        /// 鏌愪釜杞磋繍鍔ㄥ仠姝�
         /// </summary>
         /// <param name="axisNum">axisNo</param>
         /// <param name="option">0琛ㄧず骞虫粦鍋滄锛�1琛ㄧず绱ф�ュ仠姝�</param>
         /// <returns></returns>
-        public void MoveStop(int axisNum, int option)
+        public async Task<bool> MoveStop(int axisNum, int option)
         {
-            int ret = GTSCardAPI.GT_Stop((short)IConfig.CardNum, 1 << (axisNum - 1), option);
-            if (ret != (Int32)APS_Define.ResultSuccess)
+            return await Task.Run(() =>
             {
-                LogAsync(DateTime.Now, "杞�" + axisNum + "杩愬姩鍋滄寮傚父", "閿欒鐮侊細" + ret);
-                throw new Exception("杞�" + axisNum + "杩愬姩鍋滄寮傚父锛岄敊璇爜锛�" + ret);
-            }
-            else
-            {
-                LogAsync(DateTime.Now, "杞�" + axisNum + "杩愬姩鍋滄", "");
-            }
-        }
-
-        static object motionIOLock = new object();
-        /// <summary>
-        /// Get single Axis  Motion_Io status and motion status
-        /// </summary>
-        /// <param name="nAxis"></param>
-        /// <param name="nMotionSts"></param>
-        /// <returns></returns>
-        public bool GetMotionStatus(int nAxis, ref MOTION_BOOL_STATUS strcMotionSts)
-        {
-            lock (motionIOLock)
-            {
-                int nMotionSts = 0;
-                nMotionSts = APS168.APS_motion_status(nAxis);
-                if (nMotionSts < 0)
+                bool isStop = false;
+                if (option == 1)
                 {
-                    return false;
+                    StateChange(EnumHelper.DeviceState.DSExcept);
                 }
-                strcMotionSts.ASTP = Convert.ToBoolean(nMotionSts & (1 << (int)MOTION_STATUS.ASTP));
-                strcMotionSts.HMV = Convert.ToBoolean(nMotionSts & (1 << (int)MOTION_STATUS.HMV));
-                strcMotionSts.MDN = Convert.ToBoolean(nMotionSts & (1 << (int)MOTION_STATUS.MDN));
-                strcMotionSts.DIR = Convert.ToBoolean(nMotionSts & (1 << (int)MOTION_STATUS.DIR));
-            }
-            return true;
-        }
-
-        /// <summary>
-        /// Get single Axis  Motion_Io status and motion status
-        /// </summary>
-        /// <param name="nAxis"></param>
-        /// <param name="nMotionIoSts"></param>
-        /// <returns></returns>
-        public bool GetMotionIoStatus(int nAxis, ref MOTION_IO_STATUS strcMotionIoSts)
-        {
-            lock (motionIOLock)
-            {
-                //Thread.Sleep(15);
-                int nMotionIoSts = 0;
-                nMotionIoSts = APS168.APS_motion_io_status(nAxis);
-                if (nMotionIoSts < 0)
+                var ret = GTSCardAPI.GT_Stop((short)IConfig.CardNum, 1 << (axisNum - 1), option);
+                if (ret != (short)GTSRetCode.GRCRunOK)
                 {
-                    return false;
+                    LogAsync(DateTime.Now, "杞�" + axisNum + "杩愬姩鍋滄寮傚父", "閿欒鐮侊細" + ret);
+                    throw new Exception("杞�" + axisNum + "杩愬姩鍋滄寮傚父锛岄敊璇爜锛�" + ret);
                 }
-
-                bool isAlarm = Convert.ToBoolean(nMotionIoSts & (1 << (int)MOTION_IOSTATUS.ALM));
-                if (strcMotionIoSts.ALM != isAlarm)
+                else
                 {
-                    strcMotionIoSts.ALM = isAlarm;
-                    OnMotionAlarm?.Invoke(nAxis, isAlarm);
+                    LogAsync(DateTime.Now, "杞�" + axisNum + "杩愬姩鍋滄", "");
                 }
+                int repeatTime = 100;
+                do
+                {
+                    isStop = IsStop((short)axisNum);
+                    Thread.Sleep(10);
+                    repeatTime--;
+                } while (!isStop && repeatTime > 0);
 
-                strcMotionIoSts.PEL = Convert.ToBoolean(nMotionIoSts & (1 << (int)MOTION_IOSTATUS.PEL));
-                strcMotionIoSts.MEL = Convert.ToBoolean(nMotionIoSts & (1 << (int)MOTION_IOSTATUS.MEL));
-                strcMotionIoSts.ORG = Convert.ToBoolean(nMotionIoSts & (1 << (int)MOTION_IOSTATUS.ORG));
-                strcMotionIoSts.EMG = Convert.ToBoolean(nMotionIoSts & (1 << (int)MOTION_IOSTATUS.EMG));
-                strcMotionIoSts.INP = Convert.ToBoolean(nMotionIoSts & (1 << (int)MOTION_IOSTATUS.INP));
-                strcMotionIoSts.SVON = Convert.ToBoolean(nMotionIoSts & (1 << (int)MOTION_IOSTATUS.SVON));
-            }
-            return true;
-        }
-
-        public void MoveStop(bool emergencyStop = false)
-        {
-            int option = 0;
-            if (emergencyStop)
-            {
-                option = 1;
-                StateChange(EnumHelper.DeviceState.DSExcept);
-            }
-
-            IConfig.AxisSettings.Where(a => a.IsAxisEnabled).ToList().ForEach(axisNum =>
-            {
-                MoveStop(axisNum.AxisIndex, option);
+                return (ret == (short)GTSRetCode.GRCRunOK) && isStop;
             });
         }
 
         /// <summary>
+        /// 鎵�鏈夊紑鍚殑杞村仠姝�
+        /// </summary>
+        /// <param name="emergencyStop"></param>
+        public void AllMoveStop(bool emergencyStop = false)
+        {
+            int option = emergencyStop ? 1 : 0;
+            List<Task<bool>> taskList = new List<Task<bool>>(); ;
+            // 濡傛灉鏄涓酱鐨勮繍鍔� 绛夋瘡涓酱杩愬姩缁撴潫
+            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());
+        }
+
+        /// <summary>
         /// 鍥炲師鐐�
         /// </summary>
-        /// <param name="cardn">鍗″彿</param>
+        /// <param name="movingOption">鍗″彿</param>
         /// <param name="axisn">杞村彿</param>
         /// <param name="homests">杞村洖鍘熺偣鐘舵��</param>
-        public bool GoHome(short cardn, short axisn, short home_mode, short home_dir, int homeoffset)
+        public bool GoHome(MovingOption movingOption)
         {
             try
             {
-                GTSCardAPI.GT_ZeroPos(cardn, axisn, 1);
+                GTSCardAPI.GT_ZeroPos((short)IConfig.CardNum, (short)movingOption.AxisIndex, 1);
                 GTSCardAPI.THomePrm thomeprm;
                 GTSCardAPI.THomeStatus homests;
-                short rtn = GTSCardAPI.GT_GetHomePrm(cardn, axisn, out thomeprm);
-                thomeprm.mode = home_mode;//鍥為浂鏂瑰紡
-                thomeprm.moveDir = home_dir;//鍥為浂鏂瑰悜
-                thomeprm.edge = 0;
-                thomeprm.velHigh = 50;
-                thomeprm.velLow = 50;
-                thomeprm.acc = 50;
-                thomeprm.dec = 50;
-                thomeprm.searchHomeDistance = 9999999;//鎼滄悳璺濈
-                thomeprm.homeOffset = 0;  //鍋忕Щ璺濈
-                thomeprm.escapeStep = 1000;
-                rtn = GTSCardAPI.GT_GoHome(cardn, axisn, ref thomeprm);  //鍚姩鍥為浂
+                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);  //鍚姩鍥為浂
 
-                while (true)
+                bool isStop = false;
+                int repeatTime = 1000;
+                do
                 {
-                    Thread.Sleep(5);
-                    GTSCardAPI.GT_GetHomeStatus(cardn, axisn, out homests);
-                    if (homests.run == 0)
+                    Thread.Sleep(10);
+                    GTSCardAPI.GT_GetHomeStatus((short)IConfig.CardNum, (short)movingOption.AxisIndex, out homests);
+
+                    isStop = homests.run == 0;
+                    if (isStop && homests.error == 0)
                     {
-                        if (homests.error == 0)
-                        {
-                            Thread.Sleep(200);
-                            GTSCardAPI.GT_ZeroPos(cardn, axisn, 1);
-                        }
-                        return true;
+                        Thread.Sleep(200);
+                        GTSCardAPI.GT_ZeroPos((short)IConfig.CardNum, (short)movingOption.AxisIndex, 1);
                     }
-                }
+                    repeatTime--;
+                } while (!isStop && repeatTime > 0);
+
+                return isStop;
             }
             catch (Exception ex)
             {
-                MoveStop();
+                AllMoveStop(true);
                 OnExceptionRaised?.Invoke(ex);
                 return false;
             }
         }
 
         /// <summary>
-        /// 鍥炲師鐐�
-        /// </summary>
-        /// <param name="axisId"></param>
-        public void StartHoming(int axisId)
-        {
-            try
-            {
-                //servo on
-                APS168.APS_set_servo_on(axisId, 1);
-                Thread.Sleep(500); // Wait stable.
-
-                // 2. Start home move
-                APS168.APS_home_move(axisId);
-
-                WaitHomeFinish(axisId);
-
-                axisDestination[axisId] = 0;
-            }
-            catch (Exception ex)
-            {
-                MoveStop();
-                OnExceptionRaised?.Invoke(ex);
-            }
-        }
-
-        /// <summary>
-        /// 鍥炲師鐐�
-        /// </summary>
-        /// <param name="axisId"></param>
-        /// <param name="homeMode"></param>
-        /// <param name="homeDir"></param>
-        /// <param name="praCurve"></param>
-        /// <param name="praAcc"></param>
-        /// <param name="praVm"></param>
-        public void StartHoming(int axisId, int homeMode, int homeDir, double praCurve, double praAcc, double praVm)
-        {
-            // 1. Select home mode and config home parameters 
-            APS168.APS_set_axis_param(axisId, (Int32)APS_Define.PRA_HOME_MODE, homeMode); // Set home mode
-            APS168.APS_set_axis_param(axisId, (Int32)APS_Define.PRA_HOME_DIR, homeDir); // Set home direction
-            APS168.APS_set_axis_param_f(axisId, (Int32)APS_Define.PRA_HOME_CURVE, praCurve); // Set acceleration paten (T-curve)
-            APS168.APS_set_axis_param_f(axisId, (Int32)APS_Define.PRA_HOME_ACC, praAcc); // Set homing acceleration rate
-            APS168.APS_set_axis_param_f(axisId, (Int32)APS_Define.PRA_HOME_VM, praVm); // Set homing maximum velocity.
-            APS168.APS_set_axis_param_f(axisId, (Int32)APS_Define.PRA_HOME_VO, praVm / 5); // Set homing VO speed
-            APS168.APS_set_axis_param_f(axisId, (Int32)APS_Define.PRA_HOME_EZA, 0); // Set EZ signal alignment (yes or no)
-            APS168.APS_set_axis_param_f(axisId, (Int32)APS_Define.PRA_HOME_SHIFT, 0); // Set home position shfit distance. 
-            APS168.APS_set_axis_param_f(axisId, (Int32)APS_Define.PRA_HOME_POS, 0); // Set final home position.
-
-            StartHoming(axisId);
-        }
-
-        /// <summary>
-        /// 鍥炲師鐐圭粨鏉�
-        /// </summary>
-        /// <param name="axisNum"></param>
-        /// <returns></returns>
-        public void WaitHomeFinish(int axisNum)
-        {
-            MOTION_IO_STATUS MotionIoSts = new MOTION_IO_STATUS();
-            MOTION_BOOL_STATUS MotionSts = new MOTION_BOOL_STATUS();
-            var axisSetting = IConfig.AxisSettings.FirstOrDefault(a => a.AxisIndex == axisNum);
-            int startTime = System.Environment.TickCount;
-            while ((GetMotionIoStatus(axisNum, ref MotionIoSts)) && (GetMotionStatus(axisNum, ref MotionSts)))
-            {
-                if (MotionIoSts.EMG)
-                {
-                    LogAsync(DateTime.Now, "杞村浣嶄腑" + axisNum + "鎬ュ仠", "");
-                    throw new Exception("杞村浣嶄腑" + axisNum + "鎬ュ仠");
-                }
-
-                if (axisSetting.HomeMode == 0)
-                {
-                    if (!MotionSts.HMV && MotionIoSts.ORG)
-                        break;
-                }
-                else
-                {
-                    if (!MotionSts.HMV)
-                        break;
-                }
-
-                if (axisSetting.TimeOutHome < System.Environment.TickCount - startTime)
-                {
-                    LogAsync(DateTime.Now, "杞村浣嶄腑" + axisNum + "鍥炲師鐐硅秴鏃�", "");
-                    MoveStop(axisNum);
-                    throw new Exception("杞村浣嶄腑" + axisNum + "鍥炲師鐐硅秴鏃�");
-                }
-            }
-
-            //ClearPosition(axisNum);
-        }
-
-        static object _ioLock = new object();
-        /// <summary>
-        /// 璁剧疆IO鍗¤緭鍑�
-        /// </summary>
-        /// <param name="DINo">IO绔彛搴忓彿</param>
-        /// <param name="Value">璁剧疆鍊�(true:楂樼數骞筹紝 false:浣庣數骞�)</param>
-        /// <returns></returns>
-        public bool SetOutput(int DINo, bool Value)
-        {
-            if (OnCheckOutputAllowed?.Invoke(DINo, Value, new Dictionary<int, int>(axisDestination.ToDictionary(u => u.Key, u => u.Value))) ?? false)
-            {
-                OnExceptionRaised?.Invoke(new AMPRunException(DINo + "杈撳嚭" + Value.ToString() + "涓嶈鍏佽", null));
-                return false;
-            }
-
-            int ret = -1;
-            lock (_ioLock)
-            {
-                ret = APS168.APS_write_d_channel_output(0, 0, DINo, Value ? 1 : 0);
-            }
-            if (ret < 0)
-            {
-                return false;
-            }
-            return true;
-        }
-
-        /// <summary>
-        /// 鑾峰彇杈撳叆淇″彿
-        /// </summary>
-        /// <param name="stateType"></param>
-        /// <returns></returns>
-        public bool[] GetInputState()
-        {
-            int diVaule = 0;
-
-            lock (_ioLock)
-            {
-                APS168.APS_read_d_input(0, 0, ref diVaule);
-            }
-            return GetBoolSig(diVaule);
-            //return new bool[16];
-        }
-
-        /// <summary>
-        /// 鑾峰彇杈撳嚭淇″彿
-        /// </summary>
-        /// <param name="stateType"></param>
-        /// <returns></returns>
-        public bool[] GetOutputState()
-        {
-            int doVaule = 0;
-
-            lock (_ioLock)
-            {
-                APS168.APS_read_d_output(0, 0, ref doVaule);
-            }
-
-            return GetBoolSig(doVaule);
-
-        }
-
-        /// <summary>
-        /// 灏嗘棤绗﹀彿鏁村瀷杞崲涓築ool鍨嬫暟缁�
-        /// </summary>
-        /// <param name="sigStr"></param>
-        /// <returns></returns>
-        private bool[] GetBoolSig(int sigStr)
-        {
-            bool[] state = new bool[32];
-
-            for (int i = 0; i < 32; i++)
-            {
-                state[i] = (sigStr & (1 << i)) != 0;
-            }
-            return state;
-        }
-
-        /// <summary>
-        /// 灏哹ool鏁扮粍杞崲鎴愭棤绗﹀彿鏁村瀷
-        /// </summary>
-        /// <param name="sigArray"></param>
-        /// <returns></returns>
-        private int GetintSig(bool[] sigArray)
-        {
-            int state = -1;
-
-            for (int i = 31; i > -1; i--)
-            {
-                state = (state << 1) + (sigArray[i] ? 1 : 0);
-            }
-
-            return state;
-        }
-
-        /// <summary>
-        /// 璇诲彇杈撳叆
+        /// 璇诲彇IO杈撳叆
         /// </summary>
         /// <param name="cardNum">鍗″彿</param>
         /// <param name="index">杈撳叆鍙�</param>
@@ -997,166 +818,329 @@
         {
             int value;
             GTSCardAPI.GT_GetDi(cardNum, GTSCardAPI.MC_GPI, out value);
-            if ((value & 1 << index) == 0) return true;//鏈夎緭鍏ヨ繑鍥瀟rue
+            if ((value & (1 << index)) == 0) return true;//鏈夎緭鍏ヨ繑鍥瀟rue
             else return false;          //鏃犺緭鍏ヨ繑鍥瀎alse
         }
 
         /// <summary>
-        /// 杈撳嚭
+        /// 璇诲彇IO杈撳嚭
         /// </summary>
-        /// <param name="cardNum">鍗″彿</param>
-        /// <param name="index">杈撳嚭鍙�,杩斿洖1-16</param>
-        /// <param name="value">false琛ㄧず杈撳嚭锛宼rue琛ㄧず鍏抽棴</param>
-        public void WriteOut(short cardNum, short index, bool value)
-        {
-            short outNum = (short)(index % 100 + 1);
-            if (value)
-            {
-                GTSCardAPI.GT_SetDoBit(cardNum, GTSCardAPI.MC_GPO, outNum, 0);
-            }
-            else
-            {
-                GTSCardAPI.GT_SetDoBit(cardNum, GTSCardAPI.MC_GPO, outNum, 1);
-            }
-        }
-
-        /// <summary>
-        /// 鍋滄 鏌愪釜杞�
-        /// </summary>
-        /// <param name="cardNum">鍗″彿</param>
-        /// <param name="axisNum">杞村彿</param>
-        /// <param name="option">0琛ㄧず骞虫粦鍋滄锛�1琛ㄧず绱ф�ュ仠姝�</param>
-        public void Stop(short cardNum, short axisNum, short option)
-        {
-            GTSCardAPI.GT_Stop(cardNum, 1 << (axisNum - 1), option);
-        }
-
-        /// <summary>
-        /// 鍋滄 鏌愪釜杞达紙寮傛锛�
-        /// </summary>
-        /// <param name="cardNum">鍗″彿</param>
-        /// <param name="axisNum">杞村彿</param>
-        /// <param name="option">0琛ㄧず骞虫粦鍋滄锛�1琛ㄧず绱ф�ュ仠姝�</param>
-        public async Task StopAsync(short cardNum, short axisNum, short option)
-        {
-            await Task.Run(() =>
-           {
-               GTSCardAPI.GT_Stop(cardNum, 1 << (axisNum - 1), option);
-           });
-        }
-
-        /// <summary>
-        /// 鍋滄 鏌愪釜杞�
-        /// </summary>
-        /// <param name="cardNum"></param>
-        /// <param name="axisNum">杞村彿</param>
-        /// <param name="value">鍋滄鏂瑰紡锛宖alse琛ㄧず骞虫粦鍋滄锛宼rue琛ㄧず绱ф�ュ仠姝�</param>
-        public void Stop(short cardNum, short axisNum, bool emergencyStop)
-        {
-            if (emergencyStop)
-            {
-                GTSCardAPI.GT_Stop(cardNum, 1 << (axisNum - 1), 1 << (axisNum - 1));
-            }
-            else
-            {
-                GTSCardAPI.GT_Stop(cardNum, 1 << (axisNum - 1), 0);
-            }
-        }
-
-        /// <summary>
-        /// 鍋滄 鍏ㄩ儴杞�
-        /// </summary>
-        /// <param name="cardNum"></param>
-        /// <param name="value">鍋滄鏂瑰紡锛宖alse琛ㄧず骞虫粦鍋滄锛宼rue琛ㄧず绱ф�ュ仠姝�</param>
-        public void StopAll(short cardNum, bool value)
-        {
-            for (short i = 1; i <= GTSCardParameter.AxisCount; i++)
-            {
-                Stop(cardNum, i, value);
-            }
-        }
-
-        /// <summary>
-        /// IO杈撳嚭
-        /// </summary>
-        /// <param name="cardNum">鍗″彿</param>
-        /// <param name="mdl">妯″潡鍙�</param>
-        /// <param name="index">IO杈撳嚭</param>
-        /// <param name="value">true琛ㄧず杈撳嚭锛宖alse琛ㄧず鏃犺緭鍑�</param>
-        public void MC_WriteDigitalOutput(short cardNum, short mdl, short index, bool value)
-        {
-            if (value)
-            {
-                GTSCardAPI.GT_SetExtIoBit(cardNum, mdl, index, 0);
-            }
-            else
-            {
-                GTSCardAPI.GT_SetExtIoBit(cardNum, mdl, index, 1);
-            }
-        }
-
-        /// <summary>
-        /// 璇诲彇IO杈撳嚭鐘舵��
-        /// </summary>
-        /// <param name="cardNum"></param>
-        /// <param name="index"></param>
+        /// <param name="index">io绱㈠紩</param>
         /// <returns></returns>
-        public bool GetDoSts(short cardNum, short index)
+        public bool GetDoSts(short index)
         {
-            short outNum = 0;
             int outSts;
-            outNum = (short)(index % 100);
-            GTSCardAPI.GT_GetDo(cardNum, GTSCardAPI.MC_GPO, out 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;
         }
 
-
-
-
         /// <summary>
-        /// 璇诲彇褰撳墠鍊�
+        /// 鎸変綅璁剧疆鏁板瓧 IO 杈撳嚭鐘舵��
         /// </summary>
-        /// <param name="cardNum">鍗″彿</param>
-        /// <param name="axisNum">杞村彿</param>
-        /// <returns>杩斿洖褰撳墠鍊硷紝鍗曚綅姣背</returns>
-        public double GetPosMM(short cardNum, short axisNum)
+        /// <param name="index">杈撳嚭鍙�,杩斿洖1-16</param>
+        /// <param name="value">false琛ㄧず杈撳嚭锛宼rue琛ㄧず鍏抽棴</param>
+        public override void WriteOutput(short index, IOValue value)
         {
-            lock (lockObj)
+            short outNum = (short)(index % 100 + 1);
+            if ((int)value <= 1)
             {
-                double prfpos = 0; uint pclock = 0;
-                GTSCardAPI.GT_GetPrfPos(cardNum, axisNum, out prfpos, 1, out pclock);
-                return prfpos / IConfig.AxisVelocityRatio;
+                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));
             }
         }
 
         /// <summary>
         /// 璇诲彇杞寸姸鎬侊紝鍒ゆ柇鐢垫満鏄惁鍋滄
         /// </summary>
-        /// <param name="cardNum"></param>
-        /// <param name="axisNum"></param>
+        /// <param name="cardNum">鏉垮崱鍙�</param>
+        /// <param name="axisNum">杞村彿</param>
         /// <returns></returns>
-        public bool IsStop(short cardNum, short axisNum)
+        public bool IsStop(short axisNum)
         {
-            lock (lockObj)
+            int sts = GetAxisStatus(axisNum);
+            if ((sts & 0x400) == 0) return true;//鍋滄杩斿洖true
+            else return false;              //杩愯涓繑鍥瀎alse
+        }
+
+        /// <summary>
+        /// 璇诲彇杞寸姸鎬�
+        /// </summary>
+        /// <param name="cardNum">鏉垮崱鍙�</param>
+        /// <param name="axisNum">杞村彿</param>
+        /// <returns></returns>
+        public int GetAxisStatus(int 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;              //杩愯涓繑鍥瀎alse
+                GTSCardAPI.GT_GetSts((short)IConfig.CardNum, (short)axisNum, out sts, 1, out pclock);
+                return sts;
             }
         }
         #endregion
 
-        public void Monitor()
+        #region IMonitor
+
+        public List<AxisMovingStatus> GetAxisMovingStatus()
         {
-            throw new NotImplementedException();
+            List<AxisMovingStatus> axisMovingStatusesList = new List<AxisMovingStatus>();
+            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);
+                axisMovingStatus.AxisStatus = GetAxisStatus(axisMovingStatus.AxisIndex);
+
+                axisMovingStatusesList.Add(axisMovingStatus);
+
+            }
+
+            return axisMovingStatusesList;
         }
 
-        public void ResetAlarm()
+
+        public List<IOItem> GetMonitorValues()
         {
-            throw new NotImplementedException();
+            var result = new List<IOItem>();
+            //璇诲彇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);
+
+            //瑙f瀽缁撴灉
+            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<AxisMovingStatus>(newAxisMovingStatus);
+                        MonitorValues = new List<IOItem>(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();
+            // 灏嗘寚瀹欼OItem鍐欏叆鏉垮崱
+            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<IOItem> tempNew, List<IOItem> 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;
+            var axisSettings = IConfig.AxisSettings.FindAll(u => u.IsAxisEnabled);
+            GTSCardAPI.GT_ClrSts((short)IConfig.CardNum, 1, (short)axisSettings.Count);
+            foreach (var axisSetting in axisSettings)
+            {
+                axis_sts = GetAxisStatus((short)axisSetting.AxisIndex);
+                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);
+                // 姝f瀬闄愭姤璀�
+                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)
+                {
+                    // 姝e悜绉诲姩
+                    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
     }
 }

--
Gitblit v1.8.0