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