NUC-41: Extract concrete Telemetry implementations in a project.

This commit is contained in:
Denis-Cosmin Nutiu 2020-04-17 18:11:07 +03:00
parent 9d4135d6d3
commit d85447aee8
19 changed files with 153 additions and 117 deletions

View file

@ -1,38 +1,38 @@
using System; using System;
namespace NucuCar.Domain namespace NucuCar.Domain
{ {
/// <summary> /// <summary>
/// Helper class used for checking arguments and raise exception if the checks don't pass. /// Helper class used for checking arguments and raise exception if the checks don't pass.
/// </summary> /// </summary>
public static class Guard public static class Guard
{ {
/// <summary> /// <summary>
/// Checks if the argument string is null or whitespace and raises exception on check fail. /// Checks if the argument string is null or whitespace and raises exception on check fail.
/// </summary> /// </summary>
/// <param name="argumentName">The argument name that will be logged in the exception message.</param> /// <param name="argumentName">The argument name that will be logged in the exception message.</param>
/// <param name="argument">The argument to check if it's null or whitespace.</param> /// <param name="argument">The argument to check if it's null or whitespace.</param>
/// <exception cref="ArgumentNullException">Raised if the argument is null or whitespace.</exception> /// <exception cref="ArgumentNullException">Raised if the argument is null or whitespace.</exception>
internal static void ArgumentNotNullOrWhiteSpace(string argumentName, string argument) public static void ArgumentNotNullOrWhiteSpace(string argumentName, string argument)
{ {
if (string.IsNullOrWhiteSpace(argument)) if (string.IsNullOrWhiteSpace(argument))
{ {
throw new ArgumentNullException($"The argument {argumentName} is null or whitespace!"); throw new ArgumentNullException($"The argument {argumentName} is null or whitespace!");
} }
} }
/// <summary> /// <summary>
/// Checks if the argument is null and raises exception on check fail. /// Checks if the argument is null and raises exception on check fail.
/// </summary> /// </summary>
/// <param name="argumentName">The argument name that will be logged in the exception message.</param> /// <param name="argumentName">The argument name that will be logged in the exception message.</param>
/// <param name="argument">The argument to check if it's null.</param> /// <param name="argument">The argument to check if it's null.</param>
/// <exception cref="ArgumentNullException">Raised if the argument is null.</exception> /// <exception cref="ArgumentNullException">Raised if the argument is null.</exception>
public static void ArgumentNotNull(string argumentName, object argument) public static void ArgumentNotNull(string argumentName, object argument)
{ {
if (argument == null) if (argument == null)
{ {
throw new ArgumentNullException($"The argument {argumentName} is null or whitespace!"); throw new ArgumentNullException($"The argument {argumentName} is null or whitespace!");
} }
} }
} }
} }

View file

@ -1,5 +1,5 @@
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using NucuCar.Sensors.Telemetry; using NucuCar.Telemetry;
namespace NucuCar.Sensors.Environment namespace NucuCar.Sensors.Environment
{ {

View file

@ -1,5 +1,5 @@
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using NucuCar.Sensors.Telemetry; using NucuCar.Telemetry;
namespace NucuCar.Sensors.Health namespace NucuCar.Sensors.Health
{ {

View file

@ -10,7 +10,7 @@
<PackageReference Include="Iot.Device.Bindings" Version="1.0.0" /> <PackageReference Include="Iot.Device.Bindings" Version="1.0.0" />
<PackageReference Include="jose-jwt" Version="2.5.0" /> <PackageReference Include="jose-jwt" Version="2.5.0" />
<PackageReference Include="libgrpc_csharp_ext.arm7" Version="1.0.8" /> <PackageReference Include="libgrpc_csharp_ext.arm7" Version="1.0.8" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.3" />
<PackageReference Include="System.Device.Gpio" Version="1.0.0" /> <PackageReference Include="System.Device.Gpio" Version="1.0.0" />
</ItemGroup> </ItemGroup>
@ -79,5 +79,10 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\NucuCar.Domain\NucuCar.Domain.csproj" /> <ProjectReference Include="..\NucuCar.Domain\NucuCar.Domain.csproj" />
<ProjectReference Include="..\NucuCar.Telemetry\NucuCar.Telemetry.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Telemetry" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -4,7 +4,7 @@ using Microsoft.Extensions.Hosting;
using NucuCar.Sensors.Environment; using NucuCar.Sensors.Environment;
using NucuCar.Sensors.Grpc; using NucuCar.Sensors.Grpc;
using NucuCar.Sensors.Health; using NucuCar.Sensors.Health;
using NucuCar.Sensors.Telemetry; using NucuCar.Telemetry;
namespace NucuCar.Sensors namespace NucuCar.Sensors
{ {

View file

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp3.0;netcoreapp3.1</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\NucuCar.Domain\NucuCar.Domain.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.3" />
</ItemGroup>
</Project>

View file

@ -4,7 +4,7 @@ using NucuCar.Domain.Telemetry;
// ReSharper disable ClassWithVirtualMembersNeverInherited.Global // ReSharper disable ClassWithVirtualMembersNeverInherited.Global
namespace NucuCar.Sensors.Telemetry namespace NucuCar.Telemetry
{ {
public class SensorTelemetry public class SensorTelemetry
{ {

View file

@ -2,7 +2,7 @@
using NucuCar.Domain.Telemetry; using NucuCar.Domain.Telemetry;
namespace NucuCar.Sensors.Telemetry namespace NucuCar.Telemetry
{ {
public class TelemetryConfig public class TelemetryConfig
{ {

View file

@ -5,8 +5,9 @@ using System.Threading.Tasks;
using Microsoft.Azure.Devices.Client; using Microsoft.Azure.Devices.Client;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json; using Newtonsoft.Json;
using NucuCar.Domain.Telemetry;
namespace NucuCar.Domain.Telemetry namespace NucuCar.Telemetry
{ {
/// <summary> /// <summary>
/// Constructs an instance of <see cref="TelemetryPublisherAzure"/>. It is used to publish telemetry to Microsoft /// Constructs an instance of <see cref="TelemetryPublisherAzure"/>. It is used to publish telemetry to Microsoft

View file

@ -6,9 +6,10 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json; using Newtonsoft.Json;
using NucuCar.Domain.Telemetry;
using NucuCar.Domain.Utilities; using NucuCar.Domain.Utilities;
namespace NucuCar.Domain.Telemetry namespace NucuCar.Telemetry
{ {
/// <summary> /// <summary>
/// The TelemetryPublisherDisk is used to publish telemetry data to a file on the disk. /// The TelemetryPublisherDisk is used to publish telemetry data to a file on the disk.

View file

@ -1,7 +1,9 @@
using System; using System;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using NucuCar.Domain;
using NucuCar.Domain.Telemetry;
namespace NucuCar.Domain.Telemetry namespace NucuCar.Telemetry
{ {
/// <summary> /// <summary>
/// The TelemetryPublisherFactory is used instantiate TelemetryPublishers. /// The TelemetryPublisherFactory is used instantiate TelemetryPublishers.

View file

@ -8,9 +8,10 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json; using Newtonsoft.Json;
using NucuCar.Domain.Telemetry;
using NucuCar.Domain.Utilities; using NucuCar.Domain.Utilities;
namespace NucuCar.Domain.Telemetry namespace NucuCar.Telemetry
{ {
/// <summary> /// <summary>
/// This class is used to publish the telemetry data to Google's Cloud Firestore. /// This class is used to publish the telemetry data to Google's Cloud Firestore.
@ -66,6 +67,7 @@ namespace NucuCar.Domain.Telemetry
_httpClient = new HttpClient(); _httpClient = new HttpClient();
_httpClient.BaseAddress = new Uri(requestUrl); _httpClient.BaseAddress = new Uri(requestUrl);
Logger?.LogInformation($"Initialized {nameof(TelemetryPublisherFirestore)}"); Logger?.LogInformation($"Initialized {nameof(TelemetryPublisherFirestore)}");
Logger?.LogInformation($"ProjectId: {firestoreProjectId}; CollectionName: {firestoreCollection}.");
} }
private async Task SetupAuthenticationHeaders() private async Task SetupAuthenticationHeaders()

View file

@ -5,7 +5,7 @@ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using NucuCar.Domain.Telemetry; using NucuCar.Domain.Telemetry;
namespace NucuCar.Sensors.Telemetry namespace NucuCar.Telemetry
{ {
/// <summary> /// <summary>
/// Telemetry service, which pools the telemetry sources and pushes telemetry data to the cloud. /// Telemetry service, which pools the telemetry sources and pushes telemetry data to the cloud.

View file

@ -15,6 +15,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\NucuCar.Domain\NucuCar.Domain.csproj" /> <ProjectReference Include="..\NucuCar.Domain\NucuCar.Domain.csproj" />
<ProjectReference Include="..\NucuCar.Telemetry\NucuCar.Telemetry.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -1,69 +1,70 @@
// ReSharper disable UnusedAutoPropertyAccessor.Global // ReSharper disable UnusedAutoPropertyAccessor.Global
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using CommandLine; using CommandLine;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json; using Newtonsoft.Json;
using NucuCar.Domain.Telemetry; using NucuCar.Domain.Telemetry;
using NucuCar.Telemetry;
namespace NucuCar.TestClient.Telemetry
{ namespace NucuCar.TestClient.Telemetry
public class AzureTelemetryPublishCmd {
{ public class AzureTelemetryPublishCmd
[Verb("azure-telemetry-publish", HelpText = "Test the publishing telemetry using Microsoft Azure IoT Hub.")] {
public class AzureTelemetryPublishOptions [Verb("azure-telemetry-publish", HelpText = "Test the publishing telemetry using Microsoft Azure IoT Hub.")]
{ public class AzureTelemetryPublishOptions
[Option('c', "connectionString", Required = true, {
HelpText = "The publisher's connection string. Get it from the Device.")] [Option('c', "connectionString", Required = true,
public string PublisherConnectionString { get; set; } HelpText = "The publisher's connection string. Get it from the Device.")]
public string PublisherConnectionString { get; set; }
[Option('m', "message", Required = true, HelpText = "The message to publish")]
public string PublisherJsonMessage { get; set; } [Option('m', "message", Required = true, HelpText = "The message to publish")]
} public string PublisherJsonMessage { get; set; }
}
private class DummyTelemeter : ITelemeter
{ private class DummyTelemeter : ITelemeter
private readonly Dictionary<string, object> _dummyTelemeterData; {
private readonly Dictionary<string, object> _dummyTelemeterData;
public DummyTelemeter(Dictionary<string, object> dummyData)
{ public DummyTelemeter(Dictionary<string, object> dummyData)
_dummyTelemeterData = dummyData; {
} _dummyTelemeterData = dummyData;
}
public string GetIdentifier()
{ public string GetIdentifier()
return "DummyTelemeter"; {
} return "DummyTelemeter";
}
public Dictionary<string, object> GetTelemetryData()
{ public Dictionary<string, object> GetTelemetryData()
return _dummyTelemeterData; {
} return _dummyTelemeterData;
}
public bool IsTelemetryEnabled()
{ public bool IsTelemetryEnabled()
return true; {
} return true;
} }
}
public static async Task RunAzurePublisherTelemetryTest(AzureTelemetryPublishOptions opts)
{ public static async Task RunAzurePublisherTelemetryTest(AzureTelemetryPublishOptions opts)
var logger = LoggerFactory.Create(builder => { builder.AddConsole(); }) {
.CreateLogger<AzureTelemetryPublishCmd>(); var logger = LoggerFactory.Create(builder => { builder.AddConsole(); })
.CreateLogger<AzureTelemetryPublishCmd>();
var telemetryPublisher = TelemetryPublisherFactory.Create(TelemetryPublisherType.Azure,
opts.PublisherConnectionString, "NucuCar.TestClient", logger); var telemetryPublisher = TelemetryPublisherFactory.Create(TelemetryPublisherType.Azure,
opts.PublisherConnectionString, "NucuCar.TestClient", logger);
var anonymousTelemeter =
new DummyTelemeter( var anonymousTelemeter =
JsonConvert.DeserializeObject<Dictionary<string, object>>(opts.PublisherJsonMessage)); new DummyTelemeter(
JsonConvert.DeserializeObject<Dictionary<string, object>>(opts.PublisherJsonMessage));
logger.LogInformation($"Publishing message: {opts.PublisherJsonMessage}");
telemetryPublisher.RegisterTelemeter(anonymousTelemeter); logger.LogInformation($"Publishing message: {opts.PublisherJsonMessage}");
await telemetryPublisher.PublishAsync(CancellationToken.None); telemetryPublisher.RegisterTelemeter(anonymousTelemeter);
} await telemetryPublisher.PublishAsync(CancellationToken.None);
} }
}
} }

View file

@ -1,5 +1,6 @@
using System; using System;
using NucuCar.Domain.Telemetry; using NucuCar.Domain.Telemetry;
using NucuCar.Telemetry;
using Xunit; using Xunit;
namespace NucuCar.UnitTests.NucuCar.Domain.Tests.Telemetry namespace NucuCar.UnitTests.NucuCar.Domain.Tests.Telemetry

View file

@ -5,7 +5,7 @@ using Microsoft.Extensions.Options;
using Moq; using Moq;
using NucuCar.Sensors; using NucuCar.Sensors;
using NucuCar.Sensors.Environment; using NucuCar.Sensors.Environment;
using NucuCar.Sensors.Telemetry; using NucuCar.Telemetry;
using NucuCarSensorsProto; using NucuCarSensorsProto;
using Xunit; using Xunit;

View file

@ -18,6 +18,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\NucuCar.Domain\NucuCar.Domain.csproj" /> <ProjectReference Include="..\NucuCar.Domain\NucuCar.Domain.csproj" />
<ProjectReference Include="..\NucuCar.Sensors\NucuCar.Sensors.csproj" /> <ProjectReference Include="..\NucuCar.Sensors\NucuCar.Sensors.csproj" />
<ProjectReference Include="..\NucuCar.Telemetry\NucuCar.Telemetry.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -8,6 +8,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NucuCar.Domain", "NucuCar.D
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NucuCar.UnitTests", "NucuCar.UnitTests\NucuCar.UnitTests.csproj", "{C6F07921-1052-4945-911E-F328A622F229}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NucuCar.UnitTests", "NucuCar.UnitTests\NucuCar.UnitTests.csproj", "{C6F07921-1052-4945-911E-F328A622F229}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NucuCar.Telemetry", "NucuCar.Telemetry\NucuCar.Telemetry.csproj", "{C20407F3-AB62-4590-B4FF-A0DCFCFA232B}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -30,5 +32,9 @@ Global
{C6F07921-1052-4945-911E-F328A622F229}.Debug|Any CPU.Build.0 = Debug|Any CPU {C6F07921-1052-4945-911E-F328A622F229}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C6F07921-1052-4945-911E-F328A622F229}.Release|Any CPU.ActiveCfg = Release|Any CPU {C6F07921-1052-4945-911E-F328A622F229}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C6F07921-1052-4945-911E-F328A622F229}.Release|Any CPU.Build.0 = Release|Any CPU {C6F07921-1052-4945-911E-F328A622F229}.Release|Any CPU.Build.0 = Release|Any CPU
{C20407F3-AB62-4590-B4FF-A0DCFCFA232B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C20407F3-AB62-4590-B4FF-A0DCFCFA232B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C20407F3-AB62-4590-B4FF-A0DCFCFA232B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C20407F3-AB62-4590-B4FF-A0DCFCFA232B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal