balise btm

This commit is contained in:
xzb 2023-11-20 16:55:07 +08:00
parent 48e0237503
commit 3711fa98ce
3 changed files with 146 additions and 0 deletions

View File

@ -80,6 +80,7 @@ func (f *BtmDataMessageTimeAFrame) Encode() CanBusData {
//
return writer.(CanBusData)
}
func (f *BtmDataMessageTimeAFrame) Decode(reader CanBitsReader) bool {
if !f.FId.Decode(reader) {
return false
@ -328,3 +329,15 @@ func (f *BtmDataMessageEndFrame) Decode(reader CanBitsReader) bool {
//
return true
}
// 32位时间戳转换成字节数组
// 大端模型
func canTimeToBytes(ts uint32) []byte {
rt := make([]byte, 0, 4)
byteMsk := uint32(0x00_00_00_ff)
rt = append(rt, byte((ts>>24)&byteMsk))
rt = append(rt, byte((ts>>16)&byteMsk))
rt = append(rt, byte((ts>>8)&byteMsk))
rt = append(rt, byte(ts&byteMsk))
return rt
}

120
third_party/message/can_btm_rsp.go vendored Normal file
View File

@ -0,0 +1,120 @@
package message
import "log/slog"
// CreateBtmRspFramesData 数据帧与状态应答帧同时发送给ATP
// 共17帧17X12个字节每个帧12字节
// msg - 应答器报文
// msgPackError - true BTM解包发生错误则数据帧及CRC32A/B全填“0xFF”
func CreateBtmRspFramesData(statusRsp *BtmStatusRspFrame, msg []byte, msgPackError bool, msgTimeA uint32, msgTimeB uint32, tkTimeB uint32) ([]byte, bool) {
if len(msg) > 104 { //数据帧最多存储13*8个字节
return nil, false
}
//最近一次ATP查询请求序列号
sn := statusRsp.FId.ID4
//13个BtmDataMessageFrame [0x00,0x0c]
dms := make([]*BtmDataMessageFrame, 13)
for mr := 0x00; mr <= 0x0c; mr++ {
dms[mr] = NewBtmDataMessageFrame(sn, byte(mr))
dms[mr].Message = make([]byte, 8) //8字节数组默认值0
//
if !msgPackError {
mi := mr * 8
if mi < len(msg) { //数据帧中有<=8个字节数据
if mi+7 < len(msg) {
dms[mr].Message = msg[mi : mi+8]
} else {
for i, d := range msg[mi:] {
dms[mr].Message[i] = d
}
}
}
} else { //BTM解包发生错误则数据帧及CRC32A/B全填“0xFF”
for c := 0; c < 8; c++ {
dms[mr].Message[c] = 0xff
}
}
}
//
dtA := NewBtmDataMessageTimeAFrame(sn)
dtA.TimeA = msgTimeA
if !msgPackError {
var crc32AData []byte
crc32AData = append(crc32AData, msg...)
crc32AData = append(crc32AData, canTimeToBytes(dtA.TimeA)...)
dtA.Crc32A = calculateDataRspCrc32A(crc32AData) //CRC32A的校验范围是报文+时间戳A
} else { //BTM解包发生错误则数据帧及CRC32A/B全填“0xFF”
dtA.Crc32A = 0xff_ff_ff_ff
}
//
dtB := NewBtmDataMessageTimeBFrame(sn)
dtB.TimeB = msgTimeB
if !msgPackError {
var crc32BData []byte
crc32BData = append(crc32BData, msg...)
crc32BData = append(crc32BData, canTimeToBytes(dtB.TimeB)...)
dtB.Crc32B = calculateDataRspCrc32B(crc32BData) //CRC32B的校验范围是报文+时间戳B
} else { //BTM解包发生错误则数据帧及CRC32A/B全填“0xFF”
dtB.Crc32B = 0xff_ff_ff_ff
}
//
end := NewBtmDataMessageEndFrame(sn)
end.TkB = tkTimeB
//
crc32CData := make([]byte, 0, 132) //17*8-4
rt := make([]byte, 0, 204) //17*12
// 状态应答帧
statusData := statusRsp.Encode()
crc32CData = append(crc32CData, canFrameContent(statusData)...)
rt = append(rt, statusData.GetData()...)
// 数据帧
for _, dm := range dms {
dmData := dm.Encode()
crc32CData = append(crc32CData, canFrameContent(dmData)...)
rt = append(rt, dmData.GetData()...)
}
// 消息时刻A
dtAData := dtA.Encode()
crc32CData = append(crc32CData, canFrameContent(dtAData)...)
rt = append(rt, dtAData.GetData()...)
// 消息时刻B
dtBData := dtB.Encode()
crc32CData = append(crc32CData, canFrameContent(dtBData)...)
rt = append(rt, dtBData.GetData()...)
// 消息结束帧
crc32CData = append(crc32CData, canTimeToBytes(end.TkB)...)
if len(crc32CData) != 132 {
slog.Warn("BtmDataMessageEndFrame crc32 校验数据须132字节")
return nil, false
}
end.Crc32C = calculateDataRspCrc32C(crc32CData)
rt = append(rt, end.Encode().GetData()...)
if len(rt) != 204 {
slog.Warn("BTM响应ATP 17帧须136字节")
return nil, false
}
//
return rt, true
}
// CAN帧中除去开始29bits的剩余8字节数据
func canFrameContent(canFrame CanBusData) []byte {
rd := NewCanBitsReader(canFrame.GetData(), canFrame.GetLastRowBitsLen())
rd.ReadByte() //ID1
rd.ReadByte() //ID2
rd.ReadByte() //ID3
rd.ReadBits(5) //ID4
//
rt := make([]byte, 0, 8)
for {
d, ok := rd.ReadByte()
if !ok {
break
}
rt = append(rt, d)
}
if len(rt) != 8 {
panic("CAN帧中数据体须为8字节")
}
return rt
}

View File

@ -218,3 +218,16 @@ func calculateAtpReqCrc16(data []byte) uint16 {
crc := CrcTableBased(data, 16, 0, false, false, 0, crc16AtpReqTable)
return uint16(crc)
}
// CRC32A的校验范围是报文+时间戳A
func calculateDataRspCrc32A(data []byte) uint32 {
return 0
}
// CRC32B的校验范围是报文+时间戳B
func calculateDataRspCrc32B(data []byte) uint32 {
return 0
}
func calculateDataRspCrc32C(data []byte) uint32 {
return 0
}