using Advantech.Motion;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks; 
using System.Timers;
namespace ProductionControl.Device
{
    public class Axis : IDisposable
    {
        public enum AxisStateType
        {
            [Description("轴状态")]
            AxisState = 0,
            [Description("轴运动状态")]
            AxisMotionState = 1,
            [Description("轴IO状态")]
            AxisIOState = 2, 
        }
       
        public Action<int, AxisStateType, uint> axisStateEvent;
        public enum AxisPosType
        {
            [Description("命令位置")]
            CmdPos = 0,
            [Description("反馈位置")]
            ActualPos = 1,
        }
        public Action<int, AxisPosType, double> axisPosEvent;
        /// <summary>                                                   使用
        /// 轴状态(AxisState 0-14) 单一值，无需按位取
        /// STA_AxDisable -- 轴被禁用，用户可打开并激活
        /// STA_AxReady ---- 轴已准备就绪，等待新的命令                  *
        /// STA_Stopping ---- 轴停止
        /// STA_AxErrorStop --- 出现错误，轴停止
        /// STA_AxHoming ---- 轴正在执行返回原点运动
        /// STA_AxPtpMotion ---- 轴正在执行PTP 运动
        /// STA_AxContiMotion ---- 轴正在执行连续运动
        /// STA_AxSyncMotion --- 轴在一个群组中，群组正在执行插补运动；或轴是一个从轴，正在执行Ecam/E-gear/Gantry 运动。
        /// STA_AX_EXT_JOG -- 轴由外部信号控制。当外部信号激活时，轴将执行JOG 模式运动。
        /// STA_AX_EXT_MPG --- 轴由外部信号控制。当外部信号激活时，轴将执行MPG 模式运动
        /// </summary>
        //public Action<int, int> axisStateEvent;

        /// <summary>
        /// 轴运动状态        使用
        /// 位 说明
        /// Stop ---- 停止 
        /// WaitERC---- 等待ERC 完成  
        /// InFA ---- 处于特定速度中 = FA
        /// InFL ---- 处于低速中 = FL
        /// InACC ---- 加速中
        /// InFH ---- 处于最大速度中 = FH
        /// InDEC ---- 减速中
        /// WaitINP---- 到位等待
        /// </summary>
        //public Action<int, int> axisMotionStateEvent;
        /// <summary>
        /// 轴IO状态 (Ax_Motion_IO)         使用
        /// RDY---- RDY 针脚输入    
        /// ALM ---- 报警信号输入         *
        /// LMT+ ---- 限位开关+         *
        /// LMT- ---- 限位开关-         *
        /// ORG---- 原始开关         *
        /// DIR ---- DIR 输出
        /// EMG ---- 紧急信号输入       
        /// INP ---- 到位信号输入
        /// SVON ---- 伺服开启（OUT6）         *
        /// ALRM ---- 报警复位输出状态
        /// SLMT+ ---- 软件限位+
        /// SLMT- ---- 软件限位-
        /// CMP----- 比较信号（OUT5）
        /// </summary>
        //public Action<int, bool, bool, bool, bool> axisIOStateEvent;
        /// <summary>
        /// 告警(级别1 2 3)
        /// </summary>
        public Action<int, string> warningEvent; 
        /// <summary>
        /// Log输出，(0-info,1-warning 2-error)
        /// </summary>
        public Action<int, string> log;

        /// <summary>
        /// 设备列表（多张PCI板卡）
        /// </summary>
        public List<DEV_LIST> DevList { get; private set; }
        /// <summary>
        /// 设备数量
        /// </summary>
        //private uint deviceCount = 0;
        /// <summary>
        /// 设备号，用于打开设备（非索引）
        /// </summary>
        //public uint DeviceNum { get; private set; } = 0;

        /// <summary>
        /// 设备句柄
        /// </summary>
        private IntPtr m_DeviceHandle = IntPtr.Zero;
        /// <summary>
        /// 轴数量
        /// </summary>
        private uint m_ulAxisCount = 0;
        private IntPtr[] m_Axishand = new IntPtr[0];
        public double[] CmdPos { get; private set; } = new double[32];//轴命令位置
        public double[] ActualPos { get; private set; } = new double[32];//轴实际(反馈)位置

        public UInt16[] AxState { get; private set; } = new UInt16[32];//轴状态
        public UInt32[] IOStatus { get; private set; } = new UInt32[32];//轴IO状态
        public uint[] AxMotionState { get; private set; } = new uint[32];//轴运动状态

        private uint[] AxEnableEvtArray = new uint[32];
        private uint[] GpEnableEvt = new uint[32];
        /// <summary>
        /// 组
        /// </summary>
        private IntPtr m_GpHand = IntPtr.Zero;

        /// <summary>
        /// 是否打开设备成功
        /// </summary>
        public bool IsInit { get; private set; } = false;
        Thread checkEventThread;
        private System.Timers.Timer timer = new System.Timers.Timer();

        /// <summary>
        /// 获取设备列表
        /// </summary>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        //public static List<DEV_LIST> getDevList()
        //{
        //    DEV_LIST[] curAvailableDevs = new DEV_LIST[Motion.MAX_DEVICES];
        //    uint deviceCount = 0;
        //    int Result = Motion.mAcm_GetAvailableDevs(curAvailableDevs, Motion.MAX_DEVICES, ref deviceCount);
        //    if (Result != (int)ErrorCode.SUCCESS || curAvailableDevs.Length < 1)
        //        throw new Exception("Get Device Numbers Failed With Error Code: [0x" + Convert.ToString(Result, 16) + "] DevCount=" + curAvailableDevs.Length);

        //    return curAvailableDevs.ToList().Take((int)deviceCount).ToList();
        //}
        public Axis()
        {
            DEV_LIST[] curAvailableDevs = new DEV_LIST[Motion.MAX_DEVICES];
            uint deviceCount = 0;
            int Result = Motion.mAcm_GetAvailableDevs(curAvailableDevs, Motion.MAX_DEVICES, ref deviceCount);
            if (Result != (int)ErrorCode.SUCCESS || curAvailableDevs.Length < 1)
                throw new Exception("Get Device Numbers Failed With Error Code: [0x" + Convert.ToString(Result, 16) + "] DevCount=" + curAvailableDevs.Length);

            DevList = curAvailableDevs.ToList().Take((int)deviceCount).ToList();
        }
        public void Dispose()
        {
            stop(); 
        }

        /// <summary>
        /// 打开设备
        /// </summary>
        /// <exception cref="Exception"></exception>
        public void start()
        {
            if (DevList == null || DevList.Count < 1)
                throw new Exception("设备为空！");

            start(DevList[0].DeviceNum);
        }
        public void start(uint DeviceNum)
        {
            if (IsInit) return;
            //打开设备
            uint uResult = Motion.mAcm_DevOpen(DeviceNum, ref m_DeviceHandle);
            if (uResult != (int)ErrorCode.SUCCESS)
                throw new Exception("Open Device Failed With Error Code: [0x" + Convert.ToString(uResult, 16) + "]");
             
            //读取轴数量
            uResult = Motion.mAcm_GetU32Property(m_DeviceHandle, (uint)PropertyID.FT_DevAxesCount, ref m_ulAxisCount);
            if (uResult != (uint)ErrorCode.SUCCESS)
                throw new Exception("Get Axis Number Failed With Error Code: [0x" + Convert.ToString(uResult, 16) + "]");
            m_Axishand = new IntPtr[m_ulAxisCount];

            //打开轴
            for (int i = 0; i < m_ulAxisCount; i++)
            {
                //打开每个轴并获得每个轴句柄  
                uResult = Motion.mAcm_AxOpen(m_DeviceHandle, (UInt16)i, ref m_Axishand[i]);
                if (uResult != (uint)ErrorCode.SUCCESS)
                    throw new Exception("Open Axis Failed With Error Code: [0x" + Convert.ToString(uResult, 16) + "]");

                //打开电源使能,1: On
                uResult = Motion.mAcm_AxSetSvOn(m_Axishand[i], 1);
                if (uResult != (uint)ErrorCode.SUCCESS)
                    throw new Exception("Servo On Failed With Error Code: [0x" + Convert.ToString(uResult, 16) + "]");

                //每个轴的初始属性(reset 命令位置和实际(反馈)位置)
                //double cmdPosition = new double();
                //cmdPosition = 0;
                //为指定的轴设置命令位置
                //Motion.mAcm_AxSetCmdPosition(m_Axishand[i], cmdPosition);
                //为指定的轴设置实际(反馈)位置
                //Motion.mAcm_AxSetActualPosition(m_Axishand[i], cmdPosition);

                //Event
                AxEnableEvtArray[i] |= (uint)EventType.EVT_AX_MOTION_DONE; //运动完成(减速直至停止)
                AxEnableEvtArray[i] |= (uint)EventType.EVT_AX_VH_START; //轴加速到运行速度时
                AxEnableEvtArray[i] |= (uint)EventType.EVT_AX_VH_END;//轴运行速度结束时，开始减速

                //初次获取轴的运动I/O状态。
                this.refreshAxisState(i);
            }

            //根据加载的文件设置设备的所有配置
            string cfgPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\DevCfg\\Axis_" + DeviceNum + ".cfg";
            if (File.Exists(cfgPath))
            {
                uResult = Motion.mAcm_DevLoadConfig(m_DeviceHandle, cfgPath);
                if (uResult != (uint)ErrorCode.SUCCESS)
                    throw new Exception("Load Config Failed With Error Code: [0x" + Convert.ToString(uResult, 16) + "]");
            }

            uResult = Motion.mAcm_EnableMotionEvent(m_DeviceHandle, AxEnableEvtArray, GpEnableEvt, m_ulAxisCount, 3);
            if (uResult != (uint)ErrorCode.SUCCESS)
                throw new Exception("EnableMotionEvent Filed With Error Code[0x" + Convert.ToString(uResult, 16) + "]");
             
             
            IsInit = true; 
            timer.Elapsed += Timer_Elapsed;
            timer.Interval = 100;
            timer.Enabled = true;

            //用户应该创建一个新的线程来检查事件状态，例如:CheckEvtThread()函数
            checkEventThread = new Thread(new ThreadStart(checkEvtThread));
            checkEventThread.Start();
        }

        /// <summary>
        /// 关闭设备
        /// </summary>
        /// <exception cref="Exception"></exception>
        public void stop()
        {
            if (!IsInit) return;
             
            uint i;
            for (i = 0; i < m_ulAxisCount; i++)
            { 
                if (AxState[i] == (uint)AxisState.STA_AX_ERROR_STOP)
                {
                    log?.Invoke(1, i + "轴处于ErrorStop状态，已重置！");
                    //重置轴的状态。如果轴处于ErrorStop状态，则调用此函数后状态将更改为Ready
                    Motion.mAcm_AxResetError(m_Axishand[i]);
                }
                // 命令轴减速停止(缓停)
                Motion.mAcm_AxStopDec(m_Axishand[i]);

                //sleep? 关闭电源使能,1: On
                uint uResult = Motion.mAcm_AxSetSvOn(m_Axishand[i], 0);
                if (uResult != (uint)ErrorCode.SUCCESS)
                    throw new Exception("Servo On Failed With Error Code: [0x" + Convert.ToString(uResult, 16) + "]");
            }
            //删除组中的所有轴并关闭组句柄
            //Motion.mAcm_GpClose(ref m_GpHand);
            //m_GpHand = IntPtr.Zero;

            for (i = 0; i < m_ulAxisCount; i++)
            {
                //Close Axes
                Motion.mAcm_AxClose(ref m_Axishand[i]);
            }

            timer.Elapsed -= Timer_Elapsed;
            m_ulAxisCount = 0;
            //Close Device
            Motion.mAcm_DevClose(ref m_DeviceHandle);
            m_DeviceHandle = IntPtr.Zero;
            IsInit = false;
            timer.Enabled = false;
        }
        /// <summary>
        /// 缓停,jog时用
        /// </summary>
        public void stopDec(int axisIndex = -1)
        {
            for (int i = 0; i < m_ulAxisCount; i++)
            {
                if (i == axisIndex || axisIndex == -1)
                {
                    Motion.mAcm_AxStopDec(m_Axishand[i]);
                }
            }
        }
        /// <summary>
        /// 急停
        /// </summary>
        public void stop(int axisIndex = -1)
        {
            if (!IsInit) return;
            for (int i = 0; i < m_ulAxisCount; i++)
            {
                if (i == axisIndex || axisIndex == -1)
                { 
                    Motion.mAcm_AxStopEmg(m_Axishand[i]);
                }
            } 
        }
 
        public void resetAxisState(int axisIndex)
        {
            if (!IsInit) return;
            if (AxState[axisIndex] == (uint)AxisState.STA_AX_ERROR_STOP)
            { 
                //重置轴的状态。如果轴处于ErrorStop状态，则调用此函数后状态将更改为Ready
                Motion.mAcm_AxResetError(m_Axishand[axisIndex]);
            }
            // 命令轴减速停止(缓停)
            Motion.mAcm_AxStopDec(m_Axishand[axisIndex]);
        }
        /// <summary>
        /// 指定的轴设置命令位置
        /// </summary>
        public void resetCmdPosition(int axisIndex = -1, double position = 0)
        {
            if (!IsInit) return;
            for (int i = 0; i < m_ulAxisCount; i++)
            {
                if (i == axisIndex || axisIndex == -1)
                { 
                    Motion.mAcm_AxSetCmdPosition(m_Axishand[i], position);
                }
            }
        }
        /// <summary>
        /// 指定的轴设置实际(反馈)位置
        /// </summary> 
        public void resetActualPosition(int axisIndex=-1, double position = 0)
        {
            if (!IsInit) return;
            for (int i = 0; i < m_ulAxisCount; i++)
            {
                if (i == axisIndex || axisIndex == -1)
                {
                    Motion.mAcm_AxSetActualPosition(m_Axishand[i], position);
                }
            }
        }
        /// <summary>
        /// 获取速度 [vellow,velhigh,acc,dec,Jerk]
        /// </summary>
        /// <param name="axisIndex"></param>
        /// <returns></returns>
        public double[] getAxisVelParam(int axisIndex)
        {
            double[] value=new double[5]; 
            Motion.mAcm_GetF64Property(m_Axishand[axisIndex], (uint)PropertyID.PAR_AxVelLow, ref value[0]);
            Motion.mAcm_GetF64Property(m_Axishand[axisIndex], (uint)PropertyID.PAR_AxVelHigh, ref value[1]);
            Motion.mAcm_GetF64Property(m_Axishand[axisIndex], (uint)PropertyID.PAR_AxAcc, ref value[2]);
            Motion.mAcm_GetF64Property(m_Axishand[axisIndex], (uint)PropertyID.PAR_AxDec, ref value[3]);
            Motion.mAcm_GetF64Property(m_Axishand[axisIndex], (uint)PropertyID.PAR_AxJerk, ref value[4]);//0-T/S 型曲线
            return value;
        }
        /// <summary>
        /// 速度设置 注：运动的过程中可变速度，加速度和减速度需使用AxChangeVelEx方法
        /// </summary>
        /// <param name="velLow">起始速度</param>
        /// <param name="high">运行速度</param>
        /// <param name="acc">加速度</param>
        /// <param name="dec">减速度</param>
        /// <param name="axisIndex"></param>
        public void setAxisVelParam(double velLow, double high = 0, double acc = 0, double dec = 0, int axisIndex = -1)
        {
            uint result;
            for (int i = 0; i < m_ulAxisCount; i++)
            {
                if (i == axisIndex || axisIndex == -1)
                {
                    if ((AxisState)AxState[i] != AxisState.STA_AX_READY)
                        continue;
                    if (velLow > 0) result = Motion.mAcm_SetF64Property(m_Axishand[i], (uint)PropertyID.PAR_AxVelLow, velLow);
                    if (high > 0) result = Motion.mAcm_SetF64Property(m_Axishand[i], (uint)PropertyID.PAR_AxVelHigh, high);
                    if (acc > 0) result = Motion.mAcm_SetF64Property(m_Axishand[i], (uint)PropertyID.PAR_AxAcc, acc);
                    if (dec > 0) result = Motion.mAcm_SetF64Property(m_Axishand[i], (uint)PropertyID.PAR_AxDec, dec);
                    result = Motion.mAcm_SetF64Property(m_Axishand[i], (uint)PropertyID.PAR_AxJerk, 0);//0-T/S 型曲线
                    //Ret = Acm_SetF64Property(m_Axishand[0], PAR_AxVelLow, 2000); // 起始速度
                    //Ret = Acm_SetF64Property(m_Axishand[0], PAR_AxVelHigh, 8000); // 运行速度
                    //Ret = Acm_SetF64Property(m_Axishand[0], PAR_AxAcc, 10000); // 加速度
                    //Ret = Acm_SetF64Property(m_Axishand[0], PAR_AxDec, 10000); // 减速度
                    //Ret = Acm_SetF64Property(m_Axishand[0], PAR_AxJerk, 0); //0-T/S 型曲线
                }
            }
        }
        /// <summary>
        /// 回HOME
        /// </summary>
        /// <param name="axisIndex"></param>
        /// <param name="homeMode">16种回HOME模式（0-15）</param>
        /// <param name="dir">0-正向 1-负向</param>
        /// <exception cref="Exception"></exception>
        public void home(int axisIndex = -1, uint homeMode = 11, uint dir = 1)
        {
            //研华运动控制卡共提供两个函数执行回Home： Acm_AxHome 和Acm_AxMoveHome 
            //调用Acm_AxHome 执行回Home 时，通过PAR_AxVelLow、PAR_AxVelHigh、PAR_AxAcc、 PAR_AxDec、PAR_AxJerk 设置初速度，运行速度、加速度、减速度、速度曲线类型。
            //调用Acm_AxMoveHome 执行回Home 时，通过PAR_AxHomeVelLow、PAR_AxHomeVelHigh、 PAR_AxHomeAcc、PAR_AxHomeDec、PAR_AxHomeJerk 设置初速度，运行速度、加速度、 减速度、速度曲线类型。
            uint result;
            for (int i = 0; i < m_ulAxisCount; i++)
            {
                if (i == axisIndex || axisIndex == -1)
                {
                    if ((AxisState)AxState[i] != AxisState.STA_AX_READY)
                        continue;
                    result = Motion.mAcm_AxHome(m_Axishand[i], homeMode, dir);
                    if (result != (uint)ErrorCode.SUCCESS)
                        throw new Exception("AxHome Failed With Error Code: [0x" + Convert.ToString(result, 16) + "]");
                }
            }
        }
        /// <summary>
        /// 点到点运动
        /// </summary>
        /// <param name="axisIndex"></param>
        /// <param name="pos">PPU位置，方向为正负值</param>
        /// <param name="isAbs">true:绝对 false:相对</param>
        public bool move_ptp(int axisIndex, double pos, bool isAbs)
        {
            uint result;
            if ((AxisState)AxState[axisIndex] != AxisState.STA_AX_READY)
                return false;

            if (isAbs) //Start single axis's absolute position motion.
                result = Motion.mAcm_AxMoveAbs(m_Axishand[axisIndex], pos);
            else //Start single axis's relative position motion
                result = Motion.mAcm_AxMoveRel(m_Axishand[axisIndex], pos);
            if (result != (uint)ErrorCode.SUCCESS)
            {
                log?.Invoke(2, "PTP Move Failed With Error Code[0x" + Convert.ToString(result, 16) + "]");
                return false;
            }
            return true;
        }
        #region JOG
        public void openJogMode(int axisIndex)
        {
            if (!IsInit) return;
            if ((AxisState)AxState[axisIndex] != AxisState.STA_AX_READY)
                return;

            uint result;
            //启用/禁用外置硬盘模式.0: Disabled (stop command) 1: JOG Mode  2: MPG Mode
            result = Motion.mAcm_AxSetExtDrive(m_Axishand[axisIndex], 0);
            result = Motion.mAcm_AxSetExtDrive(m_Axishand[axisIndex], 1);
            if (result != (uint)ErrorCode.SUCCESS)
                throw new Exception("Start external driver Failed With Error Code[0x" + Convert.ToString(result, 16) + "]");

            //设置外部驱动器的输入引脚 
            //0 轴 0(默认值) 仅支持 0
            //1 轴 1(不支持)
            //2 轴 2(不支持)
            //3 轴 3(不支持) 
            result = Motion.mAcm_SetU32Property(m_Axishand[axisIndex], (uint)PropertyID.CFG_AxExtMasterSrc, 0);
            if (result != (uint)ErrorCode.SUCCESS)
                throw new Exception("Set Property-AxExtMasterSrc Failed With Error Code[0x" + Convert.ToString(result, 16) + "]");

            //当启用外部驱动时。此属性允许通过数字输入通道选择驱动轴 
            result = Motion.mAcm_SetU32Property(m_Axishand[axisIndex], (uint)PropertyID.CFG_AxExtSelEnable, 1);
            if (result != (uint)ErrorCode.SUCCESS && result != (uint)ErrorCode.PropertyIDNotSupport)//Added for Supporting PCI1245 and PCI1265 
                throw new Exception("Set Property-AxExtSelEnable Failed With Error Code[0x" + Convert.ToString(result, 16) + "]");

            //理论脉冲数 
            result = Motion.mAcm_SetU32Property(m_Axishand[axisIndex], (uint)PropertyID.CFG_AxExtPulseNum, 1000);
            if (result != (uint)ErrorCode.SUCCESS && result != (uint)ErrorCode.PropertyIDNotSupport)//Added for Supporting PCI1245 and PCI1265 
                throw new Exception("Set Property-CFG_AxExtPulseNum Failed With Error Code[0x" + Convert.ToString(result, 16) + "]");
        }
        public void closeJogMode(int axisIndex = -1)
        {
            if (!IsInit) return;

            uint result;
            for (int i = 0; i < m_ulAxisCount; i++)
            {
                if (i == axisIndex || axisIndex == -1)
                {
                    axisIndex = i;
                    if ((AxisState)AxState[axisIndex] == AxisState.STA_AX_EXT_JOG)
                    {
                        //启用/禁用外置硬盘模式.0: Disabled (stop command) 1: JOG Mode  2: MPG Mode
                        result = Motion.mAcm_AxSetExtDrive(m_Axishand[axisIndex], 0);
                        //命令轴减速停止
                        result = Motion.mAcm_AxStopDec(m_Axishand[axisIndex]);
                    }
                }
            }
        }
        /// <summary>
        /// jog运行
        /// </summary>
        /// <param name="axisIndex"></param>
        /// <param name="dic">0：正向，1：负向</param>
        public void jog(int axisIndex, ushort dic)
        {
            //Jog 运动的方向，0：正向，1：负向
            Motion.mAcm_AxJog(m_Axishand[axisIndex], dic);
        }
        #endregion

        #region Private 
        private void Timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            if (!IsInit) return;
             
            for (int i = 0; i < m_ulAxisCount; i++)
                refreshAxisState(i);
        }
        private void refreshAxisState(int AxisIndex)
        {
            uint result;
            //获取指定轴的当前命令位置
            if ((uint)ErrorCode.SUCCESS == Motion.mAcm_AxGetCmdPosition(m_Axishand[AxisIndex], ref CmdPos[AxisIndex]))
                axisPosEvent?.Invoke(AxisIndex, AxisPosType.CmdPos, CmdPos[AxisIndex]);
            //获取指定轴的当前实际(反馈)位置
            if ((uint)ErrorCode.SUCCESS == Motion.mAcm_AxGetActualPosition(m_Axishand[AxisIndex], ref ActualPos[AxisIndex]))
                axisPosEvent?.Invoke(AxisIndex, AxisPosType.ActualPos, ActualPos[AxisIndex]);

            //获取轴的运动I/O状态。
            if ((uint)ErrorCode.SUCCESS == Motion.mAcm_AxGetMotionIO(m_Axishand[AxisIndex], ref IOStatus[AxisIndex]))
                axisStateEvent?.Invoke(AxisIndex, AxisStateType.AxisIOState, IOStatus[AxisIndex]);
            //log?.Invoke(0, $"({AxisIndex}轴)AxisMotionIO = {((Ax_Motion_IO)IOStatus[AxisIndex]).ToString()}");
            //checkMotionIOStatus(AxisIndex, IOStatus[AxisIndex]);

            //获取Axis的当前状态
            if ((uint)ErrorCode.SUCCESS == Motion.mAcm_AxGetState(m_Axishand[AxisIndex], ref AxState[AxisIndex]))
                axisStateEvent?.Invoke(AxisIndex, AxisStateType.AxisState, AxState[AxisIndex]);
            //log?.Invoke(0, $"({AxisIndex}轴)AxisState = {((AxisState)AxState[AxisIndex]).ToString()}");
             
            //获取Axis的当前运动状态
            if ((uint)ErrorCode.SUCCESS == Motion.mAcm_AxGetMotionStatus(m_Axishand[AxisIndex], ref AxMotionState[AxisIndex]))
                axisStateEvent?.Invoke(AxisIndex,  AxisStateType.AxisMotionState, AxMotionState[AxisIndex]);
            //log?.Invoke(0, $"({AxisIndex}轴)AxisMotionStatus = {AxMotionState[AxisIndex].ToString()}");
        }
        private bool _ORG, _EL_R, _EL_L, _ALM, _SVON;
        private void checkMotionIOStatus(int axisIndex, uint IOStatus)
        {
            if ((IOStatus & (uint)Ax_Motion_IO.AX_MOTION_IO_ALM) > 0)//报警信号输出 
                warningEvent?.Invoke(2, $"轴{axisIndex} 发出告警！！");
            
            bool ALM = (IOStatus & (uint)Ax_Motion_IO.AX_MOTION_IO_ALM) > 0;
            bool ORG = (IOStatus & (uint)Ax_Motion_IO.AX_MOTION_IO_ORG) > 0;//ORG  
            bool EL_R = (IOStatus & (uint)Ax_Motion_IO.AX_MOTION_IO_LMTP) > 0;//右极限  
            bool EL_L = (IOStatus & (uint)Ax_Motion_IO.AX_MOTION_IO_LMTN) > 0;//-EL 左  
            bool SVON = (IOStatus & (uint)Ax_Motion_IO.AX_MOTION_IO_SVON) > 0; 
        }
        /// <summary>
        /// 轴事件
        /// </summary>
        private void checkEvtThread()
        {
            uint Result;
            UInt32[] AxEvtStatusArray = new UInt32[32];
            UInt32[] GpEvtStatusArray = new UInt32[32];
            UInt32 i;
            while (IsInit)
            {
                //如果你想获得轴或组的事件状态，你应该通过调用 Motion.mAcm_EnableMotionEvent 来启用这些事件  
                //AxEvtStatusArray[n]，返回每个轴的中断事件状态，n 表示运动设备的轴个数
                //GpEnableEvtArrayy[n]：返回每个群组的中断事件状态
                //AxArrayElements U32 IN AxEvtStatusArray 中元素个数
                //GpArrayElements U32 IN GpEvtStatusArray 中元素个数
                //Millisecond U32 IN 设定每次Check 事件时的等待时间
                Result = Motion.mAcm_CheckMotionEvent(m_DeviceHandle, AxEvtStatusArray, GpEvtStatusArray, m_ulAxisCount, 4, 4);//3,10
                if (Result == (uint)ErrorCode.SUCCESS)
                {
                    for (i = 0; i < m_ulAxisCount; i++)
                    {
                        if ((AxEvtStatusArray[i] & (uint)EventType.EVT_AX_MOTION_DONE) > 0)
                        {
                            //m_AxDoneEvtCnt[i]++;
                        }
                        if ((AxEvtStatusArray[i] & (uint)EventType.EVT_AX_VH_START) > 0)
                        {
                            //m_AxVHStartCnt[i]++;
                        }
                        if ((AxEvtStatusArray[i] & (uint)EventType.EVT_AX_VH_END) > 0)
                        {
                            //m_AxVHEndCnt[i]++;
                        }

                    }
                    //if (m_GpHand != IntPtr.Zero)
                    //{
                    //    if (textBoxGpID.Text != "")
                    //    {
                    //        if ((GpEvtStatusArray[0] & ((uint)EventType.EVT_GP1_MOTION_DONE << Convert.ToByte(textBoxGpID.Text))) > 0)
                    //        {
                    //            m_GpDoneEvtCnt++;
                    //        }
                    //        if ((GpEvtStatusArray[1] & ((uint)EventType.EVT_GP1_VH_START << Convert.ToByte(textBoxGpID.Text))) > 0)
                    //        {
                    //            m_GpVHStartCnt++;
                    //        }
                    //        if ((GpEvtStatusArray[2] & ((uint)EventType.EVT_GP1_VH_END << Convert.ToByte(textBoxGpID.Text))) > 0)
                    //        {
                    //            m_GpVHEndCnt++;
                    //        }
                    //    }
                    //}
                }
            }
        }

        private string getErrInfo(uint errorCode)
        {
            StringBuilder ErrorMsg = new StringBuilder("", 100);
            //Get the error message according to error code returned from API
            Boolean res = Motion.mAcm_GetErrorMessage(errorCode, ErrorMsg, 100); 
            if (res) return ErrorMsg.ToString();
            return "获取错误信息失败！";
        }
        #endregion



        /*
        [Category("HLMT")]
        [Description("启用/禁用硬件限制信号.")]
        public HLmtEnable ElEnable
        {
            get
            {
                if ((FtHELMap & 1) == 0)
                {
                    return HLmtEnable.NOT_SUPPORT;
                }

                if (Handle != IntPtr.Zero)
                {
                    uint BufferLength = 4u;
                    Motion.mAcm_GetProperty(Handle, 574u, ref m_ElEnable, ref BufferLength);
                    return (HLmtEnable)m_ElEnable;
                }

                return (HLmtEnable)m_ElEnable;
            }
            set
            {
                m_ElEnable = (uint)value;
                if (Handle != IntPtr.Zero)
                {
                    if (m_ElEnable != 2)
                    {
                        uint bufferLength = 4u;
                        result = Motion.mAcm_SetProperty(Handle, 574u, ref m_ElEnable, bufferLength);
                        if (result == 0)
                        {
                            designValue.ElEnable = value;
                        }
                        else if (result != 2147483658u && result != 2147504130u)
                        {
                            MessageBox.Show("Set ElEnable=" + ElEnable.ToString() + " failed with Error Code[0x" + Convert.ToString(result, 16) + "]:" + (ErrorCode)result, "Advantech Motion Component", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1);
                        }
                    }
                }
                else
                {
                    designValue.ElEnable = value;
                }
            }
        }

        [Category("HLMT")]
        [Description("启用/禁用此轴的负硬件限制.")]
        public HLmtEnable MelEnable
        {
            get
            {
                if ((FtHELMap & 1) == 0)
                {
                    return HLmtEnable.NOT_SUPPORT;
                }

                if (Handle != IntPtr.Zero)
                {
                    uint BufferLength = 4u;
                    Motion.mAcm_GetProperty(Handle, 758u, ref m_MelEnable, ref BufferLength);
                    return (HLmtEnable)m_MelEnable;
                }

                return (HLmtEnable)m_MelEnable;
            }
            set
            {
                m_MelEnable = (uint)value;
                if (Handle != IntPtr.Zero)
                {
                    if (m_MelEnable != 2)
                    {
                        uint bufferLength = 4u;
                        result = Motion.mAcm_SetProperty(Handle, 758u, ref m_MelEnable, bufferLength);
                        if (result == 0)
                        {
                            designValue.MelEnable = value;
                        }
                        else if (result != 2147483658u && result != 2147504130u)
                        {
                            MessageBox.Show("Set MelEnable=" + m_MelEnable.ToString() + " failed with Error Code[0x" + Convert.ToString(result, 16) + "]:" + (ErrorCode)result, "Advantech Motion Component", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1);
                        }
                    }
                }
                else
                {
                    designValue.MelEnable = value;
                }
            }
        }

        [Category("HLMT")]
        [Description("启用/禁用此轴的正向硬件限制.")] 
        public HLmtEnable PelEnable
        {
            get
            {
                if ((FtHELMap & 1) == 0)
                {
                    return HLmtEnable.NOT_SUPPORT;
                }

                if (Handle != IntPtr.Zero)
                {
                    uint BufferLength = 4u;
                    Motion.mAcm_GetProperty(Handle, 757u, ref m_PelEnable, ref BufferLength);
                    return (HLmtEnable)m_PelEnable;
                }

                return (HLmtEnable)m_PelEnable;
            }
            set
            {
                m_PelEnable = (uint)value;
                if (Handle != IntPtr.Zero)
                {
                    if (m_PelEnable != 2)
                    {
                        uint bufferLength = 4u;
                        result = Motion.mAcm_SetProperty(Handle, 757u, ref m_PelEnable, bufferLength);
                        if (result == 0)
                        {
                            designValue.PelEnable = value;
                        }
                        else if (result != 2147483658u && result != 2147504130u)
                        {
                            MessageBox.Show("Set PelEnable=" + m_PelEnable.ToString() + " failed with Error Code[0x" + Convert.ToString(result, 16) + "]:" + (ErrorCode)result, "Advantech Motion Component", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1);
                        }
                    }
                }
                else
                {
                    designValue.PelEnable = value;
                }
            }
        }

        [Category("HLMT")]
        [Description("为硬件限位信号设置活动逻辑.")]
        public HLmtLogic ElLogic
        {
            get
            {
                if ((FtHELMap & 2) == 0)
                {
                    return HLmtLogic.NOT_SUPPORT;
                }

                if (Handle != IntPtr.Zero)
                {
                    uint BufferLength = 4u;
                    Motion.mAcm_GetProperty(Handle, 575u, ref m_ElLogic, ref BufferLength);
                    return (HLmtLogic)m_ElLogic;
                }

                return (HLmtLogic)m_ElLogic;
            }
            set
            {
                m_ElLogic = (uint)value;
                if (Handle != IntPtr.Zero)
                {
                    if (m_ElLogic != 2)
                    {
                        uint BufferLength = 4u;
                        result = Motion.mAcm_SetProperty(Handle, 575u, ref m_ElLogic, BufferLength);
                        if (result == 0)
                        {
                            designValue.ElLogic = value;
                            Motion.mAcm_GetProperty(Handle, 704u, ref m_PelLogic, ref BufferLength);
                            Motion.mAcm_GetProperty(Handle, 705u, ref m_MelLogic, ref BufferLength);
                        }
                        else if (result != 2147483658u && result != 2147504130u)
                        {
                            MessageBox.Show("Set ElLogic=" + m_ElLogic.ToString() + " failed with Error Code[0x" + Convert.ToString(result, 16) + "]:" + (ErrorCode)result, "Advantech Motion Component", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1);
                        }
                    }
                }
                else
                {
                    designValue.ElLogic = value;
                }
            }
        }
        */
    }
}

