Merge branch 'master' of https://git.code.tencent.com/beijing-rtss-test/bj-rtsts-server-go
# Conflicts: # ts/protos/graphicData/stationLayoutGraphics.pb.go
This commit is contained in:
commit
2a0265941d
128
third_party/can_btm/balise_btm.go
vendored
Normal file
128
third_party/can_btm/balise_btm.go
vendored
Normal 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()))
|
||||||
|
}
|
||||||
|
}
|
70
third_party/message/can_atp_req.go
vendored
70
third_party/message/can_atp_req.go
vendored
@ -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
|
||||||
}
|
}
|
||||||
|
88
third_party/message/can_btm_data.go
vendored
88
third_party/message/can_btm_data.go
vendored
@ -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()
|
||||||
}
|
//
|
||||||
func (f *BtmDataMessageFrame) Decode(reader CanBitsReader) bool {
|
return cf
|
||||||
if !f.FId.Decode(reader) {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
func (f *BtmDataMessageFrame) Decode(cf *CanetFrame) bool {
|
||||||
|
f.FId = cf.CanId
|
||||||
|
//
|
||||||
|
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()
|
||||||
}
|
//
|
||||||
func (f *BtmDataMessageTimeBFrame) Decode(reader CanBitsReader) bool {
|
return cf
|
||||||
if !f.FId.Decode(reader) {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
func (f *BtmDataMessageTimeBFrame) Decode(cf *CanetFrame) bool {
|
||||||
|
f.FId = cf.CanId
|
||||||
|
//
|
||||||
|
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()
|
||||||
}
|
//
|
||||||
func (f *BtmDataMessageEndFrame) Decode(reader CanBitsReader) bool {
|
return cf
|
||||||
if !f.FId.Decode(reader) {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
func (f *BtmDataMessageEndFrame) Decode(cf *CanetFrame) bool {
|
||||||
|
f.FId = cf.CanId
|
||||||
|
//
|
||||||
|
reader := NewCanBitsReader(cf.CanData, 8)
|
||||||
//
|
//
|
||||||
f.TkB = 0
|
f.TkB = 0
|
||||||
a1, a1Ok := reader.ReadByte()
|
a1, a1Ok := reader.ReadByte()
|
||||||
|
82
third_party/message/can_btm_rsp.go
vendored
82
third_party/message/can_btm_rsp.go
vendored
@ -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
|
|
||||||
}
|
|
||||||
|
21
third_party/message/can_btm_status_rsp.go
vendored
21
third_party/message/can_btm_status_rsp.go
vendored
@ -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
|
||||||
}
|
}
|
||||||
|
21
third_party/message/can_btm_time_sync_rsp.go
vendored
21
third_party/message/can_btm_time_sync_rsp.go
vendored
@ -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
|
||||||
}
|
}
|
||||||
|
19
third_party/message/can_bus.go
vendored
19
third_party/message/can_bus.go
vendored
@ -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
124
third_party/message/can_net.go
vendored
Normal 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
|
||||||
|
)
|
41
third_party/tcp/tcp_client.go
vendored
41
third_party/tcp/tcp_client.go
vendored
@ -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
|
|
||||||
}
|
|
1
third_party/tcp/tcp_server.go
vendored
1
third_party/tcp/tcp_server.go
vendored
@ -1 +0,0 @@
|
|||||||
package tcp
|
|
@ -1035,6 +1035,7 @@ func fillProtoRepository(repo *proto.Repository, storage *graphicData.RtssGraphi
|
|||||||
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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user