powercollect/modbus.go
Thomas Klaehn 6d9b0da10a Initial commit
Signed-off-by: Thomas Klaehn <thomas.klaehn@perinet.io>
2022-11-09 09:32:41 +01:00

92 lines
2.1 KiB
Go

package main
import (
"math"
"strconv"
"time"
"actshad.dev/modbus"
)
var (
modbus_client modbus.Client
sample_cache sampleCache
)
func modbus_is_connected() bool {
return modbus_client != nil
}
// Read modbus register and convert result into float
func modbus_read_float_register(register_address uint16) (float32, error) {
var result float32 = 0.0
if modbus_client != nil {
res, err := modbus_client.ReadInputRegisters(register_address, 2)
if err != nil {
logger.Print("Modbus connection lost")
modbus_client = nil
return 0.0, err
}
var ieee754 uint32 = (uint32(res[0])<<24 + (uint32(res[1]) << 16) + (uint32(res[2]) << 8) + uint32(res[3]))
result = math.Float32frombits(ieee754)
}
return result, nil
}
// Connect to modbus tcp bridge
func modbus_connect(host string, port uint, slave_id byte) error {
connection := host + ":" + strconv.FormatUint(uint64(port), 10)
handler := modbus.NewTCPClientHandler(connection)
handler.Timeout = 10 * time.Second
handler.SlaveId = slave_id
err := handler.Connect()
if err != nil {
logger.Print(err)
return err
}
logger.Print("Modbus connected")
defer handler.Close()
modbus_client = modbus.NewClient(handler)
return nil
}
// connect to modbus tcp bridge host. If connection is lost try to re-connect.
func keep_mbus_connection() {
for { // ever
time.Sleep(time.Second)
if !modbus_is_connected() {
modbus_connect(config_cache.ModbusHost,
uint(config_cache.ModbusPort),
byte(config_cache.RtuAddress),
)
}
}
}
// Collect data of SDM-630 power meter
func collect_mbus_samples() {
for { // ever
if modbus_is_connected() {
sample := make(map[string]measure)
for key, register := range sdm_registers {
res, err := modbus_read_float_register(register.Address)
if err != nil {
logger.Printf("Could not read from %s (%s)", key, err)
continue
}
var mes measure
mes.Value = res
mes.Unit = register.Unit
sample[key] = mes
}
sample_cache.mutex.Lock()
sample_cache.sample = sample
sample_cache.mutex.Unlock()
}
time.Sleep(time.Duration(config_cache.SampleRate * 1000000000))
}
}