Receiving Parameterized Data
This tutorial describes the process for enumerating device messages from a received Google Pub/Sub message using C# .NET.
Receiving Parameterized Data From a Google Pub/Sub Subscription
The entire Pub/Sub message is read as a UTF-8 encoded string. The JSON payload is then deserialized into a list of VehicleRecordDTO objects using the System.Text.Json.JsonSerializer.
private Task<SubscriberClient.Reply> HandleMessageAsync(PubsubMessage batch, CancellationToken cancel)
{
Console.WriteLine($"Received pubsub message - length: {batch.Data.Length}");
try
{
string text = batch.Data.ToStringUtf8();
List<VehicleRecordDTO>? recordList = JsonSerializer.Deserialize<List<VehicleRecordDTO>>(text);
if (recordList is not null)
{
foreach (VehicleRecordDTO record in recordList)
{
if (record.Gps is not null)
{
_vm.Gps.Update(record.Timestamp, record.Gps.Value);
}
if (record.Imu is not null)
{
_vm.Imu.Update(record.Timestamp, record.Imu.Value);
}
if (record.Fms is not null)
{
_vm.UpdateFms(record.Timestamp, record.Fms.Value);
}
}
}
}
catch (Exception e)
{
Console.WriteLine($"ERROR: {e.Message}");
}
return Task.FromResult(SubscriberClient.Reply.Ack);
}
The record.VehicleId property should be used to filter messages associated with specific vehicles.
Defined Data Transfer Objects
The following structures are defined to support JSON deserialization.
VehicleRecordDTO
The VehicleRecordDTO represents the top-level record in the data model. It contains the vehicle identifier, the event time (timestamp), and optional fields for GPS, IMU, and FMS data.
public struct VehicleRecordDTO
{
[JsonPropertyName("vehicle_id")]
public required string VehicleId { get; init; }
[JsonPropertyName("timestamp")]
public required DateTime Timestamp { get; init; }
[JsonPropertyName("gps")]
public required GpsItemDTO? Gps { get; set; }
[JsonPropertyName("imu")]
public required ImuItemDTO? Imu { get; set; }
[JsonPropertyName("fms")]
public required FmsItemDTO? Fms { get; set; }
}
ImuItemDTO
The ImuItemDTO represents IMU sensor data within the vehicle records.
public readonly struct VectorDTO
{
public static readonly VectorDTO Empty = new();
[JsonPropertyName("x")]
public float X { get; init; }
[JsonPropertyName("y")]
public float Y { get; init; }
[JsonPropertyName("z")]
public float Z { get; init; }
public override string ToString()
{
return $"[{X:f2};{Y:f2};{Z:f2}]";
}
}
public readonly struct SensorDataDTO
{
public static readonly SensorDataDTO Empty = new();
[JsonPropertyName("raw")]
public VectorDTO Raw { get; init; }
[JsonPropertyName("filtered")]
public VectorDTO Filtered { get; init; }
}
public readonly struct ImuItemDTO
{
public static readonly ImuItemDTO Empty = new();
[JsonPropertyName("acceleration_sensor")]
public SensorDataDTO AccelerationSensor { get; init; }
[JsonPropertyName("gyro_sensor")]
public SensorDataDTO GyroSensor { get; init; }
[JsonPropertyName("temperature")]
public float Temperature { get; init; }
}
GpsItemDTO
The GpsItemDTO represents GPS sensor data within the vehicle records.
public readonly struct GpsItemDTO
{
public static readonly GpsItemDTO Empty = new();
[JsonPropertyName("gps_time")]
public DateTime GpsTime { get; init; }
[JsonPropertyName("latitude")]
public double Latitude { get; init; }
[JsonPropertyName("longitude")]
public double Longitude { get; init; }
[JsonPropertyName("hdop")]
public float Hdop { get; init; }
[JsonPropertyName("speed")]
public float Speed { get; init; }
[JsonPropertyName("altitude")]
public float Altitude { get; init; }
}
FmsItemDTO
The FmsItemDTO represents CAN bus signal data within the vehicle records.
public readonly struct SignalValueDTO
{
[JsonPropertyName("value")]
public object? Value { get; init; }
}
public readonly struct FmsItemDTO
{
public static readonly FmsItemDTO Empty = new();
[JsonPropertyName("signals")]
public IReadOnlyDictionary<int, SignalValueDTO> Signals { get; init; }
}