This commit is contained in:
xzb 2023-10-30 14:33:32 +08:00
commit 71f8163cab
51 changed files with 2174 additions and 3126 deletions

View File

@ -30,7 +30,6 @@ func InitSimulationRouter(api *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddle
authed.POST("/train/add", addTrain)
authed.POST("/train/remove", removeTrain)
authed.POST("/switch/operation", switchOperation)
authed.GET("/getDataChannelName", getDataChannelName)
authed.POST("/relay/operation", relayOperation)
authed.POST("/signal/operation", signalOperation)
authed.POST("/axleSection/operation", axleSectionOperation)
@ -42,10 +41,6 @@ func InitSimulationRouter(api *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddle
// 初始化地图信息
initPublishMapInfo()
// apiproto.Register(&apiproto.SimulationServer{})
// apiproto.Register(&apiproto.SimulationIBPServer{})
// apiproto.Register(&apiproto.SimulationPSLServer{})
// apiproto.Register(&apiproto.MemoryChangeServer{SimulationMap: make(map[string]*state.SimulationStatus)})
}
func initPublishMapInfo() {
@ -89,16 +84,17 @@ func createByProjectId(c *gin.Context) {
mapIds[i] = mapInfo.ID
}
// 运行环境配置
var runConfigStr string
runConfig := service.QueryRunConfig(req.ProjectRunConfigId)
if runConfig != nil {
runConfigStr = runConfig.ConfigContent
}
simulationId, err := ts.CreateSimulation(req.ProjectId, mapIds, runConfigStr)
simulationId, err := ts.CreateSimulation(req.ProjectId, mapIds, runConfig)
if err != nil {
panic(sys_error.New("测试启动失败", err))
}
rsp := dto.SimulationCreateRspDto{ProjectId: req.ProjectId, MapId: mapIds[0], MapIds: mapIds}
rsp := dto.SimulationCreateRspDto{
ProjectId: req.ProjectId,
MapId: mapIds[0],
MapIds: mapIds,
ProjectRunConfigId: req.ProjectRunConfigId,
}
rsp.SimulationId = simulationId
c.JSON(http.StatusOK, &rsp)
}
@ -425,29 +421,6 @@ func pslBtnOperation(c *gin.Context) {
c.JSON(http.StatusOK, "ok")
}
// 获取仿真信息更新通道名称
//
// @Summary 获取仿真信息更新通道名称
//
// @Security JwtAuth
//
// @Description 获取仿真信息更新通道名称
//
// Deprecated: 此接口废弃,使用轮询方式更新启动的测试列表
//
// @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)
panic(sys_error.New("接口已废弃", fmt.Errorf("此接口废弃,使用轮询方式更新启动的测试列表")))
}
// 获取仿真地图的公里标范围
//
// @Summary 获取仿真地图的公里标范围

@ -1 +1 @@
Subproject commit 6827f9671a619b95d80dac699463bbcd9ed0cb15
Subproject commit 8afde905e5b5376dc0bce29c099fb5fef2576e02

View File

@ -52,6 +52,7 @@ type centrifugo struct {
// 第三方配置结构
type ThridPartyConfig struct {
Id int32 `json:"id"`
Dynamics DynamicsConfig `json:"dynamics"`
Vobc VobcConfig `json:"vobc"`
Interlock InterlockConfig `json:"interlock"`

View File

@ -9,9 +9,9 @@ type PageProjectRunConfigReqDto struct {
type ProjectRunConfigReqDto struct {
Id int32 `json:"id" form:"id"`
Name string `json:"name" form:"name"`
Name string `json:"name" form:"name" binding:"required"`
Description string `json:"description" form:"description"`
ConfigContent string `json:"config" form:"config"`
ConfigContent string `json:"config" form:"config" binding:"required"`
}
type ProjectRunConfigDto struct {

View File

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.28.1
// protoc v4.23.1
// source: request.proto

View File

@ -25,6 +25,8 @@ type SimulationCreateRspDto struct {
SimulationId string `json:"simulationId" form:"simulationId"`
// 地图列表
MapIds []int32 `json:"mapIds" form:"mapIds"`
// 运行环境ID
ProjectRunConfigId int32 `json:"runConfigId" form:"runConfigId"`
}
//////////////////////////////////////////////////////////////////////////////
@ -140,6 +142,7 @@ type SimulationInfoRspDto struct {
MapId int32 `json:"mapId" form:"mapId"`
MapIds []int32 `form:"mapIds" json:"mapIds"`
ProjectId int32 `form:"projectId" json:"projectId"`
ProjectRunConfigId int32 `form:"runConfigId" json:"runConfigId" ` // 运行环境ID
}
type SimulationInfoRspDtoArr []SimulationInfoRspDto

View File

@ -1,66 +0,0 @@
package apiproto
import (
"time"
"google.golang.org/protobuf/proto"
"joylink.club/bj-rtsts-server/config"
"joylink.club/bj-rtsts-server/dto"
"joylink.club/bj-rtsts-server/ts"
"joylink.club/bj-rtsts-server/ts/protos/state"
)
var MemoryChangeServerSuffix = "serve-data"
type MemoryChangeServer struct {
SimulationMap map[string]*state.SimulationStatus
}
// 返回通道格式
func (t *MemoryChangeServer) getChannelName() string {
return config.SimulationId_prefix + MemoryChangeServerSuffix
}
// 消息运行间隔
func (t *MemoryChangeServer) getInterval() time.Duration {
return 1 * time.Second
}
// 定时发送数据
func (t *MemoryChangeServer) onTick() []TopicMsg {
simArr := ts.GetSimulationArr()
addArr, delArr := []*state.SimulationStatus{}, []*state.SimulationStatus{}
// 增加的仿真
allSim := make(map[string]bool)
for _, v := range simArr {
allSim[v.SimulationId] = true
if t.SimulationMap[v.SimulationId] != nil {
continue
}
status := &state.SimulationStatus{SimulationId: v.SimulationId, MapId: v.MapIds[0], ProjectId: v.ProjectId, MapIds: v.MapIds}
t.SimulationMap[v.SimulationId] = status
addArr = append(addArr, status)
}
// 已经移除的仿真
for k, v := range t.SimulationMap {
if allSim[k] {
continue
}
delArr = append(delArr, v)
}
// 删除已替换仿真主键
if len(delArr) > 0 {
for _, v := range delArr {
delete(t.SimulationMap, v.SimulationId)
}
}
if len(addArr) == 0 && len(delArr) == 0 {
return nil
}
msg := &state.MemoryDataStatus{AddSimulations: addArr, RemoveSimulations: delArr}
b, err := proto.Marshal(msg)
if err != nil {
panic(dto.ErrorDto{Code: dto.ArgumentParseError, Message: err.Error()})
}
return []TopicMsg{{channalName: t.getChannelName(), data: b}}
}

View File

@ -1,153 +0,0 @@
package apiproto
import (
context "context"
"log/slog"
"runtime/debug"
"time"
)
// 消息服务
type IMsgServer interface {
// 获取通道名
getChannelName() string
// 发送消息间隔时间,单位ms
getInterval() time.Duration
// 定时发送的消息
onTick() []TopicMsg
}
// 消息实体
type TopicMsg struct {
// 通道名称
channalName string
// 消息信息
data []byte
}
type MsgServer struct {
IMsgServer
ctx context.Context
cancelFn context.CancelFunc
}
// 消息服务管理map
var servers map[string]*MsgServer = make(map[string]*MsgServer)
// 注册消息服务
func Register(server IMsgServer) *MsgServer {
ms := &MsgServer{
IMsgServer: server,
}
ctx, cancelFn := context.WithCancel(context.Background())
ms.ctx = ctx
ms.cancelFn = cancelFn
go run(ms)
servers[server.getChannelName()] = ms
return ms
}
// 注销消息服务
func Unregister(key string) {
server := servers[key]
if server == nil {
return
}
server.cancelFn()
delete(servers, key)
}
// 消息服务运行
func run(server *MsgServer) {
defer func() {
if err := recover(); err != nil {
slog.Error("消息服务运行异常", "serverChannelName", server.getChannelName(), "error", err, "stack", string(debug.Stack()))
debug.PrintStack()
}
}()
for {
select {
case <-server.ctx.Done():
slog.Info("消息服务退出", "serverChannelName", server.getChannelName())
return
default:
}
topicMsgs := server.onTick()
if len(topicMsgs) > 0 {
// for _, msg := range topicMsgs {
// PublishMsg(msg.channalName, msg.data)
// }
}
time.Sleep(server.getInterval())
}
}
// // 消息类型服务集合
// var serverMap = make(map[string]*IMsgServer)
// // 消息服务退出通道
// var serverExitChannelMap = make(map[string]chan bool)
// // 服务运行
// func doServerRun(tick *time.Ticker, server IMsgServer, exitChannel chan bool) {
// // 循环推送信息
// for {
// <-tick.C
// topicMsgs := server.onTick()
// if len(topicMsgs) == 0 {
// continue
// }
// for _, msg := range topicMsgs {
// PublishMsg(msg.channalName, msg.data)
// }
// select {
// case <-exitChannel:
// return
// default:
// }
// }
// }
// // 注册服务
// func RegisterMsgServer(server IMsgServer) {
// if client == nil {
// InitClient()
// }
// serverMap[server.getChannelName()] = &server
// if server.getInterval() > 0 {
// exitChannel := make(chan bool)
// serverExitChannelMap[server.getChannelName()] = exitChannel
// tick := time.NewTicker(server.getInterval())
// go func() {
// defer func() {
// if r := recover(); r != nil {
// slog.Debug("定时器发生错误,%v\n", r)
// }
// // 重新启动,防止服务卡死
// doServerRun(tick, server, exitChannel)
// }()
// // 循环推送信息
// doServerRun(tick, server, exitChannel)
// }()
// }
// }
// // 注销消息服务
// func UnRegisterMsgServer(key string) {
// channel := serverExitChannelMap[key]
// if channel != nil {
// // 定时任务取消
// channel <- false
// delete(serverExitChannelMap, key)
// // 删除集合信息
// delete(serverMap, key)
// }
// }
// // 获取消息服务
// func GetMsgServer(key string) *IMsgServer {
// return serverMap[key]
// }

View File

@ -1,59 +0,0 @@
package apiproto
import (
"strconv"
"strings"
"time"
"google.golang.org/protobuf/proto"
"joylink.club/bj-rtsts-server/dto"
"joylink.club/bj-rtsts-server/ts"
"joylink.club/bj-rtsts-server/ts/protos/graphicData"
"joylink.club/bj-rtsts-server/ts/simulation/wayside/memory"
)
type SimulationIBPServer struct{}
// 返回通道格式
func (t *SimulationIBPServer) getChannelName() string {
return "simulation-ibp-{sid}_{mid}_{station}-status"
}
// 消息运行间隔
func (t *SimulationIBPServer) getInterval() time.Duration {
return 200 * time.Millisecond
}
// 定时发送数据
func (t *SimulationIBPServer) onTick() []TopicMsg {
simArr := ts.GetSimulationArr()
var msgArr []TopicMsg
for _, v := range simArr {
for _, mapId := range v.MapIds {
mapType := memory.QueryGiType(mapId)
if mapType != graphicData.PictureType_StationLayout {
continue
}
mapData := memory.QueryGiData[*graphicData.RtssGraphicStorage](mapId)
idStr := strconv.Itoa(int(mapId))
for _, station := range mapData.Stations {
channelName := handlerIBPChannelName(v.SimulationId, idStr, station.Common.Id, t.getChannelName())
b, err := proto.Marshal(v.GetAllIBPState(mapId, station.Common.Id, station.RefIbpMapCode))
if err != nil {
panic(dto.ErrorDto{Code: dto.DataOperationError, Message: err.Error()})
}
msgArr = append(msgArr, TopicMsg{channalName: channelName, data: b})
}
}
}
return msgArr
}
// 处理订阅通道名称
func handlerIBPChannelName(sid, mapId, station string, format string) string {
var channelName string
channelName = strings.Replace(format, "{sid}", sid, 1)
channelName = strings.Replace(channelName, "{mid}", mapId, 1)
channelName = strings.Replace(channelName, "{station}", station, 1)
return channelName
}

View File

@ -1,59 +0,0 @@
package apiproto
import (
"strconv"
"strings"
"time"
"google.golang.org/protobuf/proto"
"joylink.club/bj-rtsts-server/dto"
"joylink.club/bj-rtsts-server/ts"
"joylink.club/bj-rtsts-server/ts/protos/graphicData"
"joylink.club/bj-rtsts-server/ts/simulation/wayside/memory"
)
type SimulationPSLServer struct{}
// 返回通道格式
func (t *SimulationPSLServer) getChannelName() string {
return "simulation-psl-{sid}_{mid}_{psl}-status"
}
// 消息运行间隔
func (t *SimulationPSLServer) getInterval() time.Duration {
return 200 * time.Millisecond
}
// 定时发送数据
func (t *SimulationPSLServer) onTick() []TopicMsg {
simArr := ts.GetSimulationArr()
var msgArr []TopicMsg
for _, v := range simArr {
for _, mapId := range v.MapIds {
mapType := memory.QueryGiType(mapId)
if mapType != graphicData.PictureType_StationLayout {
continue
}
mapData := memory.QueryGiData[*graphicData.RtssGraphicStorage](mapId)
idStr := strconv.Itoa(int(mapId))
for _, box := range mapData.GateBoxs {
channelName := handlerPSLChannelName(v.SimulationId, idStr, box.Common.Id, t.getChannelName())
b, err := proto.Marshal(v.GetAllPSLState(mapId, box.Common.Id))
if err != nil {
panic(dto.ErrorDto{Code: dto.DataOperationError, Message: err.Error()})
}
msgArr = append(msgArr, TopicMsg{channalName: channelName, data: b})
}
}
}
return msgArr
}
// 处理订阅通道名称
func handlerPSLChannelName(sid, mapId, psl string, format string) string {
var channelName string
channelName = strings.Replace(format, "{sid}", sid, 1)
channelName = strings.Replace(channelName, "{mid}", mapId, 1)
channelName = strings.Replace(channelName, "{psl}", psl, 1)
return channelName
}

View File

@ -1,49 +0,0 @@
package apiproto
import (
"strconv"
"strings"
"time"
"google.golang.org/protobuf/proto"
"joylink.club/bj-rtsts-server/dto"
"joylink.club/bj-rtsts-server/ts"
)
type SimulationServer struct{}
// 返回通道格式
func (t *SimulationServer) getChannelName() string {
return "simulation-{sid}_{mid}-devices-status"
}
// 消息运行间隔
func (t *SimulationServer) getInterval() time.Duration {
return 200 * time.Millisecond
}
// 定时发送数据
func (t *SimulationServer) onTick() []TopicMsg {
simArr := ts.GetSimulationArr()
var msgArr []TopicMsg
for _, v := range simArr {
for _, mapId := range v.MapIds {
idStr := strconv.Itoa(int(mapId))
channelName := handlerChannelName(v.SimulationId, idStr, t.getChannelName())
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})
}
}
return msgArr
}
// 处理订阅通道名称
func handlerChannelName(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,24 +0,0 @@
package apiproto
import "time"
type TestServer struct {
data map[string]string
}
func (t *TestServer) getChannelName() string {
return "test"
}
func (t *TestServer) getInterval() time.Duration {
return time.Second
}
func (t *TestServer) allMsgData(params map[string]string) []byte {
return []byte(`{"input": "hello world"}`)
}
func (t *TestServer) onTick() []TopicMsg {
msg := TopicMsg{t.getChannelName(), []byte(`{"input": "hello from GRPC"}`)}
return []TopicMsg{msg}
}

View File

@ -2,8 +2,6 @@ package message_server
import (
"fmt"
"strconv"
"strings"
"time"
"google.golang.org/protobuf/proto"
@ -11,6 +9,9 @@ import (
"joylink.club/bj-rtsts-server/ts/protos/graphicData"
"joylink.club/bj-rtsts-server/ts/protos/state"
"joylink.club/bj-rtsts-server/ts/simulation/wayside/memory"
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
)
// 综合后备盘IBP消息服务
@ -19,8 +20,12 @@ type IbpMs struct {
mapId int32
}
func NewIBPMs(vs *memory.VerifySimulation, mapId int32) *IbpMs {
return &IbpMs{vs: vs, mapId: mapId}
}
func (ms *IbpMs) GetChannel() string {
return "simulation-ibp-{sid}_{mid}_{station}-status"
return "simulation-ibp-%s_%d_%s-status"
}
func (ms *IbpMs) GetInterval() time.Duration {
@ -30,9 +35,8 @@ func (ms *IbpMs) GetInterval() time.Duration {
func (ms *IbpMs) OnTick() ([]*ms_api.TopicMsg, error) {
var msgArr []*ms_api.TopicMsg
mapData := memory.QueryGiData[*graphicData.RtssGraphicStorage](ms.mapId)
idStr := strconv.Itoa(int(ms.mapId))
for _, station := range mapData.Stations {
channel := handlerIBPChannelName(ms.vs.SimulationId, idStr, station.Common.Id, ms.GetChannel())
channel := ms.handlerIBPChannelName(station.Common.Id)
stationIbpState, err := ms.collectStationIbpState(station)
if err != nil {
return nil, err
@ -46,16 +50,117 @@ func (ms *IbpMs) OnTick() ([]*ms_api.TopicMsg, error) {
return msgArr, nil
}
// 当发生错误时执行的逻辑
func (ms *IbpMs) OnError(err error) {
}
func (ms *IbpMs) collectStationIbpState(station *graphicData.Station) (*state.PushedDevicesStatus, error) {
// TODO: 重构之前的消息服务
if station.RefIbpMapCode == "" {
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)
if err != nil {
return nil, err
}
alarmStates, err := ms.collectIBPAlarmState(stationUid, ibpStorage.IbpAlarms)
if err != nil {
return nil, err
}
lightStates, err := ms.collectIBPLightState(stationUid, ibpStorage.IbpLights)
if err != nil {
return nil, err
}
keyStates, err := ms.collectIBPKeyState(stationUid, ibpStorage.IbpKeys)
if err != nil {
return nil, err
}
return &state.PushedDevicesStatus{
All: true,
AllStatus: &state.AllDevicesStatus{
ButtonState: buttonStates,
AlarmState: alarmStates,
LightState: lightStates,
KeyState: keyStates,
},
}, nil
}
// 收集IBP按钮状态
func (ms *IbpMs) collectIBPButtonState(stationUid string, 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)
if !ok {
return nil, fmt.Errorf("ibp按钮实体不存在: World id=%d, uid=%s", ms.vs.World.Id(), stationUid+"_button_"+data.Code)
}
if entry.HasComponent(component.ButtonTag) {
states = append(states, getIBPButtonState(data.Common.Id, entry))
}
}
return states, nil
}
// 获取IBP盘按钮状态
func getIBPButtonState(id string, entry *ecs.Entry) *state.ButtonState {
status := &state.ButtonState{Id: id}
bit := component.BitStateType.Get(entry)
status.Down = bit.Val
// 如果按钮包含灯
if entry.HasComponent(component.SingleLightType) {
lightComponent := component.SingleLightType.Get(entry)
status.Active = component.BitStateType.Get(lightComponent.Light).Val
}
return status
}
// 收集报警器状态
func (ms *IbpMs) collectIBPAlarmState(stationUid string, 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)
if !ok {
return nil, fmt.Errorf("ibp报警器实体不存在: World id=%d, uid=%s", ms.vs.World.Id(), stationUid+"_alarm_"+data.Code)
}
if entry.HasComponent(component.AlarmTag) {
states = append(states, &state.AlarmState{Id: data.Common.Id, Active: component.BitStateType.Get(entry).Val})
}
}
return states, nil
}
// 收集灯状态信息
func (ms *IbpMs) collectIBPLightState(stationUid string, 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)
if !ok {
return nil, fmt.Errorf("ibp指示灯实体不存在: World id=%d, uid=%s", ms.vs.World.Id(), stationUid+"_light_"+data.Code)
}
if entry.HasComponent(component.LightTag) {
states = append(states, &state.LightState{Id: data.Common.Id, Active: component.BitStateType.Get(entry).Val})
}
}
return states, nil
}
// 收集钥匙状态
func (ms *IbpMs) collectIBPKeyState(stationUid string, 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)
if !ok {
return nil, fmt.Errorf("ibp钥匙实体不存在: World id=%d, uid=%s", ms.vs.World.Id(), stationUid+"_key_"+data.Code)
}
if entry.HasComponent(component.KeyTag) {
states = append(states, &state.KeyState{Id: data.Common.Id, Gear: component.GearStateType.Get(entry).Val})
}
}
return states, nil
}
// 处理订阅通道名称
func handlerIBPChannelName(sid, mapId, station string, format string) string {
var channelName string
channelName = strings.Replace(format, "{sid}", sid, 1)
channelName = strings.Replace(channelName, "{mid}", mapId, 1)
channelName = strings.Replace(channelName, "{station}", station, 1)
return channelName
func (ms *IbpMs) handlerIBPChannelName(stationId string) string {
return fmt.Sprintf(ms.GetChannel(), ms.vs.SimulationId, ms.mapId, stationId)
}

View File

@ -1,5 +1,86 @@
package message_server
import (
"fmt"
"time"
"google.golang.org/protobuf/proto"
"joylink.club/bj-rtsts-server/message_server/ms_api"
"joylink.club/bj-rtsts-server/ts/protos/graphicData"
"joylink.club/bj-rtsts-server/ts/protos/state"
"joylink.club/bj-rtsts-server/ts/simulation/wayside/memory"
)
// PSL或门控箱消息服务
type PslMs struct {
vs *memory.VerifySimulation
mapId int32
}
func NewPSLMs(vs *memory.VerifySimulation, mapId int32) *PslMs {
return &PslMs{vs: vs, mapId: mapId}
}
func (r *PslMs) GetChannel() string {
return "simulation-psl-%s_%d_%s-status"
}
func (r *PslMs) GetInterval() time.Duration {
return 200 * time.Millisecond
}
func (r *PslMs) OnTick() ([]*ms_api.TopicMsg, error) {
var msgArr []*ms_api.TopicMsg
mapData := memory.QueryGiData[*graphicData.RtssGraphicStorage](r.mapId)
for _, box := range mapData.GateBoxs {
channel := r.handlerPSLChannelName(box.Common.Id)
state, err := r.collectGateBoxPSLState(box)
if err != nil {
return nil, err
}
b, err := proto.Marshal(state)
if err != nil {
return nil, fmt.Errorf("PSL设备状态消息服务数据序列化失败: %s", err)
}
msgArr = append(msgArr, ms_api.NewTopicMsg(channel, b))
}
return msgArr, nil
}
func (r *PslMs) OnError(err error) {}
// 处理订阅通道名称
func (r *PslMs) handlerPSLChannelName(gateBoxId string) string {
return fmt.Sprintf(r.GetChannel(), r.vs.SimulationId, r.mapId, gateBoxId)
}
func (r *PslMs) collectGateBoxPSLState(gatedBox *graphicData.GatedBox) (*state.PushedDevicesStatus, error) {
//world := s.GetSimulationWorld()
//uidStructure := queryUidStructure[*StationUidStructure](mapId)
//boxUid := uidStructure.GateBoxIds[boxId].Uid
//mkxEntry, ok := entity.GetEntityByUid(world, boxUid)
//var buttonStateArr []*state.ButtonState
//if ok {
// mkxCircuit := component.MkxCircuitType.Get(mkxEntry)
// var boxArr []*ecs.Entry
// boxArr = append(boxArr, mkxCircuit.PcbList...)
// boxArr = append(boxArr, mkxCircuit.PobList...)
// boxArr = append(boxArr, mkxCircuit.PabList...)
// for _, mkxBoxEntry := range boxArr {
// mkxBox := component.MkxBoxType.Get(mkxBoxEntry)
// uid := component.UidType.Get(mkxBox.Btn).Id
// down := component.BitStateType.Get(mkxBox.Btn).Val
// buttonStateArr = append(buttonStateArr, &state.ButtonState{
// Id: uid,
// Down: down,
// })
// }
//}
//return &state.PushedDevicesStatus{
// All: true,
// AllStatus: &state.AllDevicesStatus{
// ButtonState: buttonStateArr,
// },
//}
return nil, nil
}

View File

@ -1,5 +1,82 @@
package message_server
import (
"fmt"
"time"
"google.golang.org/protobuf/proto"
"joylink.club/bj-rtsts-server/message_server/ms_api"
"joylink.club/bj-rtsts-server/ts/protos/graphicData"
"joylink.club/bj-rtsts-server/ts/protos/state"
"joylink.club/bj-rtsts-server/ts/simulation/wayside/memory"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
)
// 继电器组合柜布置图消息服务
type RccMs struct {
vs *memory.VerifySimulation
mapId int32
channel string
}
func NewRccMs(vs *memory.VerifySimulation, mapId int32) *RccMs {
return &RccMs{
vs: vs,
mapId: mapId,
channel: fmt.Sprintf("simulation-%s_%d-devices-status", vs.SimulationId, mapId),
}
}
// 获取消息服务名
func (r *RccMs) GetChannel() string {
return r.channel
}
// 发送消息间隔时间,单位ms
func (r *RccMs) GetInterval() time.Duration {
return 200 * time.Millisecond
}
// 构造定时发送的消息
func (r *RccMs) OnTick() ([]*ms_api.TopicMsg, error) {
relayStates, err := r.collectRelayState()
if err != nil {
return nil, err
}
ststes := &state.PushedDevicesStatus{
All: true,
AllStatus: &state.AllDevicesStatus{
ReplyState: relayStates,
},
}
b, err := proto.Marshal(ststes)
if err != nil {
return nil, fmt.Errorf("信号布置图设备状态消息服务数据序列化失败, %s", err)
}
return []*ms_api.TopicMsg{ms_api.NewTopicMsg(r.channel, b)}, nil
}
// 当发生错误时执行的逻辑
func (r *RccMs) OnError(err error) {
}
// 获取仿真地图的继电器状态,前端推送
func (r *RccMs) collectRelayState() ([]*state.ReplyState, error) {
// 获取本地图下的继电器信息
uidMap := memory.QueryMapUidMapByType(r.mapId, &graphicData.Relay{})
var replyStateArr []*state.ReplyState
for _, u := range uidMap {
entry, ok := entity.GetEntityByUid(r.vs.World, u.Uid)
if !ok {
// 暂时注释,很多继电器都没初始化
//return nil, fmt.Errorf("继电器实体不存在: World id=%d, uid=%s", r.vs.World.Id(), u.Uid)
continue
}
if entry.HasComponent(component.RelayTag) {
bit := component.BitStateType.Get(entry)
replyStateArr = append(replyStateArr, &state.ReplyState{Id: u.CommonId, Xh: bit.Val})
}
}
return replyStateArr, nil
}

View File

@ -21,8 +21,7 @@ type SfpMs struct {
channel string
}
func NewSfpMs(vs *memory.VerifySimulation) *SfpMs {
mapId := int32(0)
func NewSfpMs(vs *memory.VerifySimulation, mapId int32) *SfpMs {
return &SfpMs{
vs: vs,
mapId: mapId,
@ -90,14 +89,75 @@ func (ms *SfpMs) OnError(err error) {
// 收集屏蔽门状态
func (ms *SfpMs) collectPsdStates() ([]*state.PsdState, error) {
// TODO: 重构之前的消息服务
return nil, nil
world := ms.vs.World
uidStructure := memory.QueryUidStructure[*memory.StationUidStructure](ms.mapId)
data := memory.QueryGiData[*graphicData.RtssGraphicStorage](ms.mapId)
var psdStateArr []*state.PsdState
for _, door := range data.ScreenDoors {
uid := uidStructure.PsdIds[door.Common.Id].Uid
psdEntry, ok := entity.GetEntityByUid(world, uid)
if ok {
var amount int32
psdState := component.PsdStateType.Get(psdEntry)
if psdState.Km8 {
amount = 8
} else if psdState.Km4 {
amount = 4
} else {
amount = 0
}
start, end := getStartEndCodeByGroup(door, amount)
var openSubDoor []int32
for i := start; i <= end; i++ {
openSubDoor = append(openSubDoor, i)
}
psdStateArr = append(psdStateArr, &state.PsdState{
Id: door.Common.Id,
OpenDoorCodes: openSubDoor,
})
}
}
return psdStateArr, nil
}
func getStartEndCodeByGroup(door *graphicData.ScreenDoor, groupAmount int32) (int32, int32) {
for _, group := range door.ScreenDoorGroupList {
if group.TrainGroupAmount == groupAmount {
return group.StartSmallDoor, group.EndSmallDoor
}
}
return 0, -1
}
// 收集区段状态
func (ms *SfpMs) collectSectionStates() ([]*state.SectionState, error) {
// TODO: 重构之前的消息服务
return nil, nil
uidMap := memory.QueryMapUidMapByType(ms.mapId, &graphicData.Section{})
var sectionArr []*state.SectionState
for _, u := range uidMap {
s := handlerSectionState(ms.vs.World, u.Uid)
if s == nil {
continue
}
s.Id = u.CommonId
sectionArr = append(sectionArr, s)
}
return sectionArr, nil
}
func handlerSectionState(w ecs.World, uid string) *state.SectionState {
entry, ok := entity.GetEntityByUid(w, uid)
if !ok {
//fmt.Printf("id=%s的信号机不存在", uid)
return nil
}
if entry.HasComponent(component.AxleSectionTag) { //计轴区段
sectionState := &state.SectionState{}
axleState := component.AxleSectionStateType.Get(entry)
sectionState.Occupied = axleState.Occ
sectionState.Type = state.SectionType_Axle
return sectionState
}
return nil
}
// 收集车站按钮状态

View File

@ -6,6 +6,7 @@ import (
"joylink.club/bj-rtsts-server/message_server/ms_api"
"joylink.club/bj-rtsts-server/message_server/ms_manage"
"joylink.club/bj-rtsts-server/ts/protos/graphicData"
"joylink.club/bj-rtsts-server/ts/simulation/wayside/memory"
)
@ -24,10 +25,20 @@ func Start(vs *memory.VerifySimulation) {
if !ok {
sms := &SimulationMs{
vs: vs,
mss: []ms_api.IMsgServer{
NewSfpMs(vs),
},
mss: []ms_api.IMsgServer{},
}
for _, mapId := range vs.MapIds {
t := memory.QueryOnlyGiType(mapId)
switch t {
case graphicData.PictureType_StationLayout: // 平面布置图
// 添加车站关联的平面布置图、IBP、PSL信息
sms.mss = append(sms.mss, NewSfpMs(vs, mapId), NewIBPMs(vs, mapId), NewPSLMs(vs, mapId))
case graphicData.PictureType_RelayCabinetLayout: // 继电器柜
sms.mss = append(sms.mss, NewRccMs(vs, mapId))
}
}
// 启动仿真状态服务
NewSimulationStateMs(vs)
ms_manage.Register(sms)
smsMap.Store(vs.SimulationId, sms)
}

View File

@ -1,5 +1,53 @@
package message_server
import (
"fmt"
"google.golang.org/protobuf/proto"
apiproto "joylink.club/bj-rtsts-server/grpcproto"
"joylink.club/bj-rtsts-server/ts/protos/state"
"joylink.club/bj-rtsts-server/ts/simulation/wayside/memory"
"joylink.club/ecs"
)
// 世界状态变化消息服务
type SimulationStateMs struct {
vs *memory.VerifySimulation
channel string
}
func NewSimulationStateMs(vs *memory.VerifySimulation) *SimulationStateMs {
ms := &SimulationStateMs{
vs: vs,
channel: fmt.Sprintf("simulation-%s-status", vs.SimulationId),
}
ecs.WorldStateChangeEvent.Subscribe(ms.vs.World, func(_ ecs.World, e ecs.WorldStateChange) {
switch e.NewState {
case ecs.WorldClose:
doSendState(ms.channel, &state.SimulationStatus{
SimulationId: vs.SimulationId,
State: state.SimulationStatus_DESTROY,
})
case ecs.WorldError:
doSendState(ms.channel, &state.SimulationStatus{
SimulationId: vs.SimulationId,
State: state.SimulationStatus_ERROR,
})
case ecs.WorldPause:
doSendState(ms.channel, &state.SimulationStatus{
SimulationId: vs.SimulationId,
State: state.SimulationStatus_PAUSE,
})
}
})
return ms
}
func doSendState(channel string, status *state.SimulationStatus) error {
b, err := proto.Marshal(status)
if err != nil {
return fmt.Errorf("仿真状态消息服务数据序列化失败, %s", err)
}
apiproto.PublishMsg(channel, b)
return nil
}

@ -1 +1 @@
Subproject commit 4fc223c9f7154d6a01e75db0c5745ad6c177c57e
Subproject commit 085bfdc6f9afc84c0724c49441aa59d734906a6a

View File

@ -21,7 +21,7 @@ func PageProjectRunConfigQuery(query *dto.PageProjectRunConfigReqDto) *dto.PageD
if err != nil {
panic(sys_error.New("查询失败,数据库错误请联系运维人员", err))
}
return &dto.PageDto{Total: int(total), PageQueryDto: query.PageQueryDto, Records: records}
return &dto.PageDto{Total: int(total), PageQueryDto: query.PageQueryDto, Records: dto.ConvertToRunConfigFromSlice(records)}
}
// 查询项目运行环境列表

View File

@ -151,7 +151,11 @@ func QueryProjectPublishedGi(id int32) []*model.PublishedGi {
mids[i] = m.Mid
}
dp := dbquery.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.Type, dp.Name).
Find()
return publishedGis
}

View File

@ -1,97 +0,0 @@
package dynamics
import (
"encoding/hex"
"encoding/json"
"fmt"
"log"
"net"
"strconv"
"testing"
"time"
"github.com/gin-gonic/gin"
"github.com/panjf2000/gnet/v2"
"joylink.club/bj-rtsts-server/config"
)
// 这里用来测试通信与数据传输是否正常
func TestAll(t *testing.T) {
loadAndChangeConfig()
//注册列车信息处理逻辑
RegisterTrainInfoHandler(func(info *TrainInfo) {
fmt.Println("处理列车信息...")
fmt.Println(info)
})
//启动udp服务
go RunUdpServer()
////启动仅用于的测试的模拟远程udp服务
go runTestUdpServer()
////启动http服务
go runTestHttpServer()
time.Sleep(2 * time.Second)
//向本地udp服务发送数据
sendDataToLocalUdpServer()
//向远程udp服务发送数据
_ = sendDynamicsMsg(encoderDynamicsTurnout(&TurnoutInfo{Code: 02}))
//发送http请求
_, _, _ = SendInitTrainReq(&InitTrainInfo{Speed: 10})
}
func loadAndChangeConfig() {
config.LoadConfig()
config.Config.Dynamics.Ip = "127.0.0.1"
config.Config.Dynamics.HttpPort = 3500
}
func sendDataToLocalUdpServer() {
addr, _ := net.ResolveUDPAddr("udp", "127.0.0.1:"+strconv.Itoa(config.Config.Dynamics.UdpLocalPort))
conn, _ := net.DialUDP("udp", nil, addr)
buf, _ := hex.DecodeString("0009012EE009000000070380000006000100020003000A000A000A000A000A000A000A")
conn.Write(buf)
conn.Close()
}
func runTestHttpServer() {
engine := gin.Default()
engine.POST("/api/aerodynamics/init/train", func(context *gin.Context) {
info := InitTrainInfo{}
err := context.ShouldBindJSON(&info)
if err != nil {
println(err.Error())
}
data, err := json.MarshalIndent(info, "", " ")
fmt.Println("---------------- 接收到的列车初始化信息 ----------------")
fmt.Println(string(data))
if info.Speed != 10 {
println("http服务接收到的数据异常")
}
})
engine.Run(fmt.Sprintf(":%d", config.Config.Dynamics.HttpPort))
}
func runTestUdpServer() {
server := &testUdpServer{addr: fmt.Sprintf("udp://:%d", config.Config.Dynamics.UdpRemotePort), multicore: false}
log.Fatal(gnet.Run(server, server.addr, gnet.WithMulticore(server.multicore)))
}
type testUdpServer struct {
gnet.BuiltinEventEngine
eng gnet.Engine
addr string
multicore bool
eventHandlers []gnet.EventHandler
}
func (server *testUdpServer) OnTraffic(c gnet.Conn) gnet.Action {
buf, err := c.Next(-1)
if err != nil {
println(err.Error())
}
fmt.Println("---------------- 远程udp服务接收到的字节数据 ----------------")
fmt.Println(buf)
return gnet.None
}

View File

@ -1,120 +0,0 @@
package dynamics
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"time"
"joylink.club/bj-rtsts-server/config"
)
func SendInitTrainReq(info *InitTrainInfo) (int, *[]byte, error) {
if !config.Config.Dynamics.Open {
return http.StatusOK, nil, nil
}
baseUrl := getUrlBase()
uri := "/api/aerodynamics/init/train/"
url := baseUrl + uri
data, _ := json.Marshal(info)
client := http.Client{
Timeout: time.Second * 5,
}
resp, err := client.Post(url, "application/json", bytes.NewBuffer(data))
if err != nil {
s := err.Error()
println(s)
return 0, nil, err
}
var buf []byte
_, err = resp.Body.Read(buf)
if err != nil {
return resp.StatusCode, nil, err
}
return resp.StatusCode, &buf, resp.Body.Close()
}
func SendRemoveTrainReq(info *InitTrainInfo) (int, *[]byte, error) {
if !config.Config.Dynamics.Open {
return http.StatusOK, nil, nil
}
baseUrl := getUrlBase()
uri := "/api/aerodynamics/remove/train/"
url := baseUrl + uri
data, _ := json.Marshal(info)
client := http.Client{
Timeout: time.Second * 5,
}
resp, err := client.Post(url, "application/json", bytes.NewBuffer(data))
if err != nil {
s := err.Error()
println(s)
return 0, nil, err
}
var buf []byte
_, err = resp.Body.Read(buf)
if err != nil {
return resp.StatusCode, nil, err
}
return resp.StatusCode, &buf, resp.Body.Close()
}
func SendSimulationStartReq(base *LineBaseInfo) (int, *[]byte, error) {
if !config.Config.Dynamics.Open {
return http.StatusOK, nil, nil
}
baseUrl := getUrlBase()
uri := "/api/start/"
url := baseUrl + uri
data, _ := json.Marshal(base)
resp, err := http.Post(url, "application/json", bytes.NewBuffer(data))
if err != nil {
s := err.Error()
println(s)
return 0, nil, err
}
var buf []byte
_, err = resp.Body.Read(buf)
if err != nil {
return resp.StatusCode, nil, err
}
return resp.StatusCode, &buf, resp.Body.Close()
}
func SendSimulationEndReq() (int, *[]byte, error) {
if !config.Config.Dynamics.Open {
return http.StatusOK, nil, nil
}
baseUrl := getUrlBase()
uri := "/api/end/"
url := baseUrl + uri
resp, err := http.Post(url, "application/json", nil)
if err != nil {
s := err.Error()
println(s)
return 0, nil, err
}
var buf []byte
_, err = resp.Body.Read(buf)
if err != nil {
return resp.StatusCode, nil, err
}
return resp.StatusCode, &buf, resp.Body.Close()
}
var (
urlBase string
)
func getUrlBase() string {
if urlBase == "" {
ip := config.Config.Dynamics.Ip
var port string
if config.Config.Dynamics.HttpPort != 0 {
port = fmt.Sprintf(":%d", config.Config.Dynamics.HttpPort)
}
urlBase = "http://" + ip + port
}
return urlBase
}

View File

@ -1,52 +0,0 @@
package dynamics
type InitTrainInfo struct {
TrainIndex uint16 `json:"trainIndex"`
LinkIndex uint16 `json:"linkIndex"`
LinkOffset uint32 `json:"linkOffset"`
//单位0.1km/h
Speed uint16 `json:"speed"`
Up bool `json:"up"`
TrainLength uint16 `json:"trainLength"`
}
// 移除列车请求参数
type RemoveTrainReq struct {
TrainIndex uint16 `json:"trainIndex"`
}
// LineBaseInfo 线路基础信息,提供给动力学作为计算依据
type LineBaseInfo struct {
LinkList []*Link `json:"linkList"`
SlopeList []*Slope `json:"slopeList"`
CurveList []*Curve `json:"curveList"`
}
type Link struct {
ID int32 `json:"id"`
//长度 mm
Len int32 `json:"len"`
ARelTurnoutId int32 `json:"ARelTurnoutId"`
ARelTurnoutPoint string `json:"ARelTurnoutPoint"`
BRelTurnoutId int32 `json:"BRelTurnoutId"`
BRelTurnoutPoint string `json:"BRelTurnoutPoint"`
}
type Slope struct {
ID int32 `json:"id"`
StartLinkId int32 `json:"startLinkId"`
StartLinkOffset int32 `json:"startLinkOffset"`
EndLinkId int32 `json:"endLinkId"`
EndLinkOffset int32 `json:"endLinkOffset"`
//坡度的三角函数(猜是sin)值的*1000
DegreeTrig int32 `json:"degreeTrig"`
}
type Curve struct {
ID int32 `json:"id"`
StartLinkId int32 `json:"startLinkId"`
StartLinkOffset int32 `json:"startLinkOffset"`
EndLinkId int32 `json:"endLinkId"`
EndLinkOffset int32 `json:"endLinkOffset"`
Curvature int32 `json:"curvature"`
}

View File

@ -1,102 +0,0 @@
package dynamics
import (
"encoding/json"
"testing"
"time"
"github.com/spf13/viper"
"joylink.club/bj-rtsts-server/config"
)
func TestSendTrainInitReq(t *testing.T) {
viper.AddConfigPath("../")
config.LoadConfig()
info := InitTrainInfo{
TrainIndex: uint16(1),
LinkIndex: 2,
LinkOffset: 3,
Speed: 4,
Up: true,
}
time.Sleep(time.Second)
SendInitTrainReq(&info)
}
func TestSendSimulationStartReq(t *testing.T) {
viper.AddConfigPath("../")
config.LoadConfig()
SendSimulationStartReq(mockLineBaseInfo())
}
func TestSendSimulationEndReq(t *testing.T) {
viper.AddConfigPath("../")
config.LoadConfig()
SendSimulationEndReq()
}
func mockLineBaseInfo() *LineBaseInfo {
var links []*Link
for i := 1; i <= 12; i++ {
var atid int32
var btid int32
if i <= 6 {
atid = int32(i - 1)
btid = int32(i)
} else {
atid = int32(i - 2)
btid = int32(i - 1)
}
if i == 1 || i == 7 {
atid = 0
} else if i == 6 || i == 12 {
btid = 0
}
links = append(links, &Link{
ID: int32(i),
Len: int32(i * 100000),
ARelTurnoutId: atid,
ARelTurnoutPoint: "A",
BRelTurnoutId: btid,
BRelTurnoutPoint: "B",
})
}
for i := 13; i <= 17; i++ {
links = append(links, &Link{
ID: int32(i),
Len: int32(i * 100000),
ARelTurnoutId: int32(i - 12),
ARelTurnoutPoint: "A",
BRelTurnoutId: int32(i - 12 + 5),
BRelTurnoutPoint: "B",
})
}
slopes := []*Slope{{
ID: 1,
StartLinkId: 1,
StartLinkOffset: 1,
EndLinkId: 1,
EndLinkOffset: 1,
DegreeTrig: 1,
}}
curves := []*Curve{{
ID: 1,
StartLinkId: 1,
StartLinkOffset: 1,
EndLinkId: 1,
EndLinkOffset: 1,
Curvature: 1,
}}
base := LineBaseInfo{
LinkList: links,
SlopeList: slopes,
CurveList: curves,
}
return &base
}
func TestCalculationBase(t *testing.T) {
base := mockLineBaseInfo()
marshal, _ := json.Marshal(base)
println(string(marshal))
}

View File

@ -1,270 +0,0 @@
package dynamics
import (
"container/list"
"encoding/binary"
"errors"
"fmt"
"log/slog"
"math"
"net"
"sync"
"time"
"github.com/panjf2000/gnet/v2"
"go.uber.org/zap"
"joylink.club/bj-rtsts-server/config"
)
func init() {
go func() {
for {
info := <-trainInfoChan
for e := handlerList.Front(); e != nil; e = e.Next() {
func() {
defer func() {
r := recover()
if r != nil {
slog.Error("列车信息处理函数报错", "error", r)
}
}()
handler := e.Value.(TrainInfoHandler)
handler(info)
}()
}
}
}()
}
type TurnoutInfoFunc func() []*TurnoutInfo
var (
running bool
mutex sync.Mutex
turnoutInfoFunc TurnoutInfoFunc
//道岔消息生命信号
turnoutLifeSignal uint16
//列车消息生命信号
trainLifeSignal uint16
//列车生命信号是否初始化
trainLifeSignalInit bool
//用于处理生命信号循环使用产生的各种特殊处理
limit uint16 = 10000
//列车消息队列
trainInfoChan chan *TrainInfo = make(chan *TrainInfo)
)
var handlerList list.List
type TrainInfoHandler func(info *TrainInfo)
type udpServer struct {
gnet.BuiltinEventEngine
eng gnet.Engine
addr string
multicore bool
}
func (server *udpServer) OnBoot(eng gnet.Engine) gnet.Action {
server.eng = eng
slog.Info("udp server启动", "multicore", server.multicore, "listeningOn", server.addr)
return gnet.None
}
// OnTraffic 接收到数据后的解析
func (server *udpServer) OnTraffic(c gnet.Conn) gnet.Action {
defer func() {
if r := recover(); r != nil {
zap.L().Error("udp服务数据解析异常", zap.Any("panic", r))
}
}()
buf, _ := c.Next(-1)
lifeSignal := binary.BigEndian.Uint16(buf[0:2])
if !trainLifeSignalInit {
trainLifeSignalInit = true
} else if trainLifeSignal < limit {
if lifeSignal < trainLifeSignal || lifeSignal > trainLifeSignal-limit {
slog.Debug("丢弃列车信息", "lifeSignal", lifeSignal, "trainLifeSignal", trainLifeSignal)
return gnet.None
}
} else if trainLifeSignal < math.MaxUint16-10000 {
if lifeSignal < trainLifeSignal {
slog.Debug("丢弃列车信息", "lifeSignal", lifeSignal, "trainLifeSignal", trainLifeSignal)
return gnet.None
}
} else {
if lifeSignal < trainLifeSignal && lifeSignal > trainLifeSignal+10000 {
slog.Debug("丢弃列车信息", "lifeSignal", lifeSignal, "trainLifeSignal", trainLifeSignal)
return gnet.None
}
}
trainLifeSignal = lifeSignal
trainInfo := decoderDynamicsTrainInfo(buf)
trainInfoChan <- trainInfo
return gnet.None
}
func RunUdpServer() {
if !config.Config.Dynamics.Open {
return
}
server := &udpServer{addr: fmt.Sprintf("udp://:%d", config.Config.Dynamics.UdpLocalPort), multicore: false}
err := gnet.Run(server, server.addr, gnet.WithMulticore(server.multicore))
zap.L().Fatal("udp服务启动失败", zap.Error(err))
}
func Run(tiFunc TurnoutInfoFunc) error {
if !config.Config.Dynamics.Open {
return nil
}
mutex.Lock()
defer mutex.Unlock()
trainLifeSignalInit = false
return runSendTurnoutStateTask(tiFunc)
}
// 注册数据操作
func RegisterTrainInfoHandler(handler TrainInfoHandler) {
handlerList.PushBack(handler)
}
func Stop() {
mutex.Lock()
defer mutex.Unlock()
turnoutInfoFunc = nil
}
// 动力学消息发送消息
func sendDynamicsMsg(buf []byte) error {
defer func() {
if r := recover(); r != nil {
slog.Error("发送道岔信息失败", r)
}
}()
addr := fmt.Sprintf("%v:%v", config.Config.Dynamics.Ip, config.Config.Dynamics.UdpRemotePort)
remoteAddr, _ := net.ResolveUDPAddr("udp", addr)
conn, err := net.DialUDP("udp", nil, remoteAddr)
if err != nil {
slog.Error("UDP通信失败", err)
return err
}
defer func(conn *net.UDPConn) {
err := conn.Close()
if err != nil {
slog.Error("关闭UDP连接失败", "error", err)
}
}(conn)
_, err = conn.Write(buf)
return err
}
// 给动力学发送列车信息
func SendDynamicsTrainMsg(buf []byte) error {
defer func() {
if r := recover(); r != nil {
slog.Error("发送道岔信息失败", r)
}
}()
addr := fmt.Sprintf("%v:%v", config.Config.Dynamics.Ip, config.Config.Dynamics.UdpRemoteTrainPort)
remoteAddr, _ := net.ResolveUDPAddr("udp", addr)
conn, err := net.DialUDP("udp", nil, remoteAddr)
if err != nil {
slog.Error("UDP通信失败", err)
return err
}
defer func(conn *net.UDPConn) {
err := conn.Close()
if err != nil {
slog.Error("关闭UDP连接失败", "error", err)
}
}(conn)
_, err = conn.Write(buf)
return err
}
// 发送道岔状态任务
func runSendTurnoutStateTask(tiFunc TurnoutInfoFunc) error {
if running {
return nil
}
if tiFunc == nil {
return errors.New("tiFunc不能为空")
}
turnoutInfoFunc = tiFunc
go func() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
// 重新运行
doDynamicsTurnoutUDPRun()
}()
// 动力学UDP逻辑运行
doDynamicsTurnoutUDPRun()
}()
return nil
}
func doDynamicsTurnoutUDPRun() {
tick := time.Tick(50 * time.Millisecond)
for range tick {
if turnoutInfoFunc == nil {
continue
}
slice := turnoutInfoFunc()
for _, turnoutInfo := range slice {
turnoutInfo.lifeSignal = turnoutLifeSignal
// sendTurnoutInfo 发送道岔信息
err := sendDynamicsMsg(encoderDynamicsTurnout(turnoutInfo))
if err != nil {
slog.Error("发送道岔信息到动力学失败", "error", err)
}
}
turnoutLifeSignal++
}
}
// 解析动力学的列车信息
func decoderDynamicsTrainInfo(buf []byte) *TrainInfo {
trainInfo := &TrainInfo{}
trainInfo.LifeSignal = binary.BigEndian.Uint16(buf[0:2])
trainInfo.Number = buf[2]
trainInfo.Len = binary.BigEndian.Uint16(buf[3:5])
trainInfo.Link = buf[5]
trainInfo.LinkOffset = binary.BigEndian.Uint32(buf[6:10])
trainInfo.Slope = binary.BigEndian.Uint16(buf[10:12])
b := buf[12]
trainInfo.UpSlope = (b & (1 << 7)) != 0
trainInfo.Up = (b & (1 << 6)) != 0
trainInfo.TotalResistance = int32(binary.BigEndian.Uint32(buf[14:18]))
trainInfo.AirResistance = int32(binary.BigEndian.Uint32(buf[18:22]))
trainInfo.SlopeResistance = int32(binary.BigEndian.Uint32(buf[22:26]))
trainInfo.CurveResistance = int32(binary.BigEndian.Uint32(buf[26:30]))
trainInfo.Speed = math.Float32frombits(binary.BigEndian.Uint32(buf[30:34]))
trainInfo.HeadSpeed1 = math.Float32frombits(binary.BigEndian.Uint32(buf[34:38]))
trainInfo.HeadSpeed2 = math.Float32frombits(binary.BigEndian.Uint32(buf[38:42]))
trainInfo.TailSpeed1 = math.Float32frombits(binary.BigEndian.Uint32(buf[42:46]))
trainInfo.TailSpeed2 = math.Float32frombits(binary.BigEndian.Uint32(buf[46:50]))
trainInfo.HeadRadarSpeed = math.Float32frombits(binary.BigEndian.Uint32(buf[50:54]))
trainInfo.TailRadarSpeed = math.Float32frombits(binary.BigEndian.Uint32(buf[54:58]))
trainInfo.Acceleration = math.Float32frombits(binary.BigEndian.Uint32(buf[58:62]))
trainInfo.VobcLifeSignal = binary.BigEndian.Uint16(buf[62:64])
return trainInfo
}
// 将道岔转为动力学的消息
func encoderDynamicsTurnout(info *TurnoutInfo) []byte {
var data []byte
data = binary.BigEndian.AppendUint16(data, info.lifeSignal)
data = binary.BigEndian.AppendUint16(data, info.Code)
var b byte
if info.NPosition {
b |= 1 << 7
}
if info.RPosition {
b |= 1 << 6
}
data = append(data, b)
return data
}

View File

@ -1,53 +0,0 @@
package dynamics
type TurnoutInfo struct {
lifeSignal uint16
Code uint16
NPosition bool
RPosition bool
}
type TrainInfo struct {
//生命信号
LifeSignal uint16
//列车号(车辆)
Number uint8
//列车长度 cm
Len uint16
//列车所在轨道link
Link uint8
//列车所在link偏移量mm
LinkOffset uint32
//列车所在位置坡度值(‰)
Slope uint16
//列车所在位置坡度走势(上/下坡)
UpSlope bool
//列车当前运行方向(偏移量增大/减小方向)
Up bool
//实际运行阻力N
TotalResistance int32
//阻力1空气阻力N
AirResistance int32
//阻力2坡道阻力N
SlopeResistance int32
//阻力3曲线阻力N
CurveResistance int32
//列车运行速度m/s
Speed float32
//头车速传1速度值m/s
HeadSpeed1 float32
//头车速度2速度值m/s
HeadSpeed2 float32
//尾车速传1速度值m/s
TailSpeed1 float32
//尾车速度2速度值m/s
TailSpeed2 float32
//头车雷达速度值m/s
HeadRadarSpeed float32
//尾车雷达速度值m/s
TailRadarSpeed float32
//加速度(m/s^2)
Acceleration float32
// 对应动力学生命周期值
VobcLifeSignal uint16
}

View File

@ -1,210 +0,0 @@
package dynamics
import (
"encoding/hex"
"fmt"
"io"
"net"
"runtime"
"testing"
"time"
"github.com/panjf2000/gnet/v2"
"github.com/spf13/viper"
"joylink.club/bj-rtsts-server/config"
)
func TestRunUdpServer(t *testing.T) {
viper.AddConfigPath("../")
config.LoadConfig()
RegisterTrainInfoHandler(func(info *TrainInfo) {
fmt.Println("处理列车信息...")
fmt.Println(info)
})
RunUdpServer()
}
func TestSendTurnoutInfo(t *testing.T) {
viper.AddConfigPath("../")
config.LoadConfig()
tick := time.Tick(50 * time.Millisecond)
for range tick {
for i := 1; i <= 9; i++ {
sendDynamicsMsg(encoderDynamicsTurnout(&TurnoutInfo{
Code: uint16(i),
NPosition: true,
RPosition: false,
}))
}
}
}
func BenchmarkUdpServer_OnTraffic(b *testing.B) {
runtime.GOMAXPROCS(1) //1个协程
buf, _ := hex.DecodeString("0009012EE009000000070380000006000100020003000A000A000A000A000A000A000A")
// 创建 udpServer 对象
server := &udpServer{}
// 创建虚拟的 gnet.Conn 对象
conn := &virtualConn{
readBuffer: buf,
}
// 在 Benchmark 中运行测试
for i := 0; i < b.N; i++ {
server.OnTraffic(conn)
}
}
type virtualConn struct {
readBuffer []byte
}
func (vc *virtualConn) Read(p []byte) (n int, err error) {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) Write(p []byte) (n int, err error) {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) Context() (ctx interface{}) {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) SetContext(ctx interface{}) {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) Close() (err error) {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) WriteTo(w io.Writer) (n int64, err error) {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) Next(n int) (buf []byte, err error) {
//TODO implement me
return vc.readBuffer, nil
}
func (vc *virtualConn) Peek(n int) (buf []byte, err error) {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) Discard(n int) (discarded int, err error) {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) InboundBuffered() (n int) {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) ReadFrom(r io.Reader) (n int64, err error) {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) Writev(bs [][]byte) (n int, err error) {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) Flush() (err error) {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) OutboundBuffered() (n int) {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) AsyncWrite(buf []byte, callback gnet.AsyncCallback) (err error) {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) AsyncWritev(bs [][]byte, callback gnet.AsyncCallback) (err error) {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) Fd() int {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) Dup() (int, error) {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) SetReadBuffer(bytes int) error {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) SetWriteBuffer(bytes int) error {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) SetLinger(sec int) error {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) SetKeepAlivePeriod(d time.Duration) error {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) SetNoDelay(noDelay bool) error {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) LocalAddr() (addr net.Addr) {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) RemoteAddr() (addr net.Addr) {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) Wake(callback gnet.AsyncCallback) (err error) {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) CloseWithCallback(callback gnet.AsyncCallback) (err error) {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) SetDeadline(t time.Time) (err error) {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) SetReadDeadline(t time.Time) (err error) {
//TODO implement me
panic("implement me")
}
func (vc *virtualConn) SetWriteDeadline(t time.Time) (err error) {
//TODO implement me
panic("implement me")
}

View File

@ -1,185 +0,0 @@
package vobc
import (
"container/list"
"encoding/binary"
"fmt"
"log/slog"
"math"
"net"
"sync"
"github.com/panjf2000/gnet/v2"
"go.uber.org/zap"
"joylink.club/bj-rtsts-server/config"
)
var (
running bool
mutex sync.Mutex
receiveTrainLifeSignal uint16 //接收列车消息生命信号
sendTrainLifeSignal uint16 //发送的列车消息生命信号
trainLifeSignalInit bool //列车生命信号是否初始化
limit uint16 = 10000 //用于处理生命信号循环使用产生的各种特殊处理
vobcMsgInfoChan chan []byte = make(chan []byte) //列车消息队列
//处理方法列表
handlerList list.List
)
func init() {
go func() {
for {
info := <-vobcMsgInfoChan
for e := handlerList.Front(); e != nil; e = e.Next() {
func() {
defer func() {
r := recover()
if r != nil {
slog.Error("列车信息处理函数报错")
}
}()
handler := e.Value.(VobcDataHandler)
handler(info)
}()
}
}
}()
}
type VobcDataHandler func([]byte)
type udpServer struct {
gnet.BuiltinEventEngine
eng gnet.Engine
addr string
multicore bool
}
// udp 启动时运行
func (server *udpServer) OnBoot(eng gnet.Engine) gnet.Action {
server.eng = eng
slog.Info("vobc udp server 启动", "multicore", server.multicore, "addr", server.addr)
return gnet.None
}
// OnTraffic 接收到数据后的解析
func (server *udpServer) OnTraffic(c gnet.Conn) gnet.Action {
defer func() {
if r := recover(); r != nil {
zap.L().Error("vobc udp服务数据解析异常", zap.Any("panic", r))
}
}()
buf, _ := c.Next(-1)
lifeSignal := binary.BigEndian.Uint16(buf[0:2])
if !trainLifeSignalInit {
trainLifeSignalInit = true
} else if receiveTrainLifeSignal < limit {
if lifeSignal < receiveTrainLifeSignal || lifeSignal > receiveTrainLifeSignal-limit {
slog.Debug("丢弃列车信息", "lifeSignal", lifeSignal, "trainLifeSignal", receiveTrainLifeSignal)
return gnet.None
}
} else if receiveTrainLifeSignal < math.MaxUint16-10000 {
if lifeSignal < receiveTrainLifeSignal {
slog.Debug("丢弃列车信息", "lifeSignal", lifeSignal, "trainLifeSignal", receiveTrainLifeSignal)
return gnet.None
}
} else {
if lifeSignal < receiveTrainLifeSignal && lifeSignal > receiveTrainLifeSignal+10000 {
slog.Debug("丢弃列车信息", "lifeSignal", lifeSignal, "trainLifeSignal", receiveTrainLifeSignal)
return gnet.None
}
}
receiveTrainLifeSignal = lifeSignal
// trainInfo := decoderVobcTrainInfo(buf)
//消息队列
vobcMsgInfoChan <- buf
return gnet.None
}
// 注册处理vobc处理方法
func RegisterTrainInfoHandler(handler VobcDataHandler) {
handlerList.PushBack(handler)
}
// 创建UDP服务
func RunUdpServer() {
if !config.Config.Vobc.Open {
return
}
server := &udpServer{addr: fmt.Sprintf("udp://:%d", config.Config.Vobc.LocalPort), multicore: false}
err := gnet.Run(server, server.addr, gnet.WithMulticore(server.multicore))
zap.L().Fatal("vobc udp服务启动失败", zap.Error(err))
}
// 发送列车速度到VOBC
func SendTrainSpeedTask(speed float64) error {
if running {
return nil
}
mutex.Lock()
defer mutex.Unlock()
trainInfo := &SendTrainInfo{
LifeSignal: sendTrainLifeSignal,
Speed: uint16(speed),
}
err := sendVobcMsg(encoderVobcTrainInfo(trainInfo))
if err != nil {
slog.Error("发送Vobc信息失败", err)
}
sendTrainLifeSignal++
return err
}
// UDP停止
func Stop() {
mutex.Lock()
defer mutex.Unlock()
running = false
}
// Vobc 消息发送消息
func sendVobcMsg(buf []byte) error {
defer func() {
if r := recover(); r != nil {
slog.Error("发送列车速度信息失败", r)
}
}()
addr := fmt.Sprintf("%v:%v", config.Config.Vobc.Ip, config.Config.Vobc.RemotePort)
remoteAddr, _ := net.ResolveUDPAddr("udp", addr)
conn, err := net.DialUDP("udp", nil, remoteAddr)
if err != nil {
slog.Error("UDP通信失败", err)
return err
}
defer func(conn *net.UDPConn) {
err := conn.Close()
if err != nil {
slog.Error("Vobc UDP连接关闭失败", err)
}
}(conn)
_, err = conn.Write(buf)
return err
}
// 将道岔转为动力学的消息
func encoderVobcTrainInfo(info *SendTrainInfo) []byte {
var data []byte
data = binary.BigEndian.AppendUint16(data, info.LifeSignal)
data = binary.BigEndian.AppendUint16(data, info.Speed)
if info.Upslope {
data = append(data, 1)
} else {
data = append(data, 0)
}
// 中间预留一位
data = append(data, 0)
data = append(data, info.Acceleration) // 加速度 100 = 1 m/s*s
data = append(data, info.Deceleration) // 减速度 100 = 1 m/s*s
data = binary.BigEndian.AppendUint32(data, info.TotalResistance) // 实际运行阻力 100 = 1KN
data = binary.BigEndian.AppendUint32(data, info.AirResistance) // 空气阻力 100 = 1KN
data = binary.BigEndian.AppendUint32(data, info.SlopeResistance) // 坡道阻力 100 = 1KN
data = binary.BigEndian.AppendUint32(data, info.CurveResistance) // 曲线阻力 100 = 1KN
data = binary.BigEndian.AppendUint16(data, info.Slope) // 坡度值 1= 1‰
return data
}

View File

@ -1,115 +0,0 @@
package vobc
import "encoding/binary"
// 接收到的列车信息
type ReceiveTrainInfo struct {
//【0 1】两个字节
// 生命信号 每个周期+1
LifeSignal uint16
//【2】 一个字节
// TC1激活状态 1=激活
Tc1Active bool
// TC2激活状态 1=激活
Tc2Active bool
// 列车方向向前 1=方向向前
DirectionForward bool
// 列车方向向后 1=方向向后
DirectionBackward bool
// 列车牵引状态 1=牵引
TractionStatus bool
// 列车制动状态 1=制动
BrakingStatus bool
// 列车紧急制动状态 1=紧急制动
EmergencyBrakingStatus bool
// 列车折返状态AR 1=折返
TurnbackStatus bool
//【3】 一个字节
// 跳跃状态 1=跳跃
JumpStatus bool
// ATO模式 1=ATO模式
ATO bool
// FAM模式 1=FAM模式
FAM bool
// CAM模式 1=CAM模式
CAM bool
// 牵引安全回路 1=牵引安全切除
TractionSafetyCircuit bool
// 停放制动状态 1=停放施加
ParkingBrakeStatus bool
// 保持制动状态 1=保持制动施加
MaintainBrakeStatus bool
//【4 5】 两个字节 列车牵引力 100=1KN
TractionForce uint16
//【6 7】 列车制动力 100=1KN
BrakeForce uint16
//【8 9】 列车载荷 100=1ton
TrainLoad uint16
// 【15】 一个字节
// 列车开左门指令 1=开门
LeftDoorOpenCommand bool
// 列车开右门指令 1=开门
RightDoorOpenCommand bool
// 列车关左门指令 1=关门
LeftDoorCloseCommand bool
// 列车关右门指令 1=关门
RightDoorCloseCommand bool
// 整列车门关好 1=门关好
AllDoorClose bool
}
// 解析VOBC列车信息
func (r *ReceiveTrainInfo) DecoderVobcTrainInfo(buf []byte) *ReceiveTrainInfo {
r.LifeSignal = binary.BigEndian.Uint16(buf[0:2])
b2 := buf[2]
r.Tc1Active = (b2 & (1 << 7)) != 0
r.Tc2Active = (b2 & (1 << 6)) != 0
r.DirectionForward = (b2 & (1 << 5)) != 0
r.DirectionBackward = (b2 & (1 << 4)) != 0
r.TractionStatus = (b2 & (1 << 3)) != 0
r.BrakingStatus = (b2 & (1 << 2)) != 0
r.EmergencyBrakingStatus = (b2 & (1 << 1)) != 0
r.TurnbackStatus = (b2 & 1) != 0
b3 := buf[3]
r.JumpStatus = (b3 & (1 << 7)) != 0
r.ATO = (b3 & (1 << 6)) != 0
r.FAM = (b3 & (1 << 5)) != 0
r.CAM = (b3 & (1 << 4)) != 0
r.TractionSafetyCircuit = (b3 & (1 << 3)) != 0
r.ParkingBrakeStatus = (b3 & (1 << 2)) != 0
r.MaintainBrakeStatus = (b3 & (1 << 1)) != 0
r.TractionForce = binary.BigEndian.Uint16(buf[4:6])
r.BrakeForce = binary.BigEndian.Uint16(buf[6:8])
r.TrainLoad = binary.BigEndian.Uint16(buf[8:10])
b4 := buf[15]
r.LeftDoorOpenCommand = (b4 & (1 << 7)) != 0
r.RightDoorOpenCommand = (b4 & (1 << 6)) != 0
r.LeftDoorCloseCommand = (b4 & (1 << 5)) != 0
r.RightDoorCloseCommand = (b4 & (1 << 4)) != 0
r.AllDoorClose = (b4 & (1 << 3)) != 0
return r
}
// 发送列车信息
type SendTrainInfo struct {
// 生命信号 每个周期+1
LifeSignal uint16
// 列车速度 10=1km/h
Speed uint16
// 上坡
Upslope bool
// 坡度值 1= 1‰
Slope uint16
// 加速度 100 = 1 m/s*s
Acceleration uint8
// 减速度 100 = 1 m/s*s
Deceleration uint8
// 实际运行阻力 100 = 1KN
TotalResistance uint32
// 空气阻力 100 = 1KN
AirResistance uint32
// 坡道阻力 100 = 1KN
SlopeResistance uint32
// 曲线阻力 100 = 1KN
CurveResistance uint32
}

View File

@ -184,7 +184,8 @@ func (d *dynamics) Start(manager DynamicsMessageManager) error {
// 初始化运行资源
err := d.initDynamicsRunRepository()
if err != nil {
panic("启动动力学消息服务错误: 存在正在运行的任务")
d.Stop() // 发送错误后将信息销毁
panic(err)
}
ctx, cancle := context.WithCancel(context.Background())
go d.sendTurnoutStateTask(ctx)
@ -205,8 +206,7 @@ func (d *dynamics) initDynamics() {
// 动力学运行所需数据
func (d *dynamics) initDynamicsRunRepository() error {
// 动力学接口调用
lineBaseInfo := d.manager.GetDynamicsRunRepository()
err := d.requestStartSimulation(lineBaseInfo)
err := d.requestStartSimulation(d.manager.GetDynamicsRunRepository())
if err != nil {
return err
}
@ -229,8 +229,8 @@ func (d *dynamics) Stop() {
}
if d.turnoutTaskCancel != nil {
d.turnoutTaskCancel()
d.manager = nil
}
d.manager = nil
}
const (

View File

@ -15,8 +15,8 @@ import (
// 联锁代理通信接口
type InterlockMessageManager interface {
CollectRelayInfo() *message.InterlockSendMsgPkg
HandleDriverInfo(b []byte)
CollectInterlockRelayInfo() []*message.InterlockSendMsgPkg
HandleInterlockDriverInfo(b []byte)
GetInterlockRunConfig() *config.InterlockConfig
}
@ -55,7 +55,7 @@ type interlockProxy struct {
func (i *interlockProxy) handleDriverInfo(b []byte) {
handler := i.manager
if handler != nil {
handler.HandleDriverInfo(b)
handler.HandleInterlockDriverInfo(b)
}
}
@ -78,10 +78,11 @@ func (i *interlockProxy) Start(manager InterlockMessageManager) {
i.collectInfoTaskCancel = cancle
}
const (
// 采集电路状态发送间隔,单位ms
InterlockMessageSendInterval = 50
)
const InterlockMessageSendInterval = 50
// 序列号
var serialNumber uint8
// 定时发送采集电路状态任务
func (i *interlockProxy) collectInfoStateTask(ctx context.Context) {
@ -97,8 +98,12 @@ func (i *interlockProxy) collectInfoStateTask(ctx context.Context) {
return
default:
}
collectInfoStates := i.manager.CollectRelayInfo()
i.sendCollectUdpClient.SendMsg(collectInfoStates)
collectInfoStates := i.manager.CollectInterlockRelayInfo()
for _, state := range collectInfoStates {
serialNumber++
state.Header.SerialNumber = serialNumber
i.sendCollectUdpClient.SendMsg(state)
}
time.Sleep(time.Millisecond * InterlockMessageSendInterval)
}
}
@ -112,8 +117,8 @@ func (i *interlockProxy) Stop() {
}
if i.collectInfoTaskCancel != nil {
i.collectInfoTaskCancel()
i.manager = nil
}
i.manager = nil
}
func (i *interlockProxy) SendCollectMessage(b []byte) {

View File

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.28.1
// protoc v4.23.1
// source: ibpGraphics.proto
@ -773,10 +773,9 @@ var file_ibpGraphics_proto_rawDesc = []byte{
0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63,
0x44, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6d, 0x62, 0x69,
0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x52, 0x10, 0x63, 0x6f, 0x6d, 0x62,
0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x42, 0x21, 0x5a, 0x1f,
0x2e, 0x2f, 0x61, 0x74, 0x73, 0x2f, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x2f, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x73, 0x2f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x42, 0x19, 0x5a, 0x17,
0x2e, 0x2f, 0x74, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x67, 0x72, 0x61, 0x70,
0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

View File

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.28.1
// protoc v4.23.1
// source: picture.proto
@ -84,10 +84,9 @@ var file_picture_proto_rawDesc = []byte{
0x0a, 0x0d, 0x53, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x10,
0x00, 0x12, 0x07, 0x0a, 0x03, 0x50, 0x73, 0x6c, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x65,
0x6c, 0x61, 0x79, 0x43, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x4c, 0x61, 0x79, 0x6f, 0x75, 0x74,
0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x49, 0x42, 0x50, 0x10, 0x03, 0x42, 0x21, 0x5a, 0x1f, 0x2e,
0x2f, 0x61, 0x74, 0x73, 0x2f, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x2f, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x73, 0x2f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x49, 0x42, 0x50, 0x10, 0x03, 0x42, 0x19, 0x5a, 0x17, 0x2e,
0x2f, 0x74, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x67, 0x72, 0x61, 0x70, 0x68,
0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

View File

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.28.1
// protoc v4.23.1
// source: pslGraphics.proto
@ -499,9 +499,9 @@ var file_pslGraphics_proto_rawDesc = []byte{
0x0a, 0x0f, 0x50, 0x73, 0x6c, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6c, 0x6f,
0x72, 0x12, 0x07, 0x0a, 0x03, 0x72, 0x65, 0x64, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x67, 0x72,
0x65, 0x65, 0x6e, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x62, 0x6c, 0x75, 0x65, 0x10, 0x02, 0x42,
0x21, 0x5a, 0x1f, 0x2e, 0x2f, 0x61, 0x74, 0x73, 0x2f, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x2f,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61,
0x74, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x19, 0x5a, 0x17, 0x2e, 0x2f, 0x74, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x67,
0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
}
var (

View File

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.28.1
// protoc v4.23.1
// source: relayCabinetLayoutGraphics.proto
@ -87,6 +87,52 @@ func (Relay_ModelType) EnumDescriptor() ([]byte, []int) {
return file_relayCabinetLayoutGraphics_proto_rawDescGZIP(), []int{2, 0}
}
type CjDataItem_PostionType int32
const (
CjDataItem_Q CjDataItem_PostionType = 0
CjDataItem_H CjDataItem_PostionType = 1
)
// Enum value maps for CjDataItem_PostionType.
var (
CjDataItem_PostionType_name = map[int32]string{
0: "Q",
1: "H",
}
CjDataItem_PostionType_value = map[string]int32{
"Q": 0,
"H": 1,
}
)
func (x CjDataItem_PostionType) Enum() *CjDataItem_PostionType {
p := new(CjDataItem_PostionType)
*p = x
return p
}
func (x CjDataItem_PostionType) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (CjDataItem_PostionType) Descriptor() protoreflect.EnumDescriptor {
return file_relayCabinetLayoutGraphics_proto_enumTypes[1].Descriptor()
}
func (CjDataItem_PostionType) Type() protoreflect.EnumType {
return &file_relayCabinetLayoutGraphics_proto_enumTypes[1]
}
func (x CjDataItem_PostionType) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use CjDataItem_PostionType.Descriptor instead.
func (CjDataItem_PostionType) EnumDescriptor() ([]byte, []int) {
return file_relayCabinetLayoutGraphics_proto_rawDescGZIP(), []int{11, 0}
}
type RelayCabinetGraphicStorage struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@ -101,6 +147,8 @@ type RelayCabinetGraphicStorage struct {
PhaseFailureProtectors []*PhaseFailureProtector `protobuf:"bytes,7,rep,name=phaseFailureProtectors,proto3" json:"phaseFailureProtectors,omitempty"`
CombinationtypeList []*Combinationtype `protobuf:"bytes,8,rep,name=combinationtypeList,proto3" json:"combinationtypeList,omitempty"`
SignalFaultAlarms []*SignalFaultAlarm `protobuf:"bytes,9,rep,name=signalFaultAlarms,proto3" json:"signalFaultAlarms,omitempty"`
CiCjList *CiCj `protobuf:"bytes,10,opt,name=ciCjList,proto3" json:"ciCjList,omitempty"` //采集列表
CiQdList *CiQd `protobuf:"bytes,11,opt,name=ciQdList,proto3" json:"ciQdList,omitempty"` //驱动列表
}
func (x *RelayCabinetGraphicStorage) Reset() {
@ -191,6 +239,20 @@ func (x *RelayCabinetGraphicStorage) GetSignalFaultAlarms() []*SignalFaultAlarm
return nil
}
func (x *RelayCabinetGraphicStorage) GetCiCjList() *CiCj {
if x != nil {
return x.CiCjList
}
return nil
}
func (x *RelayCabinetGraphicStorage) GetCiQdList() *CiQd {
if x != nil {
return x.CiQdList
}
return nil
}
type RelayCabinet struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@ -607,6 +669,377 @@ func (x *UniqueIdType) GetBelongsConcentrationStation() string {
return ""
}
// 采集
type CiCj struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
DsCount int32 `protobuf:"varint,1,opt,name=dsCount,proto3" json:"dsCount,omitempty"` //数据集位数——对应着excel表行数
CjList []*CjDataSet `protobuf:"bytes,2,rep,name=cjList,proto3" json:"cjList,omitempty"` //采集列表二维数据数组长度对应着excel表列数--数据集个数)
}
func (x *CiCj) Reset() {
*x = CiCj{}
if protoimpl.UnsafeEnabled {
mi := &file_relayCabinetLayoutGraphics_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CiCj) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CiCj) ProtoMessage() {}
func (x *CiCj) ProtoReflect() protoreflect.Message {
mi := &file_relayCabinetLayoutGraphics_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CiCj.ProtoReflect.Descriptor instead.
func (*CiCj) Descriptor() ([]byte, []int) {
return file_relayCabinetLayoutGraphics_proto_rawDescGZIP(), []int{8}
}
func (x *CiCj) GetDsCount() int32 {
if x != nil {
return x.DsCount
}
return 0
}
func (x *CiCj) GetCjList() []*CjDataSet {
if x != nil {
return x.CjList
}
return nil
}
type CjDataSet struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` //对应着excel中的列名如'D1'
BitList []*CjData `protobuf:"bytes,2,rep,name=bitList,proto3" json:"bitList,omitempty"` //对应着excel中的一列的数据
}
func (x *CjDataSet) Reset() {
*x = CjDataSet{}
if protoimpl.UnsafeEnabled {
mi := &file_relayCabinetLayoutGraphics_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CjDataSet) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CjDataSet) ProtoMessage() {}
func (x *CjDataSet) ProtoReflect() protoreflect.Message {
mi := &file_relayCabinetLayoutGraphics_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CjDataSet.ProtoReflect.Descriptor instead.
func (*CjDataSet) Descriptor() ([]byte, []int) {
return file_relayCabinetLayoutGraphics_proto_rawDescGZIP(), []int{9}
}
func (x *CjDataSet) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *CjDataSet) GetBitList() []*CjData {
if x != nil {
return x.BitList
}
return nil
}
type CjData struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
RefRelays []*CjDataItem `protobuf:"bytes,1,rep,name=refRelays,proto3" json:"refRelays,omitempty"` //采集的继电器
}
func (x *CjData) Reset() {
*x = CjData{}
if protoimpl.UnsafeEnabled {
mi := &file_relayCabinetLayoutGraphics_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CjData) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CjData) ProtoMessage() {}
func (x *CjData) ProtoReflect() protoreflect.Message {
mi := &file_relayCabinetLayoutGraphics_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CjData.ProtoReflect.Descriptor instead.
func (*CjData) Descriptor() ([]byte, []int) {
return file_relayCabinetLayoutGraphics_proto_rawDescGZIP(), []int{10}
}
func (x *CjData) GetRefRelays() []*CjDataItem {
if x != nil {
return x.RefRelays
}
return nil
}
type CjDataItem struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
RelayId string `protobuf:"bytes,1,opt,name=relayId,proto3" json:"relayId,omitempty"` //采集对应的继电器Id
Position CjDataItem_PostionType `protobuf:"varint,2,opt,name=position,proto3,enum=relayCabinetGraphicData.CjDataItem_PostionType" json:"position,omitempty"` //继电器的位置QH对应着吸合
}
func (x *CjDataItem) Reset() {
*x = CjDataItem{}
if protoimpl.UnsafeEnabled {
mi := &file_relayCabinetLayoutGraphics_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CjDataItem) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CjDataItem) ProtoMessage() {}
func (x *CjDataItem) ProtoReflect() protoreflect.Message {
mi := &file_relayCabinetLayoutGraphics_proto_msgTypes[11]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CjDataItem.ProtoReflect.Descriptor instead.
func (*CjDataItem) Descriptor() ([]byte, []int) {
return file_relayCabinetLayoutGraphics_proto_rawDescGZIP(), []int{11}
}
func (x *CjDataItem) GetRelayId() string {
if x != nil {
return x.RelayId
}
return ""
}
func (x *CjDataItem) GetPosition() CjDataItem_PostionType {
if x != nil {
return x.Position
}
return CjDataItem_Q
}
// 驱动
type CiQd struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
DsCount int32 `protobuf:"varint,1,opt,name=dsCount,proto3" json:"dsCount,omitempty"` //数据集位数——对应着excel表行数
QdList []*QdDataSet `protobuf:"bytes,2,rep,name=qdList,proto3" json:"qdList,omitempty"` //驱动列表二维数据数组长度对应着excel表列数--数据集个数)
}
func (x *CiQd) Reset() {
*x = CiQd{}
if protoimpl.UnsafeEnabled {
mi := &file_relayCabinetLayoutGraphics_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CiQd) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CiQd) ProtoMessage() {}
func (x *CiQd) ProtoReflect() protoreflect.Message {
mi := &file_relayCabinetLayoutGraphics_proto_msgTypes[12]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CiQd.ProtoReflect.Descriptor instead.
func (*CiQd) Descriptor() ([]byte, []int) {
return file_relayCabinetLayoutGraphics_proto_rawDescGZIP(), []int{12}
}
func (x *CiQd) GetDsCount() int32 {
if x != nil {
return x.DsCount
}
return 0
}
func (x *CiQd) GetQdList() []*QdDataSet {
if x != nil {
return x.QdList
}
return nil
}
type QdDataSet struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` //对应着excel中的列名如'D1'
BitList []*QdData `protobuf:"bytes,2,rep,name=bitList,proto3" json:"bitList,omitempty"` //对应着excel中的一列的数据
}
func (x *QdDataSet) Reset() {
*x = QdDataSet{}
if protoimpl.UnsafeEnabled {
mi := &file_relayCabinetLayoutGraphics_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *QdDataSet) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*QdDataSet) ProtoMessage() {}
func (x *QdDataSet) ProtoReflect() protoreflect.Message {
mi := &file_relayCabinetLayoutGraphics_proto_msgTypes[13]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use QdDataSet.ProtoReflect.Descriptor instead.
func (*QdDataSet) Descriptor() ([]byte, []int) {
return file_relayCabinetLayoutGraphics_proto_rawDescGZIP(), []int{13}
}
func (x *QdDataSet) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *QdDataSet) GetBitList() []*QdData {
if x != nil {
return x.BitList
}
return nil
}
type QdData struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
RefRelays []string `protobuf:"bytes,1,rep,name=refRelays,proto3" json:"refRelays,omitempty"` //驱动的继电器Id
}
func (x *QdData) Reset() {
*x = QdData{}
if protoimpl.UnsafeEnabled {
mi := &file_relayCabinetLayoutGraphics_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *QdData) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*QdData) ProtoMessage() {}
func (x *QdData) ProtoReflect() protoreflect.Message {
mi := &file_relayCabinetLayoutGraphics_proto_msgTypes[14]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use QdData.ProtoReflect.Descriptor instead.
func (*QdData) Descriptor() ([]byte, []int) {
return file_relayCabinetLayoutGraphics_proto_rawDescGZIP(), []int{14}
}
func (x *QdData) GetRefRelays() []string {
if x != nil {
return x.RefRelays
}
return nil
}
var File_relayCabinetLayoutGraphics_proto protoreflect.FileDescriptor
var file_relayCabinetLayoutGraphics_proto_rawDesc = []byte{
@ -615,7 +1048,7 @@ var file_relayCabinetLayoutGraphics_proto_rawDesc = []byte{
0x74, 0x6f, 0x12, 0x17, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x43, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74,
0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x1a, 0x1b, 0x73, 0x74, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69,
0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x9c, 0x05, 0x0a, 0x1a, 0x52, 0x65, 0x6c,
0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x92, 0x06, 0x0a, 0x1a, 0x52, 0x65, 0x6c,
0x61, 0x79, 0x43, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63,
0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x2b, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x76, 0x61,
0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69,
@ -657,70 +1090,116 @@ var file_relayCabinetLayoutGraphics_proto_rawDesc = []byte{
0x79, 0x43, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44,
0x61, 0x74, 0x61, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x41,
0x6c, 0x61, 0x72, 0x6d, 0x52, 0x11, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x46, 0x61, 0x75, 0x6c,
0x74, 0x41, 0x6c, 0x61, 0x72, 0x6d, 0x73, 0x22, 0x53, 0x0a, 0x0c, 0x52, 0x65, 0x6c, 0x61, 0x79,
0x43, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69,
0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f,
0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0xac, 0x02, 0x0a,
0x05, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63,
0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52,
0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x44, 0x0a, 0x08, 0x6e,
0x65, 0x77, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e,
0x72, 0x65, 0x6c, 0x61, 0x79, 0x43, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x47, 0x72, 0x61, 0x70,
0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x2e, 0x4d, 0x6f,
0x64, 0x65, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, 0x6e, 0x65, 0x77, 0x4d, 0x6f, 0x64, 0x65,
0x6c, 0x22, 0x97, 0x01, 0x0a, 0x09, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12,
0x0b, 0x0a, 0x07, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09,
0x4a, 0x50, 0x58, 0x43, 0x5f, 0x31, 0x30, 0x30, 0x30, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4a,
0x50, 0x58, 0x43, 0x5f, 0x31, 0x37, 0x30, 0x30, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x57,
0x4a, 0x58, 0x43, 0x5f, 0x34, 0x38, 0x30, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x4a, 0x57, 0x4a,
0x58, 0x43, 0x5f, 0x48, 0x31, 0x32, 0x35, 0x5f, 0x38, 0x30, 0x10, 0x04, 0x12, 0x0d, 0x0a, 0x09,
0x4a, 0x57, 0x58, 0x43, 0x5f, 0x31, 0x37, 0x30, 0x30, 0x10, 0x05, 0x12, 0x0d, 0x0a, 0x09, 0x4a,
0x57, 0x58, 0x43, 0x5f, 0x48, 0x33, 0x34, 0x30, 0x10, 0x06, 0x12, 0x11, 0x0a, 0x0d, 0x4a, 0x59,
0x4a, 0x58, 0x43, 0x5f, 0x31, 0x36, 0x30, 0x5f, 0x32, 0x36, 0x30, 0x10, 0x07, 0x12, 0x0c, 0x0a,
0x08, 0x4a, 0x5a, 0x58, 0x43, 0x5f, 0x48, 0x31, 0x38, 0x10, 0x08, 0x22, 0x5c, 0x0a, 0x15, 0x50,
0x68, 0x61, 0x73, 0x65, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x65,
0x63, 0x74, 0x6f, 0x72, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61,
0x74, 0x61, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x63,
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0x57, 0x0a, 0x10, 0x53, 0x69, 0x67,
0x6e, 0x61, 0x6c, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x6c, 0x61, 0x72, 0x6d, 0x12, 0x2f, 0x0a,
0x74, 0x41, 0x6c, 0x61, 0x72, 0x6d, 0x73, 0x12, 0x39, 0x0a, 0x08, 0x63, 0x69, 0x43, 0x6a, 0x4c,
0x69, 0x73, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x6c, 0x61,
0x79, 0x43, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44,
0x61, 0x74, 0x61, 0x2e, 0x43, 0x69, 0x43, 0x6a, 0x52, 0x08, 0x63, 0x69, 0x43, 0x6a, 0x4c, 0x69,
0x73, 0x74, 0x12, 0x39, 0x0a, 0x08, 0x63, 0x69, 0x51, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x0b,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x43, 0x61, 0x62, 0x69,
0x6e, 0x65, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43,
0x69, 0x51, 0x64, 0x52, 0x08, 0x63, 0x69, 0x51, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x53, 0x0a,
0x0c, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x43, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x12, 0x2f, 0x0a,
0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e,
0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6f, 0x6d, 0x6d,
0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x12, 0x12,
0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f,
0x64, 0x65, 0x22, 0xc1, 0x01, 0x0a, 0x11, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x6c,
0x61, 0x74, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65,
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x54, 0x0a, 0x10,
0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x73,
0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x43, 0x61,
0x64, 0x65, 0x22, 0xac, 0x02, 0x0a, 0x05, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x2f, 0x0a, 0x06,
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67,
0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f,
0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x12, 0x12, 0x0a,
0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64,
0x65, 0x12, 0x44, 0x0a, 0x08, 0x6e, 0x65, 0x77, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x04, 0x20,
0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x43, 0x61, 0x62, 0x69, 0x6e,
0x65, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x52, 0x65,
0x6c, 0x61, 0x79, 0x2e, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, 0x6e,
0x65, 0x77, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x22, 0x97, 0x01, 0x0a, 0x09, 0x4d, 0x6f, 0x64, 0x65,
0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e,
0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x50, 0x58, 0x43, 0x5f, 0x31, 0x30, 0x30, 0x30, 0x10,
0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x50, 0x58, 0x43, 0x5f, 0x31, 0x37, 0x30, 0x30, 0x10, 0x02,
0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x57, 0x4a, 0x58, 0x43, 0x5f, 0x34, 0x38, 0x30, 0x10, 0x03, 0x12,
0x11, 0x0a, 0x0d, 0x4a, 0x57, 0x4a, 0x58, 0x43, 0x5f, 0x48, 0x31, 0x32, 0x35, 0x5f, 0x38, 0x30,
0x10, 0x04, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x57, 0x58, 0x43, 0x5f, 0x31, 0x37, 0x30, 0x30, 0x10,
0x05, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x57, 0x58, 0x43, 0x5f, 0x48, 0x33, 0x34, 0x30, 0x10, 0x06,
0x12, 0x11, 0x0a, 0x0d, 0x4a, 0x59, 0x4a, 0x58, 0x43, 0x5f, 0x31, 0x36, 0x30, 0x5f, 0x32, 0x36,
0x30, 0x10, 0x07, 0x12, 0x0c, 0x0a, 0x08, 0x4a, 0x5a, 0x58, 0x43, 0x5f, 0x48, 0x31, 0x38, 0x10,
0x08, 0x22, 0x5c, 0x0a, 0x15, 0x50, 0x68, 0x61, 0x73, 0x65, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72,
0x65, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f,
0x6d, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x72, 0x61,
0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x49,
0x6e, 0x66, 0x6f, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x63,
0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22,
0x57, 0x0a, 0x10, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x6c,
0x61, 0x72, 0x6d, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74,
0x61, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x63, 0x6f,
0x6d, 0x6d, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0xc1, 0x01, 0x0a, 0x11, 0x44, 0x65, 0x76,
0x69, 0x63, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x12,
0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f,
0x64, 0x65, 0x12, 0x54, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x72,
0x65, 0x6c, 0x61, 0x79, 0x43, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68,
0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x52, 0x10, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x0a, 0x64, 0x65, 0x76, 0x69,
0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x67,
0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74,
0x65, 0x64, 0x52, 0x65, 0x66, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65,
0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0x43, 0x0a, 0x0f,
0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x12,
0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63,
0x6f, 0x64, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x66, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x73,
0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x66, 0x52, 0x65, 0x6c, 0x61, 0x79,
0x73, 0x22, 0x7c, 0x0a, 0x0c, 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x49, 0x64, 0x54, 0x79, 0x70,
0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x04, 0x63, 0x69, 0x74, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x12, 0x40, 0x0a,
0x1b, 0x62, 0x65, 0x6c, 0x6f, 0x6e, 0x67, 0x73, 0x43, 0x6f, 0x6e, 0x63, 0x65, 0x6e, 0x74, 0x72,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01,
0x28, 0x09, 0x52, 0x1b, 0x62, 0x65, 0x6c, 0x6f, 0x6e, 0x67, 0x73, 0x43, 0x6f, 0x6e, 0x63, 0x65,
0x6e, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22,
0x5c, 0x0a, 0x04, 0x43, 0x69, 0x43, 0x6a, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x73, 0x43, 0x6f, 0x75,
0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x64, 0x73, 0x43, 0x6f, 0x75, 0x6e,
0x74, 0x12, 0x3a, 0x0a, 0x06, 0x63, 0x6a, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x43, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74,
0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6a, 0x44, 0x61,
0x74, 0x61, 0x53, 0x65, 0x74, 0x52, 0x06, 0x63, 0x6a, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x5a, 0x0a,
0x09, 0x43, 0x6a, 0x44, 0x61, 0x74, 0x61, 0x53, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x39,
0x0a, 0x07, 0x62, 0x69, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x1f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x43, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x47, 0x72,
0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6a, 0x44, 0x61, 0x74, 0x61,
0x52, 0x07, 0x62, 0x69, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x4b, 0x0a, 0x06, 0x43, 0x6a, 0x44,
0x61, 0x74, 0x61, 0x12, 0x41, 0x0a, 0x09, 0x72, 0x65, 0x66, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x73,
0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x43, 0x61,
0x62, 0x69, 0x6e, 0x65, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61,
0x2e, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x74, 0x79, 0x70, 0x65,
0x52, 0x10, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x74, 0x79, 0x70,
0x65, 0x73, 0x12, 0x42, 0x0a, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65,
0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63,
0x44, 0x61, 0x74, 0x61, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x66, 0x2e,
0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69,
0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0x43, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64,
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x0a,
0x09, 0x72, 0x65, 0x66, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09,
0x52, 0x09, 0x72, 0x65, 0x66, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x22, 0x7c, 0x0a, 0x0c, 0x55,
0x6e, 0x69, 0x71, 0x75, 0x65, 0x49, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63,
0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x69, 0x74, 0x79, 0x12,
0x16, 0x0a, 0x06, 0x6c, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
0x06, 0x6c, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x12, 0x40, 0x0a, 0x1b, 0x62, 0x65, 0x6c, 0x6f, 0x6e,
0x67, 0x73, 0x43, 0x6f, 0x6e, 0x63, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53,
0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1b, 0x62, 0x65,
0x6c, 0x6f, 0x6e, 0x67, 0x73, 0x43, 0x6f, 0x6e, 0x63, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x21, 0x5a, 0x1f, 0x2e, 0x2f, 0x61,
0x74, 0x73, 0x2f, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
0x2f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x62, 0x06, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x33,
0x2e, 0x43, 0x6a, 0x44, 0x61, 0x74, 0x61, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x09, 0x72, 0x65, 0x66,
0x52, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x22, 0x90, 0x01, 0x0a, 0x0a, 0x43, 0x6a, 0x44, 0x61, 0x74,
0x61, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x49, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x49, 0x64, 0x12,
0x4b, 0x0a, 0x08, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28,
0x0e, 0x32, 0x2f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x43, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74,
0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6a, 0x44, 0x61,
0x74, 0x61, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79,
0x70, 0x65, 0x52, 0x08, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x1b, 0x0a, 0x0b,
0x50, 0x6f, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x05, 0x0a, 0x01, 0x51,
0x10, 0x00, 0x12, 0x05, 0x0a, 0x01, 0x48, 0x10, 0x01, 0x22, 0x5c, 0x0a, 0x04, 0x43, 0x69, 0x51,
0x64, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01,
0x28, 0x05, 0x52, 0x07, 0x64, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x3a, 0x0a, 0x06, 0x71,
0x64, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65,
0x6c, 0x61, 0x79, 0x43, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69,
0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x51, 0x64, 0x44, 0x61, 0x74, 0x61, 0x53, 0x65, 0x74, 0x52,
0x06, 0x71, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x5a, 0x0a, 0x09, 0x51, 0x64, 0x44, 0x61, 0x74,
0x61, 0x53, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x07, 0x62, 0x69, 0x74, 0x4c,
0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, 0x65, 0x6c, 0x61,
0x79, 0x43, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44,
0x61, 0x74, 0x61, 0x2e, 0x51, 0x64, 0x44, 0x61, 0x74, 0x61, 0x52, 0x07, 0x62, 0x69, 0x74, 0x4c,
0x69, 0x73, 0x74, 0x22, 0x26, 0x0a, 0x06, 0x51, 0x64, 0x44, 0x61, 0x74, 0x61, 0x12, 0x1c, 0x0a,
0x09, 0x72, 0x65, 0x66, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09,
0x52, 0x09, 0x72, 0x65, 0x66, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x42, 0x19, 0x5a, 0x17, 0x2e,
0x2f, 0x74, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x67, 0x72, 0x61, 0x70, 0x68,
0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@ -735,43 +1214,59 @@ func file_relayCabinetLayoutGraphics_proto_rawDescGZIP() []byte {
return file_relayCabinetLayoutGraphics_proto_rawDescData
}
var file_relayCabinetLayoutGraphics_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_relayCabinetLayoutGraphics_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
var file_relayCabinetLayoutGraphics_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
var file_relayCabinetLayoutGraphics_proto_msgTypes = make([]protoimpl.MessageInfo, 15)
var file_relayCabinetLayoutGraphics_proto_goTypes = []interface{}{
(Relay_ModelType)(0), // 0: relayCabinetGraphicData.Relay.ModelType
(*RelayCabinetGraphicStorage)(nil), // 1: relayCabinetGraphicData.RelayCabinetGraphicStorage
(*RelayCabinet)(nil), // 2: relayCabinetGraphicData.RelayCabinet
(*Relay)(nil), // 3: relayCabinetGraphicData.Relay
(*PhaseFailureProtector)(nil), // 4: relayCabinetGraphicData.PhaseFailureProtector
(*SignalFaultAlarm)(nil), // 5: relayCabinetGraphicData.SignalFaultAlarm
(*DeviceRelateRelay)(nil), // 6: relayCabinetGraphicData.DeviceRelateRelay
(*Combinationtype)(nil), // 7: relayCabinetGraphicData.Combinationtype
(*UniqueIdType)(nil), // 8: relayCabinetGraphicData.UniqueIdType
(*Canvas)(nil), // 9: graphicData.Canvas
(*CommonInfo)(nil), // 10: graphicData.CommonInfo
(RelatedRef_DeviceType)(0), // 11: graphicData.RelatedRef.DeviceType
(CjDataItem_PostionType)(0), // 1: relayCabinetGraphicData.CjDataItem.PostionType
(*RelayCabinetGraphicStorage)(nil), // 2: relayCabinetGraphicData.RelayCabinetGraphicStorage
(*RelayCabinet)(nil), // 3: relayCabinetGraphicData.RelayCabinet
(*Relay)(nil), // 4: relayCabinetGraphicData.Relay
(*PhaseFailureProtector)(nil), // 5: relayCabinetGraphicData.PhaseFailureProtector
(*SignalFaultAlarm)(nil), // 6: relayCabinetGraphicData.SignalFaultAlarm
(*DeviceRelateRelay)(nil), // 7: relayCabinetGraphicData.DeviceRelateRelay
(*Combinationtype)(nil), // 8: relayCabinetGraphicData.Combinationtype
(*UniqueIdType)(nil), // 9: relayCabinetGraphicData.UniqueIdType
(*CiCj)(nil), // 10: relayCabinetGraphicData.CiCj
(*CjDataSet)(nil), // 11: relayCabinetGraphicData.CjDataSet
(*CjData)(nil), // 12: relayCabinetGraphicData.CjData
(*CjDataItem)(nil), // 13: relayCabinetGraphicData.CjDataItem
(*CiQd)(nil), // 14: relayCabinetGraphicData.CiQd
(*QdDataSet)(nil), // 15: relayCabinetGraphicData.QdDataSet
(*QdData)(nil), // 16: relayCabinetGraphicData.QdData
(*Canvas)(nil), // 17: graphicData.Canvas
(*CommonInfo)(nil), // 18: graphicData.CommonInfo
(RelatedRef_DeviceType)(0), // 19: graphicData.RelatedRef.DeviceType
}
var file_relayCabinetLayoutGraphics_proto_depIdxs = []int32{
9, // 0: relayCabinetGraphicData.RelayCabinetGraphicStorage.canvas:type_name -> graphicData.Canvas
2, // 1: relayCabinetGraphicData.RelayCabinetGraphicStorage.relayCabinets:type_name -> relayCabinetGraphicData.RelayCabinet
3, // 2: relayCabinetGraphicData.RelayCabinetGraphicStorage.relays:type_name -> relayCabinetGraphicData.Relay
6, // 3: relayCabinetGraphicData.RelayCabinetGraphicStorage.deviceRelateRelayList:type_name -> relayCabinetGraphicData.DeviceRelateRelay
8, // 4: relayCabinetGraphicData.RelayCabinetGraphicStorage.UniqueIdPrefix:type_name -> relayCabinetGraphicData.UniqueIdType
4, // 5: relayCabinetGraphicData.RelayCabinetGraphicStorage.phaseFailureProtectors:type_name -> relayCabinetGraphicData.PhaseFailureProtector
7, // 6: relayCabinetGraphicData.RelayCabinetGraphicStorage.combinationtypeList:type_name -> relayCabinetGraphicData.Combinationtype
5, // 7: relayCabinetGraphicData.RelayCabinetGraphicStorage.signalFaultAlarms:type_name -> relayCabinetGraphicData.SignalFaultAlarm
10, // 8: relayCabinetGraphicData.RelayCabinet.common:type_name -> graphicData.CommonInfo
10, // 9: relayCabinetGraphicData.Relay.common:type_name -> graphicData.CommonInfo
0, // 10: relayCabinetGraphicData.Relay.newModel:type_name -> relayCabinetGraphicData.Relay.ModelType
10, // 11: relayCabinetGraphicData.PhaseFailureProtector.common:type_name -> graphicData.CommonInfo
10, // 12: relayCabinetGraphicData.SignalFaultAlarm.common:type_name -> graphicData.CommonInfo
7, // 13: relayCabinetGraphicData.DeviceRelateRelay.combinationtypes:type_name -> relayCabinetGraphicData.Combinationtype
11, // 14: relayCabinetGraphicData.DeviceRelateRelay.deviceType:type_name -> graphicData.RelatedRef.DeviceType
15, // [15:15] is the sub-list for method output_type
15, // [15:15] is the sub-list for method input_type
15, // [15:15] is the sub-list for extension type_name
15, // [15:15] is the sub-list for extension extendee
0, // [0:15] is the sub-list for field type_name
17, // 0: relayCabinetGraphicData.RelayCabinetGraphicStorage.canvas:type_name -> graphicData.Canvas
3, // 1: relayCabinetGraphicData.RelayCabinetGraphicStorage.relayCabinets:type_name -> relayCabinetGraphicData.RelayCabinet
4, // 2: relayCabinetGraphicData.RelayCabinetGraphicStorage.relays:type_name -> relayCabinetGraphicData.Relay
7, // 3: relayCabinetGraphicData.RelayCabinetGraphicStorage.deviceRelateRelayList:type_name -> relayCabinetGraphicData.DeviceRelateRelay
9, // 4: relayCabinetGraphicData.RelayCabinetGraphicStorage.UniqueIdPrefix:type_name -> relayCabinetGraphicData.UniqueIdType
5, // 5: relayCabinetGraphicData.RelayCabinetGraphicStorage.phaseFailureProtectors:type_name -> relayCabinetGraphicData.PhaseFailureProtector
8, // 6: relayCabinetGraphicData.RelayCabinetGraphicStorage.combinationtypeList:type_name -> relayCabinetGraphicData.Combinationtype
6, // 7: relayCabinetGraphicData.RelayCabinetGraphicStorage.signalFaultAlarms:type_name -> relayCabinetGraphicData.SignalFaultAlarm
10, // 8: relayCabinetGraphicData.RelayCabinetGraphicStorage.ciCjList:type_name -> relayCabinetGraphicData.CiCj
14, // 9: relayCabinetGraphicData.RelayCabinetGraphicStorage.ciQdList:type_name -> relayCabinetGraphicData.CiQd
18, // 10: relayCabinetGraphicData.RelayCabinet.common:type_name -> graphicData.CommonInfo
18, // 11: relayCabinetGraphicData.Relay.common:type_name -> graphicData.CommonInfo
0, // 12: relayCabinetGraphicData.Relay.newModel:type_name -> relayCabinetGraphicData.Relay.ModelType
18, // 13: relayCabinetGraphicData.PhaseFailureProtector.common:type_name -> graphicData.CommonInfo
18, // 14: relayCabinetGraphicData.SignalFaultAlarm.common:type_name -> graphicData.CommonInfo
8, // 15: relayCabinetGraphicData.DeviceRelateRelay.combinationtypes:type_name -> relayCabinetGraphicData.Combinationtype
19, // 16: relayCabinetGraphicData.DeviceRelateRelay.deviceType:type_name -> graphicData.RelatedRef.DeviceType
11, // 17: relayCabinetGraphicData.CiCj.cjList:type_name -> relayCabinetGraphicData.CjDataSet
12, // 18: relayCabinetGraphicData.CjDataSet.bitList:type_name -> relayCabinetGraphicData.CjData
13, // 19: relayCabinetGraphicData.CjData.refRelays:type_name -> relayCabinetGraphicData.CjDataItem
1, // 20: relayCabinetGraphicData.CjDataItem.position:type_name -> relayCabinetGraphicData.CjDataItem.PostionType
15, // 21: relayCabinetGraphicData.CiQd.qdList:type_name -> relayCabinetGraphicData.QdDataSet
16, // 22: relayCabinetGraphicData.QdDataSet.bitList:type_name -> relayCabinetGraphicData.QdData
23, // [23:23] is the sub-list for method output_type
23, // [23:23] is the sub-list for method input_type
23, // [23:23] is the sub-list for extension type_name
23, // [23:23] is the sub-list for extension extendee
0, // [0:23] is the sub-list for field type_name
}
func init() { file_relayCabinetLayoutGraphics_proto_init() }
@ -877,14 +1372,98 @@ func file_relayCabinetLayoutGraphics_proto_init() {
return nil
}
}
file_relayCabinetLayoutGraphics_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CiCj); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_relayCabinetLayoutGraphics_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CjDataSet); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_relayCabinetLayoutGraphics_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CjData); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_relayCabinetLayoutGraphics_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CjDataItem); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_relayCabinetLayoutGraphics_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CiQd); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_relayCabinetLayoutGraphics_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*QdDataSet); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_relayCabinetLayoutGraphics_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*QdData); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_relayCabinetLayoutGraphics_proto_rawDesc,
NumEnums: 1,
NumMessages: 8,
NumEnums: 2,
NumMessages: 15,
NumExtensions: 0,
NumServices: 0,
},

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.28.1
// protoc v4.23.1
// source: device_state.proto
@ -149,6 +149,58 @@ func (Signal_Aspect) EnumDescriptor() ([]byte, []int) {
return file_device_state_proto_rawDescGZIP(), []int{4, 0}
}
type SimulationStatus_SimulationState int32
const (
SimulationStatus_PAUSE SimulationStatus_SimulationState = 0
SimulationStatus_START SimulationStatus_SimulationState = 1
SimulationStatus_ERROR SimulationStatus_SimulationState = 2
SimulationStatus_DESTROY SimulationStatus_SimulationState = 3
)
// Enum value maps for SimulationStatus_SimulationState.
var (
SimulationStatus_SimulationState_name = map[int32]string{
0: "PAUSE",
1: "START",
2: "ERROR",
3: "DESTROY",
}
SimulationStatus_SimulationState_value = map[string]int32{
"PAUSE": 0,
"START": 1,
"ERROR": 2,
"DESTROY": 3,
}
)
func (x SimulationStatus_SimulationState) Enum() *SimulationStatus_SimulationState {
p := new(SimulationStatus_SimulationState)
*p = x
return p
}
func (x SimulationStatus_SimulationState) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (SimulationStatus_SimulationState) Descriptor() protoreflect.EnumDescriptor {
return file_device_state_proto_enumTypes[2].Descriptor()
}
func (SimulationStatus_SimulationState) Type() protoreflect.EnumType {
return &file_device_state_proto_enumTypes[2]
}
func (x SimulationStatus_SimulationState) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use SimulationStatus_SimulationState.Descriptor instead.
func (SimulationStatus_SimulationState) EnumDescriptor() ([]byte, []int) {
return file_device_state_proto_rawDescGZIP(), []int{19, 0}
}
// 相邻端点定义的link的状态
type LinkState struct {
state protoimpl.MessageState
@ -1879,9 +1931,8 @@ type SimulationStatus struct {
unknownFields protoimpl.UnknownFields
SimulationId string `protobuf:"bytes,1,opt,name=simulationId,proto3" json:"simulationId,omitempty"`
MapId int32 `protobuf:"varint,2,opt,name=mapId,proto3" json:"mapId,omitempty"`
ProjectId int32 `protobuf:"varint,3,opt,name=projectId,proto3" json:"projectId,omitempty"`
MapIds []int32 `protobuf:"varint,4,rep,packed,name=mapIds,proto3" json:"mapIds,omitempty"`
State SimulationStatus_SimulationState `protobuf:"varint,2,opt,name=state,proto3,enum=state.SimulationStatus_SimulationState" json:"state,omitempty"`
Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
}
func (x *SimulationStatus) Reset() {
@ -1923,89 +1974,18 @@ func (x *SimulationStatus) GetSimulationId() string {
return ""
}
func (x *SimulationStatus) GetMapId() int32 {
func (x *SimulationStatus) GetState() SimulationStatus_SimulationState {
if x != nil {
return x.MapId
return x.State
}
return 0
return SimulationStatus_PAUSE
}
func (x *SimulationStatus) GetProjectId() int32 {
func (x *SimulationStatus) GetDescription() string {
if x != nil {
return x.ProjectId
return x.Description
}
return 0
}
func (x *SimulationStatus) GetMapIds() []int32 {
if x != nil {
return x.MapIds
}
return nil
}
// 变更信息状态
type MemoryDataStatus struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
AllSimulations []*SimulationStatus `protobuf:"bytes,1,rep,name=allSimulations,proto3" json:"allSimulations,omitempty"`
AddSimulations []*SimulationStatus `protobuf:"bytes,2,rep,name=addSimulations,proto3" json:"addSimulations,omitempty"`
RemoveSimulations []*SimulationStatus `protobuf:"bytes,3,rep,name=removeSimulations,proto3" json:"removeSimulations,omitempty"`
}
func (x *MemoryDataStatus) Reset() {
*x = MemoryDataStatus{}
if protoimpl.UnsafeEnabled {
mi := &file_device_state_proto_msgTypes[20]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *MemoryDataStatus) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*MemoryDataStatus) ProtoMessage() {}
func (x *MemoryDataStatus) ProtoReflect() protoreflect.Message {
mi := &file_device_state_proto_msgTypes[20]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use MemoryDataStatus.ProtoReflect.Descriptor instead.
func (*MemoryDataStatus) Descriptor() ([]byte, []int) {
return file_device_state_proto_rawDescGZIP(), []int{20}
}
func (x *MemoryDataStatus) GetAllSimulations() []*SimulationStatus {
if x != nil {
return x.AllSimulations
}
return nil
}
func (x *MemoryDataStatus) GetAddSimulations() []*SimulationStatus {
if x != nil {
return x.AddSimulations
}
return nil
}
func (x *MemoryDataStatus) GetRemoveSimulations() []*SimulationStatus {
if x != nil {
return x.RemoveSimulations
}
return nil
return ""
}
var File_device_state_proto protoreflect.FileDescriptor
@ -2275,38 +2255,29 @@ var file_device_state_proto_rawDesc = []byte{
0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x35, 0x0a, 0x09, 0x61, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74,
0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65,
0x2e, 0x41, 0x6c, 0x6c, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75,
0x73, 0x52, 0x09, 0x61, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x82, 0x01, 0x0a,
0x73, 0x52, 0x09, 0x61, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xd8, 0x01, 0x0a,
0x10, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75,
0x73, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49,
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x70, 0x49, 0x64, 0x18, 0x02,
0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6d, 0x61, 0x70, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x70,
0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09,
0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x70,
0x49, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x05, 0x52, 0x06, 0x6d, 0x61, 0x70, 0x49, 0x64,
0x73, 0x22, 0xdb, 0x01, 0x0a, 0x10, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x44, 0x61, 0x74, 0x61,
0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x3f, 0x0a, 0x0e, 0x61, 0x6c, 0x6c, 0x53, 0x69, 0x6d,
0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17,
0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0e, 0x61, 0x6c, 0x6c, 0x53, 0x69, 0x6d, 0x75,
0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3f, 0x0a, 0x0e, 0x61, 0x64, 0x64, 0x53, 0x69,
0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x17, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0e, 0x61, 0x64, 0x64, 0x53, 0x69, 0x6d,
0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x45, 0x0a, 0x11, 0x72, 0x65, 0x6d, 0x6f,
0x76, 0x65, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x69, 0x6d, 0x75,
0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x11, 0x72, 0x65,
0x6d, 0x6f, 0x76, 0x65, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2a,
0x37, 0x0a, 0x0b, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x07,
0x0a, 0x03, 0x41, 0x6e, 0x79, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x41, 0x78, 0x6c, 0x65, 0x10,
0x01, 0x12, 0x09, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06,
0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x10, 0x03, 0x42, 0x54, 0x0a, 0x25, 0x63, 0x6c, 0x75, 0x62,
0x2e, 0x6a, 0x6f, 0x79, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x62, 0x6a, 0x72, 0x74, 0x73, 0x73, 0x2e,
0x61, 0x74, 0x73, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x73, 0x42, 0x10, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x50, 0x72,
0x6f, 0x74, 0x6f, 0x5a, 0x19, 0x2e, 0x2f, 0x61, 0x74, 0x73, 0x2f, 0x76, 0x65, 0x72, 0x69, 0x66,
0x79, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, 0x06,
0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x3d, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02,
0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x69, 0x6d,
0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x53, 0x69,
0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73,
0x74, 0x61, 0x74, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72,
0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3f, 0x0a, 0x0f, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x41, 0x55,
0x53, 0x45, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x54, 0x41, 0x52, 0x54, 0x10, 0x01, 0x12,
0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45,
0x53, 0x54, 0x52, 0x4f, 0x59, 0x10, 0x03, 0x2a, 0x37, 0x0a, 0x0b, 0x53, 0x65, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x6e, 0x79, 0x10, 0x00, 0x12,
0x08, 0x0a, 0x04, 0x41, 0x78, 0x6c, 0x65, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x4c, 0x6f, 0x67,
0x69, 0x63, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x10, 0x03,
0x42, 0x4c, 0x0a, 0x25, 0x63, 0x6c, 0x75, 0x62, 0x2e, 0x6a, 0x6f, 0x79, 0x6c, 0x69, 0x6e, 0x6b,
0x2e, 0x62, 0x6a, 0x72, 0x74, 0x73, 0x73, 0x2e, 0x61, 0x74, 0x73, 0x2e, 0x76, 0x65, 0x72, 0x69,
0x66, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x42, 0x10, 0x44, 0x65, 0x76, 0x69, 0x63,
0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x11, 0x2e, 0x2f, 0x74,
0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
@ -2322,62 +2293,60 @@ func file_device_state_proto_rawDescGZIP() []byte {
return file_device_state_proto_rawDescData
}
var file_device_state_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
var file_device_state_proto_msgTypes = make([]protoimpl.MessageInfo, 21)
var file_device_state_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
var file_device_state_proto_msgTypes = make([]protoimpl.MessageInfo, 20)
var file_device_state_proto_goTypes = []interface{}{
(SectionType)(0), // 0: state.SectionType
(Signal_Aspect)(0), // 1: state.Signal.Aspect
(*LinkState)(nil), // 2: state.LinkState
(*SectionState)(nil), // 3: state.SectionState
(*SwitchState)(nil), // 4: state.SwitchState
(*SignalState)(nil), // 5: state.SignalState
(*Signal)(nil), // 6: state.Signal
(*PlatformState)(nil), // 7: state.PlatformState
(*StationState)(nil), // 8: state.StationState
(*TrainState)(nil), // 9: state.TrainState
(*TrainDynamicState)(nil), // 10: state.TrainDynamicState
(*TrainVobcState)(nil), // 11: state.TrainVobcState
(*ReplyState)(nil), // 12: state.ReplyState
(*ButtonState)(nil), // 13: state.ButtonState
(*AlarmState)(nil), // 14: state.AlarmState
(*LightState)(nil), // 15: state.LightState
(*PsdState)(nil), // 16: state.PsdState
(*KeyState)(nil), // 17: state.KeyState
(*VariationStatus)(nil), // 18: state.VariationStatus
(*AllDevicesStatus)(nil), // 19: state.AllDevicesStatus
(*PushedDevicesStatus)(nil), // 20: state.PushedDevicesStatus
(*SimulationStatus)(nil), // 21: state.SimulationStatus
(*MemoryDataStatus)(nil), // 22: state.MemoryDataStatus
(SimulationStatus_SimulationState)(0), // 2: state.SimulationStatus.SimulationState
(*LinkState)(nil), // 3: state.LinkState
(*SectionState)(nil), // 4: state.SectionState
(*SwitchState)(nil), // 5: state.SwitchState
(*SignalState)(nil), // 6: state.SignalState
(*Signal)(nil), // 7: state.Signal
(*PlatformState)(nil), // 8: state.PlatformState
(*StationState)(nil), // 9: state.StationState
(*TrainState)(nil), // 10: state.TrainState
(*TrainDynamicState)(nil), // 11: state.TrainDynamicState
(*TrainVobcState)(nil), // 12: state.TrainVobcState
(*ReplyState)(nil), // 13: state.ReplyState
(*ButtonState)(nil), // 14: state.ButtonState
(*AlarmState)(nil), // 15: state.AlarmState
(*LightState)(nil), // 16: state.LightState
(*PsdState)(nil), // 17: state.PsdState
(*KeyState)(nil), // 18: state.KeyState
(*VariationStatus)(nil), // 19: state.VariationStatus
(*AllDevicesStatus)(nil), // 20: state.AllDevicesStatus
(*PushedDevicesStatus)(nil), // 21: state.PushedDevicesStatus
(*SimulationStatus)(nil), // 22: state.SimulationStatus
}
var file_device_state_proto_depIdxs = []int32{
0, // 0: state.SectionState.type:type_name -> state.SectionType
1, // 1: state.SignalState.aspect:type_name -> state.Signal.Aspect
10, // 2: state.TrainState.dynamicState:type_name -> state.TrainDynamicState
11, // 3: state.TrainState.vobcState:type_name -> state.TrainVobcState
9, // 4: state.VariationStatus.updatedTrain:type_name -> state.TrainState
4, // 5: state.VariationStatus.updatedSwitch:type_name -> state.SwitchState
3, // 6: state.VariationStatus.updatedSection:type_name -> state.SectionState
12, // 7: state.VariationStatus.updatedReply:type_name -> state.ReplyState
9, // 8: state.AllDevicesStatus.trainState:type_name -> state.TrainState
4, // 9: state.AllDevicesStatus.switchState:type_name -> state.SwitchState
3, // 10: state.AllDevicesStatus.sectionState:type_name -> state.SectionState
12, // 11: state.AllDevicesStatus.replyState:type_name -> state.ReplyState
5, // 12: state.AllDevicesStatus.signalState:type_name -> state.SignalState
13, // 13: state.AllDevicesStatus.buttonState:type_name -> state.ButtonState
14, // 14: state.AllDevicesStatus.AlarmState:type_name -> state.AlarmState
15, // 15: state.AllDevicesStatus.LightState:type_name -> state.LightState
16, // 16: state.AllDevicesStatus.psdState:type_name -> state.PsdState
17, // 17: state.AllDevicesStatus.KeyState:type_name -> state.KeyState
18, // 18: state.PushedDevicesStatus.varStatus:type_name -> state.VariationStatus
19, // 19: state.PushedDevicesStatus.allStatus:type_name -> state.AllDevicesStatus
21, // 20: state.MemoryDataStatus.allSimulations:type_name -> state.SimulationStatus
21, // 21: state.MemoryDataStatus.addSimulations:type_name -> state.SimulationStatus
21, // 22: state.MemoryDataStatus.removeSimulations:type_name -> state.SimulationStatus
23, // [23:23] is the sub-list for method output_type
23, // [23:23] is the sub-list for method input_type
23, // [23:23] is the sub-list for extension type_name
23, // [23:23] is the sub-list for extension extendee
0, // [0:23] is the sub-list for field type_name
11, // 2: state.TrainState.dynamicState:type_name -> state.TrainDynamicState
12, // 3: state.TrainState.vobcState:type_name -> state.TrainVobcState
10, // 4: state.VariationStatus.updatedTrain:type_name -> state.TrainState
5, // 5: state.VariationStatus.updatedSwitch:type_name -> state.SwitchState
4, // 6: state.VariationStatus.updatedSection:type_name -> state.SectionState
13, // 7: state.VariationStatus.updatedReply:type_name -> state.ReplyState
10, // 8: state.AllDevicesStatus.trainState:type_name -> state.TrainState
5, // 9: state.AllDevicesStatus.switchState:type_name -> state.SwitchState
4, // 10: state.AllDevicesStatus.sectionState:type_name -> state.SectionState
13, // 11: state.AllDevicesStatus.replyState:type_name -> state.ReplyState
6, // 12: state.AllDevicesStatus.signalState:type_name -> state.SignalState
14, // 13: state.AllDevicesStatus.buttonState:type_name -> state.ButtonState
15, // 14: state.AllDevicesStatus.AlarmState:type_name -> state.AlarmState
16, // 15: state.AllDevicesStatus.LightState:type_name -> state.LightState
17, // 16: state.AllDevicesStatus.psdState:type_name -> state.PsdState
18, // 17: state.AllDevicesStatus.KeyState:type_name -> state.KeyState
19, // 18: state.PushedDevicesStatus.varStatus:type_name -> state.VariationStatus
20, // 19: state.PushedDevicesStatus.allStatus:type_name -> state.AllDevicesStatus
2, // 20: state.SimulationStatus.state:type_name -> state.SimulationStatus.SimulationState
21, // [21:21] is the sub-list for method output_type
21, // [21:21] is the sub-list for method input_type
21, // [21:21] is the sub-list for extension type_name
21, // [21:21] is the sub-list for extension extendee
0, // [0:21] is the sub-list for field type_name
}
func init() { file_device_state_proto_init() }
@ -2626,26 +2595,14 @@ func file_device_state_proto_init() {
return nil
}
}
file_device_state_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*MemoryDataStatus); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_device_state_proto_rawDesc,
NumEnums: 2,
NumMessages: 21,
NumEnums: 3,
NumMessages: 20,
NumExtensions: 0,
NumServices: 0,
},

View File

@ -2,10 +2,6 @@ package memory
import (
"joylink.club/bj-rtsts-server/ts/protos/graphicData"
"joylink.club/bj-rtsts-server/ts/protos/state"
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
"joylink.club/rtsssimulation/fi"
)
@ -24,74 +20,3 @@ func ChangeIBPKeyState(sim *VerifySimulation, mapId int32, stationId, keyCode st
stationUid := QueryUidByMidAndComId(mapId, stationId, &graphicData.Station{})
fi.SwitchKeyGear(sim.World, stationUid+"_key_"+keyCode, gear)
}
// 获取仿真车站按钮状态,前端推送
func GetMapAllIBPState(sim *VerifySimulation, mapId int32, stationId, ibpMapCode string) *state.AllDevicesStatus {
status := &state.AllDevicesStatus{
ButtonState: []*state.ButtonState{},
LightState: []*state.LightState{},
AlarmState: []*state.AlarmState{},
KeyState: []*state.KeyState{},
}
stationUid := QueryUidByMidAndComId(mapId, stationId, &graphicData.Station{})
ibpStorage := getStorageIBPMapData(ibpMapCode)
for _, data := range ibpStorage.IbpButtons { // 按钮
entry, ok := entity.GetEntityByUid(sim.World, stationUid+"_button_"+data.Code)
if !ok {
continue
}
if entry.HasComponent(component.ButtonTag) {
status.ButtonState = append(status.ButtonState, getIBPButtonState(data.Common.Id, entry))
}
}
for _, data := range ibpStorage.IbpAlarms { // 报警器
entry, ok := entity.GetEntityByUid(sim.World, stationUid+"_alarm_"+data.Code)
if !ok {
continue
}
if entry.HasComponent(component.AlarmTag) {
status.AlarmState = append(status.AlarmState, &state.AlarmState{
Id: data.Common.Id,
Active: component.BitStateType.Get(entry).Val,
})
}
}
for _, data := range ibpStorage.IbpLights { // 指示灯
entry, ok := entity.GetEntityByUid(sim.World, stationUid+"_light_"+data.Code)
if !ok {
continue
}
if entry.HasComponent(component.LightTag) {
status.LightState = append(status.LightState, &state.LightState{
Id: data.Common.Id,
Active: component.BitStateType.Get(entry).Val,
})
}
}
for _, data := range ibpStorage.IbpKeys { // 钥匙
entry, ok := entity.GetEntityByUid(sim.World, stationUid+"_key_"+data.Code)
if !ok {
continue
}
if entry.HasComponent(component.KeyTag) {
status.KeyState = append(status.KeyState, &state.KeyState{
Id: data.Common.Id,
Gear: component.GearStateType.Get(entry).Val,
})
}
}
return status
}
// 获取IBP盘按钮状态
func getIBPButtonState(id string, entry *ecs.Entry) *state.ButtonState {
status := &state.ButtonState{Id: id}
bit := component.BitStateType.Get(entry)
status.Down = bit.Val
// 如果按钮包含灯
if entry.HasComponent(component.SingleLightType) {
lightComponent := component.SingleLightType.Get(entry)
status.Active = component.BitStateType.Get(lightComponent.Light).Val
}
return status
}

View File

@ -86,6 +86,14 @@ func QueryGiType(mapId int32) graphicData.PictureType {
return value.(graphicData.PictureType)
}
func QueryOnlyGiType(mapId int32) graphicData.PictureType {
value, ok := giTypeMap.Load(mapId)
if !ok {
panic(sys_error.New(fmt.Sprintf("[mapId:%d]不存在", mapId)))
}
return value.(graphicData.PictureType)
}
func QueryGiData[T proto.Message](mapId int32) T {
value, _ := giDataMap.Load(mapId)
return value.(T)
@ -108,7 +116,7 @@ func QueryEcsLinkByDeviceInfo(repo *repository.Repository, mapId int32, status *
}
}
func getStorageIBPMapData(mapCode string) *graphicData.IBPGraphicStorage {
func GetStorageIBPMapData(mapCode string) *graphicData.IBPGraphicStorage {
// 处理关联的IBP盘信息
if mapCode == "" {
return nil

View File

@ -19,7 +19,7 @@ type elementIdStructure struct {
}
// 数组为Index为 common.ButtonCode, index, uid
type stationUidStructure struct {
type StationUidStructure struct {
AxlePointIds map[string]*elementIdStructure
TurnoutIds map[string]*elementIdStructure
PhysicalSectionIds map[string]*elementIdStructure
@ -34,7 +34,7 @@ type stationUidStructure struct {
GateBoxIds map[string]*elementIdStructure
}
type relayUidStructure struct {
type RelayUidStructure struct {
RelayCabinetIds map[string]*elementIdStructure
RelayIds map[string]*elementIdStructure
}
@ -65,8 +65,8 @@ func getUIdPrefix(prefix interface{}) (string, string, string) {
}
// 初始化平面布置图 UID
func initStationUid(data *graphicData.RtssGraphicStorage) *stationUidStructure {
gus := &stationUidStructure{
func initStationUid(data *graphicData.RtssGraphicStorage) *StationUidStructure {
gus := &StationUidStructure{
AxlePointIds: make(map[string]*elementIdStructure, len(data.AxleCountings)),
TurnoutIds: make(map[string]*elementIdStructure, len(data.Turnouts)),
PhysicalSectionIds: make(map[string]*elementIdStructure, len(data.Section)),
@ -201,8 +201,8 @@ func initStationUid(data *graphicData.RtssGraphicStorage) *stationUidStructure {
}
// 初始化继电器柜 UID
func initRelayCabinetUid(data *graphicData.RelayCabinetGraphicStorage) *relayUidStructure {
rus := &relayUidStructure{
func initRelayCabinetUid(data *graphicData.RelayCabinetGraphicStorage) *RelayUidStructure {
rus := &RelayUidStructure{
RelayCabinetIds: make(map[string]*elementIdStructure, len(data.RelayCabinets)),
RelayIds: make(map[string]*elementIdStructure, len(data.Relays)),
}
@ -277,7 +277,7 @@ func buildRepositoryAllUidsMap(mapIds []int32, repo *repository.Repository) map[
if !ok {
continue
}
u, ok := d.(*stationUidStructure)
u, ok := d.(*StationUidStructure)
if ok {
saveToAllUidMap(u.AxlePointIds)
saveToAllUidMap(u.PhysicalSectionIds)
@ -294,7 +294,7 @@ func buildRepositoryAllUidsMap(mapIds []int32, repo *repository.Repository) map[
}
// 获取地图UID的映射集合
func queryUidStructure[T *stationUidStructure | *relayUidStructure](mapId int32) T {
func QueryUidStructure[T *StationUidStructure | *RelayUidStructure](mapId int32) T {
uidData, ok := giUidMap.Load(mapId)
if !ok {
panic(fmt.Errorf("id=%d的发布图没有uid缓存数据", mapId))
@ -306,27 +306,27 @@ func queryUidStructure[T *stationUidStructure | *relayUidStructure](mapId int32)
func getUidMapByType(uidData any, m interface{}) map[string]*elementIdStructure {
switch m.(type) {
case *graphicData.AxleCounting:
return (uidData.(*stationUidStructure)).AxlePointIds
return (uidData.(*StationUidStructure)).AxlePointIds
case *graphicData.Turnout:
return (uidData.(*stationUidStructure)).TurnoutIds
return (uidData.(*StationUidStructure)).TurnoutIds
case *graphicData.Section:
return (uidData.(*stationUidStructure)).PhysicalSectionIds
return (uidData.(*StationUidStructure)).PhysicalSectionIds
case *graphicData.Signal:
return (uidData.(*stationUidStructure)).SignalIds
return (uidData.(*StationUidStructure)).SignalIds
case *graphicData.Transponder:
return (uidData.(*stationUidStructure)).TransponderIds
return (uidData.(*StationUidStructure)).TransponderIds
case *graphicData.Slope:
return (uidData.(*stationUidStructure)).SlopeIds
return (uidData.(*StationUidStructure)).SlopeIds
case *graphicData.Curvature:
return (uidData.(*stationUidStructure)).CurvatureIds
return (uidData.(*StationUidStructure)).CurvatureIds
case *graphicData.RelayCabinet:
return (uidData.(*relayUidStructure)).RelayCabinetIds
return (uidData.(*RelayUidStructure)).RelayCabinetIds
case *graphicData.Relay:
return (uidData.(*relayUidStructure)).RelayIds
return (uidData.(*RelayUidStructure)).RelayIds
case *graphicData.EsbButton:
return (uidData.(*stationUidStructure)).ButtonIds
return (uidData.(*StationUidStructure)).ButtonIds
case *graphicData.Station:
return (uidData.(*stationUidStructure)).StationIds
return (uidData.(*StationUidStructure)).StationIds
default:
panic(&dto.ErrorDto{Code: dto.ArgumentParseError, Message: "类型未映射字段"})
}

View File

@ -1,50 +1 @@
package memory
import (
"joylink.club/bj-rtsts-server/ts/protos/graphicData"
"joylink.club/bj-rtsts-server/ts/protos/state"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
)
// 获取所有的列车信息
func GetMapAllPsdState(vs *VerifySimulation, mapId int32) []*state.PsdState {
world := vs.GetSimulationWorld()
uidStructure := queryUidStructure[*stationUidStructure](mapId)
data := QueryGiData[*graphicData.RtssGraphicStorage](mapId)
var psdStateArr []*state.PsdState
for _, door := range data.ScreenDoors {
uid := uidStructure.PsdIds[door.Common.Id].Uid
psdEntry, ok := entity.GetEntityByUid(world, uid)
if ok {
var amount int32
psdState := component.PsdStateType.Get(psdEntry)
if psdState.Km8 {
amount = 8
} else if psdState.Km4 {
amount = 4
} else {
amount = 0
}
start, end := getStartEndCodeByGroup(door, amount)
var openSubDoor []int32
for i := start; i <= end; i++ {
openSubDoor = append(openSubDoor, i)
}
psdStateArr = append(psdStateArr, &state.PsdState{
Id: door.Common.Id,
OpenDoorCodes: openSubDoor,
})
}
}
return psdStateArr
}
func getStartEndCodeByGroup(door *graphicData.ScreenDoor, groupAmount int32) (int32, int32) {
for _, group := range door.ScreenDoorGroupList {
if group.TrainGroupAmount == groupAmount {
return group.StartSmallDoor, group.EndSmallDoor
}
}
return 0, -1
}

View File

@ -4,9 +4,9 @@ import (
"joylink.club/rtsssimulation/fi"
)
// 操作IBP按钮
// 操作PSL按钮
func ChangePSLButtonState(sim *VerifySimulation, mapId int32, gateBoxId, btnCode string, pressDown bool) {
uid := queryUidStructure[*stationUidStructure](mapId)
uid := QueryUidStructure[*StationUidStructure](mapId)
gateBoxUid := uid.GateBoxIds[gateBoxId].Uid
if pressDown {
fi.PressDownButton(sim.World, gateBoxUid+"_"+btnCode)

View File

@ -2,9 +2,6 @@ package memory
import (
"joylink.club/bj-rtsts-server/ts/protos/graphicData"
"joylink.club/bj-rtsts-server/ts/protos/state"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
"joylink.club/rtsssimulation/fi"
)
@ -17,21 +14,3 @@ func ChangeRelayState(sim *VerifySimulation, mapId int32, id string, td bool) {
fi.DriveRelayDown(sim.World, uid)
}
}
// 获取仿真地图的继电器状态,前端推送
func GetMapAllRelayState(sim *VerifySimulation, mapId int32) []*state.ReplyState {
// 获取本地图下的继电器信息
uidMap := QueryMapUidMapByType(mapId, &graphicData.Relay{})
var replyStateArr []*state.ReplyState
for _, u := range uidMap {
entry, ok := entity.GetEntityByUid(sim.World, u.Uid)
if !ok {
continue
}
if entry.HasComponent(component.RelayTag) {
bit := component.BitStateType.Get(entry)
replyStateArr = append(replyStateArr, &state.ReplyState{Id: u.CommonId, Xh: bit.Val})
}
}
return replyStateArr
}

View File

@ -6,41 +6,9 @@ import (
"joylink.club/bj-rtsts-server/dto"
"joylink.club/bj-rtsts-server/dto/request_proto"
"joylink.club/bj-rtsts-server/ts/protos/graphicData"
"joylink.club/bj-rtsts-server/ts/protos/state"
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
"joylink.club/rtsssimulation/fi"
)
func GetMapAllSectionState(sim *VerifySimulation, mapId int32) []*state.SectionState {
uidMap := QueryMapUidMapByType(mapId, &graphicData.Section{})
var sectionArr []*state.SectionState
for _, u := range uidMap {
s := handlerSectionState(sim.World, u.Uid)
if s == nil {
continue
}
s.Id = u.CommonId
sectionArr = append(sectionArr, s)
}
return sectionArr
}
func handlerSectionState(w ecs.World, uid string) *state.SectionState {
entry, ok := entity.GetEntityByUid(w, uid)
if !ok {
//fmt.Printf("id=%s的信号机不存在", uid)
return nil
}
if entry.HasComponent(component.AxleSectionTag) { //计轴区段
sectionState := &state.SectionState{}
axleState := component.AxleSectionStateType.Get(entry)
sectionState.Occupied = axleState.Occ
sectionState.Type = state.SectionType_Axle
return sectionState
}
return nil
}
func ChangeAxleSectionState(simulation *VerifySimulation, req *dto.AxleSectionOperationReqDto) {
sectionUid := QueryUidByMidAndComId(req.MapId, req.DeviceId, &graphicData.Section{})
slog.Debug("操作计轴区段", "axleSectionUid", sectionUid)

View File

@ -9,10 +9,8 @@ import (
"joylink.club/bj-rtsts-server/ts/protos/graphicData"
"joylink.club/bj-rtsts-server/ts/protos/state"
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/component/component_proto"
"joylink.club/rtsssimulation/consts"
"joylink.club/rtsssimulation/entity"
"joylink.club/rtsssimulation/fi"
"joylink.club/rtsssimulation/repository"
"joylink.club/rtsssimulation/repository/model/proto"
@ -228,66 +226,3 @@ func changeSignal2XH1State(w ecs.World, signalUid string, toAspect state.Signal_
panic(dto.ErrorDto{Code: dto.OperationOfSignalNotSupported, Message: dto.ErrorTipMap[dto.OperationOfSignalNotSupported]})
}
}
// 获取仿真地图的信号机状态,用于推送给前端
func GetMapAllSignalState(sim *VerifySimulation, mapId int32) []*state.SignalState {
uidMap := QueryMapUidMapByType(mapId, &graphicData.Signal{})
var signalArr []*state.SignalState
for _, u := range uidMap {
s := handlerSignalState(sim.World, u.Uid)
if s == nil {
continue
}
s.Id = u.CommonId
signalArr = append(signalArr, s)
}
return signalArr
}
func handlerSignalState(w ecs.World, uid string) *state.SignalState {
entry, ok := entity.GetEntityByUid(w, uid)
if !ok {
//fmt.Printf("id=%s的信号机不存在", uid)
return nil
}
if !entry.HasComponent(component.SignalLightsType) { //信号机灯列表
return nil
}
signalState := &state.SignalState{}
lights := component.SignalLightsType.Get(entry)
isL := false
isH := false
isU := false
isA := false
isB := false
for _, light := range lights.Lights {
switch {
case light.HasComponent(component.LdTag):
isL = component.BitStateType.Get(light).Val
case light.HasComponent(component.HdTag):
isH = component.BitStateType.Get(light).Val
case light.HasComponent(component.UdTag):
isU = component.BitStateType.Get(light).Val
case light.HasComponent(component.BdTag):
isB = component.BitStateType.Get(light).Val
case light.HasComponent(component.AdTag):
isA = component.BitStateType.Get(light).Val
}
}
if isH && isU {
signalState.Aspect = state.Signal_HU
} else {
switch {
case isL:
signalState.Aspect = state.Signal_L
case isH:
signalState.Aspect = state.Signal_H
case isU:
signalState.Aspect = state.Signal_U
case isB:
signalState.Aspect = state.Signal_B
case isA:
signalState.Aspect = state.Signal_A
}
}
return signalState
}

View File

@ -2,13 +2,10 @@ package memory
import (
"joylink.club/bj-rtsts-server/ts/protos/graphicData"
"joylink.club/bj-rtsts-server/ts/protos/state"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
"joylink.club/rtsssimulation/fi"
)
// 操作IBP按钮
// 操作esb按钮
func ChangeEsbButtonState(sim *VerifySimulation, mapId int32, btnId string, pressDown bool) {
uid := QueryUidByMidAndComId(mapId, btnId, &graphicData.EsbButton{})
if pressDown {
@ -17,21 +14,3 @@ func ChangeEsbButtonState(sim *VerifySimulation, mapId int32, btnId string, pres
fi.PressUpButton(sim.World, uid)
}
}
// 获取仿真车站按钮状态,前端推送
func GetMapAllStationButtonState(sim *VerifySimulation, mapId int32) []*state.ButtonState {
// 获取地图上的按钮状态
var btnStateArr []*state.ButtonState
uidMap := QueryMapUidMapByType(mapId, &graphicData.EsbButton{})
for _, u := range uidMap {
entry, ok := entity.GetEntityByUid(sim.World, u.Uid)
if !ok {
continue
}
if entry.HasComponent(component.ButtonTag) { // 按钮
bit := component.BitStateType.Get(entry)
btnStateArr = append(btnStateArr, &state.ButtonState{Id: u.CommonId, Down: bit.Val})
}
}
return btnStateArr
}

View File

@ -80,9 +80,6 @@ func RemoveTrainState(vs *VerifySimulation, id string) {
err := dynamics.Default().RequestRemoveTrain(&message.RemoveTrainReq{
TrainIndex: uint16(trainIndex),
})
// httpCode, _, err := dynamics.SendRemoveTrainReq(&dynamics.InitTrainInfo{
// TrainIndex: uint16(trainIndex),
// })
if err != nil {
panic(dto.ErrorDto{Code: dto.DynamicsError, Message: err.Error()})
}
@ -95,29 +92,3 @@ func RemoveTrainState(vs *VerifySimulation, id string) {
panic(fmt.Sprintf("列车【%s】不存在", id))
}
}
// 获取所有的列车信息
func GetAllTrainState(vs *VerifySimulation) []*state.TrainState {
allTrainMap := &vs.Memory.Status.TrainStateMap
var trainArr []*state.TrainState
allTrainMap.Range(func(_, v any) bool {
trainArr = append(trainArr, v.(*state.TrainState))
return true
})
return trainArr
}
// 获取移除列车ID并清空
func GetRemovedTrainId(vs *VerifySimulation) []string {
ids := vs.Memory.ChangeStatus.RemoveTrainId
length := len(ids)
if length > 0 {
copyData := make([]string, length)
// 将数据复制到新的切片空间中
copy(copyData, ids)
// 清空变更信息
vs.Memory.ChangeStatus.RemoveTrainId = []string{}
return copyData
}
return []string{}
}

View File

@ -54,22 +54,6 @@ func GetAllTurnoutState(sim *VerifySimulation) []*state.SwitchState {
return switchArr
}
// 获取仿真地图的道岔状态,前端推送
func GetMapAllTurnoutState(sim *VerifySimulation, mapId int32) []*state.SwitchState {
// 获取本地图下的道岔信息
uidMap := QueryMapUidMapByType(mapId, &graphicData.Turnout{})
var switchArr []*state.SwitchState
for _, u := range uidMap {
s := handlerTurnoutState(sim.World, u.Uid)
if s == nil {
continue
}
s.Id = u.CommonId
switchArr = append(switchArr, s)
}
return switchArr
}
func handlerTurnoutState(w ecs.World, uid string) *state.SwitchState {
entry, ok := entity.GetEntityByUid(w, uid)
if !ok {

View File

@ -5,20 +5,16 @@ import (
"fmt"
"log/slog"
"math"
"runtime"
"sort"
"strconv"
"strings"
"sync"
"time"
rtss_simulation "joylink.club/rtsssimulation"
"joylink.club/bj-rtsts-server/config"
"joylink.club/bj-rtsts-server/dto"
"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/message"
"joylink.club/bj-rtsts-server/third_party/semi_physical_train"
"joylink.club/bj-rtsts-server/ts/protos/graphicData"
@ -47,6 +43,8 @@ type VerifySimulation struct {
uidMap map[string]*elementIdStructure
// 运行环境配置
runConfig *config.ThridPartyConfig
// 运行状态
runState state.SimulationStatus_SimulationState
}
// 轨旁仿真内存模型
@ -93,12 +91,16 @@ func NewWaysideMemory() *WaysideMemory {
}
// 创建仿真对象
func CreateSimulation(projectId int32, mapIds []int32, runConfig string) (*VerifySimulation, error) {
func CreateSimulation(projectId int32, mapIds []int32, runConfig *dto.ProjectRunConfigDto) (*VerifySimulation, error) {
// 地图信息
sort.Slice(mapIds, func(i, j int) bool {
return mapIds[i] < mapIds[j]
return QueryOnlyGiType(mapIds[i]) < QueryOnlyGiType(mapIds[j])
})
verifySimulation := &VerifySimulation{ProjectId: projectId, MapIds: mapIds}
verifySimulation := &VerifySimulation{
ProjectId: projectId,
MapIds: mapIds,
runState: state.SimulationStatus_PAUSE,
}
// 设置运行环境
err := verifySimulation.initRunConfig(runConfig)
if err != nil {
@ -109,89 +111,27 @@ func CreateSimulation(projectId int32, mapIds []int32, runConfig string) (*Verif
if err != nil {
return nil, err
}
// 创建world
err = verifySimulation.initWorld()
if err != nil {
return nil, err
}
// 运行第三方服务
err = verifySimulation.runThirdParty()
if err != nil {
return nil, err
}
return verifySimulation, nil
}
// 获取全量状态
func (s *VerifySimulation) GetAllState(mapId int32) *state.PushedDevicesStatus {
giType := QueryGiType(mapId)
switch giType {
case graphicData.PictureType_StationLayout:
return &state.PushedDevicesStatus{
All: true,
AllStatus: &state.AllDevicesStatus{
SwitchState: GetMapAllTurnoutState(s, mapId),
TrainState: GetAllTrainState(s),
SignalState: GetMapAllSignalState(s, mapId),
ButtonState: GetMapAllStationButtonState(s, mapId),
PsdState: GetMapAllPsdState(s, mapId),
SectionState: GetMapAllSectionState(s, mapId),
},
}
case graphicData.PictureType_RelayCabinetLayout:
return &state.PushedDevicesStatus{
All: true,
AllStatus: &state.AllDevicesStatus{
ReplyState: GetMapAllRelayState(s, mapId),
},
}
}
return &state.PushedDevicesStatus{}
// 启动
func (s *VerifySimulation) Start() {
s.runState = state.SimulationStatus_START
}
// 获取门控箱状态
func (s *VerifySimulation) GetAllPSLState(mapId int32, boxId string) *state.PushedDevicesStatus {
//world := s.GetSimulationWorld()
//uidStructure := queryUidStructure[*stationUidStructure](mapId)
//boxUid := uidStructure.GateBoxIds[boxId].Uid
//mkxEntry, ok := entity.GetEntityByUid(world, boxUid)
//var buttonStateArr []*state.ButtonState
//if ok {
// mkxCircuit := component.MkxCircuitType.Get(mkxEntry)
// var boxArr []*ecs.Entry
// boxArr = append(boxArr, mkxCircuit.PcbList...)
// boxArr = append(boxArr, mkxCircuit.PobList...)
// boxArr = append(boxArr, mkxCircuit.PabList...)
// for _, mkxBoxEntry := range boxArr {
// mkxBox := component.MkxBoxType.Get(mkxBoxEntry)
// uid := component.UidType.Get(mkxBox.Btn).Id
// down := component.BitStateType.Get(mkxBox.Btn).Val
// buttonStateArr = append(buttonStateArr, &state.ButtonState{
// Id: uid,
// Down: down,
// })
// }
//}
//return &state.PushedDevicesStatus{
// All: true,
// AllStatus: &state.AllDevicesStatus{
// ButtonState: buttonStateArr,
// },
//}
return nil
// 销毁
func (s *VerifySimulation) Destroy() {
s.runState = state.SimulationStatus_DESTROY
}
// 获取车站IBP状态
func (s *VerifySimulation) GetAllIBPState(mapId int32, stationId string, ibpMapCode string) *state.PushedDevicesStatus {
return &state.PushedDevicesStatus{
All: true,
AllStatus: GetMapAllIBPState(s, mapId, stationId, ibpMapCode),
}
// 暂停
func (s *VerifySimulation) Pause() {
s.runState = state.SimulationStatus_PAUSE
}
// 获取仿真世界信息
func (s *VerifySimulation) GetSimulationWorld() ecs.World {
return s.World
// 获取状态
func (s *VerifySimulation) GetRunState() state.SimulationStatus_SimulationState {
return s.runState
}
// 获取仿真世界信息
@ -285,10 +225,6 @@ func convert(info *message.DynamicsTrainInfo, sta *state.TrainState, simulation
// 获取动力学配置信息
func (s *VerifySimulation) GetDynamicsRunConfig() *config.DynamicsConfig {
// TODO:目前为了兼容当前配置方式做成查询方式后删除IP判断
if config.Config.Dynamics.Ip != "" {
return &config.Config.Dynamics
}
return &s.runConfig.Dynamics
}
@ -387,15 +323,11 @@ func (s *VerifySimulation) HandleSemiPhysicalTrainControlMsg(b []byte) {
// 获取半实物运行配置信息
func (s *VerifySimulation) GetSemiPhysicalRunConfig() *config.VobcConfig {
// TODO:目前为了兼容当前配置方式做成查询方式后删除IP判断
if config.Config.Vobc.Ip != "" {
return &config.Config.Vobc
}
return &s.runConfig.Vobc
}
// 处理接到的联锁消息
func (s *VerifySimulation) HandleDriverInfo(b []byte) {
func (s *VerifySimulation) HandleInterlockDriverInfo(b []byte) {
driverMsg := message.NewInterlockReceiveMsgPkg(0, 128, 8*131)
driverMsg.Decode(b)
driveState := driverMsg.DriveInfo
@ -408,42 +340,72 @@ func (s *VerifySimulation) HandleDriverInfo(b []byte) {
// 获取联锁配置
func (s *VerifySimulation) GetInterlockRunConfig() *config.InterlockConfig {
// TODO:目前为了兼容当前配置方式做成查询方式后删除IP判断
if config.Config.Interlock.Ip != "" {
return &config.Config.Interlock
}
return &s.runConfig.Interlock
}
// 采集联锁中的继电器消息
func (s *VerifySimulation) CollectRelayInfo() *message.InterlockSendMsgPkg {
msg := &message.InterlockSendMsgPkg{}
relayArr := make([]string, 256)
for index, id := range relayArr {
if index%2 == 0 {
msg.Info = append(msg.Info, fi.CollectXQCircuitState(s.World, id))
func (s *VerifySimulation) CollectInterlockRelayInfo() []*message.InterlockSendMsgPkg {
var msgPkgs []*message.InterlockSendMsgPkg
for _, mapId := range s.MapIds { // 获取继电器地图信息
if QueryOnlyGiType(mapId) != graphicData.PictureType_RelayCabinetLayout { // 继电器柜
continue
}
mapData := QueryGiData[*graphicData.RelayCabinetGraphicStorage](mapId)
// 配置继电器为空
dataLenght := len(mapData.CiCjList.CjList) * int(mapData.CiCjList.DsCount)
if dataLenght == 0 {
continue
}
index := 0
collectInfo := make([]bool, dataLenght)
uidMap := QueryUidStructure[*RelayUidStructure](mapId)
// 遍历继电器获取继电器状态
for _, col := range mapData.CiCjList.CjList {
for _, row := range col.BitList {
rs := len(row.RefRelays) > 0
for _, j := range row.RefRelays {
u := uidMap.RelayIds[j.RelayId]
if u == nil {
panic(sys_error.New(fmt.Sprintf("地图【id:%d】不存在继电器的【comId:%s】UID映射关系", mapId, j.RelayId)))
}
if j.Position == graphicData.CjDataItem_Q {
rs = rs && fi.CollectXQCircuitState(s.World, u.Uid)
} else {
msg.Info = append(msg.Info, fi.CollectLXCircuitState(s.World, id))
rs = rs && fi.CollectLXCircuitState(s.World, u.Uid)
}
}
return msg
collectInfo[index] = rs
index++
}
}
msgPkgs = append(msgPkgs, &message.InterlockSendMsgPkg{Info: collectInfo})
}
return msgPkgs
}
// 初始化仿真运行配置
func (s *VerifySimulation) initRunConfig(configStr string) error {
if configStr == "" {
func (s *VerifySimulation) initRunConfig(runConfig *dto.ProjectRunConfigDto) error {
if runConfig == nil || runConfig.ConfigContent == "" {
return nil
}
var configMap config.ThridPartyConfig
err := json.Unmarshal([]byte(configStr), &configMap)
err := json.Unmarshal([]byte(runConfig.ConfigContent), &configMap)
if err != nil {
return sys_error.New("配置信息格式错误", err)
}
s.runConfig = &configMap
s.runConfig.Id = runConfig.Id
return nil
}
// 获取仿真运行参数ID
func (s *VerifySimulation) GetRunConfigId() int32 {
if s.runConfig == nil {
return 0
}
return s.runConfig.Id
}
// 初始化运行资源
func (s *VerifySimulation) initRepository() error {
// 构建Repository
@ -473,48 +435,6 @@ func (s *VerifySimulation) initRepository() error {
return nil
}
// 创建world
func (s *VerifySimulation) initWorld() error {
//创建仿真
w, err := rtss_simulation.NewSimulation(s.Repo)
if err != nil {
return sys_error.New("仿真创建失败", err)
}
s.World = w
// 保证World关闭
runtime.SetFinalizer(s, func(verifySimulation *VerifySimulation) {
slog.Info("---关闭仿真World---")
verifySimulation.World.Close()
})
return nil
}
// 运行仿真第三方模块
func (s *VerifySimulation) runThirdParty() error {
// 动力学启动
err := dynamics.Default().Start(s)
if err != nil {
return err
}
// 半实物启动
semi_physical_train.Default().Start(s)
// 联锁启动
interlock.Default().Start(s)
return nil
}
// 停止仿真
func (s *VerifySimulation) StopSimulation() {
// 停止ecs world
s.World.Close()
// 停止动力学接口功能
dynamics.Default().Stop()
// 停止半实物
semi_physical_train.Default().Stop()
// 联锁启动
interlock.Default().Stop()
}
func buildProtoRepository(mapIds []int32) (*proto.Repository, error) {
repo := &proto.Repository{}
var exceptStationGiMapIds []int32
@ -540,7 +460,7 @@ func buildProtoRepository(mapIds []int32) (*proto.Repository, error) {
}
func buildAndRelateElectronicComponent(repo *proto.Repository, relayGi *graphicData.RelayCabinetGraphicStorage, mapId int32) {
uidsMap := queryUidStructure[*relayUidStructure](mapId)
uidsMap := QueryUidStructure[*RelayUidStructure](mapId)
city := relayGi.UniqueIdPrefix.City
lineId := relayGi.UniqueIdPrefix.LineId
station := relayGi.UniqueIdPrefix.BelongsConcentrationStation
@ -721,7 +641,7 @@ func convertRelayModel(modelType graphicData.Relay_ModelType) proto.Relay_Model
func fillProtoRepository(repo *proto.Repository, storage *graphicData.RtssGraphicStorage, mapId int32) {
repo.MainCoordinateSystem = storage.UniqueIdPrefix.MainCoordinateSystem
axleCountingMap := make(map[string]*graphicData.AxleCounting)
uidsMap := queryUidStructure[*stationUidStructure](mapId)
uidsMap := QueryUidStructure[*StationUidStructure](mapId)
for _, data := range storage.AxleCountings {
axleCountingMap[data.Common.Id] = data
cpType := proto.CheckPointType_AxleCounter
@ -947,7 +867,7 @@ func fillProtoRepository(repo *proto.Repository, storage *graphicData.RtssGraphi
// 将IBP的设备关联到车站中
func handlerIBPDeviceToStation(station *proto.Station, repo *proto.Repository, ibpMap string) {
storage := getStorageIBPMapData(ibpMap)
storage := GetStorageIBPMapData(ibpMap)
if storage == nil {
return
}
@ -1036,7 +956,7 @@ func handlerIBPDeviceToStation(station *proto.Station, repo *proto.Repository, i
station.ElectronicGroup = append(station.ElectronicGroup, empGroup, spksGroup)
}
func converCheckPointUid(data *proto.CheckPoint, uidsMap *stationUidStructure) *proto.CheckPoint {
func converCheckPointUid(data *proto.CheckPoint, uidsMap *StationUidStructure) *proto.CheckPoint {
data.Id = uidsMap.AxlePointIds[data.Id].Uid
for _, c := range data.DevicePorts {
c.DeviceId = converRefUid(c.DeviceId, c.DeviceType, uidsMap)
@ -1044,7 +964,7 @@ func converCheckPointUid(data *proto.CheckPoint, uidsMap *stationUidStructure) *
return data
}
func converSectionUid(data *proto.PhysicalSection, uidsMap *stationUidStructure) *proto.PhysicalSection {
func converSectionUid(data *proto.PhysicalSection, uidsMap *StationUidStructure) *proto.PhysicalSection {
data.Id = uidsMap.PhysicalSectionIds[data.Id].Uid
if data.ADevicePort != nil {
data.ADevicePort.DeviceId = converRefUid(data.ADevicePort.DeviceId, data.ADevicePort.DeviceType, uidsMap)
@ -1060,7 +980,7 @@ func converSectionUid(data *proto.PhysicalSection, uidsMap *stationUidStructure)
return data
}
func converTurnoutUid(data *proto.Turnout, uidsMap *stationUidStructure) *proto.Turnout {
func converTurnoutUid(data *proto.Turnout, uidsMap *StationUidStructure) *proto.Turnout {
data.Id = uidsMap.TurnoutIds[data.Id].Uid
if data.ADevicePort != nil {
data.ADevicePort.DeviceId = converRefUid(data.ADevicePort.DeviceId, data.ADevicePort.DeviceType, uidsMap)
@ -1074,7 +994,7 @@ func converTurnoutUid(data *proto.Turnout, uidsMap *stationUidStructure) *proto.
return data
}
func converSignalUid(data *proto.Signal, uidsMap *stationUidStructure) *proto.Signal {
func converSignalUid(data *proto.Signal, uidsMap *StationUidStructure) *proto.Signal {
data.Id = uidsMap.SignalIds[data.Id].Uid
if data.SectionId != "" {
data.SectionId = converRefUid(data.SectionId, proto.DeviceType_DeviceType_PhysicalSection, uidsMap)
@ -1085,7 +1005,7 @@ func converSignalUid(data *proto.Signal, uidsMap *stationUidStructure) *proto.Si
return data
}
func converTransponderUid(data *proto.Transponder, uidsMap *stationUidStructure) *proto.Transponder {
func converTransponderUid(data *proto.Transponder, uidsMap *StationUidStructure) *proto.Transponder {
data.Id = uidsMap.TransponderIds[data.Id].Uid
if data.SectionId != "" {
data.SectionId = converRefUid(data.SectionId, proto.DeviceType_DeviceType_PhysicalSection, uidsMap)
@ -1096,17 +1016,17 @@ func converTransponderUid(data *proto.Transponder, uidsMap *stationUidStructure)
return data
}
func converSlopeUid(data *proto.Slope, uidsMap *stationUidStructure) *proto.Slope {
func converSlopeUid(data *proto.Slope, uidsMap *StationUidStructure) *proto.Slope {
data.Id = uidsMap.SlopeIds[data.Id].Uid
return data
}
func converCurvatureUid(data *proto.SectionalCurvature, uidsMap *stationUidStructure) *proto.SectionalCurvature {
func converCurvatureUid(data *proto.SectionalCurvature, uidsMap *StationUidStructure) *proto.SectionalCurvature {
data.Id = uidsMap.CurvatureIds[data.Id].Uid
return data
}
func converRefUid(id string, d proto.DeviceType, uidsMap *stationUidStructure) string {
func converRefUid(id string, d proto.DeviceType, uidsMap *StationUidStructure) string {
var elementId *elementIdStructure
switch d {
case proto.DeviceType_DeviceType_CheckPoint:

View File

@ -1,15 +1,21 @@
package ts
import (
"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"
)
// 仿真存储集合
@ -26,7 +32,7 @@ func IsExistSimulation() bool {
}
// 创建仿真对象
func CreateSimulation(projectId int32, mapIds []int32, runConfig string) (string, error) {
func CreateSimulation(projectId int32, mapIds []int32, runConfig *dto.ProjectRunConfigDto) (string, error) {
simulationId := createSimulationId(projectId)
_, e := simulationMap.Load(simulationId)
if !e && IsExistSimulation() {
@ -38,7 +44,18 @@ func CreateSimulation(projectId int32, mapIds []int32, runConfig string) (string
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()
// 启动仿真消息服务
@ -55,8 +72,52 @@ func DestroySimulation(simulationId string) {
}
simulationMap.Delete(simulationId)
simulationInfo := s.(*memory.VerifySimulation)
simulationInfo.Destroy()
// 停止ecs world
simulationInfo.World.Close()
// 停止第三方
stopThirdParty(simulationInfo)
message_server.Close(simulationInfo)
simulationInfo.StopSimulation()
}
// 创建world
func initWorld(s *memory.VerifySimulation) error {
//创建仿真
w, err := rtss_simulation.NewSimulation(s.Repo)
if err != nil {
return sys_error.New("仿真创建失败", 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)
// 联锁启动
interlock.Default().Start(s)
return nil
}
// 停止仿真
func stopThirdParty(s *memory.VerifySimulation) {
// 停止动力学接口功能
dynamics.Default().Stop()
// 停止半实物
semi_physical_train.Default().Stop()
// 联锁启动
interlock.Default().Stop()
}
func createSimulationId(projectId int32) string {
@ -74,6 +135,7 @@ func ListAllSimulations() []*dto.SimulationInfoRspDto {
MapId: s.MapIds[0],
MapIds: s.MapIds,
ProjectId: s.ProjectId,
ProjectRunConfigId: s.GetRunConfigId(),
})
return true
})
@ -88,13 +150,3 @@ func FindSimulation(simulationId string) *memory.VerifySimulation {
}
return nil
}
// 获取普通仿真数组
func GetSimulationArr() []*memory.VerifySimulation {
var result []*memory.VerifySimulation
simulationMap.Range(func(_, v any) bool {
result = append(result, v.(*memory.VerifySimulation))
return true
})
return result
}