diff --git a/third_party/can_btm/balise_btm.go b/third_party/can_btm/balise_btm.go new file mode 100644 index 0000000..cd03c63 --- /dev/null +++ b/third_party/can_btm/balise_btm.go @@ -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())) + } +} diff --git a/third_party/message/can_atp_req.go b/third_party/message/can_atp_req.go index a46c4df..cd07b7c 100644 --- a/third_party/message/can_atp_req.go +++ b/third_party/message/can_atp_req.go @@ -1,6 +1,10 @@ package message -import "log/slog" +import ( + "fmt" + "log/slog" + "strings" +) //应答器传输模块BTM与车载ATP通信协议定义 @@ -30,36 +34,6 @@ type CanFrameId struct { 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 // dstAddr 目的设备地址 // 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), } } -func (f *AtpRequestFrame) Decode(bits CanBitsReader) bool { - if !f.FId.Decode(bits) { - return false - } +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 { @@ -188,10 +176,14 @@ func (f *AtpRequestFrame) Decode(bits CanBitsReader) bool { // return true } -func (f *AtpRequestFrame) Encode() CanBusData { - bits := NewCanBitsWriter(12) +func (f *AtpRequestFrame) Encode() *CanetFrame { + 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 { bits.AddBits(1, 1) @@ -223,5 +215,7 @@ func (f *AtpRequestFrame) Encode() CanBusData { bits.AddByte(byte(crc16 >> 8)) bits.AddByte(byte(crc16)) // - return bits.(CanBusData) + cf.CanData = bits.(CanBusData).GetData() + // + return cf } diff --git a/third_party/message/can_btm_data.go b/third_party/message/can_btm_data.go index 5718566..f9dcd85 100644 --- a/third_party/message/can_btm_data.go +++ b/third_party/message/can_btm_data.go @@ -16,20 +16,26 @@ func NewBtmDataMessageFrame(sn byte, offset byte) *BtmDataMessageFrame { FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+offset, sn), } } -func (f *BtmDataMessageFrame) Encode() CanBusData { - writer := NewCanBitsWriter(12) +func (f *BtmDataMessageFrame) Encode() *CanetFrame { + 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 { writer.AddByte(data) } - return writer.(CanBusData) + cf.CanData = writer.(CanBusData).GetData() + // + return cf } -func (f *BtmDataMessageFrame) Decode(reader CanBitsReader) bool { - 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) 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), } } -func (f *BtmDataMessageTimeAFrame) Encode() CanBusData { - writer := NewCanBitsWriter(12) +func (f *BtmDataMessageTimeAFrame) Encode() *CanetFrame { + 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) // @@ -78,13 +88,15 @@ func (f *BtmDataMessageTimeAFrame) Encode() CanBusData { writer.AddByte(byte((f.Crc32A >> 8) & byteMsk)) writer.AddByte(byte(f.Crc32A & byteMsk)) // - return writer.(CanBusData) + cf.CanData = writer.(CanBusData).GetData() + // + return cf } -func (f *BtmDataMessageTimeAFrame) Decode(reader CanBitsReader) bool { - if !f.FId.Decode(reader) { - return false - } +func (f *BtmDataMessageTimeAFrame) Decode(cf *CanetFrame) bool { + f.FId = cf.CanId + // + reader := NewCanBitsReader(cf.CanData, 8) // f.TimeA = 0 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), } } -func (f *BtmDataMessageTimeBFrame) Encode() CanBusData { - writer := NewCanBitsWriter(12) +func (f *BtmDataMessageTimeBFrame) Encode() *CanetFrame { + 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) // @@ -174,12 +190,14 @@ func (f *BtmDataMessageTimeBFrame) Encode() CanBusData { writer.AddByte(byte((f.Crc32B >> 8) & byteMsk)) writer.AddByte(byte(f.Crc32B & byteMsk)) // - return writer.(CanBusData) + cf.CanData = writer.(CanBusData).GetData() + // + return cf } -func (f *BtmDataMessageTimeBFrame) Decode(reader CanBitsReader) bool { - 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 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), } } -func (f *BtmDataMessageEndFrame) Encode() CanBusData { - writer := NewCanBitsWriter(12) +func (f *BtmDataMessageEndFrame) Encode() *CanetFrame { + 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) // @@ -270,12 +292,14 @@ func (f *BtmDataMessageEndFrame) Encode() CanBusData { writer.AddByte(byte((f.Crc32C >> 8) & byteMsk)) writer.AddByte(byte(f.Crc32C & byteMsk)) // - return writer.(CanBusData) + cf.CanData = writer.(CanBusData).GetData() + // + return cf } -func (f *BtmDataMessageEndFrame) Decode(reader CanBitsReader) bool { - 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 a1, a1Ok := reader.ReadByte() diff --git a/third_party/message/can_btm_rsp.go b/third_party/message/can_btm_rsp.go index dadc599..2ab9c44 100644 --- a/third_party/message/can_btm_rsp.go +++ b/third_party/message/can_btm_rsp.go @@ -61,60 +61,38 @@ func CreateBtmRspFramesData(statusRsp *BtmStatusRspFrame, msg []byte, msgPackErr end := NewBtmDataMessageEndFrame(sn) end.TkB = tkTimeB // - crc32CData := make([]byte, 0, 132) //17*8-4 - rt := make([]byte, 0, 204) //17*12 - // 状态应答帧 - statusData := statusRsp.Encode() - crc32CData = append(crc32CData, canFrameContent(statusData)...) - rt = append(rt, statusData.GetData()...) - // 数据帧 + statusCf := statusRsp.Encode() + dmsCfs := make([]*CanetFrame, 0, 13) for _, dm := range dms { - dmData := 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 + dmsCfs = append(dmsCfs, dm.Encode()) } + 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 } - -// 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 -} diff --git a/third_party/message/can_btm_status_rsp.go b/third_party/message/can_btm_status_rsp.go index ffef805..39f2564 100644 --- a/third_party/message/can_btm_status_rsp.go +++ b/third_party/message/can_btm_status_rsp.go @@ -29,10 +29,10 @@ func NewBtmStatusRspFrame(sn byte) *BtmStatusRspFrame { FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, CAN_FRAME_STATUS_RSP, sn), } } -func (f *BtmStatusRspFrame) Decode(reader CanBitsReader) bool { - if !f.FId.Decode(reader) { - return false - } +func (f *BtmStatusRspFrame) Decode(cf *CanetFrame) bool { + f.FId = cf.CanId + // + reader := NewCanBitsReader(cf.CanData, 8) //数据流水号 if d, ok := reader.ReadByte(); ok { f.Dsn = d @@ -106,10 +106,14 @@ func (f *BtmStatusRspFrame) Decode(reader CanBitsReader) bool { // return true } -func (f *BtmStatusRspFrame) Encode() CanBusData { - writer := NewCanBitsWriter(12) +func (f *BtmStatusRspFrame) Encode() *CanetFrame { + 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.BaliseCounter) writer.AddByte(f.MessageCounter) @@ -150,5 +154,6 @@ func (f *BtmStatusRspFrame) Encode() CanBusData { writer.AddByte(tk3) writer.AddByte(tk4) // - return writer.(CanBusData) + cf.CanData = writer.(CanBusData).GetData() + return cf } diff --git a/third_party/message/can_btm_time_sync_rsp.go b/third_party/message/can_btm_time_sync_rsp.go index 77afddd..0e9b940 100644 --- a/third_party/message/can_btm_time_sync_rsp.go +++ b/third_party/message/can_btm_time_sync_rsp.go @@ -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), } } -func (f *BtmTimeSyncCheckFrame) Decode(reader CanBitsReader) bool { +func (f *BtmTimeSyncCheckFrame) Decode(cf *CanetFrame) bool { + f.FId = cf.CanId // - if !f.FId.Decode(reader) { - return false - } + reader := NewCanBitsReader(cf.CanData, 8) //T2 t21, t21Ok := reader.ReadByte() if !t21Ok { @@ -69,9 +68,14 @@ func (f *BtmTimeSyncCheckFrame) Decode(reader CanBitsReader) bool { // return true } -func (f *BtmTimeSyncCheckFrame) Encode() CanBusData { - writer := NewCanBitsWriter(12) - f.FId.Encode(writer) +func (f *BtmTimeSyncCheckFrame) Encode() *CanetFrame { + cf := &CanetFrame{} + cf.CanId = f.FId + cf.CanLen = 8 + cf.FF = true + cf.RTR = false + // + writer := NewCanBitsWriter(8) // timeByteMsk := uint32(0x00_00_00_ff) //t2 @@ -93,5 +97,6 @@ func (f *BtmTimeSyncCheckFrame) Encode() CanBusData { writer.AddByte(t33) writer.AddByte(t34) // - return writer.(CanBusData) + cf.CanData = writer.(CanBusData).GetData() + return cf } diff --git a/third_party/message/can_bus.go b/third_party/message/can_bus.go index a59d659..8c5ea4c 100644 --- a/third_party/message/can_bus.go +++ b/third_party/message/can_bus.go @@ -4,8 +4,6 @@ package message // CanBits 可以在CAN总线上传输的bit流 // 按bit位来存储数据 -// 一个字节中bit位编号,从高位到低位依次为bit7-bit0 -// 对于一个CAN帧:29bits帧ID+64bits帧数据,以bit为单位,最后一字节即第12个字节的低位3bits为无用数据 type CanBits struct { Data []byte //bits LastBitsLen int //Data中最后一个字节中从高位到低位存储数据的有效位数,值范围[1,8],8-LastBitsLen则为最后一个字节中低位剩余的空位数量 @@ -203,31 +201,40 @@ const ( const ( CAN_CRC16_ATPREQ = 0x11021 + CAN_CRC32 = 0x04C11DB7 ) var ( crc16AtpReqTable []uint32 = nil + crc32CanTable []uint32 = nil ) -func CanCreateCrcTable() { +func CreateCanCrcTable() { if crc16AtpReqTable == nil { crc16AtpReqTable = CreateCrcTable(CAN_CRC16_ATPREQ, 16, false) } + if crc32CanTable == nil { + crc32CanTable = CreateCrcTable(CAN_CRC32, 32, false) + } } func calculateAtpReqCrc16(data []byte) uint16 { crc := CrcTableBased(data, 16, 0, false, false, 0, crc16AtpReqTable) return uint16(crc) } +func calculateCanCrc32(data []byte) uint32 { + crc := CrcTableBased(data, 32, 0xFF_FF_FF_FF, false, false, 0, crc32CanTable) + return crc +} // CRC32A的校验范围是:报文+时间戳A func calculateDataRspCrc32A(data []byte) uint32 { - return 0 + return calculateCanCrc32(data) } // CRC32B的校验范围是:报文+时间戳B func calculateDataRspCrc32B(data []byte) uint32 { - return 0 + return calculateCanCrc32(data) } func calculateDataRspCrc32C(data []byte) uint32 { - return 0 + return calculateCanCrc32(data) } diff --git a/third_party/message/can_net.go b/third_party/message/can_net.go new file mode 100644 index 0000000..746ffc8 --- /dev/null +++ b/third_party/message/can_net.go @@ -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 +) diff --git a/third_party/tcp/tcp_client.go b/third_party/tcp/tcp_client.go deleted file mode 100644 index e81963f..0000000 --- a/third_party/tcp/tcp_client.go +++ /dev/null @@ -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 -} diff --git a/third_party/tcp/tcp_server.go b/third_party/tcp/tcp_server.go deleted file mode 100644 index 4ae52b7..0000000 --- a/third_party/tcp/tcp_server.go +++ /dev/null @@ -1 +0,0 @@ -package tcp diff --git a/ts/simulation/wayside/memory/wayside_simulation.go b/ts/simulation/wayside/memory/wayside_simulation.go index 8950151..92eac3a 100644 --- a/ts/simulation/wayside/memory/wayside_simulation.go +++ b/ts/simulation/wayside/memory/wayside_simulation.go @@ -1031,10 +1031,11 @@ func fillProtoRepository(repo *proto.Repository, storage *graphicData.RtssGraphi turnoutPort = convertDevicePort(data.TransponderRef) } responder := &proto.Transponder{ - Id: data.Common.Id, - Km: convertKm(data.KilometerSystem), - SectionId: sectionId, - TurnoutPort: turnoutPort, + Id: data.Common.Id, + Km: convertKm(data.KilometerSystem), + SectionId: sectionId, + TurnoutPort: turnoutPort, + FixedTelegram: data.FixedTelegram, } repo.Transponders = append(repo.Transponders, converTransponderUid(responder, uidsMap)) for _, stationName := range data.CentralizedStations {