rts-sim-testing-service/api/simulation.go

517 lines
16 KiB
Go
Raw Normal View History

2023-07-28 14:36:16 +08:00
package api
import (
2023-07-31 17:27:05 +08:00
"fmt"
"log/slog"
2023-07-28 14:36:16 +08:00
"net/http"
"sort"
2023-07-31 17:27:05 +08:00
"strconv"
2023-07-28 14:36:16 +08:00
jwt "github.com/appleboy/gin-jwt/v2"
"github.com/gin-gonic/gin"
2023-07-31 17:27:05 +08:00
"github.com/golang/protobuf/proto"
"joylink.club/bj-rtsts-server/ats/verify/protos/graphicData"
"joylink.club/bj-rtsts-server/ats/verify/protos/state"
2023-07-31 08:41:42 +08:00
"joylink.club/bj-rtsts-server/ats/verify/simulation"
2023-08-01 14:54:11 +08:00
"joylink.club/bj-rtsts-server/ats/verify/simulation/wayside/memory"
2023-08-31 14:06:53 +08:00
"joylink.club/bj-rtsts-server/config"
2023-07-28 14:36:16 +08:00
"joylink.club/bj-rtsts-server/dto"
2023-10-13 17:43:48 +08:00
"joylink.club/bj-rtsts-server/dto/request_proto"
2023-07-31 08:41:42 +08:00
apiproto "joylink.club/bj-rtsts-server/grpcproto"
2023-08-30 09:28:21 +08:00
"joylink.club/bj-rtsts-server/middleware"
"joylink.club/bj-rtsts-server/service"
"joylink.club/bj-rtsts-server/sys_error"
2023-07-28 14:36:16 +08:00
)
func InitSimulationRouter(api *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
2023-08-30 09:28:21 +08:00
authed := api.Group("/v1/simulation").Use(authMiddleware.MiddlewareFunc(), middleware.PermissMiddleware)
authed.POST("/createByProject", createByProjectId)
2023-07-28 17:24:58 +08:00
authed.POST("/destroy/:id", destroy)
authed.GET("/list", findAllSimulations)
authed.POST("/check/data", checkSimMapData)
2023-07-31 17:27:05 +08:00
authed.POST("/train/add", addTrain)
authed.POST("/train/remove", removeTrain)
authed.POST("/switch/operation", switchOperation)
2023-08-31 14:06:53 +08:00
authed.GET("/getDataChannelName", getDataChannelName)
2023-10-07 17:48:39 +08:00
authed.POST("/relay/operation", relayOperation)
2023-10-13 14:41:55 +08:00
authed.POST("/signal/operation", signalOperation)
2023-10-24 10:19:51 +08:00
authed.POST("/axleSection/operation", axleSectionOperation)
2023-10-18 13:53:17 +08:00
authed.POST("/esbBtn/operation", esbBtnOperation)
2023-10-20 13:50:22 +08:00
authed.POST("/ibp/btn/operation", ibpBtnOperation)
authed.POST("/ibp/key/operation", ibpKeyOperation)
2023-10-19 17:42:01 +08:00
authed.GET("/:id/getMapKilometerRange", getMapKilometerRange)
authed.POST("/psl/operation", pslBtnOperation)
2023-07-31 08:41:42 +08:00
// 初始化地图信息
initPublishMapInfo()
apiproto.InitClient()
apiproto.Register(&apiproto.SimulationServer{})
apiproto.Register(&apiproto.SimulationIBPServer{})
apiproto.Register(&apiproto.SimulationPSLServer{})
apiproto.Register(&apiproto.MemoryChangeServer{SimulationMap: make(map[string]*state.SimulationStatus)})
2023-07-28 14:36:16 +08:00
}
func initPublishMapInfo() {
2023-08-01 17:16:16 +08:00
mapArr, err := service.ListAllPublishedGi()
if err != nil {
panic("地图加载出错")
}
sort.SliceStable(mapArr, func(i, j int) bool { return mapArr[i].Type != 0 })
for _, v := range mapArr {
memory.PublishMapVerifyStructure(v)
}
}
// 创建ATS测试仿真通过项目ID
//
// @Summary 创建ATS测试仿真
//
// @Security JwtAuth
//
// @Description 创建ATS测试仿真通过项目ID
// @Tags ATS测试仿真Api
// @Accept json
// @Produce json
// @Param Authorization header string true "JWT Token"
// @Param SimulationCreateReqDto body dto.SimulationCreateReqDto true "创建仿真请求"
// @Success 200 {object} dto.SimulationCreateRspDto
// @Failure 500 {object} dto.ErrorDto
// @Router /api/v1/simulation/createByProject [post]
func createByProjectId(c *gin.Context) {
req := dto.SimulationCreateReqDto{}
if err := c.ShouldBind(&req); nil != err {
panic(sys_error.New("测试启动失败,请求参数异常", err))
}
2023-08-31 16:16:18 +08:00
mapInfos := service.QueryProjectPublishedGi(req.ProjectId)
if len(mapInfos) == 0 {
panic(sys_error.New("测试启动失败,项目未关联发布图"))
}
2023-09-19 11:02:50 +08:00
mapIds := make([]int32, len(mapInfos))
for i, mapInfo := range mapInfos {
mapIds[i] = mapInfo.ID
}
rsp := dto.SimulationCreateRspDto{ProjectId: req.ProjectId, MapId: mapIds[0], MapIds: mapIds}
simulationId, err := simulation.CreateSimulation(req.ProjectId, mapIds)
if err != nil {
panic(sys_error.New("测试启动失败", err))
}
rsp.SimulationId = simulationId
2023-07-28 14:36:16 +08:00
c.JSON(http.StatusOK, &rsp)
}
// ATS仿真销毁
//
// @Summary ATS仿真销毁
//
// @Security JwtAuth
//
// @Description ATS测试仿真-添加列车
// @Tags ATS测试仿真Api
// @Accept json
// @Produce json
// @Param Authorization header string true "JWT Token"
// @Param id path int true "仿真id"
// @Success 200 {object} string
// @Failure 500 {object} dto.ErrorDto
// @Router /api/v1/simulation/destroy/{id} [post]
func destroy(c *gin.Context) {
simId := c.Param("id")
slog.Debug("ATS测试仿真-ATS仿真销毁 请求:", simId)
simulation.DestroySimulation(simId)
c.JSON(http.StatusOK, "ok")
}
// 获取ATS测试系统所有仿真实例的基本信息
//
// @Summary 获取ATS测试系统所有仿真实例的基本信息
//
// @Security JwtAuth
//
// @Description 获取ATS测试系统所有仿真实例的基本信息
// @Tags ATS测试仿真Api
// @Accept json
// @Produce json
// @Param Authorization header string true "JWT Token"
// @Success 200 {object} dto.SimulationInfoRspDtoArr
// @Failure 500 {object} dto.ErrorDto
// @Router /api/v1/simulation/list [get]
func findAllSimulations(c *gin.Context) {
2023-08-01 14:54:11 +08:00
c.JSON(http.StatusOK, simulation.ListAllSimulations())
}
// ATS测试仿真地图数据校验
//
// @Summary ATS测试仿真地图数据校验
//
// @Security JwtAuth
//
// @Description 地图数据校验
// @Tags ATS测试仿真Api
// @Accept json
// @Produce json
// @Param Authorization header string true "JWT Token"
// @Param RemoveTrainDto body dto.CheckMapDataReqDto true "ATS测试仿真-地图数据"
//
// @Success 200 {object} dto.CheckMapDataRspDto
// @Failure 500 {object} dto.ErrorDto
// @Router /api/v1/simulation/check/data [post]
func checkSimMapData(c *gin.Context) {
2023-07-31 17:27:05 +08:00
rt := &dto.CheckMapDataReqDto{}
if err := c.ShouldBind(&rt); nil != err {
2023-10-20 18:08:06 +08:00
panic(sys_error.New("请求参数异常", err))
2023-07-31 17:27:05 +08:00
}
err := proto.Unmarshal(rt.Data, &graphicData.RtssGraphicStorage{})
if err != nil {
2023-10-20 18:08:06 +08:00
panic(sys_error.New("非平面布置图数据"))
}
2023-08-31 16:16:18 +08:00
c.JSON(http.StatusOK, &dto.CheckMapDataRspDto{Success: true})
}
2023-07-31 17:27:05 +08:00
// ATS测试仿真-添加列车
//
// @Summary ATS测试仿真-添加列车
//
// @Security JwtAuth
//
// @Description ATS测试仿真-添加列车
// @Tags ATS测试仿真Api
// @Accept json
// @Produce json
// @Param Authorization header string true "JWT Token"
// @Param AddTrainReqDto body dto.AddTrainReqDto true "ATS测试仿真-添加列车"
// @Success 200 {object} dto.AddTrainRspDto
// @Failure 500 {object} dto.ErrorDto
// @Router /api/v1/simulation/train/add [post]
func addTrain(c *gin.Context) {
req := dto.AddTrainReqDto{}
if err := c.ShouldBind(&req); err != nil {
2023-10-20 18:08:06 +08:00
panic(sys_error.New("添加列车失败,请求参数异常", err))
2023-07-31 17:27:05 +08:00
}
simulation := checkDeviceDataAndReturn(req.SimulationId)
2023-08-22 16:44:34 +08:00
id := getAddTrainPrimaryKey(simulation)
if id == -1 {
2023-10-20 18:08:06 +08:00
panic(sys_error.New("添加列车失败,已有列车在运行"))
2023-07-31 17:27:05 +08:00
}
2023-08-31 16:16:18 +08:00
rsp := &state.TrainState{
Id: strconv.Itoa(id),
HeadDeviceId: req.Id,
HeadOffset: req.HeadOffset,
DevicePort: req.DevicePort,
RunDirection: req.RunDirection,
TrainLength: req.TrainLength,
}
2023-09-21 17:57:50 +08:00
memory.AddTrainState(simulation, rsp, req.MapId)
2023-08-31 16:16:18 +08:00
c.JSON(http.StatusOK, &rsp)
2023-07-31 17:27:05 +08:00
}
2023-07-28 16:14:31 +08:00
// ATS测试仿真-移除列车
//
2023-07-28 16:14:31 +08:00
// @Summary ATS测试仿真-移除列车
//
// @Security JwtAuth
//
2023-07-28 16:14:31 +08:00
// @Description ATS测试仿真-移除列车
// @Tags ATS测试仿真Api
// @Accept json
// @Produce json
// @Param Authorization header string true "JWT Token"
// @Param RemoveTrainDto body dto.RemoveTrainDto true "ATS测试仿真-移除列车"
//
// @Success 200 {object} string
// @Failure 500 {object} dto.ErrorDto
// @Router /api/v1/simulation/train/remove [post]
func removeTrain(c *gin.Context) {
rt := &dto.RemoveTrainDto{}
2023-07-31 17:27:05 +08:00
if err := c.ShouldBind(&rt); err != nil {
2023-10-20 18:08:06 +08:00
panic(sys_error.New("移除列车失败,请求参数异常", err))
}
slog.Debug("ATS测试仿真-移除列车,请求:", rt)
simulation := checkDeviceDataAndReturn(rt.SimulationId)
memory.RemoveTrainState(simulation, rt.TrainId)
2023-07-31 17:27:05 +08:00
//TODO 后续调用列车删除操作
c.JSON(http.StatusOK, "ok")
}
// 获取ATS测试-操作道岔
//
// @Summary 获取ATS测试-操作道岔
//
// @Security JwtAuth
//
// @Description ATS测试-操作道岔
// @Tags ATS测试仿真Api
// @Accept json
// @Produce json
// @Param Authorization header string true "JWT Token"
2023-10-16 09:05:37 +08:00
// @Param TurnoutOperationReq body request_proto.TurnoutOperationReq true "ATS测试仿真-操作道岔"
//
// @Success 200 {object} string
// @Failure 500 {object} dto.ErrorDto
// @Router /api/v1/simulation/switch/operation [post]
func switchOperation(c *gin.Context) {
2023-10-13 17:43:48 +08:00
req := &request_proto.TurnoutOperationReq{}
2023-07-31 17:27:05 +08:00
if err := c.ShouldBind(&req); err != nil {
2023-10-20 18:08:06 +08:00
panic(sys_error.New("道岔操作失败,请求参数异常", err))
2023-07-31 17:27:05 +08:00
}
simulation := checkDeviceDataAndReturn(req.SimulationId)
slog.Info("传入状态参数", "request", req)
2023-10-13 17:43:48 +08:00
memory.HandleTurnoutOperation(simulation, req)
2023-07-31 17:27:05 +08:00
c.JSON(http.StatusOK, "ok")
}
2023-10-13 14:41:55 +08:00
// ATS测试-信号机操作
//
// @Summary ATS测试-信号机操作
//
// @Security JwtAuth
//
// @Description ATS测试-信号机操作
// @Tags ATS测试仿真Api
// @Accept json
// @Produce json
// @Param Authorization header string true "JWT Token"
// @Param SignalOperationReqDto body dto.SignalOperationReqDto true "ATS测试仿真-操作信号机"
//
// @Success 200 {object} string
// @Failure 500 {object} dto.ErrorDto
// @Router /api/v1/simulation/signal/operation [post]
func signalOperation(c *gin.Context) {
req := &dto.SignalOperationReqDto{}
if err := c.ShouldBind(&req); err != nil {
2023-10-24 10:19:51 +08:00
panic(sys_error.New("输入参数格式错误", err))
2023-10-13 14:41:55 +08:00
}
2023-10-16 10:37:59 +08:00
simulation := checkDeviceDataAndReturn(req.SimulationId)
2023-10-13 14:41:55 +08:00
slog.Info("传入状态参数", req)
2023-10-19 15:08:43 +08:00
memory.ChangeSignalState(simulation, req)
2023-10-13 14:41:55 +08:00
c.JSON(http.StatusOK, "ok")
}
2023-10-24 10:19:51 +08:00
// ATS测试-计轴区段操作
//
// @Summary ATS测试-计轴区段操作
//
// @Security JwtAuth
//
// @Description ATS测试-计轴区段操作
// @Tags ATS测试仿真Api
// @Accept json
// @Produce json
// @Param Authorization header string true "JWT Token"
// @Param AxleSectionOperationReqDto body dto.AxleSectionOperationReqDto true "ATS测试仿真-操作计轴区段"
//
// @Success 200 {object} string
// @Failure 500 {object} dto.ErrorDto
// @Router /api/v1/simulation/axleSection/operation [post]
func axleSectionOperation(c *gin.Context) {
req := &dto.AxleSectionOperationReqDto{}
if err := c.ShouldBind(&req); err != nil {
panic(sys_error.New("输入参数格式错误", err))
}
simulation := checkDeviceDataAndReturn(req.SimulationId)
slog.Info("传入状态参数", req)
memory.ChangeAxleSectionState(simulation, req)
c.JSON(http.StatusOK, "ok")
}
2023-10-18 13:53:17 +08:00
// ATS测试-ESB按钮操作
//
// @Summary ATS测试-ESB按钮操作
//
// @Security JwtAuth
//
// @Description ATS测试-ESB按钮操作
// @Tags ATS测试仿真Api
// @Accept json
// @Produce json
// @Param Authorization header string true "JWT Token"
2023-10-20 13:50:22 +08:00
// @Param EsbButtonOperationReqDto body dto.EsbButtonOperationReqDto true "ATS测试仿真-ESB按钮操作"
2023-10-18 13:53:17 +08:00
//
// @Success 200 {object} string
// @Failure 500 {object} dto.ErrorDto
// @Router /api/v1/simulation/esbBtn/operation [post]
func esbBtnOperation(c *gin.Context) {
2023-10-20 13:50:22 +08:00
req := &dto.EsbButtonOperationReqDto{}
2023-10-18 13:53:17 +08:00
if err := c.ShouldBind(&req); err != nil {
2023-10-20 18:08:06 +08:00
panic(sys_error.New("紧急关闭按钮操作失败,请求参数异常", err))
2023-10-18 13:53:17 +08:00
}
simulation := checkDeviceDataAndReturn(req.SimulationId)
slog.Info("传入状态参数", req)
memory.ChangeEsbButtonState(simulation, req.MapId, req.Id, req.Down)
c.JSON(http.StatusOK, "ok")
}
// ATS测试-IBP按钮操作
//
// @Summary ATS测试-IBP按钮操作
//
// @Security JwtAuth
//
// @Description ATS测试-IBP按钮操作
// @Tags ATS测试仿真Api
// @Accept json
// @Produce json
// @Param Authorization header string true "JWT Token"
2023-10-20 13:50:22 +08:00
// @Param IBPButtonOperationReqDto body dto.IBPButtonOperationReqDto true "ATS测试仿真-IBP按钮操作"
2023-10-18 13:53:17 +08:00
//
// @Success 200 {object} string
// @Failure 500 {object} dto.ErrorDto
2023-10-20 13:50:22 +08:00
// @Router /api/v1/simulation/ibp/btn/operation [post]
2023-10-18 13:53:17 +08:00
func ibpBtnOperation(c *gin.Context) {
2023-10-20 13:50:22 +08:00
req := &dto.IBPButtonOperationReqDto{}
if err := c.ShouldBind(&req); err != nil {
2023-10-20 18:08:06 +08:00
panic(sys_error.New("IBP按钮操作失败请求参数异常", err))
2023-10-20 13:50:22 +08:00
}
simulation := checkDeviceDataAndReturn(req.SimulationId)
slog.Info("传入状态参数", req)
memory.ChangeIBPButtonState(simulation, req.MapId, req.StationId, req.ButtonCode, req.Down)
c.JSON(http.StatusOK, "ok")
}
// ATS测试-IBP钥匙操作
//
// @Summary ATS测试-IBP钥匙操作
//
// @Security JwtAuth
//
// @Description ATS测试-IBP钥匙操作
// @Tags ATS测试仿真Api
// @Accept json
// @Produce json
// @Param Authorization header string true "JWT Token"
// @Param KeyOperationReqDto body dto.KeyOperationReqDto true "ATS测试仿真-IBP钥匙操作"
//
// @Success 200 {object} string
// @Failure 500 {object} dto.ErrorDto
// @Router /api/v1/simulation/ibp/key/operation [post]
func ibpKeyOperation(c *gin.Context) {
req := &dto.KeyOperationReqDto{}
2023-10-18 13:53:17 +08:00
if err := c.ShouldBind(&req); err != nil {
2023-10-20 18:08:06 +08:00
panic(sys_error.New("IBP开关操作失败请求参数异常", err))
2023-10-18 13:53:17 +08:00
}
simulation := checkDeviceDataAndReturn(req.SimulationId)
slog.Info("传入状态参数", req)
2023-10-20 13:50:22 +08:00
memory.ChangeIBPKeyState(simulation, req.MapId, req.StationId, req.KeyCode, req.Gear)
2023-10-18 13:53:17 +08:00
c.JSON(http.StatusOK, "ok")
2023-10-13 14:41:55 +08:00
}
// PSL操作
//
// @Summary PSL操作
//
// @Security JwtAuth
//
// @Description PSL操作
// @Tags ATS测试仿真Api
// @Accept json
// @Produce json
// @Param Authorization header string true "JWT Token"
2023-10-20 13:50:22 +08:00
// @Param PslOperationReqDto body dto.PslOperationReqDto true "PSL操作"
//
// @Success 200 {object} string
// @Failure 500 {object} dto.ErrorDto
// @Router /api/v1/simulation/ibp/operation [post]
func pslBtnOperation(c *gin.Context) {
req := &dto.PslOperationReqDto{}
2023-10-18 13:53:17 +08:00
if err := c.ShouldBind(&req); err != nil {
panic(dto.ErrorDto{Code: dto.ArgumentParseError, Message: err.Error()})
}
simulation := checkDeviceDataAndReturn(req.SimulationId)
slog.Info("传入状态参数", req)
memory.ChangePSLButtonState(simulation, req.MapId, req.GateBoxId, req.ButtonCode, req.Down)
2023-10-18 13:53:17 +08:00
c.JSON(http.StatusOK, "ok")
2023-10-13 14:41:55 +08:00
}
2023-08-31 14:06:53 +08:00
// 获取仿真信息更新通道名称
//
// @Summary 获取仿真信息更新通道名称
//
// @Security JwtAuth
//
// @Description 获取仿真信息更新通道名称
// @Tags ATS测试仿真Api
// @Accept json
// @Produce json
// @Param Authorization header string true "JWT Token"
//
// @Success 200 {object} string
// @Failure 500 {object} dto.ErrorDto
// @Router /api/v1/simulation/getDataChannelName [get]
func getDataChannelName(c *gin.Context) {
c.JSON(http.StatusOK, config.SimulationId_prefix+apiproto.MemoryChangeServerSuffix)
}
2023-10-19 17:42:01 +08:00
// 获取仿真地图的公里标范围
//
// @Summary 获取仿真地图的公里标范围
//
// @Security JwtAuth
//
// @Description 获取仿真地图的公里标范围
// @Tags ATS测试仿真Api
// @Accept json
// @Produce json
// @Param Authorization header string true "JWT Token"
//
// @Success 200 {object} string
// @Failure 500 {object} dto.ErrorDto
// @Router /api/v1/simulation/:id/getMapKilometerRange [get]
func getMapKilometerRange(c *gin.Context) {
id, exist := c.Params.Get("id")
if !exist {
2023-10-20 18:08:06 +08:00
panic(sys_error.New("缺少仿真编号"))
2023-10-19 17:42:01 +08:00
}
simulation := checkDeviceDataAndReturn(id)
c.JSON(http.StatusOK, simulation.Repo.GetCoordinateInfo())
}
2023-10-07 17:48:39 +08:00
// 获取ATS测试-操作继电器
//
// @Summary 获取ATS测试-操作继电器
//
// @Security JwtAuth
//
// @Description ATS测试-操作继电器
// @Tags ATS测试仿真Api
// @Accept json
// @Produce json
// @Param Authorization header string true "JWT Token"
// @Param RelayOperationReqDto body dto.RelayOperationReqDto true "ATS测试仿真-操作继电器"
//
// @Success 200 {object} string
// @Failure 500 {object} dto.ErrorDto
// @Router /api/v1/simulation/relay/operation [post]
func relayOperation(c *gin.Context) {
req := &dto.RelayOperationReqDto{}
if err := c.ShouldBind(&req); err != nil {
2023-10-20 18:08:06 +08:00
panic(sys_error.New("继电器操作失败,请求参数异常", err))
2023-10-07 17:48:39 +08:00
}
simulation := checkDeviceDataAndReturn(req.SimulationId)
slog.Info("传入状态参数", req)
2023-10-07 17:51:00 +08:00
memory.ChangeRelayState(simulation, req.MapId, req.Id, req.Td)
2023-10-07 17:48:39 +08:00
c.JSON(http.StatusOK, "ok")
}
2023-07-31 17:27:05 +08:00
// 获取仿真设备数据并返回
2023-08-01 14:54:11 +08:00
func checkDeviceDataAndReturn(simId string) *memory.VerifySimulation {
2023-07-31 17:27:05 +08:00
deviceMemory := simulation.FindSimulation(simId)
if deviceMemory == nil {
2023-10-20 18:08:06 +08:00
panic(sys_error.New(fmt.Sprintf("仿真[%s]不存在", simId)))
}
2023-07-31 17:27:05 +08:00
return deviceMemory
}
2023-08-22 16:44:34 +08:00
// 获取列车主键
func getAddTrainPrimaryKey(simulation *memory.VerifySimulation) int {
trainMap := &simulation.Memory.Status.TrainStateMap
// 获取列车ID
i := 1
for {
_, ok := trainMap.Load(strconv.Itoa(i))
2023-08-31 16:16:18 +08:00
if !ok {
break
}
i++
2023-08-22 16:44:34 +08:00
}
return i
}