This client application simultaneously polls multiple Modbus hosts, each with their own register configurations and polling intervals.
- Connect to multiple Modbus hosts simultaneously
- Individual configuration per host (timeout, interval, registers)
- Parallel polling with unique settings for each host
- Detailed per-host result display with timing information
- Graceful error handling for connection issues
- Enable/disable individual hosts
- Comprehensive logging and result aggregation
To build the client:
go build -o modbus-client main.go
./modbus-client --config multi-host-config.json
--config
: Path to JSON configuration file (default: multi-host-config.json)--cycles
: Number of polling cycles (default: 10, 0 for infinite)--single
: Run only once then exit--log
: Log to file instead of stdout
# Poll multiple hosts continuously
./modbus-client --cycles 0
# Single poll and exit
./modbus-client --single
# Log to file
./modbus-client --log modbus-client.log
# Use custom config file
./modbus-client --config custom-config.json
The client uses a JSON configuration file to define multiple hosts and their registers:
{
"hosts": [
{
"name": "Main Controller",
"host": "localhost",
"port": 502,
"unit_id": 1,
"timeout": "5s",
"interval": "1s",
"enabled": true,
"registers": [
{
"name": "Emergency Stop",
"address": 10001,
"type": "coil",
"min_value": 0,
"max_value": 1
}
]
},
{
"name": "Sensor Panel",
"host": "192.168.1.100",
"port": 502,
"unit_id": 1,
"timeout": "3s",
"interval": "500ms",
"enabled": true,
"registers": []
}
]
}
name
: Host identifier for display purposeshost
: IP address or hostnameport
: Modbus TCP port (default: 502)unit_id
: Modbus unit ID/slave ID (default: 1)timeout
: Connection timeout (e.g., "5s", "10s")interval
: Polling interval (e.g., "1s", "500ms")enabled
: Whether to poll this hostregisters
: Array of registers to poll for this host
name
: Human-readable name for the registeraddress
: Modbus address (e.g., 10001 for coil 1)type
: One ofcoil
,discrete_input
,input_register
, orholding_register
min_value
: Minimum expected value (optional, for validation)max_value
: Maximum expected value (optional, for validation)
The client displays results grouped by host:
=== Polling Results ===
Timestamp: 2024-05-05 14:30:00.000
---------------------------------------------------------------
Host: Main Controller
Register | Type | Value | Time | Status
-----------------------------------------------------------------------------
Emergency Stop | coil | true | 45ms | OK
Humidity | input_register | 65 | 60ms | OK
Temperature | input_register | 25 | 50ms | OK
Host: Sensor Panel
Register | Type | Value | Time | Status
-----------------------------------------------------------------------------
X Axis Velocity | input_register | 1 | 78ms | OK
Y Axis Velocity | input_register | 2 | 65ms | OK
Vibration Intensity | holding_register| 150 | 90ms | OUT OF RANGE [0-700]
Host: Power Monitor
Register | Type | Value | Time | Status
-----------------------------------------------------------------------------
Voltage | input_register | 220 | 120ms | OK
Current | input_register | 1 | 110ms | OK
---------------------------------------------------------------
Each host runs in its own goroutine with independent polling intervals. A fast-polling sensor panel won't slow down a slower power monitor.
The client handles:
- Connection failures (retries automatically)
- Communication timeouts
- Invalid responses
- Network interruptions
- Proper connection cleanup on exit
- Context-based cancellation
- Graceful shutdown handling
For optimal performance with many hosts:
- Adjust individual timeouts based on network conditions
- Balance polling intervals to avoid overloading the network
- Use the
enabled
flag to disable unused hosts - Consider network bandwidth when setting very fast polling intervals
MIT