diff --git a/api/simulation.go b/api/simulation.go index 3112861..0b8df38 100644 --- a/api/simulation.go +++ b/api/simulation.go @@ -405,7 +405,7 @@ func ibpBtnOperation(c *gin.Context) { } simulation := checkDeviceDataAndReturn(req.SimulationId) slog.Info("传入状态参数", req) - err := memory.ChangeIBPButtonState(simulation, req.MapId, req.StationId, req.ButtonCode, req.Down) + err := memory.ChangeIBPButtonState(simulation, req.MapId, req.StationId, req.ButtonId, req.Down) if err != nil { panic(sys_error.New(fmt.Sprintf("IBP按钮操作失败,%s", err.Error()), err)) } @@ -435,7 +435,7 @@ func ibpKeyOperation(c *gin.Context) { } simulation := checkDeviceDataAndReturn(req.SimulationId) slog.Info("传入状态参数", req) - err := memory.ChangeIBPKeyState(simulation, req.MapId, req.StationId, req.KeyCode, req.Gear) + err := memory.ChangeIBPKeyState(simulation, req.MapId, req.StationId, req.KeyId, req.Gear) if err != nil { panic(sys_error.New(fmt.Sprintf("IBP开关操作失败,%s", err.Error()), err)) } diff --git a/dto/simulation.go b/dto/simulation.go index a8db18c..0e7dc84 100644 --- a/dto/simulation.go +++ b/dto/simulation.go @@ -119,7 +119,7 @@ type IBPButtonOperationReqDto struct { SimulationId string `form:"simulationId" json:"simulationId" binding:"required"` MapId int32 `json:"mapId" from:"mapId" binding:"required"` StationId string `form:"stationId" json:"stationId" binding:"required"` - ButtonCode string `form:"buttonCode" json:"buttonCode" binding:"required"` + ButtonId string `form:"buttonId" json:"buttonId" binding:"required"` Down bool `form:"down" json:"down"` } @@ -135,7 +135,7 @@ type KeyOperationReqDto struct { SimulationId string `form:"simulationId" json:"simulationId" binding:"required"` MapId int32 `json:"mapId" from:"mapId" binding:"required"` StationId string `form:"stationId" json:"stationId" binding:"required"` - KeyCode string `form:"keyCode" json:"keyCode"` + KeyId string `form:"keyId" json:"keyId"` Gear int32 `form:"gear" json:"gear"` } diff --git a/message_server/ibp_ms.go b/message_server/ibp_ms.go index 609fa37..6e1e02b 100644 --- a/message_server/ibp_ms.go +++ b/message_server/ibp_ms.go @@ -60,20 +60,21 @@ func (ms *IbpMs) collectStationIbpState(station *graphicData.Station) (*state.Pu return nil, nil } stationUid := memory.QueryUidByMidAndComId(ms.mapId, station.Common.Id, &graphicData.Station{}) - ibpStorage := memory.GetStorageIBPMapData(station.RefIbpMapCode) - buttonStates, err := ms.collectIBPButtonState(stationUid, ibpStorage.IbpButtons) + ibpMapId, ibpStorage := memory.GetStorageIBPMapData(station.RefIbpMapCode) + ibpUidsMap := memory.QueryUidStructure[*memory.IBPUidStructure](ibpMapId) + buttonStates, err := ms.collectIBPButtonState(stationUid, ibpUidsMap, ibpStorage.IbpButtons) if err != nil { return nil, err } - alarmStates, err := ms.collectIBPAlarmState(stationUid, ibpStorage.IbpAlarms) + alarmStates, err := ms.collectIBPAlarmState(stationUid, ibpUidsMap, ibpStorage.IbpAlarms) if err != nil { return nil, err } - lightStates, err := ms.collectIBPLightState(stationUid, ibpStorage.IbpLights) + lightStates, err := ms.collectIBPLightState(stationUid, ibpUidsMap, ibpStorage.IbpLights) if err != nil { return nil, err } - keyStates, err := ms.collectIBPKeyState(stationUid, ibpStorage.IbpKeys) + keyStates, err := ms.collectIBPKeyState(stationUid, ibpUidsMap, ibpStorage.IbpKeys) if err != nil { return nil, err } @@ -89,12 +90,13 @@ func (ms *IbpMs) collectStationIbpState(station *graphicData.Station) (*state.Pu } // 收集IBP按钮状态 -func (ms *IbpMs) collectIBPButtonState(stationUid string, ibpButtons []*graphicData.IBPButton) ([]*state.ButtonState, error) { +func (ms *IbpMs) collectIBPButtonState(stationUid string, uidsMap *memory.IBPUidStructure, ibpButtons []*graphicData.IBPButton) ([]*state.ButtonState, error) { var states []*state.ButtonState for _, data := range ibpButtons { // 按钮 - entry, ok := entity.GetEntityByUid(ms.vs.World, stationUid+"_button_"+data.Code) + uid := stationUid + "_" + uidsMap.IbpButtonIds[data.Common.Id].Uid + entry, ok := entity.GetEntityByUid(ms.vs.World, uid) if !ok { - return nil, fmt.Errorf("ibp按钮实体不存在: World id=%d, uid=%s", ms.vs.World.Id(), stationUid+"_button_"+data.Code) + return nil, fmt.Errorf("ibp按钮实体不存在: World id=%d, uid=%s", ms.vs.World.Id(), uid) } if entry.HasComponent(component.ButtonTag) { states = append(states, getIBPButtonState(data.Common.Id, entry)) @@ -117,12 +119,13 @@ func getIBPButtonState(id string, entry *ecs.Entry) *state.ButtonState { } // 收集报警器状态 -func (ms *IbpMs) collectIBPAlarmState(stationUid string, ibpAlarms []*graphicData.IbpAlarm) ([]*state.AlarmState, error) { +func (ms *IbpMs) collectIBPAlarmState(stationUid string, uidsMap *memory.IBPUidStructure, ibpAlarms []*graphicData.IbpAlarm) ([]*state.AlarmState, error) { var states []*state.AlarmState for _, data := range ibpAlarms { // 报警器 - entry, ok := entity.GetEntityByUid(ms.vs.World, stationUid+"_alarm_"+data.Code) + uid := stationUid + "_" + uidsMap.IbpAlarmIds[data.Common.Id].Uid + entry, ok := entity.GetEntityByUid(ms.vs.World, uid) if !ok { - return nil, fmt.Errorf("ibp报警器实体不存在: World id=%d, uid=%s", ms.vs.World.Id(), stationUid+"_alarm_"+data.Code) + return nil, fmt.Errorf("ibp报警器实体不存在: World id=%d, uid=%s", ms.vs.World.Id(), uid) } if entry.HasComponent(component.AlarmTag) { states = append(states, &state.AlarmState{Id: data.Common.Id, Active: component.BitStateType.Get(entry).Val}) @@ -132,12 +135,13 @@ func (ms *IbpMs) collectIBPAlarmState(stationUid string, ibpAlarms []*graphicDat } // 收集灯状态信息 -func (ms *IbpMs) collectIBPLightState(stationUid string, ibpLights []*graphicData.IbpLight) ([]*state.LightState, error) { +func (ms *IbpMs) collectIBPLightState(stationUid string, uidsMap *memory.IBPUidStructure, ibpLights []*graphicData.IbpLight) ([]*state.LightState, error) { var states []*state.LightState for _, data := range ibpLights { // 指示灯 - entry, ok := entity.GetEntityByUid(ms.vs.World, stationUid+"_light_"+data.Code) + uid := stationUid + "_" + uidsMap.IbpLightIds[data.Common.Id].Uid + entry, ok := entity.GetEntityByUid(ms.vs.World, uid) if !ok { - return nil, fmt.Errorf("ibp指示灯实体不存在: World id=%d, uid=%s", ms.vs.World.Id(), stationUid+"_light_"+data.Code) + return nil, fmt.Errorf("ibp指示灯实体不存在: World id=%d, uid=%s", ms.vs.World.Id(), uid) } if entry.HasComponent(component.LightTag) { states = append(states, &state.LightState{Id: data.Common.Id, Active: component.BitStateType.Get(entry).Val}) @@ -147,12 +151,13 @@ func (ms *IbpMs) collectIBPLightState(stationUid string, ibpLights []*graphicDat } // 收集钥匙状态 -func (ms *IbpMs) collectIBPKeyState(stationUid string, ibpKeys []*graphicData.IbpKey) ([]*state.KeyState, error) { +func (ms *IbpMs) collectIBPKeyState(stationUid string, uidsMap *memory.IBPUidStructure, ibpKeys []*graphicData.IbpKey) ([]*state.KeyState, error) { var states []*state.KeyState for _, data := range ibpKeys { // 钥匙 - entry, ok := entity.GetEntityByUid(ms.vs.World, stationUid+"_key_"+data.Code) + uid := stationUid + "_" + uidsMap.IbpKeyIds[data.Common.Id].Uid + entry, ok := entity.GetEntityByUid(ms.vs.World, uid) if !ok { - return nil, fmt.Errorf("ibp钥匙实体不存在: World id=%d, uid=%s", ms.vs.World.Id(), stationUid+"_key_"+data.Code) + return nil, fmt.Errorf("ibp钥匙实体不存在: World id=%d, uid=%s", ms.vs.World.Id(), uid) } if entry.HasComponent(component.KeyTag) { states = append(states, &state.KeyState{Id: data.Common.Id, Gear: component.GearStateType.Get(entry).Val}) diff --git a/ts/simulation/wayside/memory/wayside_memory_ibp.go b/ts/simulation/wayside/memory/wayside_memory_ibp.go index 85e0ea5..a828e3f 100644 --- a/ts/simulation/wayside/memory/wayside_memory_ibp.go +++ b/ts/simulation/wayside/memory/wayside_memory_ibp.go @@ -1,22 +1,58 @@ package memory import ( + "fmt" + "joylink.club/bj-rtsts-server/ts/protos/graphicData" "joylink.club/rtsssimulation/fi" ) // 操作IBP按钮 -func ChangeIBPButtonState(sim *VerifySimulation, mapId int32, stationId, btnCode string, pressDown bool) error { +func ChangeIBPButtonState(sim *VerifySimulation, mapId int32, stationId, btnId string, pressDown bool) error { + uidMap, err := getIbpUidByMapIdAndStationId(mapId, stationId) + if err != nil { + return err + } + if uidMap.IbpButtonIds[btnId] == nil { + return fmt.Errorf("车站【%s】按钮【%s】UID不存在", stationId, btnId) + } stationUid := QueryUidByMidAndComId(mapId, stationId, &graphicData.Station{}) if pressDown { - return fi.PressDownButton(sim.World, stationUid+"_button_"+btnCode) + return fi.PressDownButton(sim.World, stationUid+"_"+uidMap.IbpButtonIds[btnId].Uid) } else { - return fi.PressUpButton(sim.World, stationUid+"_button_"+btnCode) + return fi.PressUpButton(sim.World, stationUid+"_"+uidMap.IbpButtonIds[btnId].Uid) } } // 操作IBP按钮 -func ChangeIBPKeyState(sim *VerifySimulation, mapId int32, stationId, keyCode string, gear int32) error { +func ChangeIBPKeyState(sim *VerifySimulation, mapId int32, stationId, keyId string, gear int32) error { + uidMap, err := getIbpUidByMapIdAndStationId(mapId, stationId) + if err != nil { + return err + } + if uidMap.IbpKeyIds[keyId] == nil { + return fmt.Errorf("车站【%s】钥匙【%s】UID不存在", stationId, keyId) + } stationUid := QueryUidByMidAndComId(mapId, stationId, &graphicData.Station{}) - return fi.SwitchKeyGear(sim.World, stationUid+"_key_"+keyCode, gear) + return fi.SwitchKeyGear(sim.World, stationUid+"_"+uidMap.IbpKeyIds[keyId].Uid, gear) +} + +// 根据平面布置图ID、列车ID获取IbpUid信息 +func getIbpUidByMapIdAndStationId(mapId int32, stationId string) (*IBPUidStructure, error) { + giData := QueryGiData[*graphicData.RtssGraphicStorage](mapId) + var station *graphicData.Station + for _, s := range giData.Stations { + if s.Common.Id == stationId { + station = s + break + } + } + if station == nil { + return nil, fmt.Errorf("地图【%d】车站【%s】不存在", mapId, stationId) + } + + if station.RefIbpMapCode == "" { + return nil, fmt.Errorf("车站【%s】未关联IBP地图", station.StationName) + } + return QueryUidStructure[*IBPUidStructure](QueryGiId(station.RefIbpMapCode)), nil } diff --git a/ts/simulation/wayside/memory/wayside_memory_map.go b/ts/simulation/wayside/memory/wayside_memory_map.go index 870cc35..8e9b78c 100644 --- a/ts/simulation/wayside/memory/wayside_memory_map.go +++ b/ts/simulation/wayside/memory/wayside_memory_map.go @@ -54,6 +54,9 @@ func PublishMapVerifyStructure(graphic *dto.PublishedDto) { case graphicData.PictureType_RelayCabinetLayout: graphicStorage := message.(*graphicData.RelayCabinetGraphicStorage) giUidMap.Store(graphic.ID, initRelayCabinetUid(graphicStorage)) + case graphicData.PictureType_IBP: + graphicStorage := message.(*graphicData.IBPGraphicStorage) + giUidMap.Store(graphic.ID, initIBPUid(graphicStorage)) } } @@ -105,20 +108,20 @@ func QueryGiId(name string) int32 { return value.(int32) } -func GetStorageIBPMapData(mapCode string) *graphicData.IBPGraphicStorage { +func GetStorageIBPMapData(mapCode string) (int32, *graphicData.IBPGraphicStorage) { // 处理关联的IBP盘信息 if mapCode == "" { - return nil + return 0, nil } ibpId, ok := giNameMap.Load(mapCode) if !ok { - return nil + return 0, nil } ibpMapData, ok := giDataMap.Load(ibpId) if !ok { - return nil + return ibpId.(int32), nil } - return ibpMapData.(*graphicData.IBPGraphicStorage) + return ibpId.(int32), ibpMapData.(*graphicData.IBPGraphicStorage) } // 转换成统一坐标公里标 diff --git a/ts/simulation/wayside/memory/wayside_memory_map_init.go b/ts/simulation/wayside/memory/wayside_memory_map_init.go index bf7ce8b..8785df1 100644 --- a/ts/simulation/wayside/memory/wayside_memory_map_init.go +++ b/ts/simulation/wayside/memory/wayside_memory_map_init.go @@ -40,6 +40,13 @@ type RelayUidStructure struct { RelayIds map[string]*elementIdStructure } +type IBPUidStructure struct { + IbpButtonIds map[string]*elementIdStructure + IbpAlarmIds map[string]*elementIdStructure + IbpKeyIds map[string]*elementIdStructure + IbpLightIds map[string]*elementIdStructure +} + // 获取继电器的关联关系 type deviceRelateUidPriex struct { deviceCode string @@ -481,6 +488,65 @@ func initRelayCabinetUid(data *graphicData.RelayCabinetGraphicStorage) *RelayUid return rus } +// 初始化IBP地图UID +func initIBPUid(data *graphicData.IBPGraphicStorage) *IBPUidStructure { + rus := &IBPUidStructure{ + IbpButtonIds: make(map[string]*elementIdStructure), + IbpAlarmIds: make(map[string]*elementIdStructure), + IbpKeyIds: make(map[string]*elementIdStructure), + IbpLightIds: make(map[string]*elementIdStructure), + } + //处理继电器关联信息 + refMap := make(map[string]string) + for _, s := range data.IbpRelatedDevices { + for _, c := range s.Combinationtypes { + for _, i := range c.RefDevices { + refMap[i] = c.Code + } + } + } + codeFun := func(id, code string) string { + if refMap[id] != "" { + return refMap[id] + "_" + code + } else { + return code + } + } + // 处理按钮Uid + for _, d := range data.IbpButtons { + rus.IbpButtonIds[d.Common.Id] = &elementIdStructure{ + CommonId: d.Common.Id, + Code: d.Code, + Uid: "button_" + codeFun(d.Common.Id, d.Code), + } + } + // 处理钥匙Uid + for _, d := range data.IbpKeys { + rus.IbpKeyIds[d.Common.Id] = &elementIdStructure{ + CommonId: d.Common.Id, + Code: d.Code, + Uid: "key_" + codeFun(d.Common.Id, d.Code), + } + } + // 处理报警器Uid + for _, d := range data.IbpAlarms { + rus.IbpAlarmIds[d.Common.Id] = &elementIdStructure{ + CommonId: d.Common.Id, + Code: d.Code, + Uid: "alarm_" + codeFun(d.Common.Id, d.Code), + } + } + // 处理指示灯Uid + for _, d := range data.IbpLights { + rus.IbpLightIds[d.Common.Id] = &elementIdStructure{ + CommonId: d.Common.Id, + Code: d.Code, + Uid: "light_" + codeFun(d.Common.Id, d.Code), + } + } + return rus +} + // 构建仿真内所有地图UID映射信号布置图ID,这里为了解决多地图时根据UID反向寻找,避免多次循环地图,直接获取平面布置图元素 func buildRepositoryAllUidsMap(mapIds []int32, repo *repository.Repository) map[string]*elementIdStructure { mapLen := len(repo.CheckPointList()) + len(repo.PhysicalSectionList()) + len(repo.SignalList()) + @@ -514,7 +580,7 @@ func buildRepositoryAllUidsMap(mapIds []int32, repo *repository.Repository) map[ } // 获取地图UID的映射集合 -func QueryUidStructure[T *StationUidStructure | *RelayUidStructure](mapId int32) T { +func QueryUidStructure[T *StationUidStructure | *RelayUidStructure | *IBPUidStructure](mapId int32) T { uidData, ok := giUidMap.Load(mapId) if !ok { panic(fmt.Errorf("id=%d的发布图没有uid缓存数据", mapId)) diff --git a/ts/simulation/wayside/memory/wayside_simulation.go b/ts/simulation/wayside/memory/wayside_simulation.go index c683b5a..3278534 100644 --- a/ts/simulation/wayside/memory/wayside_simulation.go +++ b/ts/simulation/wayside/memory/wayside_simulation.go @@ -1126,7 +1126,7 @@ func fillProtoRepository(repo *proto.Repository, storage *graphicData.RtssGraphi Code: data.StationName, } // 关联车站的设备 - refs, ok := relateMap[data.Code] + refs, ok := relateMap[station.Code] if ok { for _, c := range refs.Combinationtypes { group := &proto.ElectronicGroup{Code: c.Code} @@ -1214,23 +1214,23 @@ func fillProtoRepository(repo *proto.Repository, storage *graphicData.RtssGraphi } // 将IBP的设备关联到车站中 -func handlerIBPDeviceToStation(station *proto.Station, repo *proto.Repository, ibpMap string) { - storage := GetStorageIBPMapData(ibpMap) +func handlerIBPDeviceToStation(station *proto.Station, repo *proto.Repository, ibpMapCode string) { + mapId, storage := GetStorageIBPMapData(ibpMapCode) if storage == nil { return } + uidMap := QueryUidStructure[*IBPUidStructure](mapId) deviceMap := make(map[string]*proto.ElectronicComponent) // 对应的设备类型 for _, data := range storage.IbpButtons { // 处理按钮 - buttonType := proto.Button_NO_Reset_Press - if data.IsSelfReset { - buttonType = proto.Button_Reset_Press - } b := &proto.Button{ - Id: station.Id + "_button_" + data.Code, + Id: station.Id + "_" + uidMap.IbpButtonIds[data.Common.Id].Uid, Code: data.Code, - ButtonType: buttonType, + ButtonType: proto.Button_NO_Reset_Press, HasLight: data.HasLight, } + if data.IsSelfReset { + b.ButtonType = proto.Button_Reset_Press + } deviceMap[data.Common.Id] = &proto.ElectronicComponent{ Id: b.Id, DeviceType: proto.DeviceType_DeviceType_Button, @@ -1239,7 +1239,7 @@ func handlerIBPDeviceToStation(station *proto.Station, repo *proto.Repository, i } for _, data := range storage.IbpKeys { // 钥匙 b := &proto.Key{ - Id: station.Id + "_key_" + data.Code, + Id: station.Id + "_" + uidMap.IbpKeyIds[data.Common.Id].Uid, Code: data.Code, Gear: 2, } @@ -1251,7 +1251,7 @@ func handlerIBPDeviceToStation(station *proto.Station, repo *proto.Repository, i } for _, data := range storage.IbpAlarms { // 报警器 b := &proto.Alarm{ - Id: station.Id + "_alarm_" + data.Code, + Id: station.Id + "_" + uidMap.IbpAlarmIds[data.Common.Id].Uid, Code: data.Code, } deviceMap[data.Common.Id] = &proto.ElectronicComponent{ @@ -1262,10 +1262,9 @@ func handlerIBPDeviceToStation(station *proto.Station, repo *proto.Repository, i } for _, data := range storage.IbpLights { // 指示灯, b := &proto.Light{ - Id: station.Id + "_light_" + data.Code, + Id: station.Id + "_" + uidMap.IbpLightIds[data.Common.Id].Uid, Code: data.Code, } - // 存入组合类型的 deviceMap[data.Common.Id] = &proto.ElectronicComponent{ Id: b.Id, DeviceType: proto.DeviceType_DeviceType_Light,