PLC数采

This commit is contained in:
quowingwang 2026-02-03 17:28:39 +08:00
parent e648d92e75
commit a696db26d4
10 changed files with 461 additions and 298 deletions

View File

@ -209,6 +209,9 @@ namespace Infrastructure.Model
public string ProductModel { get; set; }
public string ProductSN { get; set; }
public string IntoStationResp { get; set; }
public string IntoStationResp2 { get; set; }
public string IntoStationResp3 { get; set; }
public string IntoStationResp4 { get; set; }
}
}

View File

@ -60,18 +60,24 @@ namespace RIZO.Admin.WebApi.PLC.Service
{
{ "设备使能", "DB1000.DBW0" }, // Int
{ "工位开始查询结果", "DB1000.DBW2000" }, // Int
{ "1#产品结束保存结果", "DB1000.DBW2002" }, // Int
{ "2#产品结束保存结果", "DB1000.DBW2004" }, // Int
{ "3#产品结束保存结果", "DB1000.DBW2006" }, // Int
{ "4#产品结束保存结果", "DB1000.DBW2008" }, // Int
{ "保存结果1", "DB1000.DBW2002" }, // Int
{ "保存结果2", "DB1000.DBW2004" }, // Int
{ "保存结果3", "DB1000.DBW2006" }, // Int
{ "保存结果4", "DB1000.DBW2008" }, // Int
};
private readonly Dictionary<string, string> _mesop50IntReturnMap = new()
private readonly Dictionary<string, string> _mesop050IntReturnMap = new()
{
{ "设备使能", "DB300.DBW0" }, // Int
{ "1#产品结束保存结果", "DB300.DBW48" }, // Int
{ "2#产品结束保存结果", "DB300.DBW204" }, // Int
{ "3#产品结束保存结果", "DB300.DBW360" }, // Int
{ "4#产品结束保存结果", "DB300.DBW516" }, // Int
{ "保存结果1", "DB300.DBW48" }, // Int
{ "保存结果2", "DB300.DBW204" }, // Int
{ "保存结果3", "DB300.DBW360" }, // Int
{ "保存结果4", "DB300.DBW516" }, // Int
};
private readonly Dictionary<string, string> _mesop51ScanIntReturnMap = new()
{
{ "设备使能", "DB1000.DBW0" }, // Int
{ "工位开始查询结果", "DB1000.DBW2" }, // Int
{ "保存结果", "DB1000.DBW4" }, // Int
};
private readonly Dictionary<string, string> _mesop058IntReturnMap = new()
{
@ -112,13 +118,14 @@ namespace RIZO.Admin.WebApi.PLC.Service
{ "运行状态", "DB1001.DBW0" }, // Int - 1=空闲2=运行中3=故障
{ "设备模式", "DB1001.DBW2" }, // Int - 1=空模式2=手动4=初始化8=自动16=CycleStop
{ "设备在线状态", "DB1001.DBW4" }, // Int - 1=离线,0=在线
//{ "ByPass", "DB1001.DBW6" }, // Int - 1=ByPass,0=正常模式
{ "ByPass", "DB1001.DBW6" }, // Int - 1=ByPass,0=正常模式
{ "生产模式", "DB1001.DBW8" }, // Int - 1=正常模式;2=清线模式;4=返工模式;8=换型模式;16=预热模式
//{ "实际产量", "DB1001.DBD1104" }, // DInt
//{ "合格数量", "DB1001.DBD1108" }, // DInt
//{ "失败数量", "DB1001.DBD1112" }, // DInt
{ "实际产量", "DB1001.DBD1104" }, // DInt
{ "合格数量", "DB1001.DBD1108" }, // DInt
{ "失败数量", "DB1001.DBD1112" }, // DInt
{ "查询请求", "DB1001.DBW2000" }, // Int - 1=请求开始0=无请求
{ "上传请求", "DB1001.DBW2002" }, // Int - 1=请求开始0=无请求
{ "托盘号", "DB1001.DBW2054" }, // Int
{ "总结果", "DB1001.DBW2158" }, // Int - 一个托盘上传四次结果
@ -150,7 +157,7 @@ namespace RIZO.Admin.WebApi.PLC.Service
{ "上传请求", "DB1001.DBW2002" }, // Int - 1:请求开始0:无请求
// 节拍时间
{ "节拍时间", "DB1001.DBD2988" }, // Real
{ "节拍时间", "DB1001.DBD3030" }, // Real
// 产品结果与产量
{ "合格数量", "DB1001.DBD4110" }, // DInt
@ -158,12 +165,10 @@ namespace RIZO.Admin.WebApi.PLC.Service
{ "实际数量", "DB1001.DBD4118" } // DInt
};
// OP020-4 专属地址映射pin压合&视觉检查工位DB1001
private readonly Dictionary<string, (string Addr, int Len)> _op020_4StringMap = new()
{
{ "报警信息", ("DB1001.DBB58", 48) }, // Array[1..48] of Byte
{ "产品型号", ("DB1001.DBB1000", 48) }, // String[48]
{ "产品名称", ("DB1001.DBB1054", 48) }, // String[48]
{ "产品1SN", ("DB1001.DBB2230", 40) }, // String[40]
{ "产品2SN", ("DB1001.DBB2360", 40) }, // String[40]
{ "产品3SN", ("DB1001.DBB2490", 40) }, // String[40]
@ -178,29 +183,34 @@ namespace RIZO.Admin.WebApi.PLC.Service
{ "设备在线状态", "DB1001.DBW4" }, // Int - 1=离线,0=在线
{ "ByPass", "DB1001.DBW6" }, // Int - 1=ByPass,0=正常模式
{ "生产模式", "DB1001.DBW8" }, // Int - 1=正常模式;2=清线模式;4=返工模式;8=换型模式;16=预热模式
// 上传请求
{ "查询请求", "DB1001.DBW2000" }, // Int - 1:请求开始0:无请求
{ "产品1上传请求", "DB1001.DBW2002" }, // Int
{ "产品2上传请求", "DB1001.DBW2004" }, // Int
{ "产品3上传请求", "DB1001.DBW2006" }, // Int
{ "产品4上传请求", "DB1001.DBW2008" }, // Int
// 托盘号
{ "托盘号", "DB1001.DBW2070" }, // Int
// 产品结果
{ "产品1结果", "DB1001.DBW2274" }, // Int - 1:OK 2:NG
{ "产品2结果", "DB1001.DBW2404" }, // Int - 1:OK 2:NG
{ "产品3结果", "DB1001.DBW2534" }, // Int - 1:OK 2:NG
{ "产品4结果", "DB1001.DBW2664" }, // Int - 1:OK 2:NG
// 产量统计
{ "实际产量", "DB1001.DBD1104" }, // DInt
{ "合格数量", "DB1001.DBD1108" }, // DInt
{ "失败数量", "DB1001.DBD1112" } // DInt
};
// OP050 专属地址映射点白胶DC744工位DB300
private readonly Dictionary<string, (string Addr, int Len)> _op050StringMap = new()
{
{ "报警信息", ("DB300.DBB680", 48) }, // Array[1..48] of Byte
{ "产品型号", ("DB300.DBB728", 48) }, // String[48]
{ "报警信息", ("DB300.DBB730", 48) }, // Array[1..48] of Byte
{ "产品型号", ("DB300.DBB680", 48) }, // String[48]
{ "产品名称", ("DB300.DBB778", 48) }, // String[48]
{ "产品1SN", ("DB300.DBB50", 40) }, // String[40]
{ "产品2SN", ("DB300.DBB206", 40) }, // String[40]
@ -268,30 +278,31 @@ namespace RIZO.Admin.WebApi.PLC.Service
{ "节拍时间", "DB1001.DBD5086" }, // Real
};
// OP051扫码 专属地址映射Coating扫码工位假设使用 DB1002//待PLC给出
// OP051扫码 专属地址映射Coating扫码工位DB1001
private readonly Dictionary<string, (string Addr, int Len)> _op051ScanStringMap = new()
{
{ "产品型号", ("DB1002.DBB1000", 48) }, // String[48]
{ "产品名称", ("DB1002.DBB1054", 48) }, // String[48]
{ "SN_1", ("DB1002.DBB50", 40) }, // String[40]
{ "SN_2", ("DB1002.DBB206", 40) }, // String[40]
{ "SN_3", ("DB1002.DBB362", 40) } // String[40]
{ "报警信息", ("DB1001.DBB60", 48) }, // Array[0..48] of Byte
{ "SN", ("DB1001.DBB110", 40) }, // String[40] - 查询条码
{ "SN_1", ("DB1001.DBB152", 40) }, // String[40] - 保存条码1
{ "SN_2", ("DB1001.DBB194", 40) }, // String[40] - 保存条码2
{ "SN_3", ("DB1001.DBB236", 40) }, // String[40] - 保存条码3
{ "托盘号", ("DB1001.DBB278", 40) } // String[40]
};
private readonly Dictionary<string, string> _op051ScanIntMap = new()
{
// 基础状态
{ "运行状态", "DB1002.DBW0" }, // Int - 1=空闲2=运行中3=故障
{ "设备模式", "DB1002.DBW2" }, // Int - 1=空模式2=手动4=初始化8=自动16=CycleStop
{ "设备在线状态", "DB1002.DBW4" }, // Int - 1=离线,0=在线
{ "生产模式", "DB1002.DBW8" }, // Int - 1=正常模式;2=清线模式;4=返工模式;8=换型模式;16=预热模式
{ "运行状态", "DB1001.DBW0" }, // Int - 1=空闲2=运行中3=故障
{ "设备模式", "DB1001.DBW2" }, // Int - 1=空模式2=手动4=初始化8=自动16=CycleStop
{ "设备在线状态", "DB1001.DBW4" }, // Int - 1=离线,0=在线
{ "生产模式", "DB1001.DBW6" }, // Int - 1=正常模式;2=清线模式;4=返工模式;8=换型模式;16=预热模式
// 操作请求
{ "查询请求", "DB1002.DBW44" }, // Int - 非0为查询
{ "上传结果请求", "DB1002.DBW46" }, // Int - 非0为上传
// 托盘号
{ "托盘号", "DB1002.DBW844" } // Int
{ "查询请求", "DB1001.DBW320" }, // Int - 1:请求开始0:无请求
{ "上传结果请求", "DB1001.DBW322" }, // Int - 1:请求开始0:无请求
// 节拍时间
{ "节拍时间", "DB1001.DBD324" } // Real
};
// OP057 专属地址映射(压装定位销&激光打标工位DB1001
@ -1076,7 +1087,9 @@ namespace RIZO.Admin.WebApi.PLC.Service
{
{ "报警信息", ("DB1001.DBB58", 48) }, // Array[1..48] of Byte
{ "产品型号", ("DB1001.DBB1000", 48) }, // String[48]
{ "产品名称", ("DB1001.DBB1054", 48) } // String[48]
{ "产品名称", ("DB1001.DBB1054", 48) }, // String[48]
{ "查询SN", ("DB1001.DBB2100", 40) }, // String[40]
{ "保存SN", ("DB1001.DBB2230", 40) } // String[40]
};
private readonly Dictionary<string, string> _op115IntMap = new()
@ -1086,7 +1099,10 @@ namespace RIZO.Admin.WebApi.PLC.Service
{ "设备模式", "DB1001.DBW2" }, // Int - 1=空模式2=手动4=初始化8=自动16=CycleStop
{ "设备在线状态", "DB1001.DBW4" }, // Int - 1=离线,0=在线
{ "ByPass", "DB1001.DBW6" }, // Int - 1=ByPass,0=正常模式
{ "生产模式", "DB1001.DBW8" } // Int - 1=点检2=返工4=样件5=正常
{ "生产模式", "DB1001.DBW8" }, // Int - 1=点检2=返工4=样件5=正常
// 操作请求
{ "工位查询请求", "DB1001.DBW2000" }, // Int - 1=请求开始0=无请求
{ "结果保存请求", "DB1001.DBW2002" }, // Int - 1=请求开始0=无请求
};
// OP140 专属地址映射气密性测试工位DB1001
@ -1313,6 +1329,7 @@ namespace RIZO.Admin.WebApi.PLC.Service
break;
case "OP050":
iSaveRequest = await ReadPlcIntAsync(plc, _op050IntMap["上传请求"]).ConfigureAwait(false);
if (iSaveRequest > 0) iSaveRequest = 1;
break;
case "OP050-1":
var task5_1 = ReadPlcIntAsync(plc, _op050_1IntMap["产品1保存请求"]);
@ -1387,8 +1404,7 @@ namespace RIZO.Admin.WebApi.PLC.Service
iSaveRequest = await ReadPlcIntAsync(plc, _op110_3IntMap["产品保存请求"]).ConfigureAwait(false);
break;
case "OP115":
//iSaveRequest = await ReadPlcIntAsync(plc, _op115IntMap["结果保存请求"]).ConfigureAwait(false);
iSaveRequest = 0;
iSaveRequest = await ReadPlcIntAsync(plc, _op115IntMap["结果保存请求"]).ConfigureAwait(false);
break;
case "OP140":
iSaveRequest = await ReadPlcIntAsync(plc, _op140IntMap["结果保存请求"]).ConfigureAwait(false);
@ -1630,8 +1646,7 @@ namespace RIZO.Admin.WebApi.PLC.Service
{ "ByPass", ReadPlcIntAsync(plc, _op020_3IntMap["ByPass"]) },
{ "生产模式", ReadPlcIntAsync(plc, _op020_3IntMap["生产模式"]) },
{ "查询请求", ReadPlcIntAsync(plc, _op020_3IntMap["查询请求"]) },
{ "上传请求", ReadPlcIntAsync(plc, _op020_3IntMap["上传请求"]) },
{ "托盘号", ReadPlcIntAsync(plc, _op020_3IntMap["托盘号"]) }
{ "上传请求", ReadPlcIntAsync(plc, _op020_3IntMap["上传请求"]) }
};
// DInt/Real读取任务产量+节拍时间复用ReadPlcIntAsync兼容转换与OP020-4风格一致
@ -1664,7 +1679,6 @@ namespace RIZO.Admin.WebApi.PLC.Service
int onlineStatus = intReadTasks["设备在线状态"].Result;
int byPass = intReadTasks["ByPass"].Result;
int produceModel = intReadTasks["生产模式"].Result;
int trayNo = intReadTasks["托盘号"].Result;
// DInt/Real转换结果
int cycleTime = dIntRealReadTasks["节拍时间"].Result;
@ -1703,7 +1717,6 @@ namespace RIZO.Admin.WebApi.PLC.Service
Runstatus = runStatus,
OnlineStatus = onlineStatusDesc,
ProduceModel = produceModelDesc,
TrayNo = trayNo.ToString(),
CreatedBy = "PLC",
CreatedTime = DateTime.Now,
Product1SN = product1SN,
@ -1748,7 +1761,7 @@ namespace RIZO.Admin.WebApi.PLC.Service
{
{ "报警信息", ReadPlcStringAsync(plc, _op020_4StringMap["报警信息"].Addr, _op020_4StringMap["报警信息"].Len) },
{ "产品型号", ReadPlcStringAsync(plc, _op020_4StringMap["产品型号"].Addr, _op020_4StringMap["产品型号"].Len) },
{ "产品名称", ReadPlcStringAsync(plc, _op020_4StringMap["产品名称"].Addr, _op020_4StringMap["产品名称"].Len) },
{ "产品1SN", ReadPlcStringAsync(plc, _op020_4StringMap["产品1SN"].Addr, _op020_4StringMap["产品1SN"].Len) },
{ "产品2SN", ReadPlcStringAsync(plc, _op020_4StringMap["产品2SN"].Addr, _op020_4StringMap["产品2SN"].Len) },
{ "产品3SN", ReadPlcStringAsync(plc, _op020_4StringMap["产品3SN"].Addr, _op020_4StringMap["产品3SN"].Len) },
@ -1787,7 +1800,6 @@ namespace RIZO.Admin.WebApi.PLC.Service
// 3. 提取读取结果(直接取值+空值兜底减少await重复调用
// 字符串字段
string productModel = stringReadTasks["产品型号"].Result ?? string.Empty;
string productName = stringReadTasks["产品名称"].Result ?? string.Empty;
string product1SN = stringReadTasks["产品1SN"].Result ?? string.Empty;
string product2SN = stringReadTasks["产品2SN"].Result ?? string.Empty;
string product3SN = stringReadTasks["产品3SN"].Result ?? string.Empty;
@ -1831,7 +1843,6 @@ namespace RIZO.Admin.WebApi.PLC.Service
WorkstationCode = workstationCode,
WorkstationName = "pin压合&视觉检查", // 补充工站名称
ProductModel = productModel,
ProductName = productName,
ProductCode = product1SN, // 主产品编码取产品1SN可根据业务调整
ReworkFlag = reworkFlag,
Automanual = machineModel,
@ -2140,20 +2151,26 @@ namespace RIZO.Admin.WebApi.PLC.Service
/// <returns>PLC生产数据实体</returns>
public async Task<PlcProductionData> ReadOP051ScanDataAsync(Plc plc, string ip, string workstationCode)
{
if (plc == null || !plc.IsConnected) return null;
// 1. 入参校验(强化兜底,更严谨)
if (plc == null || !plc.IsConnected)
{
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] PLC未连接或实例为空无法读取OP051扫码工位数据");
return null;
}
if (string.IsNullOrWhiteSpace(ip)) throw new ArgumentNullException(nameof(ip), "PLC IP地址不能为空");
if (string.IsNullOrWhiteSpace(workstationCode)) throw new ArgumentNullException(nameof(workstationCode), "工位编码不能为空");
try
{
// 1. 批量创建并行读取任务(按类型分类,最大化并行效率
// 2. 批量创建并行读取任务(完全匹配点位表,无多余读取,添加空值兜底
var stringTasks = new Dictionary<string, Task<string>>
{
{ "产品型号", ReadPlcStringAsync(plc, _op051ScanStringMap["产品型号"].Addr, _op051ScanStringMap["产品型号"].Len) },
{ "产品名称", ReadPlcStringAsync(plc, _op051ScanStringMap["产品名称"].Addr, _op051ScanStringMap["产品名称"].Len) },
{ "报警信息", ReadPlcStringAsync(plc, _op051ScanStringMap["报警信息"].Addr, _op051ScanStringMap["报警信息"].Len) },
{ "查询条码", ReadPlcStringAsync(plc, _op051ScanStringMap["SN"].Addr, _op051ScanStringMap["SN"].Len) },
{ "SN_1", ReadPlcStringAsync(plc, _op051ScanStringMap["SN_1"].Addr, _op051ScanStringMap["SN_1"].Len) },
{ "SN_2", ReadPlcStringAsync(plc, _op051ScanStringMap["SN_2"].Addr, _op051ScanStringMap["SN_2"].Len) },
{ "SN_3", ReadPlcStringAsync(plc, _op051ScanStringMap["SN_3"].Addr, _op051ScanStringMap["SN_3"].Len) }
{ "SN_3", ReadPlcStringAsync(plc, _op051ScanStringMap["SN_3"].Addr, _op051ScanStringMap["SN_3"].Len) },
{ "托盘号", ReadPlcStringAsync(plc, _op051ScanStringMap["托盘号"].Addr, _op051ScanStringMap["托盘号"].Len) }
};
var intTasks = new Dictionary<string, Task<int>>
@ -2163,32 +2180,24 @@ namespace RIZO.Admin.WebApi.PLC.Service
{ "设备在线状态", ReadPlcIntAsync(plc, _op051ScanIntMap["设备在线状态"]) },
{ "生产模式", ReadPlcIntAsync(plc, _op051ScanIntMap["生产模式"]) },
{ "查询请求", ReadPlcIntAsync(plc, _op051ScanIntMap["查询请求"]) },
{ "上传结果请求", ReadPlcIntAsync(plc, _op051ScanIntMap["上传结果请求"]) },
{ "托盘号", ReadPlcIntAsync(plc, _op051ScanIntMap["托盘号"]) }
{ "上传结果请求", ReadPlcIntAsync(plc, _op051ScanIntMap["上传结果请求"]) }
};
// DInt双整数读取任务复用ReadPlcIntAsyncPLC底层兼容DInt转int
var dIntReadTasks = new Dictionary<string, Task<int>>
{
{ "实际产量", ReadPlcIntAsync(plc, _op050IntMap["实际产量"]) },
{ "合格数量", ReadPlcIntAsync(plc, _op050IntMap["合格数量"]) },
{ "失败数量", ReadPlcIntAsync(plc, _op050IntMap["失败数量"]) }
};
// 2. 并行等待所有任务完成单次WaitAll最小化等待时间
var allTasks = new List<Task>();
allTasks.AddRange(stringTasks.Values);
allTasks.AddRange(dIntReadTasks.Values);
allTasks.AddRange(intTasks.Values);
// 3. 并行等待所有任务完成最小化等待时间ConfigureAwait(false)提升异步效率)
var allTasks = new List<Task>()
.Concat(stringTasks.Values)
.Concat(intTasks.Values)
.ToList();
await Task.WhenAll(allTasks).ConfigureAwait(false);
// 3. 提取结果(直接取值,空值兜底,减少内存分配)
var now = DateTime.Now; // 单次获取时间,减少系统调用
var productModel = stringTasks["产品型号"].Result;
var productName = stringTasks["产品名称"].Result;
var sn1 = stringTasks["SN_1"].Result;
var sn2 = stringTasks["SN_2"].Result;
var sn3 = stringTasks["SN_3"].Result;
// 4. 提取结果空值兜底避免NullReferenceException简化取值逻辑
var now = DateTime.Now;
var alarmInfo = stringTasks["报警信息"].Result ?? string.Empty;
var querySn = stringTasks["查询条码"].Result ?? string.Empty;
var sn1 = stringTasks["SN_1"].Result ?? string.Empty;
var sn2 = stringTasks["SN_2"].Result ?? string.Empty;
var sn3 = stringTasks["SN_3"].Result ?? string.Empty;
var trayNo = stringTasks["托盘号"].Result ?? string.Empty;
var runStatus = intTasks["运行状态"].Result;
var machineModel = intTasks["设备模式"].Result;
@ -2196,13 +2205,8 @@ namespace RIZO.Admin.WebApi.PLC.Service
var produceModel = intTasks["生产模式"].Result;
var queryRequest = intTasks["查询请求"].Result;
var uploadRequest = intTasks["上传结果请求"].Result;
var trayNo = intTasks["托盘号"].Result.ToString(); // 转换为字符串,适配实体字段
int actualOutput = dIntReadTasks["实际产量"].Result;
int qualifiedQty = dIntReadTasks["合格数量"].Result;
int failedQty = dIntReadTasks["失败数量"].Result;
// 4. 核心逻辑转换(极简表达式,适配扫码工位业务)
// 5. 核心逻辑转换(极简表达式,适配扫码工位业务,注释清晰)
var reworkFlag = produceModel == 4 ? "1" : "0"; // 4=返工模式→1其他→0
var produceModelDesc = produceModel switch
{
@ -2218,18 +2222,15 @@ namespace RIZO.Admin.WebApi.PLC.Service
var uploadRequestDesc = uploadRequest != 0 ? "有上传请求" : "无上传请求";
var qualificationFlag = "1"; // 扫码工位默认合格(无检测结果,可根据业务调整)
// 6. 构建并返回实体(适配扫码工位特性,精简字段)
// 6. 构建并返回实体(完全匹配点位表数据,精简无冗余字段,修正注释错误)
return new PlcProductionData
{
PlcIp = ip,
OccurTime = now,
LineCode = "line2", // 可改为参数传入
LineCode = "line2", // 建议后续改为参数传入,提升方法通用性
WorkstationCode = workstationCode,
WorkstationName = "Coating扫码", // 补充工站名称
ProductModel = productModel,
ProductName = productName,
ProductCode = sn2, // 主SN用SN_1
WorkstationName = "Coating扫码",
ProductCode = sn1, // 修正注释与代码不一致主SN使用SN_1
ReworkFlag = reworkFlag,
Automanual = machineModel,
Runstatus = runStatus,
@ -2242,16 +2243,20 @@ namespace RIZO.Admin.WebApi.PLC.Service
Product2SN = sn2,
Product3SN = sn3,
QualificationFlag = qualificationFlag,
ActualOutQty = actualOutput.ToString(),
QualifiedQty = qualifiedQty.ToString(),
FailedQty = failedQty.ToString(),
CreatedBy = "PLC",
CreatedTime = now,
CreatedTime = now
};
}
catch (KeyNotFoundException ex)
{
// 精准捕获键不存在异常(点位表与读取逻辑不匹配时快速定位)
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] OP051扫码工位读取异常点位表中不存在指定键 -> {ex.Message}");
return null;
}
catch (Exception ex)
{
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] OP051扫码工位读取异常{ex.Message}");
// 通用异常捕获,保留完整异常堆栈便于排查
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] OP051扫码工位读取异常{ex.ToString()}");
return null;
}
}
@ -4750,8 +4755,10 @@ namespace RIZO.Admin.WebApi.PLC.Service
var stringTasks = new Dictionary<string, Task<string>>
{
{ "产品型号", ReadPlcStringAsync(plc, _op115StringMap["产品型号"].Addr, _op115StringMap["产品型号"].Len) },
{ "产品名称", ReadPlcStringAsync(plc, _op115StringMap["产品名称"].Addr, _op115StringMap["产品名称"].Len) }
};
{ "产品名称", ReadPlcStringAsync(plc, _op115StringMap["产品名称"].Addr, _op115StringMap["产品名称"].Len) },
{"查询SN", ReadPlcStringAsync(plc, _op115StringMap["查询SN"].Addr, _op110_3StringMap["查询SN"].Len) },
{ "保存SN", ReadPlcStringAsync(plc, _op115StringMap["保存SN"].Addr, _op110_3StringMap["保存SN"].Len) }
};
var intTasks = new Dictionary<string, Task<int>>
{
@ -4776,6 +4783,8 @@ namespace RIZO.Admin.WebApi.PLC.Service
var machineModel = intTasks["设备模式"].Result;
var onlineStatus = intTasks["设备在线状态"].Result;
var produceModel = intTasks["生产模式"].Result;
var sn1 = stringTasks["查询SN"].Result ?? string.Empty;
var sn2 = stringTasks["保存SN"].Result ?? string.Empty;
// 4. 业务逻辑转换
var reworkFlag = produceModel == 2 ? "1" : "0";
@ -4801,6 +4810,9 @@ namespace RIZO.Admin.WebApi.PLC.Service
WorkstationName = "自动上下料到固化炉工位",
ProductModel = productModel,
ProductName = productName,
ProductCode = sn1,
SN1 = sn1,
SN2 = sn2,
ReworkFlag = reworkFlag,
Automanual = machineModel,
Runstatus = runStatus,
@ -5651,12 +5663,29 @@ namespace RIZO.Admin.WebApi.PLC.Service
{
try
{
if (plcName == "OP020-4" || plcName == "OP050-1")
{
WritePlcValue(plc, _mesop20_4IntReturnMap["保存结果1"], saveResult);
WritePlcValue(plc, _mesop20_4IntReturnMap["保存结果2"], saveResult);
WritePlcValue(plc, _mesop20_4IntReturnMap["保存结果3"], saveResult);
WritePlcValue(plc, _mesop20_4IntReturnMap["保存结果4"], saveResult);
return;
}
if (plcName == "OP050")
{
WritePlcValue(plc, _mesop050IntReturnMap["保存结果1"], saveResult);
WritePlcValue(plc, _mesop050IntReturnMap["保存结果2"], saveResult);
WritePlcValue(plc, _mesop050IntReturnMap["保存结果3"], saveResult);
WritePlcValue(plc, _mesop050IntReturnMap["保存结果4"], saveResult);
return;
}
var targetMap = plcName switch
{
"OP20-3" => _mesop20_3IntReturnMap,
"OP20-4" => _mesop20_4IntReturnMap,
"OP50-1" => _mesop20_4IntReturnMap,
"OP020-3" => _mesop20_3IntReturnMap,
//"OP020-4" => _mesop20_4IntReturnMap,
//"OP050-1" => _mesop20_4IntReturnMap,
//"OP050" => _mesop050IntReturnMap,//四个保存结果
"OP051扫码" => _mesop51ScanIntReturnMap,
"OP058" => _mesop058IntReturnMap,
"OP075" => _mesop075IntReturnMap,
"OP080-1" => _mesop080_1IntReturnMap,

View File

@ -112,6 +112,12 @@ builder.Services.AddLocalization(options => options.ResourcesPath = "");
//PLC进站后台服务注册
//builder.Services.AddHostedService<PlcOutStationService_OP07_01>();
builder.Services.AddHostedService< PlcIntoStationService_OP020_2>();
builder.Services.AddHostedService<PlcIntoStationService_OP020_3>();
builder.Services.AddHostedService<PlcIntoStationService_OP020_4>();
builder.Services.AddHostedService<PlcIntoStationService_OP050>();
builder.Services.AddHostedService<PlcIntoStationService_OP050_1>();
builder.Services.AddHostedService<PlcIntoStationService_OP051Scan>();
builder.Services.AddHostedService<PlcIntoStationService_OP057>();
builder.Services.AddHostedService<PlcIntoStationService_OP058>();
builder.Services.AddHostedService<PlcIntoStationService_OP060>();
@ -120,6 +126,8 @@ builder.Services.AddHostedService<PlcIntoStationService_OP102>();
builder.Services.AddHostedService<PlcIntoStationService_OP110_1>();
builder.Services.AddHostedService<PlcIntoStationService_OP110_2>();
builder.Services.AddHostedService<PlcIntoStationService_OP110_3>();
builder.Services.AddHostedService<PlcIntoStationService_OP115>();
//螺丝枪服务注册
//builder.Services.AddHostedService<PF6ScrewGunService>();

View File

@ -114,7 +114,7 @@
"PlcSettings": [
{
"Id": 1,
"isEnble": false,
"isEnble": true,
"WorkStationCode": "OP020-2",
"WorkStationName": "OP020-2 合盖",
"PlcType": "S71500",
@ -123,13 +123,13 @@
"Heartbeat": "DB1000.DBW0", //
"IntoStationAsk": "DB1001.DBW2000", //
"ProductModel": "DB1001.DBB1000",
"ProductSN": "DB1001.DBB1054",
"IntoStationResp": "DB1000.DBW2002" //
"ProductSN": "DB1001.DBB2106",
"IntoStationResp": "DB1000.DBW2000" //
}
},
{
"Id": 2,
"isEnble": false,
"isEnble": true,
"WorkStationCode": "OP020-3",
"WorkStationName": "OP020-3 热铆",
@ -145,7 +145,7 @@
},
{
"Id": 3,
"isEnble": false,
"isEnble": true,
"WorkStationCode": "OP020-4",
"WorkStationName": "OP020-4 pin压合&视觉检查",
"PlcType": "S71500",
@ -160,22 +160,25 @@
},
{
"Id": 4,
"isEnble": false,
"isEnble": true,
"WorkStationCode": "OP050",
"WorkStationName": "OP050 点白胶DC744",
"PlcType": "S71500",
"IpAddress": "192.168.10.1",
"IntoStation": {
"Heartbeat": "DB300.DBW0", //
"IntoStationAsk": "DB300.DBW42", //
"ProductModel": "DB300.DBB728",
"ProductSN": "DB300.DBB778",
"IntoStationResp": "DB300.DBW46" //
"IntoStationAsk": "DB300.DBW44", //
"ProductModel": "DB300.DBB680",
"ProductSN": "DB300.DBB50",
"IntoStationResp": "DB300.DBW46", //
"IntoStationResp2": "DB300.DBW202",
"IntoStationResp3": "DB300.DBW358",
"IntoStationResp4": "DB300.DBW514"
}
},
{
"Id": 5,
"isEnble": false,
"isEnble": true,
"WorkStationCode": "OP050-1",
"WorkStationName": "OP050-1 自动下料",
"PlcType": "S71500",
@ -190,17 +193,17 @@
},
{
"Id": 41,
"isEnble": false,
"WorkStationCode": "OP51扫码",
"WorkStationName": "OP51扫码 Coating扫码",
"isEnble": true,
"WorkStationCode": "OP051扫码",
"WorkStationName": "OP051扫码 Coating扫码",
"PlcType": "S71500",
"IpAddress": "待定",
"IpAddress": "192.168.0.1",
"IntoStation": {
"Heartbeat": "待定", //
"IntoStationAsk": "待定", //
"Heartbeat": "DB1000.DBW0", //
"IntoStationAsk": "DB1001.DBW320", //
"ProductModel": "待定",
"ProductSN": "待定",
"IntoStationResp": "待定" //
"ProductSN": "DB1001.DBW110",
"IntoStationResp": "DB1000.DBW2" //
}
},
@ -536,16 +539,16 @@
},
{
"Id": 23,
"isEnble": false,
"isEnble": true,
"WorkStationCode": "OP115",
"WorkStationName": "OP115 自动上下料到固化炉",
"PlcType": "S71500",
"IpAddress": "192.168.11.231",
"IpAddress": "192.168.12.11",
"IntoStation": {
"Heartbeat": "DB1000.DBW0", //
"IntoStationAsk": "DB1001.DBW2000", //
"ProductModel": "DB1001.DBB1000",
"ProductSN": "DB1001.DBB1054",
"ProductSN": "DB1001.DBB2100",
"IntoStationResp": "DB1000.DBW2000" //
}
},

View File

@ -44,96 +44,142 @@ namespace RIZO.Service.PLCBackground.Stations.Into
_optionsSetting= options.Value;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.Info("PLC Polling Service started");
// 使用工厂方法创建服务实例
// 获取当前的工序/工站
//WorkstationCode = await Context.Queryable<PlantWorkstation>().Where(it => it.PlcIP == plcSetting.IpAddress)
// .Select(it => it.WorkstationCode).FirstAsync();
plcSetting = _optionsSetting.PlcSettings.Where(it => it.WorkStationCode == WorkstationCode).First();
Enum.TryParse<CpuType>(plcSetting.PlcType, out CpuType cpuType);
if (!plcSetting.isEnble)
try
{
return;
}
using (_plcService = new PlcConntectHepler(plcSetting.IpAddress, cpuType))
{
while (!stoppingToken.IsCancellationRequested)
// 1. 优化:配置查询增加空值判断,避免未找到配置抛出异常
plcSetting = _optionsSetting.PlcSettings
.FirstOrDefault(it => it.WorkStationCode == WorkstationCode);
if (plcSetting == null)
{
try
_logger.Error($"未找到工站 {WorkstationCode} 对应的 PLC 配置,服务退出");
return;
}
// 2. 优化:判断 Enum 解析结果,避免无效 PLC 连接
if (!Enum.TryParse<CpuType>(plcSetting.PlcType, out CpuType cpuType))
{
_logger.Error($"工站 {WorkstationCode} 的 PLC 类型 {plcSetting.PlcType} 解析失败,服务退出");
return;
}
// 配置未启用,直接退出
if (!plcSetting.isEnble)
{
_logger.Info($"工站 {WorkstationCode} 的 PLC 配置未启用,服务退出");
return;
}
// 保持原有 using 语法,确保 PLC 连接资源自动释放
using (_plcService = new PlcConntectHepler(plcSetting.IpAddress, cpuType))
{
while (!stoppingToken.IsCancellationRequested)
{
//心跳检测 "DB1010.DBW0"
// await _plcService.WriteAsync(plcSetting.intoStation.Heartbeat, (short)1);
await _plcService.WriteAsync2(plcSetting.intoStation.Heartbeat, 1);
// 轮询进站请求信号/工位开始查询请求 "DB1001.DBW2000"
short intoStationAsk = await _plcService.ReadAsync<short>(plcSetting.intoStation.IntoStationAsk);
if (intoStationAsk == 1)
try
{
// 处理进站请求
_logger.Info("Processing into station request...");
// 心跳检测
await _plcService.WriteAsync2(plcSetting.intoStation.Heartbeat, 1);
//获取产品SN码 "DB1001.DBB1000"
// string productModel = await _plcService.ReadStringAsync(plcSetting.intoStation.ProductModel);
string productModel = ReadPlcStringAsync(_plcService._plc, plcSetting.intoStation.ProductModel, 48).Result;
//"DB1001.DBB1054"
//string productSN = await _plcService.ReadStringAsync(plcSetting.intoStation.ProductSN);
string productSN = ReadPlcStringAsync(_plcService._plc, plcSetting.intoStation.ProductSN, 48).Result;
// 轮询进站请求信号
short intoStationAsk = await _plcService.ReadAsync<short>(plcSetting.intoStation.IntoStationAsk);
// 获取工单
//获取工艺路线工序
List<ProcessOperation> processOperations = await Context.Queryable<ProcessRouting>().LeftJoin<ProcessOperation>((r, o) => r.RoutingCode == o.FkRoutingCode)
.Where((r, o) => r.FkProductMaterialCode == productModel && r.Status == 1)
.Select((r, o) => o).ToListAsync();
//判断改产品是正常件还是返工件
string Routingcode = processOperations?.First()?.FkRoutingCode ?? "";
//插入入站请求ASK过站记录
ProductPassStationRecord ASKintoStation = new ProductPassStationRecord
if (intoStationAsk > 0)
{
ProductSN = productSN,
WorkstationCode = WorkstationCode,
Routingcode = Routingcode,
OperationCode = WorkstationCode,
OperationName= plcSetting.WorkStationName,
ProductionLifeStage = 1, // 1表示生产中
PasstationType = 0, // 0表示入站请求
PasstationDescription = "入站请求ASK",
EffectTime = DateTime.Now,
CreatedTime = DateTime.Now,
};
await Context.Insertable(ASKintoStation).ExecuteCommandAsync();
//判断该产品是否允许进站
EntryPermissionResult result = await checkEntryPermission(productModel, productSN, WorkstationCode, processOperations);
// "DB1010.DBW2000"
// await _plcService.WriteAsync(plcSetting.intoStation.IntoStationResp, (short)result);
await _plcService.WriteAsync2(plcSetting.intoStation.IntoStationResp,(int) result);
}
await Task.Delay(_pollingInterval, stoppingToken);
_logger.Info("Processing into station request...");
}
catch (OperationCanceledException ex)
{
_logger.Info("PLC Polling Service is stopping");
break;
}
catch (Exception ex)
{
_logger.Error(ex, "PLC polling error");
await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
// 3. 优化:消除 Task.Result 阻塞,改为异步 await且并行执行两个 PLC 读操作
Task<string> productModelTask = ReadPlcStringAsync(_plcService._plc, plcSetting.intoStation.ProductModel, 48);
Task<string> productSNTask = ReadPlcStringAsync(_plcService._plc, plcSetting.intoStation.ProductSN, 48);
await Task.WhenAll(productModelTask, productSNTask);
string productModel = productModelTask.Result;
string productSN = productSNTask.Result;
string Routingcode = "";
List<ProcessOperation> processOperations = new List<ProcessOperation>();
bool isSkipPermissionCheck = WorkstationCode == "OP051扫码" || WorkstationCode == "OP115";
if (!isSkipPermissionCheck)
{
// 5. 优化:数据库查询传入取消令牌,支持服务快速停止
processOperations = await Context.Queryable<ProcessRouting>()
.LeftJoin<ProcessOperation>((r, o) => r.RoutingCode == o.FkRoutingCode)
.Where((r, o) => r.FkProductMaterialCode == productModel && r.Status == 1)
.Select((r, o) => o)
.ToListAsync(stoppingToken);
Routingcode = processOperations?.FirstOrDefault()?.FkRoutingCode ?? "";
}
// 插入入站请求ASK过站记录保留原有业务逻辑
ProductPassStationRecord ASKintoStation = new ProductPassStationRecord
{
ProductSN = productSN,
WorkstationCode = WorkstationCode,
Routingcode = Routingcode,
OperationCode = WorkstationCode,
OperationName = plcSetting.WorkStationName,
ProductionLifeStage = 1, // 1表示生产中
PasstationType = 0, // 0表示入站请求
PasstationDescription = "入站请求ASK",
EffectTime = DateTime.Now,
CreatedTime = DateTime.Now,
};
await Context.Insertable(ASKintoStation).ExecuteCommandAsync(stoppingToken);
if (!isSkipPermissionCheck)
{
// 判断该产品是否允许进站
EntryPermissionResult result = await checkEntryPermission(productModel, productSN, WorkstationCode, processOperations);
// 6. 优化OP050 的多个写操作并行执行,减少 PLC 通信耗时
var plcWriteTasks = new List<Task>();
plcWriteTasks.Add(_plcService.WriteAsync2(plcSetting.intoStation.IntoStationResp, (int)result));
if (WorkstationCode == "OP050")
{
plcWriteTasks.Add(_plcService.WriteAsync2(plcSetting.intoStation.IntoStationResp2, (int)result));
plcWriteTasks.Add(_plcService.WriteAsync2(plcSetting.intoStation.IntoStationResp3, (int)result));
plcWriteTasks.Add(_plcService.WriteAsync2(plcSetting.intoStation.IntoStationResp4, (int)result));
}
// 并行执行所有写操作,提升 PLC 反馈效率
await Task.WhenAll(plcWriteTasks);
}
else
{
// 直接允许进站
await _plcService.WriteAsync2(plcSetting.intoStation.IntoStationResp, 1);
}
}
// 轮询延迟,保留取消令牌,服务停止时无需等待延迟完成
await Task.Delay(_pollingInterval, stoppingToken);
}
catch (OperationCanceledException)
{
_logger.Info("PLC Polling Service is stopping");
break;
}
catch (Exception ex)
{
_logger.Error(ex, "PLC polling error");
await Task.Delay(10, stoppingToken);
}
}
}
}
_logger.Info("PLC Polling Service stopped");
catch (Exception ex)
{
_logger.Error(ex, "PLC Polling Service encountered fatal error during initialization");
}
finally
{
_logger.Info("PLC Polling Service stopped");
}
}
/// <summary>
@ -196,9 +242,9 @@ namespace RIZO.Service.PLCBackground.Stations.Into
// 2. 清理 OperationCode去除首尾空格 + 移除 \r 等不可见控制字符(兼容你之前的问题)
string cleanOperationCode = LastOperation.OperationCode
.Replace("\r", "") // 移除回车符
.Replace("\n", "") // 可选:移除换行符
.Trim(); // 移除首尾空格
.Replace("\r", "")
.Replace("\n", "")
.Trim();
productSN = productSN.Replace("\r", "").Replace("\n", "").Trim();
// 3. 构建并执行真正的异步查询(补充执行方法,使 await 生效)
var ExistLastOperationRecord = await DbScoped.SugarScope.CopyNew()

View File

@ -29,7 +29,7 @@ namespace RIZO.Service.PLCBackground.Stations.Into
{
public PlcIntoStationService_OP020_2(IOptions<OptionsSetting> options) : base(options)
{
WorkstationCode = "OP020_2";
WorkstationCode = "OP020-2";
}
/// <summary>
@ -38,122 +38,122 @@ namespace RIZO.Service.PLCBackground.Stations.Into
/// <param name="productModel">产品型号</param>
/// <param name="productSN">产品SN</param>
/// <returns></returns>
protected override async Task<EntryPermissionResult> checkEntryPermission(string productModel, string productSN, string workstationCode, List<ProcessOperation> processOperations)
{
//protected override async Task<EntryPermissionResult> checkEntryPermission(string productModel, string productSN, string workstationCode, List<ProcessOperation> processOperations)
//{
EntryPermissionResult result = EntryPermissionResult.UnkownException;
// EntryPermissionResult result = EntryPermissionResult.UnkownException;
//2上工位无记录
// //2上工位无记录
//ProcessOperation LastOperation = processOperations.Where(operation => operation.OperationSeq < processOperations.Where(it => it.OperationCode == workstationCode).Select(it => it.OperationSeq).First()).OrderByDescending(operation => operation.OperationSeq).First();
int LastOperationSeq = processOperations.Where(operation => operation.OperationCode == workstationCode).Select(operation => operation.LastOperationSeq ?? -1).First();
ProcessOperation LastOperation = processOperations.Where(it => it.OperationSeq == LastOperationSeq).First();
bool isExistLastOperationRecord = await DbScoped.SugarScope.CopyNew().Queryable<ProductPassStationRecord>()
.Where(it => it.ProductSN == productSN)
.Where(it => it.OperationCode == LastOperation.OperationCode)
.AnyAsync();
if (!isExistLastOperationRecord)
{
return EntryPermissionResult.NoRecordAtPreviousStation;
}
// //ProcessOperation LastOperation = processOperations.Where(operation => operation.OperationSeq < processOperations.Where(it => it.OperationCode == workstationCode).Select(it => it.OperationSeq).First()).OrderByDescending(operation => operation.OperationSeq).First();
// int LastOperationSeq = processOperations.Where(operation => operation.OperationCode == workstationCode).Select(operation => operation.LastOperationSeq ?? -1).First();
// ProcessOperation LastOperation = processOperations.Where(it => it.OperationSeq == LastOperationSeq).First();
// bool isExistLastOperationRecord = await DbScoped.SugarScope.CopyNew().Queryable<ProductPassStationRecord>()
// .Where(it => it.ProductSN == productSN)
// .Where(it => it.OperationCode == LastOperation.OperationCode)
// .AnyAsync();
// if (!isExistLastOperationRecord)
// {
// return EntryPermissionResult.NoRecordAtPreviousStation;
// }
// 3 上工位NG 入站或者出站结果 NG
bool isExistLastOperationNG = await Context.Queryable<ProductPassStationRecord>()
.Where(it => it.ProductSN == productSN)
.Where(it => it.OperationCode == LastOperation.OperationCode)
.Where(it => it.PasstationType == 2 || it.PasstationType == 4)
.Where(it => it.ResultCode != 1)
.AnyAsync();
if (!isExistLastOperationNG)
{
result = EntryPermissionResult.PreviousStationNG;
goto InsertPassrecord;
}
// // 3 上工位NG 入站或者出站结果 NG
// bool isExistLastOperationNG = await Context.Queryable<ProductPassStationRecord>()
// .Where(it => it.ProductSN == productSN)
// .Where(it => it.OperationCode == LastOperation.OperationCode)
// .Where(it => it.PasstationType == 2 || it.PasstationType == 4)
// .Where(it => it.ResultCode != 1)
// .AnyAsync();
// if (!isExistLastOperationNG)
// {
// result = EntryPermissionResult.PreviousStationNG;
// goto InsertPassrecord;
// }
// 4 扫码产品型号错误
bool isExistproductSN = await Context.Queryable<ProductLifecycle>()
.Where(it => it.ProductSN == productSN).AnyAsync();
// // 4 扫码产品型号错误
// bool isExistproductSN = await Context.Queryable<ProductLifecycle>()
// .Where(it => it.ProductSN == productSN).AnyAsync();
bool isExistproductSNProducting = await Context.Queryable<ProductLifecycle>()
.Where(it => it.ProductSN == productSN && (it.ProductCurrentStatus != 1 && it.ProductCurrentStatus != 3)).AnyAsync();
if (!isExistproductSN || !isExistproductSNProducting)
{
result = EntryPermissionResult.ProductModelError;
goto InsertPassrecord;
}
//6时间超出规定无法生产
// bool isExistproductSNProducting = await Context.Queryable<ProductLifecycle>()
// .Where(it => it.ProductSN == productSN && (it.ProductCurrentStatus != 1 && it.ProductCurrentStatus != 3)).AnyAsync();
// if (!isExistproductSN || !isExistproductSNProducting)
// {
// result = EntryPermissionResult.ProductModelError;
// goto InsertPassrecord;
// }
// //6时间超出规定无法生产
//7固化时间未到规定时间
// //7固化时间未到规定时间
int LastOperationStandardTime = processOperations.Where(operation => operation.OperationCode == LastOperation.OperationCode)
.Select(operation => operation.StandardTime ?? 0).First();
// int LastOperationStandardTime = processOperations.Where(operation => operation.OperationCode == LastOperation.OperationCode)
// .Select(operation => operation.StandardTime ?? 0).First();
if (LastOperationStandardTime > 0)
{
// 上一站的入站时间 和本站的请求时间差值
DateTime LastInStationTime = await Context.Queryable<ProductPassStationRecord>()
.Where(it => it.ProductSN == productSN)
.Where(it => it.OperationCode == LastOperation.OperationCode)
.Where(it => it.PasstationType == 1)
.MaxAsync(it => it.InStationTime ?? DateTime.MinValue);
TimeSpan timeDiff = DateTime.Now - LastInStationTime;
double totalSeconds = timeDiff.TotalSeconds;
if (totalSeconds < LastOperationStandardTime)
{
result = EntryPermissionResult.CuringTimeNotReached;
goto InsertPassrecord;
}
// if (LastOperationStandardTime > 0)
// {
// // 上一站的入站时间 和本站的请求时间差值
// DateTime LastInStationTime = await Context.Queryable<ProductPassStationRecord>()
// .Where(it => it.ProductSN == productSN)
// .Where(it => it.OperationCode == LastOperation.OperationCode)
// .Where(it => it.PasstationType == 1)
// .MaxAsync(it => it.InStationTime ?? DateTime.MinValue);
// TimeSpan timeDiff = DateTime.Now - LastInStationTime;
// double totalSeconds = timeDiff.TotalSeconds;
// if (totalSeconds < LastOperationStandardTime)
// {
// result = EntryPermissionResult.CuringTimeNotReached;
// goto InsertPassrecord;
// }
}
// }
//12 最大重复入站次数
int MaxRepeatEntries = processOperations.Where(operation => operation.OperationCode == workstationCode).Select(operation => operation.MaxStationCount ?? 1).First();
if (MaxRepeatEntries > 1)
{
int currentStationEntryCount = await Context.Queryable<ProductPassStationRecord>()
.Where(it => it.ProductSN == productSN)
.Where(it => it.OperationCode == workstationCode)
.Where(it => it.PasstationType == 1)
.CountAsync();
if (currentStationEntryCount >= MaxRepeatEntries)
{
result = EntryPermissionResult.MaximumRepeatedEntries;
goto InsertPassrecord;
}
}
// //12 最大重复入站次数
// int MaxRepeatEntries = processOperations.Where(operation => operation.OperationCode == workstationCode).Select(operation => operation.MaxStationCount ?? 1).First();
// if (MaxRepeatEntries > 1)
// {
// int currentStationEntryCount = await Context.Queryable<ProductPassStationRecord>()
// .Where(it => it.ProductSN == productSN)
// .Where(it => it.OperationCode == workstationCode)
// .Where(it => it.PasstationType == 1)
// .CountAsync();
// if (currentStationEntryCount >= MaxRepeatEntries)
// {
// result = EntryPermissionResult.MaximumRepeatedEntries;
// goto InsertPassrecord;
// }
// }
//OK 准许进站
result = EntryPermissionResult.AllowIntoStation;
goto InsertPassrecord;
InsertPassrecord:
//插入入站请求Resp过站记录
ProductPassStationRecord RespintoStation = new ProductPassStationRecord
{
ProductSN = productSN,
WorkstationCode = WorkstationCode,
Routingcode = processOperations?.First()?.FkRoutingCode ?? "",
OperationCode = WorkstationCode,
OperationName = plcSetting.WorkStationName,
ProductionLifeStage = 1, // 1表示生产中
PasstationType = 1, // 入站完毕
PasstationDescription = "入站完毕Resp",
EffectTime = DateTime.Now,
InStationTime = DateTime.Now,
ResultCode = (int)result,
ResultDescription = result.ToString(),
CreatedTime = DateTime.Now,
// //OK 准许进站
// result = EntryPermissionResult.AllowIntoStation;
// goto InsertPassrecord;
//InsertPassrecord:
// //插入入站请求Resp过站记录
// ProductPassStationRecord RespintoStation = new ProductPassStationRecord
// {
// ProductSN = productSN,
// WorkstationCode = WorkstationCode,
// Routingcode = processOperations?.First()?.FkRoutingCode ?? "",
// OperationCode = WorkstationCode,
// OperationName = plcSetting.WorkStationName,
// ProductionLifeStage = 1, // 1表示生产中
// PasstationType = 1, // 入站完毕
// PasstationDescription = "入站完毕Resp",
// EffectTime = DateTime.Now,
// InStationTime = DateTime.Now,
// ResultCode = (int)result,
// ResultDescription = result.ToString(),
// CreatedTime = DateTime.Now,
};
await Context.Insertable(RespintoStation).ExecuteCommandAsync();
// };
// await Context.Insertable(RespintoStation).ExecuteCommandAsync();
return result;
}
// return result;
//}
}

View File

@ -29,7 +29,7 @@ namespace RIZO.Service.PLCBackground.Stations.Into
{
public PlcIntoStationService_OP020_3(IOptions<OptionsSetting> options) : base(options)
{
WorkstationCode = "OP020_3";
WorkstationCode = "OP020-3";
}
}

View File

@ -29,7 +29,7 @@ namespace RIZO.Service.PLCBackground.Stations.Into
{
public PlcIntoStationService_OP020_4(IOptions<OptionsSetting> options) : base(options)
{
WorkstationCode = "OP020_4";
WorkstationCode = "OP020-4";
}
}

View File

@ -0,0 +1,37 @@
using Infrastructure.Attribute;
using Infrastructure.Extensions;
using Infrastructure.Model;
using MDM.Model.Plant;
using MDM.Model.Process;
using Microsoft.AspNetCore.JsonPatch.Operations;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using NLog;
using RIZO.Model.Mes;
using RIZO.Model.MES.product_trace;
using RIZO.Repository;
using RIZO.Service.MES.product.IService;
using RIZO.Service.PLC;
using S7.Net;
using SqlSugar.IOC;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace RIZO.Service.PLCBackground.Stations.Into
{
/// <summary>
/// OP点散热胶GF1500
/// </summary>
[AppService(ServiceType = typeof(PlcIntoStationService_OP050_1), ServiceLifetime = LifeTime.Singleton)]
public class PlcIntoStationService_OP050_1 : PlcIntoStationService_Common
{
public PlcIntoStationService_OP050_1(IOptions<OptionsSetting> options) : base(options)
{
WorkstationCode = "OP050-1";
}
}
}

View File

@ -0,0 +1,37 @@
using Infrastructure.Attribute;
using Infrastructure.Extensions;
using Infrastructure.Model;
using MDM.Model.Plant;
using MDM.Model.Process;
using Microsoft.AspNetCore.JsonPatch.Operations;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using NLog;
using RIZO.Model.Mes;
using RIZO.Model.MES.product_trace;
using RIZO.Repository;
using RIZO.Service.MES.product.IService;
using RIZO.Service.PLC;
using S7.Net;
using SqlSugar.IOC;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace RIZO.Service.PLCBackground.Stations.Into
{
/// <summary>
/// OP点散热胶GF1500
/// </summary>
[AppService(ServiceType = typeof(PlcIntoStationService_OP051Scan), ServiceLifetime = LifeTime.Singleton)]
public class PlcIntoStationService_OP051Scan : PlcIntoStationService_Common
{
public PlcIntoStationService_OP051Scan(IOptions<OptionsSetting> options) : base(options)
{
WorkstationCode = "OP051扫码";
}
}
}