forked from einride/can-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
frame_json.go
95 lines (90 loc) · 2.41 KB
/
frame_json.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package can
import (
"encoding/hex"
"encoding/json"
"fmt"
"strconv"
)
type jsonFrame struct {
ID uint32 `json:"id"`
Data *string `json:"data"`
Length *uint8 `json:"length"`
Extended *bool `json:"extended"`
Remote *bool `json:"remote"`
}
// JSON returns the JSON-encoding of f, using hex-encoding for the data.
//
// Examples:
//
// {"id":32,"data":"0102030405060708"}
// {"id":32,"extended":true,"remote":true,"length":4}
func (f Frame) JSON() string {
switch {
case f.IsRemote && f.IsExtended:
return `{"id":` + strconv.Itoa(int(f.ID)) +
`,"extended":true,"remote":true,"length":` +
strconv.Itoa(int(f.Length)) + `}`
case f.IsRemote:
return `{"id":` + strconv.Itoa(int(f.ID)) +
`,"remote":true,"length":` +
strconv.Itoa(int(f.Length)) + `}`
case f.IsExtended && f.Length == 0:
return `{"id":` + strconv.Itoa(int(f.ID)) + `,"extended":true}`
case f.IsExtended:
return `{"id":` + strconv.Itoa(int(f.ID)) +
`,"data":"` + hex.EncodeToString(f.Data[:f.Length]) + `"` +
`,"extended":true}`
case f.Length == 0:
return `{"id":` + strconv.Itoa(int(f.ID)) + `}`
default:
return `{"id":` + strconv.Itoa(int(f.ID)) +
`,"data":"` + hex.EncodeToString(f.Data[:f.Length]) + `"}`
}
}
// MarshalJSON returns the JSON-encoding of f, using hex-encoding for the data.
//
// See JSON for an example of the JSON schema.
func (f Frame) MarshalJSON() ([]byte, error) {
return []byte(f.JSON()), nil
}
// UnmarshalJSON sets *f using the provided JSON-encoded values.
//
// See MarshalJSON for an example of the expected JSON schema.
//
// The result should be checked with Validate to guard against invalid JSON data.
func (f *Frame) UnmarshalJSON(jsonData []byte) error {
jf := jsonFrame{}
if err := json.Unmarshal(jsonData, &jf); err != nil {
return err
}
if jf.Data != nil {
data, err := hex.DecodeString(*jf.Data)
if err != nil {
return fmt.Errorf("failed to hex-decode CAN data: %v: %w", string(jsonData), err)
}
f.Data = Data{}
copy(f.Data[:], data)
f.Length = uint8(len(data))
} else {
f.Data = Data{}
f.Length = 0
}
f.ID = jf.ID
if jf.Remote != nil {
f.IsRemote = *jf.Remote
} else {
f.IsRemote = false
}
if f.IsRemote {
if jf.Length == nil {
return fmt.Errorf("missing length field for remote JSON frame: %v", string(jsonData))
}
f.Length = *jf.Length
}
if jf.Extended != nil {
f.IsExtended = *jf.Extended
} else {
f.IsExtended = false
}
return nil
}