diff --git a/rts-sim-module b/rts-sim-module index b7bc9bd..88b24df 160000 --- a/rts-sim-module +++ b/rts-sim-module @@ -1 +1 @@ -Subproject commit b7bc9bdb1f72aded0cd0d1f5c2d6970e6d1cef76 +Subproject commit 88b24dff6589615d68c83f19196904bc7bb64077 diff --git a/third_party/btm_vobc/beijing11/msg.go b/third_party/btm_vobc/beijing11/msg.go index 1629664..08a9e34 100644 --- a/third_party/btm_vobc/beijing11/msg.go +++ b/third_party/btm_vobc/beijing11/msg.go @@ -180,8 +180,17 @@ func (t *telegramFrame) encode() []byte { return data } +func (t *telegramFrame) getSn() byte { + if t == nil { + return 0 + } else { + return t.sn + } +} + type freeFrame struct { - id byte //递增的id码 + id byte //递增的id码 + //reservedBytes []byte //保留(2个1字节) sn byte //报文序列号。1-255,开机时为0 btmWorkState btmWorkState //BTM工作状态 workTemperature byte //工作温度。单位℃ @@ -221,6 +230,7 @@ func (f *freeFrame) encode() []byte { data = append(data, frameType_Free) data = append(data, 0) //帧长度,占位 data = append(data, f.id) + data = append(data, 0, 0) data = append(data, f.sn) data = append(data, byte(f.btmWorkState)) data = append(data, f.workTemperature) diff --git a/third_party/btm_vobc/beijing11/service.go b/third_party/btm_vobc/beijing11/service.go index ad639c3..4a2db55 100644 --- a/third_party/btm_vobc/beijing11/service.go +++ b/third_party/btm_vobc/beijing11/service.go @@ -29,8 +29,10 @@ type serviceContext struct { client udp.UdpClient server udp.UdpServer - id byte //无论何时传输数据,该数都在 1-255 范围内递增,在错误重传时也是递增的,255 之后是 1,不使用 0 - sn byte //报文序列号。1-255;开机时使用0 + id byte //无论何时传输数据,该数都在 1-255 范围内递增,在错误重传时也是递增的,255 之后是 1,不使用 0 + sn byte //报文序列号。1-255;开机时使用0 + lastTelFrame *telegramFrame //最后发送的报文帧 + sendSuccess bool //如果报文帧后第一个请求帧的报文序列号与BTM刚发送的报文帧中的报文序列号不一样,BTM就认为发送是不成功的,BTM会将同样的数据再发一次; lastCmdId byte //vobc ID命令帧最新的ID码(1~255,不使用0) lastReqId byte //vobc 请求帧最新的ID码(1~255,不使用0) @@ -41,11 +43,18 @@ type serviceContext struct { } func Start(sim *memory.VerifySimulation) { + mu.Lock() + defer mu.Unlock() + if serviceCtx != nil { + logger().Warn("重复启动服务") + return + } config := sim.GetRunConfig().BtmVobc client := udp.NewClient(fmt.Sprintf("%s:%d", config.RemoteIp, config.RemoteUdpPort)) - serviceCtx := serviceContext{ - simulation: sim, - client: client, + serviceCtx = &serviceContext{ + simulation: sim, + client: client, + sendSuccess: true, } server := udp.NewServer(fmt.Sprintf(":%d", config.LocalUdpPort), serviceCtx.handle) err := server.Listen() @@ -98,95 +107,116 @@ func (s *serviceContext) handle(data []byte) { } func (s *serviceContext) handleIdFrame(frame *idFrame) { - if frame.id < s.lastCmdId { + if frame.id < s.lastCmdId && s.lastCmdId-frame.id < 250 { //第二个条件保证id没有突破255 logger().Error(fmt.Sprintf("vobc ID命令帧id倒退[%d:%d]", s.lastCmdId, frame.id)) } s.lastCmdId = frame.id s.btmId = frame.btmId s.vobcId = frame.vobcId - rspFrame := freeFrame{ - id: s.nextId(), - sn: s.nextSn(), - btmWorkState: bws_normal, - workTemperature: 20, - amp1CurrentState: iv_normal, - amp1VoltageState: iv_normal, - amp2CurrentState: iv_normal, - amp2VoltageState: iv_normal, - antenna1Fault: false, - cable1State: cable_normal, - antenna2Fault: false, - cable2State: cable_normal, - selfCheckChannel1Fault: false, - selfCheckChannel2Fault: false, - fskChannel1Fault: false, - fskChannel2Fault: false, - receiverBoardState: rbs_normal, - channel1_24v: iv_normal, - channel2_24v: iv_normal, - channel1_23vFault: false, - channel2_23vFault: false, - powerBoardState: pbs_normal, - cpuBoardId: 0, - cpuWorkTemperatureState: wts_normal, - responseDuration: 0, - vobcCycle: frame.vobcCycle, - } - encode := rspFrame.encode() - err := s.client.Send(encode) - if err != nil { - logger().Error("发送数据失败") - } else { - logger().Info(fmt.Sprintf("回复ID命令帧:%x", encode)) - } } func (s *serviceContext) handleReqFrame(frame *reqFrame) { if frame.frameState == fs_Error { logger().Info("上一帧的报文序列或者CRC检查不正确") } - if frame.id <= s.lastReqId { + if frame.id <= s.lastReqId && s.lastReqId-frame.id < 250 { //第二个条件保证id没有突破255 logger().Info(fmt.Sprintf("vobc请求帧id倒退【%d:%d】", s.lastReqId, frame.id)) return } s.lastReqId = frame.id + if !s.sendSuccess { + if frame.sn != s.lastTelFrame.getSn() { //报文帧后第一条请求帧的报文序列号对应不上 + logger().Error(fmt.Sprintf("报文帧后第一条请求帧的报文序列号对应不上[%s:%s]", frame.sn, s.lastTelFrame.getSn())) + err := s.client.Send(s.lastTelFrame.encode()) + if err != nil { + logger().Error(fmt.Sprintf("发送上一次的报文帧出错:%s", err)) + } else { + logger().Error("BTM重发上一次的报文帧成功") + } + return + } + s.sendSuccess = true + } + var telegram []byte s.simulation.Memory.Status.TrainStateMap.Range(func(_, value any) bool { trainState := value.(*state_proto.TrainState) if trainState.ConnState.Conn && trainState.ConnState.ConnType == state_proto.TrainConnState_PC_SIM { - telFrame := telegramFrame{} - telFrame.id = s.nextId() - telFrame.headTTLTime = 1 - telFrame.sn = s.nextSn() - telFrame.btmWorkState = bws_normal - telFrame.channel1GoodBitRate = 100 - telFrame.channel2GoodBitRate = 100 - telFrame.decodeDuration = 1 - telFrame.tailTTLTime = 1 for _, bs := range trainState.BtmBaliseCacheA.BaliseList { if !bs.IsSend { - telegram, err := hex.DecodeString(bs.Telegram) + bs.IsSend = true + tel, err := hex.DecodeString(bs.Telegram) if err != nil { logger().Error(fmt.Sprintf("用户报文解码出错:%s", err)) - continue + break } - telFrame.telegram = telegram + telegram = tel + break } } - telFrame.responseDuration = 10 - telFrame.vobcReqCycle = frame.vobcCycle - - encode := telFrame.encode() - err := s.client.Send(encode) - if err != nil { - logger().Error("发送数据失败") - } else { - logger().Info(fmt.Sprintf("回复vobc请求帧:%x", encode)) - } return false } return true }) + if len(telegram) != 0 { //有未发送报文,发送报文帧 + telFrame := telegramFrame{} + telFrame.id = s.nextId() + telFrame.headTTLTime = 1 + telFrame.sn = s.nextSn() + telFrame.btmWorkState = bws_normal + telFrame.channel1GoodBitRate = 100 + telFrame.channel2GoodBitRate = 100 + telFrame.decodeDuration = 1 + telFrame.tailTTLTime = 1 + telFrame.telegram = telegram + telFrame.responseDuration = 10 + telFrame.vobcReqCycle = frame.vobcCycle + + encode := telFrame.encode() + err := s.client.Send(encode) + if err != nil { + logger().Error("发送数据失败") + } else { + logger().Info(fmt.Sprintf("发送报文帧:%x", encode)) + s.sendSuccess = false + } + } else { //否则发送空闲帧 + freeFrame := freeFrame{ + id: s.nextId(), + sn: s.lastTelFrame.getSn(), + btmWorkState: bws_normal, + workTemperature: 20, + amp1CurrentState: iv_normal, + amp1VoltageState: iv_normal, + amp2CurrentState: iv_normal, + amp2VoltageState: iv_normal, + antenna1Fault: false, + cable1State: cable_normal, + antenna2Fault: false, + cable2State: cable_normal, + selfCheckChannel1Fault: false, + selfCheckChannel2Fault: false, + fskChannel1Fault: false, + fskChannel2Fault: false, + receiverBoardState: rbs_normal, + channel1_24v: iv_normal, + channel2_24v: iv_normal, + channel1_23vFault: false, + channel2_23vFault: false, + powerBoardState: pbs_normal, + cpuBoardId: 0, + cpuWorkTemperatureState: wts_normal, + responseDuration: 0, + vobcCycle: frame.vobcCycle, + } + encode := freeFrame.encode() + err := s.client.Send(encode) + if err != nil { + logger().Error("发送数据失败") + } else { + logger().Info(fmt.Sprintf("发送空闲帧:%x", encode)) + } + } } func (s *serviceContext) nextId() byte { @@ -198,6 +228,9 @@ func (s *serviceContext) nextId() byte { } func (s *serviceContext) nextSn() byte { + if s.sn == 0 { + return 0 + } tmp := s.sn s.sn++ if s.sn == 0 { diff --git a/ts/simulation/wayside/memory/wayside_simulation.go b/ts/simulation/wayside/memory/wayside_simulation.go index dad8e43..ff35d8c 100644 --- a/ts/simulation/wayside/memory/wayside_simulation.go +++ b/ts/simulation/wayside/memory/wayside_simulation.go @@ -1158,6 +1158,9 @@ func fillProtoRepository(repo *proto.Repository, storage *data_proto.RtssGraphic } //列车停车点 for _, sp := range storage.StopPositions { + if sp.KilometerSystem.CoordinateSystem == "" { //11号线北辛安-新首钢站间两个停车点没有公里标 + continue + } //id := GetMapElementId(sp.Common) psp := &proto.StopPosition{ Id: uidsMap.StopPoint[GetMapElementId(sp.Common)].Uid, diff --git a/ts/test_simulation_manage.go b/ts/test_simulation_manage.go index fbbd24b..cc2b0e1 100644 --- a/ts/test_simulation_manage.go +++ b/ts/test_simulation_manage.go @@ -211,6 +211,8 @@ func stopThirdParty(s *memory.VerifySimulation) { //obsolete.StopLineAllRsspAxleServices() // 电机UDP停止 electrical_machinery.Default().Stop() + //11号线VOBC通信 + btmBeijing11.Stop(s) //11号线工装通信 trainBeijing11.Stop(s)