rts-sim-testing-service/third_party/message/btm_vobc_data.go

271 lines
11 KiB
Go
Raw Normal View History

2024-05-29 11:48:04 +08:00
package message
import (
"bytes"
"encoding/binary"
"encoding/hex"
"fmt"
"github.com/snksoft/crc"
"log/slog"
"strconv"
"sync"
)
const (
TRAIN_BTM_ENDA = 0x75E1
TRAIN_BTM_ENDB = 0x75E2
ID_COMMAND_TYPE = 0xF8 //命令帧
REQT_TYPE = 0xE6 //请求帧
)
const (
COMMAND_TYPE = 0x90 //ID 命令帧 VOBC→BTM20 字节
REQUEST_TYPE = 0x91 //请求帧 VOBC→BTM34 字节
MESSAGE_TYPE = 0x92 //报文帧 BTM→VOBC 135 字节
FREE_MESSAGE_TYPE = 0x94 //空闲帧 BTM→VOBC 135 字节
)
var PACKAGE_HEAD = []byte{0xFF, 0xFE}
var PACKAGE_END = []byte{0xFF, 0xFD}
func BtmVobcDecode(packData []byte) (byte, []byte, error) {
head := packData[:2]
end := packData[len(packData)-2:]
if !bytes.Equal(head, PACKAGE_HEAD) || !bytes.Equal(end, PACKAGE_END) {
slog.Error("btm vobc 数据包头或包尾尾错误", hex.EncodeToString(packData))
return 0, nil, fmt.Errorf("btm vobc 数据包头或包尾尾错误")
}
data := packData[2 : len(packData)-2]
command := data[0]
if command != ID_COMMAND_TYPE && command != REQT_TYPE {
slog.Error("btm vobc 解析未知命令帧", strconv.FormatInt(int64(command), 16), command)
return 0, nil, fmt.Errorf("btm vobc 解析未知命令帧")
}
dataText := data[1:]
frameType := dataText[0]
return frameType, dataText, nil
/* if frameType == COMMAND_TYPE {
} else if frameType == REQUEST_TYPE {
} else {
slog.Error("btm vobc 解析未知命令帧类型", strconv.FormatInt(int64(frameType), 16))
return
}*/
}
type BaseBtmVobc struct {
Frame byte //帧类型
FrameLen byte //帧长定义为 TEXT+CRC32ID 命令帧为 20 字节;
AutoIdFrame byte // 无论何时传输数据,该数都在 1-255 范围内递增在错误重传时也是递增的255 之后是 1不使用 0
Crc32 uint32
}
func baseDecode(d []byte) (BaseBtmVobc, []byte) {
frame := d[0]
frameLen := d[1]
autoIdFrame := d[2]
crc32 := binary.BigEndian.Uint32(d[len(d)-4:])
realData := d[3 : len(d)-4]
return BaseBtmVobc{Frame: frame, FrameLen: frameLen, Crc32: crc32, AutoIdFrame: autoIdFrame}, realData
}
func baseEncode(source []byte) []byte {
data := make([]byte, 0)
crc32 := crc.CalculateCRC(crc.CRC32, source)
newSource := binary.BigEndian.AppendUint32(source, uint32(crc32))
data = append(data, PACKAGE_HEAD...)
data = append(data, newSource...)
data = append(data, PACKAGE_END...)
return data
}
// ID 命令帧的正文
type BtmVobcIdCommand struct {
BaseBtmVobc
BtmId uint16 //VOBC 向 BTM 分配的 ID暂定 0x75E1 或者0x75A2其他无效
VobcId uint16 //暂定 0x5511其他无效
VobcLifeNum uint32 //7~10 1~FFFFFFFF0 不使用
yuliu []byte //11-15 预留字节
}
func (b *BtmVobcIdCommand) Decode(data []byte) {
base, realData := baseDecode(data)
b.BaseBtmVobc = base
b.BtmId = binary.BigEndian.Uint16(realData[0:2])
b.VobcId = binary.BigEndian.Uint16(realData[2:4])
b.VobcLifeNum = binary.BigEndian.Uint32(realData[4:8])
}
// 请求帧的正文
type BtmVobcReq struct {
BaseBtmVobc
FrameStatus byte //帧正确/不正确 06h帧正确15h不正确00h开机状态填00 其它无效
MessageType byte // 空闲/报文数据 05h空闲0Ah报文数据00h开机状态填00 其它无效
MessageSerial byte //报文序列号 1-255开机时使用0
yuliu []byte //预留字节10 字节)
VobcLifeNum uint32 // VOBC 周期号 1~FFFFFFFF0 不使用
TimeStamp []byte //年月日时分秒各占一个字节
Speed uint16 //速度 单位cm/s
VobcLifeWalkDistance uint16 //VOBC 周期走行距离 单位cm
}
func (b *BtmVobcReq) Decode(data []byte) {
base, realData := baseDecode(data)
b.BaseBtmVobc = base
b.FrameStatus = realData[0]
b.MessageType = realData[1]
b.MessageSerial = realData[2]
b.yuliu = realData[3:13]
b.VobcLifeNum = binary.BigEndian.Uint32(realData[13:17])
b.TimeStamp = realData[17:25]
b.Speed = binary.BigEndian.Uint16(realData[25:26])
b.VobcLifeWalkDistance = binary.BigEndian.Uint16(realData[26:27])
}
var MESSAGE_AUTO_ID byte = 1
var MESSAGE_SERIAL byte = 1
var lock sync.Mutex
func getAutoId() byte {
defer lock.Unlock()
lock.Lock()
if MESSAGE_AUTO_ID <= 0 {
MESSAGE_AUTO_ID = 1
} else if MESSAGE_AUTO_ID > 255 {
MESSAGE_AUTO_ID = 1
}
MESSAGE_AUTO_ID += 1
return MESSAGE_AUTO_ID
}
func getAutoMessageId() byte {
defer lock.Unlock()
lock.Lock()
if MESSAGE_SERIAL <= 0 {
MESSAGE_SERIAL = 1
} else if MESSAGE_SERIAL > 255 {
MESSAGE_SERIAL = 1
}
MESSAGE_SERIAL += 1
return MESSAGE_SERIAL
}
const (
btm_status_ok = 0x00
btm_status_warn = 0x04
)
var mesage_yuliu = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0}
// 报文帧的正文
type BtmVobcMessage struct {
BaseBtmVobc
FontTtl uint16 //前沿 TTL 时间 单位为 ms溢出为0xffff高字节在前车体及应答器器地面环境理想情况下误差小于 5ms
MsgSerial byte //报文序列号 1-255不使用 0
BtmStatus byte //BTM 工作状态 00H-工作正常04H-警告 BTM 有轻微故障单套故障整机能工作向BDMS 汇报FFH-BTM 故障不能正常工作在MMI进行故障提示并向ATS 汇报
Enter1 byte //1 通道好码率 0~100
Enter2 byte //2 通道好码率 0~100
DecodeTime uint16 //解码时间从包络前沿到解码成功的时间单位0.1ms。
yuliu []byte //11~19 预留 填 0
BackTtl uint16 //后沿 TTL 时间单位为 ms溢出为0xffff高字节在前车体及应答器器地面环境理想情况下误差小于 5ms.
BtmMsg []byte //22~125 应答器报文
ResponseTime byte //0~150其他非法单位0.1ms 误差小于 3ms
VobcLifeNum uint32 //VOBC 周期号 1~FFFFFFFF0 不使用。
}
func (b *BtmVobcMessage) Encode() []byte {
data := make([]byte, 0)
buf := bytes.NewBuffer(data)
b.MsgSerial = getAutoMessageId()
binary.Write(buf, binary.BigEndian, byte(MESSAGE_TYPE))
binary.Write(buf, binary.BigEndian, byte(0x87))
binary.Write(buf, binary.BigEndian, b.AutoIdFrame)
//binary.Write(buf, binary.BigEndian, getAutoId())
binary.Write(buf, binary.BigEndian, b.FontTtl)
binary.Write(buf, binary.BigEndian, b.MsgSerial)
binary.Write(buf, binary.BigEndian, b.BtmStatus)
binary.Write(buf, binary.BigEndian, byte(100)) //b.Enter1
binary.Write(buf, binary.BigEndian, byte(100)) //b.Enter2
binary.Write(buf, binary.BigEndian, b.DecodeTime)
binary.Write(buf, binary.BigEndian, mesage_yuliu)
binary.Write(buf, binary.BigEndian, b.BackTtl)
binary.Write(buf, binary.BigEndian, b.BtmMsg)
binary.Write(buf, binary.BigEndian, b.ResponseTime)
binary.Write(buf, binary.BigEndian, b.VobcLifeNum)
return baseEncode(buf.Bytes())
}
var yuliu3 = []byte{0, 0, 0, 0, 0, 0}
type BtmVobcMsgFree struct {
BaseBtmVobc
//yuliu1 byte
//yuliu2 byte
MsgSerial byte //1-255开机时为0
BtmStatus byte //BTM 工作状态 00H-工作正常04H-警告 BTM 有轻微故障单套故障整机能工作向BDMS 汇报FFH-BTM 故障不能正常工作在MMI 进行故障提示并向ATS 汇报
WorkTemperature byte
//yuliu3 []byte //8~13 保留 填 0
//0-1 位 功放 1 电流状态 功放电流状态“1”-欠流“2”- 过流 “3”-正常(欠流和过流仅作为功放状态参考)
//2-3 位 功放 1 电压状态 功放电压状态“1”-欠压“2”- 过压 “3”-正常(欠压和过压仅作为功放状态参考)
//4-5 位 (预留) 功放 2 电流状态 功放电流状态“1”-欠流“2”- 过流 “3”-正常(欠流和过流仅作为功放状态参考)
//6-7 位 功放 2 电压状 功放电压状态“1”-欠压“2”- 过压 “3”-正常(欠压和过压仅作为功放状态参考)
//8-9 位 天线 1 状态 天线 1 状态“1”-故障“3”-正常。
//10-11 位 线缆 1 状态 线缆 1 状态“1”-开路“2”-短路“3”-正常。
//12-13 位 (预留) 天线 2 状态 天线 2 状态“1”-故障“3”-正常。
//14-15 位 (预留) 线缆 2 状态 线缆 2 状态“1”-开路“2”-短路“3”-正常。
Fun1 uint16 //第 14-15 字节(功放板、天线状态)
//第 0 位 上行自检码检测通道 1 状态“1”-正常“0”-故障。(故障时,检查处理器板和接收板)
//第 1 位 上行自检码检测通道 2 状态“1”-正常“0”-故障。(故障时,检查处理器板和接收板)
//第 2 位 FSK 连接线状态通道 1状态“1”-正常“0”-故障。
//第 3 位 FSK 连接线状态通道 2状态“1”-正常“0”-故障。
//第 4-5 位 保留 保留
//第 6-7 位 接收板状态 状态“0”-双通道故障“1”-单通道故障“3”-正常第
//8-15位保留 保留
Fun2 uint16 //第 16-17 字节(接收板状态)
//第 0-1 位 通 道 1-24V 状态 状态“1”-过压“2”-欠压“3”-正常;(欠压和过压仅作为电源板状态参考)
//第 2-3 位 通 道 2-24V 状态 状态“1”-过压“2”-欠压“3”-正常;(欠压和过压仅作为电源板状态参考)
//第 4 位 通 道 1-23V 状态 状态“1”-正常“0”-故障。
//第 5 位 通 道 2-23V 状态 状态“1”-正常“0”-故障。
//第 6-13位保留 保留
//第 14-15位 电源板状态 电源板状态“0”-故障“1”-单通道故障“2”-单通道故障“3”- 正常。
Fun3 uint16 //第 18-19 字节(电源板状态)
//第 0-1 位 板卡 ID 槽位号 “0”-1 号板卡“1”-2 号板卡“2”-3 号板卡“3”-4 号板卡机箱正面从右往左顺序为处理器板1,2,3预留,4预留同一个通信周期只有一个板卡报警
//第 2-3 位 工作温度状态 “0”-过高“1”-温度报警“2”-未知“3”-正常。
//其他位保留 注保留位全部为1
Fun4 uint16 //第 20-21 字节(处理器板)
FreeMsg []byte //22~125 空闲数据 全填 00H
RespTime byte //响应时间 0~150其他非法单位0.1ms
VobcLifeNum uint32 //VOBC 周期号 1~FFFFFFFF0 不使用。
}
func (b *BtmVobcMsgFree) Encode() []byte {
data := make([]byte, 0)
buf := bytes.NewBuffer(data)
b.MsgSerial = getAutoMessageId()
binary.Write(buf, binary.BigEndian, byte(FREE_MESSAGE_TYPE))
binary.Write(buf, binary.BigEndian, byte(0x87))
//binary.Write(buf, binary.BigEndian, getAutoId())
binary.Write(buf, binary.BigEndian, b.AutoIdFrame)
binary.Write(buf, binary.BigEndian, byte(0)) //保留
binary.Write(buf, binary.BigEndian, byte(0)) //保留
binary.Write(buf, binary.BigEndian, b.MsgSerial)
binary.Write(buf, binary.BigEndian, b.BtmStatus)
binary.Write(buf, binary.BigEndian, b.WorkTemperature)
binary.Write(buf, binary.BigEndian, yuliu3)
binary.Write(buf, binary.BigEndian, b.Fun1)
binary.Write(buf, binary.BigEndian, b.Fun2)
binary.Write(buf, binary.BigEndian, b.Fun3)
binary.Write(buf, binary.BigEndian, b.Fun4)
binary.Write(buf, binary.BigEndian, b.FreeMsg)
binary.Write(buf, binary.BigEndian, b.RespTime)
binary.Write(buf, binary.BigEndian, b.VobcLifeNum)
return baseEncode(buf.Bytes())
}