Configuration
Connection Options
csharp
public sealed class ModbusClientOptions
{
// Either Host or IpAddress must be provided
public string? Host { get; init; }
public IPAddress? IpAddress { get; set; }
// Defaults to 502 (standard Modbus TCP port)
public int? Port { get; set; } = 502;
// Register byte/word ordering (see Register Packing section)
public RegisterPacking Packing { get; set; } = RegisterPacking.WordHighFirstByteBigEndian;
}Host vs IpAddress
- Use
Hostfor DNS-based resolution (supports dynamic IPs, retries DNS on reconnect) - Use
IpAddressfor direct IP connection (slightly faster, no DNS overhead) - If both are set,
Hosttakes precedence
Port
- Standard Modbus TCP uses port
502 - Custom ports logged at startup for troubleshooting
Register Packing
Multi-register values (32-bit floats, 64-bit integers) require configuring how bytes/words are ordered. This varies by manufacturer:
csharp
public enum RegisterPacking
{
// Most common (Eastron SDM, Schneider, Carlo Gavazzi, SMA, Fronius)
WordHighFirstByteBigEndian, // ABCD
// Word-swapped (some PLCs, older devices)
WordLowFirstByteBigEndian, // CDAB
// Rare variants
WordHighFirstByteLittleEndian, // BADC
WordLowFirstByteLittleEndian // DCBA
}Troubleshooting Register Packing
- If values are wildly incorrect (e.g., active power = 1.23E-38), try
WordLowFirstByteBigEndian - Consult device manual for "float byte order" or "register format"
- Test with known values (e.g., read voltage when actual voltage is known)
Common Device Formats
| Device/Manufacturer | Typical Packing |
|---|---|
| Eastron SDM series | WordHighFirstByteBigEndian (ABCD) |
| Schneider Electric | WordHighFirstByteBigEndian (ABCD) |
| Carlo Gavazzi | WordHighFirstByteBigEndian (ABCD) |
| SMA inverters | WordHighFirstByteBigEndian (ABCD) |
| Fronius inverters | WordHighFirstByteBigEndian (ABCD) |
| Some older PLCs | WordLowFirstByteBigEndian (CDAB) |
TIP
Most modern energy meters and inverters use WordHighFirstByteBigEndian (ABCD format), which is the default.
WARNING
If you see values like 1.23E-38 or NaN when reading floats, your register packing is likely incorrect. Try switching between WordHighFirstByteBigEndian and WordLowFirstByteBigEndian.