2025-01-24 22:42:26 +08:00
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
|
|
|
|
|
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
|
|
|
|
|
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
|
|
|
|
|
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
|
|
|
|
|
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
|
|
|
|
|
// 使用文档:https://thingsgateway.cn/
|
|
|
|
|
|
// QQ群:605534569
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
using MQTTnet;
|
|
|
|
|
|
|
2025-10-18 23:14:55 +08:00
|
|
|
|
using PooledAwait;
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-01-24 22:42:26 +08:00
|
|
|
|
#if NET6_0
|
|
|
|
|
|
using MQTTnet.Client;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
|
|
|
|
|
|
using ThingsGateway.Foundation;
|
|
|
|
|
|
using ThingsGateway.Gateway.Application.Extensions;
|
2025-02-06 12:08:40 +08:00
|
|
|
|
using ThingsGateway.NewLife;
|
2025-01-24 22:42:26 +08:00
|
|
|
|
using ThingsGateway.NewLife.Extension;
|
|
|
|
|
|
using ThingsGateway.NewLife.Json.Extension;
|
|
|
|
|
|
|
|
|
|
|
|
namespace ThingsGateway.Plugin.Mqtt;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// MqttClient
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public partial class MqttCollect : CollectBase
|
|
|
|
|
|
{
|
|
|
|
|
|
private IMqttClient _mqttClient;
|
|
|
|
|
|
|
|
|
|
|
|
private MqttClientOptions _mqttClientOptions;
|
|
|
|
|
|
|
|
|
|
|
|
private MqttClientSubscribeOptions _mqttSubscribeOptions;
|
|
|
|
|
|
|
2025-07-18 17:46:56 +08:00
|
|
|
|
private WaitLock ConnectLock = new(nameof(MqttCollect));
|
2025-01-24 22:42:26 +08:00
|
|
|
|
|
2025-08-12 16:00:53 +00:00
|
|
|
|
#if !Management
|
|
|
|
|
|
|
2025-01-24 22:42:26 +08:00
|
|
|
|
#region mqtt方法
|
|
|
|
|
|
|
|
|
|
|
|
private Task MqttClient_ApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs args)
|
|
|
|
|
|
{
|
|
|
|
|
|
#if NET8_0_OR_GREATER
|
|
|
|
|
|
|
|
|
|
|
|
var payload = args.ApplicationMessage.Payload;
|
|
|
|
|
|
var payloadCount = payload.Length;
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
|
|
var payload = args.ApplicationMessage.PayloadSegment;
|
|
|
|
|
|
var payloadCount = payload.Count;
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
var tuples = TopicItemDict.FirstOrDefault(t => (MqttTopicFilterComparer.Compare(args.ApplicationMessage.Topic, t.Key) == MqttTopicFilterCompareResult.IsMatch)).Value;
|
|
|
|
|
|
if (tuples != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
var payLoad = Encoding.UTF8.GetString(payload);
|
|
|
|
|
|
|
|
|
|
|
|
if (_driverPropertys.DetailLog)
|
|
|
|
|
|
{
|
2025-06-10 15:49:47 +08:00
|
|
|
|
if (LogMessage?.LogLevel <= TouchSocket.Core.LogLevel.Trace)
|
|
|
|
|
|
LogMessage?.LogTrace($"Topic:{args.ApplicationMessage.Topic}{Environment.NewLine}PayLoad:{payLoad}");
|
2025-01-24 22:42:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-06-10 15:49:47 +08:00
|
|
|
|
LogMessage?.LogTrace($"Topic:{args.ApplicationMessage.Topic}");
|
2025-01-24 22:42:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Newtonsoft.Json.Linq.JToken json = Newtonsoft.Json.Linq.JToken.Parse(payLoad);
|
|
|
|
|
|
|
|
|
|
|
|
DateTime dateTime = DateTime.Now;
|
|
|
|
|
|
foreach (var item in tuples)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
if (item.Item2.GetExpressionsResult(json).ToBoolean(true))
|
|
|
|
|
|
{
|
|
|
|
|
|
var jtoken = json.SelectToken(item.Item1);
|
|
|
|
|
|
object value;
|
|
|
|
|
|
if (jtoken is Newtonsoft.Json.Linq.JValue jValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
value = jValue.Value;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
value = jtoken;
|
|
|
|
|
|
}
|
|
|
|
|
|
item.Item3.SetValue(value, dateTime);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
2025-06-10 15:49:47 +08:00
|
|
|
|
LogMessage?.LogTrace($"parse error: topic {Environment.NewLine}{args.ApplicationMessage.Topic} {Environment.NewLine} json {Environment.NewLine}{json} {Environment.NewLine} select: {item.Item1} {Environment.NewLine} {ex}");
|
2025-01-24 22:42:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
2025-06-10 15:49:47 +08:00
|
|
|
|
LogMessage?.LogWarning($"parse error: topic {Environment.NewLine}{args.ApplicationMessage.Topic} {Environment.NewLine} {ex}");
|
2025-01-24 22:42:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
return Task.CompletedTask;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private async Task MqttClient_ConnectedAsync(MqttClientConnectedEventArgs args)
|
|
|
|
|
|
{
|
|
|
|
|
|
//连接成功后订阅相关主题
|
|
|
|
|
|
if (_mqttSubscribeOptions != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
var subResult = await _mqttClient.SubscribeAsync(_mqttSubscribeOptions).ConfigureAwait(false);
|
|
|
|
|
|
if (subResult.Items.Any(a => a.ResultCode > (MqttClientSubscribeResultCode)10))
|
|
|
|
|
|
{
|
|
|
|
|
|
LogMessage?.LogWarning($"Subscribe fail {subResult.Items
|
|
|
|
|
|
.Where(a => a.ResultCode > (MqttClientSubscribeResultCode)10)
|
|
|
|
|
|
.Select(a =>
|
|
|
|
|
|
new
|
|
|
|
|
|
{
|
|
|
|
|
|
Topic = a.TopicFilter.Topic,
|
|
|
|
|
|
ResultCode = a.ResultCode.ToString()
|
|
|
|
|
|
}
|
|
|
|
|
|
)
|
2025-05-20 23:21:58 +08:00
|
|
|
|
.ToSystemTextJsonString()}");
|
2025-01-24 22:42:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-18 23:14:55 +08:00
|
|
|
|
private ValueTask<OperResult> TryMqttClientAsync(CancellationToken cancellationToken)
|
2025-01-24 22:42:26 +08:00
|
|
|
|
{
|
2025-10-18 23:14:55 +08:00
|
|
|
|
if (DisposedValue || _mqttClient == null) return TouchSocket.Core.EasyValueTask.FromResult(new OperResult("MqttClient is disposed"));
|
|
|
|
|
|
|
2025-01-24 22:42:26 +08:00
|
|
|
|
if (_mqttClient?.IsConnected == true)
|
2025-10-18 23:14:55 +08:00
|
|
|
|
return TouchSocket.Core.EasyValueTask.FromResult(OperResult.Success);
|
|
|
|
|
|
return Client(this, cancellationToken);
|
2025-01-24 22:42:26 +08:00
|
|
|
|
|
2025-10-18 23:14:55 +08:00
|
|
|
|
static async PooledValueTask<OperResult> Client(MqttCollect @this, CancellationToken cancellationToken)
|
2025-01-24 22:42:26 +08:00
|
|
|
|
{
|
2025-10-18 23:14:55 +08:00
|
|
|
|
if (@this._mqttClient?.IsConnected == true)
|
2025-01-24 22:42:26 +08:00
|
|
|
|
return OperResult.Success;
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
2025-10-18 23:14:55 +08:00
|
|
|
|
await @this.ConnectLock.WaitAsync(cancellationToken).ConfigureAwait(false);
|
2025-03-09 10:22:05 +08:00
|
|
|
|
await Task.Delay(100, cancellationToken).ConfigureAwait(false);
|
2025-10-18 23:14:55 +08:00
|
|
|
|
if (@this._mqttClient?.IsConnected == true)
|
2025-01-24 22:42:26 +08:00
|
|
|
|
return OperResult.Success;
|
2025-10-18 23:14:55 +08:00
|
|
|
|
using var timeoutToken = new CancellationTokenSource(TimeSpan.FromMilliseconds(@this._driverPropertys.ConnectTimeout));
|
2025-01-24 22:42:26 +08:00
|
|
|
|
using CancellationTokenSource stoppingToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutToken.Token);
|
2025-10-18 23:14:55 +08:00
|
|
|
|
if (@this._mqttClient?.IsConnected == true)
|
2025-01-24 22:42:26 +08:00
|
|
|
|
return OperResult.Success;
|
2025-10-18 23:14:55 +08:00
|
|
|
|
if (@this._mqttClient == null)
|
2025-01-24 22:42:26 +08:00
|
|
|
|
{
|
|
|
|
|
|
return new OperResult("mqttClient is null");
|
|
|
|
|
|
}
|
2025-10-18 23:14:55 +08:00
|
|
|
|
var result = await @this._mqttClient.ConnectAsync(@this._mqttClientOptions, stoppingToken.Token).ConfigureAwait(false);
|
|
|
|
|
|
if (@this._mqttClient.IsConnected)
|
2025-01-24 22:42:26 +08:00
|
|
|
|
{
|
|
|
|
|
|
return OperResult.Success;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if (timeoutToken.IsCancellationRequested)
|
|
|
|
|
|
return new OperResult($"Connect timeout");
|
|
|
|
|
|
else
|
|
|
|
|
|
return new OperResult($"Connect fail {result.ReasonString}");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
return new OperResult(ex);
|
|
|
|
|
|
}
|
|
|
|
|
|
finally
|
|
|
|
|
|
{
|
2025-10-18 23:14:55 +08:00
|
|
|
|
@this.ConnectLock.Release();
|
2025-01-24 22:42:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion mqtt方法
|
2025-08-12 16:00:53 +00:00
|
|
|
|
|
|
|
|
|
|
#endif
|
2025-01-24 22:42:26 +08:00
|
|
|
|
}
|