【修改缓存逻辑】

This commit is contained in:
weizhihong 2023-09-21 16:22:55 +08:00
parent 535cb0c429
commit 5aba1de2f2
8 changed files with 42 additions and 310 deletions

View File

@ -23,7 +23,6 @@ import (
func InitSimulationRouter(api *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { func InitSimulationRouter(api *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
authed := api.Group("/v1/simulation").Use(authMiddleware.MiddlewareFunc(), middleware.PermissMiddleware) authed := api.Group("/v1/simulation").Use(authMiddleware.MiddlewareFunc(), middleware.PermissMiddleware)
authed.POST("/createByProject", createByProjectId) authed.POST("/createByProject", createByProjectId)
authed.GET("/state/:id", findSimulationState)
authed.POST("/destroy/:id", destroy) authed.POST("/destroy/:id", destroy)
authed.GET("/list", findAllSimulations) authed.GET("/list", findAllSimulations)
authed.POST("/check/data", checkSimMapData) authed.POST("/check/data", checkSimMapData)
@ -34,8 +33,7 @@ func InitSimulationRouter(api *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddle
// 初始化地图信息 // 初始化地图信息
initPublishMapInfo() initPublishMapInfo()
//apiproto.RegisterMsgServer(&apiproto.SimulationServer{}) apiproto.RegisterMsgServer(&apiproto.SimulationServer{})
apiproto.RegisterMsgServer(&apiproto.SimulationMapServer{})
apiproto.RegisterMsgServer(&apiproto.MemoryChangeServer{SimulationMap: make(map[string]*state.SimulationStatus)}) apiproto.RegisterMsgServer(&apiproto.MemoryChangeServer{SimulationMap: make(map[string]*state.SimulationStatus)})
} }
@ -82,28 +80,6 @@ func createByProjectId(c *gin.Context) {
c.JSON(http.StatusOK, &rsp) c.JSON(http.StatusOK, &rsp)
} }
// 创建并进入仿真后获取仿真的设备信息
//
// @Summary 创建并进入仿真后获取仿真的设备信息
//
// @Security JwtAuth
//
// @Description 创建并进入仿真后获取仿真的设备信息
// @Tags ATS测试仿真Api
// @Accept json
// @Produce json
// @Param Authorization header string true "JWT Token"
// @Param id path int true "仿真id"
// @Success 200 {object} dto.SimulationCreateRspDto
// @Failure 500 {object} dto.ErrorDto
// @Router /api/v1/simulation/state/:id [get]
func findSimulationState(c *gin.Context) {
simId := c.Param("id")
simulation := checkDeviceDataAndReturn(simId)
allState := simulation.GetAllState()
c.JSON(http.StatusOK, allState)
}
// ATS仿真销毁 // ATS仿真销毁
// //
// @Summary ATS仿真销毁 // @Summary ATS仿真销毁
@ -266,7 +242,7 @@ func switchOperation(c *gin.Context) {
Id: req.SwitchIndex, Id: req.SwitchIndex,
Normal: req.TurnNormal, Normal: req.TurnNormal,
Reverse: req.TurnReverse, Reverse: req.TurnReverse,
}) }, req.MapId)
c.JSON(http.StatusOK, "ok") c.JSON(http.StatusOK, "ok")
} }

View File

@ -411,7 +411,6 @@ Outter:
// 设备ID、端口、偏移量、上下行、AB走向 // 设备ID、端口、偏移量、上下行、AB走向
func QueryDeviceByCalcLink(repo *repository.Repository, id string, offset int64, up bool) ( func QueryDeviceByCalcLink(repo *repository.Repository, id string, offset int64, up bool) (
deviceId, port string, deviceOffset int64, runDirection, pointTo bool, km int64) { deviceId, port string, deviceOffset int64, runDirection, pointTo bool, km int64) {
link := repo.FindLink(id) link := repo.FindLink(id)
if link == nil { if link == nil {
panic(dto.ErrorDto{Code: dto.DataNotExist, Message: fmt.Sprintf("未找到link【%s】", id)}) panic(dto.ErrorDto{Code: dto.DataNotExist, Message: fmt.Sprintf("未找到link【%s】", id)})
@ -459,119 +458,6 @@ func QueryDeviceByCalcLink(repo *repository.Repository, id string, offset int64,
return return
} }
//// 根据linkID和link相对偏移量返回区段道岔偏移量
//// 设备ID、端口、偏移量、上下行、AB走向
//func QueryDeviceByCalcLink(vm *VerifyStructure, id int32, offset int64, up, defaultRunDirection bool) (string, string, int64, bool, bool, int64) {
// linkModel := vm.LinkModelMap[id]
// if linkModel == nil {
// panic(dto.ErrorDto{Code: dto.DataNotExist, Message: fmt.Sprintf("未找到link【%d】", id)})
// }
// if offset > int64(linkModel.Length) {
// panic(dto.ErrorDto{Code: dto.DataNotExist, Message: fmt.Sprintf("偏移超出link范围【%d】", id)})
// }
// calcPositionArr := convertPositionToCalcPosition(linkModel) // 转换位置对象
// var devicePosition, calcPosition *calcLinkPositionStruct // 获取当前、下一个节点,偏移量在这个范围中
// for _, v := range calcPositionArr {
// if v.position.Offset > int32(offset) {
// calcPosition = v
// break
// } else {
// devicePosition = v
// }
// }
// // 运行方向
// var runDirection bool
// if calcPosition != nil {
// runDirection = (calcPosition.kilometer.Kilometer >= devicePosition.kilometer.Kilometer) == up
// } else {
// runDirection = defaultRunDirection
// }
// isSwitch := (devicePosition.deviceType == 2) // 道岔
// // 获取另一个端点
// if calcPosition != nil {
// isSwitch = isSwitch || calcPosition.deviceType == 2 // 道岔
// }
// if isSwitch {
// var sid string
// var port string
// var op int64
// var trainOffset int64
// var trainKilometer int64
// var tendTo bool
// if devicePosition.deviceType == 2 {
// sid = devicePosition.index
// op = int64(devicePosition.position.Offset)
// trainKilometer = devicePosition.kilometer.Kilometer
// } else {
// sid = calcPosition.index
// op = int64(calcPosition.position.Offset)
// trainKilometer = calcPosition.kilometer.Kilometer
// }
// tm := vm.SwitchDeviceModelMap[sid]
// if tm == nil {
// panic(dto.ErrorDto{Code: dto.DataNotExist, Message: fmt.Sprintf("不存在道岔【index:%s】", sid)})
// }
// if linkModel.ARelatedSwitchRef.SwitchDevice != nil && linkModel.ARelatedSwitchRef.SwitchDevice.GetIndex() == sid { // 起始点
// port, trainOffset, tendTo = linkModel.ARelatedSwitchRef.Port.Name(), offset-op, !up
// } else if linkModel.BRelatedSwitchRef.SwitchDevice != nil && linkModel.BRelatedSwitchRef.SwitchDevice.GetIndex() == sid { // 结束点
// port, trainOffset, tendTo = linkModel.BRelatedSwitchRef.Port.Name(), op-offset, up
// } else {
// panic(dto.ErrorDto{Code: dto.DataNotExist, Message: fmt.Sprintf("不存在道岔【index:%s】", devicePosition.index)})
// }
// trainKilometer = concertTrainKilometer(trainKilometer, trainOffset, tendTo)
// // return sid, linkModel.ARelatedSwitchRef.Port.Name(), offset - op, runDirection, !up
// // return sid, linkModel.BRelatedSwitchRef.Port.Name(), op - offset, runDirection, up
// return sid, port, trainOffset, runDirection, tendTo, trainKilometer
// } else {
// sectionModel, ok := linkOffsetQuerySection(vm, devicePosition, calcPosition)
// if ok {
// isEnd := (calcPosition == nil) && (offset == int64(linkModel.Length)) // 是否已经走到尽头
// pointA := sectionModel.PortAxlePoints[face.A.Name()]
// var trainOffset int64
// var trainKilometer int64
// var tendTo bool
// var bk *graphicData.KilometerSystem
// if calcPosition != nil {
// bk = calcPosition.kilometer
// }
// if devicePosition.index == pointA.GetIndex() {
// trainOffset = offset - int64(devicePosition.position.Offset)
// trainKilometer = devicePosition.kilometer.Kilometer
// tendTo = convertPointTo(devicePosition.kilometer, bk, runDirection)
// } else if calcPosition != nil {
// trainOffset = int64(calcPosition.position.Offset) - offset
// trainKilometer = bk.Kilometer
// tendTo = convertPointTo(bk, devicePosition.kilometer, runDirection)
// } else {
// for _, v := range calcPositionArr {
// if v.deviceType == 1 && v.index == pointA.GetIndex() { // 计轴
// trainKilometer = v.kilometer.Kilometer
// if isEnd {
// trainOffset = offset - int64(v.position.Offset)
// tendTo = convertPointTo(v.kilometer, nil, runDirection)
// } else {
// trainOffset = int64(v.position.Offset) - offset
// tendTo = convertPointTo(v.kilometer, devicePosition.kilometer, runDirection)
// }
// break
// }
// }
// if trainKilometer == 0 {
// panic(dto.ErrorDto{Code: dto.DataNotExist, Message: fmt.Sprintf("区段【%s】A端计轴缺失", sectionModel.GraphicId)})
// }
// }
// trainKilometer = concertTrainKilometer(trainKilometer, trainOffset, tendTo)
// // return sectionModel.Index, "", offset - int64(devicePosition.position.Offset), runDirection, convertPointTo(devicePosition.kilometer, bk, runDirection)
// // return sectionModel.Index, "", int64(calcPosition.position.Offset) - offset, runDirection, convertPointTo(bk, devicePosition.kilometer, runDirection)
// // return sectionModel.Index, "", offset - int64(v.position.Offset), runDirection, convertPointTo(v.kilometer, nil, runDirection)
// // return sectionModel.Index, "", int64(v.position.Offset) - offset, runDirection, convertPointTo(v.kilometer, devicePosition.kilometer, runDirection)
// return sectionModel.Index, "", trainOffset, runDirection, tendTo, trainKilometer
// } else {
// panic(dto.ErrorDto{Code: dto.DataNotExist, Message: fmt.Sprintf("未找到区段【index:%s-index:%s】", devicePosition.index, calcPosition.index)})
// }
// }
//}
// 将linkPosition转换为计算对象 // 将linkPosition转换为计算对象
func convertPositionToCalcPosition(link *device.LinkModel) []*calcLinkPositionStruct { func convertPositionToCalcPosition(link *device.LinkModel) []*calcLinkPositionStruct {
result := []*calcLinkPositionStruct{} result := []*calcLinkPositionStruct{}

View File

@ -8,7 +8,7 @@ import (
) )
// 物理区段状态更新 // 物理区段状态更新
func ChangePhysicalSectionState(simulation *VerifySimulation, status *state.SectionState) { func ChangePhysicalSectionState(simulation *VerifySimulation, status *state.SectionState, mapId int32) {
allSectionMap := &simulation.Memory.Status.PhysicalSectionStateMap allSectionMap := &simulation.Memory.Status.PhysicalSectionStateMap
d, ok := allSectionMap.Load(status.Id) d, ok := allSectionMap.Load(status.Id)
if !ok { if !ok {
@ -23,18 +23,7 @@ func ChangePhysicalSectionState(simulation *VerifySimulation, status *state.Sect
} }
// 获取全部的物理区段状态 // 获取全部的物理区段状态
func GetAllPhysicalSectionState(simulation *VerifySimulation) []*state.SectionState { func GetAllPhysicalSectionState(simulation *VerifySimulation, mapId int32) []*state.SectionState {
allSectionMap := &simulation.Memory.Status.PhysicalSectionStateMap
var sectionArr []*state.SectionState
allSectionMap.Range(func(_, v any) bool {
sectionArr = append(sectionArr, v.(*state.SectionState))
return true
})
return sectionArr
}
// 获取地图全部的物理区段状态
func GetMapAllPhysicalSectionState(simulation *VerifySimulation, mid string) []*state.SectionState {
var sectionArr []*state.SectionState var sectionArr []*state.SectionState
return sectionArr return sectionArr
} }

View File

@ -2,27 +2,21 @@ package memory
import ( import (
"fmt" "fmt"
"sync" "strconv"
"google.golang.org/protobuf/proto" "joylink.club/bj-rtsts-server/ats/verify/protos/graphicData"
"joylink.club/bj-rtsts-server/ats/verify/protos/state" "joylink.club/bj-rtsts-server/ats/verify/protos/state"
"joylink.club/bj-rtsts-server/dto"
) )
// 道岔相关道岔操作方法 // 道岔相关道岔操作方法
func ChangeTurnoutState(simulation *VerifySimulation, status *state.SwitchState) { func ChangeTurnoutState(simulation *VerifySimulation, status *state.SwitchState, mapId int32) {
allSwitchMap := &simulation.Memory.Status.SwitchStateMap index, err := strconv.Atoi(status.Id)
d, ok := allSwitchMap.Load(status.Id) if err != nil {
if !ok { panic(&dto.ErrorDto{Code: dto.ArgumentParseError, Message: "参数转换出错"})
panic(fmt.Sprintf("道岔【%s】不存在", status.Id))
}
cur := d.(*state.SwitchState)
if !proto.Equal(cur, status) { // 如果信息发送了变化
// 将信息合并到当前设备状态中
cur.Normal = status.Normal
cur.Reverse = status.Reverse
// 将变更信息放入变更状态队列中
simulation.Memory.ChangeStatus.SwitchStateMap.Store(status.Id, proto.Clone(cur))
} }
uid := GetDeviceUidByIndex(mapId, int32(index), &graphicData.Turnout{})
fmt.Printf("修改道岔【UID:%s】\n", uid)
} }
// 获取全部的道岔状态 // 获取全部的道岔状态
@ -37,31 +31,7 @@ func GetAllTurnoutState(simulation *VerifySimulation) []*state.SwitchState {
} }
// 获取仿真地图的道岔状态 // 获取仿真地图的道岔状态
func GetMapAllTurnoutState(simulation *VerifySimulation, mid string) []*state.SwitchState { func GetMapAllTurnoutState(simulation *VerifySimulation, mapId int32) []*state.SwitchState {
var switchArr []*state.SwitchState var switchArr []*state.SwitchState
return switchArr return switchArr
} }
// 获取增量道岔状态
func GetChangeTurnoutState(simulation *VerifySimulation) []*state.SwitchState {
changeSwitchMap := &simulation.Memory.ChangeStatus.SwitchStateMap
var switchArr []*state.SwitchState
changeSwitchMap.Range(func(_, v any) bool {
d := v.(*state.SwitchState)
switchArr = append(switchArr, &state.SwitchState{
Id: d.Id,
Normal: d.Normal,
Reverse: d.Reverse,
})
return true
})
if len(switchArr) > 0 {
simulation.Memory.ChangeStatus.SwitchStateMap = sync.Map{}
}
return switchArr
}
func GetTurnoutState(simulation *VerifySimulation, turnoutId string) *state.SwitchState {
v, _ := simulation.Memory.Status.SwitchStateMap.Load(turnoutId)
return v.(*state.SwitchState)
}

View File

@ -75,25 +75,13 @@ func CreateSimulation(projectId int32, mapIds []int32) (*VerifySimulation, error
} }
// 获取全量状态 // 获取全量状态
func (s *VerifySimulation) GetAllState() *state.PushedDevicesStatus { func (s *VerifySimulation) GetAllState(mapId int32) *state.PushedDevicesStatus {
return &state.PushedDevicesStatus{ return &state.PushedDevicesStatus{
All: true, All: true,
AllStatus: &state.AllDevicesStatus{ AllStatus: &state.AllDevicesStatus{
SwitchState: GetAllTurnoutState(s), SwitchState: GetMapAllTurnoutState(s, mapId),
TrainState: GetAllTrainState(s), TrainState: GetAllTrainState(s),
SectionState: append(GetAllAxleSectionState(s), GetAllPhysicalSectionState(s)...), SectionState: append(GetAllAxleSectionState(s), GetAllPhysicalSectionState(s, mapId)...),
},
}
}
// 获取仿真地图数据
func (s *VerifySimulation) GetMapAllState(mid string) *state.PushedDevicesStatus {
return &state.PushedDevicesStatus{
All: true,
AllStatus: &state.AllDevicesStatus{
SwitchState: GetMapAllTurnoutState(s, mid),
TrainState: GetMapAllTrainState(s, mid),
SectionState: GetMapAllPhysicalSectionState(s, mid),
}, },
} }
} }

View File

@ -1,70 +0,0 @@
package apiproto
import (
"strconv"
"strings"
"time"
"google.golang.org/protobuf/proto"
"joylink.club/bj-rtsts-server/ats/verify/simulation"
"joylink.club/bj-rtsts-server/dto"
)
type SimulationMapServer struct{}
// 返回通道格式
func (t *SimulationMapServer) getChannelName() string {
return "simulation-{sid}_{mid}-devices-status"
}
// 消息运行间隔
func (t *SimulationMapServer) getInterval() time.Duration {
return 200 * time.Millisecond
}
// 返回所有数据
func (t *SimulationMapServer) allMsgData(params map[string]string) []byte {
simId := params["SID"]
if simId == "" {
return nil
}
mId := params["MID"]
if mId == "" {
return nil
}
simulation := simulation.FindSimulation(simId)
if simulation == nil {
return nil
}
data, err := proto.Marshal(simulation.GetMapAllState(mId))
if err != nil {
panic(dto.ErrorDto{Code: dto.DataOperationError, Message: err.Error()})
}
return data
}
// 定时发送数据
func (t *SimulationMapServer) onTick() []TopicMsg {
simArr := simulation.GetSimulationArr()
var msgArr []TopicMsg
for _, v := range simArr {
for _, mapId := range v.MapIds {
idStr := strconv.Itoa(int(mapId))
channelName := handlerMapIdChannelName(v.SimulationId, idStr, t.getChannelName())
b, err := proto.Marshal(v.GetMapAllState(idStr))
if err != nil {
panic(dto.ErrorDto{Code: dto.DataOperationError, Message: err.Error()})
}
msgArr = append(msgArr, TopicMsg{channalName: channelName, data: b})
}
}
return msgArr
}
// 处理订阅通道名称
func handlerMapIdChannelName(sid, mapId string, format string) string {
var channelName string
channelName = strings.Replace(format, "{sid}", sid, 1)
channelName = strings.Replace(channelName, "{mid}", mapId, 1)
return channelName
}

View File

@ -1,6 +1,7 @@
package apiproto package apiproto
import ( import (
"strconv"
"strings" "strings"
"time" "time"
@ -13,7 +14,7 @@ type SimulationServer struct{}
// 返回通道格式 // 返回通道格式
func (t *SimulationServer) getChannelName() string { func (t *SimulationServer) getChannelName() string {
return "simulation-{sid}-devices-status" return "simulation-{sid}_{mid}-devices-status"
} }
// 消息运行间隔 // 消息运行间隔
@ -27,11 +28,16 @@ func (t *SimulationServer) allMsgData(params map[string]string) []byte {
if simId == "" { if simId == "" {
return nil return nil
} }
mId := params["MID"]
if mId == "" {
return nil
}
simulation := simulation.FindSimulation(simId) simulation := simulation.FindSimulation(simId)
if simulation == nil { if simulation == nil {
return nil return nil
} }
data, err := proto.Marshal(simulation.GetAllState()) mapId, _ := strconv.Atoi(mId)
data, err := proto.Marshal(simulation.GetAllState(int32(mapId)))
if err != nil { if err != nil {
panic(dto.ErrorDto{Code: dto.DataOperationError, Message: err.Error()}) panic(dto.ErrorDto{Code: dto.DataOperationError, Message: err.Error()})
} }
@ -41,19 +47,25 @@ func (t *SimulationServer) allMsgData(params map[string]string) []byte {
// 定时发送数据 // 定时发送数据
func (t *SimulationServer) onTick() []TopicMsg { func (t *SimulationServer) onTick() []TopicMsg {
simArr := simulation.GetSimulationArr() simArr := simulation.GetSimulationArr()
msgArr := make([]TopicMsg, len(simArr)) var msgArr []TopicMsg
for i, v := range simArr { for _, v := range simArr {
channelName := handlerChannelName(v.SimulationId, t.getChannelName()) for _, mapId := range v.MapIds {
b, err := proto.Marshal(v.GetAllState()) idStr := strconv.Itoa(int(mapId))
if err != nil { channelName := handlerChannelName(v.SimulationId, idStr, t.getChannelName())
panic(dto.ErrorDto{Code: dto.DataOperationError, Message: err.Error()}) b, err := proto.Marshal(v.GetAllState(mapId))
if err != nil {
panic(dto.ErrorDto{Code: dto.DataOperationError, Message: err.Error()})
}
msgArr = append(msgArr, TopicMsg{channalName: channelName, data: b})
} }
msgArr[i] = TopicMsg{channalName: channelName, data: b}
} }
return msgArr return msgArr
} }
// 处理订阅通道名称 // 处理订阅通道名称
func handlerChannelName(sid string, format string) string { func handlerChannelName(sid, mapId string, format string) string {
return strings.Replace(format, "{sid}", sid, 1) var channelName string
channelName = strings.Replace(format, "{sid}", sid, 1)
channelName = strings.Replace(channelName, "{mid}", mapId, 1)
return channelName
} }

View File

@ -4,8 +4,6 @@ import (
"fmt" "fmt"
"time" "time"
"google.golang.org/protobuf/proto"
"joylink.club/bj-rtsts-server/ats/verify/protos/graphicData"
"joylink.club/bj-rtsts-server/ats/verify/simulation/wayside/memory" "joylink.club/bj-rtsts-server/ats/verify/simulation/wayside/memory"
"joylink.club/bj-rtsts-server/db/dbquery" "joylink.club/bj-rtsts-server/db/dbquery"
"joylink.club/bj-rtsts-server/db/model" "joylink.club/bj-rtsts-server/db/model"
@ -69,7 +67,7 @@ func PublishFormDraft(req *publishedGi.PublishReqDto, user *model.User) {
} }
entity := model.PublishedGi{ entity := model.PublishedGi{
Name: req.Name, Name: req.Name,
Proto: handlerPublishedGiLinkData(draft.Proto, false), Proto: draft.Proto,
UserID: user.ID, UserID: user.ID,
PublishAt: time.Now(), PublishAt: time.Now(),
Category: draft.Category, Category: draft.Category,
@ -114,7 +112,7 @@ func SaveAsDraftingFromPublish(id int32, user *model.User, name string) {
drafting := &model.Drafting{ drafting := &model.Drafting{
Name: name, Name: name,
Category: publishedGi.Category, Category: publishedGi.Category,
Proto: handlerPublishedGiLinkData(publishedGi.Proto, true), Proto: publishedGi.Proto,
CreatorID: user.ID, CreatorID: user.ID,
CreatedAt: time.Now(), CreatedAt: time.Now(),
UpdateAt: time.Now(), UpdateAt: time.Now(),
@ -141,20 +139,3 @@ func QueryProjectPublishedGi(id int32) []*model.PublishedGi {
publishedGis, _ := dp.Select(dp.ID, dp.Name, dp.Category, dp.Type).Where(dp.ID.In(mids...), dp.Status.Eq(1)).Order(dp.Name).Find() publishedGis, _ := dp.Select(dp.ID, dp.Name, dp.Category, dp.Type).Where(dp.ID.In(mids...), dp.Status.Eq(1)).Order(dp.Name).Find()
return publishedGis return publishedGis
} }
// 操作地图数据中的link数据
// del 代表是否删除地图中的link数据
func handlerPublishedGiLinkData(data []byte, del bool) []byte {
gd := &graphicData.RtssGraphicStorage{}
proto.Unmarshal(data, gd)
if del {
gd.CalculateLink = []*graphicData.CalculateLink{}
} else {
gd.CalculateLink = memory.BuildCalculateLinkData(gd)
}
rd, err := proto.Marshal(gd)
if err != nil {
panic(dto.ErrorDto{Code: dto.DataOperationError, Message: err.Error()})
}
return rd
}