|
|
@@ -1267,7 +1267,7 @@ namespace TeamAAS_VP.Core
|
|
|
Int16[] _LastMesCheck = new Int16[10];
|
|
|
Int16 _LastPickINC = 0;
|
|
|
DateTime[] _LastMesCheckTime = new DateTime[10];
|
|
|
- string ProductMainSN = "";//产品主sn
|
|
|
+ string[] ProductMainSN = new string[10];//产品主sn
|
|
|
string wo = "";
|
|
|
/// <summary>
|
|
|
/// PLC命令触发时
|
|
|
@@ -1762,6 +1762,7 @@ namespace TeamAAS_VP.Core
|
|
|
//位置编号
|
|
|
Int16 positionIndex = plc.ReadNode<Int16>(addressConfig.In_ProductNum.Address);
|
|
|
SendTaskMessage(string.Format(Lang.编号0, positionIndex), MessageLevel.Info);
|
|
|
+
|
|
|
//获取当前锁付点
|
|
|
var screwPoint = currentProduct.ScrewPoints.FirstOrDefault(p => p.Number == positionIndex);
|
|
|
//获取当前的机器人点位
|
|
|
@@ -1838,6 +1839,7 @@ namespace TeamAAS_VP.Core
|
|
|
torqueList.Clear();
|
|
|
pressureList.Clear();
|
|
|
turnList.Clear();
|
|
|
+ lockResultsAll.Clear();
|
|
|
}
|
|
|
torqueList.Add($"{lockResult.Number}-{lockResult.LockTorque:F2}");
|
|
|
pressureList.Add($"{lockResult.Number}-{lockResult.Pressure:F2}");
|
|
|
@@ -2199,79 +2201,138 @@ namespace TeamAAS_VP.Core
|
|
|
{
|
|
|
//这里缺少从MES获取产品配方的内容,需要补充
|
|
|
|
|
|
-
|
|
|
_LastMesCheckTime[i] = (await _mesService.GetServerTimeAsync(i, code, 2)).Now;
|
|
|
- LogHelper.WriteLogMes($"【mes开始QUERY】");
|
|
|
- SendTaskMessage($"mes开始QUERY", MessageLevel.Info);
|
|
|
- (bool isSuccess, string response) = await _mesService.StationGetExAsync(i, code, "", 2);//基于电池的SN获取产品SN,询问mes
|
|
|
- if (i == 0)
|
|
|
- {
|
|
|
- SendTaskMessage($"收到当前过站检查请求(当站是否生产)...", MessageLevel.Debug);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- SendTaskMessage($"收到{i}过站检查请求(当站是否生产)...", MessageLevel.Debug);
|
|
|
- }
|
|
|
- if (isSuccess)
|
|
|
+
|
|
|
+ //获取当前工位的配置
|
|
|
+ var stationConfig = _configService.GetDeviceInfo(i);
|
|
|
+ if (stationConfig.EnableDoubleMes)
|
|
|
{
|
|
|
- //产品发生改变并且供料器发生了变化时,需要通知PLC进行取料更改
|
|
|
- await plc.WriteNodeAsync(addressConfig.Out_ScrewFeederIsChanged.Address, (Int16)1); //不发生改变
|
|
|
- await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)1);
|
|
|
+ SendTaskMessage($"收到{i}:{stationConfig.DeviceName}过站检查请求(当站是否生产)(当前需要双MES验证)...", MessageLevel.Debug);
|
|
|
|
|
|
- if (response != "MES功能未启用!")
|
|
|
+ LogHelper.WriteLogMes($"【mes开始QUERY】");
|
|
|
+ SendTaskMessage($"mes开始QUERY", MessageLevel.Info);
|
|
|
+ (bool isSuccess, string response) = await _mesService.StationGetExAsync(i, code, "", 2);//基于电池的SN获取产品SN,询问mes
|
|
|
+ if (isSuccess)
|
|
|
{
|
|
|
- string[] item = response.Split('\n');
|
|
|
- if (item[3].Contains("sn="))
|
|
|
- {
|
|
|
- ProductMainSN = item[3].Replace("sn=", "");
|
|
|
- SendTaskMessage($"产品主sn:{ProductMainSN}", MessageLevel.Info);
|
|
|
- }
|
|
|
- if (item[5].Contains("wo="))
|
|
|
+ LogHelper.WriteLogMes($"询问mes成功");
|
|
|
+ SendTaskMessage($"询问mes成功:{response}", MessageLevel.Debug);
|
|
|
+ string ProductMainSN_Temp = "";
|
|
|
+ if (response != "MES功能未启用!")
|
|
|
{
|
|
|
- wo = item[5].Replace("wo=", "");
|
|
|
- SendTaskMessage($"产品主wo:{wo}", MessageLevel.Info);
|
|
|
+ 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);
|
|
|
- if (response != "MES功能未启用!")
|
|
|
- {
|
|
|
- string[] item = response.Split('\n');
|
|
|
- if (item[3].Contains("sn="))
|
|
|
+ (bool isSuccess2, string response2) = await _mesService.StationGetAsync(i, ProductMainSN_Temp, "", 2);//询问mes
|
|
|
+ if (isSuccess2)
|
|
|
{
|
|
|
- ProductMainSN = item[3].Replace("sn=", "");
|
|
|
- SendTaskMessage($"产品主sn:{ProductMainSN}", MessageLevel.Info);
|
|
|
+ LogHelper.WriteLogMes($"第二次询问mes成功");
|
|
|
+ SendTaskMessage($"第二次询问mes成功:{response2}", MessageLevel.Debug);
|
|
|
+ if (response2 != "MES功能未启用!")
|
|
|
+ {
|
|
|
+ string[] item = response2.Split('\n');
|
|
|
+ //获取产品主sn和wo用于后续上传数据使用
|
|
|
+ string snItem = item.FirstOrDefault(f => f.Contains("sn="));
|
|
|
+ string woItem = item.FirstOrDefault(f => f.Contains("wo="));
|
|
|
+ if (snItem != null)
|
|
|
+ {
|
|
|
+ ProductMainSN[i] = snItem.Replace("sn=", "").Trim();
|
|
|
+ SendTaskMessage($"产品主sn:{ProductMainSN[i]}", MessageLevel.Info);
|
|
|
+ }
|
|
|
+ if (woItem != null)
|
|
|
+ {
|
|
|
+ wo = woItem.Replace("wo=", "").Trim();
|
|
|
+ SendTaskMessage($"产品主wo:{wo}", MessageLevel.Info);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //产品发生改变并且供料器发生了变化时,需要通知PLC进行取料更改
|
|
|
+ await plc.WriteNodeAsync(addressConfig.Out_ScrewFeederIsChanged.Address, (Int16)1); //不发生改变
|
|
|
+ await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)1);
|
|
|
}
|
|
|
- if (item[5].Contains("wo="))
|
|
|
+ else
|
|
|
{
|
|
|
- wo = item[5].Replace("wo=", "");
|
|
|
- SendTaskMessage($"产品主wo:{wo}", MessageLevel.Info);
|
|
|
+ LogHelper.WriteLogMes($"第二次询问mes失败");
|
|
|
+ SendTaskMessage($"第二次询问mes失败:{response2}", MessageLevel.Error);
|
|
|
+
|
|
|
+ //产品发生改变并且供料器发生了变化时,需要通知PLC进行取料更改
|
|
|
+ await plc.WriteNodeAsync(addressConfig.Out_ScrewFeederIsChanged.Address, (Int16)1); //不发生改变
|
|
|
+ await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)2);
|
|
|
}
|
|
|
}
|
|
|
- LogHelper.WriteLogMes($"询问mes成功");
|
|
|
- SendTaskMessage($"询问mes成功:{response}", MessageLevel.Debug);
|
|
|
+ else
|
|
|
+ {
|
|
|
+ //产品发生改变并且供料器发生了变化时,需要通知PLC进行取料更改
|
|
|
+ await plc.WriteNodeAsync(addressConfig.Out_ScrewFeederIsChanged.Address, (Int16)1); //不发生改变
|
|
|
+ await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)2);
|
|
|
+
|
|
|
+ LogHelper.WriteLogMes($"询问mes失败");
|
|
|
+ SendTaskMessage($"询问mes失败:{response}", MessageLevel.Error);
|
|
|
+
|
|
|
+ //产品发生改变并且供料器发生了变化时,需要通知PLC进行取料更改
|
|
|
+ await plc.WriteNodeAsync(addressConfig.Out_ScrewFeederIsChanged.Address, (Int16)1); //不发生改变
|
|
|
+ await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)2);
|
|
|
+ }
|
|
|
+ LogHelper.WriteLogMes($"【mes结束QUERY】");
|
|
|
+ SendTaskMessage($"mes结束QUERY", MessageLevel.Info);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- //产品发生改变并且供料器发生了变化时,需要通知PLC进行取料更改
|
|
|
- await plc.WriteNodeAsync(addressConfig.Out_ScrewFeederIsChanged.Address, (Int16)1); //不发生改变
|
|
|
- await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)2);
|
|
|
+ SendTaskMessage($"收到{i}:{stationConfig.DeviceName}过站检查请求(当站是否生产)(当前不需要双MES验证)...", MessageLevel.Debug);
|
|
|
|
|
|
- LogHelper.WriteLogMes($"询问mes失败");
|
|
|
- SendTaskMessage($"询问mes失败:{response}", MessageLevel.Error);
|
|
|
+ LogHelper.WriteLogMes($"【mes开始QUERY】");
|
|
|
+ SendTaskMessage($"mes开始QUERY", MessageLevel.Info);
|
|
|
+ (bool isSuccess, string response) = await _mesService.StationGetAsync(i, code, "", 2);//询问mes
|
|
|
+ if (isSuccess)
|
|
|
+ {
|
|
|
+ if (response != "MES功能未启用!")
|
|
|
+ {
|
|
|
+ string[] item = response.Split('\n');
|
|
|
+ //获取产品主sn和wo用于后续上传数据使用
|
|
|
+ string snItem = item.FirstOrDefault(f => f.Contains("sn="));
|
|
|
+ string woItem = item.FirstOrDefault(f => f.Contains("wo="));
|
|
|
+ if (snItem != null)
|
|
|
+ {
|
|
|
+ ProductMainSN[i] = snItem.Replace("sn=", "").Trim();
|
|
|
+ SendTaskMessage($"产品主sn:{ProductMainSN[i]}", MessageLevel.Info);
|
|
|
+ }
|
|
|
+ if (woItem != null)
|
|
|
+ {
|
|
|
+ wo = woItem.Replace("wo=", "").Trim();
|
|
|
+ SendTaskMessage($"产品主wo:{wo}", MessageLevel.Info);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- //产品发生改变并且供料器发生了变化时,需要通知PLC进行取料更改
|
|
|
- await plc.WriteNodeAsync(addressConfig.Out_ScrewFeederIsChanged.Address, (Int16)1); //不发生改变
|
|
|
- await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)2);
|
|
|
+ LogHelper.WriteLogMes($"询问mes成功");
|
|
|
+ SendTaskMessage($"询问mes成功:{response}", MessageLevel.Debug);
|
|
|
+ //产品发生改变并且供料器发生了变化时,需要通知PLC进行取料更改
|
|
|
+ await plc.WriteNodeAsync(addressConfig.Out_ScrewFeederIsChanged.Address, (Int16)1); //不发生改变
|
|
|
+ await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)1);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ LogHelper.WriteLogMes($"询问mes失败");
|
|
|
+ SendTaskMessage($"询问mes失败:{response}", MessageLevel.Error);
|
|
|
+ //产品发生改变并且供料器发生了变化时,需要通知PLC进行取料更改
|
|
|
+ await plc.WriteNodeAsync(addressConfig.Out_ScrewFeederIsChanged.Address, (Int16)1); //不发生改变
|
|
|
+ await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)2);
|
|
|
+ }
|
|
|
+ LogHelper.WriteLogMes($"【mes结束QUERY】");
|
|
|
+ SendTaskMessage($"mes结束QUERY", MessageLevel.Info);
|
|
|
}
|
|
|
- LogHelper.WriteLogMes($"【mes结束QUERY】");
|
|
|
- SendTaskMessage($"mes结束QUERY", MessageLevel.Info);
|
|
|
}
|
|
|
// 上传本站数据
|
|
|
else if (state == 2)
|
|
|
{
|
|
|
- SendTaskMessage($"收到{i}上传本站数据请求...", MessageLevel.Debug);
|
|
|
+ //获取当前工位的配置
|
|
|
+ var stationConfig = _configService.GetDeviceInfo(i);
|
|
|
+ SendTaskMessage($"收到{i}:{stationConfig.DeviceName}上传本站数据请求...", MessageLevel.Debug);
|
|
|
//从服务器中获取当前时间
|
|
|
var serverTimeResult = await _mesService.GetServerTimeAsync(i, code, 2);
|
|
|
|
|
|
@@ -2290,12 +2351,12 @@ namespace TeamAAS_VP.Core
|
|
|
await _systemDatabaseService.RecordProductionAsync(new ProductionRecord()
|
|
|
{
|
|
|
ProductName = currentProduct.Name,
|
|
|
- ProductCode = ProductMainSN,
|
|
|
+ ProductCode = ProductMainSN[i],
|
|
|
DeviceId = i,
|
|
|
DeviceName = "",
|
|
|
Category = resultIndex == 1 ? "OK" : "NG",
|
|
|
Quantity = 1,
|
|
|
- Remark = $"TotalSeconds:{DateTime.UtcNow.Subtract(_LastMesCheckTime[i]).TotalSeconds.ToString("F2")}",
|
|
|
+ Remark = $"TotalSeconds:{serverTimeResult.Now.Subtract(_LastMesCheckTime[i]).TotalSeconds.ToString("F2")}",
|
|
|
});
|
|
|
|
|
|
LogHelper.WriteLogMes($"【mes开始ADD】");
|
|
|
@@ -2304,7 +2365,8 @@ namespace TeamAAS_VP.Core
|
|
|
string torque = string.Join(",", torqueList);
|
|
|
string pressure = string.Join(",", pressureList);
|
|
|
string turn = string.Join(",", turnList);
|
|
|
- (bool isSuccess, string response) = await _mesService.SubmitGetAsync(i, ProductMainSN, "", torque, pressure, turn, resultIndex == 1 ? true : false, _LastMesCheckTime[i], serverTimeResult.Now);
|
|
|
+ //这里现在上传的结果都是锁付站的,如果存在其他附属站的数据需要上传时,将不适用,要根据实际情况进行调整
|
|
|
+ (bool isSuccess, string response) = await _mesService.SubmitGetAsync(i, ProductMainSN[i], "", torque, pressure, turn, resultIndex == 1 ? true : false, _LastMesCheckTime[i], serverTimeResult.Now);
|
|
|
if (isSuccess)
|
|
|
{
|
|
|
LogHelper.WriteLogMes($"上传mes成功");
|
|
|
@@ -2317,7 +2379,44 @@ namespace TeamAAS_VP.Core
|
|
|
}
|
|
|
await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)3);
|
|
|
|
|
|
- WriteProductLog(lockResultsAll, ProductMainSN, CTtime);
|
|
|
+ //是否保存当前的产品记录至CSV?
|
|
|
+ if (stationConfig.SaveCsv)
|
|
|
+ {
|
|
|
+ //判断锁付路径字符串是否为空,如果不为空则保存,否则不保存
|
|
|
+ if (!string.IsNullOrEmpty(stationConfig.SaveCsvPath))
|
|
|
+ {
|
|
|
+ bool recordResult = false;
|
|
|
+ if (i == 0)
|
|
|
+ {
|
|
|
+ recordResult = RecordLockResult(i, lockResultsAll, ProductMainSN[i], serverTimeResult.Now.Subtract(_LastMesCheckTime[i]).TotalSeconds, _LastMesCheckTime[i], stationConfig.SaveCsvPath);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Dictionary<string,string> dataItems = new Dictionary<string, string>();
|
|
|
+ //结果
|
|
|
+ dataItems.Add("Result", resultIndex == 1 ? "OK" : "NG");
|
|
|
+ //压力值
|
|
|
+ //dataItems.Add("Pressure", pressure);
|
|
|
+ recordResult = RecordOtherStationResult(i, dataItems, ProductMainSN[i], serverTimeResult.Now.Subtract(_LastMesCheckTime[i]).TotalSeconds, _LastMesCheckTime[i], stationConfig.SaveCsvPath);
|
|
|
+ }
|
|
|
+ if (recordResult)
|
|
|
+ {
|
|
|
+ SendTaskMessage($"{i}:{stationConfig.DeviceName}产品记录保存成功", MessageLevel.Debug);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ SendTaskMessage($"{i}:{stationConfig.DeviceName}产品记录保存失败", MessageLevel.Error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ SendTaskMessage($"{i}:{stationConfig.DeviceName}工位未配置保存路径,无法保存产品记录", MessageLevel.Error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ SendTaskMessage($"{i}:{stationConfig.DeviceName}工位未配置保存产品记录", MessageLevel.Debug);
|
|
|
+ }
|
|
|
|
|
|
LogHelper.WriteLogMes($"【mes结束ADD】");
|
|
|
SendTaskMessage($"mes结束ADD", MessageLevel.Info);
|
|
|
@@ -2621,6 +2720,207 @@ namespace TeamAAS_VP.Core
|
|
|
|
|
|
lockResultsAll.Clear();
|
|
|
}
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 记录当前工位的锁付结果
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="stationIndex"></param>
|
|
|
+ /// <param name="lockResults"></param>
|
|
|
+ /// <param name="productMainSN"></param>
|
|
|
+ /// <param name="ct"></param>
|
|
|
+ /// <param name="timestamp"></param>
|
|
|
+ /// <param name="savePath"></param>
|
|
|
+ /// <param name="isSingleLine">是否将所有螺丝的锁付结果一行显示,还是每颗螺丝单独一行显示,默认所有颗螺丝单独一行显示</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ private bool RecordLockResult(int stationIndex, List<LockResult> lockResults, string productMainSN, double ct, DateTime timestamp, string savePath, bool isSingleLine = true, bool isFirstEnter = true)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ //获取当前工位的配置
|
|
|
+ var stationConfig = _configService.GetDeviceInfo(stationIndex);
|
|
|
+ if (stationConfig == null) return false;
|
|
|
+ //如果保存路径为空,则不保存
|
|
|
+ if (string.IsNullOrEmpty(savePath)) return false;
|
|
|
+ //如果锁付结果列表为空,则不保存
|
|
|
+ if (lockResults == null || lockResults.Count == 0) return false;
|
|
|
+ string fullPath = savePath;
|
|
|
+ //如果保存路径是一个文件路径,则直接保存,否则按照工位和日期进行保存
|
|
|
+ if (File.Exists(savePath) || Path.HasExtension(savePath))
|
|
|
+ {
|
|
|
+ fullPath = savePath;
|
|
|
+ //如果路径不存在,则创建
|
|
|
+ // 创建目录
|
|
|
+ string directory = Path.GetDirectoryName(fullPath);
|
|
|
+ if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
|
|
|
+ {
|
|
|
+ Directory.CreateDirectory(directory);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ //锁付结果保存至CSV文件,文件名格式:savePath\yyyy-MM\工位编号_工位名称_yyyy-MM-dd.csv
|
|
|
+ string datePath = timestamp.ToString("yyyy-MM") + "\\";
|
|
|
+ string dirPath = Path.Combine(savePath, datePath);
|
|
|
+ if (!Directory.Exists(dirPath)) Directory.CreateDirectory(dirPath);
|
|
|
+ string fileName = $"{stationIndex}_{stationConfig.DeviceName}_{timestamp.ToString("yyyy-MM-dd")}.csv";
|
|
|
+ fullPath = Path.Combine(dirPath, fileName);
|
|
|
+ }
|
|
|
+
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
+ if (!File.Exists(fullPath))
|
|
|
+ {
|
|
|
+ if (isSingleLine)
|
|
|
+ {
|
|
|
+ //将所有螺丝的锁付结果一行显示,列名格式:时间,产品主SN,CT,工位编号,工位名称,配方名称,配方编号,螺丝编号1,锁付结果1,锁付圈数1,锁付扭矩1,锁付时长1,电批程序编号1,结果详情1,压力值1,扭矩上限1,扭矩下限1,圈数上限1,圈数下限1,电批锁付速度1,锁附X1,锁附Y1,开始位置Z1,结束位置Z1,锁附下降速度1,螺丝供料器编号,...(依次类推直到螺丝编号n)
|
|
|
+ sb.Append("时间,产品主SN,CT,工位编号,工位名称,配方名称,配方编号,");
|
|
|
+ for (int i = 0; i < lockResults.Count; i++)
|
|
|
+ {
|
|
|
+ sb.Append($"螺丝编号{i + 1},锁付结果{i + 1},锁付圈数{i + 1},锁付扭矩{i + 1},锁付时长{i + 1},电批程序编号{i + 1},结果详情{i + 1},压力值{i + 1}," +
|
|
|
+ $"扭矩上限{i + 1},扭矩下限{i + 1},圈数上限{i + 1},圈数下限{i + 1},电批锁付速度{i + 1},锁附X{i + 1},锁附Y{i + 1},开始位置Z{i + 1},结束位置Z{i + 1},锁附下降速度{i + 1},螺丝供料器编号{i + 1},");
|
|
|
+ }
|
|
|
+ sb.Append("吸嘴编号,披头编号,操作员姓名");
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ sb.Append("时间,产品主SN,CT,工位编号,工位名称,配方名称,配方编号,螺丝编号,锁付结果,锁付圈数,锁付扭矩,锁付时长,电批程序编号,结果详情,压力值," +
|
|
|
+ "扭矩上限,扭矩下限,圈数上限,圈数下限,电批锁付速度,锁附X,锁附Y,开始位置Z,结束位置Z,锁附下降速度,螺丝供料器编号,吸嘴编号,披头编号,操作员姓名");
|
|
|
+ }
|
|
|
+ sb.AppendLine();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (isSingleLine)
|
|
|
+ {
|
|
|
+ //将所有螺丝的锁付结果一行显示,列名格式:时间,产品主SN,CT,工位编号,工位名称,配方名称,配方编号,螺丝编号1,锁付结果1,锁付圈数1,锁付扭矩1,锁付时长1,电批程序编号1,结果详情1,压力值1,扭矩上限1,扭矩下限1,圈数上限1,圈数下限1,电批锁付速度1,锁附X1,锁附Y1,开始位置Z1,结束位置Z1,锁附下降速度1,螺丝供料器编号,...(依次类推直到螺丝编号n)
|
|
|
+ sb.Append($"{timestamp:yyyy-MM-dd HH:mm:ss},{productMainSN},{Math.Round(ct, 3)},{stationIndex},{stationConfig.DeviceName},{lockResults[0].ProductName},{lockResults[0].ProductNumber},");
|
|
|
+ for (int i = 0; i < lockResults.Count; i++)
|
|
|
+ {
|
|
|
+ var item = lockResults[i];
|
|
|
+ sb.Append($"螺丝{i + 1},{item.LockPassed},{item.LockTurns},{item.LockTorque},{item.LockDuration},{item.ScrewdriverProgramNumber}," +
|
|
|
+ $"{item.ResultDetails},{item.Pressure},{item.TargetTorqueUpperLimit},{item.TargetTorqueLowerLimit},{item.TargetTurnsUpperLimit},{item.TargetTurnsLowerLimit},{item.TargetLockSpeed}," +
|
|
|
+ $"{item.PositionX},{item.PositionY},{item.StartPositionZ},{item.EndPositionZ},{item.LockDescentSpeed},{item.FeederNumber},");
|
|
|
+ }
|
|
|
+ sb.Append($"{lockResults[lockResults.Count - 1].NozzleNumber},{lockResults[lockResults.Count - 1].HeadNumber},{lockResults[lockResults.Count - 1].OperatorName}");
|
|
|
+ sb.AppendLine();
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ foreach (var item in lockResults)
|
|
|
+ {
|
|
|
+ sb.Append($"{timestamp:yyyy-MM-dd HH:mm:ss},{productMainSN},{Math.Round(ct, 3)},{stationIndex},{stationConfig.DeviceName},{item.ProductName},{item.ProductNumber},{item.Number},{item.LockPassed},{item.LockTurns},{item.LockTorque},{item.LockDuration},{item.ScrewdriverProgramNumber}," +
|
|
|
+ $"{item.ResultDetails},{item.Pressure},{item.TargetTorqueUpperLimit},{item.TargetTorqueLowerLimit},{item.TargetTurnsUpperLimit},{item.TargetTurnsLowerLimit},{item.TargetLockSpeed}," +
|
|
|
+ $"{item.PositionX},{item.PositionY},{item.StartPositionZ},{item.EndPositionZ},{item.LockDescentSpeed},{item.FeederNumber},{item.NozzleNumber},{item.HeadNumber},");
|
|
|
+ sb.AppendLine();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // 使用 StreamWriter 以追加模式打开文件
|
|
|
+ StreamWriter sw = new StreamWriter(fullPath, true, Encoding.UTF8);
|
|
|
+ sw.Write(sb.ToString());
|
|
|
+ sw.Close();
|
|
|
+ sw.Dispose();
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ if (!isFirstEnter)
|
|
|
+ return false;
|
|
|
+ LogHelper.WriteLogError("记录锁付结果时出错!", ex);
|
|
|
+
|
|
|
+ //我希望在这里生成一个临时文件来保存这次的记录,因为如果本地文件被打开时可能会导致无法写入,如果不保存的话可能会丢失这次的记录,所以我想在这里生成一个临时文件来保存这次的记录
|
|
|
+ //生成临时文件的路径,格式为savePath\yyyy-MM\工位编号_yyyy-MM-dd_temp\工位编号_yyyy-MM-dd_HH-mm-ss-fff_temp.csv
|
|
|
+ string datePath = timestamp.ToString("yyyy-MM") + "\\";
|
|
|
+ string tempDirPath = Path.Combine(savePath, datePath, $"{stationIndex}_{timestamp.ToString("yyyy-MM-dd")}_temp");
|
|
|
+ string tempFileName = $"{stationIndex}_{timestamp.ToString("yyyy-MM-dd_HH-mm-ss-fff")}_temp.csv";
|
|
|
+ RecordLockResult(stationIndex, lockResults, productMainSN, ct, timestamp, tempFileName, isSingleLine, false);
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 记录其他工位的结果,其他工位要存储的数据项按照键值对集合的形式传入,键为数据项名称,值为数据项的值
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="stationIndex"></param>
|
|
|
+ /// <param name="dataItems"></param>
|
|
|
+ /// <param name="productMainSN"></param>
|
|
|
+ /// <param name="ct"></param>
|
|
|
+ /// <param name="timestamp"></param>
|
|
|
+ /// <param name="savePath"></param>
|
|
|
+ /// <param name="isFirstEnter"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ private bool RecordOtherStationResult(int stationIndex, Dictionary<string, string> dataItems, string productMainSN, double ct, DateTime timestamp, string savePath, bool isFirstEnter = true)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ //获取当前工位的配置
|
|
|
+ var stationConfig = _configService.GetDeviceInfo(stationIndex);
|
|
|
+ if (stationConfig == null) return false;
|
|
|
+ //如果保存路径为空,则不保存
|
|
|
+ if (string.IsNullOrEmpty(savePath)) return false;
|
|
|
+ string fullPath = savePath;
|
|
|
+ //如果保存路径是一个文件路径,则直接保存,否则按照工位和日期进行保存
|
|
|
+ if (File.Exists(savePath) || Path.HasExtension(savePath))
|
|
|
+ {
|
|
|
+ fullPath = savePath;
|
|
|
+ //如果路径不存在,则创建
|
|
|
+ // 创建目录
|
|
|
+ string directory = Path.GetDirectoryName(fullPath);
|
|
|
+ if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
|
|
|
+ {
|
|
|
+ Directory.CreateDirectory(directory);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ //结果保存至CSV文件,文件名格式:savePath\yyyy-MM\工位编号_工位名称_yyyy-MM-dd.csv
|
|
|
+ string datePath = timestamp.ToString("yyyy-MM") + "\\";
|
|
|
+ string dirPath = Path.Combine(savePath, datePath);
|
|
|
+ if (!Directory.Exists(dirPath)) Directory.CreateDirectory(dirPath);
|
|
|
+ string fileName = $"{stationIndex}_{stationConfig.DeviceName}_{timestamp.ToString("yyyy-MM-dd")}.csv";
|
|
|
+ fullPath = Path.Combine(dirPath, fileName);
|
|
|
+ }
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
+ if (!File.Exists(fullPath))
|
|
|
+ {
|
|
|
+ sb.Append("时间,产品主SN,CT,工位编号,工位名称,配方名称,配方编号,");
|
|
|
+ foreach (var item in dataItems)
|
|
|
+ {
|
|
|
+ sb.Append($"{item.Key},");
|
|
|
+ }
|
|
|
+ sb.AppendLine();
|
|
|
+ }
|
|
|
+ sb.Append($"{timestamp:yyyy-MM-dd HH:mm:ss},{productMainSN},{Math.Round(ct, 3)},{stationIndex},{stationConfig.DeviceName},,,,");
|
|
|
+ foreach (var item in dataItems)
|
|
|
+ {
|
|
|
+ sb.Append($"{item.Value},");
|
|
|
+ }
|
|
|
+ sb.AppendLine();
|
|
|
+ // 使用 StreamWriter 以追加模式打开文件
|
|
|
+ StreamWriter sw = new StreamWriter(fullPath, true, Encoding.UTF8);
|
|
|
+ sw.Write(sb.ToString());
|
|
|
+ sw.Close();
|
|
|
+ sw.Dispose();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ if (!isFirstEnter)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ LogHelper.WriteLogError("记录其他工位结果时出错!", ex);
|
|
|
+ //我希望在这里生成一个临时文件来保存这次的记录,因为如果本地文件被打开时可能会导致无法写入,如果不保存的话可能会丢失这次的记录,所以我想在这里生成一个临时文件来保存这次的记录
|
|
|
+ //生成临时文件的路径,格式为savePath\yyyy-MM\工位编号_yyyy-MM-dd_temp\工位编号_yyyy-MM-dd_HH-mm-ss-fff_temp.csv
|
|
|
+ string datePath = timestamp.ToString("yyyy-MM") + "\\";
|
|
|
+ string tempDirPath = Path.Combine(savePath, datePath, $"{stationIndex}_{timestamp.ToString("yyyy-MM-dd")}_temp");
|
|
|
+ string tempFileName = $"{stationIndex}_{timestamp.ToString("yyyy-MM-dd_HH-mm-ss-fff")}_temp.csv";
|
|
|
+ RecordOtherStationResult(stationIndex, dataItems, productMainSN, ct, timestamp, tempFileName, false);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
#endregion
|
|
|
|
|
|
#endregion
|