package main import ( "bytes" "encoding/binary" "fmt" "time" ) const ( errorHeader byte = 0x10 plateHeader byte = 0x20 ticketHeader byte = 0x21 wantHeartbeatHeader byte = 0x40 heartbeatHeader byte = 0x41 amCameraHeader byte = 0x80 amDispatcherHeader byte = 0x81 ) func encodeErrorMessage(msg string) []byte { b := bytes.NewBuffer([]byte{errorHeader}) b.WriteByte(byte(len(msg))) b.Write([]byte(msg)) return b.Bytes() } type plateMessage struct { plate string timestamp time.Time } func decodePlateMessage(data []byte) (*plateMessage, error) { if data[0] != plateHeader { return nil, fmt.Errorf("attempted to decode plate message with header %0x", data[0]) } pl := int(data[1]) plate := string(data[2 : 2+pl]) ts32 := binary.BigEndian.Uint32(data[2+pl:]) return &plateMessage{ plate: plate, timestamp: time.Unix(int64(ts32), 0), }, nil } type ticketMessage struct { plate string road uint16 mileOne uint16 timestampOne uint32 mileTwo uint16 timestampTwo uint32 speed uint16 } func encodeTicketMessage(data []byte) (*ticketMessage, error) { panic("unimplemented") } type wantHeartbeatMessage uint32 func decodeWantHeartbeatMessage(data []byte) (*wantHeartbeatMessage, error) { if data[0] != wantHeartbeatHeader { return nil, fmt.Errorf("attempted to decode wantHearbeatMessage with header %0x", data[0]) } d := wantHeartbeatMessage(binary.BigEndian.Uint32(data[1:])) return &d, nil } func encodeHeartbeat() []byte { return []byte{heartbeatHeader} } type amCameraMessage struct { road, mile, limit uint16 } func decodeAmCameraMessage(data []byte) (*amCameraMessage, error) { if data[0] != amCameraHeader { return nil, fmt.Errorf("attempted to decode amCameraMessage with header %0x", data[0]) } return &amCameraMessage{ road: binary.BigEndian.Uint16(data[1:3]), mile: binary.BigEndian.Uint16(data[3:5]), limit: binary.BigEndian.Uint16(data[5:]), }, nil } type amDispatcherMessage struct { numroads byte roads []uint16 } func decodeAmDispatcherMessage(data []byte) (*amDispatcherMessage, error) { if data[0] != amDispatcherHeader { return nil, fmt.Errorf("attempted to decode amDispatcherMessage with header %0x", data[0]) } var roads []uint16 for i, j := 0, 2; i < int(data[1]); i++ { roads = append(roads, binary.BigEndian.Uint16(data[j:j+2])) j += 2 } return &amDispatcherMessage{ data[1], roads, }, nil }