diff --git a/message_server/sfp_ms.go b/message_server/sfp_ms.go index 4b1a1e5..1a581f0 100644 --- a/message_server/sfp_ms.go +++ b/message_server/sfp_ms.go @@ -293,6 +293,14 @@ func handlerSectionState(w ecs.World, uid string) *state_proto.SectionState { } } return sectionState + } else if entry.HasComponent(component.TrackCircuitType) { //轨道电路 + sectionState := &state_proto.SectionState{ + Occupied: component.BitStateType.Get(component.TrackCircuitType.Get(entry).GJ).Val, + AxleFault: false, + AxleDrst: false, + AxlePdrst: false, + } + return sectionState } return nil } diff --git a/rts-sim-module b/rts-sim-module index 8ccd46a..90003ec 160000 --- a/rts-sim-module +++ b/rts-sim-module @@ -1 +1 @@ -Subproject commit 8ccd46aa6c97a933fd12c7b308da929115c9aa8e +Subproject commit 90003ec9429c7db26c43dd381277800d0dfd35fa diff --git a/third_party/interlock/beijing11/beijing11_const.go b/third_party/interlock/beijing11/beijing11_const.go new file mode 100644 index 0000000..32b2e06 --- /dev/null +++ b/third_party/interlock/beijing11/beijing11_const.go @@ -0,0 +1,23 @@ +package beijing11 + +var ( + FrameHead byte = 0x0E //帧头 + FrameTail byte = 0x0E //帧尾 + ControlWord = controlWord{ + HeartBeat: 0x00, + ReadRegister: 0x01, + WriteRegister: 0x02, + Response: 0x03, + Upstream: 0x06, + DownStream: 0x07, + } +) + +type controlWord struct { + HeartBeat byte //心跳 + ReadRegister byte //读寄存器 + WriteRegister byte //写寄存器 + Response byte //回复 + Upstream byte //上行流数据 + DownStream byte //下行流数据 +} diff --git a/third_party/interlock/beijing11/interlock.go b/third_party/interlock/beijing11/interlock.go new file mode 100644 index 0000000..d699cb5 --- /dev/null +++ b/third_party/interlock/beijing11/interlock.go @@ -0,0 +1,126 @@ +// Package beijing11 北京11号线联锁通信 +package beijing11 + +import ( + "fmt" + "joylink.club/bj-rtsts-server/config" + "joylink.club/bj-rtsts-server/third_party/udp" + "log/slog" + "sync" +) + +var ( + initMutex = sync.Mutex{} + interlockMap = make(map[string]*InterlockProxy) + logTag = "[北京11号线联锁通信]" +) + +func GetInstant(c *config.InterlockConfig, msgManager MsgManager) *InterlockProxy { + initMutex.Lock() + defer initMutex.Unlock() + if interlockMap[c.Code] == nil { + interlockMap[c.Code] = &InterlockProxy{runConfig: c, msgManager: msgManager} + } + return interlockMap[c.Code] +} + +type MsgManager interface { + HandleReadRegisterMsg(req *ReadRegisterReq) (*ReadRegisterRes, error) + HandleWriteRegisterMsg(req *WriteRegisterReq) error + HandleDownstreamMsg(data []byte) error + CollectUpstreamMsg() []byte +} + +type msgManager struct { +} + +type InterlockProxy struct { + runConfig *config.InterlockConfig //联锁通信配置 + msgManager MsgManager //消息获取与处理接口0 + client udp.UdpClient //向上位机发送数据的UDP客户端 + server udp.UdpServer //接收上位机数据的UDP服务端 + running bool //此服务正在运行的标志 +} + +func (i *InterlockProxy) Start() { + if i.runConfig == nil || i.runConfig.Ip == "" || !i.runConfig.Open { + return + } + if i.running { + panic("启动联锁消息服务错误: 存在正在运行的任务") + } + //UDP通信设施 + i.server = udp.NewServer(fmt.Sprintf(":%d", i.runConfig.LocalPort), i.handleUpperData) + err := i.server.Listen() + if err != nil { + panic("启动联锁消息服务错误:无法启动UDP服务") + } + i.running = true + i.client = udp.NewClient(fmt.Sprintf("%v:%v", i.runConfig.Ip, i.runConfig.RemotePort)) +} + +// 处理来自上位机的数据 +func (i *InterlockProxy) handleUpperData(data []byte) { + baseData := &BaseStruct{} + err := baseData.Decode(data) + if err != nil { + slog.Error(logTag + "数据解析出错:" + err.Error()) + return + } + switch baseData.ControlWord { + case ControlWord.ReadRegister: + req := &ReadRegisterReq{} + err := req.Decode(baseData.Data) + if err != nil { + slog.Error(logTag + "读寄存器数据解析出错:" + err.Error()) + return + } + res, err := i.msgManager.HandleReadRegisterMsg(req) + if err != nil { + slog.Error(logTag + "读寄存器数据处理出错:" + err.Error()) + return + } + resData := &BaseStruct{ + ID: baseData.ID, + ControlWord: ControlWord.Response, + Data: res.Encode(), + } + i.SendToUpper(resData.Encode()) + case ControlWord.WriteRegister: + req := &WriteRegisterReq{} + err := req.Decode(baseData.Data) + if err != nil { + slog.Error(logTag + "写寄存器数据解析出错:" + err.Error()) + return + } + err = i.msgManager.HandleWriteRegisterMsg(req) + if err != nil { + slog.Error(logTag + "写寄存器数据处理出错:" + err.Error()) + return + } + case ControlWord.DownStream: + err = i.msgManager.HandleDownstreamMsg(baseData.Data) + if err != nil { + slog.Error(logTag + "下行数据处理出错:" + err.Error()) + return + } + } +} + +func (i *InterlockProxy) SendToUpper(data []byte) { + err := i.client.Send(data) + slog.Error(logTag + "向上位机发送数据失败:" + err.Error()) +} + +func (i *InterlockProxy) Stop() { + initMutex.Lock() + defer initMutex.Unlock() + delete(interlockMap, i.runConfig.Code) + if i.client != nil { + i.client.Close() + } + if i.server != nil { + i.server.Close() + } + i.running = false +} diff --git a/third_party/interlock/beijing11/msg.go b/third_party/interlock/beijing11/msg.go new file mode 100644 index 0000000..72f5d15 --- /dev/null +++ b/third_party/interlock/beijing11/msg.go @@ -0,0 +1,86 @@ +package beijing11 + +import ( + "encoding/binary" + "fmt" + "hash/crc32" + "joylink.club/bj-rtsts-server/sys_error" +) + +type BaseStruct struct { + ID byte + ControlWord byte + Data []byte +} + +func (m *BaseStruct) Decode(buf []byte) error { + if buf[0] != FrameHead { + return sys_error.New(logTag + "帧头不正确:" + fmt.Sprintf("%02X", buf[0])) + } + if buf[len(buf)-1] != FrameTail { + return sys_error.New(logTag + "帧尾不正确:" + fmt.Sprintf("%02X", buf[len(buf)-1])) + } + crc := crc32.ChecksumIEEE(buf[1 : len(buf)-5]) + if crc != binary.BigEndian.Uint32(buf[len(buf)-5:len(buf)-1]) { + return sys_error.New(logTag + "CRC校验失败") + } + m.ID = buf[1] + m.ControlWord = buf[2] + m.Data = buf[5 : len(buf)-5] + return nil +} + +func (m *BaseStruct) Encode() []byte { + var data []byte + data = append(data, FrameHead) + data = append(data, m.ID) + data = append(data, m.ControlWord) + data = binary.BigEndian.AppendUint16(data, uint16(len(m.Data))) + data = append(data, m.Data...) + crc := crc32.ChecksumIEEE(data[1:]) + data = binary.BigEndian.AppendUint32(data, crc) + data = append(data, FrameTail) + return data +} + +type ReadRegisterReq struct { + RegisterAddr []uint16 //寄存器地址 +} + +func (r *ReadRegisterReq) Decode(buf []byte) error { + if len(buf)%2 != 0 { + return sys_error.New(logTag + "读寄存器数据字节长度不是2的倍数") + } + for i := 0; i < len(buf); i += 2 { + r.RegisterAddr = append(r.RegisterAddr, binary.BigEndian.Uint16(buf[i:i+2])) + } + return nil +} + +type ReadRegisterRes struct { + RegisterData [][]byte //寄存器数据 +} + +func (r *ReadRegisterRes) Encode() []byte { + var data []byte + for _, datum := range r.RegisterData { + data = append(data, datum...) + } + return data +} + +type WriteRegisterReq struct { + RegisterAddr []uint16 //寄存器地址 + RegisterData [][]byte //寄存器数据 +} + +func (w *WriteRegisterReq) Decode(buf []byte) error { + if len(buf)%6 != 0 { + return sys_error.New(logTag + "写寄存器数据字节长度不是6的倍数") + } + for i := 0; i < len(buf); i += 6 { + w.RegisterAddr = append(w.RegisterAddr, binary.BigEndian.Uint16(buf[i:i+2])) + w.RegisterData = append(w.RegisterData, buf[i+2:i+6]) + } + return nil +} diff --git a/third_party/interlock/interlock.go b/third_party/interlock/beijing12/interlock.go similarity index 98% rename from third_party/interlock/interlock.go rename to third_party/interlock/beijing12/interlock.go index 857fda7..e190cb8 100644 --- a/third_party/interlock/interlock.go +++ b/third_party/interlock/beijing12/interlock.go @@ -1,4 +1,5 @@ -package interlock +// Package beijing12 北京12号线联锁通信 +package beijing12 import ( "context" diff --git a/ts/test_simulation_manage.go b/ts/test_simulation_manage.go index 9815469..2d6cd34 100644 --- a/ts/test_simulation_manage.go +++ b/ts/test_simulation_manage.go @@ -3,6 +3,7 @@ package ts import ( "fmt" "joylink.club/bj-rtsts-server/third_party/acc" + "joylink.club/bj-rtsts-server/third_party/interlock/beijing12" "joylink.club/bj-rtsts-server/third_party/radar" "joylink.club/bj-rtsts-server/third_party/train_pc_sim" "log/slog" @@ -20,7 +21,6 @@ import ( "joylink.club/bj-rtsts-server/mqtt" "joylink.club/bj-rtsts-server/sys_error" "joylink.club/bj-rtsts-server/third_party/dynamics" - "joylink.club/bj-rtsts-server/third_party/interlock" "joylink.club/bj-rtsts-server/third_party/semi_physical_train" "joylink.club/bj-rtsts-server/ts/simulation/wayside/memory" @@ -120,7 +120,7 @@ func runThirdParty(s *memory.VerifySimulation) error { semi_physical_train.Default().Start(s) // 联锁启动 for _, c := range s.GetInterlockCodes() { - interlock.Default(c).Start(s) + beijing12.Default(c).Start(s) } // 计轴RSSP启动 axle_device.StartLineAllRsspAxleServices(s) @@ -149,7 +149,7 @@ func stopThirdParty(s *memory.VerifySimulation) { semi_physical_train.Default().Stop() // 联锁启动 for _, c := range s.GetInterlockCodes() { - interlock.Default(c).Stop() + beijing12.Default(c).Stop() } //计轴RSSP启动销毁 axle_device.StopLineAllRsspAxleServices()