122 lines
4.3 KiB
C#
122 lines
4.3 KiB
C#
using Birdmap.BLL.Interfaces;
|
|
using Birdmap.BLL.Services.CommunationServices;
|
|
using Birdmap.BLL.Services.CommunicationServices.Hubs;
|
|
using Microsoft.AspNetCore.SignalR;
|
|
using Microsoft.Extensions.Logging;
|
|
using MQTTnet;
|
|
using MQTTnet.Client;
|
|
using MQTTnet.Client.Connecting;
|
|
using MQTTnet.Client.Disconnecting;
|
|
using MQTTnet.Client.Options;
|
|
using System;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Birdmap.BLL.Services.CommunicationServices.Mqtt
|
|
{
|
|
internal class MqttClientService : CommunicationServiceBase, IMqttClientService
|
|
{
|
|
private readonly IMqttClient _mqttClient;
|
|
private readonly IMqttClientOptions _options;
|
|
|
|
public override bool IsConnected => _mqttClient.IsConnected;
|
|
|
|
public MqttClientService(IMqttClientOptions options, ILogger<MqttClientService> logger, IInputService inputService, IHubContext<DevicesHub, IDevicesHubClient> hubContext)
|
|
: base(logger, inputService, hubContext)
|
|
{
|
|
_options = options;
|
|
|
|
_mqttClient = new MqttFactory().CreateMqttClient();
|
|
ConfigureMqttClient();
|
|
}
|
|
|
|
private void ConfigureMqttClient()
|
|
{
|
|
_mqttClient.ConnectedHandler = this;
|
|
_mqttClient.DisconnectedHandler = this;
|
|
_mqttClient.ApplicationMessageReceivedHandler = this;
|
|
}
|
|
|
|
public Task HandleApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs eventArgs)
|
|
{
|
|
var message = eventArgs.ApplicationMessage.ConvertPayloadToString();
|
|
|
|
_logger.LogDebug($"Recieved [{eventArgs.ClientId}] " +
|
|
$"Topic: {eventArgs.ApplicationMessage.Topic} | Payload: {message} | QoS: {eventArgs.ApplicationMessage.QualityOfServiceLevel} | Retain: {eventArgs.ApplicationMessage.Retain}");
|
|
|
|
return ProcessJsonMessageAsync(message);
|
|
}
|
|
|
|
public async Task HandleConnectedAsync(MqttClientConnectedEventArgs eventArgs)
|
|
{
|
|
try
|
|
{
|
|
var topic = _options.UserProperties.SingleOrDefault(up => up.Name == "Topic")?.Value;
|
|
_logger.LogInformation($"Connected. Auth result: {eventArgs.AuthenticateResult}. Subscribing to topic: {topic}");
|
|
|
|
await _mqttClient.SubscribeAsync(topic);
|
|
StartMessageTimer();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, $"Cannot subscribe...");
|
|
}
|
|
}
|
|
|
|
public async Task HandleDisconnectedAsync(MqttClientDisconnectedEventArgs eventArgs)
|
|
{
|
|
_logger.LogDebug(eventArgs.Exception, $"Disconnected. Reason {eventArgs.ReasonCode}. Auth result: {eventArgs.AuthenticateResult}. Reconnecting...");
|
|
|
|
await Task.Delay(TimeSpan.FromSeconds(5));
|
|
|
|
try
|
|
{
|
|
StopMessageTimer();
|
|
await _mqttClient.ConnectAsync(_options, CancellationToken.None);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogDebug(ex, $"Reconnect failed...");
|
|
}
|
|
}
|
|
|
|
public async Task StartAsync(CancellationToken cancellationToken)
|
|
{
|
|
try
|
|
{
|
|
await _mqttClient.ConnectAsync(_options);
|
|
if (!_mqttClient.IsConnected)
|
|
{
|
|
await _mqttClient.ReconnectAsync();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, $"Cannot connect...");
|
|
}
|
|
}
|
|
|
|
public async Task StopAsync(CancellationToken cancellationToken)
|
|
{
|
|
try
|
|
{
|
|
if (cancellationToken.IsCancellationRequested)
|
|
{
|
|
var disconnectOption = new MqttClientDisconnectOptions
|
|
{
|
|
ReasonCode = MqttClientDisconnectReason.NormalDisconnection,
|
|
ReasonString = "NormalDiconnection"
|
|
};
|
|
await _mqttClient.DisconnectAsync(disconnectOption, cancellationToken);
|
|
}
|
|
await _mqttClient.DisconnectAsync();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, $"Cannot disconnect...");
|
|
}
|
|
}
|
|
}
|
|
}
|