package scraper import ( "encoding/binary" "fmt" "github.com/goburrow/serial" "github.com/rs/zerolog" "github.com/things-go/go-modbus" "math" ) type Scraper struct { modbus modbus.Client logger zerolog.Logger } type Measurements struct { VoltageAN float32 VoltageBN float32 VoltageCN float32 VoltageAB float32 VoltageBC float32 VoltageCA float32 CurrentA float32 CurrentB float32 CurrentC float32 ApparantPowerA float32 ApparantPowerB float32 ApparantPowerC float32 ActivePowerA float32 ActivePowerB float32 ActivePowerC float32 Frequency float32 } func New(address string, logger zerolog.Logger) (*Scraper, error) { p := modbus.NewRTUClientProvider( modbus.WithSerialConfig(serial.Config{ Address: address, BaudRate: 19200, DataBits: 8, StopBits: 2, Parity: "N", Timeout: modbus.SerialDefaultTimeout, }), ) client := modbus.NewClient(p) err := client.Connect() if err != nil { return nil, fmt.Errorf("connecting modbus client: %w", err) } scraper := &Scraper{modbus: client, logger: logger} return scraper, nil } func (s *Scraper) GetMeasurments() (Measurements, error) { var err error measurement := Measurements{} measurement.VoltageAN, err = s.GetVoltageAN() if err != nil { s.logger.Err(err) } measurement.VoltageBN, err = s.GetVoltageBN() if err != nil { s.logger.Err(err) } measurement.VoltageCN, err = s.GetVoltageCN() if err != nil { s.logger.Err(err) } measurement.VoltageAB, err = s.GetVoltageAB() if err != nil { s.logger.Err(err) } measurement.VoltageBC, err = s.GetVoltageBC() if err != nil { s.logger.Err(err) } measurement.VoltageCA, err = s.GetVoltageCA() if err != nil { s.logger.Err(err) } measurement.CurrentA, err = s.GetCurrentA() if err != nil { s.logger.Err(err) } measurement.CurrentB, err = s.GetCurrentB() if err != nil { s.logger.Err(err) } measurement.CurrentC, err = s.GetCurrentC() if err != nil { s.logger.Err(err) } measurement.ApparantPowerA, err = s.GetApparentPowerA() if err != nil { s.logger.Err(err) } measurement.ApparantPowerB, err = s.GetApparentPowerB() if err != nil { s.logger.Err(err) } measurement.ApparantPowerC, err = s.GetApparentPowerC() if err != nil { s.logger.Err(err) } measurement.ActivePowerA, err = s.GetActivePowerA() if err != nil { s.logger.Err(err) } measurement.ActivePowerB, err = s.GetActivePowerB() if err != nil { s.logger.Err(err) } measurement.ActivePowerC, err = s.GetActivePowerC() if err != nil { s.logger.Err(err) } measurement.Frequency, err = s.GetFrequency() if err != nil { s.logger.Err(err) } return measurement, nil } //Unit: V func (s *Scraper) GetVoltageAN() (float32, error) { results, err := s.modbus.ReadInputRegistersBytes(126, 1, 2) if err != nil { return 0, fmt.Errorf("reading Voltage A-N: %w", err) } return Float32fromBytes(results), nil } //Unit: V func (s *Scraper) GetVoltageBN() (float32, error) { results, err := s.modbus.ReadInputRegistersBytes(126, 3, 2) if err != nil { return 0, fmt.Errorf("reading Voltage B-N: %w", err) } return Float32fromBytes(results), nil } //Unit: V func (s *Scraper) GetVoltageCN() (float32, error) { results, err := s.modbus.ReadInputRegistersBytes(126, 5, 2) if err != nil { return 0, fmt.Errorf("reading Voltage C-N: %w", err) } return Float32fromBytes(results), nil } //Unit: V func (s *Scraper) GetVoltageAB() (float32, error) { results, err := s.modbus.ReadInputRegistersBytes(126, 7, 2) if err != nil { return 0, fmt.Errorf("reading Voltage A-B: %w", err) } return Float32fromBytes(results), nil } //Unit: V func (s *Scraper) GetVoltageBC() (float32, error) { results, err := s.modbus.ReadInputRegistersBytes(126, 9, 2) if err != nil { return 0, fmt.Errorf("reading Voltage B-C: %w", err) } return Float32fromBytes(results), nil } //Unit: V func (s *Scraper) GetVoltageCA() (float32, error) { results, err := s.modbus.ReadInputRegistersBytes(126, 11, 2) if err != nil { return 0, fmt.Errorf("reading Voltage A-C: %w", err) } return Float32fromBytes(results), nil } //Unit: A func (s *Scraper) GetCurrentA() (float32, error) { results, err := s.modbus.ReadInputRegistersBytes(126, 13, 2) if err != nil { return 0, fmt.Errorf("reading Current A: %w", err) } return Float32fromBytes(results), nil } //Unit: A func (s *Scraper) GetCurrentB() (float32, error) { results, err := s.modbus.ReadInputRegistersBytes(126, 15, 2) if err != nil { return 0, fmt.Errorf("reading Current B: %w", err) } return Float32fromBytes(results), nil } //Unit: A func (s *Scraper) GetCurrentC() (float32, error) { results, err := s.modbus.ReadInputRegistersBytes(126, 17, 2) if err != nil { return 0, fmt.Errorf("reading Current C: %w", err) } return Float32fromBytes(results), nil } //Unit: VA func (s *Scraper) GetApparentPowerA() (float32, error) { results, err := s.modbus.ReadInputRegistersBytes(126, 19, 2) if err != nil { return 0, fmt.Errorf("reading Apparent Power A: %w", err) } return Float32fromBytes(results), nil } //Unit: VA func (s *Scraper) GetApparentPowerB() (float32, error) { results, err := s.modbus.ReadInputRegistersBytes(126, 21, 2) if err != nil { return 0, fmt.Errorf("reading Apparent Power B: %w", err) } return Float32fromBytes(results), nil } //Unit: VA func (s *Scraper) GetApparentPowerC() (float32, error) { results, err := s.modbus.ReadInputRegistersBytes(126, 23, 2) if err != nil { return 0, fmt.Errorf("reading Apparent Power C: %w", err) } return Float32fromBytes(results), nil } //Unit: VA func (s *Scraper) GetActivePowerA() (float32, error) { results, err := s.modbus.ReadInputRegistersBytes(126, 25, 2) if err != nil { return 0, fmt.Errorf("reading Active Power A: %w", err) } return Float32fromBytes(results), nil } //Unit: VA func (s *Scraper) GetActivePowerB() (float32, error) { results, err := s.modbus.ReadInputRegistersBytes(126, 27, 2) if err != nil { return 0, fmt.Errorf("reading Active Power B: %w", err) } return Float32fromBytes(results), nil } //Unit: VA func (s *Scraper) GetActivePowerC() (float32, error) { results, err := s.modbus.ReadInputRegistersBytes(126, 25, 2) if err != nil { return 0, fmt.Errorf("reading Active Power C: %w", err) } return Float32fromBytes(results), nil } //Unit: Hz func (s *Scraper) GetFrequency() (float32, error) { results, err := s.modbus.ReadInputRegistersBytes(126, 39, 2) if err != nil { return 0, fmt.Errorf("reading Freaquency: %w", err) } return Float32fromBytes(results), nil } func Float32fromBytes(bytes []byte) float32 { bits := binary.BigEndian.Uint32(bytes) float := math.Float32frombits(bits) return float }