From 6521b707dd7478b81c2ad010b3a6330b024812a9 Mon Sep 17 00:00:00 2001 From: Terekhin Alexandr Date: Fri, 4 Aug 2023 01:05:56 +0300 Subject: [PATCH] Correct timestamp when reading from stdin or file --- can/can.go | 5 ++-- can/input.go | 44 ++++++++++++++++++++++++----------- can/input_test.go | 59 +++++++++++++++++++++++++++++++++++++++++++++++ yabl/protocol.go | 11 ++++----- 4 files changed, 97 insertions(+), 22 deletions(-) create mode 100644 can/input_test.go diff --git a/can/can.go b/can/can.go index 1bc6b6e..bdf185b 100644 --- a/can/can.go +++ b/can/can.go @@ -40,7 +40,7 @@ const CAN_ID_065 = 0x065 type CanFrame struct { CanId uint32 Payload []uint8 - Date string + Date *time.Time } // NewCan New returns a new CAN bus socket. @@ -167,8 +167,9 @@ func StartCan(canbus string) (<-chan *CanFrame, error) { for { //TODO implement stop if id, data, serr := socket.Recv(); serr == nil { + var now = time.Now() canevents <- &CanFrame{ - Date: time.Now().String(), + Date: &now, CanId: id, Payload: data, } diff --git a/can/input.go b/can/input.go index 732332e..6ddca57 100644 --- a/can/input.go +++ b/can/input.go @@ -6,13 +6,15 @@ import ( "os" "regexp" "strconv" + "time" ) // (2022-07-08 16:54:15.587099) can0 100 [8] 00 00 00 00 00 00 64 00 // (1670578900.771868) can0 00004021#00000000FCFFFFFF const EXPR_HR = "\\((.*)\\)\\s+can\\d+\\s+(\\S+)\\s+\\[\\d\\]\\s+([A-F0-9]+)\\s+([A-F0-9]+)\\s+([A-F0-9]+)\\s+([A-F0-9]+)\\s+([A-F0-9]+)\\s+([A-F0-9]+)\\s+([A-F0-9]+)\\s+([A-F0-9]+)" -const EXPR_M = "\\((.*)\\)\\s+can\\d+\\s+(\\S+)#([A-F0-9]{2})([A-F0-9]{2})([A-F0-9]{2})([A-F0-9]{2})([A-F0-9]{2})([A-F0-9]{2})([A-F0-9]{2})([A-F0-9]{2})" -const length = 11 +const EXPR_M = "\\((\\d+)\\.(\\d+)\\)\\s+can\\d+\\s+(\\S+)#([A-F0-9]{2})([A-F0-9]{2})([A-F0-9]{2})([A-F0-9]{2})([A-F0-9]{2})([A-F0-9]{2})([A-F0-9]{2})([A-F0-9]{2})" +const time_hr_layout = "2006-01-02 15:04:05.000000" +const base_length = 11 var patternHr = regexp.MustCompile(EXPR_HR) var patternM = regexp.MustCompile(EXPR_M) @@ -40,7 +42,7 @@ func Readfile(filename *string) <-chan *CanFrame { func process(scanner *bufio.Scanner, ch chan<- *CanFrame) { for scanner.Scan() { text := scanner.Text() - if frame := fromString(&text); frame != nil { + if frame := fromString(text); frame != nil { ch <- frame } } @@ -60,22 +62,36 @@ func ReadStdin() <-chan *CanFrame { return c } -func fromString(text *string) *CanFrame { - var submatch []string - if submatch = patternHr.FindStringSubmatch(*text); submatch == nil { - if submatch = patternM.FindStringSubmatch(*text); submatch == nil { - return nil - } +func fromString(text string) *CanFrame { + var match []string + var now time.Time + var offset int + + if match = patternHr.FindStringSubmatch(text); match != nil { + now, _ = time.ParseInLocation(time_hr_layout, match[1], time.Local) + offset = 0 + } else if match = patternM.FindStringSubmatch(text); match != nil { + var seconds, _ = strconv.ParseInt(match[1], 10, 0) + var nanos, _ = strconv.ParseInt(match[2], 10, 0) + now = time.Unix(seconds, nanos*1000) //.In(time.Local) + + // Correct time to local zone + var _, zoneoffset = now.Zone() + now = now.Add(-time.Duration(zoneoffset) * time.Second) + + offset = 1 + } else { + return nil } - if len(submatch) == length { - canid, err := strconv.ParseUint(submatch[2], 16, 0) + if len(match) == base_length+offset { + canId, err := strconv.ParseUint(match[2+offset], 16, 0) if err != nil { return nil } payload := make([]uint8, 8) - for idx, octet := range submatch[3:] { + for idx, octet := range match[3+offset:] { val, err := strconv.ParseUint(octet, 16, 0) if err != nil { fmt.Println(err) @@ -86,8 +102,8 @@ func fromString(text *string) *CanFrame { } return &CanFrame{ - Date: submatch[1], - CanId: uint32(canid), + Date: &now, + CanId: uint32(canId), Payload: payload, } } diff --git a/can/input_test.go b/can/input_test.go new file mode 100644 index 0000000..88071ad --- /dev/null +++ b/can/input_test.go @@ -0,0 +1,59 @@ +package can + +import ( + "reflect" + "testing" + "time" +) + +const ( + frame_hr = "(2022-07-08 16:54:15.587099) can0 100 [8] 00 00 00 00 00 00 64 00" + frame_m = "(1670578900.771868) can0 00004021#00000000FCFFFFFF" +) + +func Test_fromString(t *testing.T) { + var time_m, err1 = time.ParseInLocation("2006-01-02T15:04:05.000000", "2022-12-09T09:41:40.771868", time.Local) + var time_p, err2 = time.ParseInLocation("2006-01-02 15:04:05.000000", "2022-07-08 16:54:15.587099", time.Local) + + if err1 != nil || err2 != nil { + t.Error() + } + + //time_m = time_m.In(time.Local) + //time_p = time_p.In(time.Local) + + type args struct { + text string + } + tests := []struct { + name string + args args + want *CanFrame + }{ + { + name: "Machine readable time", + args: args{text: frame_m}, + want: &CanFrame{ + Date: &time_m, + CanId: 0x4021, + Payload: []uint8{00, 00, 00, 00, 0xFC, 0xFF, 0xFF, 0xFF}, + }, + }, + { + name: "Human readable time", + args: args{text: frame_hr}, + want: &CanFrame{ + Date: &time_p, + CanId: 0x100, + Payload: []uint8{00, 00, 00, 00, 00, 00, 0x64, 00}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := fromString(tt.args.text); !reflect.DeepEqual(got, tt.want) { + t.Errorf("fromString() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/yabl/protocol.go b/yabl/protocol.go index c646450..310e4b2 100644 --- a/yabl/protocol.go +++ b/yabl/protocol.go @@ -1,7 +1,7 @@ package yabl import ( - "cli-mon/can" + can "cli-mon/can" "encoding/binary" time "time" ) @@ -40,7 +40,7 @@ type Event struct { ActionName AName Field FName Object Action - Updated time.Time + Updated *time.Time Value any } @@ -55,7 +55,7 @@ type field struct { length uint8 setter func(uint64 uint64) any value uint64 - last time.Time + last *time.Time name FName } @@ -106,14 +106,13 @@ func StartProtocolParsing(frames <-chan *can.CanFrame) <-chan *Event { var unitId = uint((frame.CanId & UNIT_ID_MASK) >> UNIT_ID_OFFSET) var canId = frame.CanId & ACTION_ID_MASK var k = key{canId: canId, unitId: unitId} - var now = time.Now() param := protocolMap[k] var start uint8 = 0 for _, f := range param.fields { if val, found := get(start, f.length, frame.Payload); found { - f.last = now + f.last = frame.Date if f.value != val { f.value = val obj := f.setter(val) @@ -122,7 +121,7 @@ func StartProtocolParsing(frames <-chan *can.CanFrame) <-chan *Event { ActionName: param.name, Object: param.object, UnitId: unitId, - Updated: now, + Updated: frame.Date, Value: obj, } }