109 lines
2.4 KiB
Go
109 lines
2.4 KiB
Go
|
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
|
||
|
}
|