jeol-t330a/succbone/succd/modbus.go
hmelder 0da94f7161
All checks were successful
/ test (push) Successful in 11s
Add modbus integration
2024-11-10 01:47:01 +01:00

102 lines
2.2 KiB
Go

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)
}
}
}