package binary_phasor import ( "encoding/binary" "errors" "math" "strconv" "strings" "testing" "time" "github.com/influxdata/telegraf" "github.com/influxdata/telegraf/metric" "github.com/influxdata/telegraf/testutil" ) func generatePhasorBinary(iou byte, pf int, ts uint32) ([]byte, error) { var data []byte var chanNum byte switch iou { case 1: data = make([]byte, 0, 11306) chanNum = 14 case 2: data = make([]byte, 0, 14106) chanNum = 15 default: return nil, errors.New("not supported type") } data = binary.LittleEndian.AppendUint32(data, ts) data = append(data, iou) data = append(data, chanNum) for i := range 8 { for range pf { data = binary.LittleEndian.AppendUint64(data, math.Float64bits(float64(i))) data = binary.LittleEndian.AppendUint64(data, math.Float64bits(float64(i))) data = binary.LittleEndian.AppendUint64(data, math.Float64bits(float64(i))) } } for range pf { data = append(data, 0xAA) // 1010 1010 } for range pf { data = append(data, 0x55) // 0101 0101 } switch iou { case 1: for i := range 4 { for range pf { data = binary.LittleEndian.AppendUint64(data, math.Float64bits(float64(i+8))) } } case 2: for i := range 2 { for range pf { data = binary.LittleEndian.AppendUint64(data, math.Float64bits(float64(i+8))) } } for i := range 3 { for range pf { data = binary.LittleEndian.AppendUint64(data, math.Float64bits(float64(i+10))) data = binary.LittleEndian.AppendUint64(data, math.Float64bits(float64(i+10))) data = binary.LittleEndian.AppendUint64(data, math.Float64bits(float64(i+10))) } } default: return nil, errors.New("not supported type") } return data, nil } func generateExpectedMetrics(device string, iou byte, pf int, ts uint32) ([]telegraf.Metric, error) { metrics := make([]telegraf.Metric, pf) var fields map[string]interface{} measurement := "" switch iou { case 1: measurement = "current" fields = make(map[string]interface{}, 44) case 2: measurement = "voltage" fields = make(map[string]interface{}, 51) default: return nil, errors.New("not supported type") } for i := range metrics { m := metric.New( measurement, map[string]string{"device": device}, fields, time.Unix(int64(ts), int64(i*1e9/pf)), ) for cj := range 8 { chanNo := strconv.Itoa(cj + 1) m.AddField("c"+chanNo+"_amp", float64(cj)) m.AddField("c"+chanNo+"_pa", float64(cj)) m.AddField("c"+chanNo+"_rms", float64(cj)) } for cj := range 8 { chanNo := strconv.Itoa(cj + 1) m.AddField("i"+chanNo, uint8((1+math.Pow(-1, float64(cj+1)))/2)) } for cj := range 8 { chanNo := strconv.Itoa(cj + 1 + 8) m.AddField("i"+chanNo, uint8((1+math.Pow(-1, float64(cj)))/2)) } switch iou { case 1: for cj, channel := range []string{"p", "q", "s", "pf"} { m.AddField(channel, float64(cj+8)) } case 2: for cj, channel := range []string{"f", "df"} { m.AddField(channel, float64(cj+8)) } for cj, channel := range []string{"uab", "ubc", "uca"} { m.AddField(channel+"_amp", float64(cj+10)) m.AddField(channel+"_pa", float64(cj+10)) m.AddField(channel+"_rms", float64(cj+10)) } default: return nil, errors.New("not supported type") } metrics[i] = m } return metrics, nil } func TestParse(t *testing.T) { topic := "ssu001_Phasor" device, _ := strings.CutSuffix(topic, "_Phasor") for iou := range 2 { ts := uint32(time.Now().Unix()) data, err := generatePhasorBinary(byte(iou+1), 50, ts) if err != nil { t.FailNow() } expected, err := generateExpectedMetrics(device, byte(iou+1), 50, ts) if err != nil { t.FailNow() } parser := new(Parser) parser.Init() actual, err := parser.Parse(data, topic) if err != nil { t.FailNow() } testutil.RequireMetricsEqual(t, expected, actual, testutil.IgnoreTime(), testutil.SortMetrics()) } }