[修改]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
}
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)

View File

@ -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 {

View File

@ -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,

View File

@ -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)