diff --git a/can/can.go b/can/can.go index f441dc4..c812f61 100644 --- a/can/can.go +++ b/can/can.go @@ -13,13 +13,35 @@ import ( const CAN_ID_071 = 0x071 const CAN_ID_073 = 0x073 +const CAN_ID_074 = 0x074 +const CAN_ID_075 = 0x075 const CAN_ID_021 = 0x021 const CAN_ID_022 = 0x022 +const CAN_ID_023 = 0x023 +const CAN_ID_011 = 0x011 +const CAN_ID_014 = 0x014 +const CAN_ID_015 = 0x015 +const CAN_ID_016 = 0x016 +const CAN_ID_01A = 0x01A +const CAN_ID_02A = 0x02A +const CAN_ID_041 = 0x041 +const CAN_ID_042 = 0x042 +const CAN_ID_046 = 0x046 +const CAN_ID_047 = 0x047 +const CAN_ID_048 = 0x048 +const CAN_ID_049 = 0x049 +const CAN_ID_067 = 0x067 +const CAN_ID_068 = 0x068 +const CAN_ID_06C = 0x06C +const CAN_ID_061 = 0x061 +const CAN_ID_062 = 0x062 +const CAN_ID_065 = 0x065 +const bufferSize = 100 type CanFrame struct { CanId uint32 Payload []uint8 - Date string + Date *time.Time } // NewCan New returns a new CAN bus socket. @@ -109,15 +131,36 @@ func StartCan(canbus string) (<-chan *CanFrame, error) { var filter []unix.CanFilter = []unix.CanFilter{ {Id: CAN_ID_071, Mask: 0xFFF}, {Id: CAN_ID_073, Mask: 0xFFF}, + {Id: CAN_ID_074, Mask: 0xFFF}, + {Id: CAN_ID_075, Mask: 0xFFF}, {Id: CAN_ID_021, Mask: 0xFFF}, {Id: CAN_ID_022, Mask: 0xFFF}, + {Id: CAN_ID_011, Mask: 0xFFF}, + {Id: CAN_ID_014, Mask: 0xFFF}, + {Id: CAN_ID_015, Mask: 0xFFF}, + {Id: CAN_ID_016, Mask: 0xFFF}, + {Id: CAN_ID_01A, Mask: 0xFFF}, + {Id: CAN_ID_023, Mask: 0xFFF}, + {Id: CAN_ID_02A, Mask: 0xFFF}, + {Id: CAN_ID_041, Mask: 0xFFF}, + {Id: CAN_ID_042, Mask: 0xFFF}, + {Id: CAN_ID_046, Mask: 0xFFF}, + {Id: CAN_ID_047, Mask: 0xFFF}, + {Id: CAN_ID_048, Mask: 0xFFF}, + {Id: CAN_ID_049, Mask: 0xFFF}, + {Id: CAN_ID_067, Mask: 0xFFF}, + {Id: CAN_ID_068, Mask: 0xFFF}, + {Id: CAN_ID_06C, Mask: 0xFFF}, + {Id: CAN_ID_061, Mask: 0xFFF}, + {Id: CAN_ID_062, Mask: 0xFFF}, + {Id: CAN_ID_065, Mask: 0xFFF}, } if socket, err := NewCan(); err == nil { if cerr := socket.Bind(canbus, filter); cerr == nil { - canevents := make(chan *CanFrame) + canevents := make(chan *CanFrame, bufferSize) go func() { defer close(canevents) @@ -125,8 +168,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/cli-mon.go b/cli-mon.go index 262890d..1801a31 100644 --- a/cli-mon.go +++ b/cli-mon.go @@ -7,12 +7,14 @@ import ( "flag" "fmt" "os" + "time" ) func main() { filename := flag.String("f", "", "Candump filename") canbus := flag.String("i", "", "CAN bus interface") stdin := flag.Bool("s", false, "Read from stdin") + gui := flag.Bool("gui", false, "Text mode gui") flag.Parse() var frames <-chan *can.CanFrame @@ -38,7 +40,46 @@ func main() { os.Exit(0) } - var messages = yabl.StartProtocolParsing(frames) + converter := yabl.NewProtocolConverter() - ui.InitCliApp(messages) + var display ui.UI + + if *gui { + display = ui.NewUI() + } else { + display = ui.NewLog() + } + + display.Start() + + updates := make(chan *yabl.Event, 1000) + + var f func() + f = func() { + if events, ok := converter.CheckTimeouts(); ok { + for _, event := range events { + updates <- event + } + } + time.AfterFunc(50*time.Millisecond, f) + } + + time.AfterFunc(5*time.Second, f) + + go func() { + for frame := range frames { + if events, ok := converter.EventsFromFrame(frame); ok { + for _, event := range events { + updates <- event + } + } + } + close(updates) + }() + + for event := range updates { + display.Consume(event) + } + + display.Stop() } diff --git a/go.mod b/go.mod index 5950aad..1a86a66 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,16 @@ module cli-mon go 1.19 require ( - github.com/gizak/termui/v3 v3.1.0 - golang.org/x/sys v0.3.0 + github.com/rivo/tview v0.0.0-20230621164836-6cc0565babaf + golang.org/x/sys v0.5.0 ) require ( - github.com/mattn/go-runewidth v0.0.2 // indirect - github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect - github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d // indirect + github.com/gdamore/encoding v1.0.0 // indirect + github.com/gdamore/tcell/v2 v2.6.0 // indirect + github.com/lucasb-eyer/go-colorful v1.2.0 // indirect + github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/rivo/uniseg v0.4.3 // indirect + golang.org/x/term v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect ) diff --git a/go.sum b/go.sum index 155a7a8..949c504 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,42 @@ -github.com/gizak/termui/v3 v3.1.0 h1:ZZmVDgwHl7gR7elfKf1xc4IudXZ5qqfDh4wExk4Iajc= -github.com/gizak/termui/v3 v3.1.0/go.mod h1:bXQEBkJpzxUAKf0+xq9MSWAvWZlE7c+aidmyFlkYTrY= -github.com/mattn/go-runewidth v0.0.2 h1:UnlwIPBGaTZfPQ6T1IGzPI0EkYAQmT9fAEJ/poFC63o= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM= -github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d h1:x3S6kxmy49zXVVyhcnrFqxvNVCBPb2KZ9hV2RBdS840= -github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ= -golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= +github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= +github.com/gdamore/tcell/v2 v2.6.0 h1:OKbluoP9VYmJwZwq/iLb4BxwKcwGthaa1YNBJIyCySg= +github.com/gdamore/tcell/v2 v2.6.0/go.mod h1:be9omFATkdr0D9qewWW3d+MEvl5dha+Etb5y65J2H8Y= +github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/rivo/tview v0.0.0-20230621164836-6cc0565babaf h1:IchpMMtnfvzg7T3je672bP1nKWz1M4tW3kMZT6CbgoM= +github.com/rivo/tview v0.0.0-20230621164836-6cc0565babaf/go.mod h1:nVwGv4MP47T0jvlk7KuTTjjuSmrGO4JF0iaiNt4bufE= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw= +github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/ui/helper.go b/ui/helper.go deleted file mode 100644 index 0ab17a9..0000000 --- a/ui/helper.go +++ /dev/null @@ -1,43 +0,0 @@ -package ui - -import "cli-mon/yabl" - -var fNewCIS = func(packet *yabl.ContactorInternalState) *contactorType { - return &contactorType{state: packet} -} -var fGetCIS = func(c *contactorType) *yabl.ContactorInternalState { - return c.state -} -var fSetCIS = func(c *contactorType, packet *yabl.ContactorInternalState) { - c.state = packet -} - -var fNewCES = func(packet *yabl.ContactorInternalErrors) *contactorType { - return &contactorType{errors: packet} -} -var fGetCES = func(c *contactorType) *yabl.ContactorInternalErrors { - return c.errors -} -var fSetCES = func(c *contactorType, packet *yabl.ContactorInternalErrors) { - c.errors = packet -} - -var fNewPPE = func(packet *yabl.PuPresentEnergy) *connectorType { - return &connectorType{energy: packet} -} -var fGetPPE = func(c *connectorType) *yabl.PuPresentEnergy { - return c.energy -} -var fSetPPE = func(c *connectorType, packet *yabl.PuPresentEnergy) { - c.energy = packet -} - -var fNewPP = func(packet *yabl.PuPeriphery) *connectorType { - return &connectorType{state: packet} -} -var fGetPP = func(c *connectorType) *yabl.PuPeriphery { - return c.state -} -var fSetPP = func(c *connectorType, packet *yabl.PuPeriphery) { - c.state = packet -} diff --git a/ui/model.go b/ui/model.go deleted file mode 100644 index 7622406..0000000 --- a/ui/model.go +++ /dev/null @@ -1,81 +0,0 @@ -package ui - -import ( - "cli-mon/yabl" - "github.com/gizak/termui/v3/widgets" - "reflect" -) - -type connectorType struct { - energy *yabl.PuPresentEnergy - state *yabl.PuPeriphery -} - -type contactorType struct { - state *yabl.ContactorInternalState - errors *yabl.ContactorInternalErrors -} - -type modelTypes interface { - *connectorType | *contactorType -} - -type dataTypes interface { - *yabl.PuPresentEnergy | *yabl.PuPeriphery | *yabl.ContactorInternalState | *yabl.ContactorInternalErrors -} - -type fNewType[T modelTypes, V dataTypes] func(e V) T -type fGetType[T modelTypes, V dataTypes] func(m T) V -type fSetType[T modelTypes, V dataTypes] func(m T, e V) - -var connectors = make([]*connectorType, connectorsCount+1) -var contactors = make([]*contactorType, contactorsCount+1) - -var connUI [connectorsCount + 1]*widgets.Paragraph -var contUI [contactorsCount + 1]*widgets.Paragraph -var contactorsErr *widgets.Paragraph - -func process(message yabl.Packet) { - if message == nil { - return - } - - unitId := message.GetUnitId() - - switch msg := message.(type) { - case *yabl.ContactorInternalState: - if updateOrNew(contactors, unitId, msg, fNewCIS, fGetCIS, fSetCIS) { - updateContactorsView(unitId) - } - - case *yabl.ContactorInternalErrors: - if updateOrNew(contactors, unitId, msg, fNewCES, fGetCES, fSetCES) { - updateContactorsStateView() - } - - case *yabl.PuPeriphery: - if updateOrNew(connectors, unitId, msg, fNewPP, fGetPP, fSetPP) { - updateConnectorsView(unitId) - } - - case *yabl.PuPresentEnergy: - if updateOrNew(connectors, unitId, msg, fNewPPE, fGetPPE, fSetPPE) { - updateConnectorsView(unitId) - } - - } -} - -func updateOrNew[T modelTypes, V dataTypes](array []T, id uint, msg V, fNew fNewType[T, V], fGet fGetType[T, V], fSet fSetType[T, V]) bool { - if model := array[id]; model != nil { - if element := fGet(model); !reflect.DeepEqual(element, msg) { - fSet(model, msg) - return true - } - } else { - model = fNew(msg) - array[id] = model - return true - } - return false -} diff --git a/ui/parameters.go b/ui/parameters.go new file mode 100644 index 0000000..119590f --- /dev/null +++ b/ui/parameters.go @@ -0,0 +1,175 @@ +package ui + +import "cli-mon/yabl" + +var pu = []key{ + {yabl.PPuPresentEnergy, yabl.FVoltageBefore, 1}, + {yabl.PPuPresentEnergy, yabl.FVoltageAfter, 2}, + {yabl.PCpuPresentEnergy, yabl.FPresentVoltage, 3}, + {yabl.PPuPresentEnergy, yabl.FPresentCurrent, 4}, + {yabl.PCpuPresentEnergy, yabl.FPresentCurrent, 5}, + {yabl.PPuPeriphery, yabl.FConnectorInsert, 6}, + {yabl.PPuPeriphery, yabl.FContactorOn, 7}, + {yabl.PPuPeriphery, yabl.FConnectorLocked, 8}, + {yabl.PPuPeriphery, yabl.FCpLineLevel, 9}, + {yabl.PPuPeriphery, yabl.FIsolationState, 10}, + {yabl.PPuPeriphery, yabl.FChargingAllowed, 11}, + {yabl.PPuPeriphery, yabl.FPwmEnabled, 12}, + {yabl.PPuPeriphery, yabl.FCpLineVoltage, 13}, + {yabl.PCpuEnergySettings, yabl.FTargetBatteryVoltage, 14}, + {yabl.PCpuEnergySettings, yabl.FTargetGoalVoltage, 15}, + {yabl.PCpuEnergySettings, yabl.FPowerMax, 16}, + {yabl.PCpuEnergySettings, yabl.FCurrentMax, 17}, + {yabl.PCpuEnergySettings, yabl.FVoltageMax, 18}, + {yabl.PPuDebug, yabl.FDebugModeOn, 19}, + {yabl.PPuDebug, yabl.FDebugContactorOutputOn, 20}, + {yabl.PPuPeriphery, yabl.FDebugContactorOn, 21}, + {yabl.PPuErrors, yabl.FBoardReady, 22}, +} + +var pu_errors = []key{ + {yabl.PPuErrors, yabl.FBoardReady, 1}, + {yabl.PPuErrors, yabl.FOtherError, 2}, + {yabl.PPuErrors, yabl.FIncorrectVoltage, 3}, + {yabl.PPuErrors, yabl.FIncorrectVoltageValue, 4}, + {yabl.PPuErrors, yabl.FIncorrectCurrent, 5}, + {yabl.PPuErrors, yabl.FIncorrectCurrentValue, 6}, + {yabl.PPuErrors, yabl.FIsolationBroken, 7}, + {yabl.PPuErrors, yabl.FCpLineBroken, 8}, + {yabl.PPuErrors, yabl.FCpLineGap69, 9}, + {yabl.PPuErrors, yabl.FCableReady, 10}, + {yabl.PPuErrors, yabl.FNotReadyCpu, 11}, + {yabl.PPuErrors, yabl.FNotReadySecc, 12}, + {yabl.PPuErrors, yabl.FContactorOutputError, 13}, + {yabl.PPuErrors, yabl.FDebugContactorOutputEnabled, 14}, + {yabl.PPuErrors, yabl.FOutputCircuitBreakerEnabled, 15}, + {yabl.PPuDebug, yabl.FDebugModeOn, 16}, + {yabl.PPuDebug, yabl.FDebugContactorOutputOn, 17}, +} + +var contactors_errors = []key{ + {yabl.PContactorInternalErrors, yabl.FBoardReady, 1}, + {yabl.PContactorInternalErrors, yabl.FOtherError, 2}, + {yabl.PContactorInternalErrors, yabl.FContactorGroupChanged, 3}, + {yabl.PContactorInternalErrors, yabl.FUnexpectedFormation, 4}, + {yabl.PContactorInternalErrors, yabl.FCpuNotReady, 5}, + {yabl.PContactorInternalErrors, yabl.FPuNotReady, 6}, + {yabl.PContactorInternalErrors, yabl.FDebug, 7}, + {yabl.PContactorInternalErrors, yabl.FPresentContactorMode, 8}, + {yabl.PContactorsInternalForce, yabl.FForceModeEnabled, 9}, + {yabl.PContactorsInternalForce, yabl.FForceModeValue, 10}, + {yabl.PContactorInternalDebug, yabl.FDebugModeOn, 11}, +} + +var contactors_state = []key{ + {yabl.PContactorInternalState, yabl.FContactorReady, 1}, + {yabl.PContactorInternalState, yabl.FContactorOn, 2}, + {yabl.PContactorInternalState, yabl.FUnexpectedState, 3}, + {yabl.PContactorInternalState, yabl.FIsolated, 4}, + {yabl.PContactorInternalState, yabl.FDebugEnabled, 5}, + {yabl.PContactorInternalDebug, yabl.FDebugContactorOn, 6}, +} + +var periphery_state = []key{ + {yabl.PPeripheryState, yabl.FErrorShakeSensor, 1}, + {yabl.PPeripheryState, yabl.FErrorCoolingGroup, 2}, + {yabl.PPeripheryState, yabl.FOtherError, 3}, + {yabl.PPeripheryState, yabl.FDebugShptFanEnabled, 4}, + {yabl.PPeripheryState, yabl.FDebugIoBoardTestLampEnabled, 5}, + {yabl.PPeripheryInfo, yabl.FStateShptFan, 6}, + {yabl.PPeripheryDebug, yabl.FDebugShptFan, 7}, + {yabl.PPeripheryDebug, yabl.FDebugIoBoardTestLamp, 8}, +} + +var periphery_station_state = []key{ + {yabl.PPeripheryState, yabl.FOtherErrorSeverity, 1}, + {yabl.PPeripheryState, yabl.FOtherError, 2}, + {yabl.PPeripheryState, yabl.FPeripheryErrorCoolingGroup, 3}, + {yabl.PPeripheryState, yabl.FErrorFireEmergency, 4}, + {yabl.PPeripheryState, yabl.FErrorFireEmergencyRun, 5}, + {yabl.PPeripheryState, yabl.FErrorFireEmergencyControl, 6}, + {yabl.PPeripheryState, yabl.FErrorOvervoltageIn, 7}, + {yabl.PPeripheryState, yabl.FPeripheryErrorPowerSupply, 8}, + {yabl.PPeripheryState, yabl.FErrorFan, 9}, + {yabl.PPeripheryState, yabl.FErrorOvervoltageOut, 10}, + {yabl.PPeripheryState, yabl.FErrorStateRemoteMode, 11}, + {yabl.PPeripheryState, yabl.FDebugShsnFanEnabled, 12}, + {yabl.PPeripheryState, yabl.FDebugShptFanEnabled, 13}, + {yabl.PPeripheryState, yabl.FDebugIoBoardTestLampEnabled, 14}, + {yabl.PPeripheryState, yabl.FErrorFireEmergencyCircuitBreaker, 15}, + {yabl.PPeripheryState, yabl.FErrorExtLightCircuitBreaker, 16}, + {yabl.PPeripheryState, yabl.FErrorIndicationCircuitBreaker, 17}, + {yabl.PPeripheryState, yabl.FErrorLowVoltagePowerCircuitBreaker, 18}, + {yabl.PPeripheryState, yabl.FErrorContactorsInternalCircuitBreaker, 19}, + {yabl.PPeripheryState, yabl.FErrorPlcCircuitBreaker, 20}, + {yabl.PPeripheryInfo, yabl.FInfoDoorOpen, 21}, + {yabl.PPeripheryInfo, yabl.FTempAirIn, 22}, + {yabl.PPeripheryInfo, yabl.FTempAirOut, 23}, + {yabl.PPeripheryInfo, yabl.FStateShsnFan, 24}, + {yabl.PPeripheryDebug, yabl.FDebugModeOn, 25}, + {yabl.PPeripheryDebug, yabl.FDebugShsnFan, 26}, +} + +var converters = []key{ + {yabl.PConverterPresentEnergy, yabl.FPresentVoltage, 1}, + {yabl.PConverterPresentEnergy, yabl.FPresentCurrent, 2}, + {yabl.PConverterPresentEnergy, yabl.FConnectedOut, 3}, + {yabl.PConverterErrors, yabl.FBoardReady, 4}, + {yabl.PConverterErrors, yabl.FOtherError, 5}, + {yabl.PConverterErrors, yabl.FNotConnectedOut, 6}, + {yabl.PConverterErrors, yabl.FNoCommunicationConverter, 7}, + {yabl.PConverterErrors, yabl.FNoCommunicationPuConverter, 8}, + {yabl.PConverterPresentEnergy, yabl.FV2gMode, 9}, + {yabl.PConverterErrors, yabl.FDebugConvEnabled, 10}, + {yabl.PConverterErrors, yabl.FDebugConvDisabled, 11}, + {yabl.PConverterDebug, yabl.FDebugModeOn, 12}, + {yabl.PConverterDebug, yabl.FDebugEnergyOn, 13}, + {yabl.PConverterDebug, yabl.FDebugTargetVoltage, 14}, + {yabl.PConverterDebug, yabl.FDebugTargetCurrent, 15}, +} + +var converters_errors = []key{ + {yabl.PConverterErrors, yabl.FBoardReady, 1}, + {yabl.PConverterErrors, yabl.FOtherError, 2}, + {yabl.PConverterErrors, yabl.FNotConnectedOut, 3}, + {yabl.PConverterErrors, yabl.FNoCommunicationConverter, 4}, + {yabl.PConverterErrors, yabl.FNoCommunicationPuConverter, 5}, + {yabl.PConverterErrors, yabl.FInputGridVoltageHigh, 6}, + {yabl.PConverterErrors, yabl.FInputGridVoltageLow, 7}, + {yabl.PConverterErrors, yabl.FOutputGridVoltageHigh, 8}, + {yabl.PConverterErrors, yabl.FOutputGridVoltageLow, 9}, + {yabl.PConverterErrors, yabl.FInputGridVoltage, 10}, + {yabl.PConverterErrors, yabl.FOutputGridVoltage, 11}, + {yabl.PConverterErrors, yabl.FShortCircuit, 12}, + {yabl.PConverterErrors, yabl.FOverHeat, 13}, + {yabl.PConverterErrors, yabl.FFanBroken, 14}, + {yabl.PConverterErrors, yabl.FOtherHardwareError, 15}, +} + +var cpu = []key{ + {yabl.PCpuErrors, yabl.FBoardReady, 1}, + {yabl.PCpuErrors, yabl.FOtherError, 2}, + {yabl.PCpuErrors, yabl.FRedButtonHard, 3}, + {yabl.PCpuErrors, yabl.FRedButtonSoft, 4}, + {yabl.PCpuErrors, yabl.FModulesGone, 5}, + {yabl.PCpuErrors, yabl.FGridVoltageHighErr, 6}, + {yabl.PCpuErrors, yabl.FGridVoltageHighWarn, 7}, + {yabl.PCpuErrors, yabl.FGridVoltageLowWarn, 8}, + {yabl.PCpuErrors, yabl.FGridVoltageLowErr, 9}, + {yabl.PCpuErrors, yabl.FGridVoltageLow, 10}, + {yabl.PCpuErrors, yabl.FGridVoltageHigh, 11}, + {yabl.PCpuErrors, yabl.FGridVoltageEmpty, 12}, + {yabl.PCpuErrors, yabl.FNotReadySecc, 13}, + {yabl.PCpuErrors, yabl.FNotReadyPu, 14}, + {yabl.PCpuErrors, yabl.FNotReadyContactors, 15}, + {yabl.PCpuErrors, yabl.FDebugConvertersEnabled, 16}, + {yabl.PCpuErrors, yabl.FContactorInputError, 17}, + {yabl.PCpuErrors, yabl.FNotReadyPeriphery, 18}, + {yabl.PCpuPeriphery, yabl.FContactorInput, 19}, + {yabl.PCpuPeriphery, yabl.FCircuitBreakerInput, 20}, + {yabl.PCpuPeriphery, yabl.FCircuitBreakerPowerCBInput, 21}, + {yabl.PCpuDebug, yabl.FDebugModeOn, 22}, + {yabl.PCpuDebug, yabl.FDebugContactorInputOn, 23}, + {yabl.PCpuDebug, yabl.FDebugCircuitBreakerOn, 24}, + {yabl.PCpuDebug, yabl.FDebugRedButtonSoftware, 25}, +} diff --git a/ui/table.go b/ui/table.go new file mode 100644 index 0000000..eb21c81 --- /dev/null +++ b/ui/table.go @@ -0,0 +1,98 @@ +package ui + +import ( + "cli-mon/yabl" + "fmt" + "github.com/gdamore/tcell/v2" + tview "github.com/rivo/tview" + "reflect" +) + +type table struct { + tview.Table + views map[key]*tview.TableCell + content []key +} + +type key struct { + action yabl.AName + field yabl.FName + id uint +} + +func (t *table) update(event *yabl.Event) { + if cell, ok := t.views[key{event.ActionName, event.Field, event.GetUnitId()}]; ok { + cell.SetText(fmt.Sprintf("%v", event.Value)) + } +} + +func (t *table) header(header string) *table { + t.SetTitle(header) + return t +} + +func (t *table) columns(name string, cols int) *table { + for i := 1; i <= cols; i++ { + t.SetCell(0, i, tview.NewTableCell(fmt.Sprintf("%s %d", name, i)).SetExpansion(2)).SetBackgroundColor(tcell.ColorDefault) + } + return t +} + +func (t *table) rows(name string, rows int) *table { + for i := 1; i <= rows; i++ { + t.SetCell(i, 0, tview.NewTableCell(fmt.Sprintf("%s %d", name, i))).SetBackgroundColor(tcell.ColorDefault) //.SetExpansion(2)) + } + return t +} + +func newTable(params []key, min, max int, invert bool, short bool) *table { + t := &table{} + t.Box = tview.NewBox() + //t.SetBorderColor(tview.Styles.GraphicsColor) + t.SetSeparator(' ') + t.SetContent(nil) + t.SetBorders(true) + t.SetBorder(true) + + t.views = make(map[key]*tview.TableCell) + + for _, param := range params { + for i := min; i <= max; i++ { + k := param + k.id = uint(i) + cell := tview.NewTableCell("").SetBackgroundColor(tcell.ColorDefault) + t.views[k] = cell + var col = i + if min == 0 { + col++ + } + if !invert { + t.SetCell(int(param.id), col, cell) + } else { + t.SetCell(col, int(param.id), cell) + } + + } + var desc string + if short { + desc = fmt.Sprintf("%s", param.field) + } else { + desc = fmt.Sprintf("%s.%s", param.action, param.field) + } + + cell := tview.NewTableCell(desc).SetBackgroundColor(tcell.ColorDefault) + if !invert { + t.SetCell(int(param.id), 0, cell) + } else { + t.SetCell(0, int(param.id), cell) + } + } + + return t +} + +func getField(v yabl.Action, field yabl.FName) interface{} { + r := reflect.ValueOf(v) + f := reflect.Indirect(r).FieldByName(string(field)) + return f.Interface() +} diff --git a/ui/ui.go b/ui/ui.go index 6ae7959..8da2e93 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -2,87 +2,250 @@ package ui import ( "cli-mon/yabl" - ui "github.com/gizak/termui/v3" - "github.com/gizak/termui/v3/widgets" - "log" + "fmt" + "github.com/gdamore/tcell/v2" + "github.com/rivo/tview" + "os" "time" ) -const headerHeight int = 4 -const contactorsCount = 18 -const connectorsCount = 6 +const ( + connectors_page = "Connectors" + connectors_errors_page = "Connectors errors" + contactors_errors_page = "Contactors errors" + contactors_state_page = "Contactors states" + periphery_state_page = "Periphery state" + periphery_station_state_page = "Periphery station state" + converters_page = "Converters" + converters_errors_page = "Converters errors" + cpu_page = "CPU" + connectorCount = 6 + contactorsCount = 18 + convertersCount = 18 + redrawMillis = 500 +) -func InitCliApp(events <-chan yabl.Packet) { - if err := ui.Init(); err != nil { - log.Fatalf("failed to initialize termui: %v", err) +type page struct { + left string + right string + primitive tview.Primitive +} + +type UI interface { + Consume(event *yabl.Event) + Start() + Stop() +} + +type gui struct { + app *tview.Application + pages *tview.Pages + redraw bool + ticker *time.Ticker + pu *table + puErrors *table + contactorsErrors *table + contactorsState *table + peripheryState *table + peripheryStationState *table + converters *table + convertersErrors *table + cpu *table +} + +type log struct { +} + +func (g *gui) Consume(event *yabl.Event) { + switch event.Object.(type) { + case *yabl.PuPresentEnergy: + g.pu.update(event) + case *yabl.PuPeriphery: + g.pu.update(event) + case *yabl.PuDebug: + g.pu.update(event) + g.puErrors.update(event) + case *yabl.PuErrors: + g.pu.update(event) + g.puErrors.update(event) + case *yabl.ContactorInternalErrors: + g.contactorsErrors.update(event) + case *yabl.ContactorInternalDebug: + g.contactorsErrors.update(event) + g.contactorsState.update(event) + case *yabl.ContactorInternalState: + g.contactorsState.update(event) + case *yabl.ContactorsInternalForce: + g.contactorsErrors.update(event) + case *yabl.PeripheryState: + g.peripheryState.update(event) + g.peripheryStationState.update(event) + case *yabl.PeripheryInfo: + g.peripheryState.update(event) + g.peripheryStationState.update(event) + case *yabl.PeripheryDebug: + g.peripheryState.update(event) + g.peripheryStationState.update(event) + case *yabl.ConverterPresentEnergy: + g.converters.update(event) + case *yabl.ConverterErrors: + g.converters.update(event) + g.convertersErrors.update(event) + case *yabl.ConverterDebug: + g.converters.update(event) + case *yabl.CpuPresentEnergy: + g.pu.update(event) + case *yabl.CpuEnergySettings: + g.pu.update(event) + case *yabl.CpuErrors: + g.cpu.update(event) + case *yabl.CpuPeriphery: + g.cpu.update(event) + case *yabl.CpuDebug: + g.cpu.update(event) + default: + return + } + g.redraw = true +} + +func NewUI() UI { + g := &gui{} + + g.app = tview.NewApplication() + g.pages = tview.NewPages() + + var active page + var layout map[string]page + + g.pu = newTable(pu, 1, connectorCount, false, false).header(connectors_page).columns("Connector", connectorCount) + g.puErrors = newTable(pu_errors, 1, connectorCount, false, false).header(connectors_errors_page).columns("Connector", connectorCount) + g.contactorsErrors = newTable(contactors_errors, 0, 0, false, false).header(contactors_errors_page) + g.contactorsState = newTable(contactors_state, 1, contactorsCount, true, true).header(contactors_state_page).rows("Contactor", contactorsCount) + g.peripheryState = newTable(periphery_state, 1, connectorCount, false, false).header(periphery_state_page).columns("Connector", connectorCount) + g.peripheryStationState = newTable(periphery_station_state, 0, 1, false, false).header(periphery_station_state_page) + g.converters = newTable(converters, 1, convertersCount, false, true).header(converters_page).columns("", convertersCount) + g.convertersErrors = newTable(converters_errors, 1, convertersCount, false, true).header(converters_errors_page).columns("", convertersCount) + g.cpu = newTable(cpu, 0, 0, false, false).header(cpu_page) + + layout = map[string]page{ + connectors_page: { + left: cpu_page, + right: connectors_errors_page, + primitive: g.pu, + }, + connectors_errors_page: { + left: connectors_page, + right: contactors_errors_page, + primitive: g.puErrors, + }, + contactors_errors_page: { + left: connectors_errors_page, + right: contactors_state_page, + primitive: g.contactorsErrors, + }, + contactors_state_page: { + left: contactors_errors_page, + right: periphery_state_page, + primitive: g.contactorsState, + }, + periphery_state_page: { + left: contactors_state_page, + right: periphery_station_state_page, + primitive: g.peripheryState, + }, + periphery_station_state_page: { + left: periphery_state_page, + right: converters_page, + primitive: g.peripheryStationState, + }, + converters_page: { + left: periphery_station_state_page, + right: converters_errors_page, + primitive: g.converters, + }, + converters_errors_page: { + left: converters_page, + right: cpu_page, + primitive: g.convertersErrors, + }, + cpu_page: { + left: converters_errors_page, + right: connectors_page, + primitive: g.cpu, + }, } - defer ui.Close() - - var connectorsTab *ui.Grid - //var contactorsErr *widgets.Paragraph - var contactorsStateTab *ui.Grid - var header *widgets.Paragraph - - tabpane := widgets.NewTabPane("Connectors", "Contactors States", "Contactors Errors") - tabpane.SetRect(0, 1, 150, 4) - tabpane.Border = true - - header = newHeader() - connectorsTab = newConnectorsView() - contactorsStateTab = newContactorsView() - contactorsErr = newContactorsErrView() - - renderTab := func() { - switch tabpane.ActiveTabIndex { - case 0: - termWidth, termHeight := ui.TerminalDimensions() - connectorsTab.SetRect(0, headerHeight, termWidth, termHeight) - ui.Render(connectorsTab) - case 1: - termWidth, termHeight := ui.TerminalDimensions() - contactorsStateTab.SetRect(0, headerHeight, termWidth, termHeight) - ui.Render(contactorsStateTab) - case 2: - ui.Render(contactorsErr) + + for k, p := range layout { + g.pages.AddPage(k, p.primitive, true, true) + } + + active = layout[connectors_page] + g.pages.SwitchToPage(connectors_page) + + g.app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { + switch event.Key() { + case tcell.KeyRight: + g.pages.SwitchToPage(active.right) + active = layout[active.right] + return nil + case tcell.KeyLeft: + g.pages.SwitchToPage(active.left) + active = layout[active.left] + return nil + case tcell.KeyCtrlC: + g.Stop() } - } + return event + }) + + g.redraw = true + + return g +} + +func (g *gui) Start() { + g.ticker = time.NewTicker(redrawMillis * time.Millisecond) - ui.Render(header, tabpane, connectorsTab) - - uiEvents := ui.PollEvents() - ticker := time.NewTicker(2 * time.Second).C - for { - select { - case e := <-uiEvents: - switch e.ID { // event string/identifier - case "q", "": // press 'q' or 'C-c' to quit - return - case "": - //payload := e.Payload.(ui.Mouse) - //x, y := payload.X, payload.Y - //p.Text = fmt.Sprintf("X = %d, Y = %d", x, y) - case "": - tabpane.FocusLeft() - ui.Clear() - ui.Render(header, tabpane) - renderTab() - case "": - tabpane.FocusRight() - ui.Clear() - ui.Render(header, tabpane) - renderTab() + go func() { + for _ = range g.ticker.C { + if g.redraw { + g.app.Draw() + g.redraw = false } + } + }() - switch e.Type { - case ui.KeyboardEvent: // handle all key presses - //eventID := e.ID // keypress string - //p.Text = eventID - } - // use Go's built-in tickers for updating and drawing data - case <-ticker: - renderTab() - case message := <-events: - process(message) + go func() { + if err := g.app.SetRoot(g.pages, true).EnableMouse(true).Run(); err != nil { + panic(err) } - } + }() +} + +func (g *gui) Stop() { + g.ticker.Stop() + g.app.Stop() + os.Exit(0) +} + +func NewLog() UI { + return &log{} + +} + +func (l log) Consume(event *yabl.Event) { + fmt.Printf( + "%v %v.%v [%d] %v\n", + event.Updated.Format("Jan _2 15:04:05.000"), + event.ActionName, + event.Field, + event.GetUnitId(), + event.Value) +} + +func (l log) Start() { +} + +func (l log) Stop() { } diff --git a/ui/view.go b/ui/view.go deleted file mode 100644 index 5397408..0000000 --- a/ui/view.go +++ /dev/null @@ -1,224 +0,0 @@ -package ui - -import ( - "cli-mon/yabl" - "fmt" - ui "github.com/gizak/termui/v3" - "github.com/gizak/termui/v3/widgets" -) - -func newHeader() *widgets.Paragraph { - widget := widgets.NewParagraph() - widget.Text = "Press q to quit, Press or to switch tabs" - widget.SetRect(0, 0, 50, 1) - widget.Border = false - widget.TextStyle.Bg = ui.ColorBlue - return widget -} - -func newConnectorsView() *ui.Grid { - grid := ui.NewGrid() - - termWidth, termHeight := ui.TerminalDimensions() - grid.SetRect(0, headerHeight, termWidth, termHeight) - - var conn [connectorsCount + 1]*widgets.Paragraph //ui.GridItem - - for i := 0; i <= connectorsCount; i++ { - p := widgets.NewParagraph() - p.Text = fmt.Sprintf("No data: #%2.d", i) - p.Title = fmt.Sprintf("Connector: #%2.d", i) - //p.SetRect(0, 0, 50, 30) - p.TextStyle.Bg = ui.ColorBlue - p.TextStyle.Fg = ui.ColorWhite - p.BorderStyle.Fg = ui.ColorYellow - p.Border = true - - connUI[i] = p - conn[i] = p //ui.NewCol(1.0/6, p) - } - - grid.Set( - ui.NewRow( - 1.0/2, - ui.NewCol(1.0/4, conn[1]), - ui.NewCol(1.0/4, conn[2]), - ui.NewCol(1.0/4, conn[3]), - ui.NewCol(1.0/4, conn[4]), - ), - ui.NewRow( - 1.0/2, - ui.NewCol(1.0/4, conn[5]), - ui.NewCol(1.0/4, conn[6]), - ui.NewCol(1.0/4, conn[0]), - ), - ) - - return grid -} - -func newContactorsView() *ui.Grid { - grid := ui.NewGrid() - - termWidth, termHeight := ui.TerminalDimensions() - grid.SetRect(0, headerHeight, termWidth, termHeight) - - var cont [contactorsCount + 1]ui.GridItem - - //var contactors = make([]ui.GridItem, contactorsCount) - for i := 1; i <= contactorsCount; i++ { - p := widgets.NewParagraph() - p.Text = fmt.Sprintf("No data: #%2.d", i) - p.Title = fmt.Sprintf("Contactor: #%2.d", i) - p.Border = false - p.TextStyle.Bg = ui.ColorBlue - p.TextStyle.Fg = ui.ColorWhite - p.BorderStyle.Fg = ui.ColorYellow - p.Border = true - - contUI[i] = p - cont[i] = ui.NewCol(1.0/6, p) - } - - grid.Set( - ui.NewRow( - 1.0/3, - cont[1], - cont[2], - cont[3], - cont[4], - cont[5], - cont[6], - ), - ui.NewRow( - 1.0/3, - cont[7], - cont[8], - cont[9], - cont[10], - cont[11], - cont[12], - ), - ui.NewRow( - 1.0/3, - cont[13], - cont[14], - cont[15], - cont[16], - cont[17], - cont[18], - )) - - //ui.NewRow(1, ui.InterfaceSlice(contactors)...) - grid.Set() - - return grid -} - -func newContactorsErrView() *widgets.Paragraph { - p := widgets.NewParagraph() - p.Text = "No data\n" - p.Title = "Contactors Errors" - p.SetRect(5, 5, 55, 15) - p.BorderStyle.Fg = ui.ColorYellow - - return p -} - -func updateContactorsView(unitId uint) { - p := contUI[unitId] - s := contactors[unitId].state - - if s == nil || p == nil { - return - } - - p.Text = fmt.Sprintf( - "BoardReady: %s\nContactorOn: %s\nUnexpectedState: %s\nIsolated: %s\nDebug: %s", - s.ContactorReady, - s.ContactorOn, - s.UnexpectedState, - s.Isolated, - s.DebugEnabled) - - if s.ContactorReady == yabl.BOARD_READY_OK { - p.TextStyle.Bg = ui.ColorClear - } else { - p.TextStyle.Bg = ui.ColorRed - } - - if s.ContactorOn == yabl.ON { - p.TitleStyle.Bg = ui.ColorBlue - } else { - p.TitleStyle.Bg = ui.ColorClear - } -} - -func updateConnectorsView(unitId uint) { - p := connUI[unitId] - s := connectors[unitId].state - e := connectors[unitId].energy - - if s == nil || e == nil { - return - } - - fstring := "ConnectorInsert %s\n" + - "ContactorOn %s\n" + - "ConnectorLocked %s\n" + - "LineLevel %s\n" + - "IsolationState %s\n" + - "ChargingAllowed %s\n" + - "PwmEnabled %s\n" + - "CpLineVoltage %s\n" + - "V2GMode %s\n" + - "VoltageBefore %s\n" + - "VoltageAfter %s\n" + - "PresentCurrent %s" - - p.Text = fmt.Sprintf( - fstring, - s.ConnectorInsert, - s.ContactorOn, - s.ConnectorLocked, - s.CpLineLevel, - s.IsolationState, - s.ChargingAllowed, - s.PwmEnabled, - s.CpLineVoltage, - e.V2GMode, - e.VoltageBefore, - e.VoltageAfter, - e.PresentCurrent) -} - -func updateContactorsStateView() { - p := contactorsErr - - if contactors[1] == nil { - return - } - - e := contactors[1].errors - - if e == nil { - return - } - - p.Text = fmt.Sprintf( - "BoardReady: %s\nOtherError: %s\nGroupChanged: %s\nUnexpectedFormation: %s\nCpuNotReady: %s\nPuNotReady: %s\nDebug: %s", - e.BoardReady, - e.OtherError, - e.ContactorGroupChanged, - e.UnexpectedFormation, - e.CpuNotReady, - e.PuNotReady, - e.Debug, - ) - - if e.BoardReady == yabl.BOARD_READY_OK { - p.TextStyle.Bg = ui.ColorClear - } else { - p.TextStyle.Bg = ui.ColorRed - } -} diff --git a/yabl/const.go b/yabl/const.go new file mode 100644 index 0000000..2acd615 --- /dev/null +++ b/yabl/const.go @@ -0,0 +1,281 @@ +package yabl + +const ( + CONVERTERS_MAX = 18 + 1 + CONTACTOR_MAX = 18 + 1 + CONNECTOR_COUNT = 6 + CONNECTOR_MAX = CONNECTOR_COUNT + 1 + ALL_BITS = 0xFFFFFFFFFFFFFFFF + UNIT_ID_OFFSET = 12 + UNIT_ID_MASK = 0b111111111111 << UNIT_ID_OFFSET + ACTION_ID_MASK = 0b111111111111 + BOARD_READY_OK BoardReadyType = 0 + BOARD_READY_INFO BoardReadyType = 1 + BOARD_READY_WARNING BoardReadyType = 2 + BOARD_READY_DEBUG BoardReadyType = 3 + BOARD_READY_DEP_ERROR BoardReadyType = 4 + BOARD_READY_ERROR BoardReadyType = 5 + BOARD_READY_CRITICAL BoardReadyType = 6 + OFF BooleanType = 0 + ON BooleanType = 1 + NO_ERROR ErrorType = 0 + ERROR ErrorType = 1 + OTHER_NO_ERROR ContactorInternalOtherErrorType = 0 + NO_PENDING_CHANGES ContactorGroupChangedType = 0 + INITIALIZED_CHANGE ContactorGroupChangedType = 1 + CHANGE_IN_PROGRESS ContactorGroupChangedType = 2 + V2G_MODE_G2V V2GModeType = 0 + V2G_MODE_V2G V2GModeType = 1 + V2G_MODE_INV V2GModeType = 2 + NOT_ENABLE CpLineLevelType = 0 + TWELVE CpLineLevelType = 1 + NINE CpLineLevelType = 2 + SIX CpLineLevelType = 3 + THREE CpLineLevelType = 4 + MINUS_TWELVE CpLineLevelType = 5 + ISOLATION_STATE_UNKNOWN IsolationStateType = 0 + ONGOING IsolationStateType = 1 + PASSED IsolationStateType = 2 + WARNING IsolationStateType = 3 + FAILED IsolationStateType = 4 + AUTH AuthModeType = 0 + PNC AuthModeType = 1 + AUTH_STATE_UNKNOWN AuthStateType = 0 + AUTH_STATE_ALLOW AuthStateType = 1 + AUTH_STATE_DENY AuthStateType = 2 + CONTACTOR_NO_MODE ContactorModeType = 0 + CONTACTOR_TRANSACTION_PROCESS ContactorModeType = 1 + CONTACTOR_CUSTOM_MODE ContactorModeType = 2 + CONTACTOR_ONLY_ONE_OUT_MODE ContactorModeType = 3 + CONTACTOR_ONE_TO_ONE_OUT_MODE ContactorModeType = 4 + CONTACTOR_SIMPLE_DYNAMIC_MODE ContactorModeType = 5 + DEBUG_SWITCH_MODE_AUTO DebugSwitchModeType = 0 + DEBUG_SWITCH_MODE_OFF DebugSwitchModeType = 1 + DEBUG_SWITCH_MODE_ON DebugSwitchModeType = 2 + DEBUG_SWITCH_MODE_PERMANENT_OFF DebugSwitchModeType = 4 + DEBUG_SWITCH_MODE_PERMANENT_ON DebugSwitchModeType = 5 + + PCpuPresentEnergy AName = "CpuPresentEnergy" + PCpuPeriphery AName = "CpuPeriphery" + PCpuEnergySettings AName = "CpuEnergySettings" + PCpuErrors AName = "CpuErrors" + PCpuDebug AName = "CpuDebug" + PPuPresentEnergy AName = "PuPresentEnergy" + PPuPeriphery AName = "PuPeriphery" + PPuErrors AName = "PuErrors" + PPuDebug AName = "PuDebug" + PSeccTargetEnergy AName = "SeccTargetEnergy" + PSeccErrors AName = "SeccErrors" + PLogicAuth AName = "LogicAuth" + PLogicEnergyMode AName = "LogicEnergyMode" + PLogicErrors AName = "LogicErrors" + PLogicWorkingMode AName = "LogicWorkingMode" + PContactorInternalState AName = "ContactorInternalState" + PContactorInternalErrors AName = "ContactorInternalErrors" + PContactorsInternalForce AName = "ContactorsInternalForce" + PContactorInternalDebug AName = "ContactorInternalDebug" + PPeripheryState AName = "PeripheryState" + PPeripheryInfo AName = "PeripheryInfo" + PPeripheryDebug AName = "PeripheryDebug" + PConverterPresentEnergy AName = "ConverterPresentEnergy" + PConverterErrors AName = "ConverterErrors" + PConverterDebug AName = "ConverterDebug" + + FContactorReady FName = "ContactorReady" + FContactorOn FName = "ContactorOn" + FUnexpectedState FName = "UnexpectedState" + FIsolated FName = "Isolated" + FDebugEnabled FName = "DebugEnabled" + + FBoardReady FName = "BoardReady" + FOtherError FName = "OtherError" + FContactorGroupChanged FName = "ContactorGroupChanged" + FUnexpectedFormation FName = "UnexpectedFormation" + FCpuNotReady FName = "CpuNotReady" + FPuNotReady FName = "PuNotReady" + FDebug FName = "Debug" + FPresentContactorMode FName = "PresentContactorMode" + + FForceModeEnabled FName = "ForceModeEnabled" + FForceModeValue FName = "ForceModeValue" + + FDebugModeOn FName = "DebugModeOn" + FDebugContactorOn FName = "DebugContactorOn" + + FV2GMode FName = "V2GMode" + FVoltageBefore FName = "VoltageBefore" + FVoltageAfter FName = "VoltageAfter" + FPresentCurrent FName = "PresentCurrent" + + FConnectorInsert FName = "ConnectorInsert" + + // FContactorOn FName = "ContactorOn" + + FConnectorLocked FName = "ConnectorLocked" + FCpLineLevel FName = "CpLineLevel" + FIsolationState FName = "IsolationState" + FChargingAllowed FName = "ChargingAllowed" + FPwmEnabled FName = "PwmEnabled" + FCpLineVoltage FName = "CpLineVoltage" + + FAuthMode FName = "AuthMode" + FAuthState FName = "AuthState" + + FV2gMode FName = "V2gMode" + FCurrentMax FName = "CurrentMax" + FVoltageMax FName = "VoltageMax" + FPowerMax FName = "PowerMax" + + // FBoardReady FName = "BoardReady" + + FNotReadySettings FName = "NotReadySettings" + + FTargetContactorMode FName = "TargetContactorMode" + FAvailability FName = "Availability" + + FPowerDirectionMode FName = "PowerDirectionMode" + + // FPresentCurrent FName = "PresentCurrent" + + FPresentVoltage FName = "PresentVoltage" + + FContactorInput FName = "ContactorInput" + FCircuitBreakerInput FName = "CircuitBreakerInput" + FCircuitBreakerPowerCBInput FName = "CircuitBreakerPowerCBInput" + + // FCurrentMax FName = "CurrentMax" + // FVoltageMax FName = "VoltageMax" + // FPowerMax FName = "PowerMax" + + FTargetBatteryVoltage FName = "TargetBatteryVoltage" + FTargetGoalVoltage FName = "TargetGoalVoltage" + + // FBoardReady FName = "BoardReady" + // FOtherError FName = "OtherError" + + FRedButtonHard FName = "RedButtonHard" + FRedButtonSoft FName = "RedButtonSoft" + FModulesGone FName = "ModulesGone" + FGridVoltageHighErr FName = "GridVoltageHighErr" + FGridVoltageHighWarn FName = "GridVoltageHighWarn" + FGridVoltageLowWarn FName = "GridVoltageLowWarn" + FGridVoltageLowErr FName = "GridVoltageLowErr" + FGridVoltageLow FName = "GridVoltageLow" + FGridVoltageHigh FName = "GridVoltageHigh" + FGridVoltageEmpty FName = "GridVoltageEmpty" + FNotReadySecc FName = "NotReadySecc" + FNotReadyPu FName = "NotReadyPu" + FNotReadyContactors FName = "NotReadyContactors" + FDebugConvertersEnabled FName = "DebugConvertersEnabled" + FContactorInputError FName = "ContactorInputError" + FNotReadyPeriphery FName = "NotReadyPeriphery" + + // FDebugModeOn FName = "DebugModeOn" + + FDebugContactorInputOn FName = "DebugContactorInputOn" + FDebugCircuitBreakerOn FName = "DebugCircuitBreakerOn" + FDebugRedButtonSoftware FName = "DebugRedButtonSoftware" + + // FBoardReady FName = "BoardReady" + // FOtherError FName = "OtherError" + + FIncorrectVoltage FName = "IncorrectVoltage" + FIncorrectVoltageValue FName = "IncorrectVoltageValue" + FIncorrectCurrent FName = "IncorrectCurrent" + FIncorrectCurrentValue FName = "IncorrectCurrentValue" + FIsolationBroken FName = "IsolationBroken" + FCpLineBroken FName = "CpLineBroken" + FCpLineGap69 FName = "CpLineGap69" + FCableReady FName = "CableReady" + FNotReadyCpu FName = "NotReadyCpu" + + // FNotReadySecc FName = "NotReadySecc" + + FContactorOutputError FName = "ContactorOutputError" + FDebugContactorOutputEnabled FName = "DebugContactorOutputEnabled" + FOutputCircuitBreakerEnabled FName = "OutputCircuitBreakerEnabled" + FOutputCircuitBreakerEnabledValue FName = "OutputCircuitBreakerEnabledValue" + + // FDebugModeOn FName = "DebugModeOn" + + FDebugContactorOutputOn FName = "DebugContactorOutputOn" + + FTargetChargingAllow FName = "TargetChargingAllow" + + // FTargetBatteryVoltage FName = "TargetBatteryVoltage" + // FTargetGoalVoltage FName = "TargetGoalVoltage" + + FTargetCurrent FName = "TargetCurrent" + + // FBoardReady FName = "BoardReady" + + FNotReadyLogic FName = "NotReadyLogic" + + FOtherErrorSeverity FName = "OtherErrorSeverity" + + // FOtherError FName = "OtherError" + + FErrorShakeSensor FName = "ErrorShakeSensor" + FErrorCoolingGroup FName = "ErrorCoolingGroup" + FPeripheryErrorCoolingGroup FName = "PeripheryErrorCoolingGroup" + FErrorFireEmergency FName = "ErrorFireEmergency" + FErrorFireEmergencyRun FName = "ErrorFireEmergencyRun" + FErrorFireEmergencyControl FName = "ErrorFireEmergencyControl" + FErrorOvervoltageIn FName = "ErrorOvervoltageIn" + FPeripheryErrorPowerSupply FName = "PeripheryErrorPowerSupply" + FErrorFan FName = "ErrorFan" + FErrorOvervoltageOut FName = "ErrorOvervoltageOut" + FErrorStateRemoteMode FName = "ErrorStateRemoteMode" + FDebugShsnFanEnabled FName = "DebugShsnFanEnabled" + FDebugShptFanEnabled FName = "DebugShptFanEnabled" + FDebugIoBoardTestLampEnabled FName = "DebugIoBoardTestLampEnabled" + FErrorFireEmergencyCircuitBreaker FName = "ErrorFireEmergencyCircuitBreaker" + FErrorExtLightCircuitBreaker FName = "ErrorExtLightCircuitBreaker" + FErrorIndicationCircuitBreaker FName = "ErrorIndicationCircuitBreaker" + FErrorLowVoltagePowerCircuitBreaker FName = "ErrorLowVoltagePowerCircuitBreaker" + FErrorContactorsInternalCircuitBreaker FName = "ErrorContactorsInternalCircuitBreaker" + FErrorPlcCircuitBreaker FName = "ErrorPlcCircuitBreaker" + + FInfoDoorOpen FName = "InfoDoorOpen" + FTempAirIn FName = "TempAirIn" + FTempAirOut FName = "TempAirOut" + FStateShsnFan FName = "StateShsnFan" + FStateShptFan FName = "StateShptFan" + + // FDebugModeOn FName = "DebugModeOn" + + FDebugShsnFan FName = "DebugShsnFan" + FDebugShptFan FName = "DebugShptFan" + FDebugIoBoardTestLamp FName = "DebugIoBoardTestLamp" + + // FV2gMode FName = "V2gMode" + // FPresentVoltage FName = "PresentVoltage" + // FPresentCurrent FName = "PresentCurrent" + + FConnectedOut FName = "ConnectedOut" + + // FBoardReady FName = "BoardReady" + // FOtherError FName = "OtherError" + + FNotConnectedOut FName = "NotConnectedOut" + FNoCommunicationConverter FName = "NoCommunicationConverter" + FNoCommunicationPuConverter FName = "NoCommunicationPuConverter" + FInputGridVoltageHigh FName = "InputGridVoltageHigh" + FInputGridVoltageLow FName = "InputGridVoltageLow" + FOutputGridVoltageHigh FName = "OutputGridVoltageHigh" + FOutputGridVoltageLow FName = "OutputGridVoltageLow" + FInputGridVoltage FName = "InputGridVoltage" + FOutputGridVoltage FName = "OutputGridVoltage" + FShortCircuit FName = "ShortCircuit" + FOverHeat FName = "OverHeat" + FFanBroken FName = "FanBroken" + FOtherHardwareError FName = "OtherHardwareError" + FDebugConvEnabled FName = "DebugConvEnabled" + FDebugConvDisabled FName = "DebugConvDisabled" + + // FDebugModeOn FName = "DebugModeOn" + + FDebugEnergyOn FName = "DebugEnergyOn" + FDebugTargetVoltage FName = "DebugTargetVoltage" + FDebugTargetCurrent FName = "DebugTargetCurrent" +) diff --git a/yabl/init.go b/yabl/init.go new file mode 100644 index 0000000..b910d9f --- /dev/null +++ b/yabl/init.go @@ -0,0 +1,406 @@ +package yabl + +import "cli-mon/can" + +func (c *converter) initialize() { + c.protocolMap = make(map[key]action) + + for i := uint(1); i <= CONNECTOR_COUNT; i++ { + key := key{can.CAN_ID_011, i} + cpe := &CpuPresentEnergy{unit: 1} + c.cpuPresentEnergyArray[i] = cpe + fields := []*field{ + {length: 2, setter: cpe.setPowerDirectionMode, name: FPowerDirectionMode}, + {length: 10, setter: cpe.setPresentCurrent, name: FPresentCurrent}, + {length: 11, setter: cpe.setPresentVoltage, name: FPresentVoltage}, + } + c.protocolMap[key] = action{fields: fields, interval: 50, name: PCpuPresentEnergy, object: cpe} + } + + c.cpuPeripheryInstance = &CpuPeriphery{unit: 0} + fields := []*field{ + {length: 2, setter: c.cpuPeripheryInstance.setContactorInput, name: FContactorInput}, + {length: 2, setter: c.cpuPeripheryInstance.setCircuitBreakerInput, name: FCircuitBreakerInput}, + {length: 2, setter: c.cpuPeripheryInstance.setCircuitBreakerPowerCBInput, name: FCircuitBreakerPowerCBInput}, + } + c.protocolMap[key{can.CAN_ID_014, 0}] = action{ + fields: fields, + interval: 1000, + name: PCpuPeriphery, + object: c.cpuPeripheryInstance, + } + + for i := uint(0); i <= CONNECTOR_COUNT; i++ { + key := key{can.CAN_ID_015, i} + ces := &CpuEnergySettings{unit: unit(i)} + c.cpuEnergySettingsArray[i] = ces + fields := []*field{ + {length: 10, setter: ces.setCurrentMax, name: FCurrentMax}, + {length: 11, setter: ces.setVoltageMax, name: FVoltageMax}, + {length: 14, setter: ces.setPowerMax, name: FPowerMax}, + {length: 11, setter: ces.setTargetBatteryVoltage, name: FTargetBatteryVoltage}, + {length: 11, setter: ces.setTargetGoalVoltage, name: FTargetGoalVoltage}, + } + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PCpuEnergySettings, object: ces} + } + + c.cpuErrorsInstance = &CpuErrors{unit: 0} + fields = []*field{ + {length: 3, setter: c.cpuErrorsInstance.setBoardReady, name: FBoardReady}, + {length: 4, setter: c.cpuErrorsInstance.setOtherError, name: FOtherError}, + {length: 2, setter: c.cpuErrorsInstance.setRedButtonHard, name: FRedButtonHard}, + {length: 2, setter: c.cpuErrorsInstance.setRedButtonSoft, name: FRedButtonSoft}, + {length: 2, setter: c.cpuErrorsInstance.setModulesGone, name: FModulesGone}, + {length: 2, setter: c.cpuErrorsInstance.setGridVoltageHighErr, name: FGridVoltageHighErr}, + {length: 2, setter: c.cpuErrorsInstance.setGridVoltageHighWarn, name: FGridVoltageHighWarn}, + {length: 2, setter: c.cpuErrorsInstance.setGridVoltageLowWarn, name: FGridVoltageLowWarn}, + {length: 2, setter: c.cpuErrorsInstance.setGridVoltageLowErr, name: FGridVoltageLowErr}, + {length: 11, setter: c.cpuErrorsInstance.setGridVoltageLow, name: FGridVoltageLow}, + {length: 11, setter: c.cpuErrorsInstance.setGridVoltageHigh, name: FGridVoltageHigh}, + {length: 2, setter: c.cpuErrorsInstance.setGridVoltageEmpty, name: FGridVoltageEmpty}, + {length: 2, setter: c.cpuErrorsInstance.setNotReadySecc, name: FNotReadySecc}, + {length: 2, setter: c.cpuErrorsInstance.setNotReadyPu, name: FNotReadyPu}, + {length: 2, setter: c.cpuErrorsInstance.setNotReadyContactors, name: FNotReadyContactors}, + {length: 2, setter: c.cpuErrorsInstance.setDebugConvertersEnabled, name: FDebugConvertersEnabled}, + {length: 2, setter: c.cpuErrorsInstance.setContactorInputError, name: FContactorInputError}, + {length: 2, setter: c.cpuErrorsInstance.setNotReadyPeriphery, name: FNotReadyPeriphery}, + } + c.protocolMap[key{can.CAN_ID_016, 0}] = action{ + fields: fields, + interval: 1000, + name: PCpuErrors, + object: c.cpuErrorsInstance, + } + + c.cpuDebugInstance = &CpuDebug{unit: 0} + fields = []*field{ + {length: 2, setter: c.cpuDebugInstance.setDebugModeOn, name: FDebugModeOn}, + {length: 3, setter: c.cpuDebugInstance.setDebugContactorInputOn, name: FDebugContactorInputOn}, + {length: 3, setter: c.cpuDebugInstance.setDebugCircuitBreakerOn, name: FDebugCircuitBreakerOn}, + {length: 3, setter: c.cpuDebugInstance.setDebugRedButtonSoftware, name: FDebugRedButtonSoftware}, + } + c.protocolMap[key{can.CAN_ID_01A, 0}] = action{ + fields: fields, + interval: 1000, + name: PCpuDebug, + object: c.cpuDebugInstance, + } + + for i := uint(1); i <= CONNECTOR_COUNT; i++ { + key := key{can.CAN_ID_021, i} + ppe := &PuPresentEnergy{unit: unit(i)} + c.puPresentEnergyArray[i] = ppe + fields := []*field{ + {length: 2, setter: ppe.setV2GMode, name: FV2GMode}, + {length: 11, setter: ppe.setVoltageBefore, name: FVoltageBefore}, + {length: 11, setter: ppe.setVoltageAfter, name: FVoltageAfter}, + {length: 10, setter: ppe.setPresentCurrent, name: FPresentCurrent}, + } + c.protocolMap[key] = action{fields: fields, interval: 50, name: PPuPresentEnergy, object: ppe} + } + + for i := uint(1); i <= CONNECTOR_COUNT; i++ { + key := key{can.CAN_ID_022, i} + pp := &PuPeriphery{unit: unit(i)} + c.puPeripheryArray[i] = pp + fields := []*field{ + {length: 2, setter: pp.setConnectorInsert, name: FConnectorInsert}, + {length: 2, setter: pp.setContactorOn, name: FContactorOn}, + {length: 2, setter: pp.setConnectorLocked, name: FConnectorLocked}, + {length: 3, setter: pp.setCpLineLevel, name: FCpLineLevel}, + {length: 3, setter: pp.setIsolationState, name: FIsolationState}, + {length: 2, setter: pp.setChargingAllowed, name: FChargingAllowed}, + {length: 2, setter: pp.setPwmEnabled, name: FPwmEnabled}, + {length: 9, setter: pp.setCpLineVoltage, name: FCpLineVoltage}, + } + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PPuPeriphery, object: pp} + } + + for i := uint(1); i <= CONNECTOR_COUNT; i++ { + key := key{can.CAN_ID_023, i} + pe := &PuErrors{unit: 1} + c.puErrorsArray[i] = pe + fields := []*field{ + {length: 3, setter: pe.setBoardReady, name: FBoardReady}, + {length: 4, setter: pe.setOtherError, name: FOtherError}, + {length: 2, setter: pe.setIncorrectVoltage, name: FIncorrectVoltage}, + {length: 11, setter: pe.setIncorrectVoltageValue, name: FIncorrectVoltageValue}, + {length: 2, setter: pe.setIncorrectCurrent, name: FIncorrectCurrent}, + {length: 10, setter: pe.setIncorrectCurrentValue, name: FIncorrectCurrentValue}, + {length: 2, setter: pe.setIsolationBroken, name: FIsolationBroken}, + {length: 2, setter: pe.setCpLineBroken, name: FCpLineBroken}, + {length: 2, setter: pe.setCpLineGap69, name: FCpLineGap69}, + {length: 3, setter: pe.setCableReady, name: FCableReady}, + {length: 2, setter: pe.setNotReadyCpu, name: FNotReadyCpu}, + {length: 2, setter: pe.setNotReadySecc, name: FNotReadySecc}, + {length: 2, setter: pe.setContactorOutputError, name: FContactorOutputError}, + {length: 2, setter: pe.setDebugContactorOutputEnabled, name: FDebugContactorOutputEnabled}, + {length: 2, setter: pe.setOutputCircuitBreakerEnabled, name: FOutputCircuitBreakerEnabled}, + {length: 12, setter: pe.setOutputCircuitBreakerEnabledValue, name: FOutputCircuitBreakerEnabledValue}, + } + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PPuErrors, object: pe} + } + + for i := uint(0); i <= CONNECTOR_COUNT; i++ { + key := key{can.CAN_ID_02A, i} + pd := &PuDebug{unit: unit(i)} + c.puDebugArray[i] = pd + fields = []*field{ + {length: 2, setter: pd.setDebugModeOn, name: FDebugModeOn}, + {length: 3, setter: pd.setDebugContactorOutputOn, name: FDebugContactorOutputOn}, + } + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PPuDebug, object: pd} + } + + for i := uint(1); i <= CONNECTOR_COUNT; i++ { + key := key{can.CAN_ID_041, i} + ste := &SeccTargetEnergy{unit: unit(i)} + c.seccTargetEnergyArray[i] = ste + fields = []*field{ + {length: 2, setter: ste.setTargetChargingAllow, name: FTargetChargingAllow}, + {length: 11, setter: ste.setTargetBatteryVoltage, name: FTargetBatteryVoltage}, + {length: 11, setter: ste.setTargetGoalVoltage, name: FTargetGoalVoltage}, + {length: 10, setter: ste.setTargetCurrent, name: FTargetCurrent}, + } + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PSeccTargetEnergy, object: ste} + } + + for i := uint(1); i <= CONNECTOR_COUNT; i++ { + key := key{can.CAN_ID_042, i} + se := &SeccErrors{unit: unit(i)} + c.seccErrorsArray[i] = se + fields = []*field{ + {length: 3, setter: se.setBoardReady, name: FBoardReady}, + {length: 2, setter: se.setNotReadyLogic, name: FNotReadyLogic}, + } + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PSeccErrors, object: se} + } + + for i := uint(0); i <= CONNECTOR_COUNT; i++ { + key := key{can.CAN_ID_046, i} + la := &LogicAuth{unit: unit(i)} + c.logicAuthArray[i] = la + fields = []*field{ + {length: 2, setter: la.setAuthMode, name: FAuthMode}, + {length: 3, setter: la.setAuthState, name: FAuthState}, + } + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PLogicAuth, object: la} + } + + for i := uint(0); i <= CONNECTOR_COUNT; i++ { + key := key{can.CAN_ID_047, i} + lem := &LogicEnergyMode{unit: unit(i)} + c.logicEnergyMode[i] = lem + fields = []*field{ + {length: 2, setter: lem.setV2gMode, name: FV2gMode}, + {length: 10, setter: lem.setCurrentMax, name: FCurrentMax}, + {length: 11, setter: lem.setVoltageMax, name: FVoltageMax}, + {length: 14, setter: lem.setPowerMax, name: FPowerMax}, + } + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PLogicEnergyMode, object: lem} + } + + c.logicErrorsInstance = &LogicErrors{unit: 0} + fields = []*field{ + {length: 3, setter: c.logicErrorsInstance.setBoardReady, name: FBoardReady}, + {length: 2, setter: c.logicErrorsInstance.setNotReadySettings, name: FNotReadySettings}, + } + c.protocolMap[key{can.CAN_ID_048, 0}] = action{ + fields: fields, + interval: 1000, + name: PLogicErrors, + object: c.logicErrorsInstance, + } + + for i := uint(0); i <= CONNECTOR_COUNT; i++ { + key := key{can.CAN_ID_049, i} + lwm := &LogicWorkingMode{unit: unit(i)} + c.logicWorkingMode[i] = lwm + fields = []*field{ + {length: 5, setter: lwm.setTargetContactorMode, name: FTargetContactorMode}, + {length: 2, setter: lwm.setAvailability, name: FAvailability}, + } + c.protocolMap[key] = action{ + fields: fields, + interval: 1000, + name: PLogicWorkingMode, + object: lwm, + } + } + + for i := uint(0); i < CONTACTOR_MAX; i++ { + key := key{can.CAN_ID_071, i} + cis := &ContactorInternalState{unit: unit(i)} + c.contactorInternalStateArray[i] = cis + fields = []*field{ + {length: 3, setter: cis.setContactorReady, name: FContactorReady}, + {length: 2, setter: cis.setContactorOn, name: FContactorOn}, + {length: 2, setter: cis.setUnexpectedState, name: FUnexpectedState}, + {length: 2, setter: cis.setIsolated, name: FIsolated}, + {length: 2, setter: cis.setDebugEnabled, name: FDebugEnabled}, + } + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PContactorInternalState, object: cis} + } + + c.contactorInternalErrorsInstance = &ContactorInternalErrors{unit: 0} + fields = []*field{ + {length: 3, setter: c.contactorInternalErrorsInstance.setBoardReady, name: FBoardReady}, + {length: 4, setter: c.contactorInternalErrorsInstance.setOtherError, name: FOtherError}, + {length: 3, setter: c.contactorInternalErrorsInstance.setContactorGroupChanged, name: FContactorGroupChanged}, + {length: 4, setter: c.contactorInternalErrorsInstance.setUnexpectedFormation, name: FUnexpectedFormation}, + {length: 2, setter: c.contactorInternalErrorsInstance.setCpuNotReady, name: FCpuNotReady}, + {length: 2, setter: c.contactorInternalErrorsInstance.setPuNotReady, name: FPuNotReady}, + {length: 2, setter: c.contactorInternalErrorsInstance.setDebug, name: FDebug}, + {length: 5, setter: c.contactorInternalErrorsInstance.setPresentContactorMode, name: FPresentContactorMode}, + } + c.protocolMap[key{can.CAN_ID_073, 0}] = action{ + fields: fields, + interval: 1000, + name: PContactorInternalErrors, + object: c.contactorInternalErrorsInstance, + } + + c.contactorsInternalForce = &ContactorsInternalForce{unit: 0} + fields = []*field{ + {length: 2, setter: c.contactorsInternalForce.setForceModeEnabled, name: FForceModeEnabled}, + {length: 4, setter: c.contactorsInternalForce.setForceModeValue, name: FForceModeValue}, + } + c.protocolMap[key{can.CAN_ID_074, 0}] = action{ + fields: fields, + interval: 1000, + name: PContactorsInternalForce, + object: c.contactorsInternalForce, + } + + for i := uint(0); i < CONTACTOR_MAX; i++ { + key := key{can.CAN_ID_075, i} + cid := &ContactorInternalDebug{unit: unit(i)} + c.contactorInternalDebugArray[i] = cid + fields = []*field{ + {length: 2, setter: cid.setDebugModeOn, name: FDebugModeOn}, + {length: 3, setter: cid.setDebugContactorOn, name: FDebugContactorOn}, + } + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PContactorInternalDebug, object: cid} + } + + for i := uint(0); i <= CONNECTOR_COUNT; i++ { + key := key{can.CAN_ID_067, i} + ps := &PeripheryState{unit: unit(i)} + c.peripheryStateArray[i] = ps + fields = []*field{ + {length: 3, setter: ps.setOtherErrorSeverity, name: FOtherErrorSeverity}, + {length: 4, setter: ps.setOtherError, name: FOtherError}, + {length: 2, setter: ps.setErrorShakeSensor, name: FErrorShakeSensor}, + {length: 2, setter: ps.setErrorCoolingGroup, name: FErrorCoolingGroup}, + {length: 2, setter: ps.setPeripheryErrorCoolingGroup, name: FPeripheryErrorCoolingGroup}, + {length: 2, setter: ps.setErrorFireEmergency, name: FErrorFireEmergency}, + {length: 2, setter: ps.setErrorFireEmergencyRun, name: FErrorFireEmergencyRun}, + {length: 2, setter: ps.setErrorFireEmergencyControl, name: FErrorFireEmergencyControl}, + {length: 2, setter: ps.setErrorOvervoltageIn, name: FErrorOvervoltageIn}, + {length: 2, setter: ps.setPeripheryErrorPowerSupply, name: FPeripheryErrorPowerSupply}, + {length: 2, setter: ps.setErrorFan, name: FErrorFan}, + {length: 2, setter: ps.setErrorOvervoltageOut, name: FErrorOvervoltageOut}, + {length: 2, setter: ps.setErrorStateRemoteMode, name: FErrorStateRemoteMode}, + {length: 2, setter: ps.setDebugShsnFanEnabled, name: FDebugShsnFanEnabled}, + {length: 2, setter: ps.setDebugShptFanEnabled, name: FDebugShptFanEnabled}, + {length: 2, setter: ps.setDebugIoBoardTestLampEnabled, name: FDebugIoBoardTestLampEnabled}, + {length: 2, setter: ps.setErrorFireEmergencyCircuitBreaker, name: FErrorFireEmergencyCircuitBreaker}, + {length: 2, setter: ps.setErrorExtLightCircuitBreaker, name: FErrorExtLightCircuitBreaker}, + {length: 2, setter: ps.setErrorIndicationCircuitBreaker, name: FErrorIndicationCircuitBreaker}, + {length: 2, setter: ps.setErrorLowVoltagePowerCircuitBreaker, name: FErrorLowVoltagePowerCircuitBreaker}, + {length: 2, setter: ps.setErrorContactorsInternalCircuitBreaker, name: FErrorContactorsInternalCircuitBreaker}, + {length: 2, setter: ps.setErrorPlcCircuitBreaker, name: FErrorPlcCircuitBreaker}, + } + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PPeripheryState, object: ps} + } + + for i := uint(0); i <= CONNECTOR_COUNT; i++ { + key := key{can.CAN_ID_068, i} + pi := &PeripheryInfo{unit: unit(i)} + c.peripheryInfoArray[i] = pi + fields = []*field{ + {length: 2, setter: pi.setInfoDoorOpen, name: FInfoDoorOpen}, + {length: 8, setter: pi.setTempAirIn, name: FTempAirIn}, + {length: 8, setter: pi.setTempAirOut, name: FTempAirOut}, + {length: 2, setter: pi.setStateShsnFan, name: FStateShsnFan}, + {length: 2, setter: pi.setStateShptFan, name: FStateShptFan}, + } + c.protocolMap[key] = action{fields: fields, interval: 5000, name: PPeripheryInfo, object: pi} + } + + for i := uint(0); i <= CONNECTOR_COUNT; i++ { + key := key{can.CAN_ID_06C, i} + pd := &PeripheryDebug{unit: unit(i)} + c.peripheryDebugArray[i] = pd + fields = []*field{ + {length: 2, setter: pd.setDebugModeOn, name: FDebugModeOn}, + {length: 3, setter: pd.setDebugShsnFan, name: FDebugShsnFan}, + {length: 3, setter: pd.setDebugShptFan, name: FDebugShptFan}, + {length: 3, setter: pd.setDebugIoBoardTestLamp, name: FDebugIoBoardTestLamp}, + } + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PPeripheryDebug, object: pd} + } + + for i := uint(1); i < CONVERTERS_MAX; i++ { + key := key{can.CAN_ID_061, i} + cpe := &ConverterPresentEnergy{unit: unit(i)} + c.converterPresentEnergyArray[i] = cpe + fields = []*field{ + {length: 2, setter: cpe.setV2gMode, name: FV2gMode}, + {length: 11, setter: cpe.setPresentVoltage, name: FPresentVoltage}, + {length: 10, setter: cpe.setPresentCurrent, name: FPresentCurrent}, + {length: 8, setter: cpe.setConnectedOut, name: FConnectedOut}, + } + c.protocolMap[key] = action{fields: fields, interval: 500, name: PConverterPresentEnergy, object: cpe} + } + + for i := uint(1); i < CONVERTERS_MAX; i++ { + key := key{can.CAN_ID_062, i} + ce := &ConverterErrors{unit: unit(i)} + c.converterErrorsArray[i] = ce + fields = []*field{ + {length: 3, setter: ce.setBoardReady, name: FBoardReady}, + {length: 4, setter: ce.setOtherError, name: FOtherError}, + {length: 2, setter: ce.setNotConnectedOut, name: FNotConnectedOut}, + {length: 2, setter: ce.setNoCommunicationConverter, name: FNoCommunicationConverter}, + {length: 2, setter: ce.setNoCommunicationPuConverter, name: FNoCommunicationPuConverter}, + {length: 2, setter: ce.setInputGridVoltageHigh, name: FInputGridVoltageHigh}, + {length: 2, setter: ce.setInputGridVoltageLow, name: FInputGridVoltageLow}, + {length: 2, setter: ce.setOutputGridVoltageHigh, name: FOutputGridVoltageHigh}, + {length: 2, setter: ce.setOutputGridVoltageLow, name: FOutputGridVoltageLow}, + {length: 11, setter: ce.setInputGridVoltage, name: FInputGridVoltage}, + {length: 11, setter: ce.setOutputGridVoltage, name: FOutputGridVoltage}, + {length: 2, setter: ce.setShortCircuit, name: FShortCircuit}, + {length: 2, setter: ce.setOverHeat, name: FOverHeat}, + {length: 2, setter: ce.setFanBroken, name: FFanBroken}, + {length: 2, setter: ce.setOtherHardwareError, name: FOtherHardwareError}, + {length: 2, setter: ce.setDebugConvEnabled, name: FDebugConvEnabled}, + {length: 2, setter: ce.setDebugConvDisabled, name: FDebugConvDisabled}, + } + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PConverterErrors, object: ce} + } + + for i := uint(0); i < CONVERTERS_MAX; i++ { + key := key{can.CAN_ID_065, i} + cd := &ConverterDebug{unit: unit(i)} + c.converterDebugArray[i] = cd + fields = []*field{ + {length: 2, setter: cd.setDebugModeOn, name: FDebugModeOn}, + {length: 3, setter: cd.setDebugEnergyOn, name: FDebugEnergyOn}, + {length: 11, setter: cd.setDebugTargetVoltage, name: FDebugTargetVoltage}, + {length: 10, setter: cd.setDebugTargetCurrent, name: FDebugTargetCurrent}, + } + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PConverterDebug, object: cd} + } + + // set "null" values + for _, element := range c.protocolMap { + var from uint8 = 0 + for _, f := range element.fields { + var mask uint64 = ^(ALL_BITS << f.length) + mask = mask << from + f.value = mask + from += f.length + } + } +} diff --git a/yabl/protocol.go b/yabl/protocol.go index 6b8b908..47bfbfd 100644 --- a/yabl/protocol.go +++ b/yabl/protocol.go @@ -3,253 +3,108 @@ package yabl import ( can "cli-mon/can" "encoding/binary" + time "time" ) -const ( - CONTACTOR_MAX = 18 + 1 - CONNECTOR_MAX = 6 + 1 - ALL_BITS = 0xFFFFFFFFFFFFFFFF - UNIT_ID_OFFSET = 12 - UNIT_ID_MASK = 0b111111111111 << UNIT_ID_OFFSET - ACTION_ID_MASK = 0b111111111111 - BOARD_READY_OK BoardReadyType = 0 - BOARD_READY_INFO BoardReadyType = 1 - BOARD_READY_WARNING BoardReadyType = 2 - BOARD_READY_DEBUG BoardReadyType = 3 - BOARD_READY_DEP_ERROR BoardReadyType = 4 - BOARD_READY_ERROR BoardReadyType = 5 - BOARD_READY_CRITICAL BoardReadyType = 6 - OFF BooleanType = 0 - ON BooleanType = 1 - NO_ERROR ErrorType = 0 - ERROR ErrorType = 1 - OTHER_NO_ERROR ContactorInternalOtherErrorType = 0 - NO_PENDING_CHANGES ContactorGroupChangedType = 0 - INITIALIZED_CHANGE ContactorGroupChangedType = 1 - CHANGE_IN_PROGRESS ContactorGroupChangedType = 2 - V2G_MODE_G2V V2GModeType = 0 - V2G_MODE_V2G V2GModeType = 1 - V2G_MODE_INV V2GModeType = 2 - NOT_ENABLE CpLineLevelType = 0 - TWELVE CpLineLevelType = 1 - NINE CpLineLevelType = 2 - SIX CpLineLevelType = 3 - THREE CpLineLevelType = 4 - MINUS_TWELVE CpLineLevelType = 5 - UNKNOWN IsolationStateType = 0 - ONGOING IsolationStateType = 1 - PASSED IsolationStateType = 2 - WARNING IsolationStateType = 3 - FAILED IsolationStateType = 4 -) - -type Packet interface { - GetUnitId() uint +type action struct { + object Action + fields []*field + interval uint + name AName } -type ContactorInternalState struct { - UnitId uint - ContactorReady BoardReadyType - ContactorOn BooleanType - UnexpectedState ErrorType - Isolated ErrorType - DebugEnabled BooleanType +type field struct { + length uint8 + setter func(uint64 uint64) any + value uint64 + last *time.Time + name FName } -type ContactorInternalErrors struct { - UnitId uint - BoardReady BoardReadyType - OtherError ContactorInternalOtherErrorType - ContactorGroupChanged ContactorGroupChangedType - UnexpectedFormation ContactorInternalOtherErrorType - CpuNotReady ErrorType - PuNotReady ErrorType - Debug BooleanType +type key struct { + canId uint32 + unitId uint } -type PuPresentEnergy struct { - UnitId uint - V2GMode V2GModeType - VoltageBefore Voltage11BitType - VoltageAfter Voltage11BitType - PresentCurrent Current10BitType +type converter struct { + protocolMap map[key]action + cpuPresentEnergyArray [CONNECTOR_MAX]*CpuPresentEnergy + cpuPeripheryInstance *CpuPeriphery + cpuEnergySettingsArray [CONNECTOR_MAX]*CpuEnergySettings + cpuErrorsInstance *CpuErrors + cpuDebugInstance *CpuDebug + puPresentEnergyArray [CONNECTOR_MAX]*PuPresentEnergy + puPeripheryArray [CONNECTOR_MAX]*PuPeriphery + puErrorsArray [CONNECTOR_MAX]*PuErrors + puDebugArray [CONNECTOR_MAX]*PuDebug + seccTargetEnergyArray [CONNECTOR_MAX]*SeccTargetEnergy + seccErrorsArray [CONNECTOR_MAX]*SeccErrors + logicAuthArray [CONNECTOR_MAX]*LogicAuth + logicEnergyMode [CONNECTOR_MAX]*LogicEnergyMode + logicErrorsInstance *LogicErrors + logicWorkingMode [CONNECTOR_MAX]*LogicWorkingMode + contactorInternalStateArray [CONTACTOR_MAX]*ContactorInternalState + contactorInternalErrorsInstance *ContactorInternalErrors + contactorsInternalForce *ContactorsInternalForce + contactorInternalDebugArray [CONTACTOR_MAX]*ContactorInternalDebug + peripheryStateArray [CONNECTOR_MAX]*PeripheryState + peripheryInfoArray [CONNECTOR_MAX]*PeripheryInfo + peripheryDebugArray [CONNECTOR_MAX]*PeripheryDebug + converterPresentEnergyArray [CONVERTERS_MAX]*ConverterPresentEnergy + converterErrorsArray [CONVERTERS_MAX]*ConverterErrors + converterDebugArray [CONVERTERS_MAX]*ConverterDebug } -type PuPeriphery struct { - UnitId uint - ConnectorInsert BooleanType - ContactorOn BooleanType - ConnectorLocked BooleanType - CpLineLevel CpLineLevelType - IsolationState IsolationStateType - ChargingAllowed BooleanType - PwmEnabled BooleanType - CpLineVoltage Voltage9BitType +type Converter interface { + EventsFromFrame(*can.CanFrame) ([]*Event, bool) + CheckTimeouts() ([]*Event, bool) } -type BoardReadyType uint -type BooleanType uint -type ErrorType uint -type ContactorInternalOtherErrorType uint -type ContactorGroupChangedType uint -type V2GModeType uint -type Voltage11BitType uint -type Current10BitType uint -type CpLineLevelType uint -type IsolationStateType uint -type Voltage9BitType float32 +func NewProtocolConverter() Converter { + c := &converter{} + c.initialize() + return c +} -func StartProtocolParsing(frames <-chan *can.CanFrame) <-chan Packet { - result := make(chan Packet) +func (c *converter) EventsFromFrame(frame *can.CanFrame) ([]*Event, bool) { + if frame == nil { + return nil, false + } + 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} - go func() { - defer close(result) - var contactorsFirstState [CONTACTOR_MAX]bool - var contactorsFirstErr [CONTACTOR_MAX]bool - var puFirst [CONNECTOR_MAX]bool - var puPeripheryFirst [CONNECTOR_MAX]bool - - for frame := range frames { - if frames == nil { - continue - } - - var unitId uint = uint((frame.CanId & UNIT_ID_MASK) >> UNIT_ID_OFFSET) - - switch { - case frame.CanId&ACTION_ID_MASK == can.CAN_ID_071: - changed := false - var model = ContactorInternalState{UnitId: unitId} - if val, ok := get(0, 3, frame.Payload); ok && model.ContactorReady != BoardReadyType(val) { - model.ContactorReady = BoardReadyType(val) - changed = true - } - if val, ok := get(3, 2, frame.Payload); ok && model.ContactorOn != BooleanType(val) { - model.ContactorOn = BooleanType(val) - changed = true - } - if val, ok := get(5, 2, frame.Payload); ok && model.UnexpectedState != ErrorType(val) { - model.UnexpectedState = ErrorType(val) - changed = true - } - if val, ok := get(7, 2, frame.Payload); ok && model.Isolated != ErrorType(val) { - model.Isolated = ErrorType(val) - changed = true - } - if val, ok := get(9, 2, frame.Payload); ok && model.DebugEnabled != BooleanType(val) { - model.DebugEnabled = BooleanType(val) - changed = true - } - if changed || !contactorsFirstState[unitId] { - contactorsFirstState[unitId] = true - result <- &model - } - case frame.CanId&ACTION_ID_MASK == can.CAN_ID_073: - changed := false - model := ContactorInternalErrors{UnitId: unitId} - if val, ok := get(0, 3, frame.Payload); ok && model.BoardReady != BoardReadyType(val) { - model.BoardReady = BoardReadyType(val) - changed = true - } - if val, ok := get(3, 4, frame.Payload); ok && model.OtherError != ContactorInternalOtherErrorType(val) { - model.OtherError = ContactorInternalOtherErrorType(val) - changed = true - } - if val, ok := get(7, 3, frame.Payload); ok && model.ContactorGroupChanged != ContactorGroupChangedType(val) { - model.ContactorGroupChanged = ContactorGroupChangedType(val) - changed = true - } - if val, ok := get(10, 4, frame.Payload); ok && model.UnexpectedFormation != ContactorInternalOtherErrorType(val) { - model.UnexpectedFormation = ContactorInternalOtherErrorType(val) - changed = true - } - if val, ok := get(14, 2, frame.Payload); ok && model.CpuNotReady != ErrorType(val) { - model.CpuNotReady = ErrorType(val) - changed = true - } - if val, ok := get(16, 2, frame.Payload); ok && model.PuNotReady != ErrorType(val) { - model.PuNotReady = ErrorType(val) - changed = true - } - if val, ok := get(18, 2, frame.Payload); ok && model.Debug != BooleanType(val) { - model.Debug = BooleanType(val) - changed = true - } - if changed || !contactorsFirstErr[unitId] { - contactorsFirstErr[unitId] = true - result <- &model - } - case frame.CanId&ACTION_ID_MASK == can.CAN_ID_021: - changed := false - model := PuPresentEnergy{UnitId: unitId} - if val, ok := get(0, 2, frame.Payload); ok && model.V2GMode != V2GModeType(val) { - model.V2GMode = V2GModeType(val) - changed = true - } - if val, ok := get(2, 11, frame.Payload); ok && model.VoltageBefore != Voltage11BitType(val) { - model.VoltageBefore = Voltage11BitType(val) - changed = true - } - if val, ok := get(13, 11, frame.Payload); ok && model.VoltageAfter != Voltage11BitType(val) { - model.VoltageAfter = Voltage11BitType(val) - changed = true - } - if val, ok := get(24, 10, frame.Payload); ok && model.PresentCurrent != Current10BitType(val) { - model.PresentCurrent = Current10BitType(val) - changed = true - } - if changed || !puFirst[unitId] { - puFirst[unitId] = true - result <- &model - } - case frame.CanId&ACTION_ID_MASK == can.CAN_ID_022: - changed := false - model := PuPeriphery{UnitId: unitId} - if val, ok := get(0, 2, frame.Payload); ok && model.ConnectorInsert != BooleanType(val) { - model.ConnectorInsert = BooleanType(val) - changed = true - } - if val, ok := get(2, 2, frame.Payload); ok && model.ContactorOn != BooleanType(val) { - model.ContactorOn = BooleanType(val) - changed = true - } - if val, ok := get(4, 2, frame.Payload); ok && model.ConnectorLocked != BooleanType(val) { - model.ConnectorLocked = BooleanType(val) - changed = true - } - if val, ok := get(6, 3, frame.Payload); ok && model.CpLineLevel != CpLineLevelType(val) { - model.CpLineLevel = CpLineLevelType(val) - changed = true - } - if val, ok := get(9, 3, frame.Payload); ok && model.IsolationState != IsolationStateType(val) { - model.IsolationState = IsolationStateType(val) - changed = true - } - if val, ok := get(12, 2, frame.Payload); ok && model.ChargingAllowed != BooleanType(val) { - model.ChargingAllowed = BooleanType(val) - changed = true - } - if val, ok := get(14, 2, frame.Payload); ok && model.PwmEnabled != BooleanType(val) { - model.PwmEnabled = BooleanType(val) - changed = true - } - if val, ok := get(16, 9, frame.Payload); ok && model.CpLineVoltage != (Voltage9BitType(val)*0.1-15) { - model.CpLineVoltage = Voltage9BitType(val)*0.1 - 15 - changed = true - } - if changed || !puPeripheryFirst[unitId] { - puPeripheryFirst[unitId] = true - result <- &model - } + if param, ok := c.protocolMap[k]; ok { + result := make([]*Event, 0, len(param.fields)) + var start uint8 = 0 + for _, f := range param.fields { + if val, found := get(start, f.length, frame.Payload); found { + f.last = frame.Date + if f.value != val { // value changed + f.value = val + obj := f.setter(val) + + event := &Event{ + Field: f.name, + ActionName: param.name, + Object: param.object, + unit: unit(unitId), + Updated: frame.Date, + Value: obj, + } + + result = append(result, event) + } } + start += f.length // next field } - }() - - return result + return result, len(result) > 0 + } + return nil, false } -func get(from uint, size uint, buffer []byte) (uint64, bool) { +func get(from uint8, size uint8, buffer []byte) (uint64, bool) { value := binary.LittleEndian.Uint64(buffer) var mask uint64 = ^(ALL_BITS << size) @@ -263,18 +118,46 @@ func get(from uint, size uint, buffer []byte) (uint64, bool) { } } -func (t ContactorInternalState) GetUnitId() uint { - return t.UnitId +func (u unit) GetUnitId() uint { + return uint(u) } -func (t ContactorInternalErrors) GetUnitId() uint { - return t.UnitId -} +func (c *converter) CheckTimeouts() ([]*Event, bool) { + var multipler uint = 2 + var events []*Event -func (t PuPresentEnergy) GetUnitId() uint { - return t.UnitId -} + for k, param := range c.protocolMap { + now := time.Now() + deadline := now.Add(-time.Duration(param.interval*multipler) * time.Millisecond) -func (t PuPeriphery) GetUnitId() uint { - return t.UnitId + var from uint8 = 0 + + for _, fld := range param.fields { + if fld.last == nil { + continue + } else if deadline.After(*fld.last) { + if events == nil { + events = make([]*Event, 0, len(param.fields)) + } + + event := &Event{ + Field: fld.name, + ActionName: param.name, + Object: param.object, + unit: unit(k.unitId), + Updated: &now, + Value: nil, + } + + var mask uint64 = ^(ALL_BITS << fld.length) + mask = mask << from + fld.value = mask + + events = append(events, event) + fld.last = nil + } + from += fld.length + } + } + return events, events != nil } diff --git a/yabl/setters.go b/yabl/setters.go new file mode 100644 index 0000000..14348dd --- /dev/null +++ b/yabl/setters.go @@ -0,0 +1,913 @@ +package yabl + +func (t *ContactorInternalState) setContactorReady(val uint64) any { + value := BoardReadyType(val) + t.ContactorReady = &value + return &value +} + +func (t *ContactorInternalState) setContactorOn(val uint64) any { + value := BooleanType(val) + t.ContactorOn = &value + return &value +} + +func (t *ContactorInternalState) setUnexpectedState(val uint64) any { + value := ErrorType(val) + t.UnexpectedState = &value + return &value +} + +func (t *ContactorInternalState) setIsolated(val uint64) any { + value := ErrorType(val) + t.Isolated = &value + return &value +} + +func (t *ContactorInternalState) setDebugEnabled(val uint64) any { + value := BooleanType(val) + t.DebugEnabled = &value + return &value +} + +func (t *ContactorInternalErrors) setBoardReady(val uint64) any { + value := BoardReadyType(val) + t.BoardReady = &value + return &value +} + +func (t *ContactorInternalErrors) setOtherError(val uint64) any { + value := ContactorInternalOtherErrorType(val) + t.OtherError = &value + return &value +} + +func (t *ContactorInternalErrors) setContactorGroupChanged(val uint64) any { + value := ContactorGroupChangedType(val) + t.ContactorGroupChanged = &value + return &value +} + +func (t *ContactorInternalErrors) setUnexpectedFormation(val uint64) any { + value := ContactorInternalOtherErrorType(val) + t.UnexpectedFormation = &value + return &value +} + +func (t *ContactorInternalErrors) setCpuNotReady(val uint64) any { + value := ErrorType(val) + t.CpuNotReady = &value + return &value +} + +func (t *ContactorInternalErrors) setPuNotReady(val uint64) any { + value := ErrorType(val) + t.PuNotReady = &value + return &value +} + +func (t *ContactorInternalErrors) setDebug(val uint64) any { + value := BooleanType(val) + t.Debug = &value + return &value +} + +func (t *ContactorInternalErrors) setPresentContactorMode(val uint64) any { + value := ContactorModeType(val) + t.PresentContactorMode = &value + return &value +} + +func (t *PuPresentEnergy) setV2GMode(val uint64) any { + value := V2GModeType(val) + t.V2GMode = &value + return &value +} + +func (t *PuPresentEnergy) setVoltageBefore(val uint64) any { + value := Voltage11BitType(val) + t.VoltageBefore = &value + return &value +} + +func (t *PuPresentEnergy) setVoltageAfter(val uint64) any { + value := Voltage11BitType(val) + t.VoltageAfter = &value + return &value +} + +func (t *PuPresentEnergy) setPresentCurrent(val uint64) any { + value := Current10BitType(val) + t.PresentCurrent = &value + return &value +} + +func (t *PuPeriphery) setConnectorInsert(val uint64) any { + value := BooleanType(val) + t.ConnectorInsert = &value + return &value +} + +func (t *PuPeriphery) setContactorOn(val uint64) any { + value := BooleanType(val) + t.ContactorOn = &value + return &value +} + +func (t *PuPeriphery) setConnectorLocked(val uint64) any { + value := BooleanType(val) + t.ConnectorLocked = &value + return &value +} + +func (t *PuPeriphery) setCpLineLevel(val uint64) any { + value := CpLineLevelType(val) + t.CpLineLevel = &value + return &value +} + +func (t *PuPeriphery) setIsolationState(val uint64) any { + value := IsolationStateType(val) + t.IsolationState = &value + return &value +} + +func (t *PuPeriphery) setChargingAllowed(val uint64) any { + value := BooleanType(val) + t.ChargingAllowed = &value + return &value +} + +func (t *PuPeriphery) setPwmEnabled(val uint64) any { + value := BooleanType(val) + t.PwmEnabled = &value + return &value +} + +func (t *PuPeriphery) setCpLineVoltage(val uint64) any { + value := Voltage9BitType(val)*0.1 - 15 + t.CpLineVoltage = &value + return &value +} + +func (t *LogicAuth) setAuthMode(val uint64) any { + value := AuthModeType(val) + t.AuthMode = &value + return &value +} + +func (t *LogicAuth) setAuthState(val uint64) any { + value := AuthStateType(val) + t.AuthState = &value + return &value +} + +func (l *LogicWorkingMode) setTargetContactorMode(val uint64) any { + value := ContactorModeType(val) + l.TargetContactorMode = &value + return &value +} + +func (l *LogicWorkingMode) setAvailability(val uint64) any { + value := BooleanType(val) + l.Availability = &value + return &value +} + +func (c *CpuPresentEnergy) setPowerDirectionMode(val uint64) any { + value := V2GModeType(val) + c.PowerDirectionMode = &value + return &value +} + +func (c *CpuPresentEnergy) setPresentCurrent(val uint64) any { + value := Current10BitType(val) + c.PresentCurrent = &value + return &value +} + +func (c *CpuPresentEnergy) setPresentVoltage(val uint64) any { + value := Voltage11BitType(val) + c.PresentVoltage = &value + return &value +} + +func (c *CpuPeriphery) setCircuitBreakerInput(val uint64) any { + value := BooleanType(val) + c.CircuitBreakerInput = &value + return &value +} + +func (c *CpuPeriphery) setCircuitBreakerPowerCBInput(val uint64) any { + value := BooleanType(val) + c.CircuitBreakerPowerCBInput = &value + return &value +} + +func (c *CpuPeriphery) setContactorInput(val uint64) any { + value := BooleanType(val) + c.ContactorInput = &value + return &value +} + +func (c *CpuEnergySettings) setCurrentMax(val uint64) any { + value := Current10BitType(val) + c.CurrentMax = &value + return &value +} + +func (c *CpuEnergySettings) setVoltageMax(val uint64) any { + value := Voltage11BitType(val) + c.VoltageMax = &value + return &value +} + +func (c *CpuEnergySettings) setPowerMax(val uint64) any { + value := Power14BitType(val * 100) + c.PowerMax = &value + return &value +} + +func (c *CpuEnergySettings) setTargetBatteryVoltage(val uint64) any { + value := Voltage11BitType(val) + c.TargetBatteryVoltage = &value + return &value +} + +func (c *CpuEnergySettings) setTargetGoalVoltage(val uint64) any { + value := Voltage11BitType(val) + c.TargetGoalVoltage = &value + return &value +} + +func (c *CpuErrors) setBoardReady(val uint64) any { + value := BoardReadyType(val) + c.BoardReady = &value + return &value +} + +func (c *CpuErrors) setOtherError(val uint64) any { + value := OtherError4BitType(val) + c.OtherError = &value + return &value +} + +func (c *CpuErrors) setRedButtonHard(val uint64) any { + value := ErrorType(val) + c.RedButtonHard = &value + return &value +} + +func (c *CpuErrors) setRedButtonSoft(val uint64) any { + value := ErrorType(val) + c.RedButtonSoft = &value + return &value +} + +func (c *CpuErrors) setModulesGone(val uint64) any { + value := ErrorType(val) + c.ModulesGone = &value + return &value +} + +func (c *CpuErrors) setGridVoltageHighErr(val uint64) any { + value := ErrorType(val) + c.GridVoltageHighErr = &value + return &value +} + +func (c *CpuErrors) setGridVoltageHighWarn(val uint64) any { + value := ErrorType(val) + c.GridVoltageHighWarn = &value + return &value +} + +func (c *CpuErrors) setGridVoltageLowWarn(val uint64) any { + value := ErrorType(val) + c.GridVoltageLowWarn = &value + return &value +} + +func (c *CpuErrors) setGridVoltageLowErr(val uint64) any { + value := ErrorType(val) + c.GridVoltageLowErr = &value + return &value +} + +func (c *CpuErrors) setGridVoltageLow(val uint64) any { + value := Voltage11BitType(val) + c.GridVoltageLow = &value + return &value +} + +func (c *CpuErrors) setGridVoltageHigh(val uint64) any { + value := Voltage11BitType(val) + c.GridVoltageHigh = &value + return &value +} + +func (c *CpuErrors) setGridVoltageEmpty(val uint64) any { + value := ErrorType(val) + c.GridVoltageEmpty = &value + return &value +} + +func (c *CpuErrors) setNotReadySecc(val uint64) any { + value := ErrorType(val) + c.NotReadySecc = &value + return &value +} + +func (c *CpuErrors) setNotReadyPu(val uint64) any { + value := ErrorType(val) + c.NotReadyPu = &value + return &value +} + +func (c *CpuErrors) setNotReadyContactors(val uint64) any { + value := ErrorType(val) + c.NotReadyContactors = &value + return &value +} + +func (c *CpuErrors) setDebugConvertersEnabled(val uint64) any { + value := ErrorType(val) + c.DebugConvertersEnabled = &value + return &value +} + +func (c *CpuErrors) setContactorInputError(val uint64) any { + value := ErrorType(val) + c.ContactorInputError = &value + return &value +} + +func (c *CpuErrors) setNotReadyPeriphery(val uint64) any { + value := ErrorType(val) + c.NotReadyPeriphery = &value + return &value +} + +func (d *CpuDebug) setDebugModeOn(val uint64) any { + value := BooleanType(val) + d.DebugModeOn = &value + return &value +} + +func (d *CpuDebug) setDebugContactorInputOn(val uint64) any { + value := DebugSwitchModeType(val) + d.DebugContactorInputOn = &value + return &value +} + +func (d *CpuDebug) setDebugCircuitBreakerOn(val uint64) any { + value := DebugSwitchModeType(val) + d.DebugCircuitBreakerOn = &value + return &value +} + +func (d *CpuDebug) setDebugRedButtonSoftware(val uint64) any { + value := DebugSwitchModeType(val) + d.DebugRedButtonSoftware = &value + return &value +} + +func (p *PuErrors) setBoardReady(val uint64) any { + value := BoardReadyType(val) + p.BoardReady = &value + return &value +} + +func (p *PuErrors) setOtherError(val uint64) any { + value := OtherError4BitType(val) + p.OtherError = &value + return &value +} + +func (p *PuErrors) setIncorrectVoltage(val uint64) any { + value := ErrorType(val) + p.IncorrectVoltage = &value + return &value +} + +func (p *PuErrors) setIncorrectVoltageValue(val uint64) any { + value := Voltage11BitType(val) + p.IncorrectVoltageValue = &value + return &value +} + +func (p *PuErrors) setIncorrectCurrent(val uint64) any { + value := ErrorType(val) + p.IncorrectCurrent = &value + return &value +} + +func (p *PuErrors) setIncorrectCurrentValue(val uint64) any { + value := Current10BitType(val) + p.IncorrectCurrentValue = &value + return &value +} + +func (p *PuErrors) setIsolationBroken(val uint64) any { + value := ErrorType(val) + p.IsolationBroken = &value + return &value +} + +func (p *PuErrors) setCpLineBroken(val uint64) any { + value := ErrorType(val) + p.CpLineBroken = &value + return &value +} + +func (p *PuErrors) setCpLineGap69(val uint64) any { + value := ErrorType(val) + p.CpLineGap69 = &value + return &value +} + +func (p *PuErrors) setCableReady(val uint64) any { + value := BoardReadyType(val) + p.CableReady = &value + return &value +} + +func (p *PuErrors) setNotReadyCpu(val uint64) any { + value := ErrorType(val) + p.NotReadyCpu = &value + return &value +} + +func (p *PuErrors) setNotReadySecc(val uint64) any { + value := ErrorType(val) + p.NotReadySecc = &value + return &value +} + +func (p *PuErrors) setContactorOutputError(val uint64) any { + value := ErrorType(val) + p.ContactorOutputError = &value + return &value +} + +func (p *PuErrors) setDebugContactorOutputEnabled(val uint64) any { + value := BooleanType(val) + p.DebugContactorOutputEnabled = &value + return &value +} + +func (p *PuErrors) setOutputCircuitBreakerEnabled(val uint64) any { + value := ErrorType(val) + p.OutputCircuitBreakerEnabled = &value + return &value +} + +func (p *PuErrors) setOutputCircuitBreakerEnabledValue(val uint64) any { + value := SignedVoltage12bitType(val - 1000) + p.OutputCircuitBreakerEnabledValue = &value + return &value +} + +func (d *PuDebug) setDebugModeOn(val uint64) any { + value := BooleanType(val) + d.DebugModeOn = &value + return &value +} + +func (d *PuDebug) setDebugContactorOutputOn(val uint64) any { + value := DebugSwitchModeType(val) + d.DebugContactorOutputOn = &value + return &value +} + +func (s *SeccTargetEnergy) setTargetChargingAllow(val uint64) any { + value := BooleanType(val) + s.TargetChargingAllow = &value + return &value +} + +func (s *SeccTargetEnergy) setTargetBatteryVoltage(val uint64) any { + value := Voltage11BitType(val) + s.TargetBatteryVoltage = &value + return &value +} + +func (s *SeccTargetEnergy) setTargetGoalVoltage(val uint64) any { + value := Voltage11BitType(val) + s.TargetGoalVoltage = &value + return &value +} + +func (s *SeccTargetEnergy) setTargetCurrent(val uint64) any { + value := Current10BitType(val) + s.TargetCurrent = &value + return &value +} + +func (e *SeccErrors) setBoardReady(val uint64) any { + value := BoardReadyType(val) + e.BoardReady = &value + return &value +} + +func (e *SeccErrors) setNotReadyLogic(val uint64) any { + value := ErrorType(val) + e.NotReadyLogic = &value + return &value +} + +func (l *LogicEnergyMode) setV2gMode(val uint64) any { + value := V2GModeType(val) + l.V2gMode = &value + return &value +} + +func (l *LogicEnergyMode) setCurrentMax(val uint64) any { + value := Current10BitType(val) + l.CurrentMax = &value + return &value +} + +func (l *LogicEnergyMode) setVoltageMax(val uint64) any { + value := Voltage11BitType(val) + l.VoltageMax = &value + return &value +} + +func (l *LogicEnergyMode) setPowerMax(val uint64) any { + value := Power14BitType(val * 100) + l.PowerMax = &value + return &value +} + +func (l *LogicErrors) setBoardReady(val uint64) any { + value := BoardReadyType(val) + l.BoardReady = &value + return &value +} + +func (l *LogicErrors) setNotReadySettings(val uint64) any { + value := ErrorType(val) + l.NotReadySettings = &value + return &value +} + +func (c *ContactorsInternalForce) setForceModeEnabled(val uint64) any { + value := BooleanType(val) + c.ForceModeEnabled = &value + return &value +} + +func (c *ContactorsInternalForce) setForceModeValue(val uint64) any { + value := ForceModeType(val) + c.ForceModeValue = &value + return &value +} + +func (c *ContactorInternalDebug) setDebugModeOn(val uint64) any { + value := BooleanType(val) + c.DebugModeOn = &value + return &value +} + +func (c *ContactorInternalDebug) setDebugContactorOn(val uint64) any { + value := DebugSwitchModeType(val) + c.DebugContactorOn = &value + return &value +} + +func (p *PeripheryState) setOtherErrorSeverity(val uint64) any { + value := BoardReadyType(val) + p.OtherErrorSeverity = &value + return &value +} + +func (p *PeripheryState) setOtherError(val uint64) any { + value := OtherError4BitType(val) + p.OtherError = &value + return &value +} + +func (p *PeripheryState) setErrorShakeSensor(val uint64) any { + value := ErrorType(val) + p.ErrorShakeSensor = &value + return &value +} + +func (p *PeripheryState) setErrorCoolingGroup(val uint64) any { + value := ErrorType(val) + p.ErrorCoolingGroup = &value + return &value +} + +func (p *PeripheryState) setPeripheryErrorCoolingGroup(val uint64) any { + value := ErrorType(val) + p.PeripheryErrorCoolingGroup = &value + return &value +} + +func (p *PeripheryState) setErrorFireEmergency(val uint64) any { + value := ErrorType(val) + p.ErrorFireEmergency = &value + return &value +} + +func (p *PeripheryState) setErrorFireEmergencyRun(val uint64) any { + value := ErrorType(val) + p.ErrorFireEmergencyRun = &value + return &value +} + +func (p *PeripheryState) setErrorFireEmergencyControl(val uint64) any { + value := ErrorType(val) + p.ErrorFireEmergencyControl = &value + return &value +} + +func (p *PeripheryState) setErrorOvervoltageIn(val uint64) any { + value := ErrorType(val) + p.ErrorOvervoltageIn = &value + return &value +} + +func (p *PeripheryState) setPeripheryErrorPowerSupply(val uint64) any { + value := ErrorType(val) + p.PeripheryErrorPowerSupply = &value + return &value +} + +func (p *PeripheryState) setErrorFan(val uint64) any { + value := ErrorType(val) + p.ErrorFan = &value + return &value +} + +func (p *PeripheryState) setErrorOvervoltageOut(val uint64) any { + value := ErrorType(val) + p.ErrorOvervoltageOut = &value + return &value +} + +func (p *PeripheryState) setErrorStateRemoteMode(val uint64) any { + value := ErrorType(val) + p.ErrorStateRemoteMode = &value + return &value +} + +func (p *PeripheryState) setDebugShsnFanEnabled(val uint64) any { + value := BooleanType(val) + p.DebugShsnFanEnabled = &value + return &value +} + +func (p *PeripheryState) setDebugShptFanEnabled(val uint64) any { + value := BooleanType(val) + p.DebugShptFanEnabled = &value + return &value +} + +func (p *PeripheryState) setDebugIoBoardTestLampEnabled(val uint64) any { + value := BooleanType(val) + p.DebugIoBoardTestLampEnabled = &value + return &value +} + +func (p *PeripheryState) setErrorFireEmergencyCircuitBreaker(val uint64) any { + value := ErrorType(val) + p.ErrorFireEmergencyCircuitBreaker = &value + return &value +} + +func (p *PeripheryState) setErrorExtLightCircuitBreaker(val uint64) any { + value := ErrorType(val) + p.ErrorExtLightCircuitBreaker = &value + return &value +} + +func (p *PeripheryState) setErrorIndicationCircuitBreaker(val uint64) any { + value := ErrorType(val) + p.ErrorIndicationCircuitBreaker = &value + return &value +} + +func (p *PeripheryState) setErrorLowVoltagePowerCircuitBreaker(val uint64) any { + value := ErrorType(val) + p.ErrorLowVoltagePowerCircuitBreaker = &value + return &value +} + +func (p *PeripheryState) setErrorContactorsInternalCircuitBreaker(val uint64) any { + value := ErrorType(val) + p.ErrorContactorsInternalCircuitBreaker = &value + return &value +} + +func (p *PeripheryState) setErrorPlcCircuitBreaker(val uint64) any { + value := ErrorType(val) + p.ErrorPlcCircuitBreaker = &value + return &value +} + +func (p *PeripheryInfo) setInfoDoorOpen(val uint64) any { + value := BooleanType(val) + p.InfoDoorOpen = &value + return &value +} + +func (p *PeripheryInfo) setTempAirIn(val uint64) any { + value := SignedAirTemp8BitType(val - 67) + p.TempAirIn = &value + return &value +} + +func (p *PeripheryInfo) setTempAirOut(val uint64) any { + value := SignedAirTemp8BitType(val - 67) + p.TempAirOut = &value + return &value +} + +func (p *PeripheryInfo) setStateShsnFan(val uint64) any { + value := BooleanType(val) + p.StateShsnFan = &value + return &value +} + +func (p *PeripheryInfo) setStateShptFan(val uint64) any { + value := BooleanType(val) + p.StateShptFan = &value + return &value +} + +func (p *PeripheryDebug) setDebugModeOn(val uint64) any { + value := BooleanType(val) + p.DebugModeOn = &value + return &value +} + +func (p *PeripheryDebug) setDebugShsnFan(val uint64) any { + value := DebugSwitchModeType(val) + p.DebugShsnFan = &value + return &value +} + +func (p *PeripheryDebug) setDebugShptFan(val uint64) any { + value := DebugSwitchModeType(val) + p.DebugShptFan = &value + return &value +} + +func (p *PeripheryDebug) setDebugIoBoardTestLamp(val uint64) any { + value := DebugSwitchModeType(val) + p.DebugIoBoardTestLamp = &value + return &value +} + +func (c *ConverterPresentEnergy) setV2gMode(val uint64) any { + value := V2GModeType(val) + c.V2gMode = &value + return &value +} + +func (c *ConverterPresentEnergy) setPresentVoltage(val uint64) any { + value := Voltage11BitType(val) + c.PresentVoltage = &value + return &value +} + +func (c *ConverterPresentEnergy) setPresentCurrent(val uint64) any { + value := Current10BitType(val) + c.PresentCurrent = &value + return &value +} + +func (c *ConverterPresentEnergy) setConnectedOut(val uint64) any { + value := ConnectedOut8bitType(val) + c.ConnectedOut = &value + return &value +} + +func (c *ConverterErrors) setBoardReady(val uint64) any { + value := BoardReadyType(val) + c.BoardReady = &value + return &value +} + +func (c *ConverterErrors) setOtherError(val uint64) any { + value := OtherError4BitType(val) + c.OtherError = &value + return &value +} + +func (c *ConverterErrors) setNotConnectedOut(val uint64) any { + value := ErrorType(val) + c.NotConnectedOut = &value + return &value +} + +func (c *ConverterErrors) setNoCommunicationConverter(val uint64) any { + value := ErrorType(val) + c.NoCommunicationConverter = &value + return &value +} + +func (c *ConverterErrors) setNoCommunicationPuConverter(val uint64) any { + value := ErrorType(val) + c.NoCommunicationPuConverter = &value + return &value +} + +func (c *ConverterErrors) setInputGridVoltageHigh(val uint64) any { + value := ErrorType(val) + c.InputGridVoltageHigh = &value + return &value +} + +func (c *ConverterErrors) setInputGridVoltageLow(val uint64) any { + value := ErrorType(val) + c.InputGridVoltageLow = &value + return &value +} + +func (c *ConverterErrors) setOutputGridVoltageHigh(val uint64) any { + value := ErrorType(val) + c.OutputGridVoltageHigh = &value + return &value +} + +func (c *ConverterErrors) setOutputGridVoltageLow(val uint64) any { + value := ErrorType(val) + c.OutputGridVoltageLow = &value + return &value +} + +func (c *ConverterErrors) setInputGridVoltage(val uint64) any { + value := Voltage11BitType(val) + c.InputGridVoltage = &value + return &value +} + +func (c *ConverterErrors) setOutputGridVoltage(val uint64) any { + value := Voltage11BitType(val) + c.OutputGridVoltage = &value + return &value +} + +func (c *ConverterErrors) setShortCircuit(val uint64) any { + value := ErrorType(val) + c.ShortCircuit = &value + return &value +} + +func (c *ConverterErrors) setOverHeat(val uint64) any { + value := ErrorType(val) + c.OverHeat = &value + return &value +} + +func (c *ConverterErrors) setFanBroken(val uint64) any { + value := ErrorType(val) + c.FanBroken = &value + return &value +} + +func (c *ConverterErrors) setOtherHardwareError(val uint64) any { + value := ErrorType(val) + c.OtherHardwareError = &value + return &value +} + +func (c *ConverterErrors) setDebugConvEnabled(val uint64) any { + value := BooleanType(val) + c.DebugConvEnabled = &value + return &value +} + +func (c *ConverterErrors) setDebugConvDisabled(val uint64) any { + value := BooleanType(val) + c.DebugConvDisabled = &value + return &value +} + +func (d *ConverterDebug) setDebugModeOn(val uint64) any { + value := BooleanType(val) + d.DebugModeOn = &value + return &value +} + +func (d *ConverterDebug) setDebugEnergyOn(val uint64) any { + value := DebugSwitchModeType(val) + d.DebugEnergyOn = &value + return &value +} + +func (d *ConverterDebug) setDebugTargetVoltage(val uint64) any { + value := Voltage11BitType(val) + d.DebugTargetVoltage = &value + return &value +} + +func (d *ConverterDebug) setDebugTargetCurrent(val uint64) any { + value := Current10BitType(val) + d.DebugTargetCurrent = &value + return &value +} diff --git a/yabl/strings.go b/yabl/strings.go index a44789f..6a295d9 100644 --- a/yabl/strings.go +++ b/yabl/strings.go @@ -109,8 +109,8 @@ func (t CpLineLevelType) String() string { func (t IsolationStateType) String() string { switch t { - case UNKNOWN: - return "UNKNOWN" + case ISOLATION_STATE_UNKNOWN: + return "ISOLATION_STATE_UNKNOWN" case ONGOING: return "ONGOING" case PASSED: @@ -127,3 +127,87 @@ func (t IsolationStateType) String() string { func (t Voltage9BitType) String() string { return fmt.Sprintf("%.1fV", t) } + +func (t AuthModeType) String() string { + switch t { + case AUTH: + return "AUTH" + case PNC: + return "PNC" + default: + panic("AuthModeType not defended") + } +} + +func (a AuthStateType) String() string { + switch a { + case AUTH_STATE_UNKNOWN: + return "UNKNOWN" + case AUTH_STATE_ALLOW: + return "ALLOW" + case AUTH_STATE_DENY: + return "DENY" + default: + return fmt.Sprintf("AuthStateType %d not defended", a) + } +} + +func (p Power14BitType) String() string { + return fmt.Sprintf("%dW", p) +} + +func (c ContactorModeType) String() string { + switch c { + case CONTACTOR_NO_MODE: + return "NO_MODE" + case CONTACTOR_TRANSACTION_PROCESS: + return "TRANSACTION_PROCESS" + case CONTACTOR_CUSTOM_MODE: + return "CUSTOM_MODE" + case CONTACTOR_ONLY_ONE_OUT_MODE: + return "ONLY_ONE_OUT_MODE" + case CONTACTOR_ONE_TO_ONE_OUT_MODE: + return "ONE_TO_ONE_OUT_MODE" + case CONTACTOR_SIMPLE_DYNAMIC_MODE: + return "SIMPLE_DYNAMIC_MODE" + default: + return fmt.Sprintf("ContactorModeType %d not defended", c) + } +} + +func (e OtherError4BitType) String() string { + return fmt.Sprintf("ErrCode_%d", e) +} + +func (d DebugSwitchModeType) String() string { + switch d { + case DEBUG_SWITCH_MODE_AUTO: + return "AUTO" + case DEBUG_SWITCH_MODE_OFF: + return "OFF" + case DEBUG_SWITCH_MODE_ON: + return "ON" + case DEBUG_SWITCH_MODE_PERMANENT_OFF: + return "PERMANENT_OFF" + case DEBUG_SWITCH_MODE_PERMANENT_ON: + return "PERMANENT_ON" + default: + return fmt.Sprintf("DebugSwitchModeType_%d", d) + } +} + +func (s SignedVoltage12bitType) String() string { + return fmt.Sprintf("%d", s) +} + +func (f ForceModeType) String() string { + return fmt.Sprintf("MODE_%d", f) +} + +func (t SignedAirTemp8BitType) String() string { + return fmt.Sprintf("%d", t) +} + +func (c ConnectedOut8bitType) String() string { + return fmt.Sprintf("%d", c) +} diff --git a/yabl/types.go b/yabl/types.go new file mode 100644 index 0000000..1d60d82 --- /dev/null +++ b/yabl/types.go @@ -0,0 +1,295 @@ +package yabl + +import "time" + +type AName string +type FName string + +type unit uint + +type Action interface { + GetUnitId() uint +} + +type Event struct { + unit + ActionName AName + Field FName + Object Action + Updated *time.Time + Value any +} + +type SignedAirTemp8BitType int +type ConnectedOut8bitType uint +type ForceModeType uint +type SignedVoltage12bitType int +type DebugSwitchModeType uint +type OtherError4BitType uint +type ContactorModeType uint +type Power14BitType uint +type AuthStateType uint +type AuthModeType uint +type BoardReadyType uint +type BooleanType uint +type ErrorType uint +type ContactorInternalOtherErrorType uint +type ContactorGroupChangedType uint +type V2GModeType uint +type Voltage11BitType uint +type Current10BitType uint +type CpLineLevelType uint +type IsolationStateType uint +type Voltage9BitType float32 + +type ContactorInternalState struct { + unit + ContactorReady *BoardReadyType + ContactorOn *BooleanType + UnexpectedState *ErrorType + Isolated *ErrorType + DebugEnabled *BooleanType +} + +type ContactorInternalErrors struct { + unit + BoardReady *BoardReadyType + OtherError *ContactorInternalOtherErrorType + ContactorGroupChanged *ContactorGroupChangedType + UnexpectedFormation *ContactorInternalOtherErrorType + CpuNotReady *ErrorType + PuNotReady *ErrorType + Debug *BooleanType + PresentContactorMode *ContactorModeType +} + +type ContactorsInternalForce struct { + unit + ForceModeEnabled *BooleanType + ForceModeValue *ForceModeType +} + +type ContactorInternalDebug struct { + unit + DebugModeOn *BooleanType + DebugContactorOn *DebugSwitchModeType +} + +type PuPresentEnergy struct { + unit + V2GMode *V2GModeType + VoltageBefore *Voltage11BitType + VoltageAfter *Voltage11BitType + PresentCurrent *Current10BitType +} + +type PuPeriphery struct { + unit + ConnectorInsert *BooleanType + ContactorOn *BooleanType + ConnectorLocked *BooleanType + CpLineLevel *CpLineLevelType + IsolationState *IsolationStateType + ChargingAllowed *BooleanType + PwmEnabled *BooleanType + CpLineVoltage *Voltage9BitType +} + +type LogicAuth struct { + unit + AuthMode *AuthModeType + AuthState *AuthStateType +} + +type LogicEnergyMode struct { + unit + V2gMode *V2GModeType + CurrentMax *Current10BitType + VoltageMax *Voltage11BitType + PowerMax *Power14BitType +} + +type LogicErrors struct { + unit + BoardReady *BoardReadyType + NotReadySettings *ErrorType +} + +type LogicWorkingMode struct { + unit + TargetContactorMode *ContactorModeType + Availability *BooleanType +} + +type CpuPresentEnergy struct { + unit + PowerDirectionMode *V2GModeType + PresentCurrent *Current10BitType + PresentVoltage *Voltage11BitType +} + +type CpuPeriphery struct { + unit + ContactorInput *BooleanType + CircuitBreakerInput *BooleanType + CircuitBreakerPowerCBInput *BooleanType +} + +type CpuEnergySettings struct { + unit + CurrentMax *Current10BitType + VoltageMax *Voltage11BitType + PowerMax *Power14BitType + TargetBatteryVoltage *Voltage11BitType + TargetGoalVoltage *Voltage11BitType +} + +type CpuErrors struct { + unit + BoardReady *BoardReadyType + OtherError *OtherError4BitType + RedButtonHard *ErrorType + RedButtonSoft *ErrorType + ModulesGone *ErrorType + GridVoltageHighErr *ErrorType + GridVoltageHighWarn *ErrorType + GridVoltageLowWarn *ErrorType + GridVoltageLowErr *ErrorType + GridVoltageLow *Voltage11BitType + GridVoltageHigh *Voltage11BitType + GridVoltageEmpty *ErrorType + NotReadySecc *ErrorType + NotReadyPu *ErrorType + NotReadyContactors *ErrorType + DebugConvertersEnabled *ErrorType + ContactorInputError *ErrorType + NotReadyPeriphery *ErrorType +} + +type CpuDebug struct { + unit + DebugModeOn *BooleanType + DebugContactorInputOn *DebugSwitchModeType + DebugCircuitBreakerOn *DebugSwitchModeType + DebugRedButtonSoftware *DebugSwitchModeType +} + +type PuErrors struct { + unit + BoardReady *BoardReadyType + OtherError *OtherError4BitType + IncorrectVoltage *ErrorType + IncorrectVoltageValue *Voltage11BitType + IncorrectCurrent *ErrorType + IncorrectCurrentValue *Current10BitType + IsolationBroken *ErrorType + CpLineBroken *ErrorType + CpLineGap69 *ErrorType + CableReady *BoardReadyType + NotReadyCpu *ErrorType + NotReadySecc *ErrorType + ContactorOutputError *ErrorType + DebugContactorOutputEnabled *BooleanType + OutputCircuitBreakerEnabled *ErrorType + OutputCircuitBreakerEnabledValue *SignedVoltage12bitType +} + +type PuDebug struct { + unit + DebugModeOn *BooleanType + DebugContactorOutputOn *DebugSwitchModeType +} + +type SeccTargetEnergy struct { + unit + TargetChargingAllow *BooleanType + TargetBatteryVoltage *Voltage11BitType + TargetGoalVoltage *Voltage11BitType + TargetCurrent *Current10BitType +} + +type SeccErrors struct { + unit + BoardReady *BoardReadyType + NotReadyLogic *ErrorType +} + +type PeripheryState struct { + unit + OtherErrorSeverity *BoardReadyType + OtherError *OtherError4BitType + ErrorShakeSensor *ErrorType + ErrorCoolingGroup *ErrorType + PeripheryErrorCoolingGroup *ErrorType + ErrorFireEmergency *ErrorType + ErrorFireEmergencyRun *ErrorType + ErrorFireEmergencyControl *ErrorType + ErrorOvervoltageIn *ErrorType + PeripheryErrorPowerSupply *ErrorType + ErrorFan *ErrorType + ErrorOvervoltageOut *ErrorType + ErrorStateRemoteMode *ErrorType + DebugShsnFanEnabled *BooleanType + DebugShptFanEnabled *BooleanType + DebugIoBoardTestLampEnabled *BooleanType + ErrorFireEmergencyCircuitBreaker *ErrorType + ErrorExtLightCircuitBreaker *ErrorType + ErrorIndicationCircuitBreaker *ErrorType + ErrorLowVoltagePowerCircuitBreaker *ErrorType + ErrorContactorsInternalCircuitBreaker *ErrorType + ErrorPlcCircuitBreaker *ErrorType +} + +type PeripheryInfo struct { + unit + InfoDoorOpen *BooleanType + TempAirIn *SignedAirTemp8BitType + TempAirOut *SignedAirTemp8BitType + StateShsnFan *BooleanType + StateShptFan *BooleanType +} + +type PeripheryDebug struct { + unit + DebugModeOn *BooleanType + DebugShsnFan *DebugSwitchModeType + DebugShptFan *DebugSwitchModeType + DebugIoBoardTestLamp *DebugSwitchModeType +} + +type ConverterPresentEnergy struct { + unit + V2gMode *V2GModeType + PresentVoltage *Voltage11BitType + PresentCurrent *Current10BitType + ConnectedOut *ConnectedOut8bitType +} + +type ConverterErrors struct { + unit + BoardReady *BoardReadyType + OtherError *OtherError4BitType + NotConnectedOut *ErrorType + NoCommunicationConverter *ErrorType + NoCommunicationPuConverter *ErrorType + InputGridVoltageHigh *ErrorType + InputGridVoltageLow *ErrorType + OutputGridVoltageHigh *ErrorType + OutputGridVoltageLow *ErrorType + InputGridVoltage *Voltage11BitType + OutputGridVoltage *Voltage11BitType + ShortCircuit *ErrorType + OverHeat *ErrorType + FanBroken *ErrorType + OtherHardwareError *ErrorType + DebugConvEnabled *BooleanType + DebugConvDisabled *BooleanType +} + +type ConverterDebug struct { + unit + DebugModeOn *BooleanType + DebugEnergyOn *DebugSwitchModeType + DebugTargetVoltage *Voltage11BitType + DebugTargetCurrent *Current10BitType +}