2019-11-17 16:27:58 +00:00
|
|
|
using System;
|
|
|
|
using System.Text;
|
|
|
|
using System.Threading;
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
using Microsoft.Azure.Devices.Client;
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
2020-08-01 15:07:13 +00:00
|
|
|
namespace NucuCar.Telemetry.Publishers
|
2019-11-17 16:27:58 +00:00
|
|
|
{
|
2020-02-08 17:47:44 +00:00
|
|
|
/// <summary>
|
2021-10-03 20:37:53 +00:00
|
|
|
/// Constructs an instance of <see cref="Azure"/>. It is used to publish telemetry to Microsoft
|
2020-02-08 17:47:44 +00:00
|
|
|
/// Azure IotHub
|
|
|
|
/// <remarks>
|
|
|
|
/// The connection string can be found in your Azure IotHub.
|
|
|
|
/// </remarks>
|
|
|
|
/// </summary>
|
2021-10-03 20:37:53 +00:00
|
|
|
public class Azure : BasePublisher
|
2019-11-17 16:27:58 +00:00
|
|
|
{
|
2019-11-23 18:53:04 +00:00
|
|
|
protected readonly DeviceClient DeviceClient;
|
|
|
|
|
2021-10-03 20:37:53 +00:00
|
|
|
public Azure(PublisherOptions opts) : base(opts)
|
2019-11-17 16:27:58 +00:00
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2019-11-23 14:09:44 +00:00
|
|
|
DeviceClient = DeviceClient.CreateFromConnectionString(ConnectionString, TransportType.Mqtt);
|
2019-11-17 16:27:58 +00:00
|
|
|
}
|
|
|
|
catch (FormatException)
|
|
|
|
{
|
2019-11-23 18:53:04 +00:00
|
|
|
Logger?.LogCritical("Can't start telemetry service! Malformed connection string!");
|
2019-11-17 16:27:58 +00:00
|
|
|
throw;
|
|
|
|
}
|
2019-11-23 18:53:04 +00:00
|
|
|
|
2019-12-18 20:57:33 +00:00
|
|
|
Logger?.LogDebug("Initialized the AzureTelemetryPublisher!");
|
2019-11-23 18:53:04 +00:00
|
|
|
}
|
|
|
|
|
2019-11-17 16:27:58 +00:00
|
|
|
public override async Task PublishAsync(CancellationToken cancellationToken)
|
|
|
|
{
|
2019-12-05 20:40:24 +00:00
|
|
|
var data = GetTelemetry();
|
|
|
|
|
|
|
|
var messageString = JsonConvert.SerializeObject(data);
|
2021-08-01 18:01:19 +00:00
|
|
|
Logger?.LogDebug("Telemetry message: {Message}", messageString);
|
2020-02-01 14:50:40 +00:00
|
|
|
var message = new Message(Encoding.UTF8.GetBytes(messageString));
|
2019-12-05 20:40:24 +00:00
|
|
|
|
|
|
|
await PublishToCloudAsync(message, cancellationToken);
|
|
|
|
}
|
|
|
|
|
|
|
|
private async Task PublishToCloudAsync(Message message, CancellationToken cancellationToken, int maxRetries = 3)
|
2019-11-17 16:27:58 +00:00
|
|
|
{
|
2019-12-05 20:40:24 +00:00
|
|
|
var retry = 0;
|
|
|
|
while (retry < maxRetries)
|
2019-11-17 16:27:58 +00:00
|
|
|
{
|
2019-12-05 20:40:24 +00:00
|
|
|
if (cancellationToken.IsCancellationRequested)
|
|
|
|
{
|
|
|
|
Logger?.LogInformation("Publishing telemetry cancelled!");
|
|
|
|
break;
|
|
|
|
}
|
2019-11-23 18:53:04 +00:00
|
|
|
|
2019-12-05 20:40:24 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
var cts = new CancellationTokenSource();
|
|
|
|
cts.CancelAfter(5000);
|
|
|
|
cts.Token.ThrowIfCancellationRequested();
|
|
|
|
|
|
|
|
/* Should throw OperationCanceledException on timeout or cancel. */
|
|
|
|
await DeviceClient.SendEventAsync(message, cts.Token);
|
|
|
|
break;
|
|
|
|
}
|
2019-12-06 22:07:24 +00:00
|
|
|
catch (OperationCanceledException)
|
2019-12-05 20:40:24 +00:00
|
|
|
{
|
|
|
|
retry += 1;
|
2021-08-01 18:01:19 +00:00
|
|
|
Logger?.LogWarning("Telemetry not sent! Retry attempt #{Retry}", retry);
|
2019-12-05 20:40:24 +00:00
|
|
|
}
|
|
|
|
}
|
2019-11-17 16:27:58 +00:00
|
|
|
}
|
2019-11-23 18:53:04 +00:00
|
|
|
|
|
|
|
public override void Dispose()
|
2019-11-17 16:27:58 +00:00
|
|
|
{
|
2019-11-23 18:53:04 +00:00
|
|
|
DeviceClient?.CloseAsync().GetAwaiter().GetResult();
|
2019-11-17 16:27:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|