领胜LDS 键盘AOI检测项目
wells.liu
2020-07-04 642cd31f0d1586a2a5ca6f9a3b3364725f4f1ecd
暂存
3个文件已添加
1个文件已删除
16个文件已修改
667 ■■■■ 已修改文件
src/Bro.Common.Device/DeviceBase/MotionCardBase.cs 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.Common.Model/Helper/EnumHelper.cs 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.Common.Model/Model/IOItem.cs 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.Device.GTSCard/GTSCardDriver.cs 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/Bro.M071.Process.csproj 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/M071Config.cs 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/M071Models.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/M071Process.cs 56 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/M071Process_IO.cs 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/M071Process_MotionCard.cs 217 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/UI/M071_MainForm.Designer.cs 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/UI/M071_MainForm.cs 65 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/UI/M071_ShortcutFrm.Designer.cs 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/UI/M071_ShortcutFrm.cs 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Config/MainFrm.Designer.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Config/MainFrm.cs 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Config/MenuForms/FrmConfig.cs 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Config/MenuForms/FrmOperation.cs 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Config/MenuForms/FrmOperation.resx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Device.Winform/MotionCard/CtrlMotionCardOperationBase.cs 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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
{
@@ -26,12 +27,14 @@
        public abstract void ResetAlarm();
        public abstract ResponseMessage Run(IOperationConfig config);
        public void ExcuteMonitorInvok(DateTime dateTime, string invokeDevice, IDevice device, IMonitorSet monitorSet, AsyncCallback OnMethodInvoked)
        public virtual void ExcuteMonitorInvoke(DateTime dateTime, string invokeDevice, IDevice device, IMonitorSet monitorSet)
        {
            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 +46,10 @@
                return InitialConfig as MotionCardInitialConfigBase;
            }
        }
        public List<IOItem> MonitorValues { get; set; } = new List<IOItem>();
        public abstract void WriteOutput(short cardNum, short index, IOValue value);
    }
    public class MotionCardInitialConfigBase : InitialConfigBase, IMonitorConfig
@@ -119,14 +126,28 @@
        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("板卡操作")]
        [Description("板卡操作配置基类集合,依次执行")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(ComplexCollectionEditor<MotionCardOperationConfigBase>), typeof(UITypeEditor))]
        public List<MotionCardOperationSet> OperationCollection { get; set; } = new List<MotionCardOperationSet>();
        public string GetDisplayText()
        {
            return string.Join(" ", OperationCollection.Select(u => u.GetDisplayText()));
        }
    }
    public class MotionCardOperationSet : IComplexDisplay
    {
        [Category("IO操作配置")]
        [DisplayName("IO预检查定义集合")]
@@ -208,6 +229,16 @@
        }
    }
    //[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
    {
        protected override CollectionForm CreateCollectionForm()
src/Bro.Common.Model/Helper/EnumHelper.cs
@@ -577,6 +577,16 @@
            OUTPUT = 1
        }
        public enum IOValue
        {
            [Description("关闭")]
            FALSE = 0,
            [Description("开启")]
            TRUE = 1,
            [Description("反转")]
            REVERSE = 2,
        }
        /// <summary>
        /// PubSubCenter事件中心的消息类型
        /// </summary>
@@ -593,5 +603,14 @@
            //[Description("更新数据")]
            //UpdateData,
        }
        public enum MachineState
        {
            Unknown,
            Ready,
            Running,
            Alarm,
            Pause,
        }
    }
}
src/Bro.Common.Model/Model/IOItem.cs
@@ -22,8 +22,9 @@
        /// IO点的值
        /// </summary>
        [Category("IO配置")]
        [Description("IO数值")]
        public virtual int Value { get; set; }
        [Description("IO状态")]
        [TypeConverter(typeof(EnumDescriptionConverter<IOValue>))]
        public virtual IOValue Value { get; set; }
        /// <summary>
        /// IO点是in还是out
@@ -44,7 +45,7 @@
        public virtual string GetDisplayText()
        {
            return $"{IOType.GetEnumDescription()}-{IONum}-{Value}";
            return $"{IOType.GetEnumDescription()}-{IONum}-{Value.GetEnumDescription()}";
        }
        public int GetHashCode(object obj)
@@ -70,7 +71,7 @@
        [Browsable(false)]
        [JsonIgnore]
        public override int Value { get; set; }
        public override IOValue Value { get; set; }
        public override string GetDisplayText()
        {
@@ -86,8 +87,8 @@
        public IODefinition IOItem { get; set; } = new IODefinition();
        [Category("IO操作配置")]
        [Description("需要操作的IO的数值")]
        public int CheckValue
        [Description("需要操作的IO的状态")]
        public IOValue CheckValue
        {
            get => IOItem.Value;
            set => IOItem.Value = value;
@@ -99,7 +100,7 @@
        public string GetDisplayText()
        {
            return IOItem.IODesc + "-" + CheckValue;
            return IOItem.IODesc + "-" + CheckValue.GetEnumDescription();
        }
    }
src/Bro.Device.GTSCard/GTSCardDriver.cs
@@ -756,16 +756,17 @@
        /// </summary>
        /// <param name="index">输出口,返回1-16</param>
        /// <param name="value">false表示输出,true表示关闭</param>
        public void WriteOut(short index, bool value)
        public override void WriteOutput(short cardNum, short index, IOValue value)
        {
            short outNum = (short)(index % 100 + 1);
            if (value)
            if ((int)value <= 1)
            {
                GTSCardAPI.GT_SetDoBit((short)IConfig.CardNum, GTSCardAPI.MC_GPO, outNum, 0);
                GTSCardAPI.GT_SetDoBit(cardNum, GTSCardAPI.MC_GPO, outNum, (short)value);
            }
            else
            {
                GTSCardAPI.GT_SetDoBit((short)IConfig.CardNum, GTSCardAPI.MC_GPO, outNum, 1);
                var currentValue = (int)MonitorValues.FirstOrDefault(u => u.IONum == outNum && u.IOType == IOType.OUTPUT).Value;
                GTSCardAPI.GT_SetDoBit(cardNum, GTSCardAPI.MC_GPO, outNum, (short)(currentValue == 1 ? 0 : 1));
            }
        }
@@ -791,7 +792,7 @@
        #region IMonitor
        public List<IOItem> MonitorValues { get; set; } = new List<IOItem>();
        //public List<IOItem> MonitorValues { get; set; } = new List<IOItem>();
        public List<IOItem> GetMonitorValues()
@@ -810,13 +811,13 @@
                IOItem inItem = new IOItem()
                {
                    IONum = index,
                    Value = (inValue & (1 << index)) == 0 ? 1 : 0,
                    Value = (inValue & (1 << index)) == 0 ? IOValue.TRUE : IOValue.FALSE,
                    IOType = IOType.INPUT
                };
                IOItem outItem = new IOItem()
                {
                    IONum = index,
                    Value = (outValue & (1 << index)) == 0 ? 1 : 0,
                    Value = (outValue & (1 << index)) == 0 ? IOValue.TRUE : IOValue.FALSE,
                    IOType = IOType.OUTPUT
                };
                result.Add(inItem);
@@ -873,7 +874,7 @@
            });
        }
        private void OnMethodInvoked(IAsyncResult ar)
        public override void OnMethodInvoked(IAsyncResult ar)
        {
            MotionCardMonitorSet monitorSet = ar.AsyncState as MotionCardMonitorSet;
            ProcessResponse resValues = monitorSet.Response;
@@ -905,13 +906,12 @@
            {
                MotionCardWarningSet warningSet = wSet as MotionCardWarningSet;
                bool isOn = ((tempNew.FirstOrDefault(u => u.IONum == warningSet.TriggerIndex && u.IOType == warningSet.WarningIOModel)?.Value >> warningSet.TriggerIndex) & 1) == (warningSet.TriggerValue ? 1 : 0);
                bool isOn = (((int)((tempNew.FirstOrDefault(u => u.IONum == warningSet.TriggerIndex && u.IOType == warningSet.WarningIOModel)?.Value)) >> warningSet.TriggerIndex) & 1) == (warningSet.TriggerValue ? 1 : 0);
                if (warningSet.CurrentStatus != isOn)
                {
                    warningSet.CurrentStatus = isOn;
                    warningSet.TriggerTime = DateTime.Now;
                    warningSet.WarningDescription = $"警报:{warningSet.Name}-触发索引:{warningSet.TriggerIndex}-{warningSet.WarningIOModel.GetEnumDescription()}:{warningSet.WarningCode}";
                    SaveAlarmCSVAsync(DateTime.Now, this.Name, warningSet);
                    ExcuteMonitorAlarm(DateTime.Now, this, warningSet);
                }
@@ -932,7 +932,7 @@
                if (newIOItem?.Value != oldIOItem?.Value)
                {
                    if (monitorSet.TriggerValue == -999 || newIOItem.Value == monitorSet.TriggerValue)
                    if (monitorSet.TriggerValue == -999 || (int)newIOItem.Value == monitorSet.TriggerValue)
                    {
                        if (monitorSet.OpConfig == null)
                        {
@@ -944,7 +944,7 @@
                        //    return tempNew[index].Value;
                        //}).ToList();
                        ExcuteMonitorInvok(DateTime.Now, monitorSet.InvokeDevice, this, monitorSet, OnMethodInvoked);
                        ExcuteMonitorInvoke(DateTime.Now, monitorSet.InvokeDevice, this, monitorSet);
                    }
                }
            });
src/Bro.M071.Process/Bro.M071.Process.csproj
@@ -110,7 +110,7 @@
    <Compile Include="M071Config.cs" />
    <Compile Include="M071Models.cs" />
    <Compile Include="M071Process.cs" />
    <Compile Include="M071Process_IO.cs" />
    <Compile Include="M071Process_MotionCard.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
    <Compile Include="UI\KeyIndicator.cs" />
    <Compile Include="UI\M071Node.cs" />
@@ -120,6 +120,12 @@
    <Compile Include="UI\M071_MainForm.Designer.cs">
      <DependentUpon>M071_MainForm.cs</DependentUpon>
    </Compile>
    <Compile Include="UI\M071_ShortcutFrm.cs">
      <SubType>Form</SubType>
    </Compile>
    <Compile Include="UI\M071_ShortcutFrm.Designer.cs">
      <DependentUpon>M071_ShortcutFrm.cs</DependentUpon>
    </Compile>
    <EmbeddedResource Include="Properties\Resources.resx">
      <Generator>ResXFileCodeGenerator</Generator>
      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
src/Bro.M071.Process/M071Config.cs
@@ -44,18 +44,21 @@
        [Category("背景图片设置")]
        [Description("运行背景图片路径")]
        [Editor(typeof(FileDialogEditor), typeof(UITypeEditor))]
        [DisplayName("背景图片")]
        public string BackgroundImagePath { get; set; }
        [Category("检测设置")]
        [Description("拍摄点位设置集合")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(ComplexCollectionEditor<SnapshotPoint>), typeof(UITypeEditor))]
        [DisplayName("拍摄点位")]
        public List<SnapshotPoint> SnapshotPointCollection { get; set; } = new List<SnapshotPoint>();
        [Category("检测设置")]
        [Description("视觉检测单键配置集合")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(ComplexCollectionEditor<KeyUnit>), typeof(UITypeEditor))]
        [DisplayName("单键配置")]
        public List<KeyUnit> KeyUnitCollection { get; set; } = new List<KeyUnit>();
        [Category("检测设置")]
@@ -74,5 +77,23 @@
        [Description("单键图片保存目录路径")]
        [Editor(typeof(FoldDialogEditor),typeof(UITypeEditor))]
        public string ImageSaveFolder { get; set; } = "";
        [Category("屏蔽配置")]
        [Description("true:屏蔽安全门 false:启用安全门")]
        [ReadOnly(true)]
        public bool IsSafetyDoorBlocked { get; set; } = false;
        [Category("屏蔽配置")]
        [Description("true:屏蔽安全光线 false:启用安全光线")]
        [ReadOnly(true)]
        public bool IsSafetyBeamBlocked { get; set; } = false;
        [Category("屏蔽配置")]
        [Description("true:屏蔽蜂鸣器 false:启用蜂鸣器")]
        public bool IsBeepBlocked { get; set; } = false;
        [Category("屏蔽配置")]
        [Description("true:禁止手动输入条码 false:允许手动输入条码")]
        public bool IsBarcodeManulInputBlocked { get; set; } = true;
    }
}
src/Bro.M071.Process/M071Models.cs
@@ -312,7 +312,7 @@
        [Category("单键配置")]
        [Description("单键结果配置")]
        [TypeConverter(typeof(KeyUnitResultConverter))]
        public string KeyResult { get; set; } = "";
        public string KeyResultId { get; set; } = "";
        public List<HImage> KeyImages = new List<HImage>();
@@ -342,7 +342,7 @@
        {
            string msg = Key;
            msg += string.IsNullOrWhiteSpace(KeyResult) ? "" : $"-{KeyResult}";
            msg += string.IsNullOrWhiteSpace(KeyResultId) ? "" : $"-{KeyResultId}";
            return msg;
        }
src/Bro.M071.Process/M071Process.cs
@@ -33,7 +33,7 @@
        #region 事件
        public event Action OnMeasureStart;
        public event Action<string> OnBarcodeChanged;
        public event Action OnClearBarcode;
        public event Action<IShapeElement> OnElementUpdated;
        #endregion
@@ -51,7 +51,7 @@
        /// </summary>
        private void CheckMachineState()
        {
            throw new NotImplementedException();
            //throw new NotImplementedException();
        }
        private void InitialSetting()
@@ -110,7 +110,7 @@
                    if (keyRespone.Count == 0)
                        throw new ProcessException($"{u.GetDisplayText()}对应的单键不存在或不可用");
                    if (b.KeyResult == "All")
                    if (b.KeyResultId == "All")
                    {
                        keyRespone.SelectMany(kr => kr.KeyResultList).ToList().ForEach(r =>
                          {
@@ -119,7 +119,7 @@
                    }
                    else
                    {
                        b.MeasureValueDict[b.KeyResult] = null;
                        b.MeasureValueDict[b.KeyResultId] = null;
                    }
                });
            });
@@ -150,19 +150,7 @@
        //}
        #endregion
        private string barCode = "";
        public string BarCode
        {
            get => barCode;
            set
            {
                if (barCode != value)
                {
                    barCode = value;
                    OnBarcodeChanged?.Invoke(value);
                }
            }
        }
        public string BarCode { get; set; }
        List<ProductionMeasurement> productionList = new List<ProductionMeasurement>();
@@ -171,6 +159,7 @@
        {
            if (string.IsNullOrWhiteSpace(BarCode))
            {
                OnClearBarcode?.Invoke();
                throw new ProcessException("未输入产品条码,请勿开始测量");
            }
@@ -236,39 +225,6 @@
            BarCode = "";
            return new ProcessResponse(true);
        }
        /// <summary>
        /// 暂停标志
        /// WaitHandle 暂停句柄  默认为非阻塞 可执行
        /// WaitResult 暂停标志 true 正常执行  false 暂停中
        /// </summary>
        ManualWaitConfirm _pauseHandle = new ManualWaitConfirm()
        {
            WaitHandle = new ManualResetEvent(true),
            WaitResult = true,
        };
        [ProcessMethod("", "PauseJob", "暂停流程", InvokeType.TestInvoke)]
        public ProcessResponse PauseJob(IOperationConfig opConfig, IDevice invokeDevice, IDevice sourceDevice)
        {
            if (_pauseHandle.WaitResult)
            {
                #region 板卡暂停动作
                #endregion
                _pauseHandle.WaitHandle.Reset();
            }
            else
            {
                #region 板卡恢复动作
                #endregion
                _pauseHandle.WaitHandle.Set();
            }
            _pauseHandle.WaitResult = !_pauseHandle.WaitResult;
            return new ProcessResponse(_pauseHandle.WaitResult);
        }
        #region 私有方法
src/Bro.M071.Process/M071Process_IO.cs
File was deleted
src/Bro.M071.Process/M071Process_MotionCard.cs
New file
@@ -0,0 +1,217 @@
using Bro.Common.Base;
using Bro.Common.Helper;
using Bro.Common.Interface;
using Bro.Common.Model;
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.M071.Process
{
    public partial class M071Process
    {
        Timer _resetTimer = null;
        const int FULLRESETTIME = 5;
        MachineState machineState = MachineState.Unknown;
        MachineState MachineState
        {
            get => machineState;
            set
            {
                machineState = value;
                switch (machineState)
                {
                    case MachineState.Ready:
                        break;
                    case MachineState.Running:
                        break;
                    case MachineState.Alarm:
                        break;
                    case MachineState.Pause:
                        break;
                    default:
                        break;
                }
            }
        }
        [ProcessMethod("MotionCardBase", "Reset", "简单复位操作", InvokeType.TestInvoke)]
        public ProcessResponse Reset(IOperationConfig opConfig, IDevice invokeDevice, IDevice sourceDevice)
        {
            //if (opConfig == null)
            //{
            //    var monitorSet = Config.MonitorSetCollection.FirstOrDefault(u => u.MethodCode == "Reset");
            //    if (monitorSet == null)
            //        throw new ProcessException("未配置默认复位操作");
            //    opConfig = monitorSet.OpConfig;
            //    if (opConfig == null)
            //        throw new ProcessException("未配置复位操作具体配置动作");
            //    if (invokeDevice == null)
            //    {
            //        invokeDevice = DeviceCollection.FirstOrDefault(u => u.Id == monitorSet.InvokeDevice);
            //        if (invokeDevice == null)
            //            throw new ProcessException("未配置复位操作执行设备");
            //    }
            //}
            MotionCardDefaultRun("Reset", ref opConfig, ref invokeDevice);
            if (_resetTimer == null)
            {
                _resetTimer = new Timer(FullReset, null, -1, -1);
            }
            if (opConfig.InputPara.Count > 0)
            {
                //大复位信号
                _resetTimer.Change(-1, opConfig.InputPara[0] == 1 ? FULLRESETTIME * 1000 : -1);
            }
            //if (invokeDevice is MotionCardBase motionCard)
            //{
            //    motionCard.Run(opConfig);
            //}
            return new ProcessResponse(true);
        }
        private void FullReset(object state)
        {
            FullReset(null, null, null);
        }
        [ProcessMethod("MotionCardOperationConfigCollection", "FullReset", "大复位操作", InvokeType.TestInvoke)]
        public ProcessResponse FullReset(IOperationConfig opConfig, IDevice invokeDevice, IDevice sourceDevice)
        {
            //if (opConfig == null)
            //{
            //    var monitorSet = Config.MonitorSetCollection.FirstOrDefault(u => u.MethodCode == "FullReset");
            //    if (monitorSet == null)
            //        throw new ProcessException("未配置默认大复位操作");
            //    opConfig = monitorSet.OpConfig;
            //    if (opConfig == null)
            //        throw new ProcessException("未配置大复位操作具体配置动作");
            //    if (invokeDevice == null)
            //    {
            //        invokeDevice = DeviceCollection.FirstOrDefault(u => u.Id == monitorSet.InvokeDevice);
            //        if (invokeDevice == null)
            //            throw new ProcessException("未配置大复位操作执行设备");
            //    }
            //}
            //if (invokeDevice is MotionCardBase motionCard)
            //{
            //    motionCard.Run(opConfig);
            //}
            //MotionCardDefaultRun("FullReset", ref opConfig, ref invokeDevice);
            return new ProcessResponse(true);
        }
        /// <summary>
        /// 暂停标志
        /// WaitHandle 暂停句柄  默认为非阻塞 可执行
        /// WaitResult 暂停标志 true 正常执行  false 暂停中
        /// </summary>
        ManualWaitConfirm _pauseHandle = new ManualWaitConfirm()
        {
            WaitHandle = new ManualResetEvent(true),
            WaitResult = true,
        };
        [ProcessMethod("", "PauseJob", "暂停流程", InvokeType.TestInvoke)]
        public ProcessResponse PauseJob(IOperationConfig opConfig, IDevice invokeDevice, IDevice sourceDevice)
        {
            if (_pauseHandle.WaitResult)
            {
                #region 板卡暂停动作
                #endregion
                _pauseHandle.WaitHandle.Reset();
            }
            else
            {
                #region 板卡恢复动作
                #endregion
                _pauseHandle.WaitHandle.Set();
            }
            _pauseHandle.WaitResult = !_pauseHandle.WaitResult;
            return new ProcessResponse(_pauseHandle.WaitResult);
        }
        [ProcessMethod("MotionCardBase", "SwitchLightRed", "切换指示灯-红", InvokeType.TestInvoke)]
        public ProcessResponse SwitchLightRed(IOperationConfig opConfig, IDevice invokeDevice, IDevice sourceDevice)
        {
            MotionCardDefaultRun("SwitchLightRed", ref opConfig, ref invokeDevice);
            return new ProcessResponse(true);
        }
        [ProcessMethod("MotionCardBase", "SwitchLightYellow", "切换指示灯-黄", InvokeType.TestInvoke)]
        public ProcessResponse SwitchLightYellow(IOperationConfig opConfig, IDevice invokeDevice, IDevice sourceDevice)
        {
            return new ProcessResponse(true);
        }
        [ProcessMethod("MotionCardBase", "SwitchLightGreen", "切换指示灯-绿", InvokeType.TestInvoke)]
        public ProcessResponse SwitchLightGreen(IOperationConfig opConfig, IDevice invokeDevice, IDevice sourceDevice)
        {
            return new ProcessResponse(true);
        }
        [ProcessMethod("MotionCardBase", "SwitchBeep", "切换蜂鸣器", InvokeType.TestInvoke)]
        public ProcessResponse SwitchBeep(IOperationConfig opConfig, IDevice invokeDevice, IDevice sourceDevice)
        {
            return new ProcessResponse(true);
        }
        [ProcessMethod("MotionCardBase", "SwitchNormalLight", "切换日光灯", InvokeType.TestInvoke)]
        public ProcessResponse SwitchNormalLight(IOperationConfig opConfig, IDevice invokeDevice, IDevice sourceDevice)
        {
            MotionCardDefaultRun("SwitchNormalLight", ref opConfig, ref invokeDevice);
            return new ProcessResponse(true);
        }
        private void MotionCardDefaultRun(string methodCode, ref IOperationConfig opConfig, ref IDevice invokeDevice)
        {
            IMonitorSet monitorSet = null;
            if (opConfig == null)
            {
                monitorSet = Config.MonitorSetCollection.FirstOrDefault(u => u.MethodCode == methodCode);
                if (monitorSet == null)
                    throw new ProcessException("未配置默认操作");
                opConfig = monitorSet.OpConfig;
                if (opConfig == null)
                    throw new ProcessException("未配置具体配置动作");
            }
            if (invokeDevice == null)
            {
                invokeDevice = DeviceCollection.FirstOrDefault(u => u.Id == monitorSet.InvokeDevice);
                if (invokeDevice == null)
                    throw new ProcessException("未配置操作执行设备");
            }
            if (invokeDevice is MotionCardBase motionCard)
            {
                motionCard.Run(opConfig);
            }
        }
    }
}
src/Bro.M071.Process/UI/M071_MainForm.Designer.cs
@@ -33,6 +33,11 @@
            this.tsmiShowToolBar = new System.Windows.Forms.ToolStripMenuItem();
            this.tsmiShowStatusBar = new System.Windows.Forms.ToolStripMenuItem();
            this.tsmiShowEditor = new System.Windows.Forms.ToolStripMenuItem();
            this.lblCT = new System.Windows.Forms.Label();
            this.txtBarcode = new System.Windows.Forms.TextBox();
            this.lblProductionState = new System.Windows.Forms.Label();
            this.lblMachineState = new System.Windows.Forms.Label();
            this.plImage = new System.Windows.Forms.Panel();
            this.tscEditLocation = new System.Windows.Forms.ToolStripContainer();
            this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
            this.btnConfirmEdit = new System.Windows.Forms.Button();
@@ -82,6 +87,61 @@
            this.tsmiShowEditor.Size = new System.Drawing.Size(148, 22);
            this.tsmiShowEditor.Text = "编辑显示点位";
            this.tsmiShowEditor.CheckedChanged += new System.EventHandler(this.tsmiShowEditor_CheckedChanged);
            //
            // lblCT
            //
            this.lblCT.AutoSize = true;
            this.lblCT.Font = new System.Drawing.Font("Tahoma", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World, ((byte)(134)));
            this.lblCT.Location = new System.Drawing.Point(464, 19);
            this.lblCT.Name = "lblCT";
            this.lblCT.Size = new System.Drawing.Size(35, 14);
            this.lblCT.TabIndex = 4;
            this.lblCT.Text = "XXXX";
            //
            // txtBarcode
            //
            this.txtBarcode.Font = new System.Drawing.Font("Tahoma", 14F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World, ((byte)(134)));
            this.txtBarcode.Location = new System.Drawing.Point(138, 13);
            this.txtBarcode.Name = "txtBarcode";
            this.txtBarcode.Size = new System.Drawing.Size(261, 24);
            this.txtBarcode.TabIndex = 3;
            this.txtBarcode.Text = "BARCODE";
            this.txtBarcode.TextChanged += new System.EventHandler(this.txtBarcode_TextChanged);
            //
            // lblProductionState
            //
            this.lblProductionState.AutoSize = true;
            this.lblProductionState.BackColor = System.Drawing.Color.Lime;
            this.lblProductionState.Font = new System.Drawing.Font("Tahoma", 20F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.World, ((byte)(134)));
            this.lblProductionState.ForeColor = System.Drawing.Color.White;
            this.lblProductionState.Location = new System.Drawing.Point(405, 13);
            this.lblProductionState.Name = "lblProductionState";
            this.lblProductionState.Size = new System.Drawing.Size(39, 24);
            this.lblProductionState.TabIndex = 2;
            this.lblProductionState.Text = "OK";
            //
            // lblMachineState
            //
            this.lblMachineState.AutoSize = true;
            this.lblMachineState.BackColor = System.Drawing.Color.Lime;
            this.lblMachineState.Font = new System.Drawing.Font("Tahoma", 20F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.World, ((byte)(134)));
            this.lblMachineState.ForeColor = System.Drawing.Color.White;
            this.lblMachineState.Location = new System.Drawing.Point(22, 12);
            this.lblMachineState.Name = "lblMachineState";
            this.lblMachineState.Size = new System.Drawing.Size(79, 24);
            this.lblMachineState.TabIndex = 2;
            this.lblMachineState.Text = "READY";
            //
            // plImage
            //
            this.plImage.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
            | System.Windows.Forms.AnchorStyles.Left)
            | System.Windows.Forms.AnchorStyles.Right)));
            this.plImage.ContextMenuStrip = this.contextMenuStrip1;
            this.plImage.Location = new System.Drawing.Point(1, 47);
            this.plImage.Name = "plImage";
            this.plImage.Size = new System.Drawing.Size(796, 304);
            this.plImage.TabIndex = 1;
            // 
            // tscEditLocation
            // 
@@ -159,7 +219,7 @@
            // 
            this.splitContainer1.Panel2.Controls.Add(this.propGridKeyIndicator);
            this.splitContainer1.Size = new System.Drawing.Size(203, 284);
            this.splitContainer1.SplitterDistance = 164;
            this.splitContainer1.SplitterDistance = 163;
            this.splitContainer1.TabIndex = 1;
            // 
            // lvMeasures
@@ -171,7 +231,7 @@
            this.lvMeasures.Location = new System.Drawing.Point(0, 0);
            this.lvMeasures.MultiSelect = false;
            this.lvMeasures.Name = "lvMeasures";
            this.lvMeasures.Size = new System.Drawing.Size(203, 164);
            this.lvMeasures.Size = new System.Drawing.Size(203, 163);
            this.lvMeasures.TabIndex = 0;
            this.lvMeasures.UseCompatibleStateImageBehavior = false;
            this.lvMeasures.View = System.Windows.Forms.View.List;
@@ -182,7 +242,7 @@
            this.propGridKeyIndicator.Dock = System.Windows.Forms.DockStyle.Fill;
            this.propGridKeyIndicator.Location = new System.Drawing.Point(0, 0);
            this.propGridKeyIndicator.Name = "propGridKeyIndicator";
            this.propGridKeyIndicator.Size = new System.Drawing.Size(203, 116);
            this.propGridKeyIndicator.Size = new System.Drawing.Size(203, 117);
            this.propGridKeyIndicator.TabIndex = 0;
            this.propGridKeyIndicator.ToolbarVisible = false;
            // 
@@ -191,10 +251,16 @@
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(800, 351);
            this.ContextMenuStrip = this.contextMenuStrip1;
            this.Controls.Add(this.lblCT);
            this.Controls.Add(this.txtBarcode);
            this.Controls.Add(this.lblProductionState);
            this.Controls.Add(this.lblMachineState);
            this.Controls.Add(this.plImage);
            this.Controls.Add(this.tscEditLocation);
            this.KeyPreview = true;
            this.Name = "M071_MainForm";
            this.Text = "M071_MainForm";
            this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.M071_MainForm_KeyUp);
            this.contextMenuStrip1.ResumeLayout(false);
            this.tscEditLocation.ContentPanel.ResumeLayout(false);
            this.tscEditLocation.ResumeLayout(false);
@@ -205,6 +271,7 @@
            ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
            this.splitContainer1.ResumeLayout(false);
            this.ResumeLayout(false);
            this.PerformLayout();
        }
@@ -221,5 +288,10 @@
        private System.Windows.Forms.ListView lvMeasures;
        private System.Windows.Forms.ToolStripMenuItem tsmiShowToolBar;
        private System.Windows.Forms.ToolStripMenuItem tsmiShowStatusBar;
        private System.Windows.Forms.Panel plImage;
        private System.Windows.Forms.Label lblMachineState;
        private System.Windows.Forms.Label lblProductionState;
        private System.Windows.Forms.TextBox txtBarcode;
        private System.Windows.Forms.Label lblCT;
    }
}
src/Bro.M071.Process/UI/M071_MainForm.cs
@@ -12,7 +12,7 @@
namespace Bro.M071.Process.UI
{
    [MenuNode("M071_MainForm", "键盘检测主界面", 3, "M071Node", true)]
    [MenuNode("M071_MainForm", "运行界面", 1, "M071Node", true)]
    public partial class M071_MainForm : MenuFrmBase
    {
        Canvas cvImage = new Canvas();
@@ -26,7 +26,7 @@
            tsmiShowStatusBar.Checked = cvImage.IsShowStatusBar = false;
            tsmiShowToolBar.Checked = cvImage.IsShowToolBar = false;
            cvImage.Dock = DockStyle.Fill;
            this.Controls.Add(cvImage);
            plImage.Controls.Add(cvImage);
            tscEditLocation.Visible = tsmiShowEditor.Checked = false;
        }
@@ -66,17 +66,14 @@
                item.Tag = u.Id;
                lvMeasures.Items.Add(item);
            });
            txtBarcode.ReadOnly = Config.IsBarcodeManulInputBlocked;
            (Process as M071Process).OnClearBarcode -= M071_MainForm_OnClearBarcode;
            (Process as M071Process).OnClearBarcode += M071_MainForm_OnClearBarcode;
        }
        
        private void lvMeasures_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lvMeasures.SelectedItems.Count <= 0)
                return;
            var ele = cvImage.Elements.FirstOrDefault(u => u.ID == lvMeasures.SelectedItems[0].Tag.ToString());
            propGridKeyIndicator.SelectedObject = ele;
        }
        #region 图片区右键菜单
        private void tsmiShowToolBar_CheckedChanged(object sender, EventArgs e)
        {
            cvImage.IsShowToolBar = tsmiShowToolBar.Checked;
@@ -90,6 +87,18 @@
        private void tsmiShowEditor_CheckedChanged(object sender, EventArgs e)
        {
            tscEditLocation.Visible = tsmiShowEditor.Checked;
            tscEditLocation.BringToFront();
        }
        #endregion
        #region 标签编辑区
        private void lvMeasures_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lvMeasures.SelectedItems.Count <= 0)
                return;
            var ele = cvImage.Elements.FirstOrDefault(u => u.ID == lvMeasures.SelectedItems[0].Tag.ToString());
            propGridKeyIndicator.SelectedObject = ele;
        }
        private void btnCancelEdit_Click(object sender, EventArgs e)
@@ -125,5 +134,39 @@
            MessageBox.Show("标签修改完成");
        }
        #endregion
        #region 上方状态区
        #region 条码
        string _barcode = "";
        private void M071_MainForm_KeyUp(object sender, KeyEventArgs e)
        {
            string keyStr = e.KeyCode.ToString();
            if (keyStr.Length == 1)
            {
                _barcode += keyStr.ToUpper();
            }
            if (e.KeyValue == 13)
            {
                txtBarcode.Text = _barcode;
                _barcode = "";
            }
        }
        private void txtBarcode_TextChanged(object sender, EventArgs e)
        {
            (Process as M071Process).BarCode = txtBarcode.Text.Trim();
        }
        private void M071_MainForm_OnClearBarcode()
        {
            txtBarcode.BeginInvoke(new Action(() => txtBarcode.Clear()));
        }
        #endregion
        #endregion
    }
}
src/Bro.M071.Process/UI/M071_ShortcutFrm.Designer.cs
New file
@@ -0,0 +1,39 @@
namespace Bro.M071.Process.UI
{
    partial class M071_ShortcutFrm
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
        #region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(800, 450);
            this.Text = "M071_ShortcutFrm";
        }
        #endregion
    }
}
src/Bro.M071.Process/UI/M071_ShortcutFrm.cs
New file
@@ -0,0 +1,22 @@
using Bro.UI.Model.Winform;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Bro.M071.Process.UI
{
    [MenuNode("M071_ShortcutFrm", "快捷操作", 2, "M071Node", true)]
    public partial class M071_ShortcutFrm : MenuFrmBase
    {
        public M071_ShortcutFrm()
        {
            InitializeComponent();
        }
    }
}
src/Bro.UI.Config/MainFrm.Designer.cs
@@ -197,6 +197,7 @@
            this.Font = new System.Drawing.Font("Tahoma", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World, ((byte)(134)));
            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
            this.IsMdiContainer = true;
            this.KeyPreview = true;
            this.MainMenuStrip = this.menuMain;
            this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
            this.Name = "MainFrm";
src/Bro.UI.Config/MainFrm.cs
@@ -491,6 +491,8 @@
        private void Device_OnDeviceStateChanged(IDevice device, EnumHelper.DeviceState currentState)
        {
            ststripDevices.BeginInvoke(new Action(() =>
            {
            for (int i = 1; i < ststripDevices.Items.Count; i++)
            {
                if ((ststripDevices.Items[i].Tag as IDevice)?.Id == device.Id)
@@ -500,6 +502,7 @@
                    break;
                }
            }
            }));
        }
        #endregion
src/Bro.UI.Config/MenuForms/FrmConfig.cs
src/Bro.UI.Config/MenuForms/FrmOperation.cs
@@ -140,7 +140,7 @@
        }
        bool isStart = true;
        private void btnStart_Click(object sender, System.EventArgs e)
        private async void btnStart_Click(object sender, System.EventArgs e)
        {
            if (Process == null)
            {
@@ -157,11 +157,11 @@
                //if (Process.ProcessState != EnumHelper.DeviceState.DSOpen)
                if (isStart)
                {
                    ProcessOperation(true);
                    await ProcessOperation(true);
                }
                else
                {
                    ProcessOperation(false);
                    await ProcessOperation(false);
                }
                isStart = !isStart;
@@ -172,7 +172,8 @@
            }
            finally
            {
                this.BeginInvoke(new Action(() => btnStart.Enabled = true));
                //this.BeginInvoke(new Action(() => btnStart.Enabled = true));
                btnStart.Enabled = true;
            }
            //});
        }
@@ -255,11 +256,11 @@
        //    }
        //}
        private void ProcessOperation(bool isStart)
        private async Task ProcessOperation(bool isStart)
        {
            if (isStart)
            {
                Process.Open();
                await Task.Run(() => Process.Open());
                //this.BeginInvoke(new Action(() =>
                //{
@@ -273,7 +274,7 @@
            }
            else
            {
                Process.Close();
                await Task.Run(() => Process.Close());
                //this.BeginInvoke(new Action(() =>
                //{
src/Bro.UI.Config/MenuForms/FrmOperation.resx
@@ -125,7 +125,7 @@
        AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
        LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
        ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADm
        CgAAAk1TRnQBSQFMAgEBAgEAAdgBAAHYAQABGAEAARgBAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
        CgAAAk1TRnQBSQFMAgEBAgEAAeABAAHgAQABGAEAARgBAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
        AwABYAMAARgDAAEBAQABCAYAAQkYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
        AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
        AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA
@@ -182,7 +182,7 @@
        AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
        LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
        ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAD4
        CAAAAk1TRnQBSQFMAwEBAAHYAQAB2AEAARgBAAEYAQAE/wEJAQAI/wFCAU0BNgEEBgABNgEEAgABKAMA
        CAAAAk1TRnQBSQFMAwEBAAHgAQAB4AEAARgBAAEYAQAE/wEJAQAI/wFCAU0BNgEEBgABNgEEAgABKAMA
        AWADAAEYAwABAQEAAQgGAAEJGAABgAIAAYADAAKAAQABgAMAAYABAAGAAQACgAIAA8ABAAHAAdwBwAEA
        AfABygGmAQABMwUAATMBAAEzAQABMwEAAjMCAAMWAQADHAEAAyIBAAMpAQADVQEAA00BAANCAQADOQEA
        AYABfAH/AQACUAH/AQABkwEAAdYBAAH/AewBzAEAAcYB1gHvAQAB1gLnAQABkAGpAa0CAAH/ATMDAAFm
src/Bro.UI.Device.Winform/MotionCard/CtrlMotionCardOperationBase.cs
@@ -52,18 +52,18 @@
        private void RadioButton_CheckedChanged(object sender, EventArgs e)
        {
            //加载对应运动的 movingConfig
            if (radioP2P.Checked)
            {
                movingConfig = MotionCardOperationConfig.MovingOps.FirstOrDefault(u => u.MoveMode == EnumHelper.MotorMoveMode.Normal);
            }
            else if (radioJog.Checked)
            {
                movingConfig = MotionCardOperationConfig.MovingOps.FirstOrDefault(u => u.MoveMode == EnumHelper.MotorMoveMode.Jog);
            }
            else if (radioGoHome.Checked)
            {
                movingConfig = MotionCardOperationConfig.MovingOps.FirstOrDefault(u => u.MoveMode == EnumHelper.MotorMoveMode.FindOri);
            }
            //if (radioP2P.Checked)
            //{
            //    movingConfig = MotionCardOperationConfig.MovingOps.FirstOrDefault(u => u.MoveMode == EnumHelper.MotorMoveMode.Normal);
            //}
            //else if (radioJog.Checked)
            //{
            //    movingConfig = MotionCardOperationConfig.MovingOps.FirstOrDefault(u => u.MoveMode == EnumHelper.MotorMoveMode.Jog);
            //}
            //else if (radioGoHome.Checked)
            //{
            //    movingConfig = MotionCardOperationConfig.MovingOps.FirstOrDefault(u => u.MoveMode == EnumHelper.MotorMoveMode.FindOri);
            //}
            propGrid.SelectedObject = movingConfig;
        }