diff --git a/api/simulation.go b/api/simulation.go index 14ccd1a..de5e1bf 100644 --- a/api/simulation.go +++ b/api/simulation.go @@ -614,7 +614,10 @@ func pslBtnOperation(c *gin.Context) { } simulation := checkDeviceDataAndReturn(req.SimulationId) slog.Info("传入状态参数", req) - memory.ChangePSLButtonState(simulation, req.MapId, req.PslId, req.ButtonCode, req.Down) + var err *sys_error.BusinessError = memory.ChangePSLButtonState(simulation, req.MapId, req.PslId, req.ButtonCode, req.Down) + if err != nil { + panic(err) + } c.JSON(http.StatusOK, "ok") } @@ -932,34 +935,6 @@ func ckmOperation(c *gin.Context) { c.JSON(http.StatusOK, "ok") } -// 车库门控制盒操作 -// -// @Summary 车库门控制盒操作 -// -// @Security JwtAuth -// -// @Description 车库门操作 -// @Tags ATS测试仿真Api -// @Accept json -// @Param Authorization header string true "JWT Token" -// @Param CkmBoxOperationReq body request_proto.CkmBoxOperationReq true "车库门控制盒操作" -// -// @Success 200 {object} string -// @Failure 500 {object} dto.ErrorDto -// @Router /api/v1/simulation/ckm/operation [put] -func ckmBoxOperation(c *gin.Context) { - req := &request_proto.CkmBoxOperationReq{} - if err := c.ShouldBind(&req); err != nil { - panic(dto.ErrorDto{Code: dto.ArgumentParseError, Message: err.Error()}) - } - simulation := checkDeviceDataAndReturn(req.SimulationId) - var err *sys_error.BusinessError = memory.CkmBoxOperation(simulation, req) - if err != nil { - panic(err) - } - c.JSON(http.StatusOK, "ok") -} - // 获取仿真设备数据并返回 func checkDeviceDataAndReturn(simId string) *memory.VerifySimulation { deviceMemory := ts.FindSimulation(simId) diff --git a/message_server/psl_ms.go b/message_server/psl_ms.go index c592bea..9f48994 100644 --- a/message_server/psl_ms.go +++ b/message_server/psl_ms.go @@ -3,6 +3,7 @@ package message_server import ( "fmt" "joylink.club/bj-rtsts-server/dto/state_proto" + "log/slog" "time" "joylink.club/bj-rtsts-server/dto/data_proto" @@ -16,19 +17,34 @@ import ( func NewPSLMs(vs *memory.VerifySimulation, mapId int32) ms_api.MsgTask { mapData := memory.QueryGiData[*data_proto.RtssGraphicStorage](mapId) - return ms_api.NewScheduleTask(fmt.Sprintf("地图[%d]综合门控箱按钮状态", mapId), func() error { + return ms_api.NewScheduleTask(fmt.Sprintf("地图[%d]PSL按钮状态", mapId), func() error { for _, box := range mapData.GateBoxs { did := memory.GetMapElementId(box.Common) - data_proto, err := collectGateBoxPSLState(vs.World, mapId, box) + data, err := collectGateBoxPSLState(vs.World, mapId, box) if err != nil { return err } - mqtt.GetMsgClient().PubPSLState(vs.SimulationId, mapId, did, data_proto) + sendMsg(vs, mapId, did, data) + } + for _, box := range mapData.GarageDoorBoxes { + did := memory.GetMapElementId(box.Common) + data, err := collectGarageDoorBoxPSLState(vs.World, mapId, box) + if err != nil { + return err + } + sendMsg(vs, mapId, did, data) } return nil }, 200*time.Millisecond) } +func sendMsg(vs *memory.VerifySimulation, mapId int32, pslId uint32, data *state_proto.PushedDevicesStatus) { + err := mqtt.GetMsgClient().PubPSLState(vs.SimulationId, mapId, pslId, data) + if err != nil { + slog.Error(fmt.Sprintf("发送PSL状态出错:%s", err.Error())) + } +} + func collectGateBoxPSLState(world ecs.World, mapId int32, box *data_proto.GatedBox) (*state_proto.PushedDevicesStatus, error) { did := memory.GetMapElementId(box.Common) uidStructure := memory.QueryUidStructure[*memory.StationUidStructure](mapId) @@ -67,3 +83,43 @@ func collectGateBoxPSLState(world ecs.World, mapId int32, box *data_proto.GatedB }, }, nil } + +func collectGarageDoorBoxPSLState(world ecs.World, mapId int32, box *data_proto.GarageDoorBox) (*state_proto.PushedDevicesStatus, error) { + return nil, nil + //did := memory.GetMapElementId(box.Common) + //uidStructure := memory.QueryUidStructure[*memory.StationUidStructure](mapId) + //boxUid := uidStructure.PslIds[did].Uid + //mkxEntry, ok := entity.GetEntityByUid(world, boxUid) + //if !ok { + // return nil, fmt.Errorf("[id:%s]的门控箱实体找不到", boxUid) + //} + //mkx := component.MkxType.Get(mkxEntry) + //var buttonStateArr []*state_proto.ButtonState + //if ok { + // _, pslStorage := memory.QueryGiDataByName[*data_proto.PslGraphicStorage](box.RefGatedBoxMapCode) + // btnUidMap := make(map[string]uint32, len(pslStorage.PslButtons)) + // for _, button := range pslStorage.PslButtons { + // btnUidMap[boxUid+"_"+button.Code] = memory.GetMapElementId(button.Common) + // } + // btnArr := []*ecs.Entry{mkx.PCB, mkx.PCBPL, mkx.POB, mkx.POBPL, mkx.PAB, mkx.PABPL, mkx.WRZF, mkx.WRZFPL, + // mkx.QKQR, mkx.QKQRPL, mkx.MPL, mkx.JXTCPL} + // for _, btn := range btnArr { + // if btn == nil { + // continue + // } + // btnState := component.BitStateType.Get(btn) + // buttonStateArr = append(buttonStateArr, &state_proto.ButtonState{ + // Id: btnUidMap[component.UidType.Get(btn).Id], + // Down: btnState.Val, + // Active: btnState.Val, + // //Bypass: btnState.BypassEnable, + // }) + // } + //} + //return &state_proto.PushedDevicesStatus{ + // All: true, + // AllStatus: &state_proto.AllDevicesStatus{ + // ButtonState: buttonStateArr, + // }, + //}, nil +} diff --git a/protobuf/main.go b/protobuf/main.go new file mode 100644 index 0000000..3f78414 --- /dev/null +++ b/protobuf/main.go @@ -0,0 +1,86 @@ +package main + +import ( + "bufio" + "fmt" + "io/fs" + "log" + "os" + "os/exec" + "path/filepath" + "strings" +) + +var ( + basePath, _ = os.Getwd() + protoFolder = filepath.Join(basePath, "rts-sim-testing-message", "protos") + protocPath = filepath.Join(basePath, "rts-sim-testing-message", "protoc-23.1", "bin", "win64", "protoc") + modulePrefix = "joylink.club/bj-rtsts-server" +) + +func main() { + //先安装以下插件 + //go install google.golang.org/protobuf/cmd/protoc-gen-go@latest + + protoFiles := getProtoFiles() + // 编译proto文件为Go文件 + if err := compileProto(protoFiles); err != nil { + log.Fatalf("编译proto文件失败:%v", err) + } +} + +// 获取指定文件夹下的所有proto文件的绝对路径 +func getProtoFiles() []string { + var protoFiles []string + err := filepath.WalkDir(protoFolder, func(path string, d fs.DirEntry, err error) error { + if !d.IsDir() { + protoFiles = append(protoFiles, path) + } + return err + }) + if err != nil { + log.Fatal("获取proto文件列表失败:", err) + } + return protoFiles +} + +// 编译proto文件为Go文件 +func compileProto(protoFiles []string) error { + for _, fileName := range protoFiles { + file, err := os.Open(fileName) + if err != nil { + return err + } + scanner := bufio.NewScanner(file) + var outPath string + for scanner.Scan() { + text := scanner.Text() + if !strings.HasPrefix(text, "option go_package") { + continue + } + start := strings.Index(text, modulePrefix) + if start < 0 { + break + } + start += len(modulePrefix) + dir := "." + text[start:len(text)-2] + err := os.MkdirAll(dir, fs.ModeDir) + if err != nil { + panic(fmt.Sprintf("创建目录 %s 失败:%v", dir, err)) + } + outPath = "paths=source_relative:" + dir + break + } + if outPath == "" { + outPath = "./" + } + cmd := exec.Command(protocPath, "-I="+protoFolder, "--go_out="+outPath, fileName) + fmt.Println(cmd.String()) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + return err + } + } + return nil +} diff --git a/rts-sim-module b/rts-sim-module index f0a6c53..d63be32 160000 --- a/rts-sim-module +++ b/rts-sim-module @@ -1 +1 @@ -Subproject commit f0a6c534ec7b4b0bb128a435c17ef2b20e481b94 +Subproject commit d63be32ad560b64cf0f3306108064ed59b6f29e8 diff --git a/rts-sim-testing-message b/rts-sim-testing-message index b748c7f..9c420a8 160000 --- a/rts-sim-testing-message +++ b/rts-sim-testing-message @@ -1 +1 @@ -Subproject commit b748c7ff3ed7d401c8caeaecd3d4ec719ae27ee2 +Subproject commit 9c420a826ce6a387384ff3b16f2097036f1d094d diff --git a/ts/simulation/wayside/memory/wayside_memory_ckm.go b/ts/simulation/wayside/memory/wayside_memory_ckm.go index 0c0bc80..2af80d5 100644 --- a/ts/simulation/wayside/memory/wayside_memory_ckm.go +++ b/ts/simulation/wayside/memory/wayside_memory_ckm.go @@ -8,7 +8,6 @@ import ( appcomponent "joylink.club/bj-rtsts-server/ts/simulation/app_component" "joylink.club/ecs" "joylink.club/rtsssimulation/entity" - "joylink.club/rtsssimulation/fi" "unsafe" ) @@ -22,22 +21,6 @@ func CkmOperation(simulation *VerifySimulation, req *request_proto.CkmOperationR return nil } -func CkmBoxOperation(sim *VerifySimulation, req *request_proto.CkmBoxOperationReq) *sys_error.BusinessError { - uid := QueryUidStructure[*StationUidStructure](req.MapId) - ckmBoxBtnUid := uid.CkmBoxIds[req.CkmBoxId].Uid - var err error - if req.Down { - err = fi.PressDownButton(sim.World, ckmBoxBtnUid+"_"+req.ButtonCode) - } else { - err = fi.PressUpButton(sim.World, ckmBoxBtnUid+"_"+req.ButtonCode) - } - if err != nil { - return sys_error.New("车库门控制盒操作失败", err) - } else { - return nil - } -} - func setParam(simulation *VerifySimulation, req *request_proto.CkmOperationReq) *sys_error.BusinessError { uid := QueryUidByMidAndComId(req.MapId, req.DeviceId, &data_proto.GarageDoor{}) result := <-ecs.Request[ecs.EmptyType](simulation.World, func() ecs.Result[ecs.EmptyType] { diff --git a/ts/simulation/wayside/memory/wayside_memory_map.go b/ts/simulation/wayside/memory/wayside_memory_map.go index c0616bc..079c483 100644 --- a/ts/simulation/wayside/memory/wayside_memory_map.go +++ b/ts/simulation/wayside/memory/wayside_memory_map.go @@ -79,7 +79,12 @@ func GenerateElementUid(city, lineId string, stationIndexList []string, code str idArr = append(idArr, city, lineId) idArr = append(idArr, stationIndexList...) idArr = append(idArr, code) - return strings.Join(idArr, "_") + return BuildUid(idArr...) +} + +// GenerateElementUid 构建uid。将args用'_'连接 +func BuildUid(args ...string) string { + return strings.Join(args, "_") } // 移除内存中的地图信息 diff --git a/ts/simulation/wayside/memory/wayside_memory_map_init.go b/ts/simulation/wayside/memory/wayside_memory_map_init.go index 50710d3..88a0528 100644 --- a/ts/simulation/wayside/memory/wayside_memory_map_init.go +++ b/ts/simulation/wayside/memory/wayside_memory_map_init.go @@ -45,7 +45,6 @@ type StationUidStructure struct { SpksSwitchIds map[uint32]*elementIdStructure IbpIds map[uint32]*elementIdStructure CkmIds map[uint32]*elementIdStructure - CkmBoxIds map[uint32]*elementIdStructure } type RelayUidStructure struct { @@ -257,9 +256,8 @@ func initStationUid(data *data_proto.RtssGraphicStorage) *StationUidStructure { PsdIds: make(map[uint32]*elementIdStructure, len(data.ScreenDoors)), PslIds: make(map[uint32]*elementIdStructure, len(data.GateBoxs)), //SpksSwitchIds: make(map[uint32]*elementIdStructure, len(data.SpksSwitchs)), - IbpIds: make(map[uint32]*elementIdStructure, len(data.IbpBoxs)), - CkmIds: make(map[uint32]*elementIdStructure, len(data.GarageDoors)), - CkmBoxIds: make(map[uint32]*elementIdStructure, len(data.GarageDoors)), + IbpIds: make(map[uint32]*elementIdStructure, len(data.IbpBoxs)), + CkmIds: make(map[uint32]*elementIdStructure, len(data.GarageDoors)), } city, lineId, _ := getUIdPrefix(data.UniqueIdPrefix) // 处理车站信息 @@ -422,6 +420,15 @@ func initStationUid(data *data_proto.RtssGraphicStorage) *StationUidStructure { Uid: GenerateElementUid(city, lineId, nil, ckm.Code), } } + for _, box := range data.GarageDoorBoxes { + eid := GetMapElementId(box.Common) + ckmUid := gus.CkmIds[box.RefGarageDoorId].Uid + gus.PslIds[eid] = &elementIdStructure{ + CommonId: eid, + Code: box.Code, + Uid: BuildUid(ckmUid, strconv.Itoa(int(eid))), + } + } //// SPKS人员防护 //for _, spk := range data.SpksSwitchs { // if spk.RefStand == 0 { diff --git a/ts/simulation/wayside/memory/wayside_memory_psl.go b/ts/simulation/wayside/memory/wayside_memory_psl.go index 50e6b2e..4451b25 100644 --- a/ts/simulation/wayside/memory/wayside_memory_psl.go +++ b/ts/simulation/wayside/memory/wayside_memory_psl.go @@ -1,16 +1,23 @@ package memory import ( + "joylink.club/bj-rtsts-server/sys_error" "joylink.club/rtsssimulation/fi" ) // 操作PSL按钮 -func ChangePSLButtonState(sim *VerifySimulation, mapId int32, gateBoxId uint32, btnCode string, pressDown bool) { +func ChangePSLButtonState(sim *VerifySimulation, mapId int32, gateBoxId uint32, btnCode string, pressDown bool) *sys_error.BusinessError { uid := QueryUidStructure[*StationUidStructure](mapId) gateBoxUid := uid.PslIds[gateBoxId].Uid + var err error if pressDown { - fi.PressDownButton(sim.World, gateBoxUid+"_"+btnCode) + err = fi.PressDownButton(sim.World, gateBoxUid+"_"+btnCode) } else { - fi.PressUpButton(sim.World, gateBoxUid+"_"+btnCode) + err = fi.PressUpButton(sim.World, gateBoxUid+"_"+btnCode) + } + if err != nil { + return sys_error.New("操作PSL按钮出错", err) + } else { + return nil } } diff --git a/ts/simulation/wayside/memory/wayside_simulation.go b/ts/simulation/wayside/memory/wayside_simulation.go index 8455f45..eae28ea 100644 --- a/ts/simulation/wayside/memory/wayside_simulation.go +++ b/ts/simulation/wayside/memory/wayside_simulation.go @@ -704,6 +704,10 @@ func buildAndRelateElectronicComponent(repo *proto.Repository, relayGi *data_pro for _, platform := range repo.Platforms { platformMap[platform.Id] = platform } + ckmMap := make(map[string]*proto.Ckm) + for _, ckm := range repo.Ckms { + ckmMap[ckm.Id] = ckm + } ciecs := stationMap[stationUid] //联锁集中站 if ciecs == nil { panic(fmt.Errorf("联锁集中站[%s]不存在", stationUid)) @@ -813,6 +817,27 @@ func buildAndRelateElectronicComponent(repo *proto.Repository, relayGi *data_pro Egs: egs, }) } + case data_proto.RelatedRef_GarageDoor: //车库门 + { + ckm, ok := ckmMap[GenerateElementUid(city, lineId, nil, relationship.Code)] + if !ok { + continue + } + for _, group := range relationship.Combinationtypes { + var componentIds []string + for _, relayId := range group.RefRelays { + if relayUidStructure.RelayIds[relayId] == nil { + continue + } + componentIds = append(componentIds, relayUidStructure.RelayIds[relayId].Uid) + } + ckm.ElectronicComponentGroups = append(ckm.ElectronicComponentGroups, + &proto.ElectronicComponentGroup{ + Code: group.Code, + ComponentIds: componentIds, + }) + } + } } } //门控箱 @@ -848,24 +873,6 @@ func buildAndRelateElectronicComponent(repo *proto.Repository, relayGi *data_pro } } } - //cis := stationMap[stationUid] - //// 零散组合 - //for _, com := range relayGi.CombinationtypeList { - // if com.Code == "LS" { // 零散组合 - // d := &proto.ElectronicGroup{Code: com.Code} - // for _, relayId := range com.RefRelays { - // if relayUidStructure.RelayIds[relayId] == nil { - // continue - // } - // d.Components = append(d.Components, &proto.ElectronicComponent{ - // BaliseId: relayUidStructure.RelayIds[relayId].Uid, - // DeviceType: proto.DeviceType_DeviceType_Relay, - // }) - // } - // cis.ElectronicGroup = append(cis.ElectronicGroup, d) - // fmt.Println("构建零散组合结果:", d) - // } - //} // 处理该集中站采集、驱动配置信息 centralizedStationId := GenerateElementUid(city, lineId, nil, station) ref := queryCentralizedStationRef(centralizedStationId, repo) @@ -1268,7 +1275,7 @@ func fillProtoRepository(repo *proto.Repository, storage *data_proto.RtssGraphic platformId_psdUid_map[data.GetRefPlatformId()] = psd.Id repo.Psds = append(repo.Psds, psd) } - //PSL + //屏蔽门PSL for _, data := range storage.PslBoxs { boxUidInfo := uidsMap.PslIds[GetMapElementId(data.Common)] mkx := &proto.Mkx{ @@ -1319,6 +1326,43 @@ func fillProtoRepository(repo *proto.Repository, storage *data_proto.RtssGraphic station := repoStationMap[data.RefStationId] handlerIBPDeviceToStation(station, boxUidInfo.Uid, repo, data.RefIbpMapCode) } + //车库门 + for _, data := range storage.GarageDoors { + id := GetMapElementId(data.Common) + ckm := &proto.Ckm{ + Id: uidsMap.CkmIds[id].Uid, + } + repo.Ckms = append(repo.Ckms, ckm) + } + //车库门PSL + for _, data := range storage.GarageDoorBoxes { + boxUidInfo := uidsMap.PslIds[GetMapElementId(data.Common)] + ckmPsl := &proto.CkmPsl{ + Id: boxUidInfo.Uid, + CkmId: uidsMap.CkmIds[data.RefGarageDoorId].Uid, + } + repo.CkmPsls = append(repo.CkmPsls, ckmPsl) + _, pslStorage := QueryGiDataByName[*data_proto.PslGraphicStorage](data.RefPslMapCode) + for _, button := range pslStorage.PslButtons { + repoButton := &proto.Button{ + Id: boxUidInfo.Uid + "_" + button.Code, + Code: button.Code, + ButtonType: proto.Button_Reset_Press, + HasLight: true, + } + repo.Buttons = append(repo.Buttons, repoButton) + switch button.Code { + case "KMA": + ckmPsl.KmaId = repoButton.Id + case "GMA": + ckmPsl.GmaId = repoButton.Id + case "MPLA": + ckmPsl.MplaId = repoButton.Id + case "MMSA": + ckmPsl.MmsaId = repoButton.Id + } + } + } } // 将IBP的设备关联到车站中