diff --git a/RIZO_Application/Modules/RIZO_Application.Modules.ModuleName/RIZO_Application.Modules.ModuleName.csproj b/RIZO_Application/Modules/RIZO_Application.Modules.ModuleName/RIZO_Application.Modules.ModuleName.csproj
index 2469eda..833d84e 100644
--- a/RIZO_Application/Modules/RIZO_Application.Modules.ModuleName/RIZO_Application.Modules.ModuleName.csproj
+++ b/RIZO_Application/Modules/RIZO_Application.Modules.ModuleName/RIZO_Application.Modules.ModuleName.csproj
@@ -5,6 +5,7 @@
+
diff --git a/RIZO_Application/Modules/RIZO_Application.Modules.ModuleName/ViewModels/MqttControlViewModel.cs b/RIZO_Application/Modules/RIZO_Application.Modules.ModuleName/ViewModels/MqttControlViewModel.cs
index ecde1f4..56f86f7 100644
--- a/RIZO_Application/Modules/RIZO_Application.Modules.ModuleName/ViewModels/MqttControlViewModel.cs
+++ b/RIZO_Application/Modules/RIZO_Application.Modules.ModuleName/ViewModels/MqttControlViewModel.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Text.Json;
using System.Threading.Tasks;
+using System.Windows;
using MQTTnet.Client;
using Prism.Events;
using Prism.Regions;
@@ -17,7 +18,7 @@ namespace RIZO_Application.Modules.ModuleName.ViewModels
private readonly IEventAggregator _eventAggregator;
private MqttHelper? _mqttHelper;
private SubscriptionToken _token;
-
+
public MqttControlViewModel(
IRegionManager regionManager,
IEventAggregator eventAggregator)
@@ -40,7 +41,7 @@ namespace RIZO_Application.Modules.ModuleName.ViewModels
_mqttHelper = new MqttHelper(serverUrl, 1883, clientId);
_mqttHelper.MessageReceived += HandleMqttMessage;
_mqttHelper.ConnectionFailed += HandleMqttConnectionFailed;
-
+ _mqttHelper.Disconnected += Publish;
if (await ConnectMqttAsync())
{
await SubscribeToTopicsAsync();
@@ -81,6 +82,7 @@ namespace RIZO_Application.Modules.ModuleName.ViewModels
{
_eventAggregator.GetEvent().Publish($"订阅:{printTopic}");
}
+
}
private async Task PublishInitialMessageAsync()
@@ -165,7 +167,14 @@ namespace RIZO_Application.Modules.ModuleName.ViewModels
_eventAggregator.GetEvent().Publish($"发布扫描消息时出错: {ex.Message}");
}
}
-
+ public void Publish(string message, int retries, int maxRetries)
+ {
+ _eventAggregator.GetEvent().Publish(message);
+ if (retries>=maxRetries)
+ {
+ MessageBox.Show("MQTT已掉线,请停止扫码");
+ }
+ }
public async void Destroy()
{
_token?.Dispose();
diff --git a/RIZO_Application/Modules/RIZO_Application.Modules.ModuleName/ViewModels/PrintControlViewModel.cs b/RIZO_Application/Modules/RIZO_Application.Modules.ModuleName/ViewModels/PrintControlViewModel.cs
index 1218ccf..78d1529 100644
--- a/RIZO_Application/Modules/RIZO_Application.Modules.ModuleName/ViewModels/PrintControlViewModel.cs
+++ b/RIZO_Application/Modules/RIZO_Application.Modules.ModuleName/ViewModels/PrintControlViewModel.cs
@@ -5,11 +5,9 @@ using Prism.Events;
using Prism.Regions;
using RIZO_Application.Core;
using RIZO_Application.Core.Mvvm;
-using RIZO_Helper.Tools;
using RIZO_Application.Infrastructure.Model;
using System.Linq;
using System.Reflection;
-using Microsoft.Extensions.Primitives;
namespace RIZO_Application.Modules.ModuleName.ViewModels
{
@@ -19,7 +17,6 @@ namespace RIZO_Application.Modules.ModuleName.ViewModels
private readonly BartenderPrintHelper _printHelper;
private SubscriptionToken _printEventToken;
private bool _isDisposed;
-
public PrintControlViewModel(
IRegionManager regionManager,
IEventAggregator eventAggregator,
@@ -120,6 +117,10 @@ namespace RIZO_Application.Modules.ModuleName.ViewModels
subStringValues: Intersect,
copies: 1);
+ //bool printSuccess = barTenderPrinter.PrintLabel(templatePath: printDto.Path,
+ // subStringValues: Intersect,
+ // copies: 1);
+
if (printSuccess)
{
_eventAggregator.GetEvent().Publish($"打印成功: {printDto.Name}");
diff --git a/RIZO_Application/Modules/RIZO_Application.Modules.ModuleName/ViewModels/ScanControlViewModel.cs b/RIZO_Application/Modules/RIZO_Application.Modules.ModuleName/ViewModels/ScanControlViewModel.cs
index 3bff303..0bbf742 100644
--- a/RIZO_Application/Modules/RIZO_Application.Modules.ModuleName/ViewModels/ScanControlViewModel.cs
+++ b/RIZO_Application/Modules/RIZO_Application.Modules.ModuleName/ViewModels/ScanControlViewModel.cs
@@ -10,6 +10,7 @@ using RIZO_Helper.Tools;
using System.Windows;
using System.IO.Ports;
using System.Windows.Documents;
+using System.Management;
namespace RIZO_Application.Modules.ModuleName.ViewModels
{
@@ -21,6 +22,8 @@ namespace RIZO_Application.Modules.ModuleName.ViewModels
private bool _isConnected;
private string _lastLabel;
private DateTime _lastScanTime;
+ private ManagementEventWatcher watcher= new ManagementEventWatcher(new WqlEventQuery(
+ "SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2 OR EventType = 3"));
// 串口连接状态属性
public bool IsConnected
{
@@ -52,11 +55,44 @@ namespace RIZO_Application.Modules.ModuleName.ViewModels
: base(regionManager)
{
+ watcher.EventArrived += new EventArrivedEventHandler(DeviceChanged);
+ watcher.Start();
+
_eventAggregator = eventAggregator;
IsConnected = false; // 初始状态为未连接
InitializeScanHelperAsync().ConfigureAwait(false);
}
+ private void DeviceChanged(object sender, EventArrivedEventArgs e)
+ {
+ // 1. 获取设备变化前的端口列表
+ string[] portsBefore = SerialPort.GetPortNames();
+
+ // 2. 等待系统完成端口更新(重要!)
+ System.Threading.Thread.Sleep(500);
+
+ // 3. 获取设备变化后的端口列表
+ string[] portsAfter = SerialPort.GetPortNames();
+
+ // 4. 检测新增的端口
+ foreach (string port in portsAfter)
+ {
+ if (Array.IndexOf(portsBefore, port) == -1)
+ {
+
+ }
+ }
+
+ // 5. 检测移除的端口
+ foreach (string port in portsBefore)
+ {
+ if (Array.IndexOf(portsAfter, port) == -1)
+ {
+
+ }
+ }
+ }
+
private async Task InitializeScanHelperAsync()
{
try
@@ -69,18 +105,17 @@ namespace RIZO_Application.Modules.ModuleName.ViewModels
}
}
- public async Task StartComScan()
+ public async Task StartComScan(string comName = "COM1",int baudRate = 9600)
{
if (_isDisposed)
throw new ObjectDisposedException(nameof(ScanControlViewModel));
- string comName = "COM1";
- int baudRate = 9600;
- if (SerialConfigs.Current != null)
- {
- comName = SerialConfigs.Current.ComName ?? string.Empty;
- baudRate = SerialConfigs.Current.BaudRate ?? 9600;
- }
+
+ //if (SerialConfigs.Current != null)
+ //{
+ // comName = SerialConfigs.Current.ComName ?? string.Empty;
+ // baudRate = SerialConfigs.Current.BaudRate ?? 9600;
+ //}
_eventAggregator.GetEvent().Publish($"串口扫码枪初始化……串口:{comName} 波特率:{baudRate}");
diff --git a/RIZO_Application/RIZO_Application.Infrastructure/Util/MqttHelper/MqttHelper.cs b/RIZO_Application/RIZO_Application.Infrastructure/Util/MqttHelper/MqttHelper.cs
index c78e372..1edfe7f 100644
--- a/RIZO_Application/RIZO_Application.Infrastructure/Util/MqttHelper/MqttHelper.cs
+++ b/RIZO_Application/RIZO_Application.Infrastructure/Util/MqttHelper/MqttHelper.cs
@@ -13,12 +13,18 @@ namespace RIZO_Helper.Tools
private readonly IMqttClient _mqttClient;
private MqttClientOptions _options;
private bool _isDisposed;
- private readonly SemaphoreSlim _connectionLock = new SemaphoreSlim(1, 1);
+
+ // 用于确保只有一个后台重连任务运行
+ private bool _isReconnecting;
+ private readonly object _reconnectLock = new object();
// 定义消息接收事件
public event EventHandler? MessageReceived;
public event EventHandler? ConnectionFailed;
+ public Action Disconnected;
+
+
public MqttHelper(string server, int port = 1883, string clientId = "wpf-demo", bool cleanSession = true)
{
if (string.IsNullOrEmpty(server))
@@ -37,8 +43,9 @@ namespace RIZO_Helper.Tools
_mqttClient.DisconnectedAsync += async e =>
{
+ Disconnected.Invoke($"MQTT连接断开,原因: {e.Reason}", 0, 1);
Debug.WriteLine($"MQTT连接断开,原因: {e.Reason}");
- await ReconnectWithBackoffAsync();
+ await StartReconnectIfNeededAsync();
};
_mqttClient.ApplicationMessageReceivedAsync += e =>
@@ -58,35 +65,28 @@ namespace RIZO_Helper.Tools
if (_mqttClient.IsConnected)
return true;
- await _connectionLock.WaitAsync(cancellationToken);
+ Debug.WriteLine($"正在连接MQTT服务器: {_options.ChannelOptions}");
+
try
{
- if (_mqttClient.IsConnected)
- return true;
-
- Debug.WriteLine($"正在连接MQTT服务器: {_options.ChannelOptions}");
-
- try
- {
- await _mqttClient.ConnectAsync(_options, cancellationToken);
- Debug.WriteLine("MQTT连接成功");
- return true;
- }
- catch (OperationCanceledException)
- {
- Debug.WriteLine("MQTT连接操作被取消");
- throw;
- }
- catch (Exception ex)
- {
- Debug.WriteLine($"MQTT连接失败: {ex.Message}");
- ConnectionFailed?.Invoke(this, ex);
- return false;
- }
+ await _mqttClient.ConnectAsync(_options, cancellationToken);
+ Debug.WriteLine("MQTT连接成功");
+ return true;
}
- finally
+ catch (OperationCanceledException)
{
- _connectionLock.Release();
+ Debug.WriteLine("MQTT连接操作被取消");
+ throw;
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine($"MQTT连接失败: {ex.Message}");
+ ConnectionFailed?.Invoke(this, ex);
+
+ // 连接失败时启动重连
+ await StartReconnectIfNeededAsync();
+
+ return false;
}
}
@@ -187,6 +187,35 @@ namespace RIZO_Helper.Tools
}
}
+ // 启动重连任务(如果没有正在运行的重连任务)
+ private async Task StartReconnectIfNeededAsync()
+ {
+ if (_isDisposed)
+ return;
+
+ // 使用锁确保只有一个重连任务启动
+ lock (_reconnectLock)
+ {
+ if (_isReconnecting)
+ return;
+
+ _isReconnecting = true;
+ }
+
+ try
+ {
+ await ReconnectWithBackoffAsync();
+ }
+ finally
+ {
+ // 无论重连成功或失败,都标记为重连已完成
+ lock (_reconnectLock)
+ {
+ _isReconnecting = false;
+ }
+ }
+ }
+
private async Task ReconnectWithBackoffAsync()
{
if (_isDisposed)
@@ -198,7 +227,9 @@ namespace RIZO_Helper.Tools
while (retries < maxRetries && !_isDisposed)
{
+ // 指数退避算法,避免频繁重试
int delayMs = baseDelayMs * (int)Math.Pow(2, retries);
+ Disconnected.Invoke($"将在 {delayMs}ms 后尝试重新连接MQTT服务器 (尝试 {retries + 1}/{maxRetries})", retries+1, maxRetries);
Debug.WriteLine($"将在 {delayMs}ms 后尝试重新连接MQTT服务器 (尝试 {retries + 1}/{maxRetries})");
await Task.Delay(delayMs);
@@ -242,7 +273,7 @@ namespace RIZO_Helper.Tools
try
{
// 先取消事件订阅,防止在释放过程中触发事件
- _mqttClient.DisconnectedAsync -= async e => await ReconnectWithBackoffAsync();
+ _mqttClient.DisconnectedAsync -= async e => await StartReconnectIfNeededAsync();
_mqttClient.ApplicationMessageReceivedAsync -= e =>
{
MessageReceived?.Invoke(this, e);
@@ -255,7 +286,6 @@ namespace RIZO_Helper.Tools
// 释放资源
_mqttClient.Dispose();
- _connectionLock.Dispose();
}
catch (Exception ex)
{