216 lines
6.8 KiB
C#
216 lines
6.8 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using WebApi.Helpers;
|
||
using Logger;
|
||
using System.Reflection;
|
||
using System.Threading;
|
||
|
||
namespace WebApi
|
||
{
|
||
public class MqttServer
|
||
{
|
||
private static string mqttTopic;
|
||
private static string mqttIp;
|
||
private static int mqttPort;
|
||
private static bool isConnected = false;
|
||
private static bool isReconnecting = false;
|
||
private static CancellationTokenSource reconnectCancellation;
|
||
public static event Action<string> ShowMsg; // 记录日志事件
|
||
|
||
public static async Task StartMqttServer()
|
||
{
|
||
try
|
||
{
|
||
reconnectCancellation = new CancellationTokenSource();
|
||
|
||
// 从配置文件读取MQTT配置
|
||
string mqttConfig = Tools.AppConfigManage.ReadConfig("mqttIp");
|
||
if (!string.IsNullOrEmpty(mqttConfig))
|
||
{
|
||
var parts = mqttConfig.Split(',');
|
||
if (parts.Length == 2)
|
||
{
|
||
mqttIp = parts[0];
|
||
mqttPort = Convert.ToInt32(parts[1]);
|
||
}
|
||
}
|
||
|
||
mqttTopic = Tools.AppConfigManage.ReadConfig("mqttTopic");
|
||
|
||
// 注册MQTT事件处理
|
||
Mqtt.ConnectionStatusChanged += OnMqttConnectionStatusChanged;
|
||
//Mqtt.MessageReceived += OnMqttMessageReceived;
|
||
|
||
await ConnectToMqttServer();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.FunError(ex, MethodBase.GetCurrentMethod().Name);
|
||
// 如果首次连接失败,也启动重连
|
||
await StartReconnection();
|
||
}
|
||
}
|
||
|
||
private static async Task ConnectToMqttServer()
|
||
{
|
||
try
|
||
{
|
||
// 连接MQTT服务器
|
||
await Mqtt.RunMqttStart(mqttIp, mqttPort, "", "");
|
||
|
||
// 订阅主题
|
||
if (!string.IsNullOrEmpty(mqttTopic))
|
||
{
|
||
await Mqtt.RunMqttSubscribe(mqttTopic);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.FunError(ex, MethodBase.GetCurrentMethod().Name);
|
||
throw;
|
||
}
|
||
}
|
||
|
||
private static async Task StartReconnection()
|
||
{
|
||
if (isReconnecting) return;
|
||
|
||
try
|
||
{
|
||
isReconnecting = true;
|
||
int retryCount = 0;
|
||
int maxRetryInterval = 10; // 最大重试间隔(秒)
|
||
|
||
while (!isConnected && !reconnectCancellation.Token.IsCancellationRequested)
|
||
{
|
||
try
|
||
{
|
||
retryCount++;
|
||
// 计算重试间隔(指数退避),但不超过最大间隔
|
||
double delaySeconds = Math.Min(Math.Pow(2, retryCount - 1), maxRetryInterval);
|
||
ShowMsg?.Invoke($"MQTT准备重连,{delaySeconds}秒后重试...");
|
||
|
||
await Task.Delay(TimeSpan.FromSeconds(delaySeconds), reconnectCancellation.Token);
|
||
await ConnectToMqttServer();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.FunError(ex, "MQTT重连失败");
|
||
}
|
||
}
|
||
}
|
||
finally
|
||
{
|
||
isReconnecting = false;
|
||
}
|
||
}
|
||
|
||
private static void OnMqttConnectionStatusChanged(bool connected)
|
||
{
|
||
isConnected = connected;
|
||
if (connected)
|
||
{
|
||
ShowMsg?.Invoke($"MQTT已连接到服务器 {mqttIp}:{mqttPort}");
|
||
}
|
||
else
|
||
{
|
||
ShowMsg?.Invoke($"MQTT已断开连接");
|
||
// 启动重连
|
||
Task.Run(StartReconnection);
|
||
}
|
||
}
|
||
|
||
private static void OnMqttMessageReceived(string clientId, string topic, string message)
|
||
{
|
||
try
|
||
{
|
||
ShowMsg?.Invoke($"收到MQTT消息: Topic={topic}, Message={message}");
|
||
// 这里可以添加消息处理逻辑
|
||
if (topic == mqttTopic)
|
||
{
|
||
// 处理特定主题的消息
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.FunError(ex, MethodBase.GetCurrentMethod().Name);
|
||
}
|
||
}
|
||
|
||
public static async Task StopMqttServer()
|
||
{
|
||
try
|
||
{
|
||
// 停止重连
|
||
if (reconnectCancellation != null)
|
||
{
|
||
reconnectCancellation.Cancel();
|
||
reconnectCancellation.Dispose();
|
||
reconnectCancellation = null;
|
||
}
|
||
|
||
// 取消订阅
|
||
if (!string.IsNullOrEmpty(mqttTopic))
|
||
{
|
||
await Mqtt.RunMqttUnSubscribe(mqttTopic);
|
||
}
|
||
|
||
// 断开连接
|
||
await Mqtt.RunMqttStop();
|
||
|
||
// 取消事件注册
|
||
Mqtt.ConnectionStatusChanged -= OnMqttConnectionStatusChanged;
|
||
//Mqtt.MessageReceived -= OnMqttMessageReceived;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.FunError(ex, MethodBase.GetCurrentMethod().Name);
|
||
}
|
||
}
|
||
|
||
public static bool IsConnected()
|
||
{
|
||
return isConnected;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 发送MQTT消息
|
||
/// </summary>
|
||
/// <param name="message">要发送的消息内容到工位</param>
|
||
/// <returns></returns>
|
||
public static async Task<bool> SendMqttMessageToOp(string opName, string type, string value)
|
||
{
|
||
try
|
||
{
|
||
if (!MqttServer.IsConnected())
|
||
{
|
||
ShowMsg?.Invoke("MQTT未连接,无法发送消息");
|
||
return false;
|
||
}
|
||
|
||
string mqttTopic = Tools.AppConfigManage.ReadConfig("mqttTopic");
|
||
if (string.IsNullOrEmpty(mqttTopic))
|
||
{
|
||
ShowMsg?.Invoke("MQTT主题未配置");
|
||
return false;
|
||
}
|
||
string sendMsg = $"MES|{type}|{opName}|{value}";
|
||
// MES/InstantMessaging/PZ126/OP010
|
||
// MES|AGVStatus|OP010|1
|
||
await Mqtt.RunMqttPublish(mqttTopic + opName, sendMsg);
|
||
ShowMsg?.Invoke($"MQTTSend: Topic={mqttTopic}, Message={sendMsg}");
|
||
return true;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.FunError(ex, MethodBase.GetCurrentMethod().Name);
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|