src/Bro.Common.Device/DeviceBase/HDevEngineTool.cs
@@ -250,7 +250,7 @@ for (int i = 0; i < tuple.Length; i++) { list.Add(tuple[i]); list.Add(tuple[i].D); } return list; src/Bro.Common.Device/DeviceBase/MotionCardBase.cs
@@ -131,7 +131,7 @@ /// <summary> /// 恢复立即暂停 /// </summary> public abstract void ResetImmediatePause(); public abstract void ResetImmediatePause(bool isResumeMoving); #endregion } src/Bro.Common.Model/Model/MotionCardRelated.cs
@@ -86,6 +86,13 @@ //[Description("IsUseWarning:是否启用报警")] //public bool IsUseWarning { get; set; } = false; [Category("原点配置")] [DisplayName("回原点参数")] [Description("回原点参数")] [TypeConverter(typeof(ComplexObjectConvert))] [Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))] public GoHomePara GoHomePara { get; set; } = new GoHomePara(); [Category("暂停配置")] [DisplayName("是否启用立即暂停")] [Description("IsImmediatePause:是否启用立即暂停")] @@ -154,25 +161,19 @@ [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; public short HomeMode { get; set; } = 11; [Category("回原点参数")] [DisplayName("边缘")] [Description("edge:边缘")] public short Edge { get; set; } = 0; [Category("回原点参数")] [Category("回原点速度")] [DisplayName("回原点最低速度")] [Description("LowVelocity:速度,为0时表示不修改当前设置")] public double LowVelocity { get; set; } = 50; [Category("回原点参数")] [Category("回原点速度")] [DisplayName("回原点最高速度")] [Description("HighVelocity:速度,为0时表示不修改当前设置")] public double HighVelocity { get; set; } = 50; @@ -182,16 +183,30 @@ //[Description("SearchHomeDistance:搜索距离")] //public int SearchHomeDistance { get; set; } = 9999999; [Category("回原点参数")] [Category("回原点偏移")] [DisplayName("偏移距离")] [Description("HomeOffset:偏移距离")] public int HomeOffset { get; set; } = 0; [Category("回原点参数")] [Category("回原点偏移")] [DisplayName("跳过步长")] [Description("EscapeStep:跳过步长")] public int EscapeStep { get; set; } = 1000; [Category("回原点方向")] [DisplayName("起始运动方向")] [Description("回原点时,轴的初始运动方向:true 正向,false 负向")] public bool IsHomeDirPositive { get; set; } = true; [Category("回原点方向")] [DisplayName("原点捕捉方向")] [Description("捕捉原点时,轴的运动方向:true 正向,false 负向")] public bool IsCaptureDirPositive { get; set; } = true; [Category("回原点超时")] [DisplayName("回原点超时")] [Description("回原点超时,单位秒")] public int GoHomeTimeOut { get; set; } = 60; } /// <summary> @@ -352,12 +367,12 @@ //} //private GoHomePara goHomePara = new GoHomePara(); [Category("运动配置")] [DisplayName("回原点参数")] [Description("GoHomePara:速度参数")] [TypeConverter(typeof(ComplexObjectConvert))] [Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))] public GoHomePara GoHomePara { get; set; } = new GoHomePara(); //[Category("运动配置")] //[DisplayName("回原点参数")] //[Description("GoHomePara:速度参数")] //[TypeConverter(typeof(ComplexObjectConvert))] //[Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))] //public GoHomePara GoHomePara { get; set; } = new GoHomePara(); //{ // get => goHomePara; // set src/Bro.Device.GTSCard/GTSCardDriver.cs
@@ -46,6 +46,8 @@ /// 运动轴立即暂停 /// </summary> Dictionary<int, ManualResetEvent> axisImmediatePauseHandleDict = new Dictionary<int, ManualResetEvent>(); Dictionary<int, bool> axisImmediatePauseFlag = new Dictionary<int, bool>(); Dictionary<int, bool> axisPauseResumeFlag = new Dictionary<int, bool>(); //Dictionary<int, CancellationTokenSource> axisMoveCancelDict = new Dictionary<int, CancellationTokenSource>(); @@ -145,16 +147,22 @@ { foreach (var preCheck in operationSet.PreCheckIOCollection) { int timeout = operationSet.PreCheckIOTimeout; _pauseHandle.Wait(); IOValue? ioData = null; while (CurrentState == DeviceState.DSOpen) if (CurrentState == DeviceState.DSOpen) { Thread.Sleep(10); ioData = MonitorValues.FirstOrDefault(u => u.IONum == preCheck.IOItem.IONum && u.IOType == preCheck.IOItem.IOType)?.Value;//IO 是开、关 从MonitorValues 获取 timeout -= 10; if (preCheck.CheckValue == ioData || (operationSet.PreCheckIOTimeout > 0 && timeout < 0)) int timeout = operationSet.PreCheckIOTimeout; while (CurrentState == DeviceState.DSOpen) { break; Thread.Sleep(10); ioData = MonitorValues.FirstOrDefault(u => u.IONum == preCheck.IOItem.IONum && u.IOType == preCheck.IOItem.IOType)?.Value;//IO 是开、关 从MonitorValues 获取 timeout -= 10; if (preCheck.CheckValue == ioData || (operationSet.PreCheckIOTimeout > 0 && timeout < 0)) { break; } } } @@ -170,10 +178,15 @@ // 2.板卡运动 if (CurrentState == DeviceState.DSOpen) { responseMessage = MoveToPoint(new MotionOperationCollection() { MovingOps = operationSet.MovingOps }); if (!responseMessage.Result) _pauseHandle.Wait(); if (CurrentState == DeviceState.DSOpen) { return responseMessage; responseMessage = MoveToPoint(new MotionOperationCollection() { MovingOps = operationSet.MovingOps }); if (!responseMessage.Result) { return responseMessage; } } } @@ -181,18 +194,24 @@ // 3.IO输出 不需要超时 if (CurrentState == DeviceState.DSOpen) { foreach (var ioOutput in operationSet.IOOutputCollection) { WriteOutput((short)ioOutput.IOItem.IONum, ioOutput.CheckValue); _pauseHandle.Wait(); //var ioData = MonitorValues.FirstOrDefault(u => u.IONum == ioOutput.IOItem.IONum && u.IOType == ioOutput.IOItem.IOType)?.Value;//IO 是开、关 从MonitorValues 获取 if (CurrentState == DeviceState.DSOpen) { WriteOutput((short)ioOutput.IOItem.IONum, ioOutput.CheckValue); //if (ioOutput.CheckValue != ioData) //{ // responseMessage.Result = false; // responseMessage.Message = $"IO输出不通过,配置:{ioOutput.GetDisplayText()},当前值:{ioData}"; // return responseMessage; //} //var ioData = MonitorValues.FirstOrDefault(u => u.IONum == ioOutput.IOItem.IONum && u.IOType == ioOutput.IOItem.IOType)?.Value;//IO 是开、关 从MonitorValues 获取 //if (ioOutput.CheckValue != ioData) //{ // responseMessage.Result = false; // responseMessage.Message = $"IO输出不通过,配置:{ioOutput.GetDisplayText()},当前值:{ioData}"; // return responseMessage; //} } } } @@ -228,6 +247,8 @@ #endregion #region ImmediatePause ManualResetEventSlim _pauseHandle = new ManualResetEventSlim(true); /// <summary> /// 启动立即暂停 /// </summary> @@ -236,12 +257,11 @@ if (!_isResetting) { var immediatePauseAxis = IConfig.AxisSettings.FindAll(a => a.IsAxisEnabled && a.IsImmediatePause).Select(u => u.AxisIndex).ToList(); _pauseHandle.Reset(); immediatePauseAxis.ForEach(async axisIndex => { axisImmediatePauseHandleDict[axisIndex].Reset(); //axisMoveCancelDict[axisIndex].Cancel(); axisImmediatePauseFlag[axisIndex] = true; await MoveStop(axisIndex, 0);//所有轴都暂停 }); @@ -251,15 +271,22 @@ /// <summary> /// 恢复立即暂停 /// </summary> public override void ResetImmediatePause() public override void ResetImmediatePause(bool isResumeMoving) { var immediatePauseAxis = IConfig.AxisSettings.FindAll(a => a.IsAxisEnabled && a.IsImmediatePause).Select(u => u.AxisIndex).ToList(); _pauseHandle.Set(); immediatePauseAxis.ForEach(axisIndex => { //axisMoveCancelDict[axisIndex] = new CancellationTokenSource(); axisImmediatePauseFlag[axisIndex] = false; axisImmediatePauseHandleDict[axisIndex].Set(); if (isResumeMoving) { axisPauseResumeFlag[axisIndex] = true; } else { axisPauseResumeFlag[axisIndex] = false; } }); } #endregion @@ -347,19 +374,11 @@ ResponseMessage responseMessage = new ResponseMessage(); if (opConfig is MotionOperationCollection gtsOperationCollection) { //List<Task<bool>> taskList = new List<Task<bool>>(); //foreach (var movingOp in gtsOperationCollection.MovingOps) //{ // var task = SingleAxisMoving(movingOp); // taskList.Add(task); // task.Start(); //} //Task.WaitAll(taskList.ToArray()); //responseMessage.Result = taskList.All(u => u.GetAwaiter().GetResult()); List<bool> resultList = new List<bool>(); Parallel.ForEach(gtsOperationCollection.MovingOps, movingOp => { axisImmediatePauseFlag[movingOp.AxisIndex] = false; axisPauseResumeFlag[movingOp.AxisIndex] = true; resultList.Add(SingleAxisMoving(movingOp).Result); }); responseMessage.Result = resultList.All(u => u == true); @@ -418,63 +437,64 @@ public override Task<bool> SingleAxisMoving(MovingOption optionPara) { return Task.Run(() => { axisImmediatePauseHandleDict[optionPara.AxisIndex].WaitOne(); bool isSuccessAndStop = false; try { if (IConfig.AxisSettings.FirstOrDefault(a => a.AxisIndex == optionPara.AxisIndex)?.IsAxisEnabled ?? false) { // string _position = ""; string motionType = optionPara.MoveMode == EnumHelper.MotionMode.Normal ? (optionPara.IsAbsolute ? "Abs" : "Rel") : optionPara.MoveMode.ToString(); { bool isSuccessAndStop = false; do { axisImmediatePauseHandleDict[optionPara.AxisIndex].WaitOne(); // _position = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff},{optionPara.AxisIndex},{motionType},{GetPosition(optionPara.AxisIndex)},{GetPrfPosition(optionPara.AxisIndex)},{optionPara.Destination},"; if (!axisPauseResumeFlag[optionPara.AxisIndex]) return true; switch (optionPara.MoveMode) { case MotionMode.Normal: { if (_isResetting) { LogAsync(DateTime.Now, "复位中启动运动异常", optionPara.AxisIndex + "启动运动异常"); return false; } try { if (IConfig.AxisSettings.FirstOrDefault(a => a.AxisIndex == optionPara.AxisIndex)?.IsAxisEnabled ?? false) { string motionType = optionPara.MoveMode == EnumHelper.MotionMode.Normal ? (optionPara.IsAbsolute ? "Abs" : "Rel") : optionPara.MoveMode.ToString(); if (optionPara.IsAbsolute) { isSuccessAndStop = P2PMoveAbs(optionPara); } else { isSuccessAndStop = P2PMoveRel(optionPara); } switch (optionPara.MoveMode) { case MotionMode.Normal: { if (_isResetting) { LogAsync(DateTime.Now, "复位中启动运动异常", optionPara.AxisIndex + "启动运动异常"); return false; } } break; case MotionMode.FindOri: { //isSuccessAndStop = GoHome(optionPara); isSuccessAndStop = P2PGoHome(optionPara); } break; case MotionMode.Jog: { isSuccessAndStop = JogMove(optionPara); } break; } //_position += $"{GetPosition(optionPara.AxisIndex)},"; //_position += $"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}"; //LogAsync(DateTime.Now, "", _position); } } catch (Exception ex) { isSuccessAndStop = false; LogAsync(DateTime.Now, $"轴{optionPara.AxisIndex}运动异常", ex.GetExceptionMessage()); } return isSuccessAndStop; }); if (optionPara.IsAbsolute) { isSuccessAndStop = P2PMoveAbs(optionPara); } //else //{ // isSuccessAndStop = P2PMoveRel(optionPara); //} } break; case MotionMode.FindOri: { //isSuccessAndStop = GoHome(optionPara); isSuccessAndStop = P2PGoHome(optionPara); } break; case MotionMode.Jog: { isSuccessAndStop = JogMove(optionPara); } break; } } } catch (Exception ex) { isSuccessAndStop = false; LogAsync(DateTime.Now, $"轴{optionPara.AxisIndex}运动异常", ex.GetExceptionMessage()); } } while (axisImmediatePauseFlag[optionPara.AxisIndex]); return isSuccessAndStop; }); } /// <summary> @@ -868,7 +888,11 @@ { try { StartCapture: var goHomePara = IConfig.AxisSettings.FirstOrDefault(u => u.AxisIndex == movingOption.AxisIndex).GoHomePara; bool homeDirection = goHomePara.IsHomeDirPositive; bool isRightLimitReached = false; StartCapture: PositionReset(movingOption.AxisIndex, 1); ClearStatus(movingOption.AxisIndex, 1); @@ -887,24 +911,24 @@ // 设置点位模式运动参数 sRtn = GTSCardAPI.GT_SetTrapPrm((short)IConfig.CardNum, (short)movingOption.AxisIndex, ref trapPrm); // 设置点位模式目标速度,即回原点速度 sRtn = GTSCardAPI.GT_SetVel((short)IConfig.CardNum, (short)movingOption.AxisIndex, movingOption.GoHomePara.HighVelocity); sRtn = GTSCardAPI.GT_SetVel((short)IConfig.CardNum, (short)movingOption.AxisIndex, goHomePara.HighVelocity); // 设置点位模式目标位置,即原点搜索距离 sRtn = GTSCardAPI.GT_SetPos((short)IConfig.CardNum, (short)movingOption.AxisIndex, movingOption.GoHomePara.HomeDir == 1 ? 99999999 : -99999999); sRtn = GTSCardAPI.GT_SetPos((short)IConfig.CardNum, (short)movingOption.AxisIndex, homeDirection ? 99999999 : -99999999); // 启动运动 sRtn = GTSCardAPI.GT_Update((short)IConfig.CardNum, 1 << (movingOption.AxisIndex - 1)); int repeatTime = 1000; int repeatTime = goHomePara.GoHomeTimeOut * 1000; short capture; int pos; uint clk;//时钟参数 do { Thread.Sleep(20); Thread.Sleep(IConfig.MonitorInterval); // 读取捕获状态 GTSCardAPI.GT_GetCaptureStatus((short)IConfig.CardNum, (short)movingOption.AxisIndex, out capture, out pos, 1, out clk); isStop = IsStop((short)movingOption.AxisIndex); repeatTime--; repeatTime -= IConfig.MonitorInterval; } while (!(isStop || capture == 1 || repeatTime <= 0)); if (repeatTime <= 0) @@ -921,7 +945,22 @@ if (((axisStatus.AxisStatus & 0x20) != 0) || ((axisStatus.AxisStatus & 0x40) != 0)) { movingOption.GoHomePara.HomeDir = (short)(movingOption.GoHomePara.HomeDir == 1 ? -1 : 1); //movingOption.GoHomePara.HomeDir = (short)(movingOption.GoHomePara.HomeDir == 1 ? -1 : 1); //正限位 if ((axisStatus.AxisStatus & 0x20) != 0 && !goHomePara.IsCaptureDirPositive) { isRightLimitReached = true; } //负限位 if ((axisStatus.AxisStatus & 0x40) != 0 && goHomePara.IsCaptureDirPositive) { isRightLimitReached = true; } homeDirection = !homeDirection; goto StartCapture; } @@ -930,12 +969,18 @@ if (capture == 1) { if (!isRightLimitReached) { capture = 0; goto StartCapture; } //先stop MoveStop((short)movingOption.AxisIndex, 0); ClearStatus((short)movingOption.AxisIndex, 1); //已经捕获到Home才可以回零 阶段2 // 运动到"捕获位置+偏移量" sRtn = GTSCardAPI.GT_SetPos((short)IConfig.CardNum, (short)movingOption.AxisIndex, pos + movingOption.GoHomePara.HomeOffset); sRtn = GTSCardAPI.GT_SetPos((short)IConfig.CardNum, (short)movingOption.AxisIndex, pos + goHomePara.HomeOffset); // 在运动状态下更新目标位置 sRtn = GTSCardAPI.GT_Update((short)IConfig.CardNum, 1 << (movingOption.AxisIndex - 1)); isStop = false; @@ -1282,10 +1327,16 @@ int axis_sts; var axisSettings = IConfig.AxisSettings.FindAll(u => u.IsAxisEnabled); ClearStatus(1, axisSettings.Count); if (AxisStatusList.Count == 0) { Thread.Sleep(10); } foreach (var axisSetting in axisSettings) { //axis_sts = GetAxisStatus((short)axisSetting.AxisIndex); axis_sts = AxisStatusList.FirstOrDefault(u => u.AxisIndex == axisSetting.AxisIndex).AxisStatus; axis_sts = AxisStatusList.FirstOrDefault(u => u.AxisIndex == axisSetting.AxisIndex)?.AxisStatus ?? 0; if ((axis_sts & 0x200) == 0) { var rst = GTSCardAPI.GT_AxisOn((short)IConfig.CardNum, (short)axisSetting.AxisIndex); src/Bro.Device.Gocator/GocatorDriver.cs
@@ -110,8 +110,6 @@ { imgSet.HImage = new HImage(); imgSet.HImage.GenImage1("uint2", (int)width, zoomHeight, zoomPtr); //imgSet.HImage = imgSet.HImage.ZoomImageSize((int)width, zoomHeight, "constant"); imgSet.HImage_2 = new HImage(); imgSet.HImage_2.GenImage1("uint2", (int)width, zoomHeight, zoomPtr); src/Bro.M071.DBManager/ExcelExportHelper.cs
@@ -12,20 +12,23 @@ public class ExcelExportSet { public List<string> Worksheets { get; set; } public List<string> Worksheets { get; set; } = new List<string>(); /// <summary> /// Key: Worksheet的名称 Value:Worksheet对应的列名集合(key 为要导出的列名 value 为导出后显示的列名) /// </summary> public Dictionary<string, Dictionary<string, string>> WorksheetColumns { get; set; } public Dictionary<string, DataTable> WorksheetDataTable { get; set; } public Dictionary<string, Dictionary<string, string>> WorksheetColumns { get; set; } = new Dictionary<string, Dictionary<string, string>>(); public ExcelExportSet() { Worksheets = new List<string>(); WorksheetColumns = new Dictionary<string, Dictionary<string, string>>(); WorksheetDataTable = new Dictionary<string, DataTable>(); } public Dictionary<string, Dictionary<string, string>> WorksheetRows { get; set; } = new Dictionary<string, Dictionary<string, string>>(); public Dictionary<string, DataTable> WorksheetDataTable { get; set; } = new Dictionary<string, DataTable>(); //public ExcelExportSet() //{ // Worksheets = new List<string>(); // WorksheetColumns = new Dictionary<string, Dictionary<string, string>>(); // WorksheetDataTable = new Dictionary<string, DataTable>(); //} } @@ -107,7 +110,7 @@ { // autofit width of cells with small content ExcelRange columnCells = workSheet.Cells[workSheet.Dimension.Start.Row, columnIndex, workSheet.Dimension.End.Row, columnIndex]; int maxLength = columnCells.Max(cell => cell.Value.ToString().Count()); int maxLength = columnCells.Max(cell => (cell.Value ?? "").ToString().Count()); if (maxLength < 150) { workSheet.Column(columnIndex).AutoFit(); @@ -258,13 +261,14 @@ { try { return obj.ToString(); return (obj ?? "").ToString(); } catch (Exception) { return ""; } } } } src/Bro.M071.Model/Model/MeasurementUnitResult.cs
@@ -48,6 +48,10 @@ public string ProductionCode { get; set; } [NotMapped] public string ProductionBarcode { get; set; } [NotMapped] public string Keys { get; set; } [NotMapped] public string Positions { get; set; } } public class MeasurementUnitResultRequest : BaseRequest src/Bro.M071.Process/Bro.M071.Process.csproj
@@ -81,6 +81,9 @@ <Reference Include="Autofac, Version=4.9.4.0, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL"> <HintPath>..\..\packages\Autofac.4.9.4\lib\net45\Autofac.dll</HintPath> </Reference> <Reference Include="EPPlus, Version=4.5.3.3, Culture=neutral, PublicKeyToken=ea159fdaa78159a1, processorArchitecture=MSIL"> <HintPath>..\..\packages\EPPlus.4.5.3.3\lib\net40\EPPlus.dll</HintPath> </Reference> <Reference Include="halcondotnet, Version=12.0.0.0, Culture=neutral, PublicKeyToken=4973bed59ddbf2b8, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> <HintPath>..\..\libs\halcon12\halcondotnet.dll</HintPath> @@ -95,8 +98,11 @@ <Reference Include="PostSharp, Version=6.2.7.0, Culture=neutral, PublicKeyToken=b13fd38b8f9c99d7, processorArchitecture=MSIL"> <HintPath>..\..\packages\PostSharp.Redist.6.2.7\lib\net45\PostSharp.dll</HintPath> </Reference> <Reference Include="PresentationCore" /> <Reference Include="System" /> <Reference Include="System.configuration" /> <Reference Include="System.Core" /> <Reference Include="System.Security" /> <Reference Include="System.Xml.Linq" /> <Reference Include="System.Data.DataSetExtensions" /> <Reference Include="Microsoft.CSharp" /> @@ -131,6 +137,12 @@ <Compile Include="UI\M071_MainForm.Designer.cs"> <DependentUpon>M071_MainForm.cs</DependentUpon> </Compile> <Compile Include="UI\M071_PatchInsertMeasurement.cs"> <SubType>Form</SubType> </Compile> <Compile Include="UI\M071_PatchInsertMeasurement.Designer.cs"> <DependentUpon>M071_PatchInsertMeasurement.cs</DependentUpon> </Compile> <Compile Include="UI\M071_ShortcutFrm.cs"> <SubType>Form</SubType> </Compile> @@ -152,6 +164,9 @@ <EmbeddedResource Include="UI\M071_MainForm.resx"> <DependentUpon>M071_MainForm.cs</DependentUpon> </EmbeddedResource> <EmbeddedResource Include="UI\M071_PatchInsertMeasurement.resx"> <DependentUpon>M071_PatchInsertMeasurement.cs</DependentUpon> </EmbeddedResource> <EmbeddedResource Include="UI\M071_ShortcutFrm.resx"> <DependentUpon>M071_ShortcutFrm.cs</DependentUpon> </EmbeddedResource> src/Bro.M071.Process/M071Config.cs
@@ -41,12 +41,19 @@ public List<KeyResult> KeyResultCollection { get; set; } = new List<KeyResult>(); #endregion [Category("背景图片设置")] [Category("显示配置")] [Description("运行背景图片路径")] [Editor(typeof(FileDialogEditor), typeof(UITypeEditor))] [DisplayName("背景图片")] public string BackgroundImagePath { get; set; } [Category("显示配置")] [Description("键盘关键键位布局显示")] [TypeConverter(typeof(CollectionCountConvert))] [Editor(typeof(ComplexCollectionEditor<KeyLocation>), typeof(UITypeEditor))] [DisplayName("键位显示")] public List<KeyLocation> KeyLocationCollection { get; set; } = new List<KeyLocation>(); [Category("检测设置")] [Description("拍摄点位设置集合")] [TypeConverter(typeof(CollectionCountConvert))] src/Bro.M071.Process/M071Models.cs
@@ -17,6 +17,28 @@ namespace Bro.M071.Process { public class KeyLocation : IComplexDisplay { [Category("键名配置")] [Description("单键键名")] [TypeConverter(typeof(KeyNameDictConverter))] public string Key { get; set; } [Category("位置配置")] [Description("单键在键盘平面图上的位置显示")] public Rectangle KeyRect { get; set; } = new Rectangle(); [Category("位置配置")] [Description("单键之后间隙位置")] public Rectangle IntervalRect { get; set; } = new Rectangle(); public string GetDisplayText() { return $"{Key}:{KeyRect.X},{KeyRect.Y},{KeyRect.Width},{KeyRect.Height}"; } } public class KeyAlgorithem : IComplexDisplay { [Browsable(false)] @@ -282,7 +304,7 @@ #region 显示 [Browsable(false)] public Rectangle DisplayLocation { get; set; } = new Rectangle(); public Rectangle DisplayLocation { get; set; } = new Rectangle(10, 10, 100, 100); #endregion #region 检测结果 @@ -391,7 +413,7 @@ { if (valuePairs == null || valuePairs.Count == 0) { IsDone = false; IsDone = false; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsDone")); return; } src/Bro.M071.Process/M071Process.cs
@@ -9,6 +9,8 @@ using Bro.Process; using HalconDotNet; using Newtonsoft.Json; using OfficeOpenXml; using OfficeOpenXml.Style; using System; using System.Collections.Generic; using System.ComponentModel; @@ -61,7 +63,6 @@ Reset(null, null, null); FullReset(null); } private void InitialMotionCardBaseAxisAlarm() @@ -82,7 +83,7 @@ private void InitialSetting() { //数据库迁移检查 DatabaseInitialize.Initialize(); //DatabaseInitialize.Initialize(); MotionCardSettingCheck(); @@ -196,7 +197,7 @@ } MachineState = MachineState.Running; OnMeasureStart?.BeginInvoke(null, null); OnMeasureStart?.Invoke(); var measurements = Config.MeasurementUnitCollection.Where(u => u.IsEnabled).ToList().DeepSerializeClone(); measurements.ForEach(m => @@ -226,9 +227,12 @@ Config.SnapshotPointCollection.Where(u => u.IsEnabled).ToList().ForEach(s => { _pauseHandle.WaitHandle.WaitOne(); _pausedHandle.Wait(); if (MachineState != MachineState.Running) if (MachineState == MachineState.Ready) return; if (MachineState != MachineState.Running && MachineState != MachineState.Pause) { throw new ProcessException("机台状态不在运行中,退出检测"); } @@ -268,7 +272,7 @@ return; } RunImageHandle(camera, s.CameraOp.OpConfig, set, s.Id, s.Name, pMeasure.Measurements); RunImageHandle(s.CameraOp.OpConfig, set, s.Id, s.Name, pMeasure.Measurements); }); BarCode = ""; @@ -336,10 +340,14 @@ { if (sender is ProductionMeasurement pMeasure) { lock (pMeasure) var production = productionList.FirstOrDefault(u => u.Barcode == pMeasure.Barcode); if (production == null) return; lock (production) { //检查是否全部完成 pMeasure.Measurements.ForEach(m => pMeasure.Measurements?.ForEach(m => { if (m.KeyUnitCollection.All(k => k.IsDone != null)) { @@ -368,7 +376,7 @@ } else { m.Spec.ActualValue = _halconToolDict[toolKey].GetResultTuple("OUTPUT_Result").D; m.Spec.ActualValue = double.Parse(_halconToolDict[toolKey].GetResultTuple("OUTPUT_Result").D.ToString("f2")); LogAsync(DateTime.Now, $"{m.GetDisplayText()}数据{m.Spec.ActualValue},结果{(m.Spec.MeasureResult == null ? "TBD" : (m.Spec.MeasureResult == true ? "OK" : "NG"))}", ""); } } @@ -381,7 +389,7 @@ indicator.ResultState = m.Spec.MeasureResult; pMeasure.ElementList.Add(indicator); //输出图形基元到界面 OnElementUpdated?.BeginInvoke(indicator, null, null); OnElementUpdated?.Invoke(indicator); SaveKeyImages(pMeasure.Barcode, m); @@ -415,7 +423,9 @@ } //Excel报表输出 (单个产品的excel导出) ExportProductionExcel(measurementUnitResultAndKeyUnitDataSet); //ExportProductionExcel(measurementUnitResultAndKeyUnitDataSet); ExportProductionInColumns(measurementUnitResultAndKeyUnitDataSet); ////数据库保存 //SaveProductionData(measurementUnitResultAndKeyUnitDataSet); @@ -494,9 +504,20 @@ MeasurementUnitResult measurementUnitResult = new MeasurementUnitResult(); measurementUnitResult.ProductionMeasurementRecordsId = productionMeasurementRecords.ID; measurementUnitResult.ProductionBarcode = productionMeasurementRecords.ProductionBarcode; measurementUnitResult.MeasurementName = measurementUnit.Name; measurementUnitResult.MeasurementName = measurementUnit.GetDisplayText(); if (measurementUnit.MeasureType == "Alignment" || measurementUnit.MeasureType == "Slant") { measurementUnitResult.Keys = string.Join("-", measurementUnit.KeyUnitCollection.Select(u => u.Key)); measurementUnitResult.Positions = string.Join("-", measurementUnit.KeyUnitCollection.Select(u => u.KeyResultId)); } else if (measurementUnit.MeasureType == "RowAlignment") { measurementUnitResult.Keys = measurementUnit.KeyUnitCollection[0].Key + "~" + measurementUnit.KeyUnitCollection[measurementUnit.KeyUnitCollection.Count() - 1].Key; measurementUnitResult.Keys = measurementUnit.KeyUnitCollection[0].KeyResultId + "~" + measurementUnit.KeyUnitCollection[measurementUnit.KeyUnitCollection.Count() - 1].KeyResultId; } measurementUnitResult.MeasurementType = measurementUnit.MeasureType; measurementUnitResult.MeasurementValue = measurementUnit.Spec.ActualValue.ToString(); measurementUnitResult.MeasurementValue = measurementUnit.Spec.ActualValue == null ? "NA" : measurementUnit.Spec.ActualValue.Value.ToString("f2"); measurementUnitResult.MeasurementResult = measurementUnit.Spec.MeasureResult.Value ? "OK" : "NG"; measurementUnitResults.Add(measurementUnitResult); @@ -512,7 +533,7 @@ keyUnitData.ProductionBarcode = productionMeasurementRecords.ProductionBarcode; keyUnitData.Key = keyUnit.Key; keyUnitData.MeasurementItem = keyValue.Key; keyUnitData.ItemValue = keyValue.Value.ToString(); keyUnitData.ItemValue = keyValue.Value == null ? "NA" : keyValue.Value.Value.ToString("f2"); keyUnitDatas.Add(keyUnitData); MeasurementAndKeyDataRelation measurementAndKeyDataRelation = new MeasurementAndKeyDataRelation(); @@ -577,6 +598,342 @@ fs.Flush(); fs.Close(); }); } static object excelExportLock = new object(); private async void ExportProductionInColumns(ProductionMeasurementUnitResultAndKeyUnitDataSet exportData) { if (!Config.IsCSVOutputEnabled) return; await Task.Run(() => { lock (excelExportLock) { if (!Directory.Exists(Config.LogPath)) { Directory.CreateDirectory(Config.LogPath); } var fileName = Path.Combine(Config.LogPath, $"LDSData_{DateTime.Now.ToString("yyyyMMdd")}.xlsx"); //bool isExisted = File.Exists(fileName); using (ExcelPackage package = new ExcelPackage(new FileInfo(fileName))) { ExcelWorksheet rawDataSheet = null; ExcelWorksheet slantSheet = null; ExcelWorksheet alignmentSheet = null; ExcelWorksheet rowAlignmentSheet = null; if (!package.Workbook.Worksheets.Any(s => s.Name == "RawData")) { package.Workbook.Worksheets.Add("RawData"); rawDataSheet = package.Workbook.Worksheets["RawData"]; for (int i = 0; i < Config.KeyNameCollection.Count; i++) { var cell = rawDataSheet.Cells[i + 3, 1]; cell.Value = Config.KeyNameCollection[i]; SetTitleCell(cell, false); } } rawDataSheet = package.Workbook.Worksheets["RawData"]; if (!package.Workbook.Worksheets.Any(s => s.Name == "Slant")) { package.Workbook.Worksheets.Add("Slant"); slantSheet = package.Workbook.Worksheets["Slant"]; var keyCell = slantSheet.Cells[2, 1]; keyCell.Value = "Key"; SetTitleCell(keyCell); for (int i = 0; i < Config.KeyNameCollection.Count; i++) { var cell = slantSheet.Cells[i + 3, 1]; cell.Value = Config.KeyNameCollection[i]; SetTitleCell(cell, false); } } slantSheet = package.Workbook.Worksheets["Slant"]; if (!package.Workbook.Worksheets.Any(s => s.Name == "Alignment")) { package.Workbook.Worksheets.Add("Alignment"); alignmentSheet = package.Workbook.Worksheets["Alignment"]; var keysCell = alignmentSheet.Cells[2, 1]; keysCell.Value = "Keys"; SetTitleCell(keysCell); var positionCell = alignmentSheet.Cells[2, 2]; positionCell.Value = "Positions"; SetTitleCell(positionCell); var alignmentMeasures = exportData.MeasurementUnitResultList.Where(u => u.MeasurementType == "Alignment").ToList(); for (int i = 0; i < alignmentMeasures.Count(); i++) { var cellKeys = alignmentSheet.Cells[i + 3, 1]; cellKeys.Value = alignmentMeasures[i].Keys; SetTitleCell(cellKeys, false); var cellPosition = alignmentSheet.Cells[i + 3, 2]; cellPosition.Value = alignmentMeasures[i].Positions; SetTitleCell(cellPosition, false); } } alignmentSheet = package.Workbook.Worksheets["Alignment"]; if (!package.Workbook.Worksheets.Any(s => s.Name == "RowAlignment")) { package.Workbook.Worksheets.Add("RowAlignment"); rowAlignmentSheet = package.Workbook.Worksheets["RowAlignment"]; var keysCell = rowAlignmentSheet.Cells[2, 1]; keysCell.Value = "Keys"; SetTitleCell(keysCell); var positionCell = rowAlignmentSheet.Cells[2, 2]; positionCell.Value = "Positions"; SetTitleCell(positionCell); var rowAlignmentMeasures = exportData.MeasurementUnitResultList.Where(u => u.MeasurementType == "RowAlignment").ToList(); for (int i = 0; i < rowAlignmentMeasures.Count(); i++) { var cellKeys = rowAlignmentSheet.Cells[i + 3, 1]; cellKeys.Value = rowAlignmentMeasures[i].Keys; SetTitleCell(cellKeys, false); var cellPosition = rowAlignmentSheet.Cells[i + 3, 2]; cellPosition.Value = rowAlignmentMeasures[i].Positions; SetTitleCell(cellPosition, false); } } rowAlignmentSheet = package.Workbook.Worksheets["RowAlignment"]; #region RawData { //rawDataSheet = package.Workbook.Worksheets["RawData"]; int rowDataStartCol = rawDataSheet.Dimension.Columns; var barcodeCell = rawDataSheet.Cells[1, rowDataStartCol + 1, 1, rowDataStartCol + 4]; barcodeCell.Merge = true; barcodeCell.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; barcodeCell.Value = exportData.ProductionMeasurementRecord.ProductionBarcode; SetTitleCell(barcodeCell); var z1Cell = rawDataSheet.Cells[2, rowDataStartCol + 1]; z1Cell.Value = "Z1"; SetTitleCell(z1Cell); var z2Cell = rawDataSheet.Cells[2, rowDataStartCol + 2]; z2Cell.Value = "Z2"; SetTitleCell(z2Cell); var z3Cell = rawDataSheet.Cells[2, rowDataStartCol + 3]; z3Cell.Value = "Z3"; SetTitleCell(z3Cell); var z4Cell = rawDataSheet.Cells[2, rowDataStartCol + 4]; z4Cell.Value = "Z4"; SetTitleCell(z4Cell); exportData.KeyUnitDataList.ForEach(k => { int keyIndex = Config.KeyNameCollection.IndexOf(k.Key); if (keyIndex < 0) { LogAsync(DateTime.Now, "Excel导出错误", $"{k.Key}的RawData未能获取行信息,未导出"); return; } int zIndex = int.Parse(k.MeasurementItem.Substring(1)); var cell = rawDataSheet.Cells[keyIndex + 1 + 2, rowDataStartCol + zIndex]; cell.Value = string.IsNullOrWhiteSpace(k.ItemValue) ? "NA" : k.ItemValue; }); } #endregion #region Slant var slantMeasures = exportData.MeasurementUnitResultList.Where(u => u.MeasurementType == "Slant").ToList(); if (slantMeasures.Count > 0) { int slantStartCol = slantSheet.Dimension.Columns; var barcodeCell = slantSheet.Cells[1, slantStartCol + 1, 1, slantStartCol + 2]; barcodeCell.Merge = true; barcodeCell.Value = exportData.ProductionMeasurementRecord.ProductionBarcode; SetTitleCell(barcodeCell); var valueCell = slantSheet.Cells[2, slantStartCol + 1]; valueCell.Value = "Value"; SetTitleCell(valueCell); var resultCell = slantSheet.Cells[2, slantStartCol + 2]; resultCell.Value = "Result"; SetTitleCell(resultCell); slantMeasures.ForEach(m => { int rowIndex = Config.KeyNameCollection.IndexOf(m.Keys); if (rowIndex < 0) { LogAsync(DateTime.Now, "Excel导出错误", $"{m.Keys}的Slant未能获取行信息,未导出"); return; } var cellValue = slantSheet.Cells[rowIndex + 1 + 2, slantStartCol + 1]; var cellResult = slantSheet.Cells[rowIndex + 1 + 2, slantStartCol + 2]; cellValue.Value = m.MeasurementValue; cellResult.Value = m.MeasurementResult; if (m.MeasurementResult != "OK") { SetNGCell(cellValue); SetNGCell(cellResult); } }); } #endregion #region Alignment { var alignmentMeasures = exportData.MeasurementUnitResultList.Where(u => u.MeasurementType == "Alignment").ToList(); if (alignmentMeasures.Count > 0) { List<string> keysList = new List<string>(); int allRowNums = alignmentSheet.Dimension.Rows; int aligneStartCol = alignmentSheet.Dimension.Columns; for (int i = 3; i <= allRowNums; i++) { string keys = alignmentSheet.Cells[i, 1].Value.ToString(); string position = alignmentSheet.Cells[i, 2].Value.ToString(); keysList.Add($"{keys}_{position}"); } var barcodeCell = alignmentSheet.Cells[1, aligneStartCol + 1, 1, aligneStartCol + 2]; barcodeCell.Merge = true; barcodeCell.Value = exportData.ProductionMeasurementRecord.ProductionBarcode; SetTitleCell(barcodeCell); var valueCell = alignmentSheet.Cells[2, aligneStartCol + 1]; valueCell.Value = "Value"; SetTitleCell(valueCell); var resultCell = alignmentSheet.Cells[2, aligneStartCol + 2]; resultCell.Value = "Result"; SetTitleCell(resultCell); alignmentMeasures.ForEach(a => { int rowIndex = keysList.IndexOf($"{a.Keys}_{a.Positions}"); if (rowIndex < 0) { LogAsync(DateTime.Now, "Excel导出错误", $"{a.Keys}_{a.Positions}的Alignment未能获取行信息,未导出"); return; } var cellValue = alignmentSheet.Cells[rowIndex + 1 + 2, aligneStartCol + 1]; var cellResult = alignmentSheet.Cells[rowIndex + 1 + 2, aligneStartCol + 2]; cellValue.Value = a.MeasurementValue; cellResult.Value = a.MeasurementResult; if (a.MeasurementResult != "OK") { SetNGCell(cellValue); SetNGCell(cellResult); } }); } } #endregion #region RowAlignment { var rowAlignmentMeasures = exportData.MeasurementUnitResultList.Where(u => u.MeasurementType == "RowAlignment").ToList(); if (rowAlignmentMeasures.Count > 0) { List<string> keysList = new List<string>(); int allRowNums = rowAlignmentSheet.Dimension.Rows; int aligneStartCol = rowAlignmentSheet.Dimension.Columns; for (int i = 3; i <= allRowNums; i++) { string keys = alignmentSheet.Cells[i, 1].Value.ToString(); string position = alignmentSheet.Cells[i, 2].Value.ToString(); keysList.Add($"{keys}_{position}"); } var barcodeCell = rowAlignmentSheet.Cells[1, aligneStartCol + 1, 1, aligneStartCol + 2]; barcodeCell.Merge = true; barcodeCell.Value = exportData.ProductionMeasurementRecord.ProductionBarcode; SetTitleCell(barcodeCell); var valueCell = rowAlignmentSheet.Cells[2, aligneStartCol + 1]; valueCell.Value = "Value"; SetTitleCell(valueCell); var resultCell = rowAlignmentSheet.Cells[2, aligneStartCol + 2]; resultCell.Value = "Result"; SetTitleCell(resultCell); rowAlignmentMeasures.ForEach(a => { int rowIndex = keysList.IndexOf($"{a.Keys}_{a.Positions}"); if (rowIndex < 0) { LogAsync(DateTime.Now, "Excel导出错误", $"{a.Keys}_{a.Positions}的RowAlignment未能获取行信息,未导出"); return; } var cellValue = rowAlignmentSheet.Cells[rowIndex + 1 + 2, aligneStartCol + 1]; var cellResult = rowAlignmentSheet.Cells[rowIndex + 1 + 2, aligneStartCol + 2]; cellValue.Value = a.MeasurementValue; cellResult.Value = a.MeasurementResult; if (a.MeasurementResult != "OK") { SetNGCell(cellValue); SetNGCell(cellResult); } }); } } #endregion package.Save(); }; } }); } private void SetNGCell(ExcelRange cell) { cell.Style.Font.Color.SetColor(Color.White); cell.Style.Font.Bold = true; cell.Style.Fill.PatternType = ExcelFillStyle.Solid; cell.Style.Fill.BackgroundColor.SetColor(Color.Red); } private void SetTitleCell(ExcelRange cell, bool isCenterAlign = true) { cell.Style.Font.Color.SetColor(Color.White); cell.Style.Font.Bold = true; cell.Style.Fill.PatternType = ExcelFillStyle.Solid; cell.Style.Fill.BackgroundColor.SetColor(Color.FromArgb(31, 73, 125)); cell.AutoFitColumns(); if (isCenterAlign) { cell.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; } else { cell.Style.HorizontalAlignment = ExcelHorizontalAlignment.Left; } } #region 图像保存 @@ -670,7 +1027,7 @@ } #endregion private async void RunImageHandle(CameraBase camera, IOperationConfig opConfig, IImageSet imgSet, string snapshotId, string snapshotName, List<MeasurementUnit> measureList) private async void RunImageHandle(IOperationConfig opConfig, IImageSet imgSet, string snapshotId, string snapshotName, List<MeasurementUnit> measureList) { await Task.Run(() => { @@ -691,6 +1048,9 @@ keyBindCollection.ForEach(k => k.FillKeyValues(null)); return; } string fileName = Path.Combine(Config.ImageSaveFolder, "BeforeRun", $"{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.tif"); imgSet.HImage.WriteImage("tiff", 0, fileName); _halconToolDict[toolKey].InputImageDic["INPUT_Image"] = imgSet.HImage; if (!_halconToolDict[toolKey].RunProcedure(out string error)) @@ -723,19 +1083,22 @@ }); } string dir = Path.Combine(Config.ImageSaveFolder, "Clips", $"{snapshotName}_{DateTime.Now.ToString("HHmmss")}"); string dir = Path.Combine(Config.ImageSaveFolder, "Clips", $"{DateTime.Now.ToString("yyyyMMdd")}", $"{snapshotName}_{DateTime.Now.ToString("HHmmss")}"); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } Parallel.For(1, count.I + 1, (i) => //for (int i = 1; i <= count.I; i++) //Parallel.For(1, count.I + 1, (i) => for (int i = 1; i <= count.I; i++) { HOperatorSet.SelectObj(images, out HObject image, i); string fileName = Path.Combine(dir, $"{i}.tif"); image.ConvertHObjectToHImage().WriteImage("tiff", 0, fileName); using (HImage temp = image.ConvertHObjectToHImage()) { temp.WriteImage("tiff", 0, fileName); } keys.Where(u => u.ImageSeq == i).ToList().ForEach(k => { @@ -753,19 +1116,22 @@ _halconToolDict[keyToolKey].InputImageDic["INPUT_Image"] = image; _halconToolDict[keyToolKey].InputTupleDic["INPUT_Resolution_X"] = scanParam.Resolution_X / 1000000.0; _halconToolDict[keyToolKey].InputTupleDic["INPUT_Resolution_Z"] = scanParam.Resolution_Z / 1000000.0; _halconToolDict[keyToolKey].InputTupleDic["INPUT_ImageId"] = $"{k.AliasName}_{DateTime.Now.ToString("HHmmssfff")}.tif"; if (!_halconToolDict[keyToolKey].RunProcedure(out string error)) { LogAsync(DateTime.Now, $"{k.AliasName}检测算法异常,{error}", ""); } else { var results = _halconToolDict[keyToolKey].GetResultTuple("OUTPUT_Results").HTupleToDouble(); var results = _halconToolDict[keyToolKey].GetResultTuple("OUTPUT_Results").DArr.ToList(); if (results.Count == 0 || results.Any(u => u < 0)) { LogAsync(DateTime.Now, $"{k.AliasName}检测结果异常", ""); LogAsync(DateTime.Now, $"{k.AliasName}原始数据异常", ""); } else { //results = results.Select(u => double.Parse(u.ToString("f2"))).ToList(); LogAsync(DateTime.Now, $"{k.AliasName}原始数据", $"{string.Join(" ", results)}"); resultDict = k.KeyResultList.ToDictionary(u => u, u => { int index = k.KeyResultList.IndexOf(u); @@ -782,9 +1148,9 @@ }); }); //image.Dispose(); image.Dispose(); } ); //); //if (count.I != 1) //{ src/Bro.M071.Process/M071Process_MotionCard.cs
@@ -20,6 +20,7 @@ const int FULLRESETTIME = 5; object machineStateLock = new object(); //MachineState _machineStatePre = MachineState.Unknown; MachineState machineState = MachineState.Unknown; public MachineState MachineState { @@ -31,100 +32,121 @@ machineState = value; switch (machineState) Task.Run(() => { case MachineState.Ready: lock (machineStateLock) { SwitchBeep(false); SwitchLightRed(false); SwitchLightYellow(false); } Task.Run(() => { while (MachineState == MachineState.Ready) switch (machineState) { case MachineState.Ready: lock (machineStateLock) { lock (machineStateLock) { SwitchLightGreen(true); Thread.Sleep(1000); SwitchLightGreen(false); Thread.Sleep(1000); } SwitchBeep(false); SwitchLightRed(false); SwitchLightYellow(false); } }); break; case MachineState.Running: lock (machineStateLock) { SwitchBeep(false); SwitchLightRed(false); SwitchLightYellow(false); SwitchLightGreen(true); } break; case MachineState.Alarm: lock (machineStateLock) { SwitchBeep(true); SwitchLightRed(true); SwitchLightYellow(false); SwitchLightGreen(false); } break; case MachineState.Pause: lock (machineStateLock) { SwitchBeep(false); SwitchLightRed(false); } Task.Run(() => { while (MachineState == MachineState.Pause) Task.Run(() => { lock (machineStateLock) while (MachineState == MachineState.Ready) { SwitchLightYellow(true); SwitchLightGreen(true); Thread.Sleep(1000); SwitchLightYellow(false); SwitchLightGreen(false); Thread.Sleep(1000); lock (machineStateLock) { SwitchLightGreen(true); Thread.Sleep(1000); SwitchLightGreen(false); Thread.Sleep(1000); } } } }); break; case MachineState.Resetting: lock (machineStateLock) { SwitchBeep(false); SwitchLightRed(false); SwitchLightGreen(false); } Task.Run(() => { while (MachineState == MachineState.Resetting) { lock (machineStateLock) { }); SwitchLightYellow(true); Thread.Sleep(1000); SwitchLightYellow(false); Thread.Sleep(1000); } break; case MachineState.Running: lock (machineStateLock) { SwitchBeep(false); SwitchLightRed(false); SwitchLightYellow(false); SwitchLightGreen(true); } }); break; default: break; } break; case MachineState.Alarm: lock (machineStateLock) { SwitchBeep(true); SwitchLightRed(true); SwitchLightYellow(false); SwitchLightGreen(false); } break; case MachineState.Pause: lock (machineStateLock) { SwitchBeep(false); SwitchLightRed(false); } Task.Run(() => { while (MachineState == MachineState.Pause) { lock (machineStateLock) { SwitchLightYellow(true); SwitchLightGreen(true); Thread.Sleep(1000); SwitchLightYellow(false); SwitchLightGreen(false); Thread.Sleep(1000); } } }); break; case MachineState.Resetting: lock (machineStateLock) { SwitchBeep(false); SwitchLightRed(false); SwitchLightGreen(false); } Task.Run(() => { while (MachineState == MachineState.Resetting) { lock (machineStateLock) { SwitchLightYellow(true); Thread.Sleep(1000); SwitchLightYellow(false); Thread.Sleep(1000); } } }); break; default: break; } }); OnMachineStateChanged?.Invoke(machineState); } } private void Pause() { #region 板卡暂停动作 outputCtrlCard.SetImmediatePause(); #endregion //_pauseHandle.WaitHandle.Reset(); //_pauseHandle.WaitResult = true; } private void Resume(bool isResumeContinueMoving) { #region 板卡恢复动作 outputCtrlCard.ResetImmediatePause(isResumeContinueMoving); #endregion //_pauseHandle.WaitHandle.Set(); //_pauseHandle.WaitResult = false; } private void MotionCardSettingCheck() @@ -203,24 +225,6 @@ [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("未配置复位操作执行设备"); // } //} if (ResetTimer == null) { ResetTimer = new Timer(FullReset, null, -1, -1); @@ -245,26 +249,23 @@ (invokeDevice as MotionCardBase).ResetAlarm(); RaisedAlarm(""); MachineState = MachineState.Ready; if (MachineState != MachineState.Pause) { MachineState = MachineState.Ready; } else { LogAsync(DateTime.Now, "设备暂停中,无法复位", ""); return new ProcessResponse(true); } if (IsEmergencyStopped) { RaisedAlarm("急停按钮未恢复,请执行大复位"); MachineState = MachineState.Alarm; return new ProcessResponse(true); } //if (opConfig.InputPara?.Count > 0) //{ // //大复位信号 // ResetTimer.Change(-1, opConfig.InputPara[0] == 1 ? FULLRESETTIME * 1000 : -1); //} //if (invokeDevice is MotionCardBase motionCard) //{ // motionCard.Run(opConfig); //} LogAsync(DateTime.Now, "普通复位动作完成", ""); @@ -287,28 +288,16 @@ [ProcessMethod("MotionCardBase", "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("未配置默认大复位操作"); if (!IsAllowedWork) { LogAsync(DateTime.Now, $"{SafetyMsg},大复位失败", ""); return new ProcessResponse(false); } // 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); //} if (MachineState == MachineState.Pause) { Resume(false); } MachineState = MachineState.Resetting; MotionCardDefaultRun("FullReset", ref opConfig, ref invokeDevice); @@ -335,12 +324,12 @@ /// WaitHandle 暂停句柄 默认为非阻塞 可执行 /// WaitResult 暂停标志 true 正常执行 false 暂停中 /// </summary> ManualWaitConfirm _pauseHandle = new ManualWaitConfirm() { WaitHandle = new ManualResetEvent(true), WaitResult = true, }; MachineState _machineStateBeforePause = MachineState.Unknown; //ManualWaitConfirm _pauseHandle = new ManualWaitConfirm() //{ // WaitHandle = new ManualResetEvent(true), // WaitResult = true, //}; List<MachineState> _statesAllowPause = new List<MachineState>() { MachineState.Running, MachineState.Ready, MachineState.Pause }; [ProcessMethod("", "SwitchJobStatus", "流程状态切换", InvokeType.TestInvoke)] public ProcessResponse SwitchJobStatus(IOperationConfig opConfig, IDevice invokeDevice, IDevice sourceDevice) @@ -358,10 +347,7 @@ throw new ProcessException("未获取板卡设备"); bool? isToPause = null; //true 暂停 false 继续 //if (opConfig.InputPara != null && opConfig.InputPara.Count > 0) //{ // isToPause = opConfig.InputPara[0] == 1; //} if (opConfig.InputPara[0] == 10) { isToPause = false; @@ -373,59 +359,41 @@ if (isToPause == null) { if (!_pauseHandle.WaitResult) { #region 板卡暂停动作 motionDevice.SetImmediatePause(); #endregion _pauseHandle.WaitHandle.Reset(); _pauseHandle.WaitResult = true; _machineStateBeforePause = MachineState; MachineState = MachineState.Pause; } else if (!_pauseHandle.WaitResult) { #region 板卡恢复动作 motionDevice.ResetImmediatePause(); #endregion _pauseHandle.WaitHandle.Set(); _pauseHandle.WaitResult = false; MachineState = _machineStateBeforePause; } IsManualPaused = !IsManualPaused; } else { if (isToPause.Value) { if (!_pauseHandle.WaitResult) { #region 板卡暂停动作 motionDevice.SetImmediatePause(); #endregion //if (isToPause.Value) //{ // if (!_pauseHandle.WaitResult) // { // //#region 板卡暂停动作 // //motionDevice.SetImmediatePause(); // //#endregion _pauseHandle.WaitHandle.Reset(); _pauseHandle.WaitResult = true; MachineState = MachineState.Pause; } } else { if (!_pauseHandle.WaitResult) { #region 板卡恢复动作 motionDevice.ResetImmediatePause(); #endregion // //_pauseHandle.WaitHandle.Reset(); // //_pauseHandle.WaitResult = true; // MachineState = MachineState.Pause; // } //} //else //{ // if (!_pauseHandle.WaitResult) // { // //#region 板卡恢复动作 // //motionDevice.ResetImmediatePause(); // //#endregion _pauseHandle.WaitHandle.Set(); _pauseHandle.WaitResult = false; MachineState = _machineStateBeforePause; } } // //_pauseHandle.WaitHandle.Set(); // //_pauseHandle.WaitResult = false; // MachineState = _machineStatePre; // } //} IsManualPaused = isToPause.Value; } return new ProcessResponse(_pauseHandle.WaitResult); return new ProcessResponse(IsManualPaused); } ////[ProcessMethod("", "PauseJob", "暂停流程", InvokeType.TestInvoke)] @@ -633,6 +601,7 @@ { get => !(IsSafetyBeamTrigged || IsSafetyDoorTrigged || IsEmergencyStopped); } string SafetyMsg { get => $"{(IsSafetyBeamTrigged ? "安全光幕" : "")}{(IsSafetyDoorTrigged ? " 安全门" : "")}{(IsEmergencyStopped ? " 急停按钮" : "")}触发中"; @@ -641,21 +610,85 @@ #region 安全门 & 安全光线 bool isSafetyDoorTrigged = false; bool isSafetyBeamTrigged = false; bool isManualPaused = false; public bool IsSafetyDoorTrigged { get => !Config.IsSafetyDoorBlocked && isSafetyDoorTrigged; set => isSafetyDoorTrigged = value; get => (!Config.IsSafetyDoorBlocked) && isSafetyDoorTrigged; set { isSafetyDoorTrigged = value; CheckMachinePauseState(); } } public bool IsSafetyBeamTrigged { get => !Config.IsSafetyBeamBlocked && isSafetyBeamTrigged; set => isSafetyBeamTrigged = value; get => (!Config.IsSafetyBeamBlocked) && isSafetyBeamTrigged; set { isSafetyBeamTrigged = value; CheckMachinePauseState(); } } public bool IsManualPaused { get => isManualPaused; set { isManualPaused = value; CheckMachinePauseState(); } } ManualResetEventSlim _pausedHandle = new ManualResetEventSlim(true); MachineState _machineStateBeforePause = MachineState.Unknown; private void CheckMachinePauseState() { //await Task.Run(() => { if (IsMachinePaused) { if (MachineState == MachineState.Ready || MachineState == MachineState.Running) { _machineStateBeforePause = MachineState; } MachineState = MachineState.Pause; _pausedHandle.Reset(); if (_machineStateBeforePause == MachineState.Running) { Pause(); } } else { if (MachineState == MachineState.Pause) { if (_machineStateBeforePause == MachineState.Running) { Resume(true); } _pausedHandle.Set(); RaisedAlarm(""); MachineState = _machineStateBeforePause; } } } //); } public bool IsMachinePaused { get => IsSafetyBeamTrigged || IsSafetyDoorTrigged || IsManualPaused; } [ProcessMethod("", "SafetyDoorSignal", "安全门信号监控,正常ON,OFF时报警", InvokeType.TestInvoke)] public ProcessResponse SafetyDoorSignal(IOperationConfig opConfig, IDevice invokeDevice, IDevice sourceDevice) { //if (MachineState != MachineState.Running && MachineState != MachineState.Pause) // return new ProcessResponse(true); if (opConfig.InputPara == null || opConfig.InputPara.Count == 0) throw new ProcessException("安全门监控未配置输入信号"); @@ -664,7 +697,6 @@ if (IsSafetyDoorTrigged) { RaisedAlarm("安全门未正常关闭"); MachineState = MachineState.Alarm; } return new ProcessResponse(true); @@ -673,9 +705,6 @@ [ProcessMethod("", "SafetyBeamSignal", "安全光幕信号监控,正常ON,OFF时报警", InvokeType.TestInvoke)] public ProcessResponse SafetyBeamSignal(IOperationConfig opConfig, IDevice invokeDevice, IDevice sourceDevice) { if (MachineState != MachineState.Running && MachineState != MachineState.Alarm) return new ProcessResponse(true); if (opConfig.InputPara == null || opConfig.InputPara.Count == 0) throw new ProcessException("安全光幕监控未配置输入信号"); @@ -684,7 +713,6 @@ if (IsSafetyBeamTrigged) { RaisedAlarm("安全光线被遮挡"); MachineState = MachineState.Alarm; } return new ProcessResponse(true); @@ -719,7 +747,7 @@ IsEmergencyStopped = opConfig.InputPara[0] == 0; if (IsEmergencyStopped) if (isEmergencyStopped) { RaisedAlarm("急停按钮被拍下"); MachineState = MachineState.Alarm; src/Bro.M071.Process/UI/M071_MainForm.Designer.cs
@@ -48,6 +48,7 @@ this.lvMeasures = new System.Windows.Forms.ListView(); this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.propGridKeyIndicator = new System.Windows.Forms.PropertyGrid(); this.tsmiRefreshLabels = new System.Windows.Forms.ToolStripMenuItem(); this.contextMenuStrip1.SuspendLayout(); this.plImage.SuspendLayout(); this.tscEditLocation.ContentPanel.SuspendLayout(); @@ -64,15 +65,16 @@ this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.tsmiShowToolBar, this.tsmiShowStatusBar, this.tsmiShowEditor}); this.tsmiShowEditor, this.tsmiRefreshLabels}); this.contextMenuStrip1.Name = "contextMenuStrip1"; this.contextMenuStrip1.Size = new System.Drawing.Size(149, 70); this.contextMenuStrip1.Size = new System.Drawing.Size(181, 114); // // tsmiShowToolBar // this.tsmiShowToolBar.CheckOnClick = true; this.tsmiShowToolBar.Name = "tsmiShowToolBar"; this.tsmiShowToolBar.Size = new System.Drawing.Size(148, 22); this.tsmiShowToolBar.Size = new System.Drawing.Size(180, 22); this.tsmiShowToolBar.Text = "显示工具条"; this.tsmiShowToolBar.CheckedChanged += new System.EventHandler(this.tsmiShowToolBar_CheckedChanged); // @@ -80,7 +82,7 @@ // this.tsmiShowStatusBar.CheckOnClick = true; this.tsmiShowStatusBar.Name = "tsmiShowStatusBar"; this.tsmiShowStatusBar.Size = new System.Drawing.Size(148, 22); this.tsmiShowStatusBar.Size = new System.Drawing.Size(180, 22); this.tsmiShowStatusBar.Text = "显示状态栏"; this.tsmiShowStatusBar.CheckedChanged += new System.EventHandler(this.tsmiShowStatusBar_CheckedChanged); // @@ -88,7 +90,7 @@ // this.tsmiShowEditor.CheckOnClick = true; this.tsmiShowEditor.Name = "tsmiShowEditor"; this.tsmiShowEditor.Size = new System.Drawing.Size(148, 22); this.tsmiShowEditor.Size = new System.Drawing.Size(180, 22); this.tsmiShowEditor.Text = "编辑显示点位"; this.tsmiShowEditor.CheckedChanged += new System.EventHandler(this.tsmiShowEditor_CheckedChanged); // @@ -291,6 +293,13 @@ this.propGridKeyIndicator.TabIndex = 0; this.propGridKeyIndicator.ToolbarVisible = false; // // tsmiRefreshLabels // this.tsmiRefreshLabels.Name = "tsmiRefreshLabels"; this.tsmiRefreshLabels.Size = new System.Drawing.Size(180, 22); this.tsmiRefreshLabels.Text = "刷新显示点位"; this.tsmiRefreshLabels.Click += new System.EventHandler(this.tsmiRefreshLabels_Click); // // M071_MainForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -343,5 +352,6 @@ private System.Windows.Forms.Button btnStartMeasure; private System.Windows.Forms.Button btnReset; private System.Windows.Forms.ColumnHeader columnHeader1; private System.Windows.Forms.ToolStripMenuItem tsmiRefreshLabels; } } src/Bro.M071.Process/UI/M071_MainForm.cs
@@ -136,6 +136,27 @@ tscEditLocation.Visible = tsmiShowEditor.Checked; tscEditLocation.BringToFront(); } private void tsmiRefreshLabels_Click(object sender, EventArgs e) { cvImage.Elements.Clear(); lvMeasures.Items.Clear(); Config.MeasurementUnitCollection.ForEach(u => { if (!u.IsEnabled) return; var ele = new KeyIndicator(u.Id, u.DisplayLocation); cvImage.Elements.Add(ele); ListViewItem item = new ListViewItem(u.GetDisplayText()); item.Tag = u.Id; lvMeasures.Items.Add(item); }); this.Invalidate(); } #endregion #region 标签编辑区 @@ -292,7 +313,7 @@ { if (lblMachineState.IsHandleCreated) { lblMachineState.BeginInvoke(new Action(() => lblMachineState.Invoke(new Action(() => { switch (state) { @@ -453,5 +474,6 @@ Process_M071.ResetTimer.Change(-1, -1); } #endregion } } src/Bro.M071.Process/UI/M071_PatchInsertMeasurement.Designer.cs
New file @@ -0,0 +1,133 @@ namespace Bro.M071.Process.UI { partial class M071_PatchInsertMeasurement { /// <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.label1 = new System.Windows.Forms.Label(); this.cboMeasureType = new System.Windows.Forms.ComboBox(); this.label2 = new System.Windows.Forms.Label(); this.cboStartKey = new System.Windows.Forms.ComboBox(); this.label3 = new System.Windows.Forms.Label(); this.cboEndKey = new System.Windows.Forms.ComboBox(); this.btnInsertMeasurement = new System.Windows.Forms.Button(); this.SuspendLayout(); // // label1 // this.label1.AutoSize = true; this.label1.Location = new System.Drawing.Point(22, 14); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(55, 13); this.label1.TabIndex = 0; this.label1.Text = "测量类型"; // // cboMeasureType // this.cboMeasureType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cboMeasureType.FormattingEnabled = true; this.cboMeasureType.Location = new System.Drawing.Point(95, 11); this.cboMeasureType.Name = "cboMeasureType"; this.cboMeasureType.Size = new System.Drawing.Size(121, 21); this.cboMeasureType.TabIndex = 1; // // label2 // this.label2.AutoSize = true; this.label2.Location = new System.Drawing.Point(22, 53); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(43, 13); this.label2.TabIndex = 0; this.label2.Text = "起始键"; // // cboStartKey // this.cboStartKey.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cboStartKey.FormattingEnabled = true; this.cboStartKey.Location = new System.Drawing.Point(95, 50); this.cboStartKey.Name = "cboStartKey"; this.cboStartKey.Size = new System.Drawing.Size(121, 21); this.cboStartKey.TabIndex = 1; // // label3 // this.label3.AutoSize = true; this.label3.Location = new System.Drawing.Point(22, 92); this.label3.Name = "label3"; this.label3.Size = new System.Drawing.Size(43, 13); this.label3.TabIndex = 0; this.label3.Text = "结束键"; // // cboEndKey // this.cboEndKey.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cboEndKey.FormattingEnabled = true; this.cboEndKey.Location = new System.Drawing.Point(95, 89); this.cboEndKey.Name = "cboEndKey"; this.cboEndKey.Size = new System.Drawing.Size(121, 21); this.cboEndKey.TabIndex = 1; // // btnInsertMeasurement // this.btnInsertMeasurement.Location = new System.Drawing.Point(25, 133); this.btnInsertMeasurement.Name = "btnInsertMeasurement"; this.btnInsertMeasurement.Size = new System.Drawing.Size(192, 36); this.btnInsertMeasurement.TabIndex = 2; this.btnInsertMeasurement.Text = "生成检测项"; this.btnInsertMeasurement.UseVisualStyleBackColor = true; this.btnInsertMeasurement.Click += new System.EventHandler(this.btnInsertMeasurement_Click); // // M071_PatchInsertMeasurement // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(800, 488); this.Controls.Add(this.btnInsertMeasurement); this.Controls.Add(this.cboEndKey); this.Controls.Add(this.cboStartKey); this.Controls.Add(this.cboMeasureType); this.Controls.Add(this.label3); this.Controls.Add(this.label2); this.Controls.Add(this.label1); this.Name = "M071_PatchInsertMeasurement"; this.Text = "M071_PatchInsertMeasurement"; this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.Label label1; private System.Windows.Forms.ComboBox cboMeasureType; private System.Windows.Forms.Label label2; private System.Windows.Forms.ComboBox cboStartKey; private System.Windows.Forms.Label label3; private System.Windows.Forms.ComboBox cboEndKey; private System.Windows.Forms.Button btnInsertMeasurement; } } src/Bro.M071.Process/UI/M071_PatchInsertMeasurement.cs
New file @@ -0,0 +1,161 @@ using Bro.Common.Helper; 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_PatchInsertMeasurement", "批量生成检测项", 4, "M071Node", true)] public partial class M071_PatchInsertMeasurement : MenuFrmBase { public M071_PatchInsertMeasurement() { InitializeComponent(); } M071Config Config => Process?.IConfig as M071Config; M071Process Process_M071 => Process as M071Process; public override void OnProcessUpdated() { base.OnProcessUpdated(); if (Config == null) return; this.Invoke(new Action(() => { UIHelper.SetCombo(cboMeasureType, Config.MeasureTypeCollection, "Code", "Code"); UIHelper.SetCombo(cboStartKey, new List<string>(Config.KeyNameCollection), "", ""); UIHelper.SetCombo(cboEndKey, new List<string>(Config.KeyNameCollection), "", ""); })); } private async void btnInsertMeasurement_Click(object sender, EventArgs e) { btnInsertMeasurement.Enabled = false; btnInsertMeasurement.Text = "生成中。。。"; string measureType = cboMeasureType.Text; string startKey = cboStartKey.Text; string endKey = cboEndKey.Text; await PatchInsertMeasurement(measureType, startKey, endKey).ContinueWith(t => { MessageBox.Show(t.Result); }); btnInsertMeasurement.Enabled = true; btnInsertMeasurement.Text = "生成检测项"; } private async Task<string> PatchInsertMeasurement(string measureType, string startKey, string endKey) { return await Task.Run(() => { int startIndex = Config.KeyNameCollection.IndexOf(startKey); int endIndex = Config.KeyNameCollection.IndexOf(endKey); KeyLocation startRect = Config.KeyLocationCollection.FirstOrDefault(u => u.Key == startKey); //KeyLocation endRect = Config.KeyLocationCollection.FirstOrDefault(u => u.Key == endKey); if (startRect == null) { return $"未配置{(startRect == null ? startKey : "")}的显示位置"; } if (startIndex > endIndex) { return "起始键不能小于结束键"; } switch (measureType) { case "Slant": { for (int i = startIndex; i <= endIndex; i++) { int curKeyEdge_X = (i - startIndex + 1) * (startRect.KeyRect.Width + startRect.IntervalRect.Width) + startRect.KeyRect.X - startRect.IntervalRect.Width; int lableX = (curKeyEdge_X + curKeyEdge_X - startRect.KeyRect.Width - 25) / 2; int lable_Up_Y = startRect.KeyRect.Y + (startRect.KeyRect.Height - 25) / 2; MeasurementUnit mUnitUp = new MeasurementUnit(); mUnitUp.MeasureType = measureType; mUnitUp.KeyUnitCollection.Add(new KeyUnitBind() { Key = Config.KeyNameCollection[i], KeyResultId = "All" }); mUnitUp.DisplayLocation = new Rectangle(lableX, lable_Up_Y, 25, 25); Config.MeasurementUnitCollection.Add(mUnitUp); } } break; case "Alignment": { for (int i = startIndex; i < endIndex; i++) { int curKeyEdge_X = (i - startIndex + 1) * (startRect.KeyRect.Width + startRect.IntervalRect.Width) + startRect.KeyRect.X - startRect.IntervalRect.Width; int nextKeyStart_X = curKeyEdge_X + startRect.IntervalRect.Width; int lableX = (curKeyEdge_X + nextKeyStart_X - 25) / 2; int lable_Up_Y = startRect.KeyRect.Y + 4; int lable_Down_y = startRect.KeyRect.Y + startRect.KeyRect.Height - 4 - 12; MeasurementUnit mUnitUp = new MeasurementUnit(); mUnitUp.MeasureType = measureType; mUnitUp.KeyUnitCollection.Add(new KeyUnitBind() { Key = Config.KeyNameCollection[i], KeyResultId = "Z2" }); mUnitUp.KeyUnitCollection.Add(new KeyUnitBind() { Key = Config.KeyNameCollection[i + 1], KeyResultId = "Z1" }); mUnitUp.DisplayLocation = new Rectangle(lableX, lable_Up_Y, 25, 12); Config.MeasurementUnitCollection.Add(mUnitUp); MeasurementUnit mUnitDown = new MeasurementUnit(); mUnitDown.MeasureType = measureType; mUnitDown.KeyUnitCollection.Add(new KeyUnitBind() { Key = Config.KeyNameCollection[i], KeyResultId = "Z4" }); mUnitDown.KeyUnitCollection.Add(new KeyUnitBind() { Key = Config.KeyNameCollection[i + 1], KeyResultId = "Z3" }); mUnitDown.DisplayLocation = new Rectangle(lableX, lable_Down_y, 25, 12); Config.MeasurementUnitCollection.Add(mUnitDown); } } break; case "RowAlignment": { int start_X = startRect.KeyRect.X + startRect.KeyRect.Width / 3; int end_X = (startRect.KeyRect.Width + startRect.IntervalRect.Width) * (endIndex - startIndex) + startRect.KeyRect.X + startRect.KeyRect.Width * 2 / 3; int lable_Up_Y = startRect.KeyRect.Y - 6; int lable_Down_Y = startRect.KeyRect.Y + startRect.KeyRect.Height - 6; MeasurementUnit mUnitUp = new MeasurementUnit(); mUnitUp.MeasureType = measureType; for (int i = startIndex; i < endIndex; i++) { mUnitUp.KeyUnitCollection.Add(new KeyUnitBind() { Key = Config.KeyNameCollection[i], KeyResultId = "Z2" }); mUnitUp.KeyUnitCollection.Add(new KeyUnitBind() { Key = Config.KeyNameCollection[i + 1], KeyResultId = "Z1" }); } mUnitUp.DisplayLocation = new Rectangle(start_X, lable_Up_Y, end_X - start_X, 12); Config.MeasurementUnitCollection.Add(mUnitUp); MeasurementUnit mUnitDown = new MeasurementUnit(); mUnitDown.MeasureType = measureType; for (int i = startIndex; i < endIndex; i++) { mUnitDown.KeyUnitCollection.Add(new KeyUnitBind() { Key = Config.KeyNameCollection[i], KeyResultId = "Z4" }); mUnitDown.KeyUnitCollection.Add(new KeyUnitBind() { Key = Config.KeyNameCollection[i + 1], KeyResultId = "Z3" }); } mUnitDown.DisplayLocation = new Rectangle(start_X, lable_Down_Y, end_X - start_X, 12); Config.MeasurementUnitCollection.Add(mUnitDown); } break; } return "已批量生成检测项,请到配置界面查看和保存"; }); } } } src/Bro.M071.Process/UI/M071_PatchInsertMeasurement.resx
New file @@ -0,0 +1,120 @@ <?xml version="1.0" encoding="utf-8"?> <root> <!-- Microsoft ResX Schema Version 2.0 The primary goals of this format is to allow a simple XML format that is mostly human readable. The generation and parsing of the various data types are done through the TypeConverter classes associated with the data types. Example: ... ado.net/XML headers & schema ... <resheader name="resmimetype">text/microsoft-resx</resheader> <resheader name="version">2.0</resheader> <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> <value>[base64 mime encoded serialized .NET Framework object]</value> </data> <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> <comment>This is a comment</comment> </data> There are any number of "resheader" rows that contain simple name/value pairs. Each data row contains a name, and value. The row also contains a type or mimetype. Type corresponds to a .NET class that support text/value conversion through the TypeConverter architecture. Classes that don't support this are serialized and stored with the mimetype set. The mimetype is used for serialized objects, and tells the ResXResourceReader how to depersist the object. This is currently not extensible. For a given mimetype the value must be set accordingly: Note - application/x-microsoft.net.object.binary.base64 is the format that the ResXResourceWriter will generate, however the reader can read any of the formats listed below. mimetype: application/x-microsoft.net.object.binary.base64 value : The object must be serialized with : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter : and then encoded with base64 encoding. mimetype: application/x-microsoft.net.object.soap.base64 value : The object must be serialized with : System.Runtime.Serialization.Formatters.Soap.SoapFormatter : and then encoded with base64 encoding. mimetype: application/x-microsoft.net.object.bytearray.base64 value : The object must be serialized into a byte array : using a System.ComponentModel.TypeConverter : and then encoded with base64 encoding. --> <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> <xsd:element name="root" msdata:IsDataSet="true"> <xsd:complexType> <xsd:choice maxOccurs="unbounded"> <xsd:element name="metadata"> <xsd:complexType> <xsd:sequence> <xsd:element name="value" type="xsd:string" minOccurs="0" /> </xsd:sequence> <xsd:attribute name="name" use="required" type="xsd:string" /> <xsd:attribute name="type" type="xsd:string" /> <xsd:attribute name="mimetype" type="xsd:string" /> <xsd:attribute ref="xml:space" /> </xsd:complexType> </xsd:element> <xsd:element name="assembly"> <xsd:complexType> <xsd:attribute name="alias" type="xsd:string" /> <xsd:attribute name="name" type="xsd:string" /> </xsd:complexType> </xsd:element> <xsd:element name="data"> <xsd:complexType> <xsd:sequence> <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> </xsd:sequence> <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> <xsd:attribute ref="xml:space" /> </xsd:complexType> </xsd:element> <xsd:element name="resheader"> <xsd:complexType> <xsd:sequence> <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> </xsd:sequence> <xsd:attribute name="name" type="xsd:string" use="required" /> </xsd:complexType> </xsd:element> </xsd:choice> </xsd:complexType> </xsd:element> </xsd:schema> <resheader name="resmimetype"> <value>text/microsoft-resx</value> </resheader> <resheader name="version"> <value>2.0</value> </resheader> <resheader name="reader"> <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> </resheader> <resheader name="writer"> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> </resheader> </root> src/Bro.M071.Process/packages.config
@@ -2,6 +2,7 @@ <packages> <package id="Autofac" version="4.9.4" targetFramework="net452" /> <package id="DockPanelSuite" version="3.0.6" targetFramework="net452" /> <package id="EPPlus" version="4.5.3.3" targetFramework="net452" /> <package id="Newtonsoft.Json" version="11.0.2" targetFramework="net452" /> <package id="PostSharp.Redist" version="6.2.7" targetFramework="net452" /> <package id="WeifenLuo.WinFormsUI.Docking" version="2.1.0" targetFramework="net452" /> src/Bro.UI.Config/MainFrm.cs
@@ -331,9 +331,14 @@ { foreach (var dock in dockPanelMain.Contents) { MenuFrmBase m = dock as MenuFrmBase; //MenuFrmBase m = dock as MenuFrmBase; m.DownloadProcess(_process); //m.DownloadProcess(_process); if (dock is MenuFrmBase menuFrm) { menuFrm.DownloadProcess(_process); } } } catch (Exception ex) src/Bro.UI.Model.Winform/CommonHelper.cs
@@ -60,7 +60,12 @@ /// 1st MouseState 初始状态 /// 2nd MouseState 变化状态 /// </summary> public static Action<ElementBase, ElementState, ElementState> ChangeElementsMouseState; public static event Action<ElementBase, ElementState, ElementState> ChangeElementsMouseState; public static void TriggerElementsMouseStateChanged(ElementBase ele, ElementState preState, ElementState curState) { ChangeElementsMouseState?.Invoke(ele, preState, curState); } } public class NoticedPoints : List<Point> src/Bro.UI.Model.Winform/ElementBase.cs
@@ -191,7 +191,7 @@ { ElementState preState = state; Set(ref state, value); EventRouter.ChangeElementsMouseState?.Invoke(this, preState, state); EventRouter.TriggerElementsMouseStateChanged(this, preState, state); switch (state) { case ElementState.MouseHover: src/Bro.UI.Model.Winform/UI/CanvasImage.cs
@@ -31,7 +31,8 @@ MouseMove += Canvas_MouseMove; MouseUp += Canvas_MouseUp; EventRouter.ChangeElementsMouseState = OnElementChangeMouseState; EventRouter.ChangeElementsMouseState -= OnElementChangeMouseState; EventRouter.ChangeElementsMouseState += OnElementChangeMouseState; } #region Event