领胜LDS 键盘AOI检测项目
wells.liu
2020-07-02 8527a31907a30c1b9f15dae1e0bdcf76e7e1f123
Merge branch 'master' of http://gitblit.broconcentric.com:8088/r/M071
2个文件已添加
12个文件已修改
1794 ■■■■ 已修改文件
src/Bro.Common.Device/Bro.Common.Device.csproj 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.Common.Device/DeviceBase/MotionCardBase.cs 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.Common.Model/Base/DeviceConfigBase.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.Common.Model/Bro.Common.Model.csproj 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.Common.Model/Helper/EnumHelper.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.Common.Model/Helper/PropertyConvertHelper.cs 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.Common.Model/Interface/IOperationConfig.cs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.Common.Model/Model/IOItem.cs 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.Common.Model/Model/MonitorSet.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.Common.Model/Model/MotionCardRelated.cs 502 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.Common.Model/Model/WarningSet.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.Device.GTSCard/GTSCardConfig.cs 990 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.Device.GTSCard/GTSCardDriver.cs 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/M071Process.cs 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.Common.Device/Bro.Common.Device.csproj
@@ -115,6 +115,7 @@
    <Compile Include="Base\DeviceBase.cs" />
    <Compile Include="DeviceBase\CameraBase.cs" />
    <Compile Include="DeviceBase\HDevEngineTool.cs" />
    <Compile Include="DeviceBase\MotionCardBase.cs" />
    <Compile Include="DeviceBase\PLCBase.cs" />
    <Compile Include="Helper\AspectHelper.cs" />
    <Compile Include="Helper\HalconHelper.cs" />
src/Bro.Common.Device/DeviceBase/MotionCardBase.cs
New file
@@ -0,0 +1,140 @@
using Bro.Common.Helper;
using Bro.Common.Interface;
using Bro.Common.Model;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing.Design;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Bro.Common.Base
{
    public abstract class MotionCardBase : DeviceBase, IMonitor, IMotionCard
    {
        public event Action<DateTime, string, IDevice, IMonitorSet> OnMonitorInvoke;
        public event Action<DateTime, IDevice, IWarningSet> OnMonitorAlarm;
        public abstract List<AxisInfo> GetCurrentAxisInfo(params string[] axisName);
        public abstract void Monitor();
        public abstract ResponseMessage MoveToPoint(IOperationConfig opConfig);
        public abstract void ResetAlarm();
        public abstract ResponseMessage Run(IOperationConfig config);
    }
    public class MotionCardInitialConfigBase : InitialConfigBase, IMonitorConfig
    {
        [Category("板卡配置")]
        [DisplayName("卡号")]
        [Description("CardNum:卡号")]
        public int CardNum { get; set; }
        [Category("板卡配置")]
        [DisplayName("初始配置文件路径")]
        [Description("InitialConfigFilePath:初始配置文件路径")]
        [Editor(typeof(FileDialogEditor), typeof(UITypeEditor))]
        public string InitialConfigFilePath { get; set; }
        [Category("轴配置")]
        [DisplayName("轴数量")]
        [Description("AxisNum:轴数量")]
        public int AxisNum { get; set; } = 4;
        [Category("轴配置")]
        [DisplayName("轴配置信息集合")]
        [Description("AxisSettings:轴配置信息集合")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(ComplexCollectionEditor<AxisSetting>), typeof(UITypeEditor))]
        public List<AxisSetting> AxisSettings { get; set; } = new List<AxisSetting>();
        [Category("轴配置")]
        [DisplayName("轴速度比率")]
        [Description("AxisVelocityRatio:轴速度比率")]
        public double AxisVelocityRatio { get; set; } = 1;
        //[Category("延时配置")]
        //[DisplayName("动作完成后延迟")]
        //[Description("ActionAfterDelay:动作完成后延迟")]
        //public int ActionAfterDelay { get; set; } = 100;
        [Category("警报配置")]
        [Description("WarningSetCollection:警报配置列表")]
        [DisplayName("警报配置")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(WarningSetsEditor), typeof(UITypeEditor))]
        public List<IWarningSet> WarningSetCollection { get; set; } = new List<IWarningSet>();
        [Category("IO配置")]
        [Description("IO定义集合")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(ComplexCollectionEditor<IODefinition>), typeof(UITypeEditor))]
        public List<IODefinition> IODefinitionCollection { get; set; } = new List<IODefinition>();
        #region IMonitorConfig
        [Category("监听设置")]
        [Description("MonitorSetCollection:监听操作配置集合")]
        [DisplayName("监听配置")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(ComplexCollectionEditor<MotionCardMonitorSet>), typeof(UITypeEditor))]
        public List<IMonitorSet> MonitorSetCollection { get; set; } = new List<IMonitorSet>();
        [Category("监听设置")]
        [Description("true:启动监听 false:关闭监听")]
        [DisplayName("监听启用")]
        public bool IsEnableMonitor { get; set; } = true;
        [Category("监听设置")]
        [Description("扫描间隔时间,单位:ms")]
        [DisplayName("扫描间隔")]
        public int MonitorInterval { get; set; } = 10;
        [Category("监听设置")]
        [Description("超时设置,单位:ms")]
        [DisplayName("监听超时")]
        public int MonitorTimeout { get; set; } = 500;
        public List<IMonitorSet> GetAllMonitorSet()
        {
            WarningSetCollection.ForEach(m => m.Source = this.Name);
            MonitorSetCollection.ForEach(m => m.SourceDevice = this.Id);
            return MonitorSetCollection;
        }
        #endregion
    }
    public class MotionCardOperationConfigBase : OperationConfigBase, IComplexDisplay
    {
        [Category("IO操作配置")]
        [Description("IO预检查定义集合")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(IORefrenceItemCollectionEditor),typeof(UITypeEditor))]
        public List<IORefrenceItem> PreCheckIOCollection { get; set; } = new List<IORefrenceItem>();
        [Category("IO操作配置")]
        [Description("IO输出定义集合")]
        [TypeConverter(typeof(CollectionCountConvert))]
        public List<IORefrenceItem> IOOutputCollection { get; set; } = new List<IORefrenceItem>();
        [Category("IO操作配置")]
        [Description("IO确认定义集合")]
        [TypeConverter(typeof(CollectionCountConvert))]
        public List<IORefrenceItem> IOConfirmCollection { get; set; } = new List<IORefrenceItem>();
        [Category("板卡运动配置")]
        [DisplayName("运动配置集合")]
        [Description("MovingOps:运动配置集合")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(ComplexCollectionEditor<MovingOption>), typeof(UITypeEditor))]
        public List<MovingOption> MovingOps { get; set; } = new List<MovingOption>();
        public string GetDisplayText()
        {
            throw new NotImplementedException();
        }
    }
}
src/Bro.Common.Model/Base/DeviceConfigBase.cs
@@ -39,6 +39,10 @@
        [Browsable(false)]
        public string MonitorSetId { get; set; } = "";
        [Browsable(false)]
        [JsonIgnore]
        public virtual string DeviceId { get; set; } = "";
    }
    public class InitialConfigBase : IInitialConfig
src/Bro.Common.Model/Bro.Common.Model.csproj
@@ -153,6 +153,7 @@
    <Compile Include="Model\DeviceOpBind.cs" />
    <Compile Include="Model\ModbusFrame.cs" />
    <Compile Include="Model\MonitorSet.cs" />
    <Compile Include="Model\MotionCardRelated.cs" />
    <Compile Include="Model\PageRequest.cs" />
    <Compile Include="Model\IOItem.cs" />
    <Compile Include="Model\PLCItem.cs" />
src/Bro.Common.Model/Helper/EnumHelper.cs
@@ -587,7 +587,7 @@
        /// <summary>
        /// 运动板卡 IO 类型(IN OUT)
        /// </summary>
        public enum IOModel
        public enum IOType
        {
            [Description("In输入")]
            In = 0,
src/Bro.Common.Model/Helper/PropertyConvertHelper.cs
@@ -1,5 +1,6 @@
using Bro.Common.Factory;
using Bro.Common.Interface;
using Bro.Common.Model;
using Newtonsoft.Json;
using System;
using System.Collections;
@@ -915,6 +916,84 @@
            return base.EditValue(context, provider, value);
        }
    }
    public class IORefrenceItemCollectionEditor : CollectionEditor
    {
        protected override CollectionForm CreateCollectionForm()
        {
            var form = base.CreateCollectionForm();
            var prop = form.GetType().GetField("propertyBrowser", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
            if (prop != null)
            {
                if (prop.GetValue(form) is PropertyGrid grid)
                {
                    grid.HelpVisible = true;
                    grid.ToolbarVisible = false;
                }
            }
            return form;
        }
        //protected override object CreateInstance(Type itemType)
        //{
        //    return base.CreateInstance(itemType);
        //}
        //protected override object[] GetItems(object editValue)
        //{
        //    return base.GetItems(editValue);
        //}
        //protected override object SetItems(object editValue, object[] value)
        //{
        //    return base.SetItems(editValue, value);
        //}
        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            return base.EditValue(context, provider, value);
        }
        public IORefrenceItemCollectionEditor(Type type) : base(type)
        {
        }
        /// <summary>
        /// 限制一次选一个实例
        /// </summary>
        /// <returns></returns>
        protected override bool CanSelectMultipleInstances()
        {
            return false;
        }
        /// <summary>
        /// 指定创建的对象类型
        /// </summary>
        /// <returns></returns>
        protected override Type CreateCollectionItemType()
        {
            return typeof(IORefrenceItem);
        }
        protected override string GetDisplayText(object value)
        {
            if (value is IComplexDisplay)
            {
                return (value as IComplexDisplay).GetDisplayText();
            }
            return base.GetDisplayText(value);
        }
        //protected override void DestroyInstance(object instance)
        //{
        //    base.DestroyInstance(instance);//重要!自动删除组件的设计时代码!
        //}
    }
    #endregion
}
src/Bro.Common.Model/Interface/IOperationConfig.cs
@@ -26,5 +26,10 @@
        /// 指示该操作的监视配置来源
        /// </summary>
        string MonitorSetId { get; set; }
        /// <summary>
        /// 调用该操作配置的设备Id
        /// </summary>
        string DeviceId { get; set; }
    }
}
src/Bro.Common.Model/Model/IOItem.cs
@@ -1,6 +1,8 @@
using Bro.Common.Helper;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using static Bro.Common.Helper.EnumHelper;
namespace Bro.Common.Model
@@ -10,21 +12,62 @@
        /// <summary>
        /// IO点编号
        /// </summary>
        public int IONum { get; set; }
        [Category("IO配置")]
        [Description("IO点编号")]
        public virtual int IONum { get; set; }
        /// <summary>
        /// IO点的值
        /// </summary>
        public int Value { get; set; }
        [Category("IO配置")]
        [Description("IO数值")]
        public virtual int Value { get; set; }
        /// <summary>
        /// IO点是in还是out
        /// </summary>   
        public IOModel Model { get; set; }
        [Category("IO配置")]
        [Description("IO类型")]
        public virtual IOType IOType { get; set; }
        public string GetDisplayText()
        {
            return $"{Model.GetEnumDescription()},编号{IONum},IO点的值{Value}";
            return $"{IOType.GetEnumDescription()},编号{IONum},IO点的值{Value}";
        }
    }
    public class IODefinition : IOItem
    {
        [Category("IO配置")]
        [Description("IO用途描述")]
        public string IODesc { get; set; }
        [Category("IO配置")]
        [Description("备注说明")]
        public string Remark { get; set; }
        [Browsable(false)]
        [JsonIgnore]
        public override int Value { get; set; }
        public new string GetDisplayText()
        {
            return $"{IODesc} {IOType.GetEnumDescription()} {IONum}";
        }
    }
    public class IORefrenceItem
    {
        [Category("IO操作配置")]
        [Description("需要操作的IO")]
        public IOItem IOItem { get; set; } = new IOItem();
        [Category("IO操作配置")]
        [Description("需要操作的IO的数值")]
        public int CheckValue { get => IOItem.Value; set => IOItem.Value = value; }
        [Browsable(false)]
        [JsonIgnore]
        public List<IODefinition> IOItemSource { get; set; } = new List<IODefinition>();
    }
}
src/Bro.Common.Model/Model/MonitorSet.cs
@@ -188,7 +188,7 @@
        [Category("监听设置")]
        [DisplayName("监听类型")]
        [Description("监听运动板卡 IO 类型(IN OUT)")]
        public IOModel MonitorIOModel { get; set; }
        public IOType MonitorIOModel { get; set; }
        /// <summary>
        /// 监听地址索引
src/Bro.Common.Model/Model/MotionCardRelated.cs
New file
@@ -0,0 +1,502 @@
using Bro.Common.Helper;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing.Design;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using static Bro.Common.Helper.EnumHelper;
namespace Bro.Common.Model
{
    /// <summary>
    /// 轴配置
    /// </summary>
    public class AxisSetting : IComplexDisplay
    {
        [Category("轴配置")]
        [DisplayName("轴号索引")]
        [Description("AxisIndex:轴号索引")]
        public int AxisIndex { get; set; }
        [Category("轴配置")]
        [DisplayName("轴名称")]
        [Description("AxisName:轴名称")]
        public string AxisName { get; set; }
        [Category("轴配置")]
        [DisplayName("轴是否启用")]
        [Description("IsAxisEnabled:轴是否启用")]
        public bool IsAxisEnabled { get; set; } = false;
        [Category("换算配置")]
        [DisplayName("脉冲数换算比例")]
        [Description("脉冲数和其他计量单位的换算比例,例如设置为1000,表示1000个脉冲等于1uint")]
        public int PulseRatio { get; set; } = 1;
        [Category("速度配置")]
        [DisplayName("默认速度参数")]
        [Description("VelocityPara:默认速度参数")]
        [TypeConverter(typeof(ComplexObjectConvert))]
        [Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))]
        public VelocityPara VelocityPara { get; set; } = new VelocityPara();
        [Category("回原点设置")]
        [DisplayName("回原点模式")]
        [Description("HomeMode:回原点模式。0:一般模式 1:极限限位模式 2:外部触发模式")]
        public int HomeMode { get; set; } = 0;
        [Category("回原点设置")]
        [DisplayName("回原点方向")]
        [Description("IsHomePositive:回原点方向。 true:正方向开始  false:负方向开始")]
        public bool IsHomePositive { get; set; } = true;
        [Category("回原点设置")]
        [DisplayName("是否自动回原点")]
        [Description("IsAutoGoHome:是否自动回原点。 true:是  false:否")]
        public bool IsAutoGoHome { get; set; } = false;
        [Category("超时设置")]
        [DisplayName("回原点超时")]
        [Description("TimeOutHome:回原点超时,单位毫秒")]
        public int TimeOutHome { get; set; } = 30000;
        [Category("超时设置")]
        [DisplayName("运动超时")]
        [Description("TimeOutMove:运动超时,单位毫秒")]
        public int TimeOutMove { get; set; } = 10000;
        [Category("开闭环设置")]
        [DisplayName("是否使用Cmmd回馈")]
        [Description("IsUseCmmdPosition:是否使用Cmmd回馈")]
        public bool IsUseCmmdPosition { get; set; } = false;
        [Category("开闭环设置")]
        [DisplayName("是否使用板卡反馈停止信号")]
        [Description("IsUseMDNStopSignal:是否使用板卡反馈停止信号")]
        public bool IsUseMDNStopSignal { get; set; } = false;
        [Category("开闭环设置")]
        [DisplayName("是否启用报警")]
        [Description("IsUseWarning:是否启用报警")]
        public bool IsUseWarning { get; set; } = false;
        [Category("暂停配置")]
        [DisplayName("是否启用立即暂停")]
        [Description("IsImmediatePause:是否启用立即暂停")]
        public bool IsImmediatePause { get; set; } = false;
        [Category("暂停配置")]
        [DisplayName("轴位置处于区间内时适用的暂停操作")]
        [Description("ImmediatePauseSections:当轴位置处于区间内时适用的暂停操作")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(ComplexCollectionEditor<Section>), typeof(UITypeEditor))]
        public List<Section> ImmediatePauseSections { get; set; } = new List<Section>();
        public string GetDisplayText()
        {
            return AxisIndex + "-" + AxisName + "-" + (IsAxisEnabled ? "启用" : "禁用");
        }
    }
    /// <summary>
    /// 位置对象
    /// </summary>
    public class Section : IComplexDisplay
    {
        [Category("暂停区间")]
        [DisplayName("起始位置")]
        [Description("StartPosition:起始位置")]
        public int StartPosition { get; set; }
        [Category("暂停区间")]
        [DisplayName("结束位置")]
        [Description("EndPosition:结束位置")]
        public int EndPosition { get; set; }
        public string GetDisplayText()
        {
            return $"{StartPosition}--{EndPosition}";
        }
    }
    /// <summary>
    /// 速度参数对象
    /// </summary>
    public class VelocityPara
    {
        [Category("速度配置")]
        [DisplayName("速度")]
        [Description("Velocity:速度,为0时表示不修改当前设置")]
        public double Velocity { get; set; } = 0;
        [Category("速度配置")]
        [DisplayName("加速度")]
        [Description("Acc:加速度,为0时表示不修改当前设置")]
        public double Acc { get; set; } = 1;
        [Category("速度配置")]
        [DisplayName("减速度")]
        [Description("减速度,为0时表示不修改当前设置")]
        public double Dec { get; set; } = 1;
    }
    /// <summary>
    /// 回原点参数对象
    /// </summary>
    public class GoHomePara
    {
        [Category("回原点参数")]
        [DisplayName("回原点方式")]
        [Description("HomeMode:回原点方式 (HOME_MODE_LIMIT = 10; HOME_MODE_LIMIT_HOME = 11; HOME_MODE_LIMIT_INDEX = 12; HOME_MODE_LIMIT_HOME_INDEX = 13;HOME_MODE_HOME = 20;HOME_MODE_HOME_INDEX = 22;HOME_MODE_INDEX = 30;")]
        public short HomeMode { get; set; } = 11;
        [Category("回原点参数")]
        [DisplayName("回原点方向")]
        [Description("HomeDir:1 正向,-1 负向")]
        public short HomeDir { get; set; } = 1;
        [Category("回原点参数")]
        [DisplayName("回原点方向")]
        [Description("HomeDir:1 正向,-1 负向")]
        public short Edge { get; set; } = 0;
        [Category("回原点参数")]
        [DisplayName("回原点最低速度")]
        [Description("LowVelocity:速度,为0时表示不修改当前设置")]
        public double LowVelocity { get; set; } = 50;
        [Category("回原点参数")]
        [DisplayName("回原点最高速度")]
        [Description("HighVelocity:速度,为0时表示不修改当前设置")]
        public double HighVelocity { get; set; } = 50;
        [Category("回原点参数")]
        [DisplayName("搜搜距离")]
        [Description("SearchHomeDistance:搜搜距离")]
        public int SearchHomeDistance { get; set; } = 9999999;
        [Category("回原点参数")]
        [DisplayName("偏移距离")]
        [Description("HomeOffset:偏移距离")]
        public int HomeOffset { get; set; } = 0;
        [Category("回原点参数")]
        [DisplayName("跳过步长")]
        [Description("EscapeStep:跳过步长")]
        public int EscapeStep { get; set; } = 1000;
    }
    /// <summary>
    /// 运动对象
    /// </summary>
    public class MovingOption : INotifyPropertyChanged, IComplexDisplay
    {
        private int axisIndex = 0;
        [Category("运动配置")]
        [DisplayName("运动轴索引")]
        [Description("AxisIndex:运动轴索引")]
        [TypeConverter(typeof(AxisIndexConvert))]
        public int AxisIndex
        {
            get => axisIndex;
            set
            {
                if (axisIndex != value)
                {
                    axisIndex = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("AxisIndex"));
                }
                axisIndex = value;
            }
        }
        private MotorMoveMode moveMode = MotorMoveMode.Normal;
        [Category("运动配置")]
        [DisplayName("运动模式")]
        [Description("MoveMode:运动模式")]
        public MotorMoveMode MoveMode
        {
            get => moveMode;
            set
            {
                if (moveMode != value)
                {
                    moveMode = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("MoveMode"));
                }
                moveMode = value;
            }
        }
        private bool isAbsolute = true;
        [Category("运动配置")]
        [DisplayName("是否绝对运动")]
        [Description("IsAbsolute:是否绝对运动")]
        public bool IsAbsolute
        {
            get => isAbsolute;
            set
            {
                if (isAbsolute != value)
                {
                    isAbsolute = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsAbsolute"));
                }
                isAbsolute = value;
            }
        }
        private int destination = 0;
        [Category("运动配置")]
        [DisplayName("目的地")]
        [Description("Destination:目的地")]
        public int Destination
        {
            get => destination;
            set
            {
                if (destination != value)
                {
                    destination = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Destination"));
                }
                destination = value;
            }
        }
        private VelocityPara velocityPara = new VelocityPara();
        [Category("运动配置")]
        [DisplayName("速度参数")]
        [Description("VelocityPara:速度参数")]
        [TypeConverter(typeof(ComplexObjectConvert))]
        [Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))]
        public VelocityPara VelocityPara
        {
            get => velocityPara;
            set
            {
                velocityPara = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("VelocityPara"));
            }
        }
        private GoHomePara goHomePara = new GoHomePara();
        [Category("运动配置")]
        [DisplayName("回原点参数")]
        [Description("GoHomePara:速度参数")]
        [TypeConverter(typeof(ComplexObjectConvert))]
        [Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))]
        public GoHomePara GoHomePara
        {
            get => goHomePara;
            set
            {
                goHomePara = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("GoHomePara"));
            }
        }
        internal List<AxisSetting> _axisSettingList = new List<AxisSetting>();
        public void SetAxisSetting(List<AxisSetting> settings)
        {
            if (settings != null)
                _axisSettingList = settings;
        }
        public string GetDisplayText()
        {
            string axisName = AxisIndex.ToString();
            var axisSet = _axisSettingList.FirstOrDefault(a => a.AxisIndex == AxisIndex);
            if (axisSet != null)
            {
                axisName += ("-" + axisSet.AxisName);
            }
            return axisName + "," + MoveMode.ToString() + "," + (IsAbsolute ? "Abs" : "Rel") + "," + Destination;
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }
    public class AxisIndexConvert : TypeConverter
    {
        Dictionary<int, string> _indexNameDict = new Dictionary<int, string>();
        public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
        {
            return true;
        }
        public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
        {
            MovingOption mo = context.Instance as MovingOption;
            _indexNameDict = mo._axisSettingList.ToDictionary(a => a.AxisIndex, a => a.AxisIndex + "-" + a.AxisName);
            return new StandardValuesCollection(_indexNameDict.Keys);
        }
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            if (sourceType == typeof(string))
            {
                return true;
            }
            return base.CanConvertFrom(context, sourceType);
        }
        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object v)
        {
            if (v is string)
            {
                foreach (var indexName in _indexNameDict)
                {
                    if (indexName.Value == v.ToString())
                    {
                        return indexName.Key;
                    }
                }
                return Convert.ToInt32(v);
            }
            return base.ConvertFrom(context, culture, v);
        }
        public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object v, Type destinationType)
        {
            if (destinationType == typeof(string))
            {
                if (_indexNameDict.ContainsKey(Convert.ToInt32(v)))
                {
                    return _indexNameDict[Convert.ToInt32(v)];
                }
            }
            return base.ConvertTo(context, culture, v, destinationType);
        }
        public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
        {
            return false;
        }
    }
    public class AxisConflictSet : IComplexDisplay
    {
        [Category("1.轴冲突条件")]
        [Description("轴冲突条件,满足全部条件时轴运动需要检查冲突")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(ComplexCollectionEditor<AxisLimit>), typeof(UITypeEditor))]
        public List<AxisLimit> AxisOptions { get; set; } = new List<AxisLimit>();
        [Category("1.轴冲突条件")]
        [Description("IO冲突条件,满足全部条件时轴运动需要检查冲突")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(ComplexCollectionEditor<IOLimit>), typeof(UITypeEditor))]
        public List<IOLimit> IOOptions { get; set; } = new List<IOLimit>();
        [Category("2.轴冲突限制")]
        [Description("轴冲突限制,轴运动允许区间")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(ComplexCollectionEditor<AxisLimit>), typeof(UITypeEditor))]
        public List<AxisLimit> AxisLimits { get; set; } = new List<AxisLimit>();
        [Category("2.轴冲突限制")]
        [Description("IO允许条件,允许输出的IO")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(ComplexCollectionEditor<IOLimit>), typeof(UITypeEditor))]
        public List<IOLimit> IOOutputs { get; set; } = new List<IOLimit>();
        [Category("3.轴冲突启用")]
        [Description("true:启用轴冲突限制 false:不启用轴冲突限制")]
        public bool IsEnabled { get; set; } = true;
        public string GetDisplayText()
        {
            string optionStr = "Options:" + String.Join(";", AxisOptions.Select(a => a.GetDisplayText()));
            string limitStr = "Limits:" + String.Join(";", AxisLimits.Select(a => a.GetDisplayText()));
            return optionStr + "|" + limitStr;
        }
    }
    public class AxisLimit : IComplexDisplay
    {
        [Category("1.轴号")]
        [Description("1.轴号")]
        public int AxisIndex { get; set; }
        [Category("2.轴最小限制")]
        [Description("2.轴最小限制")]
        public int LimitMin { get; set; }
        [Category("3.轴最大限制")]
        [Description("3.轴最大限制")]
        public int LimitMax { get; set; }
        private int currentPosition = 0;
        [Browsable(false)]
        [JsonIgnore]
        public int CurrentPosition
        {
            get => currentPosition;
            set
            {
                if (currentPosition != value)
                {
                    if (value >= LimitMin && value <= LimitMax)
                    {
                        IsInLimit = true;
                    }
                    else
                    {
                        IsInLimit = false;
                    }
                }
                currentPosition = value;
            }
        }
        [Browsable(false)]
        [JsonIgnore]
        public bool IsInLimit { get; set; }
        public string GetDisplayText()
        {
            return String.Format("Index:{0},{1}->{2}", AxisIndex, LimitMin, LimitMax);
        }
    }
    public class IOLimit : IComplexDisplay
    {
        [Category("1.IO限制")]
        [Description("IO索引")]
        public int IOIndex { get; set; }
        [Category("1.IO限制")]
        [Description("IO限制值。输入判断时该值作为启用判断值,输出判断时该值作为允许输出值")]
        public bool IOSignal { get; set; }
        public string GetDisplayText()
        {
            return IOIndex + "--" + IOSignal.ToString();
        }
    }
    public class AxisMovingStay
    {
        public int Position { get; set; }
        public int Velocity { get; set; }
        public AutoResetEvent MoveHandle { get; set; } = new AutoResetEvent(false);
        public AutoResetEvent MoveSendHandle { get; set; } = new AutoResetEvent(false);
    }
}
src/Bro.Common.Model/Model/WarningSet.cs
@@ -99,7 +99,7 @@
        [Category("警报设置")]
        [DisplayName("警报类型")]
        [Description("警报设置:运动板卡 IO 类型(IN OUT)")]
        public IOModel WarningIOModel { get; set; }
        public IOType WarningIOModel { get; set; }
        [Category("触发设置")]
        [Description("true:高电平触发报警 false:低电平触发报警")]
src/Bro.Device.GTSCard/GTSCardConfig.cs
@@ -17,105 +17,105 @@
{
    [Device("GTSCard", "固高板卡", EnumHelper.DeviceAttributeType.OperationConfig)]
    public class GTSCardOperationConfig : OperationConfigBase, IComplexDisplay
    public class GTSCardOperationConfig : MotionCardOperationConfigBase
    {
        [Category("板卡运动配置")]
        [DisplayName("运动配置集合")]
        [Description("MovingOps:运动配置集合")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(ComplexCollectionEditor<MovingOption>), typeof(UITypeEditor))]
        public ObservableCollection<MovingOption> MovingOps { get; set; } = new ObservableCollection<MovingOption>();
        //[Category("板卡运动配置")]
        //[DisplayName("运动配置集合")]
        //[Description("MovingOps:运动配置集合")]
        //[TypeConverter(typeof(CollectionCountConvert))]
        //[Editor(typeof(ComplexCollectionEditor<MovingOption>), typeof(UITypeEditor))]
        //public ObservableCollection<MovingOption> MovingOps { get; set; } = new ObservableCollection<MovingOption>();
        public string GetDisplayText()
        {
            return MovingOps.Count() == 0 ? "--" : string.Join(";", MovingOps.Select(m => m.GetDisplayText()));
        }
        //public string GetDisplayText()
        //{
        //    return MovingOps.Count() == 0 ? "--" : string.Join(";", MovingOps.Select(m => m.GetDisplayText()));
        //}
    }
    [Device("GTSCard", "固高板卡", EnumHelper.DeviceAttributeType.OperationConfig)]
    public class GTSCardInitialConfig : InitialConfigBase, IMonitorConfig
    [Device("GTSCard", "固高板卡", EnumHelper.DeviceAttributeType.InitialConfig)]
    public class GTSCardInitialConfig : MotionCardInitialConfigBase
    {
        [Category("板卡配置")]
        [DisplayName("卡号")]
        [Description("CardNum:卡号")]
        public int CardNum { get; set; }
        //[Category("板卡配置")]
        //[DisplayName("卡号")]
        //[Description("CardNum:卡号")]
        //public int CardNum { get; set; }
        [Category("板卡配置")]
        [DisplayName("初始配置文件路径")]
        [Description("InitialConfigFilePath:初始配置文件路径")]
        [Editor(typeof(FileDialogEditor), typeof(UITypeEditor))]
        public string InitialConfigFilePath { get; set; }
        //[Category("板卡配置")]
        //[DisplayName("初始配置文件路径")]
        //[Description("InitialConfigFilePath:初始配置文件路径")]
        //[Editor(typeof(FileDialogEditor), typeof(UITypeEditor))]
        //public string InitialConfigFilePath { get; set; }
        [Category("轴配置")]
        [DisplayName("轴数量")]
        [Description("AxisNum:轴数量")]
        public int AxisNum { get; set; } = 2;
        //[Category("轴配置")]
        //[DisplayName("轴数量")]
        //[Description("AxisNum:轴数量")]
        //public int AxisNum { get; set; } = 2;
        [Category("轴配置")]
        [DisplayName("轴配置信息集合")]
        [Description("AxisSettings:轴配置信息集合")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(ComplexCollectionEditor<AxisSetting>), typeof(UITypeEditor))]
        public List<AxisSetting> AxisSettings { get; set; } = new List<AxisSetting>();
        //[Category("轴配置")]
        //[DisplayName("轴配置信息集合")]
        //[Description("AxisSettings:轴配置信息集合")]
        //[TypeConverter(typeof(CollectionCountConvert))]
        //[Editor(typeof(ComplexCollectionEditor<AxisSetting>), typeof(UITypeEditor))]
        //public List<AxisSetting> AxisSettings { get; set; } = new List<AxisSetting>();
        [Category("轴配置")]
        [DisplayName("轴速度比率")]
        [Description("AxisVelocityRatio:轴速度比率")]
        public double AxisVelocityRatio { get; set; } = 1;
        //[Category("轴配置")]
        //[DisplayName("轴速度比率")]
        //[Description("AxisVelocityRatio:轴速度比率")]
        //public double AxisVelocityRatio { get; set; } = 1;
        [Category("延时配置")]
        [DisplayName("动作完成后延迟")]
        [Description("ActionAfterDelay:动作完成后延迟")]
        public int ActionAfterDelay { get; set; } = 100;
        //[Category("延时配置")]
        //[DisplayName("动作完成后延迟")]
        //[Description("ActionAfterDelay:动作完成后延迟")]
        //public int ActionAfterDelay { get; set; } = 100;
        [Category("警报配置")]
        [Description("WarningSetCollection:警报配置列表")]
        [DisplayName("警报配置")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(WarningSetsEditor), typeof(UITypeEditor))]
        public List<IWarningSet> WarningSetCollection { get; set; } = new List<IWarningSet>();
        //[Category("警报配置")]
        //[Description("WarningSetCollection:警报配置列表")]
        //[DisplayName("警报配置")]
        //[TypeConverter(typeof(CollectionCountConvert))]
        //[Editor(typeof(WarningSetsEditor), typeof(UITypeEditor))]
        //public List<IWarningSet> WarningSetCollection { get; set; } = new List<IWarningSet>();
        #region IMonitorConfig
        [Category("监听设置")]
        [Description("MonitorSetCollection:监听操作配置集合")]
        [DisplayName("监听配置")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(ComplexCollectionEditor<MotionCardMonitorSet>), typeof(UITypeEditor))]
        public List<IMonitorSet> MonitorSetCollection { get; set; } = new List<IMonitorSet>();
        //#region IMonitorConfig
        //[Category("监听设置")]
        //[Description("MonitorSetCollection:监听操作配置集合")]
        //[DisplayName("监听配置")]
        //[TypeConverter(typeof(CollectionCountConvert))]
        //[Editor(typeof(ComplexCollectionEditor<MotionCardMonitorSet>), typeof(UITypeEditor))]
        //public List<IMonitorSet> MonitorSetCollection { get; set; } = new List<IMonitorSet>();
        [Category("监听设置")]
        [Description("true:启动监听 false:关闭监听")]
        [DisplayName("监听启用")]
        public bool IsEnableMonitor { get; set; } = true;
        //[Category("监听设置")]
        //[Description("true:启动监听 false:关闭监听")]
        //[DisplayName("监听启用")]
        //public bool IsEnableMonitor { get; set; } = true;
        [Category("监听设置")]
        [Description("扫描间隔时间,单位:ms")]
        [DisplayName("扫描间隔")]
        public int MonitorInterval { get; set; } = 10;
        //[Category("监听设置")]
        //[Description("扫描间隔时间,单位:ms")]
        //[DisplayName("扫描间隔")]
        //public int MonitorInterval { get; set; } = 10;
        [Category("监听设置")]
        [Description("超时设置,单位:ms")]
        [DisplayName("监听超时")]
        public int MonitorTimeout { get; set; } = 500;
        [Category("事件地址设置")]
        [Description("事件开始地址,PLC的实际寄存器地址。十进制,不包含功能码。")]
        [DisplayName("监听开始地址")]
        public int EventStartAddress { get; set; } = 8000;
        //[Category("监听设置")]
        //[Description("超时设置,单位:ms")]
        //[DisplayName("监听超时")]
        //public int MonitorTimeout { get; set; } = 500;
        //[Category("事件地址设置")]
        //[Description("事件地址长度,最大长度128")]
        //[DisplayName("监听长度")]
        //public int EventLength { get; set; } = 120;
        //[Description("事件开始地址,PLC的实际寄存器地址。十进制,不包含功能码。")]
        //[DisplayName("监听开始地址")]
        //public int EventStartAddress { get; set; } = 8000;
        public List<IMonitorSet> GetAllMonitorSet()
        {
            WarningSetCollection.ForEach(m => m.Source = this.Name);
        ////[Category("事件地址设置")]
        ////[Description("事件地址长度,最大长度128")]
        ////[DisplayName("监听长度")]
        ////public int EventLength { get; set; } = 120;
            MonitorSetCollection.ForEach(m => m.SourceDevice = this.Id);
            return MonitorSetCollection;
        }
        #endregion
        //public List<IMonitorSet> GetAllMonitorSet()
        //{
        //    WarningSetCollection.ForEach(m => m.Source = this.Name);
        //    MonitorSetCollection.ForEach(m => m.SourceDevice = this.Id);
        //    return MonitorSetCollection;
        //}
        //#endregion
        //#region IMotion Related
        //[Category("运动配置")]
@@ -127,492 +127,492 @@
        //#endregion
    }
    /// <summary>
    /// 轴配置
    /// </summary>
    public class AxisSetting : IComplexDisplay
    {
        [Category("轴配置")]
        [DisplayName("轴号索引")]
        [Description("AxisIndex:轴号索引")]
        public int AxisIndex { get; set; }
    ///// <summary>
    ///// 轴配置
    ///// </summary>
    //public class AxisSetting : IComplexDisplay
    //{
    //    [Category("轴配置")]
    //    [DisplayName("轴号索引")]
    //    [Description("AxisIndex:轴号索引")]
    //    public int AxisIndex { get; set; }
        [Category("轴配置")]
        [DisplayName("轴名称")]
        [Description("AxisName:轴名称")]
        public string AxisName { get; set; }
    //    [Category("轴配置")]
    //    [DisplayName("轴名称")]
    //    [Description("AxisName:轴名称")]
    //    public string AxisName { get; set; }
        [Category("轴配置")]
        [DisplayName("轴是否启用")]
        [Description("IsAxisEnabled:轴是否启用")]
        public bool IsAxisEnabled { get; set; } = false;
    //    [Category("轴配置")]
    //    [DisplayName("轴是否启用")]
    //    [Description("IsAxisEnabled:轴是否启用")]
    //    public bool IsAxisEnabled { get; set; } = false;
        [Category("换算配置")]
        [DisplayName("脉冲数换算比例")]
        [Description("脉冲数和其他计量单位的换算比例,例如设置为1000,表示1000个脉冲等于1uint")]
        public int PulseRatio { get; set; } = 1;
    //    [Category("换算配置")]
    //    [DisplayName("脉冲数换算比例")]
    //    [Description("脉冲数和其他计量单位的换算比例,例如设置为1000,表示1000个脉冲等于1uint")]
    //    public int PulseRatio { get; set; } = 1;
        [Category("速度配置")]
        [DisplayName("默认速度参数")]
        [Description("VelocityPara:默认速度参数")]
        [TypeConverter(typeof(ComplexObjectConvert))]
        [Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))]
        public VelocityPara VelocityPara { get; set; } = new VelocityPara();
    //    [Category("速度配置")]
    //    [DisplayName("默认速度参数")]
    //    [Description("VelocityPara:默认速度参数")]
    //    [TypeConverter(typeof(ComplexObjectConvert))]
    //    [Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))]
    //    public VelocityPara VelocityPara { get; set; } = new VelocityPara();
        [Category("回原点设置")]
        [DisplayName("回原点模式")]
        [Description("HomeMode:回原点模式。0:一般模式 1:极限限位模式 2:外部触发模式")]
        public int HomeMode { get; set; } = 0;
    //    [Category("回原点设置")]
    //    [DisplayName("回原点模式")]
    //    [Description("HomeMode:回原点模式。0:一般模式 1:极限限位模式 2:外部触发模式")]
    //    public int HomeMode { get; set; } = 0;
        [Category("回原点设置")]
        [DisplayName("回原点方向")]
        [Description("IsHomePositive:回原点方向。 true:正方向开始  false:负方向开始")]
        public bool IsHomePositive { get; set; } = true;
    //    [Category("回原点设置")]
    //    [DisplayName("回原点方向")]
    //    [Description("IsHomePositive:回原点方向。 true:正方向开始  false:负方向开始")]
    //    public bool IsHomePositive { get; set; } = true;
        [Category("回原点设置")]
        [DisplayName("是否自动回原点")]
        [Description("IsAutoGoHome:是否自动回原点。 true:是  false:否")]
        public bool IsAutoGoHome { get; set; } = false;
    //    [Category("回原点设置")]
    //    [DisplayName("是否自动回原点")]
    //    [Description("IsAutoGoHome:是否自动回原点。 true:是  false:否")]
    //    public bool IsAutoGoHome { get; set; } = false;
        [Category("超时设置")]
        [DisplayName("回原点超时")]
        [Description("TimeOutHome:回原点超时,单位毫秒")]
        public int TimeOutHome { get; set; } = 30000;
    //    [Category("超时设置")]
    //    [DisplayName("回原点超时")]
    //    [Description("TimeOutHome:回原点超时,单位毫秒")]
    //    public int TimeOutHome { get; set; } = 30000;
        [Category("超时设置")]
        [DisplayName("运动超时")]
        [Description("TimeOutMove:运动超时,单位毫秒")]
        public int TimeOutMove { get; set; } = 10000;
    //    [Category("超时设置")]
    //    [DisplayName("运动超时")]
    //    [Description("TimeOutMove:运动超时,单位毫秒")]
    //    public int TimeOutMove { get; set; } = 10000;
        [Category("开闭环设置")]
        [DisplayName("是否使用Cmmd回馈")]
        [Description("IsUseCmmdPosition:是否使用Cmmd回馈")]
        public bool IsUseCmmdPosition { get; set; } = false;
    //    [Category("开闭环设置")]
    //    [DisplayName("是否使用Cmmd回馈")]
    //    [Description("IsUseCmmdPosition:是否使用Cmmd回馈")]
    //    public bool IsUseCmmdPosition { get; set; } = false;
        [Category("开闭环设置")]
        [DisplayName("是否使用板卡反馈停止信号")]
        [Description("IsUseMDNStopSignal:是否使用板卡反馈停止信号")]
        public bool IsUseMDNStopSignal { get; set; } = false;
    //    [Category("开闭环设置")]
    //    [DisplayName("是否使用板卡反馈停止信号")]
    //    [Description("IsUseMDNStopSignal:是否使用板卡反馈停止信号")]
    //    public bool IsUseMDNStopSignal { get; set; } = false;
        [Category("开闭环设置")]
        [DisplayName("是否启用报警")]
        [Description("IsUseWarning:是否启用报警")]
        public bool IsUseWarning { get; set; } = false;
    //    [Category("开闭环设置")]
    //    [DisplayName("是否启用报警")]
    //    [Description("IsUseWarning:是否启用报警")]
    //    public bool IsUseWarning { get; set; } = false;
        [Category("暂停配置")]
        [DisplayName("是否启用立即暂停")]
        [Description("IsImmediatePause:是否启用立即暂停")]
        public bool IsImmediatePause { get; set; } = false;
    //    [Category("暂停配置")]
    //    [DisplayName("是否启用立即暂停")]
    //    [Description("IsImmediatePause:是否启用立即暂停")]
    //    public bool IsImmediatePause { get; set; } = false;
        [Category("暂停配置")]
        [DisplayName("轴位置处于区间内时适用的暂停操作")]
        [Description("ImmediatePauseSections:当轴位置处于区间内时适用的暂停操作")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(ComplexCollectionEditor<Section>), typeof(UITypeEditor))]
        public List<Section> ImmediatePauseSections { get; set; } = new List<Section>();
    //    [Category("暂停配置")]
    //    [DisplayName("轴位置处于区间内时适用的暂停操作")]
    //    [Description("ImmediatePauseSections:当轴位置处于区间内时适用的暂停操作")]
    //    [TypeConverter(typeof(CollectionCountConvert))]
    //    [Editor(typeof(ComplexCollectionEditor<Section>), typeof(UITypeEditor))]
    //    public List<Section> ImmediatePauseSections { get; set; } = new List<Section>();
        public string GetDisplayText()
        {
            return AxisIndex + "-" + AxisName + "-" + (IsAxisEnabled ? "启用" : "禁用");
        }
    }
    //    public string GetDisplayText()
    //    {
    //        return AxisIndex + "-" + AxisName + "-" + (IsAxisEnabled ? "启用" : "禁用");
    //    }
    //}
    /// <summary>
    /// 位置对象
    /// </summary>
    public class Section : IComplexDisplay
    {
        [Category("暂停区间")]
        [DisplayName("起始位置")]
        [Description("StartPosition:起始位置")]
        public int StartPosition { get; set; }
    ///// <summary>
    ///// 位置对象
    ///// </summary>
    //public class Section : IComplexDisplay
    //{
    //    [Category("暂停区间")]
    //    [DisplayName("起始位置")]
    //    [Description("StartPosition:起始位置")]
    //    public int StartPosition { get; set; }
        [Category("暂停区间")]
        [DisplayName("结束位置")]
        [Description("EndPosition:结束位置")]
        public int EndPosition { get; set; }
    //    [Category("暂停区间")]
    //    [DisplayName("结束位置")]
    //    [Description("EndPosition:结束位置")]
    //    public int EndPosition { get; set; }
        public string GetDisplayText()
        {
            return $"{StartPosition}--{EndPosition}";
        }
    }
    //    public string GetDisplayText()
    //    {
    //        return $"{StartPosition}--{EndPosition}";
    //    }
    //}
    /// <summary>
    /// 速度参数对象
    /// </summary>
    public class VelocityPara
    {
        [Category("速度配置")]
        [DisplayName("速度")]
        [Description("Velocity:速度,为0时表示不修改当前设置")]
        public double Velocity { get; set; } = 0;
    ///// <summary>
    ///// 速度参数对象
    ///// </summary>
    //public class VelocityPara
    //{
    //    [Category("速度配置")]
    //    [DisplayName("速度")]
    //    [Description("Velocity:速度,为0时表示不修改当前设置")]
    //    public double Velocity { get; set; } = 0;
        [Category("速度配置")]
        [DisplayName("加速度")]
        [Description("Acc:加速度,为0时表示不修改当前设置")]
        public double Acc { get; set; } = 1;
    //    [Category("速度配置")]
    //    [DisplayName("加速度")]
    //    [Description("Acc:加速度,为0时表示不修改当前设置")]
    //    public double Acc { get; set; } = 1;
        [Category("速度配置")]
        [DisplayName("减速度")]
        [Description("减速度,为0时表示不修改当前设置")]
        public double Dec { get; set; } = 1;
    }
    //    [Category("速度配置")]
    //    [DisplayName("减速度")]
    //    [Description("减速度,为0时表示不修改当前设置")]
    //    public double Dec { get; set; } = 1;
    //}
    /// <summary>
    /// 回原点参数对象
    /// </summary>
    public class GoHomePara
    {
        [Category("回原点参数")]
        [DisplayName("回原点方式")]
        [Description("HomeMode:回原点方式 (HOME_MODE_LIMIT = 10; HOME_MODE_LIMIT_HOME = 11; HOME_MODE_LIMIT_INDEX = 12; HOME_MODE_LIMIT_HOME_INDEX = 13;HOME_MODE_HOME = 20;HOME_MODE_HOME_INDEX = 22;HOME_MODE_INDEX = 30;")]
        public short HomeMode { get; set; } = 11;
    ///// <summary>
    ///// 回原点参数对象
    ///// </summary>
    //public class GoHomePara
    //{
    //    [Category("回原点参数")]
    //    [DisplayName("回原点方式")]
    //    [Description("HomeMode:回原点方式 (HOME_MODE_LIMIT = 10; HOME_MODE_LIMIT_HOME = 11; HOME_MODE_LIMIT_INDEX = 12; HOME_MODE_LIMIT_HOME_INDEX = 13;HOME_MODE_HOME = 20;HOME_MODE_HOME_INDEX = 22;HOME_MODE_INDEX = 30;")]
    //    public short HomeMode { get; set; } = 11;
        [Category("回原点参数")]
        [DisplayName("回原点方向")]
        [Description("HomeDir:1 正向,-1 负向")]
        public short HomeDir { get; set; } = 1;
    //    [Category("回原点参数")]
    //    [DisplayName("回原点方向")]
    //    [Description("HomeDir:1 正向,-1 负向")]
    //    public short HomeDir { get; set; } = 1;
        [Category("回原点参数")]
        [DisplayName("回原点方向")]
        [Description("HomeDir:1 正向,-1 负向")]
        public short Edge { get; set; } = 0;
    //    [Category("回原点参数")]
    //    [DisplayName("回原点方向")]
    //    [Description("HomeDir:1 正向,-1 负向")]
    //    public short Edge { get; set; } = 0;
        [Category("回原点参数")]
        [DisplayName("回原点最低速度")]
        [Description("LowVelocity:速度,为0时表示不修改当前设置")]
        public double LowVelocity { get; set; } = 50;
    //    [Category("回原点参数")]
    //    [DisplayName("回原点最低速度")]
    //    [Description("LowVelocity:速度,为0时表示不修改当前设置")]
    //    public double LowVelocity { get; set; } = 50;
        [Category("回原点参数")]
        [DisplayName("回原点最高速度")]
        [Description("HighVelocity:速度,为0时表示不修改当前设置")]
        public double HighVelocity { get; set; } = 50;
    //    [Category("回原点参数")]
    //    [DisplayName("回原点最高速度")]
    //    [Description("HighVelocity:速度,为0时表示不修改当前设置")]
    //    public double HighVelocity { get; set; } = 50;
        [Category("回原点参数")]
        [DisplayName("搜搜距离")]
        [Description("SearchHomeDistance:搜搜距离")]
        public int SearchHomeDistance { get; set; } = 9999999;
    //    [Category("回原点参数")]
    //    [DisplayName("搜搜距离")]
    //    [Description("SearchHomeDistance:搜搜距离")]
    //    public int SearchHomeDistance { get; set; } = 9999999;
        [Category("回原点参数")]
        [DisplayName("偏移距离")]
        [Description("HomeOffset:偏移距离")]
        public int HomeOffset { get; set; } = 0;
    //    [Category("回原点参数")]
    //    [DisplayName("偏移距离")]
    //    [Description("HomeOffset:偏移距离")]
    //    public int HomeOffset { get; set; } = 0;
        [Category("回原点参数")]
        [DisplayName("跳过步长")]
        [Description("EscapeStep:跳过步长")]
        public int EscapeStep { get; set; } = 1000;
    //    [Category("回原点参数")]
    //    [DisplayName("跳过步长")]
    //    [Description("EscapeStep:跳过步长")]
    //    public int EscapeStep { get; set; } = 1000;
    }
    //}
    /// <summary>
    /// 运动对象
    /// </summary>
    public class MovingOption : INotifyPropertyChanged, IComplexDisplay
    {
        private int axisIndex = 0;
        [Category("运动配置")]
        [DisplayName("运动轴索引")]
        [Description("AxisIndex:运动轴索引")]
        [TypeConverter(typeof(AxisIndexConvert))]
        public int AxisIndex
        {
            get => axisIndex;
            set
            {
                if (axisIndex != value)
                {
                    axisIndex = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("AxisIndex"));
                }
                axisIndex = value;
            }
        }
    ///// <summary>
    ///// 运动对象
    ///// </summary>
    //public class MovingOption : INotifyPropertyChanged, IComplexDisplay
    //{
    //    private int axisIndex = 0;
    //    [Category("运动配置")]
    //    [DisplayName("运动轴索引")]
    //    [Description("AxisIndex:运动轴索引")]
    //    [TypeConverter(typeof(AxisIndexConvert))]
    //    public int AxisIndex
    //    {
    //        get => axisIndex;
    //        set
    //        {
    //            if (axisIndex != value)
    //            {
    //                axisIndex = value;
    //                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("AxisIndex"));
    //            }
    //            axisIndex = value;
    //        }
    //    }
        private MotorMoveMode moveMode = MotorMoveMode.Normal;
        [Category("运动配置")]
        [DisplayName("运动模式")]
        [Description("MoveMode:运动模式")]
        public MotorMoveMode MoveMode
        {
            get => moveMode;
            set
            {
                if (moveMode != value)
                {
                    moveMode = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("MoveMode"));
                }
    //    private MotorMoveMode moveMode = MotorMoveMode.Normal;
    //    [Category("运动配置")]
    //    [DisplayName("运动模式")]
    //    [Description("MoveMode:运动模式")]
    //    public MotorMoveMode MoveMode
    //    {
    //        get => moveMode;
    //        set
    //        {
    //            if (moveMode != value)
    //            {
    //                moveMode = value;
    //                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("MoveMode"));
    //            }
                moveMode = value;
            }
        }
    //            moveMode = value;
    //        }
    //    }
        private bool isAbsolute = true;
        [Category("运动配置")]
        [DisplayName("是否绝对运动")]
        [Description("IsAbsolute:是否绝对运动")]
        public bool IsAbsolute
        {
            get => isAbsolute;
            set
            {
                if (isAbsolute != value)
                {
                    isAbsolute = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsAbsolute"));
                }
    //    private bool isAbsolute = true;
    //    [Category("运动配置")]
    //    [DisplayName("是否绝对运动")]
    //    [Description("IsAbsolute:是否绝对运动")]
    //    public bool IsAbsolute
    //    {
    //        get => isAbsolute;
    //        set
    //        {
    //            if (isAbsolute != value)
    //            {
    //                isAbsolute = value;
    //                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsAbsolute"));
    //            }
                isAbsolute = value;
            }
        }
    //            isAbsolute = value;
    //        }
    //    }
        private int destination = 0;
        [Category("运动配置")]
        [DisplayName("目的地")]
        [Description("Destination:目的地")]
        public int Destination
        {
            get => destination;
            set
            {
                if (destination != value)
                {
                    destination = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Destination"));
                }
    //    private int destination = 0;
    //    [Category("运动配置")]
    //    [DisplayName("目的地")]
    //    [Description("Destination:目的地")]
    //    public int Destination
    //    {
    //        get => destination;
    //        set
    //        {
    //            if (destination != value)
    //            {
    //                destination = value;
    //                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Destination"));
    //            }
                destination = value;
            }
        }
    //            destination = value;
    //        }
    //    }
        private VelocityPara velocityPara = new VelocityPara();
        [Category("运动配置")]
        [DisplayName("速度参数")]
        [Description("VelocityPara:速度参数")]
        [TypeConverter(typeof(ComplexObjectConvert))]
        [Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))]
        public VelocityPara VelocityPara
        {
            get => velocityPara;
            set
            {
                velocityPara = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("VelocityPara"));
            }
        }
    //    private VelocityPara velocityPara = new VelocityPara();
    //    [Category("运动配置")]
    //    [DisplayName("速度参数")]
    //    [Description("VelocityPara:速度参数")]
    //    [TypeConverter(typeof(ComplexObjectConvert))]
    //    [Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))]
    //    public VelocityPara VelocityPara
    //    {
    //        get => velocityPara;
    //        set
    //        {
    //            velocityPara = value;
    //            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("VelocityPara"));
    //        }
    //    }
        private GoHomePara goHomePara = new GoHomePara();
        [Category("运动配置")]
        [DisplayName("回原点参数")]
        [Description("GoHomePara:速度参数")]
        [TypeConverter(typeof(ComplexObjectConvert))]
        [Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))]
        public GoHomePara GoHomePara
        {
            get => goHomePara;
            set
            {
                goHomePara = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("GoHomePara"));
            }
        }
    //    private GoHomePara goHomePara = new GoHomePara();
    //    [Category("运动配置")]
    //    [DisplayName("回原点参数")]
    //    [Description("GoHomePara:速度参数")]
    //    [TypeConverter(typeof(ComplexObjectConvert))]
    //    [Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))]
    //    public GoHomePara GoHomePara
    //    {
    //        get => goHomePara;
    //        set
    //        {
    //            goHomePara = value;
    //            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("GoHomePara"));
    //        }
    //    }
        internal List<AxisSetting> _axisSettingList = new List<AxisSetting>();
        public void SetAxisSetting(List<AxisSetting> settings)
        {
            if (settings != null)
                _axisSettingList = settings;
        }
    //    internal List<AxisSetting> _axisSettingList = new List<AxisSetting>();
    //    public void SetAxisSetting(List<AxisSetting> settings)
    //    {
    //        if (settings != null)
    //            _axisSettingList = settings;
    //    }
        public string GetDisplayText()
        {
            string axisName = AxisIndex.ToString();
            var axisSet = _axisSettingList.FirstOrDefault(a => a.AxisIndex == AxisIndex);
            if (axisSet != null)
            {
                axisName += ("-" + axisSet.AxisName);
            }
            return axisName + "," + MoveMode.ToString() + "," + (IsAbsolute ? "Abs" : "Rel") + "," + Destination;
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }
    //    public string GetDisplayText()
    //    {
    //        string axisName = AxisIndex.ToString();
    //        var axisSet = _axisSettingList.FirstOrDefault(a => a.AxisIndex == AxisIndex);
    //        if (axisSet != null)
    //        {
    //            axisName += ("-" + axisSet.AxisName);
    //        }
    //        return axisName + "," + MoveMode.ToString() + "," + (IsAbsolute ? "Abs" : "Rel") + "," + Destination;
    //    }
    //    public event PropertyChangedEventHandler PropertyChanged;
    //}
    public class AxisIndexConvert : TypeConverter
    {
        Dictionary<int, string> _indexNameDict = new Dictionary<int, string>();
    //public class AxisIndexConvert : TypeConverter
    //{
    //    Dictionary<int, string> _indexNameDict = new Dictionary<int, string>();
        public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
        {
            return true;
        }
    //    public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
    //    {
    //        return true;
    //    }
        public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
        {
            MovingOption mo = context.Instance as MovingOption;
    //    public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
    //    {
    //        MovingOption mo = context.Instance as MovingOption;
            _indexNameDict = mo._axisSettingList.ToDictionary(a => a.AxisIndex, a => a.AxisIndex + "-" + a.AxisName);
    //        _indexNameDict = mo._axisSettingList.ToDictionary(a => a.AxisIndex, a => a.AxisIndex + "-" + a.AxisName);
            return new StandardValuesCollection(_indexNameDict.Keys);
        }
    //        return new StandardValuesCollection(_indexNameDict.Keys);
    //    }
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            if (sourceType == typeof(string))
            {
                return true;
            }
            return base.CanConvertFrom(context, sourceType);
        }
    //    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    //    {
    //        if (sourceType == typeof(string))
    //        {
    //            return true;
    //        }
    //        return base.CanConvertFrom(context, sourceType);
    //    }
        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object v)
        {
            if (v is string)
            {
                foreach (var indexName in _indexNameDict)
                {
                    if (indexName.Value == v.ToString())
                    {
                        return indexName.Key;
                    }
                }
                return Convert.ToInt32(v);
            }
            return base.ConvertFrom(context, culture, v);
        }
    //    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object v)
    //    {
    //        if (v is string)
    //        {
    //            foreach (var indexName in _indexNameDict)
    //            {
    //                if (indexName.Value == v.ToString())
    //                {
    //                    return indexName.Key;
    //                }
    //            }
    //            return Convert.ToInt32(v);
    //        }
    //        return base.ConvertFrom(context, culture, v);
    //    }
        public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object v, Type destinationType)
        {
            if (destinationType == typeof(string))
            {
                if (_indexNameDict.ContainsKey(Convert.ToInt32(v)))
                {
                    return _indexNameDict[Convert.ToInt32(v)];
                }
            }
            return base.ConvertTo(context, culture, v, destinationType);
        }
    //    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object v, Type destinationType)
    //    {
    //        if (destinationType == typeof(string))
    //        {
    //            if (_indexNameDict.ContainsKey(Convert.ToInt32(v)))
    //            {
    //                return _indexNameDict[Convert.ToInt32(v)];
    //            }
    //        }
    //        return base.ConvertTo(context, culture, v, destinationType);
    //    }
        public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
        {
            return false;
        }
    }
    //    public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
    //    {
    //        return false;
    //    }
    //}
    public class AxisConflictSet : IComplexDisplay
    {
        [Category("1.轴冲突条件")]
        [Description("轴冲突条件,满足全部条件时轴运动需要检查冲突")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(ComplexCollectionEditor<AxisLimit>), typeof(UITypeEditor))]
        public List<AxisLimit> AxisOptions { get; set; } = new List<AxisLimit>();
    //public class AxisConflictSet : IComplexDisplay
    //{
    //    [Category("1.轴冲突条件")]
    //    [Description("轴冲突条件,满足全部条件时轴运动需要检查冲突")]
    //    [TypeConverter(typeof(CollectionCountConvert))]
    //    [Editor(typeof(ComplexCollectionEditor<AxisLimit>), typeof(UITypeEditor))]
    //    public List<AxisLimit> AxisOptions { get; set; } = new List<AxisLimit>();
        [Category("1.轴冲突条件")]
        [Description("IO冲突条件,满足全部条件时轴运动需要检查冲突")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(ComplexCollectionEditor<IOLimit>), typeof(UITypeEditor))]
        public List<IOLimit> IOOptions { get; set; } = new List<IOLimit>();
    //    [Category("1.轴冲突条件")]
    //    [Description("IO冲突条件,满足全部条件时轴运动需要检查冲突")]
    //    [TypeConverter(typeof(CollectionCountConvert))]
    //    [Editor(typeof(ComplexCollectionEditor<IOLimit>), typeof(UITypeEditor))]
    //    public List<IOLimit> IOOptions { get; set; } = new List<IOLimit>();
        [Category("2.轴冲突限制")]
        [Description("轴冲突限制,轴运动允许区间")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(ComplexCollectionEditor<AxisLimit>), typeof(UITypeEditor))]
        public List<AxisLimit> AxisLimits { get; set; } = new List<AxisLimit>();
    //    [Category("2.轴冲突限制")]
    //    [Description("轴冲突限制,轴运动允许区间")]
    //    [TypeConverter(typeof(CollectionCountConvert))]
    //    [Editor(typeof(ComplexCollectionEditor<AxisLimit>), typeof(UITypeEditor))]
    //    public List<AxisLimit> AxisLimits { get; set; } = new List<AxisLimit>();
        [Category("2.轴冲突限制")]
        [Description("IO允许条件,允许输出的IO")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(ComplexCollectionEditor<IOLimit>), typeof(UITypeEditor))]
        public List<IOLimit> IOOutputs { get; set; } = new List<IOLimit>();
    //    [Category("2.轴冲突限制")]
    //    [Description("IO允许条件,允许输出的IO")]
    //    [TypeConverter(typeof(CollectionCountConvert))]
    //    [Editor(typeof(ComplexCollectionEditor<IOLimit>), typeof(UITypeEditor))]
    //    public List<IOLimit> IOOutputs { get; set; } = new List<IOLimit>();
        [Category("3.轴冲突启用")]
        [Description("true:启用轴冲突限制 false:不启用轴冲突限制")]
        public bool IsEnabled { get; set; } = true;
    //    [Category("3.轴冲突启用")]
    //    [Description("true:启用轴冲突限制 false:不启用轴冲突限制")]
    //    public bool IsEnabled { get; set; } = true;
        public string GetDisplayText()
        {
            string optionStr = "Options:" + String.Join(";", AxisOptions.Select(a => a.GetDisplayText()));
            string limitStr = "Limits:" + String.Join(";", AxisLimits.Select(a => a.GetDisplayText()));
    //    public string GetDisplayText()
    //    {
    //        string optionStr = "Options:" + String.Join(";", AxisOptions.Select(a => a.GetDisplayText()));
    //        string limitStr = "Limits:" + String.Join(";", AxisLimits.Select(a => a.GetDisplayText()));
            return optionStr + "|" + limitStr;
        }
    }
    //        return optionStr + "|" + limitStr;
    //    }
    //}
    public class AxisLimit : IComplexDisplay
    {
        [Category("1.轴号")]
        [Description("1.轴号")]
        public int AxisIndex { get; set; }
    //public class AxisLimit : IComplexDisplay
    //{
    //    [Category("1.轴号")]
    //    [Description("1.轴号")]
    //    public int AxisIndex { get; set; }
        [Category("2.轴最小限制")]
        [Description("2.轴最小限制")]
        public int LimitMin { get; set; }
    //    [Category("2.轴最小限制")]
    //    [Description("2.轴最小限制")]
    //    public int LimitMin { get; set; }
        [Category("3.轴最大限制")]
        [Description("3.轴最大限制")]
        public int LimitMax { get; set; }
    //    [Category("3.轴最大限制")]
    //    [Description("3.轴最大限制")]
    //    public int LimitMax { get; set; }
        private int currentPosition = 0;
        [Browsable(false)]
        [JsonIgnore]
        public int CurrentPosition
        {
            get => currentPosition;
            set
            {
                if (currentPosition != value)
                {
                    if (value >= LimitMin && value <= LimitMax)
                    {
                        IsInLimit = true;
                    }
                    else
                    {
                        IsInLimit = false;
                    }
                }
    //    private int currentPosition = 0;
    //    [Browsable(false)]
    //    [JsonIgnore]
    //    public int CurrentPosition
    //    {
    //        get => currentPosition;
    //        set
    //        {
    //            if (currentPosition != value)
    //            {
    //                if (value >= LimitMin && value <= LimitMax)
    //                {
    //                    IsInLimit = true;
    //                }
    //                else
    //                {
    //                    IsInLimit = false;
    //                }
    //            }
                currentPosition = value;
            }
        }
    //            currentPosition = value;
    //        }
    //    }
        [Browsable(false)]
        [JsonIgnore]
        public bool IsInLimit { get; set; }
    //    [Browsable(false)]
    //    [JsonIgnore]
    //    public bool IsInLimit { get; set; }
        public string GetDisplayText()
        {
            return String.Format("Index:{0},{1}->{2}", AxisIndex, LimitMin, LimitMax);
        }
    }
    //    public string GetDisplayText()
    //    {
    //        return String.Format("Index:{0},{1}->{2}", AxisIndex, LimitMin, LimitMax);
    //    }
    //}
    public class IOLimit : IComplexDisplay
    {
        [Category("1.IO限制")]
        [Description("IO索引")]
        public int IOIndex { get; set; }
    //public class IOLimit : IComplexDisplay
    //{
    //    [Category("1.IO限制")]
    //    [Description("IO索引")]
    //    public int IOIndex { get; set; }
        [Category("1.IO限制")]
        [Description("IO限制值。输入判断时该值作为启用判断值,输出判断时该值作为允许输出值")]
        public bool IOSignal { get; set; }
    //    [Category("1.IO限制")]
    //    [Description("IO限制值。输入判断时该值作为启用判断值,输出判断时该值作为允许输出值")]
    //    public bool IOSignal { get; set; }
        public string GetDisplayText()
        {
            return IOIndex + "--" + IOSignal.ToString();
        }
    }
    //    public string GetDisplayText()
    //    {
    //        return IOIndex + "--" + IOSignal.ToString();
    //    }
    //}
    public class AxisMovingStay
    {
        public int Position { get; set; }
    //public class AxisMovingStay
    //{
    //    public int Position { get; set; }
        public int Velocity { get; set; }
    //    public int Velocity { get; set; }
        public AutoResetEvent MoveHandle { get; set; } = new AutoResetEvent(false);
    //    public AutoResetEvent MoveHandle { get; set; } = new AutoResetEvent(false);
        public AutoResetEvent MoveSendHandle { get; set; } = new AutoResetEvent(false);
    }
    //    public AutoResetEvent MoveSendHandle { get; set; } = new AutoResetEvent(false);
    //}
}
src/Bro.Device.GTSCard/GTSCardDriver.cs
@@ -153,7 +153,7 @@
        /// </summary>
        /// <param name="item">运动对象</param>
        /// <returns>运动控制+停止判断</returns>
        public bool MoveToPoint(IOperationConfig opConfig)
        public ResponseMessage MoveToPoint(IOperationConfig opConfig)
        {
            bool resultOK = false;
            var gtsOperationConfig = opConfig as GTSCardOperationConfig;
@@ -172,7 +172,8 @@
            Task.WaitAll(taskList.ToArray());
            resultOK = taskList.All(u => u.GetAwaiter().GetResult());
            return resultOK;
            //return resultOK;
            throw new NotImplementedException();
        }
        /// <summary>
@@ -702,13 +703,13 @@
                {
                    IONum = index,
                    Value = (inValue & (1 << index)) == 0 ? 1 : 0,
                    Model = IOModel.In
                    IOType = IOType.In
                };
                IOItem outItem = new IOItem()
                {
                    IONum = index,
                    Value = (outValue & (1 << index)) == 0 ? 1 : 0,
                    Model = IOModel.Out
                    IOType = IOType.Out
                };
                result.Add(inItem);
                result.Add(outItem);
@@ -779,7 +780,7 @@
            foreach (var replyIOData in monitorSet.ReplyIODatas)
            {
                //写入IO输出
                if (replyIOData.Model == IOModel.Out)
                if (replyIOData.IOType == IOType.Out)
                {
                    GTSCardAPI.GT_SetDoBit((short)IConfig.CardNum, GTSCardAPI.MC_GPI, (short)replyIOData.IONum, (short)replyIOData.Value);
                }
@@ -796,7 +797,7 @@
            {
                MotionCardWarningSet warningSet = wSet as MotionCardWarningSet;
                bool isOn = ((tempNew.FirstOrDefault(u => u.IONum == warningSet.TriggerIndex && u.Model == warningSet.WarningIOModel)?.Value >> warningSet.TriggerIndex) & 1) == (warningSet.TriggerValue ? 1 : 0);
                bool isOn = ((tempNew.FirstOrDefault(u => u.IONum == warningSet.TriggerIndex && u.IOType == warningSet.WarningIOModel)?.Value >> warningSet.TriggerIndex) & 1) == (warningSet.TriggerValue ? 1 : 0);
                if (warningSet.CurrentStatus != isOn)
                {
src/Bro.M071.Process/M071Process.cs
@@ -231,8 +231,6 @@
            BarCode = "";
            return new ProcessResponse(true);
        }