2023-11-17 14:37:32 +08:00
|
|
|
|
package message
|
|
|
|
|
|
2023-11-22 11:21:17 +08:00
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"log/slog"
|
|
|
|
|
"strings"
|
|
|
|
|
)
|
2023-11-17 14:37:32 +08:00
|
|
|
|
|
|
|
|
|
//应答器传输模块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
|
2023-11-17 16:28:05 +08:00
|
|
|
|
//crc 校验码,从数据流中接收到的
|
2023-11-17 14:37:32 +08:00
|
|
|
|
Crc16 uint16
|
2023-11-17 16:28:05 +08:00
|
|
|
|
//解码时CRC16校验结果,true-校验通过
|
|
|
|
|
Crc16CheckOk bool
|
2024-07-04 09:26:37 +08:00
|
|
|
|
IsTrainPcSim bool
|
2023-11-17 14:37:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NewAtpRequestFrame 创建ATP查询帧
|
|
|
|
|
func NewAtpRequestFrame(sn byte) *AtpRequestFrame {
|
|
|
|
|
return &AtpRequestFrame{
|
|
|
|
|
FId: *NewCanFrameId(CAN_ADDR_REQ_BTM, CAN_ADDR_REQ_ATP, CAN_FRAME_ATP_REQ, sn),
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-11-22 11:21:17 +08:00
|
|
|
|
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()
|
|
|
|
|
}
|
2023-11-21 17:20:03 +08:00
|
|
|
|
func (f *AtpRequestFrame) Decode(cf *CanetFrame) bool {
|
|
|
|
|
f.FId = cf.CanId
|
|
|
|
|
//
|
|
|
|
|
bits := NewCanBitsReader(cf.CanData, 8)
|
|
|
|
|
//
|
2023-11-17 14:37:32 +08:00
|
|
|
|
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
|
|
|
|
|
}
|
2024-01-22 13:10:10 +08:00
|
|
|
|
crc16 := Can_Crc16(timeArr)
|
2023-11-17 14:37:32 +08:00
|
|
|
|
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校验
|
2023-11-17 16:28:05 +08:00
|
|
|
|
f.Crc16CheckOk = f.Crc16 == crc16
|
|
|
|
|
if !f.Crc16CheckOk {
|
2023-11-17 14:37:32 +08:00
|
|
|
|
slog.Debug("解码AtpRequestFrame,CRC16校验未通过!!")
|
|
|
|
|
}
|
|
|
|
|
//
|
|
|
|
|
return true
|
|
|
|
|
}
|
2023-11-21 17:20:03 +08:00
|
|
|
|
func (f *AtpRequestFrame) Encode() *CanetFrame {
|
|
|
|
|
cf := &CanetFrame{}
|
2024-07-04 09:26:37 +08:00
|
|
|
|
cf.IsTrainPcSim = f.IsTrainPcSim
|
2023-11-21 17:20:03 +08:00
|
|
|
|
cf.CanId = f.FId
|
|
|
|
|
cf.CanLen = 8
|
|
|
|
|
cf.FF = true
|
|
|
|
|
cf.RTR = false
|
2023-11-17 14:37:32 +08:00
|
|
|
|
//
|
2023-11-21 17:20:03 +08:00
|
|
|
|
bits := NewCanBitsWriter(8)
|
2023-11-17 14:37:32 +08:00
|
|
|
|
//
|
|
|
|
|
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
|
2024-01-22 13:10:10 +08:00
|
|
|
|
crc16 := Can_Crc16(timeArr)
|
2023-11-17 14:37:32 +08:00
|
|
|
|
bits.AddByte(byte(crc16 >> 8))
|
|
|
|
|
bits.AddByte(byte(crc16))
|
|
|
|
|
//
|
2023-11-21 17:20:03 +08:00
|
|
|
|
cf.CanData = bits.(CanBusData).GetData()
|
|
|
|
|
//
|
|
|
|
|
return cf
|
2023-11-17 14:37:32 +08:00
|
|
|
|
}
|