[修改]11号线联锁通信逻辑忽略配置中的集中站,全线通信;创建仿真时,通过设置继电器状态,初始化道岔位置到定位

This commit is contained in:
thesai 2024-09-18 11:40:20 +08:00
parent c6cfc42774
commit 3a22950790
4 changed files with 276 additions and 209 deletions

View File

@ -9,7 +9,7 @@ import (
) )
func TestFromInterlockFrame_Decode(t *testing.T) { func TestFromInterlockFrame_Decode(t *testing.T) {
str := "58bea4c65e0e583f5bdedc310800450000bd030c0000801100003d0b0a0d3d0b7814413c40d800a9fcf182009a3c016301000600010000020000030000060000070000080000020001000005aa00020001aaaa0005aaaa00000008000401000501000601000701001801001901001a01001b010010000400000500000600000700000800000900000a00001d00001e00001f000020000021000022000023000024000025000000000000040001aaaa0002aaaa0003aaaa0004aaaa0000000000000000000000004c428d88" str := "58bea4c65e0e583f5bdedc310800450000c94eae0000801100003d0b0a0d3d0b7814413c40d800b5fcfd8200a63c0363010003000400000500000900000200040000080000020004aaaa0008aaaa0000000f000d06000e01000f060010060021060023060011060012060026060027010013060014010022060024060025060010001300001400001500001600001700001800001900001a00002c00002d00002e00002f00003000003100003200003300000000000004000daaaa000eaaaa000faaaa0010aaaa00000000000000000000000058f24545"
data, err := hex.DecodeString(str) data, err := hex.DecodeString(str)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -112,7 +112,7 @@ func TestFromInterlockFrame_Decode(t *testing.T) {
} }
func TestToInterlockFrame_Decode(t *testing.T) { func TestToInterlockFrame_Decode(t *testing.T) {
str := "583f5bdedc3158bea4c65e0e0800450000f6dfe9400040115dd63d0b78143d0b0a0dd341413c00e2e8c88300d363013c0100060001010002010003010006010007010008010002000102eeaaaaaa000502eeaaaaaa00020001aa000005aa0000000011000101000201000301000401000501000601000701001501001601001701001801001901001a01001b01002901002a01002c010015000100000200000300000400000500000600000700000800000900000a00001b00001c00001d00001e00001f000020000021000022000023000024000025000000000000040001aaff0002aaff0003aaff0004aaff00000100000000000000000000000000000000f38414ee" str := "583f5bdedc3158bea4c65e0e080045000172b52c4000401188173d0b78143d0b0a0d40d8413c015ebe7f83014f63013c0200030004010005010009020006000202eeaaaaaa000302eeaaaaaa000402eeaaaaaa000602eeaaaaaa000702eeaaaaaa000802eeaaaaaa00060002aaaa0003aaaa0004aaaa0006aaaa0007aaaa0008aaaa0000001b000800000900000a00000b00000c00000d06000e01000f06001006001106001206001306001401001c00001d00001e00001f00002000002106002206002306002406002506002606002701002800002b00001e000b00000c00000d00000e00000f00001000001100001200001300001400001500001600001700001800001900001a00002600002700002800002900002a00002b00002c00002d00002e00002f0000300000310000320000330000000000000c0005aaaa0006aaaa0007aaaa0008aaaa0009aaaa000aaaaa000baaaa000caaaa000daaaa000eaaaa000faaaa0010aaaa00000100000000000000000000000000000000328ef0af"
data, err := hex.DecodeString(str) data, err := hex.DecodeString(str)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)

View File

@ -2,8 +2,8 @@ package beijing11
// StationDeviceIndexTable 联锁站设备索引表 // StationDeviceIndexTable 联锁站设备索引表
type StationDeviceIndexTable struct { type StationDeviceIndexTable struct {
StationName string //地图数据中车站的Code属性 //StationName string //地图数据中车站的Code属性
InterlockCode uint16 //通信数据中的“联锁编号” //InterlockCode uint16 //通信数据中的“联锁编号”
TurnoutMap map[uint16]*Row //key-联锁编号 TurnoutMap map[uint16]*Row //key-联锁编号
PsdMap map[uint16]*Row //key-联锁编号 PsdMap map[uint16]*Row //key-联锁编号
EsbMap map[uint16]*Row //key-联锁编号 EsbMap map[uint16]*Row //key-联锁编号
@ -17,10 +17,10 @@ type StationDeviceIndexTable struct {
XcjMap map[uint16]*Row //key-联锁编号 XcjMap map[uint16]*Row //key-联锁编号
} }
func NewStationDeviceIndexTable(stationName string, interlockIndex uint16) *StationDeviceIndexTable { func NewStationDeviceIndexTable( /*stationName string, interlockIndex uint16*/ ) *StationDeviceIndexTable {
return &StationDeviceIndexTable{ return &StationDeviceIndexTable{
StationName: stationName, //StationName: stationName,
InterlockCode: 0x3C00 + interlockIndex, //InterlockCode: 0x3C00 + interlockIndex,
TurnoutMap: make(map[uint16]*Row), TurnoutMap: make(map[uint16]*Row),
PsdMap: make(map[uint16]*Row), PsdMap: make(map[uint16]*Row),
EsbMap: make(map[uint16]*Row), EsbMap: make(map[uint16]*Row),
@ -36,6 +36,7 @@ func NewStationDeviceIndexTable(stationName string, interlockIndex uint16) *Stat
} }
type Row struct { type Row struct {
interlockCode uint16 //所属联锁站编号
commonId uint32 //地图中设备的ID commonId uint32 //地图中设备的ID
uid string //模型仓库中的设备模型ID uid string //模型仓库中的设备模型ID
index uint16 //联锁通信中的设备ID index uint16 //联锁通信中的设备ID

View File

@ -33,12 +33,13 @@ var (
) )
type serviceContext struct { type serviceContext struct {
cancelFunc context.CancelFunc //用来结束各个协程的函数 cancelFunc context.CancelFunc //用来结束各个协程的函数
ioAddr *net.UDPAddr //向联锁发送数据的客户端 ioAddr *net.UDPAddr //向联锁发送数据的客户端
server udp.UdpServer //接收联锁数据的服务端同时也是向联锁发送数据的udp客户端 server udp.UdpServer //接收联锁数据的服务端同时也是向联锁发送数据的udp客户端
sim *memory.VerifySimulation //启动服务所使用的仿真 sim *memory.VerifySimulation //启动服务所使用的仿真
iConfig config.InterlockConfig //启动服务使用的联锁配置 iConfig config.InterlockConfig //启动服务使用的联锁配置
deviceTable *StationDeviceIndexTable //联锁站的设备ID表key-车站名 deviceTable *StationDeviceIndexTable //联锁站的设备ID表key-车站名
toInterlockFrames []*ToInterlockFrame //发给联锁的消息,因为需要按车站划分范围、排序,故将数据提前整理好,仅替换设备状态
} }
func Start(interlockConfig config.InterlockConfig, simulation *memory.VerifySimulation) { func Start(interlockConfig config.InterlockConfig, simulation *memory.VerifySimulation) {
@ -48,7 +49,7 @@ func Start(interlockConfig config.InterlockConfig, simulation *memory.VerifySimu
mu.Lock() mu.Lock()
defer mu.Unlock() defer mu.Unlock()
//制表 //制表
table := makeTable(simulation, interlockConfig.Code) table, toInterlockFrames := preprocessingData(simulation, interlockConfig.Code)
if table == nil { //当前仿真内没有11号线联锁通信所需数据 if table == nil { //当前仿真内没有11号线联锁通信所需数据
return return
} }
@ -64,11 +65,12 @@ func Start(interlockConfig config.InterlockConfig, simulation *memory.VerifySimu
ctx, cancelFunc := context.WithCancel(context.Background()) ctx, cancelFunc := context.WithCancel(context.Background())
serviceCtx = &serviceContext{ serviceCtx = &serviceContext{
cancelFunc: cancelFunc, cancelFunc: cancelFunc,
ioAddr: ioAddr, ioAddr: ioAddr,
sim: simulation, sim: simulation,
iConfig: interlockConfig, iConfig: interlockConfig,
deviceTable: table, deviceTable: table,
toInterlockFrames: toInterlockFrames,
} }
//UDP服务端 //UDP服务端
server := udp.NewServer(fmt.Sprintf(":%d", interlockConfig.LocalPort), serviceCtx.handleDriveMsg) server := udp.NewServer(fmt.Sprintf(":%d", interlockConfig.LocalPort), serviceCtx.handleDriveMsg)
@ -94,9 +96,9 @@ func (s *serviceContext) handleDriveMsg(data []byte) {
wd := entity.GetWorldData(s.sim.World) wd := entity.GetWorldData(s.sim.World)
for _, cmd := range frame.TurnoutData.CmdList { for _, cmd := range frame.TurnoutData.CmdList {
uid := s.deviceTable.TurnoutMap[cmd.Id].uid uid := s.deviceTable.TurnoutMap[cmd.Id].uid
if cmd.Cmd == 0x55 { if cmd.Cmd == 0x01 {
err = fi.DriveTurnoutDCOn(s.sim.World, uid) err = fi.DriveTurnoutDCOn(s.sim.World, uid)
} else if cmd.Cmd == 0xaa { } else if cmd.Cmd == 0x02 {
err = fi.DriveTurnoutFCOn(s.sim.World, uid) err = fi.DriveTurnoutFCOn(s.sim.World, uid)
} else { } else {
err = fi.DriveTurnoutDCOff(s.sim.World, uid) err = fi.DriveTurnoutDCOff(s.sim.World, uid)
@ -109,7 +111,6 @@ func (s *serviceContext) handleDriveMsg(data []byte) {
row := s.deviceTable.PsdMap[cmd.Id] row := s.deviceTable.PsdMap[cmd.Id]
entry := wd.EntityMap[row.uid] entry := wd.EntityMap[row.uid]
circuit := component.PsdCircuitType.Get(entry) circuit := component.PsdCircuitType.Get(entry)
logger().Info(fmt.Sprintf("屏蔽门命令:%x", cmd.Cmd))
switch cmd.Cmd { switch cmd.Cmd {
case 0xAA: //短编组开门 case 0xAA: //短编组开门
wd.SetQdBit(row.relateDeviceMap[S], true) wd.SetQdBit(row.relateDeviceMap[S], true)
@ -267,10 +268,22 @@ func (s *serviceContext) handleDriveMsg(data []byte) {
default: default:
logger().Error(fmt.Sprintf("信号机[%s]无法开放[%x]信号", uid, cmd.Cmd)) logger().Error(fmt.Sprintf("信号机[%s]无法开放[%x]信号", uid, cmd.Cmd))
} }
} else { } else {
logger().Error(fmt.Sprintf("信号机[%s]的型号未知", uid)) logger().Error(fmt.Sprintf("信号机[%s]的型号未知", uid))
} }
} }
{ //采集状态赋值
signalAspectMap := make(map[uint16]byte)
for _, cmd := range frame.SignalData.CmdList {
signalAspectMap[cmd.Id] = cmd.Cmd
}
for _, interlockFrame := range s.toInterlockFrames {
for _, state := range interlockFrame.SignalStates {
state.State = signalAspectMap[state.Id]
}
}
}
for _, cmd := range frame.AxleSectionData.CmdList { for _, cmd := range frame.AxleSectionData.CmdList {
if cmd.Cmd == 0x80 { if cmd.Cmd == 0x80 {
uid := s.deviceTable.AxleSectionMap[cmd.Id].uid uid := s.deviceTable.AxleSectionMap[cmd.Id].uid
@ -309,7 +322,7 @@ func Stop(stationCode string) {
} }
} }
func makeTable(sim *memory.VerifySimulation, stationCode string) *StationDeviceIndexTable { func preprocessingData(sim *memory.VerifySimulation, stationCode string) (*StationDeviceIndexTable, []*ToInterlockFrame) {
for _, mapId := range sim.MapIds { for _, mapId := range sim.MapIds {
giType := memory.QueryGiType(mapId) giType := memory.QueryGiType(mapId)
if giType != data_proto.PictureType_StationLayout { if giType != data_proto.PictureType_StationLayout {
@ -320,22 +333,23 @@ func makeTable(sim *memory.VerifySimulation, stationCode string) *StationDeviceI
continue continue
} }
uids := memory.QueryUidStructure[*memory.StationUidStructure](mapId) frameMap := make(map[uint16]*ToInterlockFrame)
var table *StationDeviceIndexTable frameSlice := make([]*ToInterlockFrame, 0, 2)
for _, station := range stationGi.Stations { getFrame := func(interlockCode uint16) *ToInterlockFrame {
if station.StationName != stationCode { frame := frameMap[interlockCode]
continue if frame == nil {
frame = &ToInterlockFrame{InterlockCode: interlockCode, WaysideCode: waysideCode}
frameMap[interlockCode] = frame
frameSlice = append(frameSlice, frame)
} }
for _, lianSuoIndexData := range stationGi.LianSuoData.Stations { return frame
if lianSuoIndexData.Id == station.Common.Id {
table = NewStationDeviceIndexTable(station.StationName, uint16(lianSuoIndexData.Index))
break
}
}
break
} }
if table == nil {
panic(fmt.Sprintf("联锁配置车站[%s]在地图中没有对应的车站或联锁编号数据", stationCode)) uids := memory.QueryUidStructure[*memory.StationUidStructure](mapId)
table := NewStationDeviceIndexTable()
stationMap := make(map[uint32]uint16)
for _, station := range stationGi.LianSuoData.Stations {
stationMap[station.Id] = uint16(0x3c00 + station.Index)
} }
//道岔 //道岔
for _, data := range stationGi.LianSuoData.Switchs { for _, data := range stationGi.LianSuoData.Switchs {
@ -343,8 +357,12 @@ func makeTable(sim *memory.VerifySimulation, stationCode string) *StationDeviceI
continue continue
} }
for _, station := range uids.TurnoutIds[data.Id].CentralizedStations { for _, station := range uids.TurnoutIds[data.Id].CentralizedStations {
if station.StationName == stationCode { interlockCode := stationMap[station.Common.Id]
if interlockCode != 0 {
frame := getFrame(interlockCode)
frame.TurnoutStates = append(frame.TurnoutStates, &TurnoutState{Id: uint16(data.Index)})
table.TurnoutMap[uint16(data.Index)] = &Row{ table.TurnoutMap[uint16(data.Index)] = &Row{
interlockCode: interlockCode,
commonId: data.Id, commonId: data.Id,
uid: uids.TurnoutIds[data.Id].Uid, uid: uids.TurnoutIds[data.Id].Uid,
index: uint16(data.Index), index: uint16(data.Index),
@ -377,7 +395,10 @@ func makeTable(sim *memory.VerifySimulation, stationCode string) *StationDeviceI
relateDeviceMap[S] = sRelayId relateDeviceMap[S] = sRelayId
relateDeviceMap[L] = lRelayId relateDeviceMap[L] = lRelayId
for _, station := range uids.PsdIds[data.Id].CentralizedStations { for _, station := range uids.PsdIds[data.Id].CentralizedStations {
if station.StationName == stationCode { interlockCode := stationMap[station.Common.Id]
if interlockCode != 0 {
frame := getFrame(interlockCode)
frame.PsdStates = append(frame.PsdStates, &PSDState{Id: uint16(data.Index)})
for _, mkx := range sim.Repo.MkxList() { for _, mkx := range sim.Repo.MkxList() {
if mkx.Psd().Id() == uids.PsdIds[data.Id].Uid { if mkx.Psd().Id() == uids.PsdIds[data.Id].Uid {
relateDeviceMap[POB] = mkx.Pobj().Id() relateDeviceMap[POB] = mkx.Pobj().Id()
@ -386,6 +407,7 @@ func makeTable(sim *memory.VerifySimulation, stationCode string) *StationDeviceI
} }
} }
table.PsdMap[uint16(data.Index)] = &Row{ table.PsdMap[uint16(data.Index)] = &Row{
interlockCode: interlockCode,
commonId: data.Id, commonId: data.Id,
uid: uids.PsdIds[data.Id].Uid, uid: uids.PsdIds[data.Id].Uid,
index: uint16(data.Index), index: uint16(data.Index),
@ -400,8 +422,12 @@ func makeTable(sim *memory.VerifySimulation, stationCode string) *StationDeviceI
continue continue
} }
for _, station := range uids.EsbIds[data.Id].CentralizedStations { for _, station := range uids.EsbIds[data.Id].CentralizedStations {
if station.StationName == stationCode { interlockCode := stationMap[station.Common.Id]
if interlockCode != 0 {
frame := getFrame(interlockCode)
frame.ESBStates = append(frame.ESBStates, &ESBState{Id: uint16(data.Index)})
table.EsbMap[uint16(data.Index)] = &Row{ table.EsbMap[uint16(data.Index)] = &Row{
interlockCode: interlockCode,
commonId: data.Id, commonId: data.Id,
uid: uids.EsbIds[data.Id].Uid, uid: uids.EsbIds[data.Id].Uid,
index: uint16(data.Index), index: uint16(data.Index),
@ -417,8 +443,12 @@ func makeTable(sim *memory.VerifySimulation, stationCode string) *StationDeviceI
continue continue
} }
for _, station := range uids.SignalIds[data.Id].CentralizedStations { for _, station := range uids.SignalIds[data.Id].CentralizedStations {
if station.StationName == stationCode { interlockCode := stationMap[station.Common.Id]
if interlockCode != 0 {
frame := getFrame(interlockCode)
frame.SignalStates = append(frame.SignalStates, &SignalState{Id: uint16(data.Index)})
table.SignalMap[uint16(data.Index)] = &Row{ table.SignalMap[uint16(data.Index)] = &Row{
interlockCode: interlockCode,
commonId: data.Id, commonId: data.Id,
uid: uids.SignalIds[data.Id].Uid, uid: uids.SignalIds[data.Id].Uid,
index: uint16(data.Index), index: uint16(data.Index),
@ -427,6 +457,17 @@ func makeTable(sim *memory.VerifySimulation, stationCode string) *StationDeviceI
} }
} }
} }
{ //临时补充一个信号机
table.SignalMap[40] = &Row{
interlockCode: 0x3c02,
commonId: 0,
uid: "",
index: 40,
relateDeviceMap: nil,
}
frame := getFrame(0x3c02)
frame.SignalStates = append(frame.SignalStates, &SignalState{Id: 40})
}
//计轴区段 //计轴区段
for _, data := range stationGi.LianSuoData.AcSections { for _, data := range stationGi.LianSuoData.AcSections {
if data.Index <= 0 { if data.Index <= 0 {
@ -434,8 +475,13 @@ func makeTable(sim *memory.VerifySimulation, stationCode string) *StationDeviceI
} }
sectionModule := sim.Repo.FindAxleCountingSection(uids.AxleCountingSectionIds[data.Id].Uid) sectionModule := sim.Repo.FindAxleCountingSection(uids.AxleCountingSectionIds[data.Id].Uid)
for _, station := range sectionModule.PhysicalSection().CentralizedStation() { for _, station := range sectionModule.PhysicalSection().CentralizedStation() {
if station.GetCode() == stationCode { //目前没发现一个计轴区段属于两个联锁区的情况,暂不处理
interlockCode := stationMap[sim.UidMap[station.Id()].CommonId]
if interlockCode != 0 {
frame := getFrame(interlockCode)
frame.AxleSectionStates = append(frame.AxleSectionStates, &AxleSectionState{Id: uint16(data.Index)})
table.AxleSectionMap[uint16(data.Index)] = &Row{ table.AxleSectionMap[uint16(data.Index)] = &Row{
interlockCode: interlockCode,
commonId: data.Id, commonId: data.Id,
uid: uids.AxleCountingSectionIds[data.Id].Uid, uid: uids.AxleCountingSectionIds[data.Id].Uid,
index: uint16(data.Index), index: uint16(data.Index),
@ -452,8 +498,12 @@ func makeTable(sim *memory.VerifySimulation, stationCode string) *StationDeviceI
continue continue
} }
for _, station := range uids.SpksIds[data.Id].CentralizedStations { for _, station := range uids.SpksIds[data.Id].CentralizedStations {
if station.StationName == stationCode { interlockCode := stationMap[station.Common.Id]
if interlockCode != 0 {
frame := getFrame(interlockCode)
frame.SPKSStates = append(frame.SPKSStates, &SPKSState{Id: uint16(data.Index)})
table.SpksMap[uint16(data.Index)] = &Row{ table.SpksMap[uint16(data.Index)] = &Row{
interlockCode: interlockCode,
commonId: data.Id, commonId: data.Id,
uid: uids.SpksIds[data.Id].Uid, uid: uids.SpksIds[data.Id].Uid,
index: uint16(data.Index), index: uint16(data.Index),
@ -464,9 +514,31 @@ func makeTable(sim *memory.VerifySimulation, stationCode string) *StationDeviceI
} }
//车库门实际数据中数量为0 //车库门实际数据中数量为0
//洗车机,实际数据中没有 //洗车机,实际数据中没有
return table //按设备id大小排序
for _, frame := range frameSlice {
sort.Slice(frame.TurnoutStates, func(i, j int) bool {
return frame.TurnoutStates[i].Id < frame.TurnoutStates[j].Id
})
sort.Slice(frame.PsdStates, func(i, j int) bool {
return frame.PsdStates[i].Id < frame.PsdStates[j].Id
})
sort.Slice(frame.ESBStates, func(i, j int) bool {
return frame.ESBStates[i].Id < frame.ESBStates[j].Id
})
sort.Slice(frame.SignalStates, func(i, j int) bool {
return frame.SignalStates[i].Id < frame.SignalStates[j].Id
})
sort.Slice(frame.AxleSectionStates, func(i, j int) bool {
return frame.AxleSectionStates[i].Id < frame.AxleSectionStates[j].Id
})
sort.Slice(frame.SPKSStates, func(i, j int) bool {
return frame.SPKSStates[i].Id < frame.SPKSStates[j].Id
})
}
return table, frameSlice
} }
return nil return nil, nil
} }
func (s *serviceContext) runCollectTask(ctx context.Context) { func (s *serviceContext) runCollectTask(ctx context.Context) {
@ -482,178 +554,152 @@ func (s *serviceContext) runCollectTask(ctx context.Context) {
case <-ctx.Done(): case <-ctx.Done():
return return
default: default:
frame := s.collectDeviceState() s.collectDeviceState()
data := frame.encode() for _, frame := range s.toInterlockFrames {
_, err := s.server.WriteToUdp(data, s.ioAddr) data := frame.encode()
if err != nil { _, err := s.server.WriteToUdp(data, s.ioAddr)
logger().Error("向联锁发送数据失败", "error", err) if err != nil {
} else { logger().Error("向联锁发送数据失败", "error", err)
logger().Info(fmt.Sprintf("向联锁发送数据:%x", data)) } else {
logger().Info(fmt.Sprintf("向联锁发送数据:%x", data))
}
} }
} }
} }
}() }()
} }
func (s *serviceContext) collectDeviceState() *ToInterlockFrame { func (s *serviceContext) collectDeviceState() {
wd := entity.GetWorldData(s.sim.World) wd := entity.GetWorldData(s.sim.World)
frame := &ToInterlockFrame{} for _, frame := range s.toInterlockFrames {
frame.WaysideCode = waysideCode //道岔
frame.InterlockCode = s.deviceTable.InterlockCode for _, state := range frame.TurnoutStates {
//道岔 row := s.deviceTable.TurnoutMap[state.Id]
for _, row := range s.deviceTable.TurnoutMap { entry := wd.EntityMap[row.uid]
entry := wd.EntityMap[row.uid] tp := component.TurnoutPositionType.Get(entry)
tp := component.TurnoutPositionType.Get(entry) var stateByte byte
var stateByte byte if entry.HasComponent(component.TurnoutFaultCiqdType) {
if entry.HasComponent(component.TurnoutFaultCiqdType) { stateByte = 0xff
stateByte = 0xff } else {
} else { if tp.Dw {
if tp.Dw { stateByte = 0x01
stateByte = 0x01 } else if tp.Fw {
} else if tp.Fw { stateByte = 0x02
} else {
stateByte = 0x08
}
}
state.State = stateByte
}
//屏蔽门
for _, state := range frame.PsdStates {
row := s.deviceTable.PsdMap[state.Id]
entry := wd.EntityMap[row.uid]
psdState := component.PsdStateType.Get(entry)
mkxBytes := make([]byte, 0, 3)
for _, mkxRelayUid := range []string{row.relateDeviceMap[POB], row.relateDeviceMap[PCB], row.relateDeviceMap[DPB]} {
if mkxRelayUid == "" {
continue
}
mkxBytes = append(mkxBytes, GetStateByte(component.BitStateType.Get(wd.EntityMap[mkxRelayUid]).Val))
}
var stateByte byte
if psdState.Close {
stateByte = 0x02 stateByte = 0x02
} else { } else {
stateByte = 0x08
}
}
frame.TurnoutStates = append(frame.TurnoutStates, &TurnoutState{
Id: row.index,
State: stateByte,
})
}
sort.Slice(frame.TurnoutStates, func(i, j int) bool {
return frame.TurnoutStates[i].Id < frame.TurnoutStates[j].Id
})
//屏蔽门
for _, row := range s.deviceTable.PsdMap {
entry := wd.EntityMap[row.uid]
psdState := component.PsdStateType.Get(entry)
mkxBytes := make([]byte, 0, 3)
for _, mkxRelayUid := range []string{row.relateDeviceMap[POB], row.relateDeviceMap[PCB], row.relateDeviceMap[DPB]} {
if mkxRelayUid == "" {
continue
}
mkxBytes = append(mkxBytes, GetStateByte(component.BitStateType.Get(wd.EntityMap[mkxRelayUid]).Val))
}
var state byte
if psdState.Close {
state = 0x02
} else {
state = 0x01
}
var hsjc byte
if psdState.InterlockRelease {
hsjc = 0xff
} else {
hsjc = 0xee
}
frame.PsdStates = append(frame.PsdStates, &PSDState{
Id: row.index,
State: state,
Hsjc: hsjc,
PCB: mkxBytes[0],
POB: mkxBytes[1],
DPB: mkxBytes[2],
})
}
sort.Slice(frame.PsdStates, func(i, j int) bool {
return frame.PsdStates[i].Id < frame.PsdStates[j].Id
})
//紧急停车
for _, row := range s.deviceTable.EsbMap {
esb := s.sim.Repo.FindEsb(row.uid)
relay := wd.EntityMap[esb.RelayId()]
pla := wd.EntityMap[esb.PlaId()]
frame.ESBStates = append(frame.ESBStates, &ESBState{
Id: row.index,
State: GetStateByte(!component.BitStateType.Get(relay).Val),
PlState: GetStateByte(component.BitStateType.Get(pla).Val),
//PlState: 0x00,
})
}
sort.Slice(frame.ESBStates, func(i, j int) bool {
return frame.ESBStates[i].Id < frame.ESBStates[j].Id
})
//信号机
for _, row := range s.deviceTable.SignalMap {
entry := wd.EntityMap[row.uid]
lights := component.SignalLightsType.Get(entry)
isL := false
isH := false
isU := false
isA := false
isB := false
for _, light := range lights.Lights {
switch {
case light.HasComponent(component.LdTag):
isL = component.BitStateType.Get(light).Val
case light.HasComponent(component.HdTag):
isH = component.BitStateType.Get(light).Val
case light.HasComponent(component.UdTag):
isU = component.BitStateType.Get(light).Val
case light.HasComponent(component.BdTag):
isB = component.BitStateType.Get(light).Val
case light.HasComponent(component.AdTag):
isA = component.BitStateType.Get(light).Val
}
}
var stateByte byte
if isH && isU {
stateByte = 0x03
} else {
switch {
case isL:
stateByte = 0x04
case isH:
stateByte = 0x01 stateByte = 0x01
case isU:
stateByte = 0x02
case isB:
stateByte = 0x08
case isA:
stateByte = 0x09
} }
var hsjc byte
if psdState.InterlockRelease {
hsjc = 0xff
} else {
hsjc = 0xee
}
state.State = stateByte
state.Hsjc = hsjc
state.PCB = mkxBytes[0]
state.POB = mkxBytes[1]
state.DPB = mkxBytes[2]
} }
frame.SignalStates = append(frame.SignalStates, &SignalState{ //紧急停车
Id: row.index, for _, state := range frame.ESBStates {
State: stateByte, row := s.deviceTable.EsbMap[state.Id]
}) esb := s.sim.Repo.FindEsb(row.uid)
} relay := wd.EntityMap[esb.RelayId()]
sort.Slice(frame.SignalStates, func(i, j int) bool { pla := wd.EntityMap[esb.PlaId()]
return frame.SignalStates[i].Id < frame.SignalStates[j].Id
}) state.State = GetStateByte(!component.BitStateType.Get(relay).Val)
//计轴区段 state.PlState = GetStateByte(component.BitStateType.Get(pla).Val)
for _, row := range s.deviceTable.AxleSectionMap { }
entry := wd.EntityMap[row.uid] ////信号机
sectionState := component.AxleCountingSectionStateType.Get(entry) //for _, state := range frame.SignalStates {
var stateByte byte = 0x00 // row := s.deviceTable.SignalMap[state.Id]
if sectionState.Occupied { // entry := wd.EntityMap[row.uid]
stateByte = 0x40 // lights := component.SignalLightsType.Get(entry)
// isL := false
// isH := false
// isU := false
// isA := false
// isB := false
// for _, light := range lights.Lights {
// switch {
// case light.HasComponent(component.LdTag):
// isL = component.BitStateType.Get(light).Val
// case light.HasComponent(component.HdTag):
// isH = component.BitStateType.Get(light).Val
// case light.HasComponent(component.UdTag):
// isU = component.BitStateType.Get(light).Val
// case light.HasComponent(component.BdTag):
// isB = component.BitStateType.Get(light).Val
// case light.HasComponent(component.AdTag):
// isA = component.BitStateType.Get(light).Val
// }
// }
// var stateByte byte
// if isH && isU {
// stateByte = 0x03
// } else {
// switch {
// case isL:
// stateByte = 0x04
// case isH:
// stateByte = 0x01
// case isU:
// stateByte = 0x02
// case isB:
// stateByte = 0x08
// case isA:
// stateByte = 0x09
// }
// }
//
// state.State = stateByte
//}
//计轴区段
for _, state := range frame.AxleSectionStates {
row := s.deviceTable.AxleSectionMap[state.Id]
entry := wd.EntityMap[row.uid]
sectionState := component.AxleCountingSectionStateType.Get(entry)
var stateByte byte = 0x00
if sectionState.Occupied {
stateByte = 0x40
}
state.State = stateByte
}
//SPKS
for _, state := range frame.SPKSStates {
row := s.deviceTable.SpksMap[state.Id]
spks := s.sim.Repo.FindSpks(row.uid)
relay := wd.EntityMap[spks.Relay()]
pla := wd.EntityMap[spks.PlaId()]
state.State = GetStateByte(!component.BitStateType.Get(relay).Val)
state.PlState = GetStateByte(component.BitStateType.Get(pla).Val)
} }
frame.AxleSectionStates = append(frame.AxleSectionStates, &AxleSectionState{
Id: row.index,
State: stateByte,
})
} }
sort.Slice(frame.AxleSectionStates, func(i, j int) bool {
return frame.AxleSectionStates[i].Id < frame.AxleSectionStates[j].Id
})
//SPKS
for _, row := range s.deviceTable.SpksMap {
spks := s.sim.Repo.FindSpks(row.uid)
relay := wd.EntityMap[spks.Relay()]
pla := wd.EntityMap[spks.PlaId()]
frame.SPKSStates = append(frame.SPKSStates, &SPKSState{
Id: row.index,
State: GetStateByte(!component.BitStateType.Get(relay).Val),
PlState: GetStateByte(component.BitStateType.Get(pla).Val),
//PlState: 0xff,
})
}
sort.Slice(frame.SPKSStates, func(i, j int) bool {
return frame.SPKSStates[i].Id < frame.SPKSStates[j].Id
})
return frame
} }
func logger() *slog.Logger { func logger() *slog.Logger {

View File

@ -9,10 +9,12 @@ import (
"joylink.club/bj-rtsts-server/third_party/interlock/beijing12" "joylink.club/bj-rtsts-server/third_party/interlock/beijing12"
"joylink.club/bj-rtsts-server/third_party/radar" "joylink.club/bj-rtsts-server/third_party/radar"
"joylink.club/bj-rtsts-server/third_party/train_pc_sim" "joylink.club/bj-rtsts-server/third_party/train_pc_sim"
"joylink.club/rtsssimulation/fi"
"log/slog" "log/slog"
"runtime" "runtime"
"strconv" "strconv"
"sync" "sync"
"time"
"joylink.club/bj-rtsts-server/third_party/can_btm" "joylink.club/bj-rtsts-server/third_party/can_btm"
cidcmodbus "joylink.club/bj-rtsts-server/third_party/cidc_modbus" cidcmodbus "joylink.club/bj-rtsts-server/third_party/cidc_modbus"
@ -58,24 +60,26 @@ func CreateSimulation(projectId int32, mapIds []int32, runConfig *dto.ProjectRun
return "", err return "", err
} }
verifySimulation.SimulationId = simulationId verifySimulation.SimulationId = simulationId
verifySimulation.ProjectCode = project.Code
// world构建 // world构建
err = initWorld(verifySimulation) err = initWorld(verifySimulation)
if err != nil { if err != nil {
return "", err return "", err
} }
// verifySimulation.Start()
// 全部成功,启动仿真
verifySimulation.World.StartUp()
// 初始化设备状态
initDeviceStatus(verifySimulation)
// 启动仿真消息服务
message_server.Start(verifySimulation)
// 第三方服务处理 // 第三方服务处理
err = runThirdParty(verifySimulation) err = runThirdParty(verifySimulation)
if err != nil { if err != nil {
verifySimulation.World.Close() verifySimulation.World.Close()
return "", err return "", err
} }
verifySimulation.ProjectCode = project.Code
simulationMap.Store(simulationId, verifySimulation) simulationMap.Store(simulationId, verifySimulation)
// verifySimulation.Start()
// 全部成功,启动仿真
verifySimulation.World.StartUp()
// 启动仿真消息服务
message_server.Start(verifySimulation)
} }
return simulationId, nil return simulationId, nil
} }
@ -98,6 +102,22 @@ func DestroySimulation(simulationId string) {
stopThirdParty(simulationInfo) stopThirdParty(simulationInfo)
} }
func initDeviceStatus(simulation *memory.VerifySimulation) {
for _, turnout := range simulation.Repo.TurnoutList() {
err := fi.DriveTurnoutDCOn(simulation.World, turnout.Id())
if err != nil {
slog.Error("初始驱动道岔到定位失败", "error", err)
}
}
time.Sleep(200 * time.Millisecond)
for _, turnout := range simulation.Repo.TurnoutList() {
err := fi.DriveTurnoutDCOff(simulation.World, turnout.Id())
if err != nil {
slog.Error("取消驱动道岔到定位失败", "error", err)
}
}
}
// 创建world // 创建world
func initWorld(s *memory.VerifySimulation) error { func initWorld(s *memory.VerifySimulation) error {
//创建仿真 //创建仿真