succd: implement auto-restarting of MODBUS connection in case of network loss
This commit is contained in:
		
							parent
							
								
									152290f5a3
								
							
						
					
					
						commit
						9ec580c26f
					
				
					 1 changed files with 33 additions and 2 deletions
				
			
		| 
						 | 
				
			
			@ -2,6 +2,7 @@ package main
 | 
			
		|||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"net"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/simonvetter/modbus"
 | 
			
		||||
| 
						 | 
				
			
			@ -35,10 +36,17 @@ func (d *daemon) modbusConnect() error {
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *daemon) modbusRestart() error {
 | 
			
		||||
	d.modbusClient.Close()
 | 
			
		||||
	return d.modbusClient.Open()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// There are currently two devices connected to the modbus.
 | 
			
		||||
// The first one (slave 1) is a temperature/humidity sensor.
 | 
			
		||||
// 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
 | 
			
		||||
 | 
			
		||||
	// Switch to slave 1 (BTA1)
 | 
			
		||||
| 
						 | 
				
			
			@ -48,6 +56,9 @@ func (d *daemon) modbusUpdate() {
 | 
			
		|||
	var registersBTA1 []uint16 // temperature, humidity
 | 
			
		||||
	registersBTA1, err = d.modbusClient.ReadRegisters(1, 2, modbus.INPUT_REGISTER)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if _, ok := err.(net.Error); ok {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
		klog.Warningf("error while reading registers from BTA1 %v", err)
 | 
			
		||||
	} else if len(registersBTA1) != 2 {
 | 
			
		||||
		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
 | 
			
		||||
	registersKEC2, err = d.modbusClient.ReadRegisters(0, 3, modbus.HOLDING_REGISTER)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if _, ok := err.(net.Error); ok {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
		klog.Warningf("error while reading registers from KEC2 %v", err)
 | 
			
		||||
	} else if len(registersKEC2) != 3 {
 | 
			
		||||
		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)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if _, ok := err.(net.Error); ok {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
		klog.Warningf("error while reading digital inputs from KEC1 %v", err)
 | 
			
		||||
	} else {
 | 
			
		||||
		// Convert MODBUS words into bools
 | 
			
		||||
| 
						 | 
				
			
			@ -140,8 +157,13 @@ func (d *daemon) modbusUpdate() {
 | 
			
		|||
 | 
			
		||||
	err = d.modbusClient.WriteRegisters(0x01, registerValuesKEC1[:])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if _, ok := err.(net.Error); ok {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
		klog.Warningf("error while updating registers %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Call modbusUpdate every 100 milliseconds
 | 
			
		||||
| 
						 | 
				
			
			@ -151,7 +173,16 @@ func (d *daemon) modbusProcess(ctx context.Context) {
 | 
			
		|||
		case <-ctx.Done():
 | 
			
		||||
			return
 | 
			
		||||
		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)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue