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