NUC-31: Finish working implementation for FirebaseRestTranslator

This commit is contained in:
Denis-Cosmin Nutiu 2020-02-16 15:45:41 +02:00
parent 24e0630421
commit ff492258a8
4 changed files with 50 additions and 23 deletions

View file

@ -16,7 +16,6 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Google.Cloud.Firestore" Version="1.1.0" />
<PackageReference Include="Google.Protobuf" Version="3.10.1" />
<PackageReference Include="Grpc" Version="2.25.0" />
<PackageReference Include="Grpc.Tools" Version="2.25.0" />

View file

@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Google.Cloud.Firestore;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using NucuCar.Domain.Utilities;
namespace NucuCar.Domain.Telemetry
@ -22,8 +24,7 @@ namespace NucuCar.Domain.Telemetry
/// </summary>
public class TelemetryPublisherFirestore : TelemetryPublisher
{
private readonly FirestoreDb _database;
private readonly string _firestoreCollection;
private readonly HttpClient _httpClient;
private readonly int _timeout;
public TelemetryPublisherFirestore(TelemetryPublisherBuilderOptions opts) : base(opts)
@ -36,16 +37,19 @@ namespace NucuCar.Domain.Telemetry
$"Missing ProjectId!");
}
if (!options.TryGetValue("CollectionName", out _firestoreCollection))
if (!options.TryGetValue("CollectionName", out var firestoreCollection))
{
Logger?.LogCritical(
$"Can't start {nameof(TelemetryPublisherFirestore)}! Malformed connection string! " +
$"Missing CollectionName!");
}
_timeout = int.Parse(options.GetValueOrDefault("Timeout", "10000"));
_database = FirestoreDb.Create(firestoreProjectId);
var requestUrl = $"https://firestore.googleapis.com/v1/projects/{firestoreProjectId}/" +
$"databases/(default)/documents/{firestoreCollection}/";
_httpClient = new HttpClient();
_httpClient.BaseAddress = new Uri(requestUrl);
Logger?.LogInformation($"Initialized {nameof(TelemetryPublisherFirestore)}");
}
@ -55,14 +59,14 @@ namespace NucuCar.Domain.Telemetry
{
return;
}
var docRef = _database.Collection(_firestoreCollection).Document();
var data = GetTelemetry();
var cts = new CancellationTokenSource();
cts.CancelAfter(_timeout);
try
{
await docRef.SetAsync(data, cancellationToken: cts.Token);
var data = FirebaseRestTranslator.Translate(null, GetTelemetry());
var content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
await _httpClient.PostAsync("", content, cts.Token);
Logger?.LogInformation("Published data to Firestore!");
}
catch (Exception e)
@ -76,4 +80,4 @@ namespace NucuCar.Domain.Telemetry
{
}
}
}
}

View file

@ -12,11 +12,15 @@ namespace NucuCar.Domain.Utilities
{
return BuildRoot(name, dict);
}
private static Dictionary<string, object> BuildRoot(string name, Dictionary<string, object> dict)
{
var root = new Dictionary<string, object>();
root["name"] = name;
if (name != null)
{
root["name"] = name;
}
root["fields"] = new Dictionary<string, object>();
// iterate through fields and build leaf
foreach (var entry in dict)
@ -24,19 +28,16 @@ namespace NucuCar.Domain.Utilities
var fields = (Dictionary<string, object>) root["fields"];
fields[entry.Key] = BuildNode(entry.Value);
}
return root;
}
private static Dictionary<string, object> BuildNode(object value)
{
switch (value)
{
case string v:
{
if (DateTime.TryParse(v, out _))
{
return BuildTimestamp(v);
}
return BuildString(v);
}
case int v:
@ -51,16 +52,31 @@ namespace NucuCar.Domain.Utilities
{
return BuildBool(v);
}
case DateTime v:
{
return BuildTimestamp(v);
}
case List<Dictionary<string, object>> v:
{
return BuildArray(v);
}
case Dictionary<string, object>[] v:
{
return BuildArray(new List<Dictionary<string, object>>(v));
}
case Dictionary<string, object> v:
{
return BuildMap(v);
}
default:
{
if (value.GetType().IsEnum)
{
return BuildInteger((int) value);
}
break;
}
}
throw new ArgumentException($"Can't build leaf! Unknown type for: {value}");
}
@ -71,26 +87,32 @@ namespace NucuCar.Domain.Utilities
[type] = value
};
}
private static Dictionary<string, object> BuildString(string value)
{
return BuildSimpleValue("stringValue", value);
}
private static Dictionary<string, object> BuildInteger(int value)
{
return BuildSimpleValue("integerValue", value);
}
private static Dictionary<string, object> BuildTimestamp(string value)
private static Dictionary<string, object> BuildTimestamp(DateTime value)
{
return BuildSimpleValue("timestampValue", value);
}
private static Dictionary<string, object> BuildDouble(double value)
{
return BuildSimpleValue("doubleValue", value);
}
private static Dictionary<string, object> BuildBool(bool value)
{
return BuildSimpleValue("booleanValue", value);
}
private static Dictionary<string, object> BuildArray(List<Dictionary<string, object>> array)
{
var values = new List<Dictionary<string, object>>();
@ -101,11 +123,12 @@ namespace NucuCar.Domain.Utilities
["values"] = values
}
};
foreach (var entry in array)
{
values.Add(BuildNode(entry));
}
return root;
}
@ -123,6 +146,7 @@ namespace NucuCar.Domain.Utilities
{
fields[entry.Key] = BuildNode(entry.Value);
}
return root;
}
}

View file

@ -66,7 +66,7 @@ namespace NucuCar.UnitTests.NucuCar.Domain.Tests.Utilities
public void Test_FireBaseTranslator_Parse()
{
var expectedJson =
"{\"name\":\"Test\",\"fields\":{\"source\":{\"stringValue\":\"NucuCar.Sensors\"},\"timestamp\":{\"timestampValue\":\"2019-12-01T23:26:13.5537227+02:00\"},\"data\":{\"arrayValue\":{\"values\":[{\"mapValue\":{\"fields\":{\"sensor_state\":{\"integerValue\":2},\"cpu_temperature\":{\"doubleValue\":48.849998474121094},\"_id\":{\"stringValue\":\"CpuTemperature\"}}}},{\"mapValue\":{\"fields\":{\"sensor_state\":{\"integerValue\":2},\"temperature\":{\"doubleValue\":32.65},\"humidity\":{\"doubleValue\":100.0},\"pressure\":{\"doubleValue\":62228.49},\"voc\":{\"doubleValue\":0.0},\"_id\":{\"stringValue\":\"Bme680-Sensor\"}}}}]}}}}";
"{\"name\":\"Test\",\"fields\":{\"source\":{\"stringValue\":\"NucuCar.Sensors\"},\"timestamp\":{\"stringValue\":\"2019-12-01T23:26:13.5537227+02:00\"},\"data\":{\"arrayValue\":{\"values\":[{\"mapValue\":{\"fields\":{\"sensor_state\":{\"integerValue\":2},\"cpu_temperature\":{\"doubleValue\":48.849998474121094},\"_id\":{\"stringValue\":\"CpuTemperature\"}}}},{\"mapValue\":{\"fields\":{\"sensor_state\":{\"integerValue\":2},\"temperature\":{\"doubleValue\":32.65},\"humidity\":{\"doubleValue\":100.0},\"pressure\":{\"doubleValue\":62228.49},\"voc\":{\"doubleValue\":0.0},\"_id\":{\"stringValue\":\"Bme680-Sensor\"}}}}]}}}}";
var basicTelemetryData = getBasicTelemetryData();
var result = FirebaseRestTranslator.Translate("Test", basicTelemetryData);
var json = JsonConvert.SerializeObject(result);