92 lines
2.1 KiB
Go
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))
|
||
|
}
|
||
|
}
|