222 lines
5.1 KiB
Go
222 lines
5.1 KiB
Go
package message
|
||
|
||
import (
|
||
"fmt"
|
||
"log/slog"
|
||
"strings"
|
||
)
|
||
|
||
//应答器传输模块BTM与车载ATP通信协议定义
|
||
|
||
const (
|
||
CAN_ADDR_REQ_BTM = byte(0x62) //设备地址
|
||
CAN_ADDR_REQ_ATP = byte(0x81) //设备地址
|
||
CAN_ADDR_RSP_BTM = byte(0x02) //设备地址
|
||
CAN_ADDR_RSP_ATP = byte(0x01) //设备地址
|
||
CAN_FRAME_ATP_REQ = byte(0x02) //帧类型-查询请求帧
|
||
CAN_FRAME_STATUS_RSP = byte(0x01) //状态应答帧
|
||
CAN_FRAME_TIME_SYNC_RSP = byte(0x02) //时间同步应答帧
|
||
CAN_FRAME_DATA_RSP = byte(0x80) //数据应答帧
|
||
CAN_FRAME_DATA_END_RSP = byte(0xff) //数据结束应答帧
|
||
)
|
||
|
||
////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
// CanFrameId CAN串行总线帧ID定义,29bits
|
||
type CanFrameId struct {
|
||
//ID1 8bits
|
||
ID1 byte
|
||
//ID2 8bits
|
||
ID2 byte
|
||
//ID3 8bits
|
||
ID3 byte
|
||
//ID4 5bits ,有效位[bit4,bit0],无效位[bit7,bit5]
|
||
ID4 byte
|
||
}
|
||
|
||
// NewCanFrameId 创建CAN串行总线帧ID
|
||
// dstAddr 目的设备地址
|
||
// srcAddr 源设备地址
|
||
// frameType 帧类型
|
||
// sn 序列号
|
||
func NewCanFrameId(dstAddr byte, srcAddr byte, frameType byte, sn byte) *CanFrameId {
|
||
return &CanFrameId{
|
||
ID1: dstAddr,
|
||
ID2: srcAddr,
|
||
ID3: frameType,
|
||
ID4: sn,
|
||
}
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////
|
||
|
||
// AtpRequestFrame ATP查询帧
|
||
type AtpRequestFrame struct {
|
||
//帧ID
|
||
FId CanFrameId
|
||
//功率放大器命令,false-0关闭功率放大器,true-1s开启功率放大器
|
||
PowerAmplifierTurnOn bool
|
||
//功率放大器控制者,false-0BTM控制,true-1ATP控制
|
||
PowerAmplifierControlledByAtp bool
|
||
//重发请求
|
||
ResendRequest byte
|
||
//速度,1=0.1km/h
|
||
Speed uint16
|
||
//当前ATP系统时间,1=1ms
|
||
Time uint32
|
||
//crc 校验码,从数据流中接收到的
|
||
Crc16 uint16
|
||
//解码时CRC16校验结果,true-校验通过
|
||
Crc16CheckOk bool
|
||
}
|
||
|
||
// NewAtpRequestFrame 创建ATP查询帧
|
||
func NewAtpRequestFrame(sn byte) *AtpRequestFrame {
|
||
return &AtpRequestFrame{
|
||
FId: *NewCanFrameId(CAN_ADDR_REQ_BTM, CAN_ADDR_REQ_ATP, CAN_FRAME_ATP_REQ, sn),
|
||
}
|
||
}
|
||
func (f *AtpRequestFrame) String() string {
|
||
sb := strings.Builder{}
|
||
sb.WriteString(fmt.Sprintf("AtpRequestFrame ID1 = 0x%0x, ID2 = 0x%0x, ID3 = 0x%0x, ID4 = 0x%0x,",
|
||
f.FId.ID1, f.FId.ID2, f.FId.ID3, f.FId.ID4))
|
||
sb.WriteString(fmt.Sprintf("PowerAmplifierTurnOn = %t", f.PowerAmplifierTurnOn))
|
||
sb.WriteString(fmt.Sprintf(",PowerAmplifierControlledByAtp = %t", f.PowerAmplifierControlledByAtp))
|
||
sb.WriteString(fmt.Sprintf(",ResendRequest = %d", f.ResendRequest))
|
||
sb.WriteString(fmt.Sprintf(",Speed = %d", f.Speed))
|
||
sb.WriteString(fmt.Sprintf(",Time = %d", f.Time))
|
||
sb.WriteString(fmt.Sprintf(",Crc16 = %d", f.Crc16))
|
||
sb.WriteString(fmt.Sprintf(",Crc16CheckOk = %t", f.Crc16CheckOk))
|
||
return sb.String()
|
||
}
|
||
func (f *AtpRequestFrame) Decode(cf *CanetFrame) bool {
|
||
f.FId = cf.CanId
|
||
//
|
||
bits := NewCanBitsReader(cf.CanData, 8)
|
||
//
|
||
if d, ok := bits.ReadBits(1); ok {
|
||
f.PowerAmplifierTurnOn = d == 1
|
||
} else {
|
||
return false
|
||
}
|
||
if d, ok := bits.ReadBits(1); ok {
|
||
f.PowerAmplifierControlledByAtp = d == 1
|
||
} else {
|
||
return false
|
||
}
|
||
if d, ok := bits.ReadBits(2); ok {
|
||
f.ResendRequest = d
|
||
} else {
|
||
return false
|
||
}
|
||
//speed
|
||
f.Speed = 0x0000
|
||
if d, ok := bits.ReadBits(4); ok {
|
||
f.Speed = uint16(d)
|
||
f.Speed <<= 8
|
||
} else {
|
||
return false
|
||
}
|
||
if d, ok := bits.ReadByte(); ok {
|
||
f.Speed |= uint16(d)
|
||
} else {
|
||
return false
|
||
}
|
||
//time
|
||
f.Time = 0
|
||
timeArr := make([]byte, 4, 4)
|
||
if d, ok := bits.ReadByte(); ok {
|
||
timeArr[0] = d
|
||
} else {
|
||
return false
|
||
}
|
||
if d, ok := bits.ReadByte(); ok {
|
||
timeArr[1] = d
|
||
} else {
|
||
return false
|
||
}
|
||
if d, ok := bits.ReadByte(); ok {
|
||
timeArr[2] = d
|
||
} else {
|
||
return false
|
||
}
|
||
if d, ok := bits.ReadByte(); ok {
|
||
timeArr[3] = d
|
||
} else {
|
||
return false
|
||
}
|
||
crc16 := Can_Crc16(timeArr)
|
||
t1 := uint32(timeArr[0])
|
||
t2 := uint32(timeArr[1])
|
||
t3 := uint32(timeArr[2])
|
||
t4 := uint32(timeArr[3])
|
||
f.Time |= t1 << 24
|
||
f.Time |= t2 << 16
|
||
f.Time |= t3 << 8
|
||
f.Time |= t4
|
||
//crc
|
||
f.Crc16 = 0
|
||
if d, ok := bits.ReadByte(); ok {
|
||
crc1 := uint16(d)
|
||
f.Crc16 |= crc1 << 8
|
||
} else {
|
||
return false
|
||
}
|
||
if d, ok := bits.ReadByte(); ok {
|
||
crc2 := uint16(d)
|
||
f.Crc16 |= crc2
|
||
} else {
|
||
return false
|
||
}
|
||
//crc校验
|
||
f.Crc16CheckOk = f.Crc16 == crc16
|
||
if !f.Crc16CheckOk {
|
||
slog.Debug("解码AtpRequestFrame,CRC16校验未通过!!")
|
||
}
|
||
//
|
||
return true
|
||
}
|
||
func (f *AtpRequestFrame) Encode() *CanetFrame {
|
||
cf := &CanetFrame{}
|
||
cf.CanId = f.FId
|
||
cf.CanLen = 8
|
||
cf.FF = true
|
||
cf.RTR = false
|
||
//
|
||
bits := NewCanBitsWriter(8)
|
||
//
|
||
if f.PowerAmplifierTurnOn {
|
||
bits.AddBits(1, 1)
|
||
} else {
|
||
bits.AddBits(0, 1)
|
||
}
|
||
//
|
||
if f.PowerAmplifierControlledByAtp {
|
||
bits.AddBits(1, 1)
|
||
} else {
|
||
bits.AddBits(0, 1)
|
||
}
|
||
//
|
||
bits.AddBits(f.ResendRequest, 2)
|
||
//速度
|
||
bits.AddBits(byte(f.Speed>>8), 4)
|
||
bits.AddByte(byte(f.Speed))
|
||
//时间
|
||
timeArr := make([]byte, 4, 4)
|
||
timeArr[0] = byte(f.Time >> 24)
|
||
timeArr[1] = byte(f.Time >> 16)
|
||
timeArr[2] = byte(f.Time >> 8)
|
||
timeArr[3] = byte(f.Time)
|
||
for _, timeByte := range timeArr {
|
||
bits.AddByte(timeByte)
|
||
}
|
||
//crc
|
||
crc16 := Can_Crc16(timeArr)
|
||
bits.AddByte(byte(crc16 >> 8))
|
||
bits.AddByte(byte(crc16))
|
||
//
|
||
cf.CanData = bits.(CanBusData).GetData()
|
||
//
|
||
return cf
|
||
}
|