PLC数采
This commit is contained in:
parent
da16fed4dc
commit
2c8e09d794
@ -12,6 +12,7 @@ using S7.Net;
|
|||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
using SqlSugar.IOC;
|
using SqlSugar.IOC;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -41,11 +42,6 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
// 先在类中添加2个核心优化字段(支撑高频访问)
|
// 先在类中添加2个核心优化字段(支撑高频访问)
|
||||||
private readonly SemaphoreSlim _concurrencySemaphore = new SemaphoreSlim(15, 50); // 限制20并发(适配50台PLC)
|
private readonly SemaphoreSlim _concurrencySemaphore = new SemaphoreSlim(15, 50); // 限制20并发(适配50台PLC)
|
||||||
private readonly ConcurrentDictionary<string, (Plc Client, DateTime LastUsedTime)> _plcConnPool = new(); // 连接池
|
private readonly ConcurrentDictionary<string, (Plc Client, DateTime LastUsedTime)> _plcConnPool = new(); // 连接池
|
||||||
private readonly SqlSugarClient Context;
|
|
||||||
public PlcService()
|
|
||||||
{
|
|
||||||
Context = DbScoped.SugarScope.CopyNew();
|
|
||||||
}
|
|
||||||
#region PLC地址块儿映射
|
#region PLC地址块儿映射
|
||||||
//MES返回PLC请求映射
|
//MES返回PLC请求映射
|
||||||
private readonly Dictionary<string, string> _mesIntReturnMap = new()
|
private readonly Dictionary<string, string> _mesIntReturnMap = new()
|
||||||
@ -615,36 +611,36 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
// OP085 专属地址映射(自动上料到波峰焊工位,DB1001)
|
// OP085 专属地址映射(自动上料到波峰焊工位,DB1001)
|
||||||
private readonly Dictionary<string, (string Addr, int Len)> _op085StringMap = new()
|
private readonly Dictionary<string, (string Addr, int Len)> _op085StringMap = new()
|
||||||
{
|
{
|
||||||
{ "报警信息", ("DB1001.DBB58", 48) }, // Array[1..48] of Byte
|
{ "报警信息", ("DB1030.DBB58", 48) }, // Array[1..48] of Byte
|
||||||
{ "产品型号", ("DB1001.DBB1000", 48) }, // String[48]
|
{ "产品型号", ("DB1030.DBB1000", 48) }, // String[48]
|
||||||
{ "产品名称", ("DB1001.DBB1054", 48) }, // String[48]
|
{ "产品名称", ("DB1030.DBB1054", 48) }, // String[48]
|
||||||
{ "波峰焊托盘条码", ("DB1001.DBB2070", 40) }, // String[40]
|
{ "波峰焊托盘条码", ("DB1030.DBB2070", 40) }, // String[40]
|
||||||
{ "穴位1产品SN", ("DB1001.DBB2486", 40) }, // String[40]
|
{ "穴位1产品SN", ("DB1030.DBB2486", 40) }, // String[40]
|
||||||
{ "穴位2产品SN", ("DB1001.DBB2528", 40) }, // String[40]
|
{ "穴位2产品SN", ("DB1030.DBB2528", 40) }, // String[40]
|
||||||
{ "穴位3产品SN", ("DB1001.DBB2570", 40) }, // String[40]
|
{ "穴位3产品SN", ("DB1030.DBB2570", 40) }, // String[40]
|
||||||
{ "穴位4产品SN", ("DB1001.DBB2612", 40) } // String[40]
|
{ "穴位4产品SN", ("DB1030.DBB2612", 40) } // String[40]
|
||||||
};
|
};
|
||||||
|
|
||||||
private readonly Dictionary<string, string> _op085IntMap = new()
|
private readonly Dictionary<string, string> _op085IntMap = new()
|
||||||
{
|
{
|
||||||
// 基础状态
|
// 基础状态
|
||||||
{ "运行状态", "DB1001.DBW0" }, // Int - 1=空闲,2=运行中,3=故障
|
{ "运行状态", "DB1030.DBW0" }, // Int - 1=空闲,2=运行中,3=故障
|
||||||
{ "设备模式", "DB1001.DBW2" }, // Int - 1=空模式;2=手动;4=初始化;8=自动;16=CycleStop
|
{ "设备模式", "DB1030.DBW2" }, // Int - 1=空模式;2=手动;4=初始化;8=自动;16=CycleStop
|
||||||
{ "设备在线状态", "DB1001.DBW4" }, // Int - 1=离线,0=在线
|
{ "设备在线状态", "DB1030.DBW4" }, // Int - 1=离线,0=在线
|
||||||
{ "ByPass", "DB1001.DBW6" }, // Int - 1=ByPass,0=正常模式
|
{ "ByPass", "DB1030.DBW6" }, // Int - 1=ByPass,0=正常模式
|
||||||
{ "生产模式", "DB1001.DBW8" }, // Int - 1=点检,2=返工,4=样件,5=正常
|
{ "生产模式", "DB1030.DBW8" }, // Int - 1=点检,2=返工,4=样件,5=正常
|
||||||
|
|
||||||
// 产量数据
|
// 产量数据
|
||||||
{ "实际产量", "DB1001.DBD1104" }, // DInt
|
{ "实际产量", "DB1030.DBD1104" }, // DInt
|
||||||
{ "合格数量", "DB1001.DBD1108" }, // DInt
|
{ "合格数量", "DB1030.DBD1108" }, // DInt
|
||||||
{ "失败数量", "DB1001.DBD1112" }, // DInt
|
{ "失败数量", "DB1030.DBD1112" }, // DInt
|
||||||
|
|
||||||
// 操作请求
|
// 操作请求
|
||||||
{ "保存请求", "DB1001.DBW2002" }, // Int - 1=请求开始,0=无请求
|
{ "保存请求", "DB1030.DBW2002" }, // Int - 1=请求开始,0=无请求
|
||||||
{ "线体托盘号", "DB1001.DBW2070" }, // Int
|
{ "线体托盘号", "DB1030.DBW2070" }, // Int
|
||||||
|
|
||||||
// 工艺参数
|
// 工艺参数
|
||||||
{ "节拍时间", "DB1001.DBD2242" } // Real
|
{ "节拍时间", "DB1030.DBD2242" } // Real
|
||||||
};
|
};
|
||||||
|
|
||||||
// OP100 专属地址映射(手动上料壳体&盖板工位,DB1001)
|
// OP100 专属地址映射(手动上料壳体&盖板工位,DB1001)
|
||||||
@ -1344,7 +1340,7 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
? $"{plcName}生产数据读取成功(复用连接)"
|
? $"{plcName}生产数据读取成功(复用连接)"
|
||||||
: $"{plcName}生产数据读取成功(新建连接)";
|
: $"{plcName}生产数据读取成功(新建连接)";
|
||||||
WritePlcSaveRequestResult(plc, ip, plcName, prodData, "1");
|
WritePlcSaveRequestResult(plc, ip, plcName, prodData, "1");
|
||||||
_ = Task.Run(() => RecordPlcOperationResult(plcName, prodData)).ConfigureAwait(false);
|
_ = Task.Run(() => RecordPlcOperationResult(plcName, prodData)).ConfigureAwait(false);
|
||||||
return (true, prodData, successMsg);
|
return (true, prodData, successMsg);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1403,11 +1399,17 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
var taskTrayNo = ReadPlcIntAsync(plc, _op020_2IntMap["托盘号"]);
|
var taskTrayNo = ReadPlcIntAsync(plc, _op020_2IntMap["托盘号"]);
|
||||||
var taskTotalResult = ReadPlcIntAsync(plc, _op020_2IntMap["总结果"]);
|
var taskTotalResult = ReadPlcIntAsync(plc, _op020_2IntMap["总结果"]);
|
||||||
|
|
||||||
|
// DInt任务(单独提取,避免字典开销)
|
||||||
|
var taskActualOutput = ReadPlcIntAsync(plc, _op050IntMap["实际产量"]);
|
||||||
|
var taskQualifiedQty = ReadPlcIntAsync(plc, _op050IntMap["合格数量"]);
|
||||||
|
var taskFailedQty = ReadPlcIntAsync(plc, _op050IntMap["失败数量"]);
|
||||||
|
|
||||||
|
|
||||||
// 1.3 等待所有并行任务完成(关键:耗时=最慢的单个读取任务,而非总和)
|
// 1.3 等待所有并行任务完成(关键:耗时=最慢的单个读取任务,而非总和)
|
||||||
await Task.WhenAll(
|
await Task.WhenAll(
|
||||||
taskProductModel, taskProductName, taskSN,
|
taskProductModel, taskProductName, taskSN,
|
||||||
taskRunStatus, taskMachineModel, taskOnlineStatus,
|
taskRunStatus, taskMachineModel, taskOnlineStatus,
|
||||||
taskProduceModel, taskTrayNo, taskTotalResult);
|
taskProduceModel, taskTrayNo, taskTotalResult, taskActualOutput, taskQualifiedQty, taskFailedQty);
|
||||||
|
|
||||||
// 2. 获取读取结果(带空值兜底,避免后续空引用)
|
// 2. 获取读取结果(带空值兜底,避免后续空引用)
|
||||||
string productModel = await taskProductModel ?? string.Empty;
|
string productModel = await taskProductModel ?? string.Empty;
|
||||||
@ -1419,6 +1421,9 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
int produceModel = await taskProduceModel;
|
int produceModel = await taskProduceModel;
|
||||||
int trayNo = await taskTrayNo;
|
int trayNo = await taskTrayNo;
|
||||||
int totalResult = await taskTotalResult;
|
int totalResult = await taskTotalResult;
|
||||||
|
int actualOutput = await taskActualOutput;
|
||||||
|
int qualifiedQty = await taskQualifiedQty;
|
||||||
|
int failedQty = await taskFailedQty;
|
||||||
|
|
||||||
// 3. 异步复位上传请求(非阻塞,不影响数据读取效率)
|
// 3. 异步复位上传请求(非阻塞,不影响数据读取效率)
|
||||||
_ = ResetUploadRequestAsync(plc, ip, _op020_2IntMap["上传请求"]);
|
_ = ResetUploadRequestAsync(plc, ip, _op020_2IntMap["上传请求"]);
|
||||||
@ -1438,9 +1443,6 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
string onlineStatusDesc = onlineStatus == 1 ? "离线" : "在线";
|
string onlineStatusDesc = onlineStatus == 1 ? "离线" : "在线";
|
||||||
string qualificationFlag = totalResult switch { 1 => "1", 2 => "0", _ => totalResult.ToString() };
|
string qualificationFlag = totalResult switch { 1 => "1", 2 => "0", _ => totalResult.ToString() };
|
||||||
|
|
||||||
// 调试日志(优化:使用StringBuilder减少拼接开销,高频场景更友好)
|
|
||||||
Console.WriteLine($"OP020-2({ip})读取结果:产品型号={productModel},运行状态={runStatusDesc},总结果={qualificationFlag}");
|
|
||||||
|
|
||||||
// 5. 构建数据实体(优化:减少Trim/空值判断,提前兜底)
|
// 5. 构建数据实体(优化:减少Trim/空值判断,提前兜底)
|
||||||
return new PlcProductionData
|
return new PlcProductionData
|
||||||
{
|
{
|
||||||
@ -1460,7 +1462,10 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
Runstatus = runStatus,
|
Runstatus = runStatus,
|
||||||
OnlineStatus = onlineStatusDesc,
|
OnlineStatus = onlineStatusDesc,
|
||||||
ProduceModel = produceModelDesc,
|
ProduceModel = produceModelDesc,
|
||||||
TrayNo = trayNo.ToString(), // int转string开销可忽略,无需优化
|
ActualOutQty = actualOutput.ToString(),
|
||||||
|
QualifiedQty = qualifiedQty.ToString(),
|
||||||
|
FailedQty = failedQty.ToString(),
|
||||||
|
TrayNo = trayNo.ToString(),
|
||||||
CreatedBy = "PLC",
|
CreatedBy = "PLC",
|
||||||
CreatedTime = DateTime.Now
|
CreatedTime = DateTime.Now
|
||||||
};
|
};
|
||||||
@ -1494,8 +1499,13 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
var taskOnlineStatus = ReadPlcIntAsync(plc, _op020_3IntMap["设备在线状态"]);
|
var taskOnlineStatus = ReadPlcIntAsync(plc, _op020_3IntMap["设备在线状态"]);
|
||||||
var taskProduceModel = ReadPlcIntAsync(plc, _op020_3IntMap["生产模式"]);
|
var taskProduceModel = ReadPlcIntAsync(plc, _op020_3IntMap["生产模式"]);
|
||||||
|
|
||||||
|
// DInt任务(单独提取,避免字典开销)
|
||||||
|
var taskActualOutput = ReadPlcIntAsync(plc, _op050IntMap["实际产量"]);
|
||||||
|
var taskQualifiedQty = ReadPlcIntAsync(plc, _op050IntMap["合格数量"]);
|
||||||
|
var taskFailedQty = ReadPlcIntAsync(plc, _op050IntMap["失败数量"]);
|
||||||
|
|
||||||
// 步骤2:等待所有任务并行完成(耗时=最慢的单个读取任务,而非总和)
|
// 步骤2:等待所有任务并行完成(耗时=最慢的单个读取任务,而非总和)
|
||||||
await Task.WhenAll(taskRunStatus, taskMachineModel, taskOnlineStatus, taskProduceModel);
|
await Task.WhenAll(taskRunStatus, taskMachineModel, taskOnlineStatus, taskProduceModel, taskActualOutput, taskQualifiedQty, taskFailedQty);
|
||||||
|
|
||||||
// 步骤3:获取结果(带await确保值已返回,无需额外判空)
|
// 步骤3:获取结果(带await确保值已返回,无需额外判空)
|
||||||
int runStatus = await taskRunStatus;
|
int runStatus = await taskRunStatus;
|
||||||
@ -1503,6 +1513,10 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
int onlineStatus = await taskOnlineStatus;
|
int onlineStatus = await taskOnlineStatus;
|
||||||
int produceModel = await taskProduceModel;
|
int produceModel = await taskProduceModel;
|
||||||
|
|
||||||
|
int actualOutput = await taskActualOutput;
|
||||||
|
int qualifiedQty = await taskQualifiedQty;
|
||||||
|
int failedQty = await taskFailedQty;
|
||||||
|
|
||||||
// 2. 业务逻辑计算(优化:常量复用+减少冗余计算)
|
// 2. 业务逻辑计算(优化:常量复用+减少冗余计算)
|
||||||
var reworkFlag = produceModel == 4 ? "1" : "0";
|
var reworkFlag = produceModel == 4 ? "1" : "0";
|
||||||
|
|
||||||
@ -1539,7 +1553,9 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
LineCode = "line2",
|
LineCode = "line2",
|
||||||
WorkstationCode = workstationCode,
|
WorkstationCode = workstationCode,
|
||||||
WorkstationName = "热铆", // 补充工站名称
|
WorkstationName = "热铆", // 补充工站名称
|
||||||
// 状态字段:直接赋值,无冗余转换
|
ActualOutQty = actualOutput.ToString(),
|
||||||
|
QualifiedQty = qualifiedQty.ToString(),
|
||||||
|
FailedQty = failedQty.ToString(),
|
||||||
ReworkFlag = reworkFlag,
|
ReworkFlag = reworkFlag,
|
||||||
Automanual = machineModel,
|
Automanual = machineModel,
|
||||||
Runstatus = runStatus,
|
Runstatus = runStatus,
|
||||||
@ -1598,10 +1614,19 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
{ "产品4结果", ReadPlcIntAsync(plc, _op020_4IntMap["产品4结果"]) }
|
{ "产品4结果", ReadPlcIntAsync(plc, _op020_4IntMap["产品4结果"]) }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// DInt(双整数)读取任务(复用ReadPlcIntAsync,PLC底层兼容DInt转int)
|
||||||
|
var dIntReadTasks = new Dictionary<string, Task<int>>
|
||||||
|
{
|
||||||
|
{ "实际产量", ReadPlcIntAsync(plc, _op050IntMap["实际产量"]) },
|
||||||
|
{ "合格数量", ReadPlcIntAsync(plc, _op050IntMap["合格数量"]) },
|
||||||
|
{ "失败数量", ReadPlcIntAsync(plc, _op050IntMap["失败数量"]) }
|
||||||
|
};
|
||||||
|
|
||||||
// 2. 并行等待所有读取任务完成(合并任务列表,单次WaitAll提升效率)
|
// 2. 并行等待所有读取任务完成(合并任务列表,单次WaitAll提升效率)
|
||||||
var allTasks = new List<Task>();
|
var allTasks = new List<Task>();
|
||||||
allTasks.AddRange(stringReadTasks.Values);
|
allTasks.AddRange(stringReadTasks.Values);
|
||||||
allTasks.AddRange(intReadTasks.Values);
|
allTasks.AddRange(intReadTasks.Values);
|
||||||
|
allTasks.AddRange(dIntReadTasks.Values);
|
||||||
await Task.WhenAll(allTasks).ConfigureAwait(false);
|
await Task.WhenAll(allTasks).ConfigureAwait(false);
|
||||||
|
|
||||||
// 3. 提取读取结果(直接取值+空值兜底,减少await重复调用)
|
// 3. 提取读取结果(直接取值+空值兜底,减少await重复调用)
|
||||||
@ -1624,6 +1649,9 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
int product3Result = intReadTasks["产品3结果"].Result;
|
int product3Result = intReadTasks["产品3结果"].Result;
|
||||||
int product4Result = intReadTasks["产品4结果"].Result;
|
int product4Result = intReadTasks["产品4结果"].Result;
|
||||||
|
|
||||||
|
int actualOutput = dIntReadTasks["实际产量"].Result;
|
||||||
|
int qualifiedQty = dIntReadTasks["合格数量"].Result;
|
||||||
|
int failedQty = dIntReadTasks["失败数量"].Result;
|
||||||
|
|
||||||
// 4. 业务逻辑转换(极简逻辑,仅保留必要转换)
|
// 4. 业务逻辑转换(极简逻辑,仅保留必要转换)
|
||||||
string reworkFlag = produceModel == 4 ? "1" : "0";
|
string reworkFlag = produceModel == 4 ? "1" : "0";
|
||||||
@ -1668,6 +1696,9 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
Product4Result = product1Result.ToString(),
|
Product4Result = product1Result.ToString(),
|
||||||
SN1 = product1SN,
|
SN1 = product1SN,
|
||||||
SN2 = product2SN,
|
SN2 = product2SN,
|
||||||
|
ActualOutQty = actualOutput.ToString(),
|
||||||
|
QualifiedQty = qualifiedQty.ToString(),
|
||||||
|
FailedQty = failedQty.ToString(),
|
||||||
QualificationFlag = qualificationFlag
|
QualificationFlag = qualificationFlag
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1755,6 +1786,7 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
int byPass = intReadTasks["ByPass"].Result;
|
int byPass = intReadTasks["ByPass"].Result;
|
||||||
int produceModel = intReadTasks["生产模式"].Result;
|
int produceModel = intReadTasks["生产模式"].Result;
|
||||||
int trayNo = intReadTasks["托盘号"].Result;
|
int trayNo = intReadTasks["托盘号"].Result;
|
||||||
|
|
||||||
int actualOutput = dIntReadTasks["实际产量"].Result;
|
int actualOutput = dIntReadTasks["实际产量"].Result;
|
||||||
int qualifiedQty = dIntReadTasks["合格数量"].Result;
|
int qualifiedQty = dIntReadTasks["合格数量"].Result;
|
||||||
int failedQty = dIntReadTasks["失败数量"].Result;
|
int failedQty = dIntReadTasks["失败数量"].Result;
|
||||||
@ -1927,7 +1959,9 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
TrayNo = string.Empty,
|
TrayNo = string.Empty,
|
||||||
CreatedBy = "PLC",
|
CreatedBy = "PLC",
|
||||||
CreatedTime = DateTime.Now,
|
CreatedTime = DateTime.Now,
|
||||||
// 产量/节拍核心字段
|
ActualOutQty = actualOutput.ToString(),
|
||||||
|
QualifiedQty = qualifiedQty.ToString(),
|
||||||
|
FailedQty = failedQty.ToString(),
|
||||||
ProductionCycle = (int)Math.Round(cycleTime), // 节拍时间转整数秒
|
ProductionCycle = (int)Math.Round(cycleTime), // 节拍时间转整数秒
|
||||||
QualificationFlag = qualificationFlag,
|
QualificationFlag = qualificationFlag,
|
||||||
// 备注记录产量信息(便于排查)
|
// 备注记录产量信息(便于排查)
|
||||||
@ -1978,9 +2012,18 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
{ "托盘号", ReadPlcIntAsync(plc, _op051ScanIntMap["托盘号"]) }
|
{ "托盘号", ReadPlcIntAsync(plc, _op051ScanIntMap["托盘号"]) }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// DInt(双整数)读取任务(复用ReadPlcIntAsync,PLC底层兼容DInt转int)
|
||||||
|
var dIntReadTasks = new Dictionary<string, Task<int>>
|
||||||
|
{
|
||||||
|
{ "实际产量", ReadPlcIntAsync(plc, _op050IntMap["实际产量"]) },
|
||||||
|
{ "合格数量", ReadPlcIntAsync(plc, _op050IntMap["合格数量"]) },
|
||||||
|
{ "失败数量", ReadPlcIntAsync(plc, _op050IntMap["失败数量"]) }
|
||||||
|
};
|
||||||
|
|
||||||
// 2. 并行等待所有任务完成(单次WaitAll,最小化等待时间)
|
// 2. 并行等待所有任务完成(单次WaitAll,最小化等待时间)
|
||||||
var allTasks = new List<Task>();
|
var allTasks = new List<Task>();
|
||||||
allTasks.AddRange(stringTasks.Values);
|
allTasks.AddRange(stringTasks.Values);
|
||||||
|
allTasks.AddRange(dIntReadTasks.Values);
|
||||||
allTasks.AddRange(intTasks.Values);
|
allTasks.AddRange(intTasks.Values);
|
||||||
await Task.WhenAll(allTasks).ConfigureAwait(false);
|
await Task.WhenAll(allTasks).ConfigureAwait(false);
|
||||||
|
|
||||||
@ -2000,6 +2043,10 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
var uploadRequest = intTasks["上传结果请求"].Result;
|
var uploadRequest = intTasks["上传结果请求"].Result;
|
||||||
var trayNo = intTasks["托盘号"].Result.ToString(); // 转换为字符串,适配实体字段
|
var trayNo = intTasks["托盘号"].Result.ToString(); // 转换为字符串,适配实体字段
|
||||||
|
|
||||||
|
int actualOutput = dIntReadTasks["实际产量"].Result;
|
||||||
|
int qualifiedQty = dIntReadTasks["合格数量"].Result;
|
||||||
|
int failedQty = dIntReadTasks["失败数量"].Result;
|
||||||
|
|
||||||
// 4. 核心逻辑转换(极简表达式,适配扫码工位业务)
|
// 4. 核心逻辑转换(极简表达式,适配扫码工位业务)
|
||||||
var reworkFlag = produceModel == 4 ? "1" : "0"; // 4=返工模式→1,其他→0
|
var reworkFlag = produceModel == 4 ? "1" : "0"; // 4=返工模式→1,其他→0
|
||||||
var produceModelDesc = produceModel switch
|
var produceModelDesc = produceModel switch
|
||||||
@ -2040,6 +2087,9 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
Product2SN = sn2,
|
Product2SN = sn2,
|
||||||
Product3SN = sn3,
|
Product3SN = sn3,
|
||||||
QualificationFlag = qualificationFlag,
|
QualificationFlag = qualificationFlag,
|
||||||
|
ActualOutQty = actualOutput.ToString(),
|
||||||
|
QualifiedQty = qualifiedQty.ToString(),
|
||||||
|
FailedQty = failedQty.ToString(),
|
||||||
CreatedBy = "PLC",
|
CreatedBy = "PLC",
|
||||||
CreatedTime = now,
|
CreatedTime = now,
|
||||||
};
|
};
|
||||||
@ -2178,6 +2228,9 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
Product1Result = pin1Result.ToString(),
|
Product1Result = pin1Result.ToString(),
|
||||||
Product2Result = pin2Result.ToString(),
|
Product2Result = pin2Result.ToString(),
|
||||||
QualificationFlag = qualificationFlag,
|
QualificationFlag = qualificationFlag,
|
||||||
|
ActualOutQty = actualOutput.ToString(),
|
||||||
|
QualifiedQty = qualifiedQty.ToString(),
|
||||||
|
FailedQty = failedQty.ToString(),
|
||||||
ProductionCycle = (int)Math.Round(cycleTime),
|
ProductionCycle = (int)Math.Round(cycleTime),
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -2268,6 +2321,9 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
PinPressure1 = pressure.ToString(),
|
PinPressure1 = pressure.ToString(),
|
||||||
PinStroke1 = stroke.ToString(),
|
PinStroke1 = stroke.ToString(),
|
||||||
QualificationFlag = qualificationFlag,
|
QualificationFlag = qualificationFlag,
|
||||||
|
ActualOutQty = actualOutput.ToString(),
|
||||||
|
QualifiedQty = qualifiedQty.ToString(),
|
||||||
|
FailedQty = failedQty.ToString(),
|
||||||
ProductionCycle = (int)Math.Round(cycleTime),
|
ProductionCycle = (int)Math.Round(cycleTime),
|
||||||
CreatedBy = "PLC_System",
|
CreatedBy = "PLC_System",
|
||||||
CreatedTime = now,
|
CreatedTime = now,
|
||||||
@ -2353,6 +2409,8 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
var onlineStatus = intTasks["设备在线状态"].Result;
|
var onlineStatus = intTasks["设备在线状态"].Result;
|
||||||
var produceModel = intTasks["生产模式"].Result;
|
var produceModel = intTasks["生产模式"].Result;
|
||||||
var actualOutput = intTasks["实际产量"].Result;
|
var actualOutput = intTasks["实际产量"].Result;
|
||||||
|
var qualifiedQty = intTasks["合格数量"].Result;
|
||||||
|
var failedQty = intTasks["失败数量"].Result;
|
||||||
var productTotalResult = intTasks["产品总结果"].Result;
|
var productTotalResult = intTasks["产品总结果"].Result;
|
||||||
var screw1Result = intTasks["1#螺丝结果"].Result;
|
var screw1Result = intTasks["1#螺丝结果"].Result;
|
||||||
var screw2Result = intTasks["2#螺丝结果"].Result;
|
var screw2Result = intTasks["2#螺丝结果"].Result;
|
||||||
@ -2408,6 +2466,9 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
OnlineStatus = onlineStatusDesc,
|
OnlineStatus = onlineStatusDesc,
|
||||||
ProduceModel = produceModelDesc,
|
ProduceModel = produceModelDesc,
|
||||||
QualificationFlag = qualificationFlag,
|
QualificationFlag = qualificationFlag,
|
||||||
|
ActualOutQty = actualOutput.ToString(),
|
||||||
|
QualifiedQty = qualifiedQty.ToString(),
|
||||||
|
FailedQty = failedQty.ToString(),
|
||||||
ProductionCycle = (int)Math.Round(cycleTime),
|
ProductionCycle = (int)Math.Round(cycleTime),
|
||||||
CreatedBy = "PLC",
|
CreatedBy = "PLC",
|
||||||
CreatedTime = now,
|
CreatedTime = now,
|
||||||
@ -2482,7 +2543,10 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
var taskTrayNo = ReadPlcIntAsync(plc, _op070_1IntMap["托盘号"]);
|
var taskTrayNo = ReadPlcIntAsync(plc, _op070_1IntMap["托盘号"]);
|
||||||
var taskCameraResult = ReadPlcIntAsync(plc, _op070_1IntMap["相机结果"]);
|
var taskCameraResult = ReadPlcIntAsync(plc, _op070_1IntMap["相机结果"]);
|
||||||
var taskStationResult = ReadPlcIntAsync(plc, _op070_1IntMap["站位结果"]);
|
var taskStationResult = ReadPlcIntAsync(plc, _op070_1IntMap["站位结果"]);
|
||||||
|
// DInt任务(单独提取,避免字典开销)
|
||||||
|
var taskActualOutput = ReadPlcIntAsync(plc, _op050IntMap["实际产量"]);
|
||||||
|
var taskQualifiedQty = ReadPlcIntAsync(plc, _op050IntMap["合格数量"]);
|
||||||
|
var taskFailedQty = ReadPlcIntAsync(plc, _op050IntMap["失败数量"]);
|
||||||
// ========== Real字段并行任务 ==========
|
// ========== Real字段并行任务 ==========
|
||||||
var taskCycleTime = ReadPlcRealAsync(plc, _op070_1IntMap["节拍时间"]);
|
var taskCycleTime = ReadPlcRealAsync(plc, _op070_1IntMap["节拍时间"]);
|
||||||
|
|
||||||
@ -2494,7 +2558,9 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
taskRunStatus, taskMachineModel, taskOnlineStatus, taskByPass, taskProduceModel,
|
taskRunStatus, taskMachineModel, taskOnlineStatus, taskByPass, taskProduceModel,
|
||||||
taskTrayNo, taskCameraResult, taskStationResult,
|
taskTrayNo, taskCameraResult, taskStationResult,
|
||||||
// Real任务
|
// Real任务
|
||||||
taskCycleTime);
|
taskCycleTime,
|
||||||
|
// DInt任务
|
||||||
|
taskActualOutput, taskQualifiedQty, taskFailedQty);
|
||||||
|
|
||||||
// 3. 获取并行读取结果(带空值兜底,避免后续空引用)
|
// 3. 获取并行读取结果(带空值兜底,避免后续空引用)
|
||||||
// 字符串字段
|
// 字符串字段
|
||||||
@ -2513,10 +2579,14 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
int trayNo = await taskTrayNo;
|
int trayNo = await taskTrayNo;
|
||||||
int cameraResult = await taskCameraResult;
|
int cameraResult = await taskCameraResult;
|
||||||
int stationResult = await taskStationResult;
|
int stationResult = await taskStationResult;
|
||||||
|
int actualOutput = await taskActualOutput;
|
||||||
|
int qualifiedQty = await taskQualifiedQty;
|
||||||
|
int failedQty = await taskFailedQty;
|
||||||
|
|
||||||
// Real字段
|
// Real字段
|
||||||
float cycleTime = await taskCycleTime;
|
float cycleTime = await taskCycleTime;
|
||||||
|
|
||||||
|
|
||||||
// 4. 异步复位保存请求(非阻塞,不影响读取效率)
|
// 4. 异步复位保存请求(非阻塞,不影响读取效率)
|
||||||
//_ = ResetSaveRequestAsync(plc, ip, _op070_1IntMap["保存请求"]);
|
//_ = ResetSaveRequestAsync(plc, ip, _op070_1IntMap["保存请求"]);
|
||||||
|
|
||||||
@ -2553,6 +2623,9 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
SN1 = sn1,
|
SN1 = sn1,
|
||||||
SN2 = sn2,
|
SN2 = sn2,
|
||||||
QualificationFlag = qualificationFlag,
|
QualificationFlag = qualificationFlag,
|
||||||
|
ActualOutQty = actualOutput.ToString(),
|
||||||
|
QualifiedQty = qualifiedQty.ToString(),
|
||||||
|
FailedQty = failedQty.ToString(),
|
||||||
ReworkFlag = reworkFlag,
|
ReworkFlag = reworkFlag,
|
||||||
Automanual = machineModel,
|
Automanual = machineModel,
|
||||||
Runstatus = runStatus,
|
Runstatus = runStatus,
|
||||||
@ -2609,6 +2682,11 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
// ========== Real字段并行任务 ==========
|
// ========== Real字段并行任务 ==========
|
||||||
var taskCycleTime = ReadPlcRealAsync(plc, _op075IntMap["节拍时间"]);
|
var taskCycleTime = ReadPlcRealAsync(plc, _op075IntMap["节拍时间"]);
|
||||||
|
|
||||||
|
// DInt任务(单独提取,避免字典开销)
|
||||||
|
var taskActualOutput = ReadPlcIntAsync(plc, _op050IntMap["实际产量"]);
|
||||||
|
var taskQualifiedQty = ReadPlcIntAsync(plc, _op050IntMap["合格数量"]);
|
||||||
|
var taskFailedQty = ReadPlcIntAsync(plc, _op050IntMap["失败数量"]);
|
||||||
|
|
||||||
// 2. 等待所有并行任务完成(核心:耗时=最慢的单个读取任务,而非总和)
|
// 2. 等待所有并行任务完成(核心:耗时=最慢的单个读取任务,而非总和)
|
||||||
await Task.WhenAll(
|
await Task.WhenAll(
|
||||||
// 字符串任务
|
// 字符串任务
|
||||||
@ -2617,7 +2695,10 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
taskRunStatus, taskMachineModel, taskOnlineStatus, taskByPass, taskProduceModel,
|
taskRunStatus, taskMachineModel, taskOnlineStatus, taskByPass, taskProduceModel,
|
||||||
taskTrayNo, taskStationResult,
|
taskTrayNo, taskStationResult,
|
||||||
// Real任务
|
// Real任务
|
||||||
taskCycleTime);
|
taskCycleTime
|
||||||
|
// DInt任务
|
||||||
|
, taskActualOutput, taskQualifiedQty, taskFailedQty
|
||||||
|
);
|
||||||
|
|
||||||
// 3. 获取并行读取结果(带空值兜底,避免后续空引用)
|
// 3. 获取并行读取结果(带空值兜底,避免后续空引用)
|
||||||
// 字符串字段
|
// 字符串字段
|
||||||
@ -2636,7 +2717,9 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
int produceModel = await taskProduceModel;
|
int produceModel = await taskProduceModel;
|
||||||
int trayNo = await taskTrayNo;
|
int trayNo = await taskTrayNo;
|
||||||
int stationResult = await taskStationResult;
|
int stationResult = await taskStationResult;
|
||||||
|
int actualOutput = await taskActualOutput;
|
||||||
|
int qualifiedQty = await taskQualifiedQty;
|
||||||
|
int failedQty = await taskFailedQty;
|
||||||
// Real字段
|
// Real字段
|
||||||
float cycleTime = await taskCycleTime;
|
float cycleTime = await taskCycleTime;
|
||||||
|
|
||||||
@ -2676,6 +2759,9 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
SN2 = sn2,
|
SN2 = sn2,
|
||||||
ChipSN = chipsn, // 保留芯片SN独有字段
|
ChipSN = chipsn, // 保留芯片SN独有字段
|
||||||
QualificationFlag = qualificationFlag,
|
QualificationFlag = qualificationFlag,
|
||||||
|
ActualOutQty = actualOutput.ToString(),
|
||||||
|
QualifiedQty = qualifiedQty.ToString(),
|
||||||
|
FailedQty = failedQty.ToString(),
|
||||||
ReworkFlag = reworkFlag,
|
ReworkFlag = reworkFlag,
|
||||||
Automanual = machineModel,
|
Automanual = machineModel,
|
||||||
Runstatus = runStatus,
|
Runstatus = runStatus,
|
||||||
@ -2690,16 +2776,9 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
// 增强异常日志:包含堆栈,便于定位问题
|
// 增强异常日志:包含堆栈,便于定位问题
|
||||||
Console.WriteLine($"OP075({ip})数据读取异常:{ex.Message}\n{ex.StackTrace}");
|
Console.WriteLine($"OP075({ip})数据读取异常:{ex.Message}");
|
||||||
// 异常时返回基础实体,避免业务空引用
|
// 异常时返回基础实体,避免业务空引用
|
||||||
return new PlcProductionData
|
return null;
|
||||||
{
|
|
||||||
PlcIp = ip,
|
|
||||||
WorkstationCode = workstationCode,
|
|
||||||
CreatedBy = "PLC",
|
|
||||||
CreatedTime = DateTime.Now,
|
|
||||||
OnlineStatus = "读取异常"
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5479,17 +5558,22 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var routingCode = await Context.Queryable<ProcessRouting>()
|
// 在方法内创建上下文,并使用using确保自动释放
|
||||||
|
using var context = DbScoped.SugarScope.CopyNew();
|
||||||
|
if (context == null)
|
||||||
|
throw new InvalidOperationException("无法创建数据库上下文,请检查SqlSugar配置");
|
||||||
|
var routingCode = string.Empty;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
routingCode = await context.Queryable<ProcessRouting>()
|
||||||
.LeftJoin<ProcessOperation>((r, o) => r.RoutingCode == o.FkRoutingCode)
|
.LeftJoin<ProcessOperation>((r, o) => r.RoutingCode == o.FkRoutingCode)
|
||||||
.Where((r, o) => r.FkProductMaterialCode == strSN && r.Status == 1)
|
.Where((r, o) => r.FkProductMaterialCode == strSN && r.Status == 1)
|
||||||
.Select((r, o) => o.FkRoutingCode)
|
.Select((r, o) => o.FkRoutingCode)
|
||||||
.FirstAsync(); // 直接取第一条,避免ToList+First的双重开销
|
.FirstAsync(); // 直接取第一条,避免ToList+First的双重开销
|
||||||
|
}
|
||||||
// 4.1 工艺路线校验(合并判断,减少分支)
|
catch
|
||||||
if (string.IsNullOrWhiteSpace(routingCode))
|
{
|
||||||
{
|
|
||||||
Console.WriteLine($"[{now:HH:mm:ss}] {plcName} - {strSN} 工艺路线无效,跳过记录");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. 返工状态判断(无分配判断,直接赋值)
|
// 5. 返工状态判断(无分配判断,直接赋值)
|
||||||
@ -5510,7 +5594,7 @@ namespace RIZO.Admin.WebApi.PLC.Service
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 7. 插入数据库(批量插入优化,减少IO交互)
|
// 7. 插入数据库(批量插入优化,减少IO交互)
|
||||||
var insertCount = await Context.Insertable(askOutStation).ExecuteCommandAsync();
|
var insertCount = await context.Insertable(askOutStation).ExecuteCommandAsync();
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (ArgumentNullException ex)
|
catch (ArgumentNullException ex)
|
||||||
|
|||||||
@ -23,7 +23,7 @@ namespace RIZO.Service.PLCBackground.Stations.Into
|
|||||||
private static Logger _logger = LogManager.GetCurrentClassLogger();
|
private static Logger _logger = LogManager.GetCurrentClassLogger();
|
||||||
private PlcConntectHepler _plcService;
|
private PlcConntectHepler _plcService;
|
||||||
private readonly TimeSpan _pollingInterval = TimeSpan.FromSeconds(5);
|
private readonly TimeSpan _pollingInterval = TimeSpan.FromSeconds(5);
|
||||||
private readonly string _ipAddress = "192.168.11.56";
|
private readonly string _ipAddress = "192.168.1.111";
|
||||||
private readonly CpuType _cpuType = CpuType.S71500;
|
private readonly CpuType _cpuType = CpuType.S71500;
|
||||||
private string WorkstationCode;
|
private string WorkstationCode;
|
||||||
private readonly SqlSugarClient Context;
|
private readonly SqlSugarClient Context;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user