[修改]11号线BTM与VOBC通信服务逻辑
This commit is contained in:
parent
5735f54b30
commit
3203edf906
@ -1 +1 @@
|
|||||||
Subproject commit b7bc9bdb1f72aded0cd0d1f5c2d6970e6d1cef76
|
Subproject commit 88b24dff6589615d68c83f19196904bc7bb64077
|
10
third_party/btm_vobc/beijing11/msg.go
vendored
10
third_party/btm_vobc/beijing11/msg.go
vendored
@ -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)
|
||||||
|
139
third_party/btm_vobc/beijing11/service.go
vendored
139
third_party/btm_vobc/beijing11/service.go
vendored
@ -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 {
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user