rts-sim-testing-service/ts/simulation/wayside/memory/wayside_simulation.go

1622 lines
50 KiB
Go
Raw Normal View History

2023-08-01 14:54:11 +08:00
package memory
import (
"encoding/hex"
"encoding/json"
"fmt"
"log/slog"
"math"
2023-09-21 14:54:27 +08:00
"sort"
"strconv"
"strings"
2023-09-22 11:29:56 +08:00
"sync"
2023-09-21 14:54:27 +08:00
"joylink.club/bj-rtsts-server/config"
2023-09-21 14:54:27 +08:00
"joylink.club/bj-rtsts-server/dto"
"joylink.club/bj-rtsts-server/dto/data_proto"
"joylink.club/bj-rtsts-server/dto/state_proto"
"joylink.club/bj-rtsts-server/sys_error"
"joylink.club/bj-rtsts-server/third_party/electrical_machinery"
"joylink.club/bj-rtsts-server/third_party/message"
"joylink.club/bj-rtsts-server/third_party/semi_physical_train"
2023-09-21 14:54:27 +08:00
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
2023-10-24 10:57:04 +08:00
"joylink.club/rtsssimulation/fi"
"joylink.club/rtsssimulation/repository"
"joylink.club/rtsssimulation/repository/model/proto"
)
2023-08-01 14:54:11 +08:00
// 轨旁仿真定义
type VerifySimulation struct {
//地图id
2023-09-19 11:02:50 +08:00
MapIds []int32
// 项目ID
ProjectId int32
2023-08-01 14:54:11 +08:00
//仿真id
SimulationId string
//仿真内存数据
Memory *WaysideMemory
//模型仓库
Repo *repository.Repository
//Rtss仿真世界的
World ecs.World
//设备UID映射 key-uid
UidMap map[string]*elementIdStructure
// 运行环境配置
runConfig *config.ThridPartyConfig
2023-08-01 14:54:11 +08:00
}
2023-09-22 11:29:56 +08:00
// 轨旁仿真内存模型
type WaysideMemory struct {
//可变状态数据:轨旁仿真模型状态(全量数据)
Status *VerifyStatus
// 要变更的状态:用户操作过的状态记录在这里,增量推送次数据
ChangeStatus *ChangeVerifyStatus
//状态保护锁
rwLock *sync.RWMutex
}
// 轨旁仿真模型状态
type VerifyStatus struct {
//道岔状态key为道岔id即索引 state_proto.SwitchState
2023-09-22 11:29:56 +08:00
SwitchStateMap sync.Map
//轨道状态key为轨道id即索引 state_proto.LinkState
2023-09-22 11:29:56 +08:00
LinkStateMap sync.Map
//列车状态key为列车id即索引 state_proto.TrainState
2023-09-22 11:29:56 +08:00
TrainStateMap sync.Map
//计轴区段状态key为计轴区段的id即索引 state_proto.SectionState
2023-09-22 11:29:56 +08:00
AxleSectionStateMap sync.Map
//物理区段状态key为物理区段id即索引 state_proto.SectionState
2023-09-22 11:29:56 +08:00
PhysicalSectionStateMap sync.Map
//逻辑区段状态key为逻辑区段id即索引 state_proto.SectionState
2023-09-22 11:29:56 +08:00
LogicSectionStateMap sync.Map
//信号机状态key为信号机id,即索引 state_proto.SignalState
2023-09-22 11:29:56 +08:00
SignalStateMap sync.Map
}
// 轨旁仿真模型状态(变更)
type ChangeVerifyStatus struct {
VerifyStatus
//删除的列车ID列表
RemoveTrainId []string
}
func NewWaysideMemory() *WaysideMemory {
return &WaysideMemory{
Status: &VerifyStatus{},
ChangeStatus: &ChangeVerifyStatus{},
rwLock: &sync.RWMutex{},
}
}
2023-08-01 14:54:11 +08:00
// 创建仿真对象
2023-10-26 18:09:09 +08:00
func CreateSimulation(projectId int32, mapIds []int32, runConfig *dto.ProjectRunConfigDto) (*VerifySimulation, error) {
// 地图信息
sort.Slice(mapIds, func(i, j int) bool {
return QueryGiType(mapIds[i]) < QueryGiType(mapIds[j])
})
verifySimulation := &VerifySimulation{
ProjectId: projectId,
MapIds: mapIds,
}
// 设置运行环境
err := verifySimulation.initRunConfig(runConfig)
if err != nil {
return nil, err
}
// 构建Repository
err = verifySimulation.initRepository()
if err != nil {
return nil, err
}
return verifySimulation, nil
2023-08-01 14:54:11 +08:00
}
// // 启动
// func (s *VerifySimulation) Start() {
// s.runState = state_proto.SimulationStatus_START
// }
// // 销毁
// func (s *VerifySimulation) Destroy() {
// s.runState = state_proto.SimulationStatus_DESTROY
// }
// // 暂停
// func (s *VerifySimulation) Pause() {
// s.runState = state_proto.SimulationStatus_PAUSE
// }
// // 获取状态
// func (s *VerifySimulation) GetRunState() state_proto.SimulationStatus_SimulationState {
// return s.runState
// }
2023-09-25 17:05:17 +08:00
// 获取仿真世界信息
2023-12-14 13:04:48 +08:00
func (s *VerifySimulation) GetComIdByUid(uid string) uint32 {
es := s.UidMap
2023-09-25 17:05:17 +08:00
if es == nil {
panic(&dto.ErrorDto{Code: dto.DataNotExist, Message: "无映射信息"})
}
if es[uid] == nil {
panic(&dto.ErrorDto{Code: dto.DataNotExist, Message: "无【uid】映射信息"})
}
return es[uid].CommonId
}
2023-11-24 15:20:05 +08:00
// GetBtmCanetConfig 获取CANET配置信息
func (s *VerifySimulation) GetBtmCanetConfig() config.BtmCanetConfig {
return s.runConfig.BtmCanet
}
2023-11-09 13:05:29 +08:00
func (s *VerifySimulation) GetLineAllRsspAxleCfgs() []config.RsspAxleConfig {
return s.runConfig.RsspAxleCfgs
}
2023-09-25 17:05:17 +08:00
2023-11-14 10:31:06 +08:00
// GetSectionCodePoints 获取集中站的区段码表
func (s *VerifySimulation) GetSectionCodePoints(city string, lineId string, centralizedStation string) []*proto.CiSectionCodePoint {
2023-11-07 17:47:47 +08:00
stationUid := GenerateElementUid(city, lineId, nil, centralizedStation)
ref := s.Repo.GetCentralizedStationRef(stationUid)
if ref == nil {
2023-11-14 10:31:06 +08:00
return nil
2023-11-07 17:47:47 +08:00
}
//
2023-11-14 10:31:06 +08:00
return ref.SectionCodePoints
}
// CollectSectionStatus 收集仿真中计轴区段状态
func (s *VerifySimulation) CollectSectionStatus(city string, lineId string, centralizedStation string) ([]*message.SectionStatusMsg, error) {
stationUid := GenerateElementUid(city, lineId, nil, centralizedStation)
//
codePoints := s.GetSectionCodePoints(city, lineId, centralizedStation)
2023-11-07 17:47:47 +08:00
if len(codePoints) <= 0 {
return nil, fmt.Errorf("没有找到GetCentralizedStationRef[%s]的区段码表为空", stationUid)
}
2023-11-14 17:57:54 +08:00
//slog.Debug("收集计轴区段状态", "区段码表len", len(codePoints))
2023-11-07 17:47:47 +08:00
//
var msg []*message.SectionStatusMsg
var axleSectionIds []string
for _, section := range codePoints {
axleSectionIds = append(axleSectionIds, section.SectionId)
}
//
2023-11-14 17:57:54 +08:00
//slog.Debug("收集计轴区段状态", "计轴区段len", len(axleSectionIds), "axleSectionIds", axleSectionIds)
2023-11-07 17:47:47 +08:00
as, e := fi.FindAxleSectionsStatus(s.World, axleSectionIds)
if e != nil { //从仿真中收集计轴区段状态的失败列表
return nil, e
}
2023-11-14 17:57:54 +08:00
//slog.Debug("收集计轴区段状态", "仿真中计轴状态len", len(as))
2023-11-07 17:47:47 +08:00
//
stateMap := make(map[string]*fi.AxleSectionState)
for _, a := range as {
stateMap[a.Id] = a
}
//
sort.SliceStable(codePoints, func(i, j int) bool {
return codePoints[i].Row < codePoints[j].Row
})
//
for _, codePoint := range codePoints {
sectionState, find := stateMap[codePoint.SectionId]
if find {
state_proto := &message.SectionStatusMsg{}
state_proto.Rac = sectionState.Rac
state_proto.Rjt = sectionState.Rjt
state_proto.Rjo = sectionState.Rjo
state_proto.Occ = sectionState.Occ
state_proto.Clr = sectionState.Clr
msg = append(msg, state_proto)
2023-11-07 17:47:47 +08:00
} else {
return nil, fmt.Errorf("仿真中没有对应区段[%s]的状态", codePoint.SectionId)
}
}
//
2023-11-14 17:57:54 +08:00
//slog.Debug("收集计轴区段状态", "区段计轴msgLen", len(msg))
2023-11-07 17:47:47 +08:00
return msg, nil
}
// 采集动力学道岔状态
2024-01-17 17:01:43 +08:00
func (s *VerifySimulation) CollectDynamicsTurnoutInfo() *message.DynamicsTurnoutInfo {
turnoutState := &message.DynamicsTurnoutInfo{}
for _, turnout := range s.Repo.TurnoutList() {
sta := s.UidMap[turnout.Id()]
if sta == nil {
continue
}
2024-01-17 17:01:43 +08:00
entry, ok := entity.GetEntityByUid(s.World, turnout.Id())
if !ok {
slog.Warn(fmt.Sprintf("id=%s的道岔不存在", turnout.Id()))
return nil
}
if !entry.HasComponent(component.TurnoutPositionType) {
return nil
}
2024-01-17 17:01:43 +08:00
pos := component.TurnoutPositionType.Get(entry)
turnoutState.TurnoutInfos = append(turnoutState.TurnoutInfos, &message.TurnoutInfo{
Code: uint16(sta.CommonId),
2024-01-17 17:01:43 +08:00
NPosition: pos.Dw,
RPosition: pos.Fw,
})
}
2024-01-17 17:01:43 +08:00
return turnoutState
}
2023-11-07 13:22:47 +08:00
// HandleSectionCmdMsg 计轴设备接收到联锁发送来的控制命令
2023-11-07 17:47:47 +08:00
func (s *VerifySimulation) HandleSectionCmdMsg(city string, lineId string, centralizedStation string, msg *message.SectionCmdMsgPack) {
stationUid := GenerateElementUid(city, lineId, nil, centralizedStation)
ref := s.Repo.GetCentralizedStationRef(stationUid)
if ref == nil {
slog.Warn(fmt.Sprintf("没有找到GetCentralizedStationRef [%s]", stationUid))
return
2023-11-07 13:22:47 +08:00
}
2023-11-07 17:47:47 +08:00
//
codePoints := ref.SectionCodePoints
if len(codePoints) != len(msg.Scs) {
slog.Warn(fmt.Sprintf("本地配置区段码表个数[%d] != 联锁发送集中站[%s]的区段命令个数[%d]", len(codePoints), stationUid, len(msg.Scs)))
return
2023-11-07 13:22:47 +08:00
}
2023-11-07 17:47:47 +08:00
//
var cpSectionMap = make(map[int]*proto.CiSectionCodePoint)
for _, cp := range codePoints {
cpSectionMap[int(cp.Row)] = cp
}
//
var cmds []*fi.AxleSectionCmd
for index, cmdMsg := range msg.Scs {
cp := cpSectionMap[index]
cmd := &fi.AxleSectionCmd{}
cmd.SectionId = cp.SectionId
cmd.Drst = cmdMsg.Drst
cmd.Pdrst = cmdMsg.Pdrst
cmds = append(cmds, cmd)
}
fi.AxleSectionRstDrive(s.World, cmds)
2023-11-07 13:22:47 +08:00
}
2023-11-07 17:47:47 +08:00
// 处理动力学列车速度消息
func (s *VerifySimulation) HandleDynamicsTrainInfo(info *message.DynamicsTrainInfo) {
trainId := strconv.Itoa(int(info.Number))
2024-04-13 09:40:25 +08:00
t, ok := s.Memory.Status.TrainStateMap.Load(trainId)
if !ok {
return
}
2024-04-13 09:40:25 +08:00
train := t.(*state_proto.TrainState)
if train.ConnState.Conn && train.ConnState.ConnType == state_proto.TrainConnState_VOBC {
semi_physical_train.Default().SendTrainControlMessage(info)
}
// 更新列车状态
trainState := UpdateTrainStateByDynamics(s, trainId, info)
// 更新电机转速
electrical_machinery.Default().SendElectricMachineryMessage(&message.ElectricMachinery{
Speed: info.Speed,
WheelDiameter: trainState.WheelDiameter,
IsBack: trainState.VobcState.DirectionBackward,
})
}
// 获取动力学配置信息
func (s *VerifySimulation) GetDynamicsRunConfig() *config.DynamicsConfig {
return &s.runConfig.Dynamics
}
2023-12-13 11:22:30 +08:00
func (s *VerifySimulation) GetCidcModbusConfig() []config.CidcModbusConfig {
return s.runConfig.CidcModbus
}
// 获取动力学运行资源
func (s *VerifySimulation) GetDynamicsRunRepository() *message.LineBaseInfo {
info := &message.LineBaseInfo{}
for _, model := range s.Repo.LinkList() {
id, _ := strconv.Atoi(model.Id())
link := &message.Link{
ID: int32(id),
Len: int32(model.Length()),
}
info.LinkList = append(info.LinkList, link)
if model.ARelation() != nil {
2023-12-14 13:04:48 +08:00
turnoutId := s.GetComIdByUid(model.ARelation().Device().Id())
link.ARelTurnoutId = int32(turnoutId)
switch model.ARelation().Port() {
case proto.Port_A:
link.ARelTurnoutPoint = "A"
case proto.Port_B:
link.ARelTurnoutPoint = "B"
case proto.Port_C:
link.ARelTurnoutPoint = "C"
}
}
if model.BRelation() != nil {
2023-12-14 13:04:48 +08:00
turnoutId := s.GetComIdByUid(model.BRelation().Device().Id())
link.BRelTurnoutId = int32(turnoutId)
switch model.BRelation().Port() {
case proto.Port_A:
link.BRelTurnoutPoint = "A"
case proto.Port_B:
link.BRelTurnoutPoint = "B"
case proto.Port_C:
link.BRelTurnoutPoint = "C"
}
}
}
for _, model := range s.Repo.SlopeList() {
2023-12-14 13:04:48 +08:00
id := s.GetComIdByUid(model.Id())
slope := &message.Slope{
ID: int32(id),
StartLinkOffset: int32(model.StartLinkPosition().Offset()),
EndLinkOffset: int32(model.EndLinkPosition().Offset()),
DegreeTrig: model.Degree(),
}
info.SlopeList = append(info.SlopeList, slope)
startLinkId, _ := strconv.Atoi(model.StartLinkPosition().Link().Id())
slope.StartLinkId = int32(startLinkId)
endLinkId, _ := strconv.Atoi(model.EndLinkPosition().Link().Id())
slope.EndLinkId = int32(endLinkId)
}
for _, model := range s.Repo.SectionalCurvatureList() {
2023-12-14 13:04:48 +08:00
id := s.GetComIdByUid(model.Id())
curve := &message.Curve{
ID: int32(id),
StartLinkOffset: int32(model.StartLinkPosition().Offset()),
EndLinkOffset: int32(model.EndLinkPosition().Offset()),
Curvature: model.Radius(),
}
info.CurveList = append(info.CurveList, curve)
startLinkId, _ := strconv.Atoi(model.StartLinkPosition().Link().Id())
curve.StartLinkId = int32(startLinkId)
endLinkId, _ := strconv.Atoi(model.EndLinkPosition().Link().Id())
curve.EndLinkId = int32(endLinkId)
}
return info
}
// 发送给前端的速度格式化
func speedParse(speed float32) int32 {
return int32(math.Abs(float64(speed * 3.6 * 100)))
}
// 处理半实物仿真列车控制消息
func (s *VerifySimulation) HandleSemiPhysicalTrainControlMsg(b []byte) {
s.Memory.Status.TrainStateMap.Range(func(_, value any) bool {
train := value.(*state_proto.TrainState)
if !train.Show { // 下线列车
return true
}
connState := train.ConnState
if connState.Conn == true && connState.ConnType == state_proto.TrainConnState_VOBC {
2024-04-13 09:40:25 +08:00
/*trainId, err := strconv.Atoi(train.Id)
if err != nil {
panic(dto.ErrorDto{Code: dto.ArgumentParseError, Message: err.Error()})
}*/
// 存放至列车中
2024-04-13 09:40:25 +08:00
//接收半实物列车控制不单独发送动力学,由动力学统一发送
//d := append(b, uint8(trainId))
//dynamics.Default().SendTrainControlMessage(d)
controlMessage := &message.TrainControlMsg{}
controlMessage.Decode(b)
2024-04-15 08:44:37 +08:00
controlMessage.TrainId = train.Id
controlMessage.FromVobc = true
train.VobcState = controlMessage.ControlInfo
2024-04-15 08:44:37 +08:00
return false
}
return true
})
}
2024-04-13 09:40:25 +08:00
func (s *VerifySimulation) CollectTrainControlState() []message.TrainControlMsg {
cms := make([]message.TrainControlMsg, 0)
s.Memory.Status.TrainStateMap.Range(func(_, value any) bool {
train := value.(*state_proto.TrainState)
if !train.Show { // 下线列车
return true
}
vobc := false
if train.ConnState.Conn == true && train.ConnState.ConnType == state_proto.TrainConnState_VOBC {
vobc = true
}
cms = append(cms, message.TrainControlMsg{ControlInfo: train.VobcState, TrainId: train.Id, FromVobc: vobc})
return true
})
return cms
}
// 获取半实物运行配置信息
func (s *VerifySimulation) GetSemiPhysicalRunConfig() *config.VobcConfig {
return &s.runConfig.Vobc
}
// 获取所有联锁配置唯一Code
func (s *VerifySimulation) GetInterlockCodes() []*config.InterlockConfig {
stationMap := make(map[string]string)
for _, station := range s.Repo.StationList() {
stationMap[station.GetCode()] = station.Id()
}
var configs []*config.InterlockConfig
for _, c := range s.runConfig.Interlocks {
if stationMap[c.Code] == "" || !c.Open {
continue
2023-10-24 10:57:04 +08:00
}
configs = append(configs, &config.InterlockConfig{
Code: stationMap[c.Code],
Ip: c.Ip,
LocalPort: c.LocalPort,
RemotePort: c.RemotePort,
Open: c.Open,
})
2023-10-24 10:57:04 +08:00
}
return configs
2023-10-24 09:03:38 +08:00
}
// 处理接到的联锁消息
func (s *VerifySimulation) HandleInterlockDriverInfo(code string, b []byte) {
for _, m := range s.Repo.CiQcList() { // 获取继电器地图信息
if m.StationId != code {
continue
}
driverMsg := message.NewInterlockReceiveMsgPkg(0, len(m.QdList), len(m.TransponderId))
driverMsg.Decode(b)
driveState := driverMsg.DriveInfo
for i, r := range m.QdList {
ds := driveState[i]
for _, b := range r.RefRelays {
slog.Debug("继电器位【%s】获取到驱动状态【%v】", b, ds)
}
}
return
}
}
2023-10-24 10:57:04 +08:00
// 采集联锁中的继电器消息
func (s *VerifySimulation) CollectInterlockRelayInfo(code string) *message.InterlockSendMsgPkg {
for _, m := range s.Repo.CiQcList() { // 获取继电器地图信息
if m.StationId != code {
2023-10-27 17:57:12 +08:00
continue
}
if len(m.CjList) == 0 {
return nil
}
2023-10-31 09:39:40 +08:00
collectInfo := make([]bool, len(m.CjList))
for i, l := range m.CjList {
if l == nil || len(l.RefRelays) == 0 {
continue
}
rs := true
for _, j := range l.RefRelays {
if j.Q {
rs = rs && CollectXQCircuitState(s.World, j.RelayId)
2023-10-31 09:39:40 +08:00
} else {
rs = rs && CollectLXCircuitState(s.World, j.RelayId)
2023-10-27 17:57:12 +08:00
}
if !rs {
break
}
2023-10-27 17:57:12 +08:00
}
2023-10-31 09:39:40 +08:00
collectInfo[i] = rs
2023-10-24 10:57:04 +08:00
}
return message.NewInterlockSendMsgPkg(collectInfo)
2023-10-24 10:57:04 +08:00
}
return nil
2023-10-24 10:57:04 +08:00
}
func (s *VerifySimulation) FindTrainConnTypes() []dto.TrainConnTypeConfigDto {
typeConfig := make([]dto.TrainConnTypeConfigDto, 0)
if s.runConfig.Vobc.Open /*&& s.runConfig.Vobc.Ip != ""*/ {
typeConfig = append(typeConfig, dto.TrainConnTypeConfigDto{ConnType: state_proto.TrainConnState_VOBC})
}
if s.runConfig.PcSimConfig.Open /*&& s.runConfig.PcSimConfig.PcSimIp != ""*/ {
typeConfig = append(typeConfig, dto.TrainConnTypeConfigDto{ConnType: state_proto.TrainConnState_PC_SIM})
}
return typeConfig
}
2023-10-24 09:03:38 +08:00
// 获取电机转速参数
func (s *VerifySimulation) GetElectricMachineryRunConfig() *config.ElectricMachineryConfig {
return &s.runConfig.ElectricMachinery
}
// 初始化仿真运行配置
2023-10-26 18:09:09 +08:00
func (s *VerifySimulation) initRunConfig(runConfig *dto.ProjectRunConfigDto) error {
if runConfig == nil || runConfig.ConfigContent == "" {
return nil
}
var configMap config.ThridPartyConfig
2023-10-26 18:09:09 +08:00
err := json.Unmarshal([]byte(runConfig.ConfigContent), &configMap)
if err != nil {
return sys_error.New("配置信息格式错误", err)
}
s.runConfig = &configMap
2023-10-26 18:09:09 +08:00
s.runConfig.Id = runConfig.Id
return nil
}
2023-10-27 09:12:40 +08:00
// 获取仿真运行参数ID
func (s *VerifySimulation) GetRunConfigId() int32 {
if s.runConfig == nil {
return 0
}
return s.runConfig.Id
}
2023-11-24 15:20:05 +08:00
func (s *VerifySimulation) EvnWorld() ecs.World {
return s.World
}
2023-10-27 09:12:40 +08:00
// 初始化运行资源
func (s *VerifySimulation) initRepository() error {
// 构建Repository
var mapIdStrSlice []string
var mapVersion []string
for _, id := range s.MapIds {
mapIdStrSlice = append(mapIdStrSlice, strconv.Itoa(int(id)))
mapVersion = append(mapVersion, strconv.Itoa(int(QueryGiVersion(id))))
}
repoId := strings.Join(mapIdStrSlice, "|")
repoVersion := strings.Join(mapVersion, ".")
repo := repository.FindRepository(repoId, repoVersion)
if repo == nil {
protoRepo, err := buildProtoRepository(s.MapIds)
if err != nil {
return sys_error.New("数据错误", err)
}
protoRepo.Id, protoRepo.Version = repoId, repoVersion
newRepo, err := repository.BuildRepository(protoRepo)
if err != nil {
return sys_error.New("数据错误", err)
}
repo = newRepo
}
s.Repo = repo
s.Memory = NewWaysideMemory()
// 构建所有UID映射关系
s.UidMap = buildRepositoryAllUidsMap(s.MapIds, s.Repo)
return nil
}
2024-01-24 17:12:34 +08:00
// GetRunRadarConfig 获取雷达配置信息
func (s *VerifySimulation) GetRunRadarConfig() config.RadarConfig {
return s.runConfig.Radar
}
2024-01-26 17:57:35 +08:00
// GetRunAccConfig 获取加速计配置信息
func (s *VerifySimulation) GetRunAccConfig() config.AccConfig {
return s.runConfig.Acc
}
2024-01-24 17:12:34 +08:00
// FindRadarTrain 查找一个列车 只有1端雷达开启啊
func (s *VerifySimulation) FindRadarTrain() *state_proto.TrainState {
var trainStatus *state_proto.TrainState
s.Memory.Status.TrainStateMap.Range(func(k any, v any) bool {
val, ok := v.(*state_proto.TrainState)
if ok {
2024-04-11 08:55:12 +08:00
if val.TrainEndsA.RadarEnable || val.TrainEndsB.RadarEnable {
trainStatus = val
return false
}
/*if val.TrainEndsA.RadarEnable && val.TrainEndsB.RadarEnable {
2024-01-24 17:12:34 +08:00
return true
} else if val.TrainEndsA.RadarEnable || val.TrainEndsB.RadarEnable {
trainStatus = val
return false
2024-04-11 08:55:12 +08:00
}*/
2024-01-24 17:12:34 +08:00
}
return true
})
return trainStatus
}
2024-01-26 17:57:35 +08:00
// FindRadarTrain 查找一个列车 只有1端雷达开启啊
func (s *VerifySimulation) FindAccTrain() *state_proto.TrainState {
var trainStatus *state_proto.TrainState
s.Memory.Status.TrainStateMap.Range(func(k any, v any) bool {
val, ok := v.(*state_proto.TrainState)
if ok {
if val.TrainEndsA.AccEnable && val.TrainEndsB.AccEnable {
//trainStatus = val
//return false
return true
} else if val.TrainEndsA.AccEnable || val.TrainEndsB.AccEnable {
trainStatus = val
return false
}
}
return true
})
return trainStatus
}
func buildProtoRepository(mapIds []int32) (*proto.Repository, error) {
repo := &proto.Repository{}
var exceptStationGiMapIds []int32
//创建设备
for _, mapId := range mapIds {
giType := QueryGiType(mapId)
if giType == data_proto.PictureType_StationLayout {
stationGi := QueryGiData[*data_proto.RtssGraphicStorage](mapId)
fillProtoRepository(repo, stationGi, mapId)
} else {
exceptStationGiMapIds = append(exceptStationGiMapIds, mapId)
}
}
//构建并关联电子元件
for _, mapId := range exceptStationGiMapIds {
giType := QueryGiType(mapId)
if giType == data_proto.PictureType_RelayCabinetLayout {
relayGi := QueryGiData[*data_proto.RelayCabinetGraphicStorage](mapId)
buildAndRelateElectronicComponent(repo, relayGi, mapId)
}
}
2023-11-07 15:10:19 +08:00
//构建信号平面图中物理区段码表与集中站的关系
for _, mapId := range mapIds {
giType := QueryGiType(mapId)
if giType == data_proto.PictureType_StationLayout {
stationGi := QueryGiData[*data_proto.RtssGraphicStorage](mapId)
2023-11-07 15:10:19 +08:00
buildSectionCodePoint(repo, stationGi, mapId)
}
}
return repo, nil
}
func buildSectionCodePoint(repo *proto.Repository, storage *data_proto.RtssGraphicStorage, mapId int32) {
2023-12-14 13:04:48 +08:00
// city := storage.UniqueIdPrefix.City
// lineId := storage.UniqueIdPrefix.LineId
uidsMap := QueryUidStructure[*StationUidStructure](mapId)
2023-11-07 15:10:19 +08:00
for _, sscp := range storage.SectionCodePointList {
centralizedStation := sscp.CentralizedStation
sectionGIds := sscp.SectionIds
2023-12-14 13:04:48 +08:00
centralizedStationId := uidsMap.StationIds[centralizedStation].Uid // GenerateElementUid(city, lineId, nil, centralizedStation)
2023-11-07 15:10:19 +08:00
ref := queryCentralizedStationRef(centralizedStationId, repo)
var ccs []*proto.CiSectionCodePoint
for sectionPoint, sectionGId := range sectionGIds {
cc := &proto.CiSectionCodePoint{}
cc.Row = int32(sectionPoint)
cc.SectionId = QueryUidByMidAndComId(mapId, sectionGId, &data_proto.Section{})
2023-11-07 15:10:19 +08:00
ccs = append(ccs, cc)
}
ref.SectionCodePoints = ccs
}
}
func buildAndRelateElectronicComponent(repo *proto.Repository, relayGi *data_proto.RelayCabinetGraphicStorage, mapId int32) {
relayUidStructure := QueryUidStructure[*RelayUidStructure](mapId)
city := relayGi.UniqueIdPrefix.City
lineId := relayGi.UniqueIdPrefix.LineId
station := relayGi.UniqueIdPrefix.BelongsConcentrationStation
2023-11-02 15:54:26 +08:00
stationUid := GenerateElementUid(city, lineId, nil, station)
relayMap := make(map[string]*proto.Relay)
for _, relay := range relayGi.Relays {
rid := GetMapElementId(relay.Common)
repoRelay := &proto.Relay{
Id: relayUidStructure.RelayIds[rid].Uid,
2023-11-02 15:54:26 +08:00
Code: relay.Code,
Model: convertRelayModel(relay.NewModel),
StationId: stationUid,
}
repo.Relays = append(repo.Relays, repoRelay)
relayMap[repoRelay.Id] = repoRelay
}
for _, pfp := range relayGi.PhaseFailureProtectors {
pid := GetMapElementId(pfp.Common)
repo.PhaseFailureProtectors = append(repo.PhaseFailureProtectors, &proto.PhaseFailureProtector{
Id: relayUidStructure.RelayIds[pid].Uid,
Code: pfp.Code,
})
}
turnoutMap := make(map[string]*proto.Turnout)
for _, turnout := range repo.Turnouts {
turnoutMap[turnout.Id] = turnout
}
signalMap := make(map[string]*proto.Signal)
for _, signal := range repo.Signals {
signalMap[signal.Id] = signal
}
stationMap := make(map[string]*proto.Station)
for _, station := range repo.Stations {
stationMap[station.Id] = station
}
psdMap := make(map[string]*proto.Psd)
for _, psd := range repo.Psds {
psdMap[psd.Id] = psd
}
platformMap := make(map[string]*proto.Platform)
for _, platform := range repo.Platforms {
platformMap[platform.Id] = platform
}
ckmMap := make(map[string]*proto.Ckm)
for _, ckm := range repo.Ckms {
ckmMap[ckm.Id] = ckm
}
xcjMap := make(map[string]*proto.Xcj)
for _, xcj := range repo.Xcjs {
xcjMap[xcj.Id] = xcj
}
2023-11-09 14:27:35 +08:00
ciecs := stationMap[stationUid] //联锁集中站
if ciecs == nil {
panic(fmt.Errorf("联锁集中站[%s]不存在", stationUid))
}
for _, relationship := range relayGi.DeviceRelateRelayList {
2023-09-26 09:34:23 +08:00
switch relationship.DeviceType {
case data_proto.RelatedRef_Turnout:
turnout := turnoutMap[GenerateElementUid(city, lineId, []string{station}, relationship.Code)]
2023-09-26 10:25:01 +08:00
if turnout == nil {
continue
}
for _, group := range relationship.Combinationtypes {
var componentIds []string
for _, relayId := range group.RefRelays {
if relayUidStructure.RelayIds[relayId] == nil {
2023-09-27 14:15:11 +08:00
continue
}
componentIds = append(componentIds, relayUidStructure.RelayIds[relayId].Uid)
}
turnout.ElectronicComponentGroups = append(turnout.ElectronicComponentGroups,
&proto.ElectronicComponentGroup{
Code: group.Code,
ComponentIds: componentIds,
})
}
case data_proto.RelatedRef_signal:
signal := signalMap[GenerateElementUid(city, lineId, []string{station}, relationship.Code)]
2023-09-26 10:25:01 +08:00
if signal == nil {
continue
}
2023-10-16 14:06:47 +08:00
//信号机只有一个组合类型
if len(relationship.Combinationtypes) != 1 {
panic(fmt.Sprintf("信号机[%s]须有一个组合类型", signal.Id))
}
group := relationship.Combinationtypes[0]
var componentIds []string
for _, relayId := range group.RefRelays {
if relayUidStructure.RelayIds[relayId] == nil {
2023-10-16 14:06:47 +08:00
continue
}
componentIds = append(componentIds, relayUidStructure.RelayIds[relayId].Uid)
}
2023-10-16 14:06:47 +08:00
signal.Code = group.Code
signal.ElectronicComponentGroups = append(signal.ElectronicComponentGroups,
&proto.ElectronicComponentGroup{
Code: group.Code,
ComponentIds: componentIds,
})
case data_proto.RelatedRef_station:
station := stationMap[GenerateElementUid(city, lineId, nil, relationship.Code)]
if station == nil {
continue
}
for _, group := range relationship.Combinationtypes {
d := &proto.ElectronicGroup{Code: group.Code}
for _, relayId := range group.RefRelays {
if relayUidStructure.RelayIds[relayId] == nil {
2023-09-27 14:15:11 +08:00
continue
}
d.Components = append(d.Components, &proto.ElectronicComponent{
Id: relayUidStructure.RelayIds[relayId].Uid,
DeviceType: proto.DeviceType_DeviceType_Relay,
})
}
station.ElectronicGroup = append(station.ElectronicGroup, d)
}
case data_proto.RelatedRef_ScreenDoor:
psd, ok := psdMap[GenerateElementUid(city, lineId, nil, relationship.Code)]
if !ok {
continue
}
for _, group := range relationship.Combinationtypes {
var componentIds []string
for _, relayId := range group.RefRelays {
if relayUidStructure.RelayIds[relayId] == nil {
continue
}
componentIds = append(componentIds, relayUidStructure.RelayIds[relayId].Uid)
}
psd.ElectronicComponentGroups = append(psd.ElectronicComponentGroups,
&proto.ElectronicComponentGroup{
Code: group.Code,
ComponentIds: componentIds,
})
}
case data_proto.RelatedRef_SignalFaultAlarm: // 信号机故障报警仪设备组合
2023-11-09 14:27:35 +08:00
{
egs := buildEgs(relationship.Combinationtypes, relayUidStructure)
ciecs.Deccs = append(ciecs.Deccs, &proto.DeviceEcc{
DeviceType: proto.DeviceType_DeviceType_SignalFaultAlarm,
Egs: egs,
})
}
case data_proto.RelatedRef_Breakers: // 断路器
2023-11-09 14:27:35 +08:00
{
egs := buildEgs(relationship.Combinationtypes, relayUidStructure)
ciecs.Deccs = append(ciecs.Deccs, &proto.DeviceEcc{
DeviceType: proto.DeviceType_DeviceType_Breakers,
Egs: egs,
})
}
case data_proto.RelatedRef_PowerScreen: // 电源屏
2023-11-09 14:27:35 +08:00
{
egs := buildEgs(relationship.Combinationtypes, relayUidStructure)
ciecs.Deccs = append(ciecs.Deccs, &proto.DeviceEcc{
DeviceType: proto.DeviceType_DeviceType_PowerScreen,
Egs: egs,
})
}
case data_proto.RelatedRef_GarageDoor, data_proto.RelatedRef_FloodGate: //车库门||防淹门
{
ckm, ok := ckmMap[GenerateElementUid(city, lineId, nil, relationship.Code)]
if !ok {
continue
}
for _, group := range relationship.Combinationtypes {
var componentIds []string
for _, relayId := range group.RefRelays {
if relayUidStructure.RelayIds[relayId] == nil {
continue
}
componentIds = append(componentIds, relayUidStructure.RelayIds[relayId].Uid)
}
ckm.ElectronicComponentGroups = append(ckm.ElectronicComponentGroups,
&proto.ElectronicComponentGroup{
Code: group.Code,
ComponentIds: componentIds,
})
}
}
case data_proto.RelatedRef_CarWashing:
{
xcj, ok := xcjMap[GenerateElementUid(city, lineId, nil, relationship.Code)]
if !ok {
continue
}
for _, group := range relationship.Combinationtypes {
var componentIds []string
for _, relayId := range group.RefRelays {
if relayUidStructure.RelayIds[relayId] == nil {
continue
}
componentIds = append(componentIds, relayUidStructure.RelayIds[relayId].Uid)
}
xcj.ElectronicComponentGroups = append(xcj.ElectronicComponentGroups,
&proto.ElectronicComponentGroup{
Code: group.Code,
ComponentIds: componentIds,
})
}
}
}
}
//门控箱
for _, mkx := range repo.Mkxs {
platform := platformMap[psdMap[mkx.PsdId].GetPlatformId()]
station := stationMap[platform.GetStationId()]
var s string
if strings.Contains(platform.GetCode(), "上行") {
s = "S"
} else if strings.Contains(platform.GetCode(), "下行") {
s = "X"
} else {
continue
}
for _, group := range station.ElectronicGroup {
if group.Code == "MKX" {
for _, component := range group.Components {
relay := relayMap[component.Id]
if strings.Contains(relay.GetCode(), s) {
if strings.Contains(relay.GetCode(), "PCB") {
mkx.PcbjId = relay.Id
} else if strings.Contains(relay.GetCode(), "POB") {
mkx.PobjId = relay.Id
} else if strings.Contains(relay.GetCode(), "PAB") || strings.Contains(relay.GetCode(), "PDB") {
mkx.PabjId = relay.Id
} else if strings.Contains(relay.GetCode(), "WRZF") {
mkx.WrzfjId = relay.Id
} else if strings.Contains(relay.GetCode(), "QKQR") {
mkx.QkqrjId = relay.Id
}
}
}
}
}
}
2023-10-31 09:39:40 +08:00
// 处理该集中站采集、驱动配置信息
centralizedStationId := GenerateElementUid(city, lineId, nil, station)
ref := queryCentralizedStationRef(centralizedStationId, repo)
ref.CjList = append(ref.CjList, handlerRelayGiCj(relayUidStructure, centralizedStationId, relayGi.CiCjList)...)
sortQcTable(ref.CjList)
ref.QdList = append(ref.QdList, handlerRelayGiQd(relayUidStructure, centralizedStationId, relayGi.CiQdList)...)
sortQcTable(ref.QdList)
}
func buildEgs(cts []*data_proto.Combinationtype, relayUidStructure *RelayUidStructure) []*proto.ElectronicComponentGroup {
2023-11-09 14:27:35 +08:00
var egs []*proto.ElectronicComponentGroup
for _, ct := range cts {
d := &proto.ElectronicComponentGroup{Code: ct.Code}
for _, relayId := range ct.RefRelays {
if relayUidStructure.RelayIds[relayId] == nil {
continue
}
d.ComponentIds = append(d.ComponentIds, relayUidStructure.RelayIds[relayId].Uid)
}
egs = append(egs, d)
}
return egs
}
type IQcTable interface {
GetRow() int32
GetCol() int32
}
func sortQcTable[T IQcTable](s []T) {
sort.SliceStable(s, func(i, j int) bool {
a := s[i]
b := s[j]
if a.GetCol() < b.GetCol() {
return true
} else if a.GetCol() > b.GetCol() {
return false
} else {
if a.GetRow() < b.GetRow() {
return true
} else {
return false
}
}
})
2023-10-31 09:39:40 +08:00
}
// 查询集中站配置信息
func queryCentralizedStationRef(stationId string, repo *proto.Repository) *proto.CentralizedStationRef {
var ref *proto.CentralizedStationRef
for _, r := range repo.CentralizedStationRefs {
if r.StationId == stationId {
ref = r
break
}
}
if ref == nil {
ref = &proto.CentralizedStationRef{StationId: stationId}
repo.CentralizedStationRefs = append(repo.CentralizedStationRefs, ref)
}
return ref
}
// 处理继电器采集信息
func handlerRelayGiCj(uidsMap *RelayUidStructure, stationId string, ciCj *data_proto.CiCj) []*proto.CjData {
2023-10-31 09:39:40 +08:00
if ciCj == nil {
return nil
}
// 采集信息
dataLenght := len(ciCj.CjList) * int(ciCj.DsCount)
if dataLenght == 0 {
return nil
}
cjList := make([]*proto.CjData, dataLenght)
index := 0
for ci, col := range ciCj.CjList {
for ri, row := range col.BitList {
r := &proto.CjData{Row: int32(ri), Col: int32(ci)}
if len(row.RefRelays) > 0 {
for _, j := range row.RefRelays {
u := uidsMap.RelayIds[j.RelayId]
if u == nil {
2023-12-14 13:04:48 +08:00
panic(sys_error.New(fmt.Sprintf("集中站【id:%s】不存在继电器的【comId:%d】UID映射关系", stationId, j.RelayId)))
}
d := &proto.CjDataItem{RelayId: u.Uid}
if j.Position == data_proto.CjDataItem_H {
d.Q = false
} else {
d.Q = true
}
r.RefRelays = append(r.RefRelays, d)
2023-10-31 09:39:40 +08:00
}
}
cjList[index] = r
index++
}
}
return cjList
}
// 处理继电器驱动信息
func handlerRelayGiQd(uidsMap *RelayUidStructure, stationId string, ciQd *data_proto.CiQd) []*proto.QdData {
2023-10-31 09:39:40 +08:00
if ciQd == nil {
return nil
}
// 驱动信息
dataLenght := len(ciQd.QdList) * int(ciQd.DsCount)
if dataLenght == 0 {
return nil
}
qdList := make([]*proto.QdData, dataLenght)
index := 0
for ci, col := range ciQd.QdList {
for ri, row := range col.BitList {
r := &proto.QdData{Row: int32(ri), Col: int32(ci)}
if len(row.RefRelays) > 0 {
for _, j := range row.RefRelays {
u := uidsMap.RelayIds[j]
if u == nil {
2023-12-14 13:04:48 +08:00
panic(sys_error.New(fmt.Sprintf("集中站【id:%s】不存在继电器的【comId:%d】UID映射关系", stationId, j)))
}
r.RefRelays = append(r.RefRelays, u.Uid)
2023-10-31 09:39:40 +08:00
}
}
qdList[index] = r
index++
}
}
return qdList
}
func convertRelayModel(modelType data_proto.Relay_ModelType) proto.Relay_Model {
switch modelType {
case data_proto.Relay_Unknown:
return proto.Relay_Unknown
case data_proto.Relay_JPXC_1000:
return proto.Relay_JPXC_1000
case data_proto.Relay_JPXC_1700:
return proto.Relay_JPXC_1700
case data_proto.Relay_JWJXC_480:
return proto.Relay_JWJXC_480
case data_proto.Relay_JWJXC_H125_80:
return proto.Relay_JWJXC_H125_80
case data_proto.Relay_JWXC_1700:
return proto.Relay_JWXC_1700
case data_proto.Relay_JWXC_H340:
return proto.Relay_JWXC_H340
case data_proto.Relay_JYJXC_160_260:
return proto.Relay_JYJXC_160_260
case data_proto.Relay_JZXC_H18:
return proto.Relay_JZXC_H18
default:
panic(fmt.Sprintf("意料之外的继电器型号:%s", modelType))
}
}
func fillProtoRepository(repo *proto.Repository, storage *data_proto.RtssGraphicStorage, mapId int32) {
2023-10-19 18:04:21 +08:00
repo.MainCoordinateSystem = storage.UniqueIdPrefix.MainCoordinateSystem
axleCountingMap := make(map[uint32]*data_proto.AxleCounting)
uidsMap := QueryUidStructure[*StationUidStructure](mapId)
2024-02-20 09:20:52 +08:00
//计轴
for _, data := range storage.AxleCountings {
id := GetMapElementId(data.Common)
axleCountingMap[id] = data
cpType := proto.CheckPointType_AxleCounter
if data.Type == data_proto.AxleCounting_SectionBoundary {
cpType = proto.CheckPointType_Boundary
}
cp := &proto.CheckPoint{
2023-12-14 13:04:48 +08:00
Id: uidsMap.AxlePointIds[id].Uid,
Km: convertKm(data.KilometerSystem),
Type: cpType,
}
2023-12-14 13:04:48 +08:00
for _, ref := range data.AxleCountingRef {
cp.DevicePorts = append(cp.DevicePorts, convertDevicePort(ref, uidsMap))
}
repo.CheckPoints = append(repo.CheckPoints, cp)
}
2024-02-20 09:20:52 +08:00
//区段
for _, data := range storage.Section {
2023-12-14 13:04:48 +08:00
var turnoutUids []string
if data.SectionType == data_proto.Section_TurnoutPhysical {
2023-12-14 13:04:48 +08:00
turnoutIds := findTurnoutIds(axleCountingMap, data.AxleCountings)
for _, tid := range turnoutIds {
turnoutUids = append(turnoutUids, uidsMap.TurnoutIds[tid].Uid)
}
}
2023-12-14 13:04:48 +08:00
var centralizedStation string
2023-10-31 16:53:39 +08:00
if len(data.CentralizedStations) > 0 {
2023-11-30 10:59:34 +08:00
s := uidsMap.StationIds[data.CentralizedStations[0]]
if s != nil {
centralizedStation = s.Code
}
2023-10-31 16:53:39 +08:00
}
physicalSection := &proto.PhysicalSection{
2023-12-14 13:04:48 +08:00
Id: uidsMap.PhysicalSectionIds[GetMapElementId(data.Common)].Uid,
ADevicePort: convertDevicePort(data.PaRef, uidsMap),
BDevicePort: convertDevicePort(data.PbRef, uidsMap),
TurnoutIds: turnoutUids,
2023-10-31 16:53:39 +08:00
CentralizedStation: centralizedStation,
}
2023-12-14 13:04:48 +08:00
repo.PhysicalSections = append(repo.PhysicalSections, physicalSection)
}
2024-02-20 09:20:52 +08:00
//道岔
for _, data := range storage.Turnouts {
var km *proto.Kilometer
for _, ks := range data.KilometerSystem {
if ks.Kilometer != 0 {
km = convertKm(ks)
break
}
}
2023-12-14 13:04:48 +08:00
turnout := &proto.Turnout{
Id: uidsMap.TurnoutIds[GetMapElementId(data.Common)].Uid,
Km: km,
ADevicePort: convertDevicePort(data.PaRef, uidsMap),
BDevicePort: convertDevicePort(data.PbRef, uidsMap),
CDevicePort: convertDevicePort(data.PcRef, uidsMap),
}
2023-09-28 17:45:08 +08:00
switch data.SwitchMachineType {
case data_proto.Turnout_ZDJ9_Single:
2023-12-14 13:04:48 +08:00
turnout.SwitchMachineType = proto.Turnout_ZDJ9_Single
case data_proto.Turnout_ZDJ9_Double:
2023-12-14 13:04:48 +08:00
turnout.SwitchMachineType = proto.Turnout_ZDJ9_Double
}
2023-12-14 13:04:48 +08:00
repo.Turnouts = append(repo.Turnouts, turnout)
}
2024-02-20 09:20:52 +08:00
//信号机
for _, data := range storage.Signals {
2023-12-14 13:04:48 +08:00
signal := &proto.Signal{
Id: uidsMap.SignalIds[GetMapElementId(data.Common)].Uid,
Km: convertKm(data.KilometerSystem),
Model: convertToProtoSignalModel(data.Mt),
}
switch data.RefDev.DeviceType {
case data_proto.RelatedRef_Section:
2023-12-14 13:04:48 +08:00
signal.SectionId = uidsMap.PhysicalSectionIds[data.RefDev.Id].Uid
case data_proto.RelatedRef_Turnout:
2023-12-14 13:04:48 +08:00
signal.TurnoutPort = convertDevicePort(data.RefDev, uidsMap)
}
2023-12-14 13:04:48 +08:00
repo.Signals = append(repo.Signals, signal)
}
2023-10-31 09:39:40 +08:00
stm := make(map[string][]string)
2024-02-20 09:20:52 +08:00
//应答器
for _, data := range storage.Transponders {
fixedTelegram, err := hex.DecodeString(data.FixedTelegram)
if err != nil {
slog.Error(fmt.Sprintf("解析应答器[%s]的固定报文出错:", err.Error()))
}
fixedUserTelegram, err := hex.DecodeString(data.FixedUserTelegram)
if err != nil {
slog.Error(fmt.Sprintf("解析应答器[%s]的固定用户报文出错:", err.Error()))
}
responder := &proto.Transponder{
Id: uidsMap.TransponderIds[GetMapElementId(data.Common)].Uid,
Km: convertKm(data.KilometerSystem),
FixedTelegram: fixedTelegram,
Type: convertToProtoBaliseType(data.Type),
FixedUserTelegram: fixedUserTelegram,
}
2023-12-14 13:04:48 +08:00
switch data.TransponderRef.DeviceType {
case data_proto.RelatedRef_Section:
2023-12-14 13:04:48 +08:00
responder.SectionId = uidsMap.PhysicalSectionIds[data.TransponderRef.Id].Uid
case data_proto.RelatedRef_Turnout:
2023-12-14 13:04:48 +08:00
responder.TurnoutPort = convertDevicePort(data.TransponderRef, uidsMap)
}
2023-11-30 10:59:34 +08:00
for _, stationId := range data.CentralizedStations {
var stationName string
if uidsMap.StationIds[stationId] == nil {
stationName = uidsMap.StationIds[stationId].Code
}
2023-12-14 13:04:48 +08:00
stm[stationName] = append(stm[stationName], responder.Id)
2023-10-31 09:39:40 +08:00
}
2023-12-14 13:04:48 +08:00
repo.Transponders = append(repo.Transponders, responder)
}
slopeKsMap := make(map[uint32]*data_proto.SlopeKiloMarker)
2024-02-20 09:20:52 +08:00
//坡度公里标
for _, data := range storage.SlopeKiloMarker {
slopeKsMap[GetMapElementId(data.Common)] = data
}
2024-02-20 09:20:52 +08:00
//坡度
for _, data := range storage.Slopes {
var kms []*proto.Kilometer
for _, id := range data.RefDeviceId {
kms = append(kms, convertKm(slopeKsMap[id].KilometerSystem[0]))
}
slope := &proto.Slope{
2023-12-14 13:04:48 +08:00
Id: uidsMap.SlopeIds[GetMapElementId(data.Common)].Uid,
Kms: kms,
Degree: data.SlopeNumber,
}
2023-12-14 13:04:48 +08:00
repo.Slopes = append(repo.Slopes, slope)
}
curveKsMap := make(map[uint32]*data_proto.CurvatureKiloMarker)
2024-02-20 09:20:52 +08:00
//曲度公里标
2023-12-14 13:04:48 +08:00
for _, data := range storage.CurvatureKiloMarker {
curveKsMap[GetMapElementId(data.Common)] = data
}
2024-02-20 09:20:52 +08:00
//曲度
for _, data := range storage.Curvatures {
var kms []*proto.Kilometer
for _, id := range data.RefDeviceId {
kms = append(kms, convertKm(curveKsMap[id].KilometerSystem[0]))
}
slope := &proto.SectionalCurvature{
2023-12-14 13:04:48 +08:00
Id: uidsMap.CurvatureIds[GetMapElementId(data.Common)].Uid,
Kms: kms,
Radius: data.CurvatureNumber,
}
2023-12-14 13:04:48 +08:00
repo.SectionalCurvatures = append(repo.SectionalCurvatures, slope)
}
2024-02-20 09:20:52 +08:00
//公里标转换
2023-09-26 09:34:23 +08:00
for _, data := range storage.KilometerConvertList {
repo.KilometerConverts = append(repo.KilometerConverts, &proto.KilometerConvert{
KmA: convertKm(data.KmA),
KmB: convertKm(data.KmB),
SameTrend: data.SameTrend,
})
}
// 初始化站场图按钮
for _, data := range storage.EsbButtons {
repo.Buttons = append(repo.Buttons, &proto.Button{
Id: uidsMap.ButtonIds[GetMapElementId(data.Common)].Uid,
Code: data.Code,
ButtonType: proto.Button_Reset_Press,
})
}
// 车站关联关系
relateMap := make(map[string]*data_proto.StationRelateDevice)
for _, data := range storage.StationRelateDeviceList {
relateMap[data.Code] = data
}
// 处理车站信息
2024-02-20 09:20:52 +08:00
repoStationMap := make(map[uint32]*proto.Station)
for _, data := range storage.Stations {
station := &proto.Station{
Id: uidsMap.StationIds[GetMapElementId(data.Common)].Uid,
Code: data.StationName,
}
2024-02-20 09:20:52 +08:00
repoStationMap[GetMapElementId(data.Common)] = station
// 关联车站的设备
2023-12-07 10:17:48 +08:00
refs, ok := relateMap[station.Code]
if ok {
for _, c := range refs.Combinationtypes {
group := &proto.ElectronicGroup{Code: c.Code}
for _, d := range c.RefDevices {
var comp *proto.ElectronicComponent
if uidsMap.ButtonIds[d] != nil { // 目前只处理按钮
comp = &proto.ElectronicComponent{
Id: uidsMap.ButtonIds[d].Uid,
DeviceType: proto.DeviceType_DeviceType_Button,
}
} else {
continue
}
group.Components = append(group.Components, comp)
}
station.ElectronicGroup = append(station.ElectronicGroup, group)
}
}
2024-02-20 09:20:52 +08:00
//// 处理车站关联IBP的设备
//handlerIBPDeviceToStation(station, repo, data.RefIbpMapCode)
repo.Stations = append(repo.Stations, station)
2023-10-31 09:39:40 +08:00
// 处理集中站的信息
if stm[station.Code] != nil {
ref := queryCentralizedStationRef(station.Id, repo)
ref.TransponderId = append(ref.TransponderId, stm[station.Code]...)
}
}
2024-02-20 09:20:52 +08:00
//站台
platformMap := make(map[uint32]*data_proto.Platform)
for _, data := range storage.Platforms {
platformId := GetMapElementId(data.Common)
platformMap[platformId] = data
platform := &proto.Platform{
Id: uidsMap.PlatformIds[platformId].Uid,
Code: data.Code,
}
repo.Platforms = append(repo.Platforms, platform)
platform.StationId = uidsMap.StationIds[data.RefStationId].Uid
platform.PhysicalSectionId = uidsMap.PhysicalSectionIds[data.RefSectionId].Uid
}
//屏蔽门
platformId_psdUid_map := make(map[uint32]string)
for _, data := range storage.ScreenDoors {
var asdGroups []*proto.AsdGroup
for _, group := range storage.ScreenDoorConfig.ScreenDoorGroupList {
asdGroups = append(asdGroups, &proto.AsdGroup{
Group: group.TrainGroupAmount,
Start: group.StartSmallDoor,
End: group.EndSmallDoor,
})
}
psd := &proto.Psd{
Id: uidsMap.PsdIds[GetMapElementId(data.Common)].Uid,
AsdAmount: storage.ScreenDoorConfig.SonDoorAmount,
AsdGroups: asdGroups,
PlatformId: uidsMap.PlatformIds[data.RefPlatformId].Uid,
}
platformId_psdUid_map[data.GetRefPlatformId()] = psd.Id
repo.Psds = append(repo.Psds, psd)
}
//屏蔽门PSL
2024-02-20 09:20:52 +08:00
for _, data := range storage.PslBoxs {
boxUidInfo := uidsMap.PslIds[GetMapElementId(data.Common)]
mkx := &proto.Mkx{
Id: boxUidInfo.Uid,
2024-02-20 09:20:52 +08:00
PsdId: platformId_psdUid_map[data.RefPlatformId],
}
repo.Mkxs = append(repo.Mkxs, mkx)
2024-02-20 09:20:52 +08:00
_, pslStorage := QueryGiDataByName[*data_proto.PslGraphicStorage](data.RefPslMapCode)
for _, button := range pslStorage.PslButtons {
repoButton := &proto.Button{
Id: boxUidInfo.Uid + "_" + button.Code,
Code: button.Code,
ButtonType: proto.Button_Reset_Press,
HasLight: true,
}
repo.Buttons = append(repo.Buttons, repoButton)
switch button.Code {
case "PCB":
mkx.PcbaId = repoButton.Id
case "PCBPL":
mkx.PcbplaId = repoButton.Id
case "POB":
mkx.PobaId = repoButton.Id
case "POBPL":
mkx.PobplaId = repoButton.Id
case "PAB":
mkx.PabaId = repoButton.Id
case "PABPL":
mkx.PabplaId = repoButton.Id
case "WRZF":
mkx.WrzfaId = repoButton.Id
case "WRZFPL":
mkx.WrzfplaId = repoButton.Id
case "QKQR":
mkx.QkqraId = repoButton.Id
case "QKQRPL":
mkx.QkqrplaId = repoButton.Id
case "MPL":
mkx.MplaId = repoButton.Id
case "JXTCPLA":
mkx.JxtcplaId = repoButton.Id
}
}
}
2024-02-20 09:20:52 +08:00
//IBP
for _, data := range storage.IbpBoxs {
boxUidInfo := uidsMap.IbpIds[data.Common.Id]
2024-02-20 09:20:52 +08:00
station := repoStationMap[data.RefStationId]
handlerIBPDeviceToStation(station, boxUidInfo.Uid, repo, data.RefIbpMapCode)
}
//车库门和车库门PSL
fillCkmOrFym(repo, storage.GarageDoors, uidsMap)
//防淹门和防淹门PSL
fillCkmOrFym(repo, storage.FloodGates, uidsMap)
//洗车机
for _, data := range storage.CarWashings {
xcj := &proto.Xcj{
Id: uidsMap.XcjIds[data.Common.Id].Uid,
NumSegments: data.DuanNum,
}
repo.Xcjs = append(repo.Xcjs, xcj)
}
}
func fillCkmOrFym(repo *proto.Repository, doors []*data_proto.GarageDoor, uidsMap *StationUidStructure) {
for _, data := range doors {
//车库门
ckmId := GetMapElementId(data.Common)
ckm := &proto.Ckm{
Id: uidsMap.CkmIds[ckmId].Uid,
}
repo.Ckms = append(repo.Ckms, ckm)
//车库门PSL
pslUid := uidsMap.PslIds[ckmId].Uid
ckmPsl := &proto.CkmPsl{
Id: pslUid,
CkmId: uidsMap.CkmIds[ckmId].Uid,
}
repo.CkmPsls = append(repo.CkmPsls, ckmPsl)
_, pslStorage := QueryGiDataByName[*data_proto.PslGraphicStorage](data.RefPslMapCode)
for _, button := range pslStorage.PslButtons {
repoButton := &proto.Button{
Id: pslUid + "_" + button.Code,
Code: button.Code,
ButtonType: proto.Button_Reset_Press,
HasLight: true,
}
repo.Buttons = append(repo.Buttons, repoButton)
switch button.Code {
case "KMA":
ckmPsl.KmaId = repoButton.Id
case "GMA":
ckmPsl.GmaId = repoButton.Id
case "MPLA":
ckmPsl.MplaId = repoButton.Id
case "MMSA":
ckmPsl.MmsaId = repoButton.Id
}
}
}
}
// 将IBP的设备关联到车站中
func handlerIBPDeviceToStation(station *proto.Station, ibpBoxUid string, repo *proto.Repository, ibpMapCode string) {
mapId, storage := QueryGiDataByName[*data_proto.IBPGraphicStorage](ibpMapCode)
if storage == nil {
return
}
2023-12-07 10:17:48 +08:00
uidMap := QueryUidStructure[*IBPUidStructure](mapId)
2023-12-14 13:04:48 +08:00
deviceMap := make(map[uint32]*proto.ElectronicComponent) // 对应的设备类型
for _, data := range storage.IbpButtons { // 处理按钮
id := GetMapElementId(data.Common)
b := &proto.Button{
Id: ibpBoxUid + "_" + uidMap.IbpButtonIds[id].Uid,
Code: data.Code,
2023-12-07 10:17:48 +08:00
ButtonType: proto.Button_NO_Reset_Press,
2023-10-18 14:09:36 +08:00
HasLight: data.HasLight,
}
2023-12-07 10:17:48 +08:00
if data.IsSelfReset {
b.ButtonType = proto.Button_Reset_Press
}
deviceMap[id] = &proto.ElectronicComponent{
Id: b.Id,
DeviceType: proto.DeviceType_DeviceType_Button,
}
repo.Buttons = append(repo.Buttons, b)
}
for _, data := range storage.IbpKeys { // 钥匙
id := GetMapElementId(data.Common)
2023-10-20 13:50:22 +08:00
b := &proto.Key{
Id: ibpBoxUid + "_" + uidMap.IbpKeyIds[id].Uid,
2023-10-20 13:50:22 +08:00
Code: data.Code,
Gear: 2,
}
deviceMap[id] = &proto.ElectronicComponent{
Id: b.Id,
2023-10-20 13:50:22 +08:00
DeviceType: proto.DeviceType_DeviceType_Key,
}
2023-10-20 13:50:22 +08:00
repo.Keys = append(repo.Keys, b)
}
for _, data := range storage.IbpAlarms { // 报警器
id := GetMapElementId(data.Common)
b := &proto.Alarm{
Id: ibpBoxUid + "_" + uidMap.IbpAlarmIds[id].Uid,
Code: data.Code,
}
deviceMap[id] = &proto.ElectronicComponent{
Id: b.Id,
DeviceType: proto.DeviceType_DeviceType_Alarm,
}
repo.Alarms = append(repo.Alarms, b)
}
2023-10-20 15:52:50 +08:00
for _, data := range storage.IbpLights { // 指示灯,
id := GetMapElementId(data.Common)
b := &proto.Light{
Id: ibpBoxUid + "_" + uidMap.IbpLightIds[id].Uid,
2023-10-20 15:52:50 +08:00
Code: data.Code,
}
deviceMap[id] = &proto.ElectronicComponent{
Id: b.Id,
DeviceType: proto.DeviceType_DeviceType_Light,
}
repo.Lights = append(repo.Lights, b)
}
2023-10-20 15:52:50 +08:00
for _, data := range storage.IbpRelatedDevices { // 组信息
for _, c := range data.Combinationtypes {
group := &proto.ElectronicGroup{Code: c.Code}
for _, d := range c.RefDevices {
deviceType, ok := deviceMap[d]
if !ok {
slog.Debug("IBP组合类型类型不存在设备id:%s", d)
continue
}
group.Components = append(group.Components, deviceType)
}
station.ElectronicGroup = append(station.ElectronicGroup, group)
}
}
}
func convertKm(ks *data_proto.KilometerSystem) *proto.Kilometer {
var dir proto.Direction
switch ks.Direction {
case data_proto.KilometerSystem_LEFT:
dir = proto.Direction_LEFT
case data_proto.KilometerSystem_RIGHT:
dir = proto.Direction_RIGHT
}
return &proto.Kilometer{
Value: ks.Kilometer,
CoordinateSystem: ks.CoordinateSystem,
Direction: dir,
}
}
func convertDevicePort(ref *data_proto.RelatedRef, uidsMap *StationUidStructure) *proto.DevicePort {
if ref == nil {
return nil
}
var port proto.Port
switch ref.DevicePort {
case data_proto.RelatedRef_A:
port = proto.Port_A
case data_proto.RelatedRef_B:
port = proto.Port_B
case data_proto.RelatedRef_C:
port = proto.Port_C
}
2023-12-14 13:04:48 +08:00
var elementId string
var deviceType proto.DeviceType
switch ref.DeviceType {
case data_proto.RelatedRef_Section:
deviceType = proto.DeviceType_DeviceType_PhysicalSection
2023-12-14 13:04:48 +08:00
elementId = uidsMap.PhysicalSectionIds[ref.Id].Uid
case data_proto.RelatedRef_Turnout:
deviceType = proto.DeviceType_DeviceType_Turnout
2023-12-14 13:04:48 +08:00
elementId = uidsMap.TurnoutIds[ref.Id].Uid
default:
panic(fmt.Sprintf("异常的设备类型-%s", ref.DeviceType))
}
return &proto.DevicePort{
2023-12-14 13:04:48 +08:00
DeviceId: elementId,
DeviceType: deviceType,
Port: port,
}
}
func findTurnoutIds(axleCountingMap map[uint32]*data_proto.AxleCounting, axleIds []uint32) []uint32 {
if len(axleIds) <= 2 {
return nil
}
2023-12-14 13:04:48 +08:00
turnoutMap := make(map[uint32]int)
for _, axleId := range axleIds {
axle := axleCountingMap[axleId]
for _, ref := range axle.AxleCountingRef {
if ref.DeviceType == data_proto.RelatedRef_Turnout {
turnoutMap[ref.Id] = turnoutMap[ref.Id] + 1
}
}
}
2023-12-14 13:04:48 +08:00
var turnoutIds []uint32
for id, num := range turnoutMap {
if num > 1 {
turnoutIds = append(turnoutIds, id)
}
}
return turnoutIds
}
2023-11-16 17:21:05 +08:00
/*
enum Model{
HL = 0; //2XH-1 红绿
HLU_FU = 1; //2XH-1 红绿黄,封黄灯,无引导
HLU_DU_YY = 2; //3XH-1 红绿黄,不封灯,有单黄,带引导
HLU_YY = 3; //3XH-2或JDXH 红绿黄,不封灯,无单黄,带引导
HLU_FL_DU_YY = 4;//3XH-3 红绿黄,封绿灯,有单黄,带引导
HLU_DU = 5; //3XH-4 红绿黄,不封灯,有单黄,无引导
AB = 6; //DXCH 蓝白
HBU_DU = 7; //JCKXH 红白黄,不封灯,有单黄,无引导
}
*/
func convertToProtoSignalModel(gSmt data_proto.Signal_Model) proto.Signal_Model {
2023-10-20 09:38:23 +08:00
switch gSmt {
case data_proto.Signal_HL:
2023-10-20 09:38:23 +08:00
return proto.Signal_HL
case data_proto.Signal_HLU_FU:
2023-10-20 09:38:23 +08:00
return proto.Signal_HLU_FU
case data_proto.Signal_HLU_DU_YY:
2023-11-16 17:21:05 +08:00
return proto.Signal_HLU_DU_YY
case data_proto.Signal_HLU_YY:
2023-11-16 17:21:05 +08:00
return proto.Signal_HLU_YY
case data_proto.Signal_HLU_FL_DU_YY:
2023-11-16 17:21:05 +08:00
return proto.Signal_HLU_FL_DU_YY
case data_proto.Signal_HLU_DU:
2023-11-16 17:21:05 +08:00
return proto.Signal_HLU_DU
case data_proto.Signal_AB:
2023-10-20 09:38:23 +08:00
return proto.Signal_AB
case data_proto.Signal_HBU_DU:
2023-11-16 17:21:05 +08:00
return proto.Signal_HBU_DU
2023-10-20 09:38:23 +08:00
default:
panic(fmt.Sprintf("data_proto.Signal_Model[%d]无法映射到proto.Signal_Model", gSmt))
2023-10-20 09:38:23 +08:00
}
}
func convertToProtoBaliseType(bt data_proto.Transponder_TransponderTypeEnum) proto.Transponder_Type {
2023-11-23 13:30:08 +08:00
switch bt {
case data_proto.Transponder_FB:
2023-11-23 13:30:08 +08:00
return proto.Transponder_FB
case data_proto.Transponder_WB:
2023-11-23 13:30:08 +08:00
return proto.Transponder_WB
case data_proto.Transponder_DB:
2023-11-23 13:30:08 +08:00
return proto.Transponder_DB
case data_proto.Transponder_VB:
2023-11-23 13:30:08 +08:00
return proto.Transponder_VB
case data_proto.Transponder_IB:
2023-11-23 13:30:08 +08:00
return proto.Transponder_IB
default:
panic(fmt.Sprintf("data_proto.Transponder_TransponderTypeEnum[%d]无法映射到proto.Transponder_Type", bt))
2023-11-23 13:30:08 +08:00
}
}
2023-11-24 15:20:05 +08:00
// VerifyEvn 测试环境
type VerifyEvn interface {
EvnWorld() ecs.World
}