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 }