Skip to content

Voltimax.Edge.Modbus

Modbus TCP client library with automatic reconnection, type-safe register operations, and full OpenTelemetry instrumentation.

Quick Start

csharp
var builder = Host.CreateApplicationBuilder(args);

// Register Modbus client factory
builder.Services.AddModbusClient();

// Optional: Configure OpenTelemetry
builder.Services.AddOpenTelemetry()
    .WithMetrics(metrics => metrics.AddModbusInstrumentation())
    .WithTracing(tracing => tracing.AddModbusInstrumentation());

var app = builder.Build();

// Create a client using the factory
var factory = app.Services.GetRequiredService<IModbusClientFactory>();
var client = await factory.CreateClientAsync(options =>
{
    options.Host = "192.168.1.100";
    options.Port = 502;
    options.Packing = RegisterPacking.WordHighFirstByteBigEndian;
});

// Read 32-bit float from holding registers
var voltage = await client.ReadHoldingRegistersAsync<float>(
    startAddress: 0,
    slaveAddress: 1
);

// Write single coil
await client.WriteSingleCoilAsync(
    coilAddress: 100,
    value: true,
    slaveAddress: 1
);

Key Features

  • Long-lived connections - Designed for persistent connections with automatic reconnection
  • Type-safe operations - Generic methods for reading/writing float, int, uint, long, ulong, etc.
  • Register packing - Handles multiple byte/word ordering formats (ABCD, CDAB, BADC, DCBA)
  • Resilience - Built-in retry logic, circuit breaker, and connection recovery with exponential backoff
  • Observable - Full OpenTelemetry instrumentation with metrics, traces, and structured logging
  • Thread-safe - Serialized operation execution prevents concurrent access issues
  • Factory pattern - Create multiple clients for different devices from a single factory

Client Lifecycle

Creating Clients

Use IModbusClientFactory to create client instances:

csharp
// Async factory method (recommended) - connects immediately
var client = await factory.CreateClientAsync(options =>
{
    options.Host = "plc.local";
    options.Port = 502;
});

// Or pass options object
var options = new ModbusClientOptions
{
    IpAddress = IPAddress.Parse("10.0.0.50"),
    Port = 502,
    Packing = RegisterPacking.WordHighFirstByteBigEndian
};
var client = await factory.CreateClientAsync(options);

The CreateClientAsync method establishes the TCP connection before returning. For deferred connection, use the synchronous CreateClient() and call ConnectAsync() manually:

csharp
var client = factory.CreateClient(options => options.Host = "192.168.1.100");
await client.ConnectAsync(cancellationToken);

Disposal

Always dispose clients when done to release network resources:

csharp
await using var client = await factory.CreateClientAsync(options);
// Use client...
// Automatic disposal via await using

Disposal waits for in-flight operations to complete gracefully.

Package Reference

xml
<PackageReference Include="Voltimax.Edge.Modbus" Version="1.0.0" />

Dependencies:

  • NModbus - Underlying Modbus protocol implementation
  • Microsoft.Extensions.Resilience - Polly-based retry/circuit breaker
  • OpenTelemetry.Api - Metrics and tracing primitives

Next Steps