Skip to main content

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);
}
note

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; }
}