diff --git a/Services/MqttBackgroundService.cs b/Services/MqttBackgroundService.cs
index 330d1df..c143430 100644
--- a/Services/MqttBackgroundService.cs
+++ b/Services/MqttBackgroundService.cs
@@ -1,18 +1,11 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.Extensions.Hosting;
+using System.Text;
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Client.Connecting;
using MQTTnet.Client.Disconnecting;
using MQTTnet.Client.Options;
-using PMSWPF.Models;
-using PMSWPF.Services;
using PMSWPF.Helper;
-using PMSWPF.Enums;
+using PMSWPF.Models;
namespace PMSWPF.Services
{
@@ -69,7 +62,7 @@ namespace PMSWPF.Services
_serviceMainThread.Start();
}
- private void Execute()
+ private async void Execute()
{
while (!_stopEvent.WaitOne(0))
{
@@ -81,11 +74,23 @@ namespace PMSWPF.Services
_reloadEvent.WaitOne();
- // 初始加载MQTT配置和变量数据。
- LoadMqttConfigurations();
- ConnectMqttList();
-
- _reloadEvent.Reset();
+ try
+ {
+ // 初始加载MQTT配置和变量数据。
+ var isLoaded = LoadMqttConfigurations();
+ if (isLoaded)
+ {
+ await ConnectMqttList();
+ }
+ }
+ catch (Exception e)
+ {
+ NotificationHelper.ShowError($"Mqt后台服务主程序在加载变量和连接服务器过程中出现了错误:{e.Message} ", e);
+ }
+ finally
+ {
+ _reloadEvent.Reset();
+ }
}
}
@@ -93,7 +98,7 @@ namespace PMSWPF.Services
///
/// 停止MQTT后台服务。
///
- public void StopService()
+ public async Task StopService()
{
NlogHelper.Info("Mqtt后台服务开始停止...."); // 记录服务停止信息
@@ -101,7 +106,7 @@ namespace PMSWPF.Services
// 取消订阅事件。
_dataServices.OnMqttListChanged -= HandleMqttListChanged;
- DisconnecetAll();
+ await DisconnecetAll();
// 清空所有字典。
_mqttClients.Clear();
@@ -110,19 +115,24 @@ namespace PMSWPF.Services
NlogHelper.Info("Mqtt后台服务已停止。"); // 记录服务停止信息
}
- private void DisconnecetAll()
+ private async Task DisconnecetAll()
{
// 断开所有已连接的MQTT客户端。
foreach (var mqttId in _mqttClients.Keys.ToList())
{
- var client = _mqttClients[mqttId];
- var mqtt = _mqttConfigDic[mqttId];
- mqtt.IsConnected = false;
- if (client.IsConnected)
+ try
{
- client.DisconnectAsync()
- .GetAwaiter()
- .GetResult();
+ var client = _mqttClients[mqttId];
+ var mqtt = _mqttConfigDic[mqttId];
+ mqtt.IsConnected = false;
+ if (client.IsConnected)
+ {
+ await client.DisconnectAsync();
+ }
+ }
+ catch (Exception e)
+ {
+ NlogHelper.Error($"MqttID:{mqttId},断开连接的过程中发生了错误:{e.Message}",e);
}
}
}
@@ -132,21 +142,30 @@ namespace PMSWPF.Services
/// 加载并连接MQTT配置。
///
/// 表示异步操作的任务。
- private void LoadMqttConfigurations()
+ private bool LoadMqttConfigurations()
{
- NlogHelper.Info("开始加载Mqtt配置文件...");
- _mqttConfigDic.Clear();
- // 从数据服务获取所有MQTT配置。
- var _mqttConfigList = _dataServices.Mqtts.Where(m => m.IsActive)
- .ToList();
- foreach (var mqtt in _mqttConfigList)
+ try
{
- mqtt.OnMqttIsActiveChanged += OnMqttIsActiveChangedHandler;
- _mqttConfigDic[mqtt.Id] = mqtt;
- mqtt.ConnectMessage = "配置加载成功.";
- }
+ NlogHelper.Info("开始加载Mqtt配置文件...");
+ _mqttConfigDic.Clear();
+ // 从数据服务获取所有MQTT配置。
+ var _mqttConfigList = _dataServices.Mqtts.Where(m => m.IsActive)
+ .ToList();
+ foreach (var mqtt in _mqttConfigList)
+ {
+ mqtt.OnMqttIsActiveChanged += OnMqttIsActiveChangedHandler;
+ _mqttConfigDic[mqtt.Id] = mqtt;
+ mqtt.ConnectMessage = "配置加载成功.";
+ }
- NlogHelper.Info($"Mqtt配置文件加载成功,开启的Mqtt客户端:{_mqttConfigList.Count}个。");
+ NlogHelper.Info($"Mqtt配置文件加载成功,开启的Mqtt客户端:{_mqttConfigList.Count}个。");
+ return true;
+ }
+ catch (Exception e)
+ {
+ NotificationHelper.ShowError($"Mqtt后台服务在加载变量的过程中发生了错误:{e.Message}");
+ return false;
+ }
}
private async void OnMqttIsActiveChangedHandler(Mqtt mqtt)
@@ -159,7 +178,7 @@ namespace PMSWPF.Services
}
else
{
- if (!_mqttClients.TryGetValue(mqtt.Id,out var client))
+ if (!_mqttClients.TryGetValue(mqtt.Id, out var client))
{
NlogHelper.Warn($"没有在Mqtt连接字典中找到名字为:{mqtt.Name}的连接。");
return;
@@ -167,7 +186,7 @@ namespace PMSWPF.Services
if (client.IsConnected)
{
- await client.DisconnectAsync();
+ await client.DisconnectAsync();
}
mqtt.IsConnected = false;
@@ -175,14 +194,12 @@ namespace PMSWPF.Services
_mqttClients.Remove(mqtt.Id);
NlogHelper.Info($"{mqtt.Name}的客户端,与服务器断开连接.");
-
}
}
catch (Exception e)
{
- NotificationHelper.ShowError($"{mqtt.Name}客户端,开启或关闭的过程中发生了错误:{e.Message}",e);
+ NotificationHelper.ShowError($"{mqtt.Name}客户端,开启或关闭的过程中发生了错误:{e.Message}", e);
}
-
}
///
@@ -204,7 +221,7 @@ namespace PMSWPF.Services
continue;
}
- await ConnectMqtt(mqtt);
+ await ConnectMqtt(mqtt);
}
catch (Exception ex)
{
@@ -235,11 +252,11 @@ namespace PMSWPF.Services
client.UseApplicationMessageReceivedHandler(e => { HandleMessageReceived(e, mqtt); });
// 设置断开连接事件处理程序。
- client.UseDisconnectedHandler(async (e) => await HandleDisconnected(e,options, client, mqtt));
+ client.UseDisconnectedHandler(async (e) => await HandleDisconnected(e, options, client, mqtt));
// 尝试连接到MQTT代理。
- await client.ConnectAsync(options, CancellationToken.None);
-
+ await client.ConnectAsync(options, CancellationToken.None);
+
// 将连接成功的客户端添加到字典。
_mqttClients[mqtt.Id] = client;
}
@@ -247,7 +264,7 @@ namespace PMSWPF.Services
private static void HandleMessageReceived(MqttApplicationMessageReceivedEventArgs e, Mqtt mqtt)
{
var topic = e.ApplicationMessage.Topic;
- var payload = System.Text.Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
+ var payload = Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
NlogHelper.Info($"MQTT客户端 {mqtt.Name} 收到消息: 主题={topic}, 消息={payload}");
// 在这里添加处理消息的逻辑
diff --git a/Services/S7BackgroundService.cs b/Services/S7BackgroundService.cs
index b410c3b..99dc928 100644
--- a/Services/S7BackgroundService.cs
+++ b/Services/S7BackgroundService.cs
@@ -1,17 +1,8 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.Extensions.Hosting;
-using Microsoft.Extensions.Logging;
-using S7.Net;
-using PMSWPF.Models;
using PMSWPF.Enums;
using PMSWPF.Helper;
+using PMSWPF.Models;
+using S7.Net;
using S7.Net.Types;
-using SqlSugar;
using DateTime = System.DateTime;
namespace PMSWPF.Services
@@ -39,6 +30,8 @@ namespace PMSWPF.Services
private readonly int S7PollOnceReadMultipleVars = 9;
// S7轮询一遍后的等待时间
private readonly int S7PollOnceSleepTimeMs = 100;
+
+ Dictionary _readVariableDic;
// 轮询数据的线程。
private Thread _pollingThread;
@@ -62,6 +55,7 @@ namespace PMSWPF.Services
_pollVariableDic = new();
_s7PlcClientDic = new();
_variableDic = new();
+ _readVariableDic = new();
// 订阅设备列表变更事件,以便在设备配置更新时重新加载。
_dataServices.OnDeviceListChanged += HandleDeviceListChanged;
}
@@ -116,6 +110,11 @@ namespace PMSWPF.Services
_reloadEvent.Reset();
}
}
+ catch (ThreadInterruptedException tie)
+ {
+ NlogHelper.Error($"S7后台服务主线程关闭。");
+ DisconnectAllPlc();
+ }
catch (Exception e)
{
NlogHelper.Error($"S7后台服务主线程运行中发生了错误:{e.Message}",e);
@@ -134,7 +133,6 @@ namespace PMSWPF.Services
try
{
// Stopwatch sw = Stopwatch.StartNew();
- int varCount = 0;
// 遍历并读取每个S7变量。
foreach (var deviceId in _pollVariableDic.Keys.ToList())
{
@@ -163,7 +161,7 @@ namespace PMSWPF.Services
continue;
}
- Dictionary readVarDic = new Dictionary();
+
foreach (var variable in variableList)
{
@@ -178,38 +176,7 @@ namespace PMSWPF.Services
if ((DateTime.Now - variable.UpdateTime) < interval)
continue; // 未到轮询时间,跳过。
- try
- {
- readVarDic.Add(variable.Id, DataItem.FromAddress(variable.S7Address));
- varCount++;
- if (readVarDic.Count == S7PollOnceReadMultipleVars)
- {
- // 批量读取
- plcClient.ReadMultipleVars(readVarDic.Values.ToList());
- // 批量读取后还原结果
- foreach (var varId in readVarDic.Keys.ToList())
- {
- DataItem dataItem = readVarDic[varId];
- if (!_variableDic.TryGetValue(varId, out var variableData))
- {
- NlogHelper.Warn($"S7后台服务批量读取变量后,还原值,在_variableDic中找不到ID为{varId}的变量");
- continue;
- }
-
- // 更新变量的原始数据值和显示值。
- variableData.DataValue = dataItem.Value.ToString();
- variableData.UpdateTime = DateTime.Now;
- Console.WriteLine($"S7轮询变量:{variableData.Name},值:{variableData.DataValue}");
- }
-
- readVarDic.Clear();
- }
-
- }
- catch (Exception ex)
- {
- NlogHelper.Warn($"从设备 {device.Name} 读取变量 {variable.Name} 失败:{ex.Message}");
- }
+ ReadVariableData(variable, plcClient, device);
}
}
@@ -225,6 +192,11 @@ namespace PMSWPF.Services
NlogHelper.Info("S7后台服务轮询变量结束。");
}
+ catch (ThreadInterruptedException tie)
+ {
+ NlogHelper.Error($"S7后台服务轮询变量线程关闭。");
+ DisconnectAllPlc();
+ }
catch (Exception e)
{
NlogHelper.Error($"S7后台服务轮询变量线程运行中发生了错误:{e.Message}",e);
@@ -232,6 +204,48 @@ namespace PMSWPF.Services
}
}
+ ///
+ /// 读取变量数据
+ ///
+ ///
+ ///
+ ///
+ private void ReadVariableData(VariableData variable,
+ Plc plcClient, Device device)
+ {
+ try
+ {
+ _readVariableDic.Add(variable.Id, DataItem.FromAddress(variable.S7Address));
+ if (_readVariableDic.Count == S7PollOnceReadMultipleVars)
+ {
+ // 批量读取
+ plcClient.ReadMultipleVars(_readVariableDic.Values.ToList());
+ // 批量读取后还原结果
+ foreach (var varId in _readVariableDic.Keys.ToList())
+ {
+ DataItem dataItem = _readVariableDic[varId];
+ if (!_variableDic.TryGetValue(varId, out var variableData))
+ {
+ NlogHelper.Warn($"S7后台服务批量读取变量后,还原值,在_variableDic中找不到ID为{varId}的变量");
+ continue;
+ }
+ // 更新变量的原始数据值和显示值。
+ variableData.DataValue = dataItem.Value.ToString();
+ variableData.UpdateTime = DateTime.Now;
+ Console.WriteLine($"S7轮询变量:{variableData.Name},值:{variableData.DataValue}");
+ }
+
+ _readVariableDic.Clear();
+ }
+
+ }
+ catch (Exception ex)
+ {
+ NlogHelper.Warn($"从设备 {device.Name} 读取变量 {variable.Name} 失败:{ex.Message}");
+ }
+
+ }
+
private void ConnectS7Service()
{
try
@@ -249,14 +263,7 @@ namespace PMSWPF.Services
var plcClient = new Plc(device.CpuType, device.Ip, (short)device.Prot, device.Rack, device.Slot);
plcClient.Open(); // 尝试打开连接。
// 将新创建的客户端添加到字典。
- if (_s7PlcClientDic.ContainsKey(device.Ip))
- {
- _s7PlcClientDic[device.Ip] = plcClient;
- }
- else
- {
- _s7PlcClientDic.Add(device.Ip, plcClient);
- }
+ _s7PlcClientDic[device.Ip] = plcClient;
NotificationHelper.ShowSuccess($"已连接到S7 PLC: {device.Name} ({device.Ip})");
}
@@ -267,6 +274,9 @@ namespace PMSWPF.Services
}
}
+ ///
+ /// 加载变量
+ ///
private void LoadVariables()
{
try
@@ -291,17 +301,9 @@ namespace PMSWPF.Services
.ToList();
// 将变量存储到字典中,方便以后通过ID快速查找
foreach (var s7Variable in s7Variables)
- {
- if (_variableDic.ContainsKey(s7Variable.Id))
- {
- _variableDic[s7Variable.Id] = s7Variable;
- }
- else
- {
- _variableDic.Add(s7Variable.Id, s7Variable);
- }
- }
+ _variableDic[s7Variable.Id] = s7Variable;
+
varCount += s7Variables.Count();
_pollVariableDic.Add(device.Id, s7Variables);
}
@@ -320,28 +322,38 @@ namespace PMSWPF.Services
///
public void StopService()
{
- NlogHelper.Info("S7后台服务正在关闭....");
- _stopEvent.Set();
-
- _pollingThread.Interrupt();
- _serviceMainThread.Interrupt();
- DisconnectAllPlc();
-
- foreach (Device device in _deviceDic.Values.ToList())
+ try
{
- device.IsRuning = false;
+ NlogHelper.Info("S7后台服务正在关闭....");
+ _stopEvent.Set();
+
+ _pollingThread.Interrupt();
+ _serviceMainThread.Interrupt();
+ DisconnectAllPlc();
+
+ foreach (Device device in _deviceDic.Values.ToList())
+ {
+ device.IsRuning = false;
+ }
+ // 关闭事件
+ _reloadEvent.Close();
+ _stopEvent.Reset();
+ _stopEvent.Close();
+ // 清空所有字典。
+ _deviceDic.Clear();
+ _s7PlcClientDic.Clear();
+ _pollVariableDic.Clear();
+ NlogHelper.Info("S7后台服务已关闭");
+ }
+ catch (Exception e)
+ {
+ NlogHelper.Error($"S7后台服务关闭时发生了错误:{e.Message}",e);
}
- // 关闭事件
- _reloadEvent.Close();
- _stopEvent.Reset();
- _stopEvent.Close();
- // 清空所有字典。
- _deviceDic.Clear();
- _s7PlcClientDic.Clear();
- _pollVariableDic.Clear();
- NlogHelper.Info("S7后台服务已关闭");
}
+ ///
+ /// 关闭所有PLC的连接
+ ///
private void DisconnectAllPlc()
{
if (_s7PlcClientDic==null || _s7PlcClientDic.Count == 0)
@@ -349,10 +361,17 @@ namespace PMSWPF.Services
// 关闭所有活跃的PLC连接。
foreach (var plcClient in _s7PlcClientDic.Values.ToList())
{
- if (plcClient.IsConnected)
+ try
{
- plcClient.Close();
- NlogHelper.Info($"关闭S7连接: {plcClient.IP}");
+ if (plcClient.IsConnected)
+ {
+ plcClient.Close();
+ NlogHelper.Info($"关闭S7连接: {plcClient.IP}");
+ }
+ }
+ catch (Exception e)
+ {
+ NlogHelper.Error($"S7后台服务关闭{plcClient.IP},后台连接时发生错误:{e.Message}",e);
}
}
}