succd: implement auto-restarting of MODBUS connection in case of network loss
All checks were successful
/ test (push) Successful in 11s
/ test (pull_request) Successful in 10s

This commit is contained in:
hmelder 2024-11-10 06:51:21 +01:00
parent 152290f5a3
commit 9ec580c26f

View file

@ -2,6 +2,7 @@ package main
import ( import (
"context" "context"
"net"
"time" "time"
"github.com/simonvetter/modbus" "github.com/simonvetter/modbus"
@ -35,10 +36,17 @@ func (d *daemon) modbusConnect() error {
return nil return nil
} }
func (d *daemon) modbusRestart() error {
d.modbusClient.Close()
return d.modbusClient.Open()
}
// There are currently two devices connected to the modbus. // There are currently two devices connected to the modbus.
// The first one (slave 1) is a temperature/humidity sensor. // The first one (slave 1) is a temperature/humidity sensor.
// The second one (slave 2) is a PTA8D08 transmitter // The second one (slave 2) is a PTA8D08 transmitter
func (d *daemon) modbusUpdate() { //
// Returns whether modbus should restart (only in case of an underlying network error)
func (d *daemon) modbusUpdate() bool {
var err error var err error
// Switch to slave 1 (BTA1) // Switch to slave 1 (BTA1)
@ -48,6 +56,9 @@ func (d *daemon) modbusUpdate() {
var registersBTA1 []uint16 // temperature, humidity var registersBTA1 []uint16 // temperature, humidity
registersBTA1, err = d.modbusClient.ReadRegisters(1, 2, modbus.INPUT_REGISTER) registersBTA1, err = d.modbusClient.ReadRegisters(1, 2, modbus.INPUT_REGISTER)
if err != nil { if err != nil {
if _, ok := err.(net.Error); ok {
return true
}
klog.Warningf("error while reading registers from BTA1 %v", err) klog.Warningf("error while reading registers from BTA1 %v", err)
} else if len(registersBTA1) != 2 { } else if len(registersBTA1) != 2 {
klog.Warningf("expected two registers from modbus slave 1, but got %d", len(registersBTA1)) klog.Warningf("expected two registers from modbus slave 1, but got %d", len(registersBTA1))
@ -68,6 +79,9 @@ func (d *daemon) modbusUpdate() {
var registersKEC2 []uint16 // temperatures dp var registersKEC2 []uint16 // temperatures dp
registersKEC2, err = d.modbusClient.ReadRegisters(0, 3, modbus.HOLDING_REGISTER) registersKEC2, err = d.modbusClient.ReadRegisters(0, 3, modbus.HOLDING_REGISTER)
if err != nil { if err != nil {
if _, ok := err.(net.Error); ok {
return true
}
klog.Warningf("error while reading registers from KEC2 %v", err) klog.Warningf("error while reading registers from KEC2 %v", err)
} else if len(registersKEC2) != 3 { } else if len(registersKEC2) != 3 {
klog.Warningf("expected three registers from modbus slave 2, but got %d", len(registersKEC2)) klog.Warningf("expected three registers from modbus slave 2, but got %d", len(registersKEC2))
@ -88,6 +102,9 @@ func (d *daemon) modbusUpdate() {
digitalInputRegisters, err = d.modbusClient.ReadRegisters(0x81, 8, modbus.HOLDING_REGISTER) digitalInputRegisters, err = d.modbusClient.ReadRegisters(0x81, 8, modbus.HOLDING_REGISTER)
if err != nil { if err != nil {
if _, ok := err.(net.Error); ok {
return true
}
klog.Warningf("error while reading digital inputs from KEC1 %v", err) klog.Warningf("error while reading digital inputs from KEC1 %v", err)
} else { } else {
// Convert MODBUS words into bools // Convert MODBUS words into bools
@ -140,8 +157,13 @@ func (d *daemon) modbusUpdate() {
err = d.modbusClient.WriteRegisters(0x01, registerValuesKEC1[:]) err = d.modbusClient.WriteRegisters(0x01, registerValuesKEC1[:])
if err != nil { if err != nil {
if _, ok := err.(net.Error); ok {
return true
}
klog.Warningf("error while updating registers %v", err) klog.Warningf("error while updating registers %v", err)
} }
return false
} }
// Call modbusUpdate every 100 milliseconds // Call modbusUpdate every 100 milliseconds
@ -151,7 +173,16 @@ func (d *daemon) modbusProcess(ctx context.Context) {
case <-ctx.Done(): case <-ctx.Done():
return return
default: default:
d.modbusUpdate() shouldRestart := d.modbusUpdate()
// the modbus library does not reopen the tcp socket in case of
// a connection loss.
if shouldRestart {
klog.Infof("restarting modbus connection...")
err := d.modbusRestart()
if err != nil {
klog.Warningf("failed to restart modbus %v", err)
}
}
time.Sleep(time.Millisecond * 100) time.Sleep(time.Millisecond * 100)
} }
} }