From 42e18b5af12f069c9ef084cdeaa4aabb4c7013f9 Mon Sep 17 00:00:00 2001 From: quowingwang Date: Sat, 24 Jan 2026 17:28:23 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=87=E9=9B=86PLC=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PLC/Model/Dto/PlcProductionDataDto.cs | 4 +- .../PLC/Model/PlcProductionData.cs | 6 + .../PLC/Service/PlcHostedService.cs | 6 +- .../PLC/Service/PlcProductionDataService.cs | 80 ++-- RIZO.Admin.WebApi/PLC/Service/PlcService.cs | 379 +++++++++++++----- RIZO.Admin.WebApi/Program.cs | 2 +- RIZO.Admin.WebApi/appsettings.json | 8 - 7 files changed, 329 insertions(+), 156 deletions(-) diff --git a/RIZO.Admin.WebApi/PLC/Model/Dto/PlcProductionDataDto.cs b/RIZO.Admin.WebApi/PLC/Model/Dto/PlcProductionDataDto.cs index 39d2744..f7cdb9d 100644 --- a/RIZO.Admin.WebApi/PLC/Model/Dto/PlcProductionDataDto.cs +++ b/RIZO.Admin.WebApi/PLC/Model/Dto/PlcProductionDataDto.cs @@ -1,6 +1,6 @@ -using MDM.Model; using MiniExcelLibs.Attributes; +using RIZO.Model; using System.ComponentModel.DataAnnotations; namespace RIZO.Admin.WebApi.PLC.Model.Dto @@ -154,6 +154,8 @@ namespace RIZO.Admin.WebApi.PLC.Model.Dto public string? Screw7TightenTime { get; set; } + public string? ChipSN { get; set; } + [ExcelColumn(Name = "运行状态:1=空闲,2=运行中,3=故障;")] diff --git a/RIZO.Admin.WebApi/PLC/Model/PlcProductionData.cs b/RIZO.Admin.WebApi/PLC/Model/PlcProductionData.cs index 43205e0..28161a7 100644 --- a/RIZO.Admin.WebApi/PLC/Model/PlcProductionData.cs +++ b/RIZO.Admin.WebApi/PLC/Model/PlcProductionData.cs @@ -417,5 +417,11 @@ namespace RIZO.Admin.WebApi.PLC.Model [SugarColumn(ColumnName = "Screw7TightenTime")] public string Screw7TightenTime { get; set; } + /// + /// 芯片 SN(PWM 条码) + /// + [SugarColumn(ColumnName = "Screw7TightenTime")] + public string ChipSN { get; set; } + } } \ No newline at end of file diff --git a/RIZO.Admin.WebApi/PLC/Service/PlcHostedService.cs b/RIZO.Admin.WebApi/PLC/Service/PlcHostedService.cs index 78a7d23..7b037d6 100644 --- a/RIZO.Admin.WebApi/PLC/Service/PlcHostedService.cs +++ b/RIZO.Admin.WebApi/PLC/Service/PlcHostedService.cs @@ -26,10 +26,10 @@ namespace RIZO.Admin.WebApi.PLC.Service private readonly ConcurrentDictionary _connectionStateCache; // 可配置参数(建议放到配置文件中,通过IOptions注入) - private readonly int _parallelDegree = 10; // 并行度(20+PLC建议8-12) - private readonly int _pollingIntervalSeconds = 5; // 轮询间隔 + private readonly int _parallelDegree = 15; // 并行度(20+PLC建议8-12) + private readonly double _pollingIntervalSeconds = 0.2; // 轮询间隔 private readonly int _connectTimeoutSeconds = 1; // 单个PLC连接超时时间 - private readonly int _stateCacheExpireSeconds = 10; // 连接状态缓存有效期 + private readonly int _stateCacheExpireSeconds = 5; // 连接状态缓存有效期 private PlantWorkstationService plantWorkstationService = new PlantWorkstationService(); diff --git a/RIZO.Admin.WebApi/PLC/Service/PlcProductionDataService.cs b/RIZO.Admin.WebApi/PLC/Service/PlcProductionDataService.cs index fe74401..1cb6566 100644 --- a/RIZO.Admin.WebApi/PLC/Service/PlcProductionDataService.cs +++ b/RIZO.Admin.WebApi/PLC/Service/PlcProductionDataService.cs @@ -25,26 +25,26 @@ namespace RIZO.Admin.WebApi.PLC.Service { var predicate = QueryExp(parm); #region - if (!string.IsNullOrEmpty(parm.ProductName)) - { - predicate = predicate.And(x => x.ProductName == parm.ProductName); - } - if (!string.IsNullOrEmpty(parm.ProductCode)) - { - predicate = predicate.And(x => x.ProductCode == parm.ProductCode); - } - if (!string.IsNullOrEmpty(parm.ReworkFlag)) - { - predicate = predicate.And(x => x.ReworkFlag == parm.ReworkFlag); - } - if (parm.startTime != null && parm.startTime > DateTime.MinValue) - { - predicate = predicate.And(x => x.CreatedTime >= parm.startTime); - } - if (parm.endTime != null && parm.endTime > DateTime.MinValue) - { - predicate = predicate.And(x => x.CreatedTime <= parm.endTime); - } + //if (!string.IsNullOrEmpty(parm.ProductName)) + //{ + // predicate = predicate.And(x => x.ProductName == parm.ProductName); + //} + //if (!string.IsNullOrEmpty(parm.ProductCode)) + //{ + // predicate = predicate.And(x => x.ProductCode == parm.ProductCode); + //} + //if (!string.IsNullOrEmpty(parm.ReworkFlag)) + //{ + // predicate = predicate.And(x => x.ReworkFlag == parm.ReworkFlag); + //} + //if (parm.startTime != null && parm.startTime > DateTime.MinValue) + //{ + // predicate = predicate.And(x => x.CreatedTime >= parm.startTime); + //} + //if (parm.endTime != null && parm.endTime > DateTime.MinValue) + //{ + // predicate = predicate.And(x => x.CreatedTime <= parm.endTime); + //} #endregion var response = Queryable() .Where(predicate.ToExpression()) @@ -62,26 +62,26 @@ namespace RIZO.Admin.WebApi.PLC.Service { var predicate = QueryExp(parm); #region - if (!string.IsNullOrEmpty(parm.ProductName)) - { - predicate = predicate.And(x => x.ProductName == parm.ProductName); - } - if (!string.IsNullOrEmpty(parm.ProductCode)) - { - predicate = predicate.And(x => x.ProductCode == parm.ProductCode); - } - if (!string.IsNullOrEmpty(parm.ReworkFlag)) - { - predicate = predicate.And(x => x.ReworkFlag == parm.ReworkFlag); - } - if (parm.startTime != null && parm.startTime > DateTime.MinValue) - { - predicate = predicate.And(x => x.CreatedTime >= parm.startTime); - } - if (parm.endTime != null && parm.endTime > DateTime.MinValue) - { - predicate = predicate.And(x => x.CreatedTime <= parm.endTime); - } + //if (!string.IsNullOrEmpty(parm.ProductName)) + //{ + // predicate = predicate.And(x => x.ProductName == parm.ProductName); + //} + //if (!string.IsNullOrEmpty(parm.ProductCode)) + //{ + // predicate = predicate.And(x => x.ProductCode == parm.ProductCode); + //} + //if (!string.IsNullOrEmpty(parm.ReworkFlag)) + //{ + // predicate = predicate.And(x => x.ReworkFlag == parm.ReworkFlag); + //} + //if (parm.startTime != null && parm.startTime > DateTime.MinValue) + //{ + // predicate = predicate.And(x => x.CreatedTime >= parm.startTime); + //} + //if (parm.endTime != null && parm.endTime > DateTime.MinValue) + //{ + // predicate = predicate.And(x => x.CreatedTime <= parm.endTime); + //} #endregion var response = Queryable() .Where(predicate.ToExpression()) diff --git a/RIZO.Admin.WebApi/PLC/Service/PlcService.cs b/RIZO.Admin.WebApi/PLC/Service/PlcService.cs index bcf1a81..4a4d6d0 100644 --- a/RIZO.Admin.WebApi/PLC/Service/PlcService.cs +++ b/RIZO.Admin.WebApi/PLC/Service/PlcService.cs @@ -41,101 +41,130 @@ namespace RIZO.Admin.WebApi.PLC.Service // OP070-1 专属地址映射 private readonly Dictionary _op070_1StringMap = new() { - //{ "报警信息", ("DB1001.DBB58", 48) }, // Array[1..48] of Byte - { "订单名称", ("DB1001.DBB1000", 48) }, // String[48] - { "产品名称", ("DB1001.DBB1054", 48) }, // String[48] - { "产品型号", ("DB1001.DBB2006", 28) }, // String[28] - { "SN_1", ("DB1001.DBB2100", 28) }, // String[28] - { "SN_2", ("DB1001.DBB2134", 28) } // String[28] + //{ "报警信息", ("DB1011.DBB58", 48) }, // Array[1..48] of Byte + { "订单名称", ("DB1011.DBB1000", 48) }, // String[48] + { "产品名称", ("DB1011.DBB1054", 48) }, // String[48] + { "产品型号", ("DB1011.DBB2006", 28) }, // String[28] + { "SN_1", ("DB1011.DBB2100", 28) }, // String[28] + { "SN_2", ("DB1011.DBB2134", 28) } // String[28] }; private readonly Dictionary _op070_1IntMap = new() { - { "运行状态", "DB1001.DBW0" }, // Int - { "设备模式", "DB1001.DBW2" }, // Int - { "设备在线状态", "DB1001.DBW4" }, // Int - { "ByPass", "DB1001.DBW6" }, // Int - { "生产模式", "DB1001.DBW8" }, // Int - { "实际产量", "DB1001.DBD1104" }, // DInt - //{ "合格数量", "DB1001.DBD1108" }, // DInt - //{ "失败数量", "DB1001.DBD1112" }, // DInt - //{ "查询请求", "DB1001.DBW2000" }, // Int - { "保存请求", "DB1001.DBW2002" }, // Int - { "托盘号", "DB1001.DBW2004" }, // Int - { "相机结果", "DB1001.DBW2164" }, // Int - { "站位结果", "DB1001.DBW2166" }, // Int - { "节拍时间", "DB1001.DBD2168" } // Real + { "运行状态", "DB1011.DBW0" }, // Int + { "设备模式", "DB1011.DBW2" }, // Int + { "设备在线状态", "DB1011.DBW4" }, // Int + { "ByPass", "DB1011.DBW6" }, // Int + { "生产模式", "DB1011.DBW8" }, // Int + { "实际产量", "DB1011.DBD1104" }, // DInt + //{ "合格数量", "DB1011.DBD1108" }, // DInt + //{ "失败数量", "DB1011.DBD1112" }, // DInt + { "查询请求", "DB1011.DBW2000" }, // Int + { "保存请求", "DB1011.DBW2002" }, // Int + { "托盘号", "DB1011.DBW2004" }, // Int + { "相机结果", "DB1011.DBW2164" }, // Int + { "站位结果", "DB1011.DBW2166" }, // Int + { "节拍时间", "DB1011.DBD2168" } // Real + }; + + // OP075 专属地址映射 + private readonly Dictionary _op075StringMap = new() + { + //{ "报警信息", ("DB1011.DBB58", 48) }, // Array[1..48] of Byte + { "订单名称", ("DB1011.DBB1000", 48) }, // String[48] + { "产品名称", ("DB1011.DBB1054", 48) }, // String[48] + { "产品型号", ("DB1011.DBB2006", 28) }, // String[28] + { "SN_1", ("DB1011.DBB2100", 28) }, // String[28] + { "SN_2", ("DB1011.DBB2192", 28) }, // String[28] + { "芯片SN", ("DB1011.DBB2222", 28) } // String[28] + }; + + private readonly Dictionary _op075IntMap = new() + { + { "运行状态", "DB1011.DBW0" }, // Int + { "设备模式", "DB1011.DBW2" }, // Int + { "设备在线状态", "DB1011.DBW4" }, // Int + { "ByPass", "DB1011.DBW6" }, // Int + { "生产模式", "DB1011.DBW8" }, // Int + { "实际产量", "DB1011.DBD1104" }, // DInt + //{ "合格数量", "DB1011.DBD1108" }, // DInt + //{ "失败数量", "DB1011.DBD1112" }, // DInt + { "查询请求", "DB1011.DBW2000" }, // Int + { "保存请求", "DB1011.DBW2002" }, // Int + { "托盘号", "DB1011.DBW2004" }, // Int + { "站位结果", "DB1011.DBW2252" }, // Int + { "节拍时间", "DB1011.DBD2284" } // Real }; // OP080-1 专属地址映射 private readonly Dictionary _op080_1StringMap = new() { - //{ "报警信息", ("DB1001.DBB58", 48) }, // Array[1..48] of Byte - { "订单名称", ("DB1001.DBB1000", 48) }, // String[48] - { "产品名称", ("DB1001.DBB1054", 48) }, // String[48] - { "合装位机壳_SN", ("DB1001.DBB2100", 28) }, // String[28] - { "合装位PCB_SN", ("DB1001.DBB2130", 28) }, // String[28] - { "拧紧位机壳_SN", ("DB1001.DBB2904", 28) }, // String[28] - { "拧紧位PCB_SN", ("DB1001.DBB3092", 28) }, // String[28] + //{ "报警信息", ("DB1016.DBB58", 48) }, // Array[1..48] of Byte + { "订单名称", ("DB1016.DBB1000", 48) }, // String[48] + { "产品名称", ("DB1016.DBB1054", 48) }, // String[48] + { "合装位机壳_SN", ("DB1016.DBB2100", 28) }, // String[28] + { "合装位PCB_SN", ("DB1016.DBB2130", 28) }, // String[28] + { "拧紧位机壳_SN", ("DB1016.DBB2904", 28) }, // String[28] + { "拧紧位PCB_SN", ("DB1016.DBB3092", 28) }, // String[28] }; private readonly Dictionary _op080_1IntMap = new() { - { "运行状态", "DB1001.DBW0" }, // Int - { "设备模式", "DB1001.DBW2" }, // Int - { "设备在线状态", "DB1001.DBW4" }, // Int - { "ByPass", "DB1001.DBW6" }, // Int - { "生产模式", "DB1001.DBW8" }, // Int - { "实际产量", "DB1001.DBD1104" }, // DInt - { "合格数量", "DB1001.DBD1108" }, // DInt - { "失败数量", "DB1001.DBD1112" }, // DInt - { "合装工位查询请求", "DB1001.DBW2000" }, // Int - { "合装结果保存请求", "DB1001.DBW2004" }, // Int - { "拧紧结果保存请求", "DB1001.DBW2006" }, // Int - { "合装位托盘号", "DB1001.DBW2100" }, // Int - { "拧紧位托盘号", "DB1001.DBW3152" }, // Int + { "运行状态", "DB1016.DBW0" }, // Int + { "设备模式", "DB1016.DBW2" }, // Int + { "设备在线状态", "DB1016.DBW4" }, // Int + { "ByPass", "DB1016.DBW6" }, // Int + { "生产模式", "DB1016.DBW8" }, // Int + { "实际产量", "DB1016.DBD1104" }, // DInt + { "合格数量", "DB1016.DBD1108" }, // DInt + { "失败数量", "DB1016.DBD1112" }, // DInt + { "合装工位查询请求", "DB1016.DBW2000" }, // Int + { "合装结果保存请求", "DB1016.DBW2004" }, // Int + { "拧紧结果保存请求", "DB1016.DBW2006" }, // Int + { "合装位托盘号", "DB1016.DBW2100" }, // Int + { "拧紧位托盘号", "DB1016.DBW3152" }, // Int // 2号螺钉 - { "2号螺钉_结果", "DB1001.DBW3164" }, // Int - { "2号螺钉_扭矩", "DB1001.DBD3166" }, // Real - { "2号螺钉_深度", "DB1001.DBD3170" }, // Real - { "2号螺钉_角度", "DB1001.DBD3174" }, // Real - { "2号螺钉_拧紧时间", "DB1001.DBD3178" }, // Real + { "2号螺钉_结果", "DB1016.DBW3164" }, // Int + { "2号螺钉_扭矩", "DB1016.DBD3166" }, // Real + { "2号螺钉_深度", "DB1016.DBD3170" }, // Real + { "2号螺钉_角度", "DB1016.DBD3174" }, // Real + { "2号螺钉_拧紧时间", "DB1016.DBD3178" }, // Real // 3号螺钉 - { "3号螺钉_结果", "DB1001.DBW3182" }, // Int - { "3号螺钉_扭矩", "DB1001.DBD3184" }, // Real - { "3号螺钉_深度", "DB1001.DBD3188" }, // Real - { "3号螺钉_角度", "DB1001.DBD3192" }, // Real - { "3号螺钉_拧紧时间", "DB1001.DBD3196" }, // Real + { "3号螺钉_结果", "DB1016.DBW3182" }, // Int + { "3号螺钉_扭矩", "DB1016.DBD3184" }, // Real + { "3号螺钉_深度", "DB1016.DBD3188" }, // Real + { "3号螺钉_角度", "DB1016.DBD3192" }, // Real + { "3号螺钉_拧紧时间", "DB1016.DBD3196" }, // Real // 4号螺钉 - { "4号螺钉_结果", "DB1001.DBW3200" }, // Int - { "4号螺钉_扭矩", "DB1001.DBD3202" }, // Real - { "4号螺钉_深度", "DB1001.DBD3206" }, // Real - { "4号螺钉_角度", "DB1001.DBD3210" }, // Real - { "4号螺钉_拧紧时间", "DB1001.DBD3214" }, // Real + { "4号螺钉_结果", "DB1016.DBW3200" }, // Int + { "4号螺钉_扭矩", "DB1016.DBD3202" }, // Real + { "4号螺钉_深度", "DB1016.DBD3206" }, // Real + { "4号螺钉_角度", "DB1016.DBD3210" }, // Real + { "4号螺钉_拧紧时间", "DB1016.DBD3214" }, // Real // 1号螺钉 - { "1号螺钉_结果", "DB1001.DBW3218" }, // Int - { "1号螺钉_扭矩", "DB1001.DBD3220" }, // Real - { "1号螺钉_深度", "DB1001.DBD3224" }, // Real - { "1号螺钉_角度", "DB1001.DBD3228" }, // Real - { "1号螺钉_拧紧时间", "DB1001.DBD3232" }, // Real + { "1号螺钉_结果", "DB1016.DBW3218" }, // Int + { "1号螺钉_扭矩", "DB1016.DBD3220" }, // Real + { "1号螺钉_深度", "DB1016.DBD3224" }, // Real + { "1号螺钉_角度", "DB1016.DBD3228" }, // Real + { "1号螺钉_拧紧时间", "DB1016.DBD3232" }, // Real // 5号螺钉 - { "5号螺钉_结果", "DB1001.DBW3236" }, // Int - { "5号螺钉_扭矩", "DB1001.DBD3238" }, // Real - { "5号螺钉_深度", "DB1001.DBD3242" }, // Real - { "5号螺钉_角度", "DB1001.DBD3246" }, // Real - { "5号螺钉_拧紧时间", "DB1001.DBD3250" }, // Real + { "5号螺钉_结果", "DB1016.DBW3236" }, // Int + { "5号螺钉_扭矩", "DB1016.DBD3238" }, // Real + { "5号螺钉_深度", "DB1016.DBD3242" }, // Real + { "5号螺钉_角度", "DB1016.DBD3246" }, // Real + { "5号螺钉_拧紧时间", "DB1016.DBD3250" }, // Real // 6号螺钉 - { "6号螺钉_结果", "DB1001.DBW3254" }, // Int - { "6号螺钉_扭矩", "DB1001.DBD3256" }, // Real - { "6号螺钉_深度", "DB1001.DBD3260" }, // Real - { "6号螺钉_角度", "DB1001.DBD3264" }, // Real - { "6号螺钉_拧紧时间", "DB1001.DBD3268" }, // Real + { "6号螺钉_结果", "DB1016.DBW3254" }, // Int + { "6号螺钉_扭矩", "DB1016.DBD3256" }, // Real + { "6号螺钉_深度", "DB1016.DBD3260" }, // Real + { "6号螺钉_角度", "DB1016.DBD3264" }, // Real + { "6号螺钉_拧紧时间", "DB1016.DBD3268" }, // Real // 7号螺钉 - { "7号螺钉_结果", "DB1001.DBW3272" }, // Int - { "7号螺钉_扭矩", "DB1001.DBD3274" }, // Real - { "7号螺钉_深度", "DB1001.DBD3278" }, // Real - { "7号螺钉_角度", "DB1001.DBD3282" }, // Real - { "7号螺钉_拧紧时间", "DB1001.DBD3286" }, // Real + { "7号螺钉_结果", "DB1016.DBW3272" }, // Int + { "7号螺钉_扭矩", "DB1016.DBD3274" }, // Real + { "7号螺钉_深度", "DB1016.DBD3278" }, // Real + { "7号螺钉_角度", "DB1016.DBD3282" }, // Real + { "7号螺钉_拧紧时间", "DB1016.DBD3286" }, // Real }; #endregion @@ -202,18 +231,13 @@ namespace RIZO.Admin.WebApi.PLC.Service plc = CreatePlcClient(cpuType, ip, rack, slot); bool isConnected = false; // for循环替代while,逻辑更直观 - for (int retry = 0; retry < 2; retry++) + try + { + await OpenPlcConnectionAsync(plc); + isConnected = plc.IsConnected; + } + catch { - try - { - await OpenPlcConnectionAsync(plc); - isConnected = plc.IsConnected; - if (isConnected) break; - } - catch - { - if (retry < 1) await Task.Delay(100); // 仅第一次失败后重试 - } } if (!isConnected) @@ -225,20 +249,39 @@ namespace RIZO.Admin.WebApi.PLC.Service // 4. 多工位查询请求标志适配(核心:区分不同工位的寄存器地址) int iQueryRequest = 0; int iSaveRequest = 0; - if (plcName == "OP070-1" || plcName == "OP070-2" || plcName == "OP070-3" || plcName == "OP075") + string strSaveRequest = ""; + if (plcName == "OP070-1" || plcName == "OP070-2" || plcName == "OP070-3") { iQueryRequest = await ReadPlcIntAsync(plc, _op070_1IntMap["查询请求"]); iSaveRequest = await ReadPlcIntAsync(plc, _op070_1IntMap["保存请求"]); } + else if (plcName == "OP075") + { + iQueryRequest = await ReadPlcIntAsync(plc, _op075IntMap["查询请求"]); + iSaveRequest = await ReadPlcIntAsync(plc, _op075IntMap["保存请求"]); + } else if (plcName == "OP080-1") { iQueryRequest = await ReadPlcIntAsync(plc, _op080_1IntMap["合装工位查询请求"]); //考虑一条数据更新两次,还是生成两条数据 int iSaveRequest1 = await ReadPlcIntAsync(plc, _op080_1IntMap["合装结果保存请求"]); int iSaveRequest2 = await ReadPlcIntAsync(plc, _op080_1IntMap["拧紧结果保存请求"]); - if (iSaveRequest1 == 1 || iSaveRequest2 == 1) + if (iSaveRequest1 == 1) { iSaveRequest = 1; + strSaveRequest = "合装结果保存请求"; + } + if (iSaveRequest2 == 1) + { + iSaveRequest = 1; + if (strSaveRequest.Length > 0) + { + strSaveRequest += ",拧紧结果保存请求"; + } + else + { + strSaveRequest = "拧紧结果保存请求"; + } } } // 无效请求直接返回(避免无谓资源消耗) @@ -255,13 +298,19 @@ namespace RIZO.Admin.WebApi.PLC.Service if (iSaveRequest == 1) { // 5. 多工位专属数据读取(预留扩展,逻辑隔离) - if (plcName == "OP070-1" || plcName == "OP070-2" || plcName == "OP070-3" || plcName == "OP075") + if (plcName == "OP070-1" || plcName == "OP070-2" || plcName == "OP070-3") { prodData = await ReadOP070_1DataAsync(plc, ip, plcName); } + else if (plcName == "OP075") + { + prodData = await ReadOP075DataAsync(plc, ip, plcName); + } else if (plcName == "OP080-1" || plcName == "OP080-2") { - prodData = await ReadOP080_1DataAsync(plc, ip, plcName); + int iSaveRequest1 = await ReadPlcIntAsync(plc, _op080_1IntMap["合装结果保存请求"]); + int iSaveRequest2 = await ReadPlcIntAsync(plc, _op080_1IntMap["拧紧结果保存请求"]); + prodData = await ReadOP080_1DataAsync(plc, ip, plcName, strSaveRequest); } // 6. 统一空值兜底(避免空引用) @@ -356,8 +405,14 @@ namespace RIZO.Admin.WebApi.PLC.Service float cycleTime = realFields; // 3. 写入保存请求(异步+增强异常日志) - try { WritePlcValue(plc, _op070_1IntMap["保存请求"], "1"); } - catch (Exception ex) { Console.WriteLine($"OP070-1({ip})写保存请求失败:{ex.Message}"); } + try + { + WritePlcValue(plc, _op070_1IntMap["保存请求"], "0"); + } + catch (Exception ex) + { + Console.WriteLine($"OP070-1({ip})写保存请求失败:{ex.Message}"); + } // 4. 极简条件计算(增强类型安全) var reworkFlag = produceModel == 4 ? "1" : "0"; @@ -409,8 +464,120 @@ namespace RIZO.Admin.WebApi.PLC.Service CreatedTime = DateTime.Now }; } + /// + /// OP075数据读取 + /// + private async Task ReadOP075DataAsync(Plc plc, string ip, string workstationCode) + { + // 1. 批量并行读取所有字段(沿用原有结构+增强型读取方法) + var (strFields, intFields, realFields) = await Task.Run(async () => ( + // 字符串字段(增强空值和异常处理) + ( + //await ReadPlcStringAsync(plc, _op075StringMap["报警信息"].Addr, _op075StringMap["报警信息"].Len), + await ReadPlcStringAsync(plc, _op075StringMap["产品名称"].Addr, _op075StringMap["产品名称"].Len), + await ReadPlcStringAsync(plc, _op075StringMap["订单名称"].Addr, _op075StringMap["订单名称"].Len), + await ReadPlcStringAsync(plc, _op075StringMap["产品型号"].Addr, _op075StringMap["产品型号"].Len), + await ReadPlcStringAsync(plc, _op075StringMap["SN_1"].Addr, _op075StringMap["SN_1"].Len), + await ReadPlcStringAsync(plc, _op075StringMap["SN_2"].Addr, _op075StringMap["SN_2"].Len), + await ReadPlcStringAsync(plc, _op075StringMap["芯片SN"].Addr, _op075StringMap["芯片SN"].Len) + ), + // Int字段(使用增强版ReadPlcIntAsync) + ( + await ReadPlcIntAsync(plc, _op075IntMap["运行状态"]), + await ReadPlcIntAsync(plc, _op075IntMap["设备模式"]), + await ReadPlcIntAsync(plc, _op075IntMap["设备在线状态"]), + await ReadPlcIntAsync(plc, _op075IntMap["ByPass"]), + await ReadPlcIntAsync(plc, _op075IntMap["生产模式"]), + await ReadPlcIntAsync(plc, _op075IntMap["查询请求"]), + await ReadPlcIntAsync(plc, _op075IntMap["保存请求"]), + await ReadPlcIntAsync(plc, _op075IntMap["托盘号"]), + await ReadPlcIntAsync(plc, _op075IntMap["站位结果"]) + ), + // DInt字段(增强版读取方法) + //( + // await ReadPlcDIntAsync(plc, _op075IntMap["实际产量"]), + // await ReadPlcDIntAsync(plc, _op075IntMap["合格数量"]), + // await ReadPlcDIntAsync(plc, _op075IntMap["失败数量"]) + //), + // Real字段(增强版读取方法) + ( + await ReadPlcRealAsync(plc, _op075IntMap["节拍时间"]) + ) + )); - private async Task ReadOP080_1DataAsync(Plc plc, string ip, string workstationCode) + // 2. 解构字段(保持原有逻辑,空值兜底) + var (productName, orderName, productModel, sn1, sn2,chipsn) = strFields; + var (runStatus, machineModel, onlineStatus, byPass, produceModel, queryReq, saveReq, trayNo, stationResult) = intFields; + //var (actualOutput, qualifiedQty, failedQty) = dintFields; + float cycleTime = realFields; + + // 3. 写入保存请求(异步+增强异常日志) + try + { + WritePlcValue(plc, _op075IntMap["保存请求"], "0"); + } + catch (Exception ex) + { + Console.WriteLine($"OP075({ip})写保存请求失败:{ex.Message}"); + } + + // 4. 极简条件计算(增强类型安全) + var reworkFlag = produceModel == 4 ? "1" : "0"; + string produceModelDesc = produceModel switch + { + 1 => "正常模式", + 2 => "清线模式", + 4 => "返工模式", + 8 => "换型模式", + 16 => "预热模式", + _ => $"未知({produceModel})" + }; + string runStatusDesc = runStatus switch { 1 => "空闲", 2 => "运行中", 3 => "故障", _ => $"未知({runStatus})" }; + string onlineStatusDesc = onlineStatus == 1 ? "离线" : "在线"; + //string byPassDesc = byPass == 1 ? "旁路模式" : "正常模式"; + string qualificationFlag = stationResult switch { 1 => "1", 2 => "0", _ => stationResult.ToString() }; + + // 调试日志:输出关键读取结果 + Console.WriteLine($"OP075({ip})读取结果:产品型号={productModel},运行状态={runStatusDesc},订单名称={orderName}"); + + // 5. 构建数据实体(增强空值处理) + return new PlcProductionData + { + PlcIp = ip.Trim(), + OccurTime = DateTime.Now, + LineCode = "line2", + WorkstationCode = workstationCode, + ProductModel = productModel ?? string.Empty, + ProductName = productName ?? string.Empty, + ProductCode = sn2 ?? string.Empty, + SN1 = sn1 ?? string.Empty, + SN2 = sn2 ?? string.Empty, + QualificationFlag = qualificationFlag, + ReworkFlag = reworkFlag, + Automanual = machineModel, + Runstatus = runStatus, + OnlineStatus = onlineStatusDesc, + //ByPass = byPassDesc, + ProduceModel = produceModelDesc, + TrayNo = trayNo.ToString(), + ChipSN = chipsn, + //ActualOutput = actualOutput, + //QualifiedQuantity = qualifiedQty, + //FailedQuantity = failedQty, + ProductionCycle = (int?)cycleTime, + //AlarmMsg = alarmMsg ?? string.Empty, + CreatedBy = "PLC", + CreatedTime = DateTime.Now + }; + } + /// + /// 读取OP080-1数据 + /// + /// + /// + /// + /// + private async Task ReadOP080_1DataAsync(Plc plc, string ip, string workstationCode,string strSaveRequest) { // 1. 批量并行读取所有字段(沿用原有结构+增强型读取方法) var (strFields, intFields, realFields) = await Task.Run(async () => ( @@ -516,16 +683,22 @@ namespace RIZO.Admin.WebApi.PLC.Service screw7Torque, screw7Depth, screw7Angle, screw7Time ) = realFields; - // 3. 写入保存请求(异步+增强异常日志) - //try - //{ - // WritePlcValue(plc, _op080_1IntMap["合装结果保存请求"], "1"); - // WritePlcValue(plc, _op080_1IntMap["拧紧结果保存请 求"], "1"); - //} - //catch (Exception ex) - //{ - // Console.WriteLine($"OP080-1({ip})写保存请求失败:{ex.Message}"); - //} + // 3. 写入保存请求(异步+增强异常日志),收完数据给这个数据位置0 + try + { + if (strSaveRequest.Contains("合装结果保存请求")) + { + WritePlcValue(plc, _op080_1IntMap["合装结果保存请求"], "0"); + } + if (strSaveRequest.Contains("拧紧结果保存请求")) + { + WritePlcValue(plc, _op080_1IntMap["拧紧结果保存请求"], "0"); + } + } + catch (Exception ex) + { + Console.WriteLine($"OP080-1({ip})写保存请求失败:{ex.Message}"); + } // 4. 极简条件计算(增强类型安全) var reworkFlag = produceModel == 4 ? "1" : "0"; diff --git a/RIZO.Admin.WebApi/Program.cs b/RIZO.Admin.WebApi/Program.cs index 4fd5b22..f8f3d61 100644 --- a/RIZO.Admin.WebApi/Program.cs +++ b/RIZO.Admin.WebApi/Program.cs @@ -35,7 +35,7 @@ builder.Services.Configure(builder.Configuration.GetSection("Gl builder.Services.AddSingleton(); builder.Services.AddScoped(); // 新增:注册PLC后台监听服务(项目启动自动执行) -//builder.Services.AddHostedService(); +builder.Services.AddHostedService(); // ========================== // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle diff --git a/RIZO.Admin.WebApi/appsettings.json b/RIZO.Admin.WebApi/appsettings.json index c145c0b..d75ff1c 100644 --- a/RIZO.Admin.WebApi/appsettings.json +++ b/RIZO.Admin.WebApi/appsettings.json @@ -96,14 +96,6 @@ "vuePath": "", //前端代码存储路径eg:D:\Work\RIZOAdmin-Vue3 "uniappPath": "D:\\Work" //h5前端代码存储路径 }, - "PlcConfigs": [ - { - "PlcName": "PLC-1号产线", // 自定义名称,便于识别 - "Ip": "192.168.1.111", - "Rack": 0, - "Slot": 1 - } - ], "GlobalConfig": { "ConnectTimeout": 5000, // 连接超时(毫秒) "ReadWriteTimeout": 5000 // 读写超时(毫秒)