[修改]11号线BTM与VOBC通信服务逻辑

This commit is contained in:
thesai 2024-11-19 10:48:13 +08:00
parent 5735f54b30
commit 3203edf906
5 changed files with 114 additions and 66 deletions

@ -1 +1 @@
Subproject commit b7bc9bdb1f72aded0cd0d1f5c2d6970e6d1cef76 Subproject commit 88b24dff6589615d68c83f19196904bc7bb64077

View File

@ -180,8 +180,17 @@ func (t *telegramFrame) encode() []byte {
return data return data
} }
func (t *telegramFrame) getSn() byte {
if t == nil {
return 0
} else {
return t.sn
}
}
type freeFrame struct { type freeFrame struct {
id byte //递增的id码 id byte //递增的id码
//reservedBytes []byte //保留2个1字节
sn byte //报文序列号。1-255开机时为0 sn byte //报文序列号。1-255开机时为0
btmWorkState btmWorkState //BTM工作状态 btmWorkState btmWorkState //BTM工作状态
workTemperature byte //工作温度。单位℃ workTemperature byte //工作温度。单位℃
@ -221,6 +230,7 @@ func (f *freeFrame) encode() []byte {
data = append(data, frameType_Free) data = append(data, frameType_Free)
data = append(data, 0) //帧长度,占位 data = append(data, 0) //帧长度,占位
data = append(data, f.id) data = append(data, f.id)
data = append(data, 0, 0)
data = append(data, f.sn) data = append(data, f.sn)
data = append(data, byte(f.btmWorkState)) data = append(data, byte(f.btmWorkState))
data = append(data, f.workTemperature) data = append(data, f.workTemperature)

View File

@ -31,6 +31,8 @@ type serviceContext struct {
id byte //无论何时传输数据,该数都在 1-255 范围内递增在错误重传时也是递增的255 之后是 1不使用 0 id byte //无论何时传输数据,该数都在 1-255 范围内递增在错误重传时也是递增的255 之后是 1不使用 0
sn byte //报文序列号。1-255开机时使用0 sn byte //报文序列号。1-255开机时使用0
lastTelFrame *telegramFrame //最后发送的报文帧
sendSuccess bool //如果报文帧后第一个请求帧的报文序列号与BTM刚发送的报文帧中的报文序列号不一样BTM就认为发送是不成功的BTM会将同样的数据再发一次
lastCmdId byte //vobc ID命令帧最新的ID码1~255不使用0 lastCmdId byte //vobc ID命令帧最新的ID码1~255不使用0
lastReqId byte //vobc 请求帧最新的ID码1~255不使用0 lastReqId byte //vobc 请求帧最新的ID码1~255不使用0
@ -41,11 +43,18 @@ type serviceContext struct {
} }
func Start(sim *memory.VerifySimulation) { func Start(sim *memory.VerifySimulation) {
mu.Lock()
defer mu.Unlock()
if serviceCtx != nil {
logger().Warn("重复启动服务")
return
}
config := sim.GetRunConfig().BtmVobc config := sim.GetRunConfig().BtmVobc
client := udp.NewClient(fmt.Sprintf("%s:%d", config.RemoteIp, config.RemoteUdpPort)) client := udp.NewClient(fmt.Sprintf("%s:%d", config.RemoteIp, config.RemoteUdpPort))
serviceCtx := serviceContext{ serviceCtx = &serviceContext{
simulation: sim, simulation: sim,
client: client, client: client,
sendSuccess: true,
} }
server := udp.NewServer(fmt.Sprintf(":%d", config.LocalUdpPort), serviceCtx.handle) server := udp.NewServer(fmt.Sprintf(":%d", config.LocalUdpPort), serviceCtx.handle)
err := server.Listen() err := server.Listen()
@ -98,15 +107,83 @@ func (s *serviceContext) handle(data []byte) {
} }
func (s *serviceContext) handleIdFrame(frame *idFrame) { 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)) logger().Error(fmt.Sprintf("vobc ID命令帧id倒退[%d%d]", s.lastCmdId, frame.id))
} }
s.lastCmdId = frame.id s.lastCmdId = frame.id
s.btmId = frame.btmId s.btmId = frame.btmId
s.vobcId = frame.vobcId s.vobcId = frame.vobcId
rspFrame := freeFrame{ }
func (s *serviceContext) handleReqFrame(frame *reqFrame) {
if frame.frameState == fs_Error {
logger().Info("上一帧的报文序列或者CRC检查不正确")
}
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 {
for _, bs := range trainState.BtmBaliseCacheA.BaliseList {
if !bs.IsSend {
bs.IsSend = true
tel, err := hex.DecodeString(bs.Telegram)
if err != nil {
logger().Error(fmt.Sprintf("用户报文解码出错:%s", err))
break
}
telegram = tel
break
}
}
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(), id: s.nextId(),
sn: s.nextSn(), sn: s.lastTelFrame.getSn(),
btmWorkState: bws_normal, btmWorkState: bws_normal,
workTemperature: 20, workTemperature: 20,
amp1CurrentState: iv_normal, amp1CurrentState: iv_normal,
@ -132,61 +209,14 @@ func (s *serviceContext) handleIdFrame(frame *idFrame) {
responseDuration: 0, responseDuration: 0,
vobcCycle: frame.vobcCycle, vobcCycle: frame.vobcCycle,
} }
encode := rspFrame.encode() encode := freeFrame.encode()
err := s.client.Send(encode) err := s.client.Send(encode)
if err != nil { if err != nil {
logger().Error("发送数据失败") logger().Error("发送数据失败")
} else { } else {
logger().Info(fmt.Sprintf("回复ID命令帧:%x", encode)) logger().Info(fmt.Sprintf("发送空闲帧:%x", encode))
} }
} }
func (s *serviceContext) handleReqFrame(frame *reqFrame) {
if frame.frameState == fs_Error {
logger().Info("上一帧的报文序列或者CRC检查不正确")
}
if frame.id <= s.lastReqId {
logger().Info(fmt.Sprintf("vobc请求帧id倒退【%d%d】", s.lastReqId, frame.id))
return
}
s.lastReqId = frame.id
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)
if err != nil {
logger().Error(fmt.Sprintf("用户报文解码出错:%s", err))
continue
}
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("回复vobc请求帧%x", encode))
}
return false
}
return true
})
} }
func (s *serviceContext) nextId() byte { func (s *serviceContext) nextId() byte {
@ -198,6 +228,9 @@ func (s *serviceContext) nextId() byte {
} }
func (s *serviceContext) nextSn() byte { func (s *serviceContext) nextSn() byte {
if s.sn == 0 {
return 0
}
tmp := s.sn tmp := s.sn
s.sn++ s.sn++
if s.sn == 0 { if s.sn == 0 {

View File

@ -1158,6 +1158,9 @@ func fillProtoRepository(repo *proto.Repository, storage *data_proto.RtssGraphic
} }
//列车停车点 //列车停车点
for _, sp := range storage.StopPositions { for _, sp := range storage.StopPositions {
if sp.KilometerSystem.CoordinateSystem == "" { //11号线北辛安-新首钢站间两个停车点没有公里标
continue
}
//id := GetMapElementId(sp.Common) //id := GetMapElementId(sp.Common)
psp := &proto.StopPosition{ psp := &proto.StopPosition{
Id: uidsMap.StopPoint[GetMapElementId(sp.Common)].Uid, Id: uidsMap.StopPoint[GetMapElementId(sp.Common)].Uid,

View File

@ -211,6 +211,8 @@ func stopThirdParty(s *memory.VerifySimulation) {
//obsolete.StopLineAllRsspAxleServices() //obsolete.StopLineAllRsspAxleServices()
// 电机UDP停止 // 电机UDP停止
electrical_machinery.Default().Stop() electrical_machinery.Default().Stop()
//11号线VOBC通信
btmBeijing11.Stop(s)
//11号线工装通信 //11号线工装通信
trainBeijing11.Stop(s) trainBeijing11.Stop(s)