GoLang解析部标JT808协议(支持最新的JT808-2019)

主流项目还是得用java

Java版的演示地址:

http://gps.lingx.com
账号:admin
密码:123456

以下JT808解析的部分代码:

package jt808

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"log"
	"net"

	"lingx.com/jt808-server/tools"
)

var Obj *Jt808

//初始化函数
func init() {
	Obj = new(Jt808)
	Obj.sessions = make(map[string]net.Conn)
	Obj.fbCache = make(map[string][]byte)
	Obj.msgHandleMap = make(map[uint16]func(data []byte, tid string, sn uint16, conn net.Conn))
	Obj.lastPosition = make(map[string]map[string]interface{})

}

func GetJT808Object() *Jt808 {
	return Obj
}

type Jt808 struct {
	//会话缓存
	sessions map[string]net.Conn
	//消息处理函数缓存
	msgHandleMap map[uint16]func(data []byte, tid string, sn uint16, conn net.Conn)
	//分包缓存
	fbCache map[string][]byte
	//最新数据缓存
	lastPosition map[string]map[string]interface{}
}

//注册消息处理函数
func (jt808 *Jt808) RegisterFun(msgId uint16, f func(data []byte, tid string, sn uint16, conn net.Conn)) {

	jt808.msgHandleMap[msgId] = f
}

//协议解析
func (jt808 *Jt808) Analyze(data []byte, conn net.Conn) {
	if !jt808.CheckJt808Packet(data) {
		log.Fatal("JT808校验码不通过,丢掉该包")
		return
	}
	data = jt808.Decode(data) //解码
	var byteBuf = new(tools.ByteBuf)
	byteBuf.WriteBytes(data)

	byteBuf.ReadByte() //0x7E
	var msgId = byteBuf.ReadUInt16()
	var length = byteBuf.ReadUInt16()
	var content []byte                             //正文
	isFB := (length & 0b0010000000000000) > 0      //是否分包
	isVersion := (length & 0b0100000000000000) > 0 //是否版本标识
	var tid string
	if isVersion {
		byteBuf.ReadByte() //	version
		tid = byteBuf.ReadBCD(10)
	} else {
		tid = byteBuf.ReadBCD(6)
	}

	jt808.sessions[tid] = conn //创建Session

	var sn = (byteBuf.ReadUInt16()) //流水号
	if isFB {
		//分包处理
		fbbytes := make([]byte, 4)
		byteBuf.ReadBytes(fbbytes)
		var maxPack, currPack uint16
		bytesBuffer := bytes.NewBuffer(fbbytes[0:2])
		binary.Read(bytesBuffer, binary.BigEndian, &maxPack)
		bytesBuffer = bytes.NewBuffer(fbbytes[2:4])
		binary.Read(bytesBuffer, binary.BigEndian, &currPack)
		log.Println("分包max,curr", maxPack, currPack)
		var key = tid + fmt.Sprintf("%04X", msgId)

		content = make([]byte, length&0x3ff)
		byteBuf.ReadBytes(content)
		if maxPack == currPack {
			//合并分包
			jt808.fbCache[key] = append(jt808.fbCache[key], content...)

			content = jt808.fbCache[key]
			if content == nil {
				return
			}
		} else {
			if currPack == 1 {
				tempArr := make([]byte, 0)
				tempArr = append(tempArr, content...)
				jt808.fbCache[key] = tempArr
			} else {
				jt808.fbCache[key] = append(jt808.fbCache[key], content...)
			}
			return //等待传包结束
		}
	} else {
		content = make([]byte, length&0x3ff)
		byteBuf.ReadBytes(content)
	}

	byteBuf.ReadByte() //check
	byteBuf.ReadByte() //0x7E

	//fmt.Println(msgId, tid)
	handleFun := jt808.msgHandleMap[msgId]
	if handleFun != nil {
		handleFun(content, tid, sn, conn)
	} else {
		log.Fatalln("JT808未实现处理消息:", fmt.Sprintf("%04X", msgId))
	}
}

//检查校验码
func (jt808 *Jt808) CheckJt808Packet(bytes []byte) bool {
	var xor byte = 0
	check := (bytes)[len(bytes)-2]
	for _, b := range (bytes)[1 : len(bytes)-2] {
		xor ^= b
	}
	return check == xor
}

//根据J808规则转码
func (jt808 *Jt808) Encode(bytes []byte) []byte {
	array := make([]byte, 0)
	for i, b := range bytes {
		if i == 0 || i == len(bytes)-1 {
			array = append(array, b)
		} else if b == 0x7D {
			array = append(array, 0x7D)
			array = append(array, 0x01)
		} else if b == 0x7E {
			array = append(array, 0x7D)
			array = append(array, 0x02)
		} else {
			array = append(array, b)
		}

	}
	_ = bytes //释放原数组
	return array
}

//根据JT808规则解码
func (jt808 *Jt808) Decode(bytes []byte) []byte {
	array := make([]byte, 0)
	length := len(bytes)
	array = append(array, 0x7E)
	for i := 1; i < length-1; i++ {
		if (bytes)[i] == 0x7D {
			if (bytes)[i+1] == 0x01 {
				array = append(array, 0x7D)
				i++
			} else if (bytes)[i+1] == 0x02 {
				array = append(array, 0x7E)
				i++
			} else {
				array = append(array, (bytes)[i])
			}
		} else {
			array = append(array, (bytes)[i])
		}
	}
	array = append(array, 0x7E)
	_ = bytes //释放原数组
	return array
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值