feat: write protocol acknowledgements from go gateway
This commit is contained in:
130
go/vehicle-gateway/internal/protocol/jt808/response.go
Normal file
130
go/vehicle-gateway/internal/protocol/jt808/response.go
Normal file
@@ -0,0 +1,130 @@
|
||||
package jt808
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
|
||||
"lingniu-vehicle-ingest/go/vehicle-gateway/internal/envelope"
|
||||
)
|
||||
|
||||
var ErrResponseHeaderTooShort = errors.New("jt808 response header too short")
|
||||
|
||||
const (
|
||||
msgTerminalGeneralResponse = uint16(0x0001)
|
||||
msgTerminalRegister = uint16(0x0100)
|
||||
msgPlatformGeneralResponse = uint16(0x8001)
|
||||
msgPlatformRegisterAck = uint16(0x8100)
|
||||
)
|
||||
|
||||
type AutoResponder struct {
|
||||
authCode string
|
||||
}
|
||||
|
||||
func NewAutoResponder(authCode string) AutoResponder {
|
||||
if authCode == "" {
|
||||
authCode = "g7gps"
|
||||
}
|
||||
return AutoResponder{authCode: authCode}
|
||||
}
|
||||
|
||||
func (r AutoResponder) Respond(raw []byte, env envelope.FrameEnvelope) ([]byte, bool, error) {
|
||||
if env.ParseStatus == envelope.ParseBadFrame {
|
||||
return nil, false, nil
|
||||
}
|
||||
header, err := parseResponseHeader(raw)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
if header.messageID == msgTerminalGeneralResponse {
|
||||
return nil, false, nil
|
||||
}
|
||||
if header.messageID == msgTerminalRegister {
|
||||
body := make([]byte, 3, 3+len(r.authCode))
|
||||
binary.BigEndian.PutUint16(body[0:2], header.sequence)
|
||||
body[2] = 0
|
||||
body = append(body, []byte(r.authCode)...)
|
||||
return encodeResponse(msgPlatformRegisterAck, header, body), true, nil
|
||||
}
|
||||
body := make([]byte, 5)
|
||||
binary.BigEndian.PutUint16(body[0:2], header.sequence)
|
||||
binary.BigEndian.PutUint16(body[2:4], header.messageID)
|
||||
body[4] = 0
|
||||
return encodeResponse(msgPlatformGeneralResponse, header, body), true, nil
|
||||
}
|
||||
|
||||
type responseHeader struct {
|
||||
messageID uint16
|
||||
versioned bool
|
||||
protocolVersion byte
|
||||
phoneBCD []byte
|
||||
sequence uint16
|
||||
}
|
||||
|
||||
func parseResponseHeader(raw []byte) (responseHeader, error) {
|
||||
if len(raw) < 12 {
|
||||
return responseHeader{}, ErrResponseHeaderTooShort
|
||||
}
|
||||
props := binary.BigEndian.Uint16(raw[2:4])
|
||||
versioned := props&0x4000 != 0
|
||||
phoneStart := 4
|
||||
phoneLen := 6
|
||||
protocolVersion := byte(0)
|
||||
if versioned {
|
||||
if len(raw) < 17 {
|
||||
return responseHeader{}, ErrResponseHeaderTooShort
|
||||
}
|
||||
protocolVersion = raw[4]
|
||||
phoneStart = 5
|
||||
phoneLen = 10
|
||||
}
|
||||
sequenceStart := phoneStart + phoneLen
|
||||
if len(raw) < sequenceStart+2 {
|
||||
return responseHeader{}, ErrResponseHeaderTooShort
|
||||
}
|
||||
phone := append([]byte(nil), raw[phoneStart:sequenceStart]...)
|
||||
return responseHeader{
|
||||
messageID: binary.BigEndian.Uint16(raw[0:2]),
|
||||
versioned: versioned,
|
||||
protocolVersion: protocolVersion,
|
||||
phoneBCD: phone,
|
||||
sequence: binary.BigEndian.Uint16(raw[sequenceStart : sequenceStart+2]),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func encodeResponse(messageID uint16, header responseHeader, body []byte) []byte {
|
||||
props := uint16(len(body)) & 0x03ff
|
||||
if header.versioned {
|
||||
props |= 0x4000
|
||||
}
|
||||
payload := make([]byte, 0, 4+1+len(header.phoneBCD)+2+len(body)+1)
|
||||
payload = appendU16(payload, messageID)
|
||||
payload = appendU16(payload, props)
|
||||
if header.versioned {
|
||||
payload = append(payload, header.protocolVersion)
|
||||
}
|
||||
payload = append(payload, header.phoneBCD...)
|
||||
payload = appendU16(payload, header.sequence)
|
||||
payload = append(payload, body...)
|
||||
payload = append(payload, checksum(payload))
|
||||
return frame(payload)
|
||||
}
|
||||
|
||||
func appendU16(out []byte, value uint16) []byte {
|
||||
return append(out, byte(value>>8), byte(value))
|
||||
}
|
||||
|
||||
func frame(payload []byte) []byte {
|
||||
out := []byte{0x7e}
|
||||
for _, value := range payload {
|
||||
switch value {
|
||||
case 0x7e:
|
||||
out = append(out, 0x7d, 0x02)
|
||||
case 0x7d:
|
||||
out = append(out, 0x7d, 0x01)
|
||||
default:
|
||||
out = append(out, value)
|
||||
}
|
||||
}
|
||||
out = append(out, 0x7e)
|
||||
return out
|
||||
}
|
||||
Reference in New Issue
Block a user