implement messages
This commit is contained in:
parent
6dfbe636bd
commit
ef19fa588f
|
@ -0,0 +1,5 @@
|
|||
package main
|
||||
|
||||
func main() {
|
||||
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
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
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestPlateMessage(t *testing.T) {
|
||||
data := []byte{0x20, 0x04, 0x55, 0x4e, 0x31, 0x58, 0x00, 0x00, 0x03, 0xe8}
|
||||
p, err := decodePlateMessage(data)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if p.plate != "UN1X" {
|
||||
t.Error("plate wrong")
|
||||
}
|
||||
if p.timestamp != time.Unix(0x000003e8, 0) {
|
||||
t.Error("timestamp wrong")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWantHeartbeatMessage(t *testing.T) {
|
||||
data := []byte{0x40, 0x00, 0x00, 0x00, 0x0a}
|
||||
h, err := decodeWantHeartbeatMessage(data)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if *h != wantHeartbeatMessage(10) {
|
||||
t.Error("Wrong duration")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAmCameraMessage(t *testing.T) {
|
||||
data := []byte{0x80, 0x00, 0x42, 0x00, 0x64, 0x00, 0x3c}
|
||||
m, err := decodeAmCameraMessage(data)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if m.road != 66 {
|
||||
t.Error("wrong road")
|
||||
}
|
||||
if m.mile != 100 {
|
||||
t.Error("wrong mile")
|
||||
}
|
||||
if m.limit != 60 {
|
||||
t.Error("wrong limit")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAmDispatcherMessage(t *testing.T) {
|
||||
data := []byte{0x81, 0x01, 0x00, 0x42}
|
||||
m, err := decodeAmDispatcherMessage(data)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if m.numroads != 1 {
|
||||
t.Error("wrong numroads")
|
||||
}
|
||||
if len(m.roads) != 1 {
|
||||
t.Error("wrong length of roads")
|
||||
}
|
||||
if m.roads[0] != 66 {
|
||||
t.Error("wrong roads[0]")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAmDispatcherMessageLong(t *testing.T) {
|
||||
data := []byte{0x81, 0x03, 0x00, 0x42, 0x01, 0x70, 0x13, 0x88}
|
||||
m, err := decodeAmDispatcherMessage(data)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if m.numroads != 3 {
|
||||
t.Error("wrong numroads")
|
||||
}
|
||||
if len(m.roads) != 3 {
|
||||
t.Error("wrong length of roads")
|
||||
}
|
||||
if m.roads[0] != 66 {
|
||||
t.Error("wrong roads[0]")
|
||||
}
|
||||
if m.roads[1] != 368 {
|
||||
t.Error("wrong roads[0]")
|
||||
}
|
||||
if m.roads[2] != 5000 {
|
||||
t.Error("wrong roads[0]")
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue