Add modbus integration
This commit is contained in:
parent
4edabc5c56
commit
2e6a3be100
|
@ -4,5 +4,8 @@ go 1.22.3
|
|||
|
||||
require (
|
||||
github.com/coder/websocket v1.8.12
|
||||
github.com/simonvetter/modbus v1.6.3
|
||||
k8s.io/klog v1.0.0
|
||||
)
|
||||
|
||||
require github.com/goburrow/serial v0.1.0 // indirect
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo=
|
||||
github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs=
|
||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||
github.com/goburrow/serial v0.1.0 h1:v2T1SQa/dlUqQiYIT8+Cu7YolfqAi3K96UmhwYyuSrA=
|
||||
github.com/goburrow/serial v0.1.0/go.mod h1:sAiqG0nRVswsm1C97xsttiYCzSLBmUZ/VSlVLZJ8haA=
|
||||
github.com/simonvetter/modbus v1.6.3 h1:kDzwVfIPczsM4Iz09il/Dij/bqlT4XiJVa0GYaOVA9w=
|
||||
github.com/simonvetter/modbus v1.6.3/go.mod h1:hh90ZaTaPLcK2REj6/fpTbiV0J6S7GWmd8q+GVRObPw=
|
||||
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
|
||||
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
||||
|
|
|
@ -61,6 +61,11 @@ func main() {
|
|||
}
|
||||
d.adcPirani = adc
|
||||
|
||||
err = d.modbusConnect()
|
||||
if err != nil {
|
||||
klog.Exitf("Failed to connect to modbus %v", err)
|
||||
}
|
||||
|
||||
for _, c := range []struct {
|
||||
out *gpio
|
||||
num int
|
||||
|
@ -92,5 +97,9 @@ func main() {
|
|||
}()
|
||||
|
||||
go d.process(ctx)
|
||||
if !flagFake {
|
||||
go d.modbusProcess(ctx)
|
||||
}
|
||||
|
||||
<-ctx.Done()
|
||||
}
|
||||
|
|
101
succbone/succd/modbus.go
Normal file
101
succbone/succd/modbus.go
Normal file
|
@ -0,0 +1,101 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/simonvetter/modbus"
|
||||
)
|
||||
|
||||
func modbusValuesToFloat(v uint16) float32 {
|
||||
return float32(v) / 10.0
|
||||
}
|
||||
|
||||
func (d *daemon) modbusConnect() error {
|
||||
var err error
|
||||
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
// Setup modbus client
|
||||
d.modbusClient, err = modbus.NewClient(&modbus.ClientConfiguration{
|
||||
URL: "tcp://10.250.241.20:8887",
|
||||
Timeout: 5 * time.Second,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Connect to modbus client
|
||||
err = d.modbusClient.Open()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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() error {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
var err error
|
||||
var registers []uint16 // temperature, humidity
|
||||
|
||||
// Switch to slave 1
|
||||
d.modbusClient.SetUnitId(1)
|
||||
|
||||
// Read temperature and humidity
|
||||
registers, err = d.modbusClient.ReadRegisters(1, 2, modbus.INPUT_REGISTER)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(registers) != 2 {
|
||||
msg := fmt.Sprintf("Expected two registers from modbus slave 1, but got %d", len(registers))
|
||||
return errors.New(msg)
|
||||
}
|
||||
|
||||
d.daemonState.tempSEM = modbusValuesToFloat(registers[0])
|
||||
d.daemonState.humiditySEM = modbusValuesToFloat(registers[1])
|
||||
|
||||
// Switch to slave 2
|
||||
d.modbusClient.SetUnitId(2)
|
||||
|
||||
// PT100 mapping
|
||||
// Channel 0: Cable -WGA6, Sensor "dp bottom"
|
||||
// Channel 1: Cable -WGA8, Sensor "dp inlet"
|
||||
// Channel 2: Cable WGA7, Sensor "dp top"
|
||||
registers, err = d.modbusClient.ReadRegisters(0, 3, modbus.HOLDING_REGISTER)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(registers) != 3 {
|
||||
msg := fmt.Sprintf("Expected three registers from modbus slave 2, but got %d", len(registers))
|
||||
return errors.New(msg)
|
||||
}
|
||||
|
||||
d.daemonState.tempDPBottom = modbusValuesToFloat(registers[0])
|
||||
d.daemonState.tempDPInlet = modbusValuesToFloat(registers[1])
|
||||
d.daemonState.tempDPTop = modbusValuesToFloat(registers[2])
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Call modbusUpdate every second
|
||||
func (d *daemon) modbusProcess(ctx context.Context) {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
default:
|
||||
d.modbusUpdate()
|
||||
time.Sleep(time.Second * 1)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,11 +8,13 @@ import (
|
|||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/simonvetter/modbus"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
// daemon is the main service of the succdaemon.
|
||||
type daemon struct {
|
||||
modbusClient *modbus.ModbusClient
|
||||
// adcPirani is the adc implementation returning the voltage of the Pfeiffer
|
||||
// Pirani gauge.
|
||||
adcPirani adc
|
||||
|
|
Loading…
Reference in a new issue