shgx_tz_mom/ZR.Admin.WebApi/background/SocketBackgroundService.cs
2026-01-06 08:49:12 +08:00

202 lines
8.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using DOAN.ServiceCore.MyMatchPush;
using Infrastructure;
using Infrastructure.Helper;
using Microsoft.Extensions.Logging;
using System.Net.Sockets;
namespace ZR.Admin.WebApi.background
{
public class SocketBackgroundService : BackgroundService
{
private readonly SocketGatewayServer _socketGateway;
//private readonly ModbusTcpClientHelper _modbusClient;
private readonly ILogger<SocketBackgroundService> _logger;
// 直接注入包装类无需IServiceProvider无需命名
private readonly ThreeColorLightModbus _threeColorLightModbus;
private readonly AlarmLightModbus _alarmLightModbus;
//public SocketBackgroundService(SocketGatewayServer socketGateway, ILogger<SocketBackgroundService> logger, ModbusTcpClientHelper modbusClient)
//{
// _socketGateway = socketGateway;
// _logger = logger;
// _modbusClient = modbusClient;
//}
public SocketBackgroundService( SocketGatewayServer socketGateway,ILogger<SocketBackgroundService> logger,
ThreeColorLightModbus threeColorLightModbus, // 三色灯实例
AlarmLightModbus alarmLightModbus) // 调漆房实例
{
_socketGateway = socketGateway;
_logger = logger;
_threeColorLightModbus = threeColorLightModbus;
_alarmLightModbus = alarmLightModbus;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
try
{
// 等待服务完全启动
await Task.Delay(1000, stoppingToken);
// 测试Socket推送功能
string strWatchAddress = "181-127-162-058";
var result = Watchup.StartPush("测试Socket推送功能", _socketGateway, strWatchAddress);
_logger.LogInformation($"Socket推送测试结果: {result}");
//TestLight();
TestTiaoQiIOModel();
}
catch (Exception ex)
{
_logger.LogError(ex, "Socket推送测试失败");
}
}
/// <summary>
/// 仅测试与调漆房IO模块的通讯连通性
/// </summary>
private void TestTiaoQiIOModel()
{
// 仅保留通用配置IP/端口不再硬编码复用注入的_modbusClient的配置
const byte MODBUS_SLAVE_ID = 0x01; // 从站地址模块默认1
const int TIMEOUT_LOG_THRESHOLD = 2000; // 超时阈值2秒
try
{
var startTime = DateTime.Now;
bool isCommSuccess = false;
// 尝试读取1个离散输入寄存器DI功能码02- 最简指令,不易出错
try
{
//List<ushort> testValues = _modbusClient.ReadInputRegisters(MODBUS_SLAVE_ID, 0x0000, 1);
List<ushort> testValues = _alarmLightModbus.ReadInputRegisters(MODBUS_SLAVE_ID, 0x0000, 1);
var costTime = (DateTime.Now - startTime).TotalMilliseconds;
// 指令返回非空即代表协议层通讯成功
if (testValues != null && testValues.Count == 1)
{
isCommSuccess = true;
_logger.LogInformation($"✅ IO模块通讯通讯测试成功");
}
else
{
_logger.LogError($"❌ 通讯测试失败MODBUS指令返回空/数量不匹配");
}
}
catch (Exception cmdEx)
{
_logger.LogError(cmdEx, $"❌ 通讯测试失败MODBUS指令执行异常");
}
}
catch (SocketException ex)
{
_logger.LogError(ex, $"❌ TCP连接失败IP/端口错误/模块离线/网段不一致");
}
catch (Exception ex)
{
_logger.LogError(ex, $"❌ IO模块通讯测试异常非TCP层面");
}
}
private void TestLight()
{
// 2. 定义要读取的寄存器信息(根据您的表格)
const byte UNIT_ID = 0x01; // 从站地址,根据您的指令示例是 01
ushort startAddress = 0x0000; // 起始地址,对应 40001
ushort numberOfRegisters = 12; // 要读取的寄存器数量 (40001 到 40012)
// 3. PLC 下发读指令并获取原始寄存器值列表
Console.WriteLine($"正在读取从站 {UNIT_ID} 的寄存器 {startAddress} 开始的 {numberOfRegisters} 个寄存器...");
//List<ushort> registerValues = _modbusClient.ReadHoldingRegisters(UNIT_ID, startAddress, numberOfRegisters);
List<ushort> registerValues = _alarmLightModbus.ReadHoldingRegisters(UNIT_ID, startAddress, numberOfRegisters);
// 4. 解析警灯返回指令(即解析读取到的寄存器值)
if (registerValues.Count == numberOfRegisters)
{
Console.WriteLine("读取成功,解析数据:");
// 创建一个字典或列表来存储解析后的状态
var lightStatus = new Dictionary<string, ushort>
{
{ "红色", registerValues[0] }, // 40001 -> index 0
{ "绿色", registerValues[1] }, // 40002 -> index 1
{ "黄色", registerValues[2] }, // 40003 -> index 2
{ "蓝色", registerValues[3] }, // 40004 -> index 3
{ "白色", registerValues[4] }, // 40005 -> index 4
{ "备用1", registerValues[5] }, // 40006 -> index 5
{ "备用2", registerValues[6] }, // 40007 -> index 6
{ "备用3", registerValues[7] }, // 40008 -> index 7
{ "备用4", registerValues[8] }, // 40009 -> index 8
{ "备用5", registerValues[9] }, // 40010 -> index 9
{ "蜂鸣器", registerValues[10] }, // 40011 -> index 10
{ "电池电量", registerValues[11] } // 40012 -> index 11
};
// 打印解析结果
foreach (var status in lightStatus)
{
Console.WriteLine($"{status.Key}: {status.Value}");
}
// --- 根据业务逻辑解读状态值 ---
// 示例:假设 0=灭/关, 1=闪烁, 2=常亮 (具体含义需查阅设备手册)
InterpretLightStatus(lightStatus);
}
}
/// <summary>
/// 根据业务逻辑解读灯的状态值(这是一个示例,具体值需参考设备手册)
/// </summary>
static void InterpretLightStatus(Dictionary<string, ushort> status)
{
Console.WriteLine("\n--- 状态解读 (示例) ---");
// 红色
switch (status["红色"])
{
case 0: Console.WriteLine("红色: 灭"); break;
case 1: Console.WriteLine("红色: 0.1S 闪烁"); break; // 根据您之前的例子
default: Console.WriteLine($"红色: 未知状态 ({status[""]})"); break;
}
// 绿色
switch (status["绿色"])
{
case 0: Console.WriteLine("绿色: 灭"); break;
case 10: Console.WriteLine("绿色: 1S 闪烁"); break; // 根据您之前的例子 (10 * 0.1S = 1S)
default: Console.WriteLine($"绿色: 未知状态 ({status["绿"]})"); break;
}
// 黄色
switch (status["黄色"])
{
case 0: Console.WriteLine("黄色: 灭"); break;
case 99: Console.WriteLine("黄色: 常亮"); break; // 根据您之前的例子
default: Console.WriteLine($"黄色: 未知状态 ({status[""]})"); break;
}
// 蓝、白
Console.WriteLine($"蓝色: {(status[""] == 0 ? "" : $"({status["蓝色"]})")}");
Console.WriteLine($"白色: {(status[""] == 0 ? "" : $"({status["白色"]})")}");
// 蜂鸣器
switch (status["蜂鸣器"])
{
case 0: Console.WriteLine("蜂鸣器: 静音"); break;
case 10: Console.WriteLine("蜂鸣器: 1S 蜂鸣"); break; // 根据您之前的例子
default: Console.WriteLine($"蜂鸣器: 未知状态 ({status[""]})"); break;
}
// 电池电量
Console.WriteLine($"电池电量: {status[""]}%"); // 假设寄存器值直接代表百分比
}
}
}