领胜LDS 键盘AOI检测项目
src/Bro.Common.Device/DeviceBase/MotionCardBase.cs
@@ -12,6 +12,7 @@
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static Bro.Common.Helper.EnumHelper;
namespace Bro.Common.Base
{
@@ -19,19 +20,99 @@
    {
        public event Action<DateTime, string, IDevice, IMonitorSet> OnMonitorInvoke;
        public event Action<DateTime, IDevice, IWarningSet> OnMonitorAlarm;
        public event Action<int, string> OnAxisAlarmRaised;
        public event Action<int, int, int> OnAxisStatusChanged;
        public event Action<int, int> OnAxisPositionChanged;
        public void AxisAlarmRaised(int axisIndex, string msg)
        {
            OnAxisAlarmRaised?.Invoke(axisIndex, msg);
        }
        public void AxisStatusChanged(int axisIndex, int preStatus, int curStatus)
        {
            OnAxisStatusChanged?.Invoke(axisIndex, preStatus, curStatus);
        }
        public void AxisPositionChanged(int axisIndex, int currentPosition)
        {
            OnAxisPositionChanged?.Invoke(axisIndex, currentPosition);
        }
        protected override void Start()
        {
            AxisStatusList = IConfig.AxisSettings.Where(a => a.IsAxisEnabled).ToList().ConvertAll(a =>
            {
                AxisMovingStatus axisSts = new AxisMovingStatus();
                axisSts.AxisIndex = a.AxisIndex;
                axisSts.AxisName = a.AxisName;
                return axisSts;
            });
            Task.Run(() =>
            {
                Monitor();
            });
        }
        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);
        /// <summary>
        /// 清除状态
        /// </summary>
        /// <param name="startAxisIndex">起始轴号</param>
        /// <param name="count">数量</param>
        /// <returns></returns>
        public abstract bool ClearStatus(int startAxisIndex, int count);
        public void ExcuteMonitorInvok(DateTime dateTime, string invokeDevice, IDevice device, IMonitorSet monitorSet)
        /// <summary>
        /// 读取轴状态
        /// </summary>
        /// <param name="axisNum">轴号</param>
        /// <returns></returns>
        public abstract int GetAxisStatus(int axisNum);
        /// <summary>
        /// 位置清零
        /// </summary>
        /// <param name="startAxisIndex">起始轴号</param>
        /// <param name="count">数量</param>
        /// <returns></returns>
        public abstract bool PositionReset(int startAxisIndex, int count);
        public abstract bool AllAxisOn();
        public abstract bool AllAxisOff();
        public abstract Task<bool> AxisOnAsync(int axisNum);
        public abstract Task<bool> AxisOffAsync(int axisNum);
        /// <summary>
        /// 单个轴 运动(点到点 jog 回零...)
        /// </summary>
        /// <param name="optionPara">运动参数对象</param>
        public abstract Task<bool> SingleAxisMoving(MovingOption optionPara);
        /// <summary>
        /// 某个轴运动停止
        /// </summary>
        /// <param name="axisNum">轴号</param>
        /// <param name="option">0表示平滑停止,1表示紧急停止</param>
        /// <returns></returns>
        public abstract Task<bool> MoveStop(int axisNum, int option);
        public virtual void ExcuteMonitorInvoke(DateTime dateTime, string invokeDevice, IDevice device, IMonitorSet monitorSet)
        {
            OnMonitorInvoke?.BeginInvoke(dateTime, invokeDevice, device, monitorSet, null, null);
            OnMonitorInvoke?.BeginInvoke(dateTime, invokeDevice, device, monitorSet, OnMethodInvoked, null);
        }
        public void ExcuteMonitorAlarm(DateTime dateTime, IDevice device, IWarningSet warningSet)
        public abstract void OnMethodInvoked(IAsyncResult ar);
        public virtual void ExcuteMonitorAlarm(DateTime dateTime, IDevice device, IWarningSet warningSet)
        {
            OnMonitorAlarm?.BeginInvoke(dateTime, device, warningSet, null, null);
        }
@@ -43,6 +124,30 @@
                return InitialConfig as MotionCardInitialConfigBase;
            }
        }
        /// <summary>
        /// IO的监听值
        /// </summary>
        public List<IOItem> MonitorValues { get; set; } = new List<IOItem>();
        /// <summary>
        /// 轴的运动状态值
        /// </summary>
        public List<AxisMovingStatus> AxisStatusList { get; set; } = new List<AxisMovingStatus>();
        public abstract void WriteOutput(short index, IOValue value);
        #region ImmediatePause
        /// <summary>
        /// 启动立即暂停
        /// </summary>
        public abstract void SetImmediatePause();
        /// <summary>
        /// 恢复立即暂停
        /// </summary>
        public abstract void ResetImmediatePause(bool isResumeMoving);
        #endregion
    }
    public class MotionCardInitialConfigBase : InitialConfigBase, IMonitorConfig
@@ -50,7 +155,7 @@
        [Category("板卡配置")]
        [DisplayName("卡号")]
        [Description("CardNum:卡号")]
        public int CardNum { get; set; }
        public int CardNum { get; set; } = 1;
        [Category("板卡配置")]
        [DisplayName("初始配置文件路径")]
@@ -93,6 +198,10 @@
        [Editor(typeof(ComplexCollectionEditor<IODefinition>), typeof(UITypeEditor))]
        public List<IODefinition> IODefinitionCollection { get; set; } = new List<IODefinition>();
        [Category("IO配置")]
        [Description("true:输出取反 false:输出不取反")]
        public bool IsOutputReversed { get; set; } = true;
        #region IMonitorConfig
        [Category("监听设置")]
        [Description("MonitorSetCollection:监听操作配置集合")]
@@ -119,35 +228,170 @@
        public List<IMonitorSet> GetAllMonitorSet()
        {
            WarningSetCollection.ForEach(m => m.Source = this.Name);
            MonitorSetCollection.ForEach(m => m.SourceDevice = this.Id);
            return MonitorSetCollection;
        }
        #endregion
    }
    [Device("MotionCardBase", "板卡操作配置基类", EnumHelper.DeviceAttributeType.OperationConfig)]
    public class MotionCardOperationConfigBase : OperationConfigBase, IComplexDisplay
    {
        [Category("IO操作配置")]
        [DisplayName("IO预检查定义集合")]
        [Category("板卡操作")]
        [Description("板卡操作配置基类集合,依次执行")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(MotionCardOperationSetEditor), typeof(UITypeEditor))]
        public List<MotionCardOperationSet> OperationCollection { get; set; } = new List<MotionCardOperationSet>();
        public string GetDisplayText()
        {
            //OperationCollection.ForEach(o =>
            //{
            //    o.MotionCardId = DeviceId;
            //});
            return string.Join(" ", OperationCollection.Select(u => u.GetDisplayText()));
        }
    }
    public class MotionCardOperationSetEditor : ComplexCollectionEditor<MotionCardOperationSet>
    {
        public MotionCardOperationSetEditor(Type type) : base(type) { }
        IOperationConfig opConfig = null;
        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            if (context.Instance is IOperationConfig config && value is List<MotionCardOperationSet> setList)
            {
                opConfig = config;
                setList.ForEach(set => set.MotionCardId = opConfig.DeviceId);
            }
            return base.EditValue(context, provider, value);
        }
        protected override object CreateInstance(Type itemType)
        {
            object obj = base.CreateInstance(itemType);
            if (obj is MotionCardOperationSet set)
            {
                set.MotionCardId = opConfig?.DeviceId;
            }
            return obj;
        }
    }
    [Device("MotionOperationSet", "运动操作配置基类", EnumHelper.DeviceAttributeType.OperationConfig)]
    public class MotionCardOperationSet : IComplexDisplay
    {
        [Category("1.IO操作配置")]
        [DisplayName("1.IO预检查")]
        [Description("IO预检查定义集合")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(IORefrenceItemCollectionEditor), typeof(UITypeEditor))]
        public List<IORefrenceItem> PreCheckIOCollection { get; set; } = new List<IORefrenceItem>();
        [Category("IO操作配置")]
        [DisplayName("IO输出定义集合")]
        [Category("1.IO操作配置")]
        [Description("超时设置,单位:ms")]
        [DisplayName("2.IO预检查超时")]
        public int PreCheckIOTimeout { get; set; } = 0;
        [Category("1.IO操作配置")]
        [DisplayName("3.IO输出")]
        [Description("IO输出定义集合")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(IORefrenceItemCollectionEditor), typeof(UITypeEditor))]
        public List<IORefrenceItem> IOOutputCollection { get; set; } = new List<IORefrenceItem>();
        [Category("IO操作配置")]
        [DisplayName("IO确认定义集合")]
        [Category("1.IO操作配置")]
        [DisplayName("4.IO输出确认")]
        [Description("IO确认定义集合")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(IORefrenceItemCollectionEditor), typeof(UITypeEditor))]
        public List<IORefrenceItem> IOConfirmCollection { get; set; } = new List<IORefrenceItem>();
        [Category("板卡运动配置")]
        [Category("1.IO操作配置")]
        [Description("超时设置,单位:ms")]
        [DisplayName("5.IO输出确认超时")]
        public int IOConfirmTimeout { get; set; } = 0;
        [Category("2.板卡运动配置")]
        [DisplayName("运动配置集合")]
        [Description("MovingOps:运动配置集合")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(MovingOpsCollectionEditor), typeof(UITypeEditor))]
        public List<MovingOption> MovingOps { get; set; } = new List<MovingOption>();
        [Category("3.运动延时")]
        [Description("操作前延时,单位ms")]
        public int DelayBefore { get; set; } = 0;
        [Category("3.运动延时")]
        [Description("操作后延时,单位ms")]
        public int DelayAfter { get; set; } = 0;
        public string MotionCardId = "";
        //[Category("板卡运动配置")]
        //[DisplayName("运动配置集合")]
        //[Description("MovingOps:运动配置集合")]
        //[TypeConverter(typeof(ComplexObjectConvert))]
        //[Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))]
        //public MotionOperationCollection MotionOperationCollection { get; set; } = new MotionOperationCollection();
        public string GetDisplayText()
        {
            string preCheck = "";
            PreCheckIOCollection.ForEach(i =>
            {
                preCheck += i.GetDisplayText() + " ";
            });
            if (preCheck != "")
            {
                preCheck = " 预检:" + preCheck;
            }
            string output = "";
            IOOutputCollection.ForEach(i =>
            {
                output += i.GetDisplayText() + " ";
            });
            if (output != "")
            {
                output = " 输出:" + output;
            }
            string confirm = "";
            IOConfirmCollection.ForEach(i =>
            {
                confirm += i.GetDisplayText() + " ";
            });
            if (confirm != "")
            {
                confirm = " 确认:" + confirm;
            }
            string moving = "";
            MovingOps.ForEach(i =>
            {
                moving += i.GetDisplayText() + " ";
            });
            if (moving != "")
            {
                moving = " 运动:" + moving;
            }
            return (preCheck + output + confirm + moving).Trim();
        }
    }
    public class MotionOperationCollection : OperationConfigBase, IComplexDisplay
    {
        [Category("运动配置")]
        [DisplayName("运动配置集合")]
        [Description("MovingOps:运动配置集合")]
        [TypeConverter(typeof(CollectionCountConvert))]
@@ -156,9 +400,19 @@
        public string GetDisplayText()
        {
            throw new NotImplementedException();
            return $"{string.Join(" ", MovingOps.Select(u => u.GetDisplayText()))}";
        }
    }
    //[Device("MotionCardOperationConfigCollection", "板卡操作配置基类集合", EnumHelper.DeviceAttributeType.OperationConfig)]
    //public class MotionCardOperationConfigCollection : OperationConfigBase
    //{
    //    [Category("复位操作")]
    //    [Description("板卡操作配置基类集合,依次执行")]
    //    [TypeConverter(typeof(CollectionCountConvert))]
    //    [Editor(typeof(ComplexCollectionEditor<MotionCardOperationConfigBase>), typeof(UITypeEditor))]
    //    public List<MotionCardOperationConfigBase> MotionCardOpsCollection { get; set; } = new List<MotionCardOperationConfigBase>();
    //}
    public class IORefrenceItemCollectionEditor : CollectionEditor
    {
@@ -180,10 +434,31 @@
            return form;
        }
        //protected override object CreateInstance(Type itemType)
        //{
        //    return base.CreateInstance(itemType);
        //}
        protected override object CreateInstance(Type itemType)
        {
            if (itemType == typeof(IORefrenceItem))
            {
                IORefrenceItem item = new IORefrenceItem();
                if (this.Context.Instance is MotionCardOperationSet set)
                {
                    using (var scope = GlobalVar.Container.BeginLifetimeScope())
                    {
                        List<IDevice> deviceList = scope.Resolve<List<IDevice>>();
                        var device = deviceList.FirstOrDefault(u => u.Id == set.MotionCardId);
                        if (device != null && (device is MotionCardBase motionCard))
                        {
                            item.IOItemSource = (motionCard.InitialConfig as MotionCardInitialConfigBase).IODefinitionCollection;
                        }
                    }
                }
                return item;
            }
            return base.CreateInstance(itemType);
        }
        //protected override object[] GetItems(object editValue)
        //{
@@ -197,9 +472,9 @@
        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            if (context.Instance is IOperationConfig opConfig)
            if (context.Instance is MotionCardOperationSet set)
            {
                if (string.IsNullOrWhiteSpace(opConfig.DeviceId))
                if (string.IsNullOrWhiteSpace(set.MotionCardId))
                {
                    return base.EditValue(context, provider, value);
                }
@@ -208,7 +483,7 @@
                {
                    List<IDevice> deviceList = scope.Resolve<List<IDevice>>();
                    var device = deviceList.FirstOrDefault(u => u.Id == opConfig.DeviceId);
                    var device = deviceList.FirstOrDefault(u => u.Id == set.MotionCardId);
                    if (device == null)
                    {
@@ -217,9 +492,12 @@
                    if (device is MotionCardBase motionCard)
                    {
                        if (value is IORefrenceItem item)
                        if (value is List<IORefrenceItem> items)
                        {
                            item.IOItemSource = (motionCard.InitialConfig as MotionCardInitialConfigBase).IODefinitionCollection;
                            items.ForEach(item =>
                            {
                                item.IOItemSource = (motionCard.InitialConfig as MotionCardInitialConfigBase).IODefinitionCollection;
                            });
                        }
                    }
                }
@@ -266,4 +544,66 @@
        //}
    }
    public class MovingOpsCollectionEditor : ComplexCollectionEditor<MovingOption>
    {
        public MovingOpsCollectionEditor(Type type) : base(type)
        {
        }
        MotionCardBase motionCard = null;
        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            if (context.Instance is MotionCardOperationSet set)
            {
                if (!string.IsNullOrWhiteSpace(set.MotionCardId))
                {
                    using (var scope = GlobalVar.Container.BeginLifetimeScope())
                    {
                        var deviceList = scope.Resolve<List<IDevice>>();
                        if (deviceList != null)
                        {
                            motionCard = deviceList.FirstOrDefault(u => u.Id == set.MotionCardId) as MotionCardBase;
                        }
                    }
                }
                if (motionCard != null && value is List<MovingOption> ops)
                {
                    ops.ForEach(o => o.SetAxisSetting(motionCard.IConfig.AxisSettings));
                }
            }
            return base.EditValue(context, provider, value);
        }
        protected override object SetItems(object editValue, object[] value)
        {
            Array.ForEach(value, v =>
             {
                 if (v is MovingOption op && motionCard != null)
                 {
                     op.SetAxisSetting(motionCard.IConfig.AxisSettings);
                 }
             });
            return base.SetItems(editValue, value);
        }
        ///// <summary>
        ///// 限制一次选一个实例
        ///// </summary>
        ///// <returns></returns>
        //protected override bool CanSelectMultipleInstances()
        //{
        //    return false;
        //}
        ///// <summary>
        ///// 指定创建的对象类型
        ///// </summary>
        ///// <returns></returns>
        //protected override Type CreateCollectionItemType()
        //{
        //    return typeof(MovingOption);
        //}
    }
}