Skip to content

Commit e7beadc

Browse files
committed
wip: add udp transport
1 parent bd04b09 commit e7beadc

19 files changed

Lines changed: 73 additions & 13 deletions

cmd/commons.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ func meterHelp() string {
6060
s += fmt.Sprintf("\n %s", "TCP")
6161
s += fmt.Sprintf("\n %-10s%s", "SUNS", "Sunspec-compatible MODBUS TCP device (SMA, SolarEdge, KOSTAL, etc)")
6262

63+
s += fmt.Sprintf("\n %s", "UDP")
64+
udpTypes := []string{"VM3P"}
65+
for _, t := range udpTypes {
66+
if p, ok := rs485.Producers[t]; ok {
67+
s += fmt.Sprintf("\n %-10s%s", t, p().Description())
68+
}
69+
}
70+
6371
return s
6472
}
6573

cmd/confighandler.go

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ type InfluxConfig struct {
5050
type AdapterConfig struct {
5151
Device string
5252
RTU bool
53+
UDP bool
5354
Baudrate int
5455
Comset string
5556
}
@@ -77,12 +78,16 @@ func NewDeviceConfigHandler() *DeviceConfigHandler {
7778
return conf
7879
}
7980

80-
// createConnection parses adapter string to create TCP or RTU connection
81-
func createConnection(device string, rtu bool, baudrate int, comset string, timeout time.Duration) (res meters.Connection) {
81+
// createConnection parses adapter string to create TCP, UDP or RTU connection
82+
func createConnection(device string, rtu bool, udp bool, baudrate int, comset string, timeout time.Duration) (res meters.Connection) {
8283
if device == "mock" {
8384
res = meters.NewMock(device) // mocked connection
8485
} else if tcp, _ := regexp.MatchString(":[0-9]+$", device); tcp {
85-
if rtu {
86+
if udp {
87+
// special case: RTU over UDP
88+
log.Printf("config: creating RTU over UDP connection for %s", device)
89+
res = meters.NewRTUOverUDP(device) // udp connection
90+
} else if rtu {
8691
// special case: RTU over TCP
8792
log.Printf("config: creating RTU over TCP connection for %s", device)
8893
res = meters.NewRTUOverTCP(device) // tcp connection
@@ -106,10 +111,10 @@ func createConnection(device string, rtu bool, baudrate int, comset string, time
106111
}
107112

108113
// ConnectionManager returns connection manager from cache or creates new connection wrapped by manager
109-
func (conf *DeviceConfigHandler) ConnectionManager(connSpec string, rtu bool, baudrate int, comset string, timeout time.Duration) *meters.Manager {
114+
func (conf *DeviceConfigHandler) ConnectionManager(connSpec string, rtu bool, udp bool, baudrate int, comset string, timeout time.Duration) *meters.Manager {
110115
manager, ok := conf.Managers[connSpec]
111116
if !ok {
112-
conn := createConnection(connSpec, rtu, baudrate, comset, timeout)
117+
conn := createConnection(connSpec, rtu, udp, baudrate, comset, timeout)
113118
manager = meters.NewManager(conn)
114119
conf.Managers[connSpec] = manager
115120
}
@@ -222,9 +227,9 @@ func (conf *DeviceConfigHandler) CreateDeviceFromSpec(deviceDef string, timeout
222227
log.Fatalf("Error parsing device id %s: %v. See -h for help.", devID, err)
223228
}
224229

225-
// If this is an RTU over TCP device, a default RTU over TCP should already
226-
// have been created of the --rtu flag was specified. We'll not re-check this here.
227-
manager := conf.ConnectionManager(connSpec, false, 0, "", timeout)
230+
// If this is an RTU over TCP/UDP device, a default connection should already
231+
// have been created if the --rtu or --udp flag was specified. We'll not re-check this here.
232+
manager := conf.ConnectionManager(connSpec, false, false, 0, "", timeout)
228233

229234
meter := conf.createDeviceForManager(manager, meterType, subdevice)
230235
if err := manager.Add(uint8(id), meter); err != nil {

cmd/inspect.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ func inspect(cmd *cobra.Command, args []string) {
143143
defaultDevice := viper.GetString("adapter")
144144
if defaultDevice != "" {
145145
confHandler.DefaultDevice = defaultDevice
146-
confHandler.ConnectionManager(defaultDevice, viper.GetBool("rtu"), viper.GetInt("baudrate"), viper.GetString("comset"), viper.GetDuration("timeout"))
146+
confHandler.ConnectionManager(defaultDevice, viper.GetBool("rtu"), viper.GetBool("udp"), viper.GetInt("baudrate"), viper.GetString("comset"), viper.GetDuration("timeout"))
147147
}
148148

149149
// create devices from command line

cmd/read.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func modbusClient() (meters.Connection, modbus.Client) {
5656
}
5757

5858
// connection
59-
conn := createConnection(adapter, viper.GetBool("rtu"), viper.GetInt("baudrate"), viper.GetString("comset"), viper.GetDuration("timeout"))
59+
conn := createConnection(adapter, viper.GetBool("rtu"), viper.GetBool("udp"), viper.GetInt("baudrate"), viper.GetString("comset"), viper.GetDuration("timeout"))
6060
client := conn.ModbusClient()
6161

6262
// raw log

cmd/root.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@ Only applicable if the default adapter is an RTU device`,
6565
`Use RTU over TCP for default adapter.
6666
Typically used with RS485 to Ethernet adapters that don't perform protocol conversion (e.g. USR-TCP232).
6767
Only applicable if the default adapter is a TCP connection`,
68+
)
69+
rootCmd.PersistentFlags().Bool(
70+
"udp",
71+
false,
72+
`Use RTU over UDP for default adapter.
73+
Applicable for devices that use Modbus/UDP (e.g. Victron VM-3P75CT, VM-3P5A).
74+
Only applicable if the default adapter is a UDP address`,
6875
)
6976
rootCmd.PersistentFlags().BoolP(
7077
"help", "h",

cmd/run.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ func run(cmd *cobra.Command, args []string) {
212212
defaultDevice := viper.GetString("adapter")
213213
if defaultDevice != "" {
214214
confHandler.DefaultDevice = defaultDevice
215-
confHandler.ConnectionManager(defaultDevice, viper.GetBool("rtu"), viper.GetInt("baudrate"), viper.GetString("comset"), viper.GetDuration("timeout"))
215+
confHandler.ConnectionManager(defaultDevice, viper.GetBool("rtu"), viper.GetBool("udp"), viper.GetInt("baudrate"), viper.GetString("comset"), viper.GetDuration("timeout"))
216216
}
217217

218218
// create devices from command line
@@ -239,7 +239,7 @@ func run(cmd *cobra.Command, args []string) {
239239
if len(devices) == 0 {
240240
// add adapters from configuration
241241
for _, a := range conf.Adapters {
242-
confHandler.ConnectionManager(a.Device, a.RTU, a.Baudrate, a.Comset, viper.GetDuration("timeout"))
242+
confHandler.ConnectionManager(a.Device, a.RTU, a.UDP, a.Baudrate, a.Comset, viper.GetDuration("timeout"))
243243
}
244244

245245
// add devices from configuration

cmd/scan.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ func scan(cmd *cobra.Command, args []string) {
6868
log.Fatal("missing adapter configuration")
6969
}
7070

71-
conn := createConnection(adapter, viper.GetBool("rtu"), viper.GetInt("baudrate"), viper.GetString("comset"), viper.GetDuration("timeout"))
71+
conn := createConnection(adapter, viper.GetBool("rtu"), viper.GetBool("udp"), viper.GetInt("baudrate"), viper.GetString("comset"), viper.GetDuration("timeout"))
7272
client := conn.ModbusClient()
7373

7474
// raw log

docs/mbmd.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ Easily read and distribute data from ModBus meters and grid inverters
2222
Typically used with RS485 to Ethernet adapters that don't perform protocol conversion (e.g. USR-TCP232).
2323
Only applicable if the default adapter is a TCP connection
2424
--timeout duration Timeout for MODBUS communication (default 300ms)
25+
--udp Use RTU over UDP for default adapter.
26+
Applicable for devices that use Modbus/UDP (e.g. Victron VM-3P75CT, VM-3P5A).
27+
Only applicable if the default adapter is a UDP address
2528
-v, --verbose Verbose mode
2629
```
2730

docs/mbmd_completion.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ See each sub-command's help for details on how to use the generated script.
2424
Typically used with RS485 to Ethernet adapters that don't perform protocol conversion (e.g. USR-TCP232).
2525
Only applicable if the default adapter is a TCP connection
2626
--timeout duration Timeout for MODBUS communication (default 300ms)
27+
--udp Use RTU over UDP for default adapter.
28+
Applicable for devices that use Modbus/UDP (e.g. Victron VM-3P75CT, VM-3P5A).
29+
Only applicable if the default adapter is a UDP address
2730
-v, --verbose Verbose mode
2831
```
2932

docs/mbmd_completion_bash.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ mbmd completion bash
5252
Typically used with RS485 to Ethernet adapters that don't perform protocol conversion (e.g. USR-TCP232).
5353
Only applicable if the default adapter is a TCP connection
5454
--timeout duration Timeout for MODBUS communication (default 300ms)
55+
--udp Use RTU over UDP for default adapter.
56+
Applicable for devices that use Modbus/UDP (e.g. Victron VM-3P75CT, VM-3P5A).
57+
Only applicable if the default adapter is a UDP address
5558
-v, --verbose Verbose mode
5659
```
5760

0 commit comments

Comments
 (0)