Add gRPC support for NucuCar.Sensors project

This commit is contained in:
Denis-Cosmin Nutiu 2019-11-10 14:38:40 +02:00
parent 6e6f1c6fcd
commit a557d44c98
15 changed files with 240 additions and 27 deletions

View file

@ -4,9 +4,9 @@ namespace NucuCar.Sensors.EnvironmentSensor
{ {
public struct Measurement public struct Measurement
{ {
public Temperature Temperature { get; set; } public Temperature Temperature { get; private set; }
public double Pressure { get; set; } public double Pressure { get; private set; }
public double Humidity { get; set; } public double Humidity { get; private set; }
public Measurement(Temperature temperature, double pressure, double humidity) : this() public Measurement(Temperature temperature, double pressure, double humidity) : this()
{ {

View file

@ -9,21 +9,52 @@ namespace NucuCar.Sensors.EnvironmentSensor
{ {
public class Sensor : IDisposable public class Sensor : IDisposable
{ {
private readonly ILogger _logger; private ILogger _logger;
private I2cConnectionSettings _i2CSettings; private I2cConnectionSettings _i2CSettings;
private I2cDevice _i2CDevice; private I2cDevice _i2CDevice;
private Bme680 _bme680; private Bme680 _bme680;
private Measurement _measurement; private Measurement _measurement;
private SensorState _sensorState; private SensorState _sensorState;
public Sensor(ILogger logger) /* Singleton Instance */
public static Sensor Instance { get; } = new Sensor();
static Sensor()
{
}
private Sensor()
{
_sensorState = SensorState.Uninitialized;
}
public Measurement GetMeasurement()
{
return _measurement;
}
public SensorState GetState()
{
return _sensorState;
}
public void Dispose()
{
_bme680?.Dispose();
}
internal void SetLogger(ILogger logger)
{ {
_logger = logger; _logger = logger;
InitializeSensor();
} }
internal void InitializeSensor() internal void InitializeSensor()
{ {
if (_sensorState == SensorState.Initialized)
{
return;
}
try try
{ {
/* Connect to default i2c address 0x76 */ /* Connect to default i2c address 0x76 */
@ -70,22 +101,5 @@ namespace NucuCar.Sensors.EnvironmentSensor
_logger.LogInformation( _logger.LogInformation(
$"{temperature.Celsius:N2} \u00B0C | {pressure} hPa | {humidity:N2} %rH"); $"{temperature.Celsius:N2} \u00B0C | {pressure} hPa | {humidity:N2} %rH");
} }
// TODO: Make gRpc accessible.
public Measurement GetMeasurement()
{
return _measurement;
}
// TODO: Make gRpc accessible.
public SensorState GetState()
{
return _sensorState;
}
public void Dispose()
{
_bme680?.Dispose();
}
} }
} }

View file

@ -0,0 +1,27 @@
using System.Threading.Tasks;
using Grpc.Core;
using Microsoft.Extensions.Logging;
using NucuCarGrpcSensors;
namespace NucuCar.Sensors.EnvironmentSensor
{
public class Service : EnvironmentSensorGrpcService.EnvironmentSensorGrpcServiceBase
{
private readonly ILogger<Service> _logger;
private readonly Sensor _sensor;
public Service(ILogger<Service> logger)
{
_sensor = Sensor.Instance;
_logger = logger;
}
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
return Task.FromResult(new HelloReply
{
Message = "Hello " + request.Name
});
}
}
}

View file

@ -17,7 +17,10 @@ namespace NucuCar.Sensors.EnvironmentSensor
protected override async Task ExecuteAsync(CancellationToken stoppingToken) protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{ {
using var sensor = new Sensor(_logger); using var sensor = Sensor.Instance;
sensor.SetLogger(_logger);
sensor.InitializeSensor();
while (!stoppingToken.IsCancellationRequested) while (!stoppingToken.IsCancellationRequested)
{ {
if (sensor.GetState() == SensorState.Initialized) if (sensor.GetState() == SensorState.Initialized)

View file

@ -0,0 +1,43 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace NucuCar.Sensors
{
public class GrpcStartup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddGrpc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseHttpsRedirection();
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<EnvironmentSensor.Service>();
endpoints.MapGet("/",
async context =>
{
await context.Response.WriteAsync(
"Communication with gRPC endpoints must be made through a gRPC client. " +
"To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");
});
});
}
}
}

View file

@ -6,6 +6,10 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.10.1" />
<PackageReference Include="Grpc.AspNetCore" Version="2.25.0" />
<PackageReference Include="Grpc.Core" Version="2.25.0" />
<PackageReference Include="Grpc.Tools" Version="2.25.0" />
<PackageReference Include="Iot.Device.Bindings" Version="1.0.0" /> <PackageReference Include="Iot.Device.Bindings" Version="1.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="3.0.0" />
<PackageReference Include="System.Device.Gpio" Version="1.0.0" /> <PackageReference Include="System.Device.Gpio" Version="1.0.0" />
@ -13,37 +17,62 @@
<ItemGroup> <ItemGroup>
<_UnmanagedRegistrationCache Remove="obj\NucuCar.Sensors.csproj.UnmanagedRegistration.cache" /> <_UnmanagedRegistrationCache Remove="obj\NucuCar.Sensors.csproj.UnmanagedRegistration.cache" />
<_UnmanagedRegistrationCache Remove="obj\NucuCar.Sensors.csproj.UnmanagedRegistration.cache" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<_ResolveComReferenceCache Remove="obj\Debug\netcoreapp3.0\NucuCar.Sensors.csproj.ResolveComReference.cache" /> <_ResolveComReferenceCache Remove="obj\Debug\netcoreapp3.0\NucuCar.Sensors.csproj.ResolveComReference.cache" />
<_ResolveComReferenceCache Remove="obj\Debug\netcoreapp3.0\NucuCar.Sensors.csproj.ResolveComReference.cache" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<IntermediateAssembly Remove="obj\Debug\netcoreapp3.0\NucuCar.Sensors.dll" /> <IntermediateAssembly Remove="obj\Debug\netcoreapp3.0\NucuCar.Sensors.dll" />
<IntermediateAssembly Remove="obj\Debug\netcoreapp3.0\NucuCar.Sensors.dll" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<_DebugSymbolsIntermediatePath Remove="obj\Debug\netcoreapp3.0\NucuCar.Sensors.pdb" /> <_DebugSymbolsIntermediatePath Remove="obj\Debug\netcoreapp3.0\NucuCar.Sensors.pdb" />
<_DebugSymbolsIntermediatePath Remove="obj\Debug\netcoreapp3.0\NucuCar.Sensors.pdb" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<_DeploymentManifestEntryPoint Remove="obj\Debug\netcoreapp3.0\NucuCar.Sensors.dll" /> <_DeploymentManifestEntryPoint Remove="obj\Debug\netcoreapp3.0\NucuCar.Sensors.dll" />
<_DeploymentManifestEntryPoint Remove="obj\Debug\netcoreapp3.0\NucuCar.Sensors.dll" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ApplicationManifest Remove="obj\Debug\netcoreapp3.0\NucuCar.Sensors.dll.manifest" /> <ApplicationManifest Remove="obj\Debug\netcoreapp3.0\NucuCar.Sensors.dll.manifest" />
<ApplicationManifest Remove="obj\Debug\netcoreapp3.0\NucuCar.Sensors.dll.manifest" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<DeployManifest Remove="obj\Debug\netcoreapp3.0\NucuCar.Sensors.application" /> <DeployManifest Remove="obj\Debug\netcoreapp3.0\NucuCar.Sensors.application" />
<DeployManifest Remove="obj\Debug\netcoreapp3.0\NucuCar.Sensors.application" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClsidMap Remove="obj\Debug\netcoreapp3.0\NucuCar.Sensors.clsidmap" /> <ClsidMap Remove="obj\Debug\netcoreapp3.0\NucuCar.Sensors.clsidmap" />
<ClsidMap Remove="obj\Debug\netcoreapp3.0\NucuCar.Sensors.clsidmap" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<RegFreeComManifest Remove="obj\Debug\netcoreapp3.0\NucuCar.Sensors.X.manifest" /> <RegFreeComManifest Remove="obj\Debug\netcoreapp3.0\NucuCar.Sensors.X.manifest" />
<RegFreeComManifest Remove="obj\Debug\netcoreapp3.0\NucuCar.Sensors.X.manifest" />
</ItemGroup>
<ItemGroup>
<Folder Include="Services" />
</ItemGroup>
<ItemGroup>
<Protobuf Include="Protos\EnvironmentSensor.proto">
<GrpcServices>Both</GrpcServices>
<Access>Public</Access>
<ProtoCompile>True</ProtoCompile>
<ProtoRoot></ProtoRoot>
<CompileOutputs>True</CompileOutputs>
<OutputDir>obj/Debug/netcoreapp3.0/</OutputDir>
<Generator>MSBuild:Compile</Generator>
</Protobuf>
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -1,3 +1,4 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using NucuCar.Sensors.EnvironmentSensor; using NucuCar.Sensors.EnvironmentSensor;
@ -13,6 +14,7 @@ namespace NucuCar.Sensors
public static IHostBuilder CreateHostBuilder(string[] args) => public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args) Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) => { services.AddHostedService<Worker>(); }); .ConfigureServices((hostContext, services) => { services.AddHostedService<Worker>(); })
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<GrpcStartup>(); });
} }
} }

View file

@ -0,0 +1,19 @@
syntax = "proto3";
package NucuCarGrpcSensors;
// The greeting service definition.
service EnvironmentSensorGrpcService {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}

View file

@ -11,5 +11,7 @@ Sensor capabilities:
* Humidity * Humidity
* VOC Gas (Currently not implemented in binding) * VOC Gas (Currently not implemented in binding)
Note: Currently using the development certificate for gRpc calls.

View file

@ -3,6 +3,7 @@ namespace NucuCar.Sensors
public enum SensorState public enum SensorState
{ {
Error, Error,
Uninitialized,
Initialized Initialized
} }
} }

View file

@ -3,6 +3,7 @@
"LogLevel": { "LogLevel": {
"Default": "Debug", "Default": "Debug",
"System": "Information", "System": "Information",
"Grpc": "Information",
"Microsoft": "Information" "Microsoft": "Information"
} }
} }

View file

@ -5,5 +5,16 @@
"Microsoft": "Warning", "Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information" "Microsoft.Hosting.Lifetime": "Information"
} }
},
"AllowedHosts": "*",
"Kestrel": {
"EndpointDefaults": {
"Protocols": "Http2"
},
"EndPoints": {
"Https":{
"Url": "https://localhost:8000"
}
}
} }
} }

View file

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Grpc.Core" Version="2.25.0" />
<PackageReference Include="Grpc.Net.Client" Version="2.25.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\NucuCar.Sensors\NucuCar.Sensors.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,38 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Grpc.Net.Client;
using NucuCarGrpcSensors;
namespace NucuCar.TestClient
{
class Program
{
/* Warning! Before issuing a gRPC call the dev certificate must be trusted or you'll get:
* Detail="Error starting gRPC call: The SSL connection could not be established, see inner exception."
* See: https://docs.microsoft.com/en-us/aspnet/core/security/enforcing-ssl?view=aspnetcore-3.0&tabs=visual-studio#trust-the-aspnet-core-https-development-certificate-on-windows-and-macos
*/
static async Task Main(string[] args)
{
// Used to allow gRPC calls over unsecured HTTP.
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
// Allow untrusted certificates.
var httpClientHandler = new HttpClientHandler();
httpClientHandler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var httpClient = new HttpClient(httpClientHandler);
// The port number(5001) must match the port of the gRPC server.
var channel = GrpcChannel.ForAddress("https://localhost:8000",
new GrpcChannelOptions {HttpClient = httpClient});
var client = new EnvironmentSensorGrpcService.EnvironmentSensorGrpcServiceClient(channel);
var reply = await client.SayHelloAsync(
new HelloRequest {Name = "GreeterClient"});
Console.WriteLine("Greeting: " + reply.Message);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
}

View file

@ -2,6 +2,8 @@
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NucuCar.Sensors", "NucuCar.Sensors\NucuCar.Sensors.csproj", "{94C44683-F5AF-4D7D-83AE-1F94A81E1E91}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NucuCar.Sensors", "NucuCar.Sensors\NucuCar.Sensors.csproj", "{94C44683-F5AF-4D7D-83AE-1F94A81E1E91}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NucuCar.TestClient", "NucuCar.TestClient\NucuCar.TestClient.csproj", "{402BE859-07C7-4C77-8F3A-E727988CCFAD}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -12,5 +14,9 @@ Global
{94C44683-F5AF-4D7D-83AE-1F94A81E1E91}.Debug|Any CPU.Build.0 = Debug|Any CPU {94C44683-F5AF-4D7D-83AE-1F94A81E1E91}.Debug|Any CPU.Build.0 = Debug|Any CPU
{94C44683-F5AF-4D7D-83AE-1F94A81E1E91}.Release|Any CPU.ActiveCfg = Release|Any CPU {94C44683-F5AF-4D7D-83AE-1F94A81E1E91}.Release|Any CPU.ActiveCfg = Release|Any CPU
{94C44683-F5AF-4D7D-83AE-1F94A81E1E91}.Release|Any CPU.Build.0 = Release|Any CPU {94C44683-F5AF-4D7D-83AE-1F94A81E1E91}.Release|Any CPU.Build.0 = Release|Any CPU
{402BE859-07C7-4C77-8F3A-E727988CCFAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{402BE859-07C7-4C77-8F3A-E727988CCFAD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{402BE859-07C7-4C77-8F3A-E727988CCFAD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{402BE859-07C7-4C77-8F3A-E727988CCFAD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal