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 usingDisposal 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 implementationMicrosoft.Extensions.Resilience- Polly-based retry/circuit breakerOpenTelemetry.Api- Metrics and tracing primitives
Next Steps
- Configuration - Connection options and register packing
- Operations - Reading and writing registers, coils, and inputs
- Resilience - Error handling and automatic reconnection
- Observability - Metrics, tracing, and logging
- Advanced Topics - Custom conversions, testing, and best practices