|
|
@@ -7,6 +7,7 @@ using Prism.Events;
|
|
|
using Prism.Ioc;
|
|
|
using Prism.Mvvm;
|
|
|
using Prism.Regions;
|
|
|
+using SqlSugar;
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Collections.ObjectModel;
|
|
|
@@ -19,6 +20,7 @@ using System.Security.Claims;
|
|
|
using System.Text;
|
|
|
using System.Threading;
|
|
|
using System.Threading.Tasks;
|
|
|
+using System.Web;
|
|
|
using System.Web.UI.WebControls;
|
|
|
using System.Windows.Media;
|
|
|
using Team.FFFeederService.Interfaces;
|
|
|
@@ -1201,6 +1203,7 @@ namespace TeamAAS_VP.Core
|
|
|
addressConfig.In_RequestPosition.Address,
|
|
|
addressConfig.In_QrCodePhotoRequest.Address,
|
|
|
addressConfig.In_ScrewTeachExe.Address,
|
|
|
+ addressConfig.In_Screw_checkExe.Address,
|
|
|
addressConfig.In_PickINC.Address,
|
|
|
addressConfig.In_Throw.Address,
|
|
|
addressConfig.RunMode.Address,
|
|
|
@@ -1208,6 +1211,7 @@ namespace TeamAAS_VP.Core
|
|
|
addressConfig.ManualMode.Address,
|
|
|
addressConfig.ClearMode.Address,
|
|
|
addressConfig.Fault.Address,
|
|
|
+ addressConfig.In_FzCameraPixExe.Address,
|
|
|
};
|
|
|
var systemconfig = _configService.GetSystemConfiguration();
|
|
|
for (int i = 0; i < 10; i++)
|
|
|
@@ -1353,11 +1357,13 @@ namespace TeamAAS_VP.Core
|
|
|
bool _LastDowmCameraExe = false;
|
|
|
bool _LastScrewTeachExe = false;
|
|
|
bool _LastUpCameraPickExe = false;
|
|
|
+ bool _LastScrewFuJianExe = false;
|
|
|
bool _LastUpCameraPutExe = false;
|
|
|
bool _LastUPCameracheckExe = false;
|
|
|
bool _LastFixedCameraPickExe = false;
|
|
|
bool _LastFixedCameraPutExe = false;
|
|
|
bool _LastFixedCameracheckExe = false;
|
|
|
+ bool _LastFzCameracheckExe = false;
|
|
|
bool _LastThrowExe = false;
|
|
|
bool _LastRunModel = false;
|
|
|
public bool _LastAutoRunning = false;
|
|
|
@@ -1372,6 +1378,7 @@ namespace TeamAAS_VP.Core
|
|
|
Int16 _LastPickINC = 0;
|
|
|
DateTime[] _LastMesCheckTime = new DateTime[10];
|
|
|
Dictionary<string, string> mes_cc = new Dictionary<string, string>();
|
|
|
+ Dictionary<string, double> Point = new Dictionary<string, double>();
|
|
|
string[] ProductMainSN { get; set; } = new string[10];//产品主sn
|
|
|
string[] model_num { get; set; } = new string[10];//产品model_num
|
|
|
string[] wo { get; set; } = new string[10];//产品wo
|
|
|
@@ -1797,6 +1804,90 @@ namespace TeamAAS_VP.Core
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+ //下相机拍照螺丝复检
|
|
|
+ else if (addressConfig.In_Screw_checkExe.Address.Contains(tuple.nodeId))
|
|
|
+ {
|
|
|
+ Point.Clear();
|
|
|
+ if (tuple.value is bool state)
|
|
|
+ {
|
|
|
+ if (_LastScrewFuJianExe != state)
|
|
|
+ {
|
|
|
+ _LastScrewFuJianExe = state;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (state)
|
|
|
+ {
|
|
|
+
|
|
|
+ SendTaskMessage(Lang.触发相机拍照螺丝复检, MessageLevel.Debug);
|
|
|
+ //相机的编号
|
|
|
+ Int16 cameraIndex = plc.ReadNode<Int16>(addressConfig.In_DowmCameraNum.Address);
|
|
|
+ SendTaskMessage(string.Format(Lang.编号0, cameraIndex), MessageLevel.Info);
|
|
|
+
|
|
|
+ // 获取流程
|
|
|
+ var process = _productService.GetCurrentProductProcedureModelById(currentProduct.FixedUpCameraProcedureId);
|
|
|
+ if (process == null)
|
|
|
+ {
|
|
|
+ SendTaskMessage(string.Format(Lang.固定向上相机视觉流程流程ID, currentProduct.FixedUpCameraProcedureId), MessageLevel.Alarm);
|
|
|
+ await plc.WriteNodeAsync(addressConfig.Out_Screw_check_status.Address, (Int16)2);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取机器人当前坐标
|
|
|
+ var robot = _robotService.GetAllRobots().FirstOrDefault();
|
|
|
+ if (robot == null)
|
|
|
+ {
|
|
|
+ SendTaskMessage(Lang.未找到机器人无法执行上相机锁附组装拍照视觉任务, MessageLevel.Alarm);
|
|
|
+ await plc.WriteNodeAsync(addressConfig.Out_Screw_check_status.Address, (Int16)2);
|
|
|
+ return;
|
|
|
+
|
|
|
+ }
|
|
|
+ var currentPosition = robot.GetRobotPos();
|
|
|
+
|
|
|
+ // 执行视觉任务
|
|
|
+ var _cts = new CancellationTokenSource();
|
|
|
+ ImageParameters imgPara = new ImageParameters();
|
|
|
+ imgPara.SNCode = productSn;
|
|
|
+ var visionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint1(process, null, null, _cts.Token, cameraIndex, cameraIndex, null, imgPara);
|
|
|
+ //string X, Y, U;
|
|
|
+ if (visionResult.IsSucceed)
|
|
|
+ {
|
|
|
+ //披头偏差
|
|
|
+ //float offsetX = (float)(visionResult.X - currentPosition.X);
|
|
|
+ //float offsetY = (float)(visionResult.Y - currentPosition.Y);
|
|
|
+ string[] keys = { "X", "Y", "U" };
|
|
|
+ double[] values = { visionResult.X, visionResult.Y, visionResult.U };
|
|
|
+ for (int i = 0; i < keys.Length; i++)
|
|
|
+ {
|
|
|
+ Point.Add(keys[i], values[i]);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 生成CSV文件(替换成你的保存路径)
|
|
|
+ string csvPath = @"D:\视觉检测数据\XYU结果.csv";
|
|
|
+ // 调用生成方法(appendMode=true 每次拍照新增一行,不会覆盖历史数据)
|
|
|
+ ExportDictionaryToCsv(Point, csvPath, appendMode: true);
|
|
|
+ //DowmCameraResults[cameraIndex] = new PointF(offsetX, offsetY);
|
|
|
+ //ExportDictionaryToCsv1(ProductMainSN[1], visionResult.X, visionResult.Y, visionResult.U);
|
|
|
+
|
|
|
+ await plc.WriteNodeAsync(addressConfig.Out_Screw_check_status.Address, (Int16)1);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ await plc.WriteNodeAsync(addressConfig.Out_Screw_check_status.Address, (Int16)2);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ SendTaskMessage(Lang.触发下相机拍照信号已关闭, MessageLevel.Alarm);
|
|
|
+ await plc.WriteNodeAsync(addressConfig.Out_Screw_check_status.Address, (Int16)0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
// 固定相机取料拍照
|
|
|
else if (addressConfig.In_FixedCameraPickExe.Address.Contains(tuple.nodeId))
|
|
|
{
|
|
|
@@ -1885,6 +1976,213 @@ namespace TeamAAS_VP.Core
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+ // 翻转相机检测拍照
|
|
|
+ else if (addressConfig.In_FzCameraPixExe.Address.Contains(tuple.nodeId))
|
|
|
+ {
|
|
|
+ if (tuple.value is bool state)
|
|
|
+ {
|
|
|
+ if (_LastFzCameracheckExe != state)
|
|
|
+ {
|
|
|
+ _LastFzCameracheckExe = state;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (state)
|
|
|
+ {
|
|
|
+ int i = 5;
|
|
|
+ SendTaskMessage("触发翻转相机拍照", MessageLevel.Debug);
|
|
|
+ var code = plc.ReadNode<string>(string.Format(addressConfig.In_Code.Address, 1));
|
|
|
+
|
|
|
+ string resultphoto = "";
|
|
|
+ //这里缺少从MES获取产品配方的内容,需要补充
|
|
|
+
|
|
|
+ _LastMesCheckTime[5] = (await _mesService.GetServerTimeAsync(5, code, 2)).Now;
|
|
|
+ var stationConfig2 = _configService.GetDeviceInfo(0);
|
|
|
+ //LogHelper.WriteLogMes($"【mes开始QUERY】");
|
|
|
+ //SendTaskMessage($"mes开始QUERY", MessageLevel.Info);
|
|
|
+ //if (stationConfig2.EnableMES)
|
|
|
+ //{
|
|
|
+ // (bool isSuccess, string response) = await _mesService.StationGetExAsync(code, "", 2);
|
|
|
+ // if (isSuccess)
|
|
|
+ // {
|
|
|
+ // string ProductMainSN_Temp = "";
|
|
|
+ // LogHelper.WriteLogMes($"询问mes成功");
|
|
|
+ // SendTaskMessage($"询问mes成功:{response}", MessageLevel.Debug);
|
|
|
+ // string[] item = response.Split('\n');
|
|
|
+ // //获取过度件sn
|
|
|
+ // string snItem = item.FirstOrDefault(f => f.Contains("sn="));
|
|
|
+ // if (snItem != null)
|
|
|
+ // {
|
|
|
+ // ProductMainSN_Temp = snItem.Replace("sn=", "").Trim();
|
|
|
+
|
|
|
+ // SendTaskMessage($"过度件sn:{ProductMainSN_Temp}", MessageLevel.Info);
|
|
|
+ // }
|
|
|
+
|
|
|
+ // LogHelper.WriteLogMes($"询问mes成功");
|
|
|
+ // SendTaskMessage($"询问mes成功:{response}", MessageLevel.Debug);
|
|
|
+
|
|
|
+ // //20260214,螺丝机特别版
|
|
|
+ // (bool isSuccess2, string response2) = await _mesService.StationGetAsync(ProductMainSN_Temp, "", 2);//询问mes
|
|
|
+ // if (isSuccess2)
|
|
|
+ // {
|
|
|
+ // LogHelper.WriteLogMes($"询问mes成功");
|
|
|
+ // SendTaskMessage($"询问mes成功:{response2}", MessageLevel.Debug);
|
|
|
+
|
|
|
+ // string[] items = response2.Split('\n');
|
|
|
+ // //获取产品主sn和wo用于后续上传数据使用
|
|
|
+ // string snItem2 = items.FirstOrDefault(f => f.Contains("sn="));
|
|
|
+ // if (snItem2 != null)
|
|
|
+ // {
|
|
|
+ // var codesn = snItem2.Replace("sn=", "").Trim();
|
|
|
+ // //_productService.CurrentProductCode = codesn;
|
|
|
+ // SendTaskMessage($"产品主sn:{codesn}", MessageLevel.Info);
|
|
|
+ // }
|
|
|
+ // string woItem = item.FirstOrDefault(f => f.Contains("wo="));
|
|
|
+ // if (woItem != null)
|
|
|
+ // {
|
|
|
+ // wo[i] = woItem.Replace("wo=", "").Trim();
|
|
|
+ // SendTaskMessage($"工单信息:{wo[i]}", MessageLevel.Info);
|
|
|
+ // }
|
|
|
+ // string modelItem = item.FirstOrDefault(f => f.Contains("model_num="));
|
|
|
+ // if (modelItem != null)
|
|
|
+ // {
|
|
|
+ // model_num[i] = modelItem.Replace("model_num=", "").Trim();
|
|
|
+ // SendTaskMessage($"model_num:{model_num[i]}", MessageLevel.Info);
|
|
|
+ // }
|
|
|
+ // string colorItem = item.FirstOrDefault(f => f.Contains("color="));
|
|
|
+ // if (colorItem != null)
|
|
|
+ // {
|
|
|
+ // color[i] = colorItem.Replace("color=", "").Trim();
|
|
|
+ // SendTaskMessage($"color:{color[i]}", MessageLevel.Info);
|
|
|
+ // }
|
|
|
+ // string ppidItem = item.FirstOrDefault(f => f.Contains("ppid="));
|
|
|
+ // if (ppidItem != null)
|
|
|
+ // {
|
|
|
+ // ppid[5] = ppidItem.Replace("ppid=", "").Trim();
|
|
|
+ // SendTaskMessage($"ppid:{ppid[5]}", MessageLevel.Info);
|
|
|
+ // }
|
|
|
+ // string revisionItem = item.FirstOrDefault(f => f.Contains("stage="));
|
|
|
+ // if (revisionItem != null)
|
|
|
+ // {
|
|
|
+ // revision[5] = revisionItem.Replace("stage=", "").Trim();
|
|
|
+ // SendTaskMessage($"stage:{revision[5]}", MessageLevel.Info);
|
|
|
+ // }
|
|
|
+ // LogHelper.WriteLogMes($"第二次询问mes成功");
|
|
|
+ // SendTaskMessage($"第二次询问mes成功:{response2}", MessageLevel.Debug);
|
|
|
+
|
|
|
+ // }
|
|
|
+ // else
|
|
|
+ // {
|
|
|
+ // LogHelper.WriteLogMes($"第二次询问mes失败");
|
|
|
+ // SendTaskMessage($"第二次询问mes失败:{response2}", MessageLevel.Error);
|
|
|
+ // await plc.WriteNodeAsync(addressConfig.Out_FzCameraPickStatus.Address, (Int16)2);
|
|
|
+ // return;
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // else
|
|
|
+ // {
|
|
|
+ // LogHelper.WriteLogMes($"询问mes失败");
|
|
|
+ // SendTaskMessage($"询问mes失败:{response}", MessageLevel.Error);
|
|
|
+ // await plc.WriteNodeAsync(addressConfig.Out_FzCameraPickStatus.Address, (Int16)2);
|
|
|
+ // return;
|
|
|
+ // }
|
|
|
+ //}
|
|
|
+ //else
|
|
|
+ //{
|
|
|
+ // SendTaskMessage($"mes未启用", MessageLevel.Info);
|
|
|
+ //}
|
|
|
+
|
|
|
+ Guid FzCameraProcedureId = currentProduct.FzCameraProcedureId;
|
|
|
+
|
|
|
+ var FzCameraProcess = _productService.GetCurrentProductProcedureModelById(FzCameraProcedureId);
|
|
|
+ if (FzCameraProcess == null)
|
|
|
+ {
|
|
|
+ SendTaskMessage($"未找到翻转相机视觉流程,流程ID: {FzCameraProcedureId}", MessageLevel.Alarm);
|
|
|
+ await plc.WriteNodeAsync(addressConfig.Out_FzCameraPickStatus.Address, (Int16)2);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ SendTaskMessage($"开始执行翻转相机视觉流程", MessageLevel.Debug);
|
|
|
+ var _cts = new CancellationTokenSource();
|
|
|
+
|
|
|
+ await _remoteCommandService.SetLightBeforePhoto(FzCameraProcess);
|
|
|
+ var FzCameraResult = _remoteCommandService.ExecutePhotoGetDistance(FzCameraProcess, null);
|
|
|
+
|
|
|
+ if (FzCameraResult)
|
|
|
+ {
|
|
|
+ SendTaskMessage("翻转相机拍照成功", MessageLevel.Debug);
|
|
|
+ resultphoto = "Pass";
|
|
|
+ await plc.WriteNodeAsync(addressConfig.Out_FzCameraPickStatus.Address, (Int16)1);
|
|
|
+
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ SendTaskMessage("翻转相机拍照失败", MessageLevel.Alarm);
|
|
|
+ resultphoto = "Fail";
|
|
|
+ await plc.WriteNodeAsync(addressConfig.Out_FzCameraPickStatus.Address, (Int16)2);
|
|
|
+ }
|
|
|
+ if (stationConfig2.SaveCsv)
|
|
|
+ {
|
|
|
+ List<DataFormCtq> DFC = new List<DataFormCtq>();
|
|
|
+ string saveppid = "NA";
|
|
|
+ string names = currentProduct.Name;
|
|
|
+ if (stationConfig2.SaveCsvPPID) saveppid = ppid[i];
|
|
|
+ DateTime servertime = DateTime.Now;
|
|
|
+ // Dictionary<string, double> adjacentDiffDict1 = GetAdjacentDiffDict(keyData1);
|
|
|
+ //判断锁付路径字符串是否为空,如果不为空则保存,否则不保存
|
|
|
+ if (!string.IsNullOrEmpty(stationConfig2.SaveCsvPath))
|
|
|
+ {
|
|
|
+
|
|
|
+ DFC.Add(new DataFormCtq
|
|
|
+ {
|
|
|
+ PPID = saveppid,
|
|
|
+ PROCESS_NAME = stationConfig2.DataInfo.PROCESS_NAME,
|
|
|
+ PROCESS_START_TIME = _LastMesCheckTime[5].ToString("yyyy-MM-ddTHH:mm:ss.fffffff") + "+08:00",
|
|
|
+ CTQ_NAME = "FzCameraPhoto",
|
|
|
+ CTQ_VALUE = 0,
|
|
|
+ CTQ_LSL = 0,
|
|
|
+ CTQ_USL = 0,
|
|
|
+ PROCESS_END_TIME = servertime.ToString("yyyy-MM-ddTHH:mm:ss.fffffff") + "+08:00",
|
|
|
+ SUPPLIER_NAME = stationConfig2.DataInfo.SUPPLIER_NAME,
|
|
|
+ COMMODITY_TYPE = stationConfig2.DataInfo.COMMODITY_TYPE,
|
|
|
+ REVISION = stationConfig2.DataInfo.REVISION + "_" + revision[i],
|
|
|
+ WO = "wo",//
|
|
|
+ MFG_LOT = stationConfig2.DataInfo.MFG_LOT,//
|
|
|
+ MFG_ASSY_LINE = stationConfig2.DataInfo.MFG_ASSY_LINE,
|
|
|
+ PROCESS_OUTCOME = resultphoto,
|
|
|
+ PROCESS_MACHINE_ID = stationConfig2.DataInfo.PROCESS_MACHINE_ID,
|
|
|
+ CTQ_UNIT_OF_MEASURE = "mm",
|
|
|
+ ERROR_MESSAGE = "",
|
|
|
+ PD_ATTR_01 = _productService.CurrentProductCode,//
|
|
|
+ PD_ATTR_02 = "",
|
|
|
+ PD_ATTR_03 = "",
|
|
|
+ PD_ATTR_04 = code,
|
|
|
+ PD_ATTR_05 = "",
|
|
|
+ });
|
|
|
+ bool recordResult = RecordStationResult(0, DFC, _productService.CurrentProductCode, servertime.Subtract(_LastMesCheckTime[5]).TotalSeconds, _LastMesCheckTime[5], stationConfig2.SaveCsvPath);
|
|
|
+ if (recordResult)
|
|
|
+ {
|
|
|
+ SendTaskMessage($"翻转相机拍照产品记录保存成功", MessageLevel.Debug);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ SendTaskMessage($"{stationConfig2.DeviceName}产品记录保存失败", MessageLevel.Error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ SendTaskMessage($"{stationConfig2.DeviceName}工位未配置保存路径,无法保存产品记录", MessageLevel.Error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ SendTaskMessage($"触发翻转相机检测拍照信号已关闭", MessageLevel.Alarm);
|
|
|
+ await plc.WriteNodeAsync(addressConfig.Out_FzCameraPickStatus.Address, (Int16)0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
// 开始锁付
|
|
|
else if (addressConfig.In_WorkStart.Address.Contains(tuple.nodeId))
|
|
|
{
|
|
|
@@ -2130,26 +2428,29 @@ namespace TeamAAS_VP.Core
|
|
|
}
|
|
|
//验证当前锁附点位与设置锁附点位的差值是否超限,超限则报警并停止流程
|
|
|
//目前验证已OK 缺少切换按钮
|
|
|
- //try
|
|
|
- //{
|
|
|
- // var ScrewLimit = currentProduct.GlobalParamListCollection.FirstOrDefault((p) => p.Number == positionIndex - 1);
|
|
|
- // //判断实际偏差与设置的点位差数是否偏差过大
|
|
|
- // float XOffsetPoint = Math.Abs(PositionPoint.X_Position - (TempPoint.X_Position + TempPoint.X_Offset));
|
|
|
- // float YOffsetPoint = Math.Abs(PositionPoint.Y_Position - (TempPoint.Y_Position + TempPoint.Y_Offset));
|
|
|
- // if (!(XOffsetPoint >= float.Parse(ScrewLimit.Param1) && XOffsetPoint <= float.Parse(ScrewLimit.Param2)) ||
|
|
|
- // !(YOffsetPoint >= float.Parse(ScrewLimit.Param3) && YOffsetPoint <= float.Parse(ScrewLimit.Param4)))
|
|
|
- // {
|
|
|
- // SendTaskMessage($"当前锁附点位{positionIndex}与设置锁附点位差值超限,X偏差:{XOffsetPoint},Y偏差{YOffsetPoint}", MessageLevel.Error);
|
|
|
- // await plc.WriteNodeAsync(addressConfig.Out_CameraDone.Address, (Int16)2);
|
|
|
- // return;
|
|
|
- // }
|
|
|
- //}
|
|
|
- //catch (Exception ex)
|
|
|
- //{
|
|
|
- // SendTaskMessage($"当前锁附点位与设置锁附点位差值未设置:" + ex.Message, MessageLevel.Error);
|
|
|
- // await plc.WriteNodeAsync(addressConfig.Out_CameraDone.Address, (Int16)2);
|
|
|
- // return;
|
|
|
- //}
|
|
|
+ if (_configService.GetDeviceInfo().ScrewOverrun)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ var ScrewLimit = currentProduct.GlobalParamListCollection.FirstOrDefault((p) => p.Number == positionIndex - 1);
|
|
|
+ //判断实际偏差与设置的点位差数是否偏差过大
|
|
|
+ float XOffsetPoint = Math.Abs(PositionPoint.X_Position - (TempPoint.X_Position + TempPoint.X_Offset));
|
|
|
+ float YOffsetPoint = Math.Abs(PositionPoint.Y_Position - (TempPoint.Y_Position + TempPoint.Y_Offset));
|
|
|
+ if (!(XOffsetPoint >= float.Parse(ScrewLimit.Param1) && XOffsetPoint <= float.Parse(ScrewLimit.Param2)) ||
|
|
|
+ !(YOffsetPoint >= float.Parse(ScrewLimit.Param3) && YOffsetPoint <= float.Parse(ScrewLimit.Param4)))
|
|
|
+ {
|
|
|
+ SendTaskMessage($"当前锁附点位{positionIndex}与设置锁附点位差值超限,X偏差:{XOffsetPoint},Y偏差{YOffsetPoint}", MessageLevel.Error);
|
|
|
+ await plc.WriteNodeAsync(addressConfig.Out_CameraDone.Address, (Int16)2);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ SendTaskMessage($"当前锁附点位与设置锁附点位差值未设置:" + ex.Message, MessageLevel.Error);
|
|
|
+ await plc.WriteNodeAsync(addressConfig.Out_CameraDone.Address, (Int16)2);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
await PositionPoint.WriteToPlcAddress(addressConfig.Out_Screw, plc, positionIndex);
|
|
|
}
|
|
|
//拍2打所有
|
|
|
@@ -2175,25 +2476,28 @@ namespace TeamAAS_VP.Core
|
|
|
point.X_Position = (float)worldPoint[0];
|
|
|
point.Y_Position = (float)worldPoint[1];
|
|
|
SendTaskMessage($"点:{i},{point.X_Position:F3},{point.Y_Position:F4}", MessageLevel.Info);
|
|
|
- try
|
|
|
+ if (_configService.GetDeviceInfo().ScrewOverrun)
|
|
|
{
|
|
|
- var ScrewLimit = currentProduct.GlobalParamListCollection.FirstOrDefault((p) => p.Number == positionIndex - 1);
|
|
|
- //判断实际偏差与设置的点位差数是否偏差过大
|
|
|
- float XOffsetPoint = Math.Abs(localPoint.X - (float)worldPoint[0]);
|
|
|
- float YOffsetPoint = Math.Abs(localPoint.Y - (float)worldPoint[1]);
|
|
|
- if ((XOffsetPoint >= float.Parse(ScrewLimit.Param1) && XOffsetPoint <= float.Parse(ScrewLimit.Param2)) ||
|
|
|
- (YOffsetPoint >= float.Parse(ScrewLimit.Param3) && YOffsetPoint <= float.Parse(ScrewLimit.Param4)))
|
|
|
+ try
|
|
|
+ {
|
|
|
+ var ScrewLimit = currentProduct.GlobalParamListCollection.FirstOrDefault((p) => p.Number == positionIndex - 1);
|
|
|
+ //判断实际偏差与设置的点位差数是否偏差过大
|
|
|
+ float XOffsetPoint = Math.Abs(localPoint.X - (float)worldPoint[0]);
|
|
|
+ float YOffsetPoint = Math.Abs(localPoint.Y - (float)worldPoint[1]);
|
|
|
+ if ((XOffsetPoint >= float.Parse(ScrewLimit.Param1) && XOffsetPoint <= float.Parse(ScrewLimit.Param2)) ||
|
|
|
+ (YOffsetPoint >= float.Parse(ScrewLimit.Param3) && YOffsetPoint <= float.Parse(ScrewLimit.Param4)))
|
|
|
+ {
|
|
|
+ SendTaskMessage($"当前锁附点位{i}与设置锁附点位差值超限,X偏差:{XOffsetPoint},Y偏差{YOffsetPoint}", MessageLevel.Error);
|
|
|
+ await plc.WriteNodeAsync(addressConfig.Out_CameraDone.Address, (Int16)2);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
{
|
|
|
- SendTaskMessage($"当前锁附点位{i}与设置锁附点位差值超限,X偏差:{XOffsetPoint},Y偏差{YOffsetPoint}", MessageLevel.Error);
|
|
|
+ SendTaskMessage($"当前锁附点位与设置锁附点位差值超限:" + ex.Message, MessageLevel.Error);
|
|
|
await plc.WriteNodeAsync(addressConfig.Out_CameraDone.Address, (Int16)2);
|
|
|
- return;
|
|
|
}
|
|
|
}
|
|
|
- catch (Exception ex)
|
|
|
- {
|
|
|
- SendTaskMessage($"当前锁附点位与设置锁附点位差值超限:" + ex.Message, MessageLevel.Error);
|
|
|
- await plc.WriteNodeAsync(addressConfig.Out_CameraDone.Address, (Int16)2);
|
|
|
- }
|
|
|
await point.WriteToPlcAddress(addressConfig.Out_Screw, plc);
|
|
|
}
|
|
|
await plc.WriteNodeAsync(addressConfig.Out_WorkNum.Address, (Int16)currentProduct.ScrewPoints.Count);
|
|
|
@@ -2485,8 +2789,20 @@ namespace TeamAAS_VP.Core
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
- SendTaskMessage($"二维码扫码成功:{code}", MessageLevel.Info);
|
|
|
- await plc.WriteNodeAsync(addressConfig.Out_QrCodePhotoResault.Address, (Int16)1);
|
|
|
+
|
|
|
+ bool _isSuccess = plc.WriteNode<string>(string.Format(addressConfig.In_Code.Address, 0), code);
|
|
|
+ if (_isSuccess)
|
|
|
+ {
|
|
|
+ SendTaskMessage($"二维码扫码成功:{code}", MessageLevel.Info);
|
|
|
+ await plc.WriteNodeAsync(addressConfig.Out_QrCodePhotoResault.Address, (Int16)1);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ SendTaskMessage($"二维码扫码成功:{code}", MessageLevel.Info);
|
|
|
+ SendTaskMessage($"发送plc二维码失败:{code}", MessageLevel.Error);
|
|
|
+ await plc.WriteNodeAsync(addressConfig.Out_QrCodePhotoResault.Address, (Int16)2);
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
@@ -2511,7 +2827,7 @@ namespace TeamAAS_VP.Core
|
|
|
}
|
|
|
|
|
|
productSn = code;
|
|
|
-
|
|
|
+ SendTaskMessage($"收到plc信号{state}", MessageLevel.Debug);
|
|
|
//询问mes
|
|
|
if (state == 1)
|
|
|
{
|
|
|
@@ -2750,7 +3066,7 @@ namespace TeamAAS_VP.Core
|
|
|
//产品发生改变并且供料器发生了变化时,需要通知PLC进行取料更改
|
|
|
await plc.WriteNodeAsync(addressConfig.Out_ScrewFeederIsChanged.Address, (Int16)1); //不发生改变
|
|
|
await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)1);
|
|
|
-
|
|
|
+ return;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
@@ -2762,10 +3078,14 @@ namespace TeamAAS_VP.Core
|
|
|
if (models)
|
|
|
{
|
|
|
await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)3);
|
|
|
+ SendTaskMessage($"发送plc信号3", MessageLevel.Debug);
|
|
|
+ return;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)2);
|
|
|
+ SendTaskMessage($"发送plc信号2", MessageLevel.Debug);
|
|
|
+ return;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -2779,10 +3099,14 @@ namespace TeamAAS_VP.Core
|
|
|
if (models)
|
|
|
{
|
|
|
await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)3);
|
|
|
+ SendTaskMessage($"发送plc信号3", MessageLevel.Debug);
|
|
|
+ return;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)2);
|
|
|
+ SendTaskMessage($"发送plc信号2", MessageLevel.Debug);
|
|
|
+ return;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -2801,6 +3125,7 @@ namespace TeamAAS_VP.Core
|
|
|
SendTaskMessage($"未启用mes", MessageLevel.Info);
|
|
|
await plc.WriteNodeAsync(addressConfig.Out_ScrewFeederIsChanged.Address, (Int16)1); //不发生改变
|
|
|
await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)1);
|
|
|
+ SendTaskMessage($"发送plc信号2", MessageLevel.Debug);
|
|
|
}
|
|
|
}
|
|
|
// 上传本站数据
|
|
|
@@ -3163,7 +3488,7 @@ namespace TeamAAS_VP.Core
|
|
|
SendTaskMessage($"mes结束ADD", MessageLevel.Info);
|
|
|
}
|
|
|
//kb 螺丝站位询问mes 具体需求跟plc对接
|
|
|
- if (state == 5)
|
|
|
+ else if (state == 5)
|
|
|
{
|
|
|
|
|
|
SendTaskMessage($"收到KB Screw站点{i}过站检查请求(当站是否生产)...", MessageLevel.Debug);
|
|
|
@@ -3313,8 +3638,7 @@ namespace TeamAAS_VP.Core
|
|
|
return;
|
|
|
}
|
|
|
// 后面还有一些判断条件也需跟当前AE对接
|
|
|
-
|
|
|
-
|
|
|
+ await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)2);
|
|
|
}
|
|
|
|
|
|
LogHelper.WriteLogMes($"【mes结束QUERY】");
|
|
|
@@ -3338,6 +3662,7 @@ namespace TeamAAS_VP.Core
|
|
|
{
|
|
|
SendTaskMessage($"{i}过站检查信号:state={state},处理为默认状态", MessageLevel.Alarm);
|
|
|
await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)0);
|
|
|
+ return;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -3871,6 +4196,97 @@ namespace TeamAAS_VP.Core
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
+ #region 拍螺丝数据保存csv
|
|
|
+ /// <summary>
|
|
|
+ /// 通用方法:将存储XYU的字典导出为规范CSV文件
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="dataDict">存储XYU的字典</param>
|
|
|
+ /// <param name="savePath">CSV文件保存路径</param>
|
|
|
+ /// <param name="appendMode">是否追加模式(true=每次运行新增一行,false=覆盖原有文件)</param>
|
|
|
+ /// <param name="decimalPlaces">数值保留的小数位数(默认4位,适配工业视觉精度)</param>
|
|
|
+ static void ExportDictionaryToCsv(Dictionary<string, double> dataDict, string savePath, bool appendMode = false, int decimalPlaces = 4)
|
|
|
+ {
|
|
|
+ // 自动创建目录(避免路径不存在报错)
|
|
|
+ string directory = Path.GetDirectoryName(savePath);
|
|
|
+ if (!Directory.Exists(directory))
|
|
|
+ {
|
|
|
+ Directory.CreateDirectory(directory);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构建CSV内容
|
|
|
+ StringBuilder csvContent = new StringBuilder();
|
|
|
+
|
|
|
+ // 处理表头:仅当文件不存在/非追加模式时,才写入表头
|
|
|
+ if (!appendMode || !File.Exists(savePath))
|
|
|
+ {
|
|
|
+ csvContent.AppendLine(string.Join(",", dataDict.Keys));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理数据行:按指定小数位数格式化数值
|
|
|
+ List<string> formattedValues = new List<string>();
|
|
|
+ foreach (var value in dataDict.Values)
|
|
|
+ {
|
|
|
+ formattedValues.Add(Math.Round(value, decimalPlaces).ToString());
|
|
|
+ }
|
|
|
+ csvContent.AppendLine(string.Join(",", formattedValues));
|
|
|
+
|
|
|
+ // 写入文件:UTF-8带BOM编码,Excel打开无乱码
|
|
|
+ if (appendMode)
|
|
|
+ {
|
|
|
+ // 追加模式:在文件末尾新增内容
|
|
|
+ File.AppendAllText(savePath, csvContent.ToString(), Encoding.UTF8);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // 覆盖模式:新建/替换文件
|
|
|
+ File.WriteAllText(savePath, csvContent.ToString(), Encoding.UTF8);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public bool ExportDictionaryToCsv1(string rfid, double x, double y, double u)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ DateTime dt = DateTime.Now;
|
|
|
+ if (rfid == null || rfid.Count() == 0)
|
|
|
+ {
|
|
|
+ rfid = dt.ToString("MM-dd-mm");
|
|
|
+ }
|
|
|
+ string path = $"D:\\视觉检测数据XYU数据\\{dt.ToString("yyyy-MM")}\\{dt.ToString("yyyy-MM-dd")}\\{rfid}.csv";
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
+ sb.AppendLine($"SN,X,Y,U");
|
|
|
+ sb.AppendLine();
|
|
|
+ sb.AppendLine($"{rfid},{x},{y},{u}");
|
|
|
+ sb.AppendLine();
|
|
|
+ if (!Directory.Exists(Path.GetDirectoryName(path))) //判断文件夹是否
|
|
|
+ {
|
|
|
+ Directory.CreateDirectory(Path.GetDirectoryName(path)); //创建文件夹
|
|
|
+ }
|
|
|
+ if (File.Exists(path))
|
|
|
+ {
|
|
|
+ // 使用 StreamWriter 以追加模式打开文件
|
|
|
+ StreamWriter sw = new StreamWriter(path, true, Encoding.UTF8);
|
|
|
+ sw.WriteLine(sb.ToString().TrimEnd(','));
|
|
|
+ //sw.WriteLine(sb1.ToString().TrimEnd(','));
|
|
|
+ sw.Close();
|
|
|
+ sw.Dispose();
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ StreamWriter sw = new StreamWriter(path, true, Encoding.UTF8);
|
|
|
+ sw.WriteLine(sb.ToString().TrimEnd(','));
|
|
|
+ sw.Close();
|
|
|
+ sw.Dispose();
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ LogHelper.WriteLogError("写入产品记录时出错!", ex);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
#region 产品锁付记录进行存储
|
|
|
/// <summary>
|
|
|
/// 产品锁付记录进行存储
|