src.dualinventive.com/go/cp3000-interface/internal/statusupdate/update_decoder.go

79 lines
2.3 KiB
Go

package statusupdate
import (
"encoding/csv"
"strconv"
"strings"
"sync"
"src.dualinventive.com/go/lib/dilog"
)
// UpdateDecoder decodes cp3000 update messages
type UpdateDecoder struct {
mu sync.RWMutex
prevUpdateState *StatusUpdate
logger dilog.Logger
}
// NewUpdateDecoder creates a new update decoder. The logger is already attatched
func NewUpdateDecoder(logger dilog.Logger) *UpdateDecoder {
return &UpdateDecoder{
prevUpdateState: &StatusUpdate{},
logger: logger,
}
}
// Decode decodes the cp3000 update message
func (d *UpdateDecoder) Decode(args []string) error {
r := csv.NewReader(strings.NewReader(args[1]))
r.Comma = ','
r.LazyQuotes = true
records, err := r.Read()
if err != nil {
return err
}
f, err := strconv.ParseUint(strings.Trim(args[0], "\""), 10, 32)
if err != nil {
return err
}
fields := StatUpdateField(f)
newStat := *d.prevUpdateState
newStat.Fields = fields
// IMPORTANT the order here is important
records = decodeState(d.logger, &newStat, fields, records)
records = decodePMGT(d.logger, &newStat, fields, records)
records = decodeSwitch(d.logger, &newStat, fields, records)
records = decodeWCPUState(d.logger, &newStat, fields, records)
records = decodeRMS(d.logger, &newStat, fields, records)
records = decodeBA(d.logger, &newStat, fields, records)
records = decodeNATWS(d.logger, &newStat, fields, records)
records = decodeAutocal(d.logger, &newStat, fields, records)
records = decodeBatSelected(d.logger, &newStat, fields, records)
records = decodeBatt1Level(d.logger, &newStat, fields, records)
records = decodeBatt2Level(d.logger, &newStat, fields, records)
records = decodeTempOnBoard(d.logger, &newStat, fields, records)
records = decodeTempNTC(d.logger, &newStat, fields, records)
records = decodeGSM(d.logger, &newStat, fields, records)
records = decodeGPS(d.logger, &newStat, fields, records)
records = decodeTilt(d.logger, &newStat, fields, records)
if len(records) > 0 {
d.logger.WithField("recs", records).WithField("fields", fields).Info("more data left")
}
d.mu.Lock()
d.prevUpdateState = &newStat
d.mu.Unlock()
return nil
}
// StatusUpdate returns the last known status update
func (d *UpdateDecoder) StatusUpdate() *StatusUpdate {
d.mu.RLock()
defer d.mu.RUnlock()
return d.prevUpdateState
}