Frame enumeration
The following C# code snippets demonstrate how to enumerate vehicle data frames from a received data batch:
internal readonly struct PubSubFrame
{
public int Version { get; init; }
public string VehicleId { get; init; }
public int Length { get; init; }
public ReadOnlyMemory<byte> Data { get; init; }
}
internal readonly struct PubSubBatch(ReadOnlyMemory<byte> data) : IEnumerable<PubSubFrame>
{
public ReadOnlyMemory<byte> Data { get; } = data;
public IEnumerator<PubSubFrame> GetEnumerator()
{
const int VEHICLE_ID_LENGTH = 16;
const char HEADER_CHAR = 'F';
const int VERSION_V1 = 0x01;
for (int idx = 0; idx < Data.Length;)
{
byte header = Data.Span[idx++];
if (header != HEADER_CHAR)
{
throw new Exception("Invalid frame header");
}
byte version = Data.Span[idx++];
if (version != VERSION_V1)
{
throw new Exception("Unsupported version");
}
ReadOnlyMemory<byte> vId = Data.Slice(idx, VEHICLE_ID_LENGTH);
Guid vGuid = new(vId.ToArray());
string vehicleId = vGuid.ToString();
idx += VEHICLE_ID_LENGTH;
int length = BinaryPrimitives.ReadInt32LittleEndian(Data.Span[idx..]);
idx += sizeof(int);
ReadOnlyMemory<byte> data = Data.Slice(idx, length);
idx += length;
yield return new PubSubFrame()
{
Version = version,
VehicleId = vehicleId,
Length = length,
Data = data
};
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Usage Example
The following example shows how to process incoming messages and iterate through the vehicle data frames contained in each batch:
Task startTask = subscriber.StartAsync((PubsubMessage message, CancellationToken cancel) =>
{
Console.WriteLine($"Received message - length: {message.Data.Length}");
try
{
// Process received message here
foreach (PubSubFrame frame in new PubSubBatch(message.Data.Memory))
{
// Processing vehicle data frames
}
}
catch (Exception e)
{
Console.WriteLine($"ERROR: {e.Message}");
}
return Task.FromResult(SubscriberClient.Reply.Ack);
});