修复Log不显示的问题,重构了S7BackgroundService中的读取变量的方法
This commit is contained in:
11
App.xaml.cs
11
App.xaml.cs
@@ -28,8 +28,14 @@ public partial class App : Application
|
||||
public App()
|
||||
{
|
||||
Host = Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder()
|
||||
.ConfigureServices((context, services) => { ConfigureServices(services); })
|
||||
.ConfigureLogging(loggingBuilder => { ConfigureLogging(loggingBuilder); })
|
||||
.ConfigureServices((context, services) =>
|
||||
{
|
||||
ConfigureServices(services);
|
||||
})
|
||||
.ConfigureLogging(loggingBuilder =>
|
||||
{
|
||||
ConfigureLogging(loggingBuilder);
|
||||
})
|
||||
.Build();
|
||||
Services = Host.Services;
|
||||
}
|
||||
@@ -85,6 +91,7 @@ public partial class App : Application
|
||||
|
||||
private void ConfigureLogging(ILoggingBuilder loggingBuilder)
|
||||
{
|
||||
LogManager.Setup().LoadConfigurationFromFile("Config/nlog.config");
|
||||
loggingBuilder.ClearProviders();
|
||||
loggingBuilder.SetMinimumLevel(LogLevel.Trace);
|
||||
loggingBuilder.AddNLog();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -66,6 +67,51 @@ namespace PMSWPF.Services
|
||||
_logger.LogInformation("S7 Background Service has stopped.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化或重新连接PLC客户端
|
||||
/// </summary>
|
||||
/// <param name="device">S7设备</param>
|
||||
/// <returns>连接成功的Plc客户端实例,如果连接失败则返回null</returns>
|
||||
private async Task<Plc?> InitializePlcClient(Device device)
|
||||
{
|
||||
// 检查字典中是否已存在该设备的PLC客户端
|
||||
if (!_s7PlcClients.TryGetValue(device.Id, out var plcClient))
|
||||
{
|
||||
// 如果不存在,则创建新的Plc客户端
|
||||
try
|
||||
{
|
||||
plcClient = new Plc(device.CpuType, device.Ip, (short)device.Prot, device.Rack, device.Slot);
|
||||
await plcClient.OpenAsync(); // 尝试打开连接
|
||||
_s7PlcClients[device.Id] = plcClient; // 将新创建的客户端添加到字典
|
||||
_logger.LogInformation($"已连接到S7 PLC: {device.Name} ({device.Ip})");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, $"连接S7 PLC失败: {device.Name} ({device.Ip})");
|
||||
return null; // 连接失败,返回null
|
||||
}
|
||||
}
|
||||
else if (!plcClient.IsConnected)
|
||||
{
|
||||
// 如果存在但未连接,则尝试重新连接
|
||||
try
|
||||
{
|
||||
await plcClient.OpenAsync(); // 尝试重新打开连接
|
||||
_logger.LogInformation($"已重新连接到S7 PLC: {device.Name} ({device.Ip})");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, $"重新连接S7 PLC失败: {device.Name} ({device.Ip})");
|
||||
return null; // 重新连接失败,返回null
|
||||
}
|
||||
}
|
||||
return plcClient; // 返回连接成功的Plc客户端
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 轮询S7设备数据
|
||||
/// </summary>
|
||||
/// <param name="stoppingToken">取消令牌</param>
|
||||
private async Task PollS7Devices(CancellationToken stoppingToken)
|
||||
{
|
||||
if (_s7Devices == null || !_s7Devices.Any())
|
||||
@@ -78,98 +124,72 @@ namespace PMSWPF.Services
|
||||
{
|
||||
if (stoppingToken.IsCancellationRequested) return;
|
||||
|
||||
if (!_s7PlcClients.ContainsKey(device.Id))
|
||||
// 尝试获取或初始化PLC客户端连接
|
||||
var plcClient = await InitializePlcClient(device);
|
||||
if (plcClient == null)
|
||||
{
|
||||
// Initialize Plc client for the device
|
||||
continue; // 如果连接失败,则跳过当前设备
|
||||
}
|
||||
|
||||
|
||||
// 读取设备变量
|
||||
await ReadDeviceVariables(plcClient, device, stoppingToken);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取设备的S7变量并更新其值。
|
||||
/// </summary>
|
||||
/// <param name="plcClient">已连接的Plc客户端实例。</param>
|
||||
/// <param name="device">S7设备。</param>
|
||||
/// <param name="stoppingToken">取消令牌。</param>
|
||||
private async Task ReadDeviceVariables(Plc plcClient, Device device, CancellationToken stoppingToken)
|
||||
{
|
||||
// 过滤出当前设备和S7协议相关的变量
|
||||
var s7Variables = device.VariableTables
|
||||
.Where(vt => vt.ProtocolType == ProtocolType.S7 && vt.IsActive)
|
||||
.SelectMany(vt => vt.DataVariables)
|
||||
.ToList();
|
||||
|
||||
if (!s7Variables.Any())
|
||||
{
|
||||
_logger.LogDebug($"设备 {device.Name} 没有找到活跃的S7变量。");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Stopwatch sw = Stopwatch.StartNew();
|
||||
// 遍历并读取每个S7变量
|
||||
foreach (var variable in s7Variables)
|
||||
{
|
||||
if (stoppingToken.IsCancellationRequested) return; // 如果取消令牌被请求,则停止读取
|
||||
|
||||
try
|
||||
{
|
||||
var plc = new Plc(device.CpuType, device.Ip, (short)device.Prot, device.Rack, device.Slot);
|
||||
await plc.OpenAsync();
|
||||
_s7PlcClients[device.Id] = plc;
|
||||
_logger.LogInformation($"Connected to S7 PLC: {device.Name} ({device.Ip})");
|
||||
// 从PLC读取变量值
|
||||
var value = await plcClient.ReadAsync(variable.S7Address);
|
||||
if (value != null)
|
||||
{
|
||||
// 更新变量的原始数据值和显示值
|
||||
variable.DataValue = value.ToString();
|
||||
variable.DisplayValue = SiemensHelper.ConvertS7Value(value, variable.DataType, variable.Converstion);
|
||||
// _logger.LogDebug($"已读取变量 {variable.Name}: {variable.DataValue}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, $"Failed to connect to S7 PLC: {device.Name} ({device.Ip})");
|
||||
continue;
|
||||
_logger.LogError(ex, $"从设备 {device.Name} 读取变量 {variable.Name} 失败。");
|
||||
}
|
||||
}
|
||||
|
||||
var plcClient = _s7PlcClients[device.Id];
|
||||
if (!plcClient.IsConnected)
|
||||
{
|
||||
try
|
||||
{
|
||||
await plcClient.OpenAsync();
|
||||
_logger.LogInformation($"Reconnected to S7 PLC: {device.Name} ({device.Ip})");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, $"Failed to reconnect to S7 PLC: {device.Name} ({device.Ip})");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Filter variables for the current device and S7 protocol
|
||||
var s7VariablesTemp = device
|
||||
.VariableTables.Where(vd => vd.ProtocolType == ProtocolType.S7 && vd.IsActive)
|
||||
.ToList();
|
||||
|
||||
var s7Variables = s7VariablesTemp.SelectMany(vt => vt.DataVariables)
|
||||
.ToList();
|
||||
// ?.SelectMany(vt => vt.DataVariables)
|
||||
|
||||
|
||||
if (s7Variables == null || !s7Variables.Any())
|
||||
{
|
||||
_logger.LogDebug($"No active S7 variables found for device: {device.Name}");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Batch read variables
|
||||
var addressesToRead = s7Variables.Select(vd => vd.S7Address)
|
||||
.ToList();
|
||||
if (!addressesToRead.Any()) continue;
|
||||
|
||||
try
|
||||
{
|
||||
// S7.Net.Plus library supports ReadMultiple, but it's more complex for different data types.
|
||||
// For simplicity, we'll read them one by one for now, or use a more advanced batch read if all are same type.
|
||||
// A more robust solution would involve grouping by data block and type.
|
||||
|
||||
// Example of reading multiple items (assuming all are of type DWord for simplicity)
|
||||
// This part needs to be refined based on actual variable types and addresses
|
||||
// var dataItems = addressesToRead.Select(addr => new DataItem { DataType = DataType.DataBlock, VarType = VarType.DWord, StringLength = 1, DB = 1, StartByteAdr = 0 }).ToList();
|
||||
// plcClient.ReadMultiple(dataItems);
|
||||
|
||||
foreach (var variable in s7Variables)
|
||||
{
|
||||
if (stoppingToken.IsCancellationRequested) return;
|
||||
try
|
||||
{
|
||||
// This is a simplified read. In a real scenario, you'd parse S7Address
|
||||
// to get DataType, DB, StartByteAdr, BitAdr, etc.
|
||||
// For now, assuming S7Address is directly readable by Read method (e.g., "DB1.DBW0")
|
||||
var value = await plcClient.ReadAsync(variable.S7Address);
|
||||
if (value != null)
|
||||
{
|
||||
// Update the variable's DataValue and DisplayValue
|
||||
variable.DataValue = value.ToString();
|
||||
variable.DisplayValue
|
||||
= SiemensHelper.ConvertS7Value(value, variable.DataType, variable.Converstion);
|
||||
_logger.LogDebug($"Read {variable.Name}: {variable.DataValue}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, $"Failed to read variable {variable.Name} from {device.Name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, $"Error during batch read for device {device.Name}");
|
||||
}
|
||||
sw.Stop();
|
||||
_logger.LogInformation($"从: {device.Name} ({device.Ip})读取变量总耗时:{sw.ElapsedMilliseconds}ms");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, $"设备 {device.Name} 批量读取过程中发生错误。");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user