Parcourir la source

优化MES过站检查及数据上传流程,增强记录功能

本次更新包括:
- 产品主SN变量改为数组,支持多工位SN记录
- 完善MES双验证逻辑,支持过渡件SN查询
- 细化MES结果处理,丰富日志与PLC状态反馈
- 新增锁付及其他工位结果CSV保存方法,支持临时文件防止数据丢失
- 上传MES及生产记录时按工位使用SN数组
- CSV保存路径和内容可灵活配置,支持多种记录格式
- 优化日志和消息提示,提升调试与运维便利性
徐孝锋 il y a 6 mois
Parent
commit
d75c6d72e0
1 fichiers modifiés avec 356 ajouts et 56 suppressions
  1. 356 56
      TeamAAS-VM/Core/Management.cs

+ 356 - 56
TeamAAS-VM/Core/Management.cs

@@ -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