Transport Layer

All communication in SharpMeter goes through the ITransport interface, making the protocol layers completely transport-agnostic.

ITransport Interface

public interface ITransport : IAsyncDisposable
{
    bool IsConnected { get; }
    ValueTask<Result<bool>> ConnectAsync(CancellationToken ct = default);
    ValueTask DisconnectAsync(CancellationToken ct = default);
    ValueTask<Result<bool>> SendAsync(ReadOnlyMemory<byte> data, CancellationToken ct = default);
    ValueTask<Result<int>> ReceiveAsync(Memory<byte> buffer, CancellationToken ct = default);
    ValueTask SendControlAsync(byte controlByte, CancellationToken ct = default);
}

Serial Transport

For optical port / RS-232 connections:

var options = new TransportOptions
{
    PortName = "COM3",       // or "/dev/ttyUSB0" on Linux
    BaudRate = 9600,
    DataBits = 8,
    ReadTimeoutMs = 5000,
    WriteTimeoutMs = 5000
};

await using var transport = new SerialTransport(options, logger);

TCP Transport

For network-connected meters and collectors:

var options = new TransportOptions
{
    Host = "192.168.1.100",  // IPv4, IPv6, or hostname
    Port = 1153,
    ReadTimeoutMs = 10000
};

await using var transport = new TcpTransport(options, logger);

Loopback Transport

In-memory transport using System.IO.Pipelines for testing:

var (client, server) = LoopbackTransport.CreatePair(logger);
await client.ConnectAsync();
await server.ConnectAsync();

// Data sent by client is received by server and vice versa
await client.SendAsync(new byte[] { 0x01, 0x02 });
var buffer = new byte[256];
var result = await server.ReceiveAsync(buffer);

Custom Transport

Implement ITransport for any communication channel:

public sealed class BluetoothTransport : ITransport
{
    // Implement all interface members
    // Use for BLE-connected meters, etc.
}
Last updated: 2026-04-08
Was this page helpful?