# Conflicts:
#	ts/protos/graphicData/stationLayoutGraphics.pb.go
This commit is contained in:
weizhihong 2023-11-22 17:07:08 +08:00
commit 2a0265941d
11 changed files with 415 additions and 191 deletions

128
third_party/can_btm/balise_btm.go vendored Normal file
View File

@ -0,0 +1,128 @@
package can_btm
import (
"fmt"
"joylink.club/bj-rtsts-server/third_party/message"
"joylink.club/bj-rtsts-server/third_party/udp"
"log/slog"
"sort"
)
// btm与canet(网口-CAN口转换器)
type btmCanetClient struct {
//udp
udpServer udp.UdpServer
//udp
udpClient udp.UdpClient
localUdpPort int
remoteUdpPort int
remoteIp string
trainId string
}
type BtmCanetClient interface {
Start()
Stop()
TrainId() string
}
type BtmMessageManager interface {
BtmRcvAtpReqFrame(trainId string, atpReq *message.AtpRequestFrame)
BtmScanBaliseContent(trainId string)
}
func NewBtmCanetClient(trainId string, remoteIp string, remoteUdpPort int, localUdpPort int) BtmCanetClient {
return &btmCanetClient{trainId: trainId, remoteIp: remoteIp, remoteUdpPort: remoteUdpPort, localUdpPort: localUdpPort}
}
func (s *btmCanetClient) TrainId() string {
return s.trainId
}
func (s *btmCanetClient) Start() {
//
s.udpServer = udp.NewServer(fmt.Sprintf(":%d", s.localUdpPort), s.handleCanetFrames)
s.udpServer.Listen()
//
s.udpClient = udp.NewClient(fmt.Sprintf("%s:%d", s.remoteIp, s.remoteUdpPort))
}
func (s *btmCanetClient) Stop() {
if s.udpServer != nil {
s.udpServer.Close()
}
if s.udpClient != nil {
s.udpClient.Close()
}
}
func (s *btmCanetClient) handleCanetFrames(cfs []byte) {
//一个cannet 帧 13字节
if len(cfs) > 0 && len(cfs)%13 == 0 {
cfSum := len(cfs) / 13
dms := make([]*message.CanetFrame, 0, 16) //13个应答器报文数据帧+TimeA帧+TimeB帧+结束帧
for cfi := 0; cfi < cfSum; cfi++ {
cfStart := cfi * 13
cf := message.NewCanetFrame(cfs[cfStart : cfStart+13])
//
switch cf.CanFrameType() {
case message.CfReq:
s.dealWithAptReq(cf)
case message.CfStatusRsp:
s.dealWithBtmStatusRsp(cf)
case message.CfTimeSync:
s.dealWithBtmTimeSyncRsp(cf)
case message.CfMsg:
fallthrough
case message.CfMsgTimeA:
fallthrough
case message.CfMsgTimeB:
fallthrough
case message.CfMsgEnd:
dms = append(dms, cf)
default:
slog.Warn("CanetFrame帧没有具体对应的应用帧", "CannetFrame", cf.String())
} //switch
} //for
//将数据包按ID3即0x80+offset由小到大排序
sort.SliceStable(dms, func(i, j int) bool {
return dms[i].CanId.ID3 < dms[j].CanId.ID3
})
//有数据帧但是不足16帧
if len(dms) > 0 {
if len(dms) != 16 {
slog.Warn("接收到数据帧但数据帧数量不足16帧")
} else {
s.dealWithBtmDataFrames(dms)
}
}
} else {
slog.Warn("从cannet接收数据未满足条件len(cfs) > 0 && len(cfs)%13 == 0", "len(cfs)", len(cfs))
}
}
// 处理接收的ATP查询请求帧
func (s *btmCanetClient) dealWithAptReq(f *message.CanetFrame) {
atpReq := &message.AtpRequestFrame{}
if !atpReq.Decode(f) {
slog.Warn("CanetFrame解码成AtpRequestFrame失败", "CanetFrame", f.String())
}
//处理查询请求
slog.Debug(fmt.Sprintf("处理查询请求:%s", atpReq.String()))
//todo
}
//////////////////////////////////////////////////////////////////////////////////////////
// 处理接收的状态应答帧
func (s *btmCanetClient) dealWithBtmStatusRsp(f *message.CanetFrame) {
slog.Debug(fmt.Sprintf("接收到状态应答帧%s", f.String()))
}
// 处理接收的时间同步校验应答帧
func (s *btmCanetClient) dealWithBtmTimeSyncRsp(f *message.CanetFrame) {
slog.Debug(fmt.Sprintf("接收到时间同步校验应答帧%s", f.String()))
}
// 处理接收到的16帧数据帧
func (s *btmCanetClient) dealWithBtmDataFrames(dms []*message.CanetFrame) {
for _, dm := range dms {
slog.Debug(fmt.Sprintf("接收到数据帧%s", dm.String()))
}
}

View File

@ -1,6 +1,10 @@
package message package message
import "log/slog" import (
"fmt"
"log/slog"
"strings"
)
//应答器传输模块BTM与车载ATP通信协议定义 //应答器传输模块BTM与车载ATP通信协议定义
@ -30,36 +34,6 @@ type CanFrameId struct {
ID4 byte ID4 byte
} }
func (f *CanFrameId) Encode(bits CanBitsWriter) {
bits.AddByte(f.ID1)
bits.AddByte(f.ID2)
bits.AddByte(f.ID3)
bits.AddBits(f.ID4, 5)
}
func (f *CanFrameId) Decode(bits CanBitsReader) bool {
if id, ok := bits.ReadByte(); ok {
f.ID1 = id
} else {
return false
}
if id, ok := bits.ReadByte(); ok {
f.ID2 = id
} else {
return false
}
if id, ok := bits.ReadByte(); ok {
f.ID3 = id
} else {
return false
}
if id, ok := bits.ReadBits(5); ok {
f.ID4 = id
} else {
return false
}
return true
}
// NewCanFrameId 创建CAN串行总线帧ID // NewCanFrameId 创建CAN串行总线帧ID
// dstAddr 目的设备地址 // dstAddr 目的设备地址
// srcAddr 源设备地址 // srcAddr 源设备地址
@ -102,10 +76,24 @@ func NewAtpRequestFrame(sn byte) *AtpRequestFrame {
FId: *NewCanFrameId(CAN_ADDR_REQ_BTM, CAN_ADDR_REQ_ATP, CAN_FRAME_ATP_REQ, sn), FId: *NewCanFrameId(CAN_ADDR_REQ_BTM, CAN_ADDR_REQ_ATP, CAN_FRAME_ATP_REQ, sn),
} }
} }
func (f *AtpRequestFrame) Decode(bits CanBitsReader) bool { func (f *AtpRequestFrame) String() string {
if !f.FId.Decode(bits) { sb := strings.Builder{}
return false 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 { if d, ok := bits.ReadBits(1); ok {
f.PowerAmplifierTurnOn = d == 1 f.PowerAmplifierTurnOn = d == 1
} else { } else {
@ -188,10 +176,14 @@ func (f *AtpRequestFrame) Decode(bits CanBitsReader) bool {
// //
return true return true
} }
func (f *AtpRequestFrame) Encode() CanBusData { func (f *AtpRequestFrame) Encode() *CanetFrame {
bits := NewCanBitsWriter(12) cf := &CanetFrame{}
cf.CanId = f.FId
cf.CanLen = 8
cf.FF = true
cf.RTR = false
// //
f.FId.Encode(bits) bits := NewCanBitsWriter(8)
// //
if f.PowerAmplifierTurnOn { if f.PowerAmplifierTurnOn {
bits.AddBits(1, 1) bits.AddBits(1, 1)
@ -223,5 +215,7 @@ func (f *AtpRequestFrame) Encode() CanBusData {
bits.AddByte(byte(crc16 >> 8)) bits.AddByte(byte(crc16 >> 8))
bits.AddByte(byte(crc16)) bits.AddByte(byte(crc16))
// //
return bits.(CanBusData) cf.CanData = bits.(CanBusData).GetData()
//
return cf
} }

View File

@ -16,20 +16,26 @@ func NewBtmDataMessageFrame(sn byte, offset byte) *BtmDataMessageFrame {
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+offset, sn), FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+offset, sn),
} }
} }
func (f *BtmDataMessageFrame) Encode() CanBusData { func (f *BtmDataMessageFrame) Encode() *CanetFrame {
writer := NewCanBitsWriter(12) cf := &CanetFrame{}
cf.CanId = f.FId
cf.CanLen = 8
cf.FF = true
cf.RTR = false
// //
f.FId.Encode(writer) writer := NewCanBitsWriter(8)
// //
for _, data := range f.Message { for _, data := range f.Message {
writer.AddByte(data) writer.AddByte(data)
} }
return writer.(CanBusData) cf.CanData = writer.(CanBusData).GetData()
//
return cf
} }
func (f *BtmDataMessageFrame) Decode(reader CanBitsReader) bool { func (f *BtmDataMessageFrame) Decode(cf *CanetFrame) bool {
if !f.FId.Decode(reader) { f.FId = cf.CanId
return false //
} reader := NewCanBitsReader(cf.CanData, 8)
// //
f.Message = make([]byte, 0, 8) f.Message = make([]byte, 0, 8)
for c := 0; c < 8; c++ { for c := 0; c < 8; c++ {
@ -61,10 +67,14 @@ func NewBtmDataMessageTimeAFrame(sn byte) *BtmDataMessageTimeAFrame {
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x0d, sn), FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x0d, sn),
} }
} }
func (f *BtmDataMessageTimeAFrame) Encode() CanBusData { func (f *BtmDataMessageTimeAFrame) Encode() *CanetFrame {
writer := NewCanBitsWriter(12) cf := &CanetFrame{}
cf.CanId = f.FId
cf.CanLen = 8
cf.FF = true
cf.RTR = false
// //
f.FId.Encode(writer) writer := NewCanBitsWriter(8)
// //
byteMsk := uint32(0x00_00_00_ff) byteMsk := uint32(0x00_00_00_ff)
// //
@ -78,13 +88,15 @@ func (f *BtmDataMessageTimeAFrame) Encode() CanBusData {
writer.AddByte(byte((f.Crc32A >> 8) & byteMsk)) writer.AddByte(byte((f.Crc32A >> 8) & byteMsk))
writer.AddByte(byte(f.Crc32A & byteMsk)) writer.AddByte(byte(f.Crc32A & byteMsk))
// //
return writer.(CanBusData) cf.CanData = writer.(CanBusData).GetData()
//
return cf
} }
func (f *BtmDataMessageTimeAFrame) Decode(reader CanBitsReader) bool { func (f *BtmDataMessageTimeAFrame) Decode(cf *CanetFrame) bool {
if !f.FId.Decode(reader) { f.FId = cf.CanId
return false //
} reader := NewCanBitsReader(cf.CanData, 8)
// //
f.TimeA = 0 f.TimeA = 0
a1, a1Ok := reader.ReadByte() a1, a1Ok := reader.ReadByte()
@ -157,10 +169,14 @@ func NewBtmDataMessageTimeBFrame(sn byte) *BtmDataMessageTimeBFrame {
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x0e, sn), FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x0e, sn),
} }
} }
func (f *BtmDataMessageTimeBFrame) Encode() CanBusData { func (f *BtmDataMessageTimeBFrame) Encode() *CanetFrame {
writer := NewCanBitsWriter(12) cf := &CanetFrame{}
cf.CanId = f.FId
cf.CanLen = 8
cf.FF = true
cf.RTR = false
// //
f.FId.Encode(writer) writer := NewCanBitsWriter(8)
// //
byteMsk := uint32(0x00_00_00_ff) byteMsk := uint32(0x00_00_00_ff)
// //
@ -174,12 +190,14 @@ func (f *BtmDataMessageTimeBFrame) Encode() CanBusData {
writer.AddByte(byte((f.Crc32B >> 8) & byteMsk)) writer.AddByte(byte((f.Crc32B >> 8) & byteMsk))
writer.AddByte(byte(f.Crc32B & byteMsk)) writer.AddByte(byte(f.Crc32B & byteMsk))
// //
return writer.(CanBusData) cf.CanData = writer.(CanBusData).GetData()
//
return cf
} }
func (f *BtmDataMessageTimeBFrame) Decode(reader CanBitsReader) bool { func (f *BtmDataMessageTimeBFrame) Decode(cf *CanetFrame) bool {
if !f.FId.Decode(reader) { f.FId = cf.CanId
return false //
} reader := NewCanBitsReader(cf.CanData, 8)
// //
f.TimeB = 0 f.TimeB = 0
a1, a1Ok := reader.ReadByte() a1, a1Ok := reader.ReadByte()
@ -253,10 +271,14 @@ func NewBtmDataMessageEndFrame(sn byte) *BtmDataMessageEndFrame {
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x7f, sn), FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x7f, sn),
} }
} }
func (f *BtmDataMessageEndFrame) Encode() CanBusData { func (f *BtmDataMessageEndFrame) Encode() *CanetFrame {
writer := NewCanBitsWriter(12) cf := &CanetFrame{}
cf.CanId = f.FId
cf.CanLen = 8
cf.FF = true
cf.RTR = false
// //
f.FId.Encode(writer) writer := NewCanBitsWriter(8)
// //
byteMsk := uint32(0x00_00_00_ff) byteMsk := uint32(0x00_00_00_ff)
// //
@ -270,12 +292,14 @@ func (f *BtmDataMessageEndFrame) Encode() CanBusData {
writer.AddByte(byte((f.Crc32C >> 8) & byteMsk)) writer.AddByte(byte((f.Crc32C >> 8) & byteMsk))
writer.AddByte(byte(f.Crc32C & byteMsk)) writer.AddByte(byte(f.Crc32C & byteMsk))
// //
return writer.(CanBusData) cf.CanData = writer.(CanBusData).GetData()
//
return cf
} }
func (f *BtmDataMessageEndFrame) Decode(reader CanBitsReader) bool { func (f *BtmDataMessageEndFrame) Decode(cf *CanetFrame) bool {
if !f.FId.Decode(reader) { f.FId = cf.CanId
return false //
} reader := NewCanBitsReader(cf.CanData, 8)
// //
f.TkB = 0 f.TkB = 0
a1, a1Ok := reader.ReadByte() a1, a1Ok := reader.ReadByte()

View File

@ -61,60 +61,38 @@ func CreateBtmRspFramesData(statusRsp *BtmStatusRspFrame, msg []byte, msgPackErr
end := NewBtmDataMessageEndFrame(sn) end := NewBtmDataMessageEndFrame(sn)
end.TkB = tkTimeB end.TkB = tkTimeB
// //
crc32CData := make([]byte, 0, 132) //17*8-4 statusCf := statusRsp.Encode()
rt := make([]byte, 0, 204) //17*12 dmsCfs := make([]*CanetFrame, 0, 13)
// 状态应答帧
statusData := statusRsp.Encode()
crc32CData = append(crc32CData, canFrameContent(statusData)...)
rt = append(rt, statusData.GetData()...)
// 数据帧
for _, dm := range dms { for _, dm := range dms {
dmData := dm.Encode() dmsCfs = append(dmsCfs, 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
} }
dtACf := dtA.Encode()
dtBCf := dtB.Encode()
// //
crc32cData := make([]byte, 0, 132)
crc32cData = append(crc32cData, statusCf.CanData...)
for _, dmCf := range dmsCfs {
crc32cData = append(crc32cData, dmCf.CanData...)
}
crc32cData = append(crc32cData, dtACf.CanData...)
crc32cData = append(crc32cData, dtBCf.CanData...)
crc32cData = append(crc32cData, canTimeToBytes(end.TkB)...)
//
end.Crc32C = calculateDataRspCrc32C(crc32cData)
//
endCf := end.Encode()
//
rt := make([]byte, 0, 221) //17*13
rt = append(rt, statusCf.Encode()...)
for _, dmCf := range dmsCfs {
rt = append(rt, dmCf.Encode()...)
}
rt = append(rt, dtACf.Encode()...)
rt = append(rt, dtBCf.Encode()...)
rt = append(rt, endCf.Encode()...)
if len(rt) != 221 {
slog.Warn("len(rt)!=221")
return nil, false
}
return rt, true 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

@ -29,10 +29,10 @@ func NewBtmStatusRspFrame(sn byte) *BtmStatusRspFrame {
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, CAN_FRAME_STATUS_RSP, sn), FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, CAN_FRAME_STATUS_RSP, sn),
} }
} }
func (f *BtmStatusRspFrame) Decode(reader CanBitsReader) bool { func (f *BtmStatusRspFrame) Decode(cf *CanetFrame) bool {
if !f.FId.Decode(reader) { f.FId = cf.CanId
return false //
} reader := NewCanBitsReader(cf.CanData, 8)
//数据流水号 //数据流水号
if d, ok := reader.ReadByte(); ok { if d, ok := reader.ReadByte(); ok {
f.Dsn = d f.Dsn = d
@ -106,10 +106,14 @@ func (f *BtmStatusRspFrame) Decode(reader CanBitsReader) bool {
// //
return true return true
} }
func (f *BtmStatusRspFrame) Encode() CanBusData { func (f *BtmStatusRspFrame) Encode() *CanetFrame {
writer := NewCanBitsWriter(12) cf := &CanetFrame{}
cf.CanId = f.FId
cf.CanLen = 8
cf.FF = true
cf.RTR = false
// //
f.FId.Encode(writer) writer := NewCanBitsWriter(8)
writer.AddByte(f.Dsn) writer.AddByte(f.Dsn)
writer.AddByte(f.BaliseCounter) writer.AddByte(f.BaliseCounter)
writer.AddByte(f.MessageCounter) writer.AddByte(f.MessageCounter)
@ -150,5 +154,6 @@ func (f *BtmStatusRspFrame) Encode() CanBusData {
writer.AddByte(tk3) writer.AddByte(tk3)
writer.AddByte(tk4) writer.AddByte(tk4)
// //
return writer.(CanBusData) cf.CanData = writer.(CanBusData).GetData()
return cf
} }

View File

@ -17,11 +17,10 @@ func NewBtmTimeSyncCheckFrame(sn byte) *BtmTimeSyncCheckFrame {
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, CAN_FRAME_TIME_SYNC_RSP, sn), FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, CAN_FRAME_TIME_SYNC_RSP, sn),
} }
} }
func (f *BtmTimeSyncCheckFrame) Decode(reader CanBitsReader) bool { func (f *BtmTimeSyncCheckFrame) Decode(cf *CanetFrame) bool {
f.FId = cf.CanId
// //
if !f.FId.Decode(reader) { reader := NewCanBitsReader(cf.CanData, 8)
return false
}
//T2 //T2
t21, t21Ok := reader.ReadByte() t21, t21Ok := reader.ReadByte()
if !t21Ok { if !t21Ok {
@ -69,9 +68,14 @@ func (f *BtmTimeSyncCheckFrame) Decode(reader CanBitsReader) bool {
// //
return true return true
} }
func (f *BtmTimeSyncCheckFrame) Encode() CanBusData { func (f *BtmTimeSyncCheckFrame) Encode() *CanetFrame {
writer := NewCanBitsWriter(12) cf := &CanetFrame{}
f.FId.Encode(writer) cf.CanId = f.FId
cf.CanLen = 8
cf.FF = true
cf.RTR = false
//
writer := NewCanBitsWriter(8)
// //
timeByteMsk := uint32(0x00_00_00_ff) timeByteMsk := uint32(0x00_00_00_ff)
//t2 //t2
@ -93,5 +97,6 @@ func (f *BtmTimeSyncCheckFrame) Encode() CanBusData {
writer.AddByte(t33) writer.AddByte(t33)
writer.AddByte(t34) writer.AddByte(t34)
// //
return writer.(CanBusData) cf.CanData = writer.(CanBusData).GetData()
return cf
} }

View File

@ -4,8 +4,6 @@ package message
// CanBits 可以在CAN总线上传输的bit流 // CanBits 可以在CAN总线上传输的bit流
// 按bit位来存储数据 // 按bit位来存储数据
// 一个字节中bit位编号从高位到低位依次为bit7-bit0
// 对于一个CAN帧29bits帧ID+64bits帧数据以bit为单位最后一字节即第12个字节的低位3bits为无用数据
type CanBits struct { type CanBits struct {
Data []byte //bits Data []byte //bits
LastBitsLen int //Data中最后一个字节中从高位到低位存储数据的有效位数值范围[1,8],8-LastBitsLen则为最后一个字节中低位剩余的空位数量 LastBitsLen int //Data中最后一个字节中从高位到低位存储数据的有效位数值范围[1,8],8-LastBitsLen则为最后一个字节中低位剩余的空位数量
@ -203,31 +201,40 @@ const (
const ( const (
CAN_CRC16_ATPREQ = 0x11021 CAN_CRC16_ATPREQ = 0x11021
CAN_CRC32 = 0x04C11DB7
) )
var ( var (
crc16AtpReqTable []uint32 = nil crc16AtpReqTable []uint32 = nil
crc32CanTable []uint32 = nil
) )
func CanCreateCrcTable() { func CreateCanCrcTable() {
if crc16AtpReqTable == nil { if crc16AtpReqTable == nil {
crc16AtpReqTable = CreateCrcTable(CAN_CRC16_ATPREQ, 16, false) crc16AtpReqTable = CreateCrcTable(CAN_CRC16_ATPREQ, 16, false)
} }
if crc32CanTable == nil {
crc32CanTable = CreateCrcTable(CAN_CRC32, 32, false)
}
} }
func calculateAtpReqCrc16(data []byte) uint16 { func calculateAtpReqCrc16(data []byte) uint16 {
crc := CrcTableBased(data, 16, 0, false, false, 0, crc16AtpReqTable) crc := CrcTableBased(data, 16, 0, false, false, 0, crc16AtpReqTable)
return uint16(crc) return uint16(crc)
} }
func calculateCanCrc32(data []byte) uint32 {
crc := CrcTableBased(data, 32, 0xFF_FF_FF_FF, false, false, 0, crc32CanTable)
return crc
}
// CRC32A的校验范围是报文+时间戳A // CRC32A的校验范围是报文+时间戳A
func calculateDataRspCrc32A(data []byte) uint32 { func calculateDataRspCrc32A(data []byte) uint32 {
return 0 return calculateCanCrc32(data)
} }
// CRC32B的校验范围是报文+时间戳B // CRC32B的校验范围是报文+时间戳B
func calculateDataRspCrc32B(data []byte) uint32 { func calculateDataRspCrc32B(data []byte) uint32 {
return 0 return calculateCanCrc32(data)
} }
func calculateDataRspCrc32C(data []byte) uint32 { func calculateDataRspCrc32C(data []byte) uint32 {
return 0 return calculateCanCrc32(data)
} }

124
third_party/message/can_net.go vendored Normal file
View File

@ -0,0 +1,124 @@
package message
import (
"fmt"
"log/slog"
"strings"
)
// CanetFrame USR-CANET200_V1.0.7 设备 以太网-CAN 透传协议帧(13字节)
type CanetFrame struct {
FF bool //true-1扩展帧
RTR bool //true-1远程帧
CanLen byte //CAN帧数据长度[0,8]CanData中有效数据字节数
CanId CanFrameId //CAN帧ID
CanData []byte //CAN帧数据8字节
}
func NewCanetFrame(buf []byte) *CanetFrame {
cf := &CanetFrame{}
cf.Decode(buf)
return cf
}
func (p *CanetFrame) Encode() []byte {
buf := make([]byte, 0, 13)
//canet200帧信息
b1 := byte(0x00)
if p.FF {
b1 |= 0x80 //bit7
}
if p.RTR {
b1 |= 0x40 //bit6
}
b1 |= p.CanLen & 0x0f
buf = append(buf, b1)
//CAN 帧ID
buf = append(buf, p.CanId.ID1)
buf = append(buf, p.CanId.ID2)
buf = append(buf, p.CanId.ID3)
buf = append(buf, p.CanId.ID4<<3)
//CAN 帧数据
if len(p.CanData) != 8 {
panic("len(p.CanData)!=8")
}
buf = append(buf, p.CanData...)
return buf
}
func (p *CanetFrame) Decode(buf []byte) {
if len(buf) != 13 {
panic("len(buf)!=13")
}
//
p.FF = buf[0]&0x80 == 0x80
p.RTR = buf[0]&0x40 == 0x40
p.CanLen = buf[0] & 0x0f
//1 2 3 4
p.CanId.ID1 = buf[1]
p.CanId.ID2 = buf[2]
p.CanId.ID3 = buf[3]
p.CanId.ID4 = buf[4] >> 3
//
p.CanData = buf[5:]
}
func (p *CanetFrame) String() string {
sb := strings.Builder{}
sb.WriteString(fmt.Sprintf("CanetFrame FF = %t, RTR = %t, CanLen = %d, ID1 = 0x%0x, ID2 = 0x%0x, ID3 = 0x%0x, ID4 = 0x%0x,", p.FF, p.RTR, p.CanLen,
p.CanId.ID1, p.CanId.ID2, p.CanId.ID3, p.CanId.ID4))
sb.WriteString("CanData = ")
for _, d := range p.CanData {
sb.WriteString(fmt.Sprintf(" 0x%0x ", d))
}
return sb.String()
}
// CanFrameType 获取canet帧类型
func (p *CanetFrame) CanFrameType() CanFrameType {
switch p.CanId.ID3 {
case 0x01:
{ //状态应答帧0x01
return CfStatusRsp
}
case 0x8d:
{ //msgTimeA数据帧0x80+0x0d
return CfMsgTimeA
}
case 0x8e:
{ //msgTimeB数据帧0x80+0x0e
return CfMsgTimeB
}
case 0xff:
{ //msgEnd数据帧0x80+0x7f
return CfMsgEnd
}
case 0x02:
{
if p.CanId.ID1 == 0x62 && p.CanId.ID2 == 0x81 {
return CfReq
} else {
return CfTimeSync
}
}
default:
if p.CanId.ID3 >= 0x80 && p.CanId.ID3 <= 0x8c { //数据帧0x80+(0x00-0x0c)
return CfMsg
} else {
slog.Warn(fmt.Sprintf("无法识别的Canet帧[%s]", p.String()))
return CfNon
}
}
}
// CanFrameType 帧类型定义
type CanFrameType = byte
// Can帧类型枚举
const (
CfNon = CanFrameType(0)
CfReq = CanFrameType(1) //查询帧0x02
CfStatusRsp = CanFrameType(2) //状态应答帧0x01
CfTimeSync = CanFrameType(3) //时间同步校验帧0x02
CfMsg = CanFrameType(4) //数据帧0x80+(0x00-0x0c)
CfMsgTimeA = CanFrameType(5) //msgTimeA数据帧0x80+0x0d
CfMsgTimeB = CanFrameType(6) //msgTimeB数据帧0x80+0x0e
CfMsgEnd = CanFrameType(7) //msgEnd数据帧0x80+0x7f
)

View File

@ -1,41 +0,0 @@
package tcp
import "net"
type client struct {
laddr *net.TCPAddr //local address
raddr *net.TCPAddr //remote address
con *net.TCPConn //tcp 连接
}
func (c *client) NewClientWithLocal(remoteAddr string, localAddr string) *client {
ra, raEr := net.ResolveTCPAddr("tcp", remoteAddr)
if raEr != nil {
panic(raEr)
}
c.raddr = ra
//
la, laEr := net.ResolveTCPAddr("tcp", localAddr)
if laEr != nil {
panic(laEr)
}
c.laddr = la
return c
}
func (c *client) NewClient(remoteAddr string) *client {
ra, raEr := net.ResolveTCPAddr("tcp", remoteAddr)
if raEr != nil {
panic(raEr)
}
c.raddr = ra
c.con.LocalAddr()
return c
}
func (c *client) Start() error {
con, e := net.DialTCP(c.raddr.Network(), c.laddr, c.raddr)
if e != nil {
return e
}
c.con = con
return nil
}

View File

@ -1 +0,0 @@
package tcp

View File

@ -1031,10 +1031,11 @@ func fillProtoRepository(repo *proto.Repository, storage *graphicData.RtssGraphi
turnoutPort = convertDevicePort(data.TransponderRef) turnoutPort = convertDevicePort(data.TransponderRef)
} }
responder := &proto.Transponder{ responder := &proto.Transponder{
Id: data.Common.Id, Id: data.Common.Id,
Km: convertKm(data.KilometerSystem), Km: convertKm(data.KilometerSystem),
SectionId: sectionId, SectionId: sectionId,
TurnoutPort: turnoutPort, TurnoutPort: turnoutPort,
FixedTelegram: data.FixedTelegram,
} }
repo.Transponders = append(repo.Transponders, converTransponderUid(responder, uidsMap)) repo.Transponders = append(repo.Transponders, converTransponderUid(responder, uidsMap))
for _, stationName := range data.CentralizedStations { for _, stationName := range data.CentralizedStations {