package ts import ( "fmt" "joylink.club/bj-rtsts-server/third_party/axle_device" "log/slog" "runtime" "strconv" "sync" "joylink.club/bj-rtsts-server/config" "joylink.club/bj-rtsts-server/message_server" "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" "joylink.club/bj-rtsts-server/dto" rtss_simulation "joylink.club/rtsssimulation" ) // 仿真存储集合 var simulationMap sync.Map // 创建前检查 func IsExistSimulation() bool { i := 0 simulationMap.Range(func(_, _ any) bool { i++ return true }) return i > 0 } // 创建仿真对象 func CreateSimulation(projectId int32, mapIds []int32, runConfig *dto.ProjectRunConfigDto) (string, error) { simulationId := createSimulationId(projectId) _, e := simulationMap.Load(simulationId) if !e && IsExistSimulation() { return "", sys_error.New("一套环境同时只能运行一个仿真") } if !e { verifySimulation, err := memory.CreateSimulation(projectId, mapIds, runConfig) if err != nil { return "", err } verifySimulation.SimulationId = simulationId // world构建 err = initWorld(verifySimulation) if err != nil { return "", err } // 第三方服务处理 err = runThirdParty(verifySimulation) if err != nil { return "", err } simulationMap.Store(simulationId, verifySimulation) verifySimulation.Start() // 全部成功,启动仿真 verifySimulation.World.StartUp() // 启动仿真消息服务 message_server.Start(verifySimulation) /* //测试用 cps := verifySimulation.GetSectionCodePoints("北京", "12", "酒仙桥") if len(cps) > 0 { sort.SliceStable(cps, func(i, j int) bool { return cps[i].Row < cps[j].Row }) } sb := strings.Builder{} for row, cp := range cps { sb.WriteString(fmt.Sprintf("%d:\"%s\",", row, cp.SectionId)) } fmt.Println("====================@@@@@@@>>>>>>>>", sb.String()) */ } return simulationId, nil } // 删除仿真对象 func DestroySimulation(simulationId string) { s, e := simulationMap.Load(simulationId) if !e { return } simulationMap.Delete(simulationId) simulationInfo := s.(*memory.VerifySimulation) simulationInfo.Destroy() // 停止ecs world simulationInfo.World.Close() // 停止第三方 stopThirdParty(simulationInfo) message_server.Close(simulationInfo) } // 创建world func initWorld(s *memory.VerifySimulation) error { //创建仿真 w, err := rtss_simulation.NewSimulation(s.Repo) if err != nil { return sys_error.New(fmt.Sprintf("仿真创建失败: %s", err), err) } s.World = w // 保证World关闭 runtime.SetFinalizer(s, func(verifySimulation *memory.VerifySimulation) { slog.Info("---关闭仿真World---") verifySimulation.World.Close() }) return nil } // 运行仿真第三方模块 func runThirdParty(s *memory.VerifySimulation) error { // 动力学启动 err := dynamics.Default().Start(s) if err != nil { return err } // 半实物启动 semi_physical_train.Default().Start(s) // 联锁启动 for _, c := range s.GetInterlockCodes() { interlock.Default(c).Start(s) } // 计轴RSSP启动 axle_device.StartLineAllRsspAxleServices(s) return nil } // 停止仿真 func stopThirdParty(s *memory.VerifySimulation) { // 停止动力学接口功能 dynamics.Default().Stop() // 停止半实物 semi_physical_train.Default().Stop() // 联锁启动 for _, c := range s.GetInterlockCodes() { interlock.Default(c).Stop() } //计轴RSSP启动销毁 axle_device.StopLineAllRsspAxleServices() } func createSimulationId(projectId int32) string { // 当前服务器IP + 端口 + 项目 return config.SimulationId_prefix + "_" + strconv.Itoa(config.Config.Server.Port) + "_" + strconv.Itoa(int(projectId)) } // 获取仿真列表 func ListAllSimulations() []*dto.SimulationInfoRspDto { var simArr []*dto.SimulationInfoRspDto simulationMap.Range(func(_, v any) bool { s := v.(*memory.VerifySimulation) simArr = append(simArr, &dto.SimulationInfoRspDto{ SimulationId: s.SimulationId, MapId: s.MapIds[0], MapIds: s.MapIds, ProjectId: s.ProjectId, ProjectRunConfigId: s.GetRunConfigId(), }) return true }) return simArr } // 根据仿真id查找仿真实例 func FindSimulation(simulationId string) *memory.VerifySimulation { m, e := simulationMap.Load(simulationId) if e { return m.(*memory.VerifySimulation) } return nil }