[修改]11号线BTM与VOBC通信服务逻辑
This commit is contained in:
parent
5735f54b30
commit
3203edf906
|
@ -1 +1 @@
|
|||
Subproject commit b7bc9bdb1f72aded0cd0d1f5c2d6970e6d1cef76
|
||||
Subproject commit 88b24dff6589615d68c83f19196904bc7bb64077
|
|
@ -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码
|
||||
//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)
|
||||
|
|
|
@ -31,6 +31,8 @@ type serviceContext struct {
|
|||
|
||||
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{
|
||||
serviceCtx = &serviceContext{
|
||||
simulation: sim,
|
||||
client: client,
|
||||
sendSuccess: true,
|
||||
}
|
||||
server := udp.NewServer(fmt.Sprintf(":%d", config.LocalUdpPort), serviceCtx.handle)
|
||||
err := server.Listen()
|
||||
|
@ -98,15 +107,83 @@ 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{
|
||||
}
|
||||
|
||||
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(),
|
||||
sn: s.nextSn(),
|
||||
sn: s.lastTelFrame.getSn(),
|
||||
btmWorkState: bws_normal,
|
||||
workTemperature: 20,
|
||||
amp1CurrentState: iv_normal,
|
||||
|
@ -132,61 +209,14 @@ func (s *serviceContext) handleIdFrame(frame *idFrame) {
|
|||
responseDuration: 0,
|
||||
vobcCycle: frame.vobcCycle,
|
||||
}
|
||||
encode := rspFrame.encode()
|
||||
encode := freeFrame.encode()
|
||||
err := s.client.Send(encode)
|
||||
if err != nil {
|
||||
logger().Error("发送数据失败")
|
||||
} 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 {
|
||||
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Loading…
Reference in New Issue