From d832d4e20a9d657d1499de1c64b79e566abd3420 Mon Sep 17 00:00:00 2001 From: quowingwang Date: Thu, 8 Jan 2026 10:57:12 +0800 Subject: [PATCH] =?UTF-8?q?=E5=93=8D=E5=BA=94=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Helper/ModbusTcpClientHelper.cs | 38 +++++++++++++++ ZR.Admin.WebApi/Program.cs | 18 +++++-- ZR.Admin.WebApi/appsettings.development.json | 3 +- .../background/SocketBackgroundService.cs | 6 +-- .../Utils/MyAlarmLigth/TiaoQiFangLight.cs | 48 ++++++++----------- .../mes/andon/AndonAlarmRecordService.cs | 42 ++++++++-------- 6 files changed, 100 insertions(+), 55 deletions(-) diff --git a/Infrastructure/Helper/ModbusTcpClientHelper.cs b/Infrastructure/Helper/ModbusTcpClientHelper.cs index 0610361d..2a17928a 100644 --- a/Infrastructure/Helper/ModbusTcpClientHelper.cs +++ b/Infrastructure/Helper/ModbusTcpClientHelper.cs @@ -89,6 +89,44 @@ namespace Infrastructure.Helper return ParseReadRegistersResponse(response, numberOfRegisters); } + /// + /// 读取离散输入(功能码0x02,对应DI/数字输入端口,如X1-X8) + /// + /// 从站地址 + /// 起始地址(0-based) + /// 离散输入数量 + /// 离散输入状态列表(true=导通/按下,false=断开/未按下) + public List ReadDiscreteInputs(byte unitId, ushort startAddress, ushort numberOfInputs) + { + var request = BuildReadRequest(unitId, 0x02, startAddress, numberOfInputs); + var response = SendAndReceive(request); + return ParseReadDiscreteInputsResponse(response, numberOfInputs); + } + + /// + /// 解析离散输入响应(功能码02,逻辑和读线圈一致) + /// + private List ParseReadDiscreteInputsResponse(byte[] response, ushort expectedCount) + { + // 功能码校验(02=读离散输入) + if (response[7] != 0x02) + throw new Exception($"Modbus异常:功能码={response[7]:X2},预期02"); + + var byteCount = response[8]; + var expectedBytes = (expectedCount + 7) / 8; // 位转字节,向上取整 + if (byteCount != expectedBytes) + throw new Exception($"响应字节数与预期不符:实际={byteCount},预期={expectedBytes}"); + + var discreteInputs = new List(); + for (int i = 0; i < expectedCount; i++) + { + var byteIndex = 9 + i / 8; // 每个字节存8个位 + var bitIndex = i % 8; // 字节内的位索引 + var mask = (byte)(1 << bitIndex); + discreteInputs.Add((response[byteIndex] & mask) != 0); + } + return discreteInputs; + } /// /// 写入单个保持寄存器(功能码0x06) /// diff --git a/ZR.Admin.WebApi/Program.cs b/ZR.Admin.WebApi/Program.cs index c3a8a2d6..bea59cec 100644 --- a/ZR.Admin.WebApi/Program.cs +++ b/ZR.Admin.WebApi/Program.cs @@ -122,7 +122,7 @@ builder.Services.Configure((o) => //手表通知配置 builder.Services.AddSingleton(provider => { - var server = new SocketGatewayServer("192.168.1.56", 8877); // 你可以按需修改 IP 和端口 + var server = new SocketGatewayServer("192.168.60.56", 8877); // 你可以按需修改 IP 和端口 server.Start(); // 项目启动时立即启动监听 //server.StartReceiving(); @@ -144,8 +144,6 @@ builder.Services.AddSingleton(provider => var modbus = new AlarmLightModbus(); modbus.Connect("192.168.60.105", 10001); // 你可以按需修改 IP 和端口 - - return modbus; }); // 2. 注册调漆房灯控监听类 @@ -160,6 +158,20 @@ builder.Services.AddSingleton(provider => return lightListener; }); var app = builder.Build(); +using (var scope = app.Services.CreateScope()) +{ + var serviceProvider = scope.ServiceProvider; + try + { + // 主动获取实例,强制执行上面的工厂方法 + var tiaoQiFangLight = serviceProvider.GetRequiredService(); + app.Logger.LogInformation("调漆房灯控监听已强制启动"); + } + catch (Exception ex) + { + app.Logger.LogError(ex, "调漆房灯控监听启动失败"); + } +} InternalApp.ServiceProvider = app.Services; InternalApp.Configuration = builder.Configuration; InternalApp.WebHostEnvironment = app.Environment; diff --git a/ZR.Admin.WebApi/appsettings.development.json b/ZR.Admin.WebApi/appsettings.development.json index fc981bf8..1e6aba5c 100644 --- a/ZR.Admin.WebApi/appsettings.development.json +++ b/ZR.Admin.WebApi/appsettings.development.json @@ -16,7 +16,8 @@ //外网连接服务器 // "Conn": "Data Source=47.116.122.230;Port=3307;User ID=root;Password=123456;Initial Catalog=ZrAdmin;", //"Conn": "Data Source=139.224.232.211;User ID=root;Password=doantech123;Initial Catalog=ZrAdmin;Port=3308;AllowLoadLocalInfile=true", - "Conn": "Data Source=192.168.1.48;User ID=root;Password=123456;Initial Catalog=ZrAdmin;Port=3306;AllowLoadLocalInfile=true", + //"Conn": "Data Source=192.168.1.48;User ID=root;Password=123456;Initial Catalog=ZrAdmin;Port=3306;AllowLoadLocalInfile=true", + "Conn": "Data Source=127.0.0.1;User ID=root;Password=123456;Initial Catalog=ZrAdmin;Port=3306;AllowLoadLocalInfile=true", // 干巷服务器 // "Conn": "Data Source=192.168.60.251;Port=3306;User ID=root;Password=123456;Initial Catalog=ZrAdmin;", //内网连接服务器 diff --git a/ZR.Admin.WebApi/background/SocketBackgroundService.cs b/ZR.Admin.WebApi/background/SocketBackgroundService.cs index 1732a968..58082ae3 100644 --- a/ZR.Admin.WebApi/background/SocketBackgroundService.cs +++ b/ZR.Admin.WebApi/background/SocketBackgroundService.cs @@ -41,9 +41,9 @@ namespace ZR.Admin.WebApi.background await Task.Delay(1000, stoppingToken); // 测试Socket推送功能 - string strWatchAddress = "181-127-162-058"; - var result = Watchup.StartPush("测试Socket推送功能", _socketGateway, strWatchAddress); - _logger.LogInformation($"Socket推送测试结果: {result}"); + //string strWatchAddress = "181-127-162-058"; + //var result = Watchup.StartPush("测试Socket推送功能", _socketGateway, strWatchAddress); + //_logger.LogInformation($"Socket推送测试结果: {result}"); //TestLight(); TestTiaoQiIOModel(); } diff --git a/ZR.Service/Utils/MyAlarmLigth/TiaoQiFangLight.cs b/ZR.Service/Utils/MyAlarmLigth/TiaoQiFangLight.cs index c3da8c9e..cead249a 100644 --- a/ZR.Service/Utils/MyAlarmLigth/TiaoQiFangLight.cs +++ b/ZR.Service/Utils/MyAlarmLigth/TiaoQiFangLight.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -19,7 +20,7 @@ namespace ZR.Service.Utils.MyAlarmLigth private const int DI_COUNT = 8; // 依赖注入(仅保留核心依赖) - private readonly ModbusTcpClientHelper _modbusClient; + private readonly AlarmLightModbus _modbusClient; private readonly ILogger _logger; // 状态缓存+监听控制(精简命名) @@ -30,7 +31,7 @@ namespace ZR.Service.Utils.MyAlarmLigth /// /// 构造函数(精简参数,日志可选) /// - public TiaoQiFangLight(ModbusTcpClientHelper modbusClient, ILogger logger = null) + public TiaoQiFangLight(AlarmLightModbus modbusClient, ILogger logger = null) { _modbusClient = modbusClient; _logger = logger; @@ -50,7 +51,6 @@ namespace ZR.Service.Utils.MyAlarmLigth _cts = new CancellationTokenSource(); _listenTask = Task.Run(() => ListenDiLoop(_cts.Token), _cts.Token); - _logger?.LogInformation($"✅ 启动X1-X8监听(轮询间隔:{POLLING_INTERVAL_MS}ms)"); } /// @@ -74,43 +74,45 @@ namespace ZR.Service.Utils.MyAlarmLigth { try { - // 1. 读取X1-X8状态(对齐测试代码的ReadInputRegisters写法) - List diValues = _modbusClient.ReadInputRegisters(MODBUS_SLAVE_ID, DI_START_ADDR, DI_COUNT); + // ====== 关键修改:用ReadDiscreteInputs读取DI端口 ====== + List diStates = _modbusClient.ReadDiscreteInputs( + MODBUS_SLAVE_ID, + DI_START_ADDR, + (ushort)DI_COUNT // 转为ushort匹配方法参数 + ); - // 2. 结果校验(精简判断逻辑) - if (diValues == null || diValues.Count != DI_COUNT) + // 结果校验 + if (diStates == null || diStates.Count != DI_COUNT) { - _logger?.LogError($"❌ 读取X1-X8失败:返回值数量异常(预期{DI_COUNT}个,实际{diValues?.Count ?? 0}个)"); await Task.Delay(POLLING_INTERVAL_MS, cancellationToken); continue; } - // 3. 检测状态变化(精简遍历逻辑) for (int i = 0; i < DI_COUNT; i++) { - bool isPressed = diValues[i] == 1; + bool isPressed = diStates[i]; // true=按下,false=未按下 string portName = $"X{i + 1}"; - // 仅“从未按下→按下”时触发(精简条件判断) + // 仅“从未按下→按下”时触发 if (isPressed && !_lastDiState[i]) { - _logger?.LogInformation($"📌 检测到{portName}按下,触发灯控方法"); - TriggerLightMethod(i + 1); // X1=1,直接传端口号 + TriggerLightMethod(i + 1); } - _lastDiState[i] = isPressed; // 更新缓存 } } - // 分类捕获异常(对齐测试代码的异常分类) + catch (OperationCanceledException) + { + _logger?.LogInformation("监听循环被取消,正常退出"); + break; + } catch (Exception cmdEx) { - _logger?.LogError(cmdEx, $"❌ 读取DI状态异常"); } await Task.Delay(POLLING_INTERVAL_MS, cancellationToken); } } - /// /// 触发灯控方法(精简逻辑,仅保留核心映射) /// @@ -124,9 +126,11 @@ namespace ZR.Service.Utils.MyAlarmLigth // X1-X4 → 红灯 case 1: _logger?.LogInformation($"✅ X{portNumber}触发:红灯闪烁"); + _modbusClient.WriteSingleCoil(lightUnitId, 0, true); //0-Y1地址 break; case 2: _logger?.LogInformation($"✅ X{portNumber}触发:红灯闪烁"); + _modbusClient.WriteSingleCoil(lightUnitId, 1, false); break; case 3: _logger?.LogInformation($"✅ X{portNumber}触发:红灯闪烁"); @@ -138,16 +142,6 @@ namespace ZR.Service.Utils.MyAlarmLigth case 5: _logger?.LogInformation($"✅ X{portNumber}触发:绿灯常亮"); break; - // X6-X8 → 黄灯(精简默认逻辑) - case 6: - _logger?.LogInformation($"✅ X{portNumber}触发:黄灯常亮"); - break; - case 7: - _logger?.LogInformation($"✅ X{portNumber}触发:黄灯常亮"); - break; - case 8: - _logger?.LogInformation($"✅ X{portNumber}触发:黄灯常亮"); - break; } } catch (Exception ex) diff --git a/ZR.Service/mes/andon/AndonAlarmRecordService.cs b/ZR.Service/mes/andon/AndonAlarmRecordService.cs index 8e5f6807..3b086aff 100644 --- a/ZR.Service/mes/andon/AndonAlarmRecordService.cs +++ b/ZR.Service/mes/andon/AndonAlarmRecordService.cs @@ -830,27 +830,27 @@ namespace ZR.Service.mes.andon public ApiResult InitAlarmLightStates() { - //var lights = andonAlarmAreaLightDicService.GetList(); - //if (lights.Any()) - //{ - // foreach (var item in lights) - // { - // if (!string.IsNullOrEmpty(item.Lightip)) - // { - // byte bLightIp = Convert.ToByte(item.Lightip); - // if (bLightIp != 0) - // { - // LightUp.CheckLightOnStatusAndTurnOn(_modbusClient, bLightIp); - // } - // } - // } - //} - LightUp.CheckLightOnStatusAndTurnOn(_modbusClient, Convert.ToByte(14)); - LightUp.CheckLightOnStatusAndTurnOn(_modbusClient, Convert.ToByte(08)); - LightUp.CheckLightOnStatusAndTurnOn(_modbusClient, Convert.ToByte(07)); - LightUp.CheckLightOnStatusAndTurnOn(_modbusClient, Convert.ToByte(13)); - LightUp.CheckLightOnStatusAndTurnOn(_modbusClient, Convert.ToByte(04)); - LightUp.CheckLightOnStatusAndTurnOn(_modbusClient, Convert.ToByte(15)); + var lights = andonAlarmAreaLightDicService.GetList(); + if (lights.Any()) + { + foreach (var item in lights) + { + if (!string.IsNullOrEmpty(item.Lightip)) + { + byte bLightIp = Convert.ToByte(item.Lightip); + if (bLightIp != 0) + { + LightUp.CheckLightOnStatusAndTurnOn(_modbusClient, bLightIp); + } + } + } + } + //LightUp.CheckLightOnStatusAndTurnOn(_modbusClient, Convert.ToByte(14)); + //LightUp.CheckLightOnStatusAndTurnOn(_modbusClient, Convert.ToByte(08)); + //LightUp.CheckLightOnStatusAndTurnOn(_modbusClient, Convert.ToByte(07)); + //LightUp.CheckLightOnStatusAndTurnOn(_modbusClient, Convert.ToByte(13)); + //LightUp.CheckLightOnStatusAndTurnOn(_modbusClient, Convert.ToByte(04)); + //LightUp.CheckLightOnStatusAndTurnOn(_modbusClient, Convert.ToByte(15)); return ApiResult.Success("处理成功"); } }