Refactor kafka to pure Go (franz-go), fix DBC stubs, update Dockerfile
This commit is contained in:
135
pkg/can-go/frame.go
Normal file
135
pkg/can-go/frame.go
Normal file
@@ -0,0 +1,135 @@
|
||||
package can
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
idBits = 11
|
||||
extendedIDBits = 29
|
||||
)
|
||||
|
||||
// CAN format constants.
|
||||
const (
|
||||
MaxID = 0x7ff
|
||||
MaxExtendedID = 0x1fffffff
|
||||
)
|
||||
|
||||
// Frame represents a CAN frame.
|
||||
//
|
||||
// A Frame is intentionally designed to fit into 16 bytes on common architectures
|
||||
// and is therefore amenable to pass-by-value and judicious copying.
|
||||
type Frame struct {
|
||||
// ID is the CAN ID
|
||||
ID uint32
|
||||
// Length is the number of bytes of data in the frame.
|
||||
Length uint16
|
||||
// Data is the frame data.
|
||||
Data Data
|
||||
// IsRemote is true for remote frames.
|
||||
IsRemote bool
|
||||
// IsExtended is true for extended frames, i.e. frames with 29-bit IDs.
|
||||
IsExtended bool
|
||||
}
|
||||
|
||||
// Validate returns an error if the Frame is not a valid CAN frame.
|
||||
func (f *Frame) Validate() error {
|
||||
// Validate: ID
|
||||
if f.IsExtended && f.ID > MaxExtendedID {
|
||||
return fmt.Errorf(
|
||||
"invalid extended CAN id: %v does not fit in %v bits",
|
||||
f.ID,
|
||||
extendedIDBits,
|
||||
)
|
||||
} else if !f.IsExtended && f.ID > MaxID {
|
||||
return fmt.Errorf(
|
||||
"invalid standard CAN id: %v does not fit in %v bits",
|
||||
f.ID,
|
||||
idBits,
|
||||
)
|
||||
}
|
||||
// Validate: Data
|
||||
if f.Length > MaxDataLength {
|
||||
return fmt.Errorf("invalid data length: %v", f.Length)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// String returns an ASCII representation the CAN frame.
|
||||
//
|
||||
// Format:
|
||||
//
|
||||
// ([0-9A-F]{3}|[0-9A-F]{3})#(R[0-8]?|[0-9A-F]{0,16})
|
||||
//
|
||||
// The format is compatible with the candump(1) log file format.
|
||||
func (f Frame) String() string {
|
||||
var id string
|
||||
if f.IsExtended {
|
||||
id = fmt.Sprintf("%08X", f.ID)
|
||||
} else {
|
||||
id = fmt.Sprintf("%03X", f.ID)
|
||||
}
|
||||
if f.IsRemote && f.Length == 0 {
|
||||
return id + "#R"
|
||||
} else if f.IsRemote {
|
||||
return id + "#R" + strconv.Itoa(int(f.Length))
|
||||
}
|
||||
return id + "#" + strings.ToUpper(hex.EncodeToString(f.Data[:f.Length]))
|
||||
}
|
||||
|
||||
// UnmarshalString sets *f using the provided ASCII representation of a Frame.
|
||||
func (f *Frame) UnmarshalString(s string) error {
|
||||
// Split split into parts
|
||||
parts := strings.Split(s, "#")
|
||||
if len(parts) != 2 {
|
||||
return fmt.Errorf("invalid frame format: %v", s)
|
||||
}
|
||||
idPart, dataPart := parts[0], parts[1]
|
||||
var frame Frame
|
||||
// Parse: IsExtended
|
||||
if len(idPart) != 3 && len(idPart) != 8 {
|
||||
return fmt.Errorf("invalid ID length: %v", s)
|
||||
}
|
||||
frame.IsExtended = len(idPart) == 8
|
||||
// Parse: ID
|
||||
id, err := strconv.ParseUint(idPart, 16, 32)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid frame ID: %v", s)
|
||||
}
|
||||
frame.ID = uint32(id)
|
||||
if len(dataPart) == 0 {
|
||||
*f = frame
|
||||
return nil
|
||||
}
|
||||
// Parse: IsRemote
|
||||
if dataPart[0] == 'R' {
|
||||
frame.IsRemote = true
|
||||
if len(dataPart) > 2 {
|
||||
return fmt.Errorf("invalid remote length: %v", s)
|
||||
} else if len(dataPart) == 2 {
|
||||
dataLength, err := strconv.Atoi(dataPart[1:2])
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid remote length: %v: %w", s, err)
|
||||
}
|
||||
frame.Length = uint16(dataLength)
|
||||
}
|
||||
*f = frame
|
||||
return nil
|
||||
}
|
||||
// Parse: Length
|
||||
if len(dataPart) > 16 || len(dataPart)%2 != 0 {
|
||||
return fmt.Errorf("invalid data length: %v", s)
|
||||
}
|
||||
frame.Length = uint16(len(dataPart) / 2)
|
||||
// Parse: Data
|
||||
decodedData, err := hex.DecodeString(dataPart)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid data: %v: %w", s, err)
|
||||
}
|
||||
copy(frame.Data[:], decodedData)
|
||||
*f = frame
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user