rts-sim-testing-service/ts/simulation/wayside/memory/wayside_simulation.go
2023-12-13 15:05:42 +08:00

1528 lines
47 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package memory
import (
"encoding/json"
"fmt"
"log/slog"
"math"
"sort"
"strconv"
"strings"
"sync"
"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/electrical_machinery"
"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"
"joylink.club/bj-rtsts-server/ts/protos/state"
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
"joylink.club/rtsssimulation/fi"
"joylink.club/rtsssimulation/repository"
"joylink.club/rtsssimulation/repository/model/proto"
)
// 轨旁仿真定义
type VerifySimulation struct {
//地图id
MapIds []int32
// 项目ID
ProjectId int32
//仿真id
SimulationId string
//仿真内存数据
Memory *WaysideMemory
//模型仓库
Repo *repository.Repository
//Rtss仿真世界的
World ecs.World
//设备UID映射
uidMap map[string]*elementIdStructure
// 运行环境配置
runConfig *config.ThridPartyConfig
// 运行状态
runState state.SimulationStatus_SimulationState
}
// 轨旁仿真内存模型
type WaysideMemory struct {
//可变状态数据:轨旁仿真模型状态(全量数据)
Status *VerifyStatus
// 要变更的状态:用户操作过的状态记录在这里,增量推送次数据
ChangeStatus *ChangeVerifyStatus
//状态保护锁
rwLock *sync.RWMutex
}
// 轨旁仿真模型状态
type VerifyStatus struct {
//道岔状态key为道岔id即索引 state.SwitchState
SwitchStateMap sync.Map
//轨道状态key为轨道id即索引 state.LinkState
LinkStateMap sync.Map
//列车状态key为列车id即索引 state.TrainState
TrainStateMap sync.Map
//计轴区段状态key为计轴区段的id即索引 state.SectionState
AxleSectionStateMap sync.Map
//物理区段状态key为物理区段id即索引 state.SectionState
PhysicalSectionStateMap sync.Map
//逻辑区段状态key为逻辑区段id即索引 state.SectionState
LogicSectionStateMap sync.Map
//信号机状态key为信号机id,即索引 state.SignalState
SignalStateMap sync.Map
}
// 轨旁仿真模型状态(变更)
type ChangeVerifyStatus struct {
VerifyStatus
//删除的列车ID列表
RemoveTrainId []string
}
func NewWaysideMemory() *WaysideMemory {
return &WaysideMemory{
Status: &VerifyStatus{},
ChangeStatus: &ChangeVerifyStatus{},
rwLock: &sync.RWMutex{},
}
}
// 创建仿真对象
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,
runState: state.SimulationStatus_PAUSE,
}
// 设置运行环境
err := verifySimulation.initRunConfig(runConfig)
if err != nil {
return nil, err
}
// 构建Repository
err = verifySimulation.initRepository()
if err != nil {
return nil, err
}
return verifySimulation, nil
}
// 启动
func (s *VerifySimulation) Start() {
s.runState = state.SimulationStatus_START
}
// 销毁
func (s *VerifySimulation) Destroy() {
s.runState = state.SimulationStatus_DESTROY
}
// 暂停
func (s *VerifySimulation) Pause() {
s.runState = state.SimulationStatus_PAUSE
}
// 获取状态
func (s *VerifySimulation) GetRunState() state.SimulationStatus_SimulationState {
return s.runState
}
// 获取仿真世界信息
func (s *VerifySimulation) GetComIdByUid(uid string) string {
es := s.uidMap
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
}
// GetBtmCanetConfig 获取CANET配置信息
func (s *VerifySimulation) GetBtmCanetConfig() config.BtmCanetConfig {
return s.runConfig.BtmCanet
}
func (s *VerifySimulation) GetLineAllRsspAxleCfgs() []config.RsspAxleConfig {
return s.runConfig.RsspAxleCfgs
}
// GetSectionCodePoints 获取集中站的区段码表
func (s *VerifySimulation) GetSectionCodePoints(city string, lineId string, centralizedStation string) []*proto.CiSectionCodePoint {
stationUid := GenerateElementUid(city, lineId, nil, centralizedStation)
ref := s.Repo.GetCentralizedStationRef(stationUid)
if ref == nil {
return nil
}
//
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)
if len(codePoints) <= 0 {
return nil, fmt.Errorf("没有找到GetCentralizedStationRef[%s]的区段码表为空", stationUid)
}
//slog.Debug("收集计轴区段状态", "区段码表len", len(codePoints))
//
var msg []*message.SectionStatusMsg
var axleSectionIds []string
for _, section := range codePoints {
axleSectionIds = append(axleSectionIds, section.SectionId)
}
//
//slog.Debug("收集计轴区段状态", "计轴区段len", len(axleSectionIds), "axleSectionIds", axleSectionIds)
as, e := fi.FindAxleSectionsStatus(s.World, axleSectionIds)
if e != nil { //从仿真中收集计轴区段状态的失败列表
return nil, e
}
//slog.Debug("收集计轴区段状态", "仿真中计轴状态len", len(as))
//
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 := &message.SectionStatusMsg{}
state.Rac = sectionState.Rac
state.Rjt = sectionState.Rjt
state.Rjo = sectionState.Rjo
state.Occ = sectionState.Occ
state.Clr = sectionState.Clr
msg = append(msg, state)
} else {
return nil, fmt.Errorf("仿真中没有对应区段[%s]的状态", codePoint.SectionId)
}
}
//
//slog.Debug("收集计轴区段状态", "区段计轴msgLen", len(msg))
return msg, nil
}
// 采集动力学道岔状态
func (s *VerifySimulation) CollectDynamicsTurnoutInfo() []*message.DynamicsTurnoutInfo {
var turnoutStates []*message.DynamicsTurnoutInfo
for _, o := range s.Repo.TurnoutList() {
sta := s.uidMap[o.Id()]
if sta == nil {
continue
}
code64, err := strconv.ParseUint(sta.CommonId, 10, 16)
if err != nil {
slog.Error("id转uint16报错", err)
}
s := handlerDynamicsTurnoutState(s.World, o.Id())
if s == nil {
continue
}
s.Code = uint16(code64)
turnoutStates = append(turnoutStates, s)
}
return turnoutStates
}
// HandleSectionCmdMsg 计轴设备接收到联锁发送来的控制命令
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
}
//
codePoints := ref.SectionCodePoints
if len(codePoints) != len(msg.Scs) {
slog.Warn(fmt.Sprintf("本地配置区段码表个数[%d] != 联锁发送集中站[%s]的区段命令个数[%d]", len(codePoints), stationUid, len(msg.Scs)))
return
}
//
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)
}
func handlerDynamicsTurnoutState(w ecs.World, uid string) *message.DynamicsTurnoutInfo {
entry, ok := entity.GetEntityByUid(w, uid)
if !ok {
fmt.Printf("id=%s的道岔不存在", uid)
return nil
}
if !entry.HasComponent(component.TurnoutPositionType) {
return nil
}
pos := component.TurnoutPositionType.Get(entry)
return &message.DynamicsTurnoutInfo{NPosition: pos.Dw, RPosition: pos.Fw}
}
// 处理动力学列车速度消息
func (s *VerifySimulation) HandleDynamicsTrainInfo(info *message.DynamicsTrainInfo) {
trainId := strconv.Itoa(int(info.Number))
_, ok := s.Memory.Status.TrainStateMap.Load(trainId)
if !ok {
return
}
// 给半实物仿真发送速度
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
}
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 {
turnoutId, _ := strconv.Atoi(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 {
turnoutId, _ := strconv.Atoi(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() {
id, _ := strconv.Atoi(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() {
id, _ := strconv.Atoi(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.TrainState)
if !train.Show { // 下线列车
return false
}
trainId, err := strconv.Atoi(train.Id)
if err != nil {
panic(dto.ErrorDto{Code: dto.ArgumentParseError, Message: err.Error()})
}
d := append(b, uint8(trainId))
// 发送给动力学
dynamics.Default().SendTrainControlMessage(d)
// 存放至列车中
controlMessage := &message.TrainControlMsg{}
controlMessage.Decode(b)
train.VobcState = controlMessage.ControlInfo
return true
})
}
// 获取半实物运行配置信息
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
}
configs = append(configs, &config.InterlockConfig{
Code: stationMap[c.Code],
Ip: c.Ip,
LocalPort: c.LocalPort,
RemotePort: c.RemotePort,
Open: c.Open,
})
}
return configs
}
// 处理接到的联锁消息
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
}
}
// 采集联锁中的继电器消息
func (s *VerifySimulation) CollectInterlockRelayInfo(code string) *message.InterlockSendMsgPkg {
for _, m := range s.Repo.CiQcList() { // 获取继电器地图信息
if m.StationId != code {
continue
}
if len(m.CjList) == 0 {
return nil
}
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 && fi.CollectXQCircuitState(s.World, j.RelayId)
} else {
rs = rs && fi.CollectLXCircuitState(s.World, j.RelayId)
}
if !rs {
break
}
}
collectInfo[i] = rs
}
return message.NewInterlockSendMsgPkg(collectInfo)
}
return nil
}
// 获取电机转速参数
func (s *VerifySimulation) GetElectricMachineryRunConfig() *config.ElectricMachineryConfig {
return &s.runConfig.ElectricMachinery
}
// 初始化仿真运行配置
func (s *VerifySimulation) initRunConfig(runConfig *dto.ProjectRunConfigDto) error {
if runConfig == nil || runConfig.ConfigContent == "" {
return nil
}
var configMap config.ThridPartyConfig
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) EvnWorld() ecs.World {
return s.World
}
// 初始化运行资源
func (s *VerifySimulation) initRepository() error {
// 构建Repository
var mapIdStrSlice []string
for _, id := range s.MapIds {
mapIdStrSlice = append(mapIdStrSlice, strconv.Itoa(int(id)))
}
repoId := strings.Join(mapIdStrSlice, "|")
repoVersion := "0.1"
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
}
func buildProtoRepository(mapIds []int32) (*proto.Repository, error) {
repo := &proto.Repository{}
var exceptStationGiMapIds []int32
//创建设备
for _, mapId := range mapIds {
giType := QueryGiType(mapId)
if giType == graphicData.PictureType_StationLayout {
stationGi := QueryGiData[*graphicData.RtssGraphicStorage](mapId)
fillProtoRepository(repo, stationGi, mapId)
} else {
exceptStationGiMapIds = append(exceptStationGiMapIds, mapId)
}
}
//构建并关联电子元件
for _, mapId := range exceptStationGiMapIds {
giType := QueryGiType(mapId)
if giType == graphicData.PictureType_RelayCabinetLayout {
relayGi := QueryGiData[*graphicData.RelayCabinetGraphicStorage](mapId)
buildAndRelateElectronicComponent(repo, relayGi, mapId)
}
}
//构建信号平面图中物理区段码表与集中站的关系
for _, mapId := range mapIds {
giType := QueryGiType(mapId)
if giType == graphicData.PictureType_StationLayout {
stationGi := QueryGiData[*graphicData.RtssGraphicStorage](mapId)
buildSectionCodePoint(repo, stationGi, mapId)
}
}
//
return repo, nil
}
func buildSectionCodePoint(repo *proto.Repository, storage *graphicData.RtssGraphicStorage, mapId int32) {
city := storage.UniqueIdPrefix.City
lineId := storage.UniqueIdPrefix.LineId
for _, sscp := range storage.SectionCodePointList {
centralizedStation := sscp.CentralizedStation
sectionGIds := sscp.SectionIds
centralizedStationId := GenerateElementUid(city, lineId, nil, centralizedStation)
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, &graphicData.Section{})
ccs = append(ccs, cc)
}
ref.SectionCodePoints = ccs
}
}
func buildAndRelateElectronicComponent(repo *proto.Repository, relayGi *graphicData.RelayCabinetGraphicStorage, mapId int32) {
relayUidStructure := QueryUidStructure[*RelayUidStructure](mapId)
city := relayGi.UniqueIdPrefix.City
lineId := relayGi.UniqueIdPrefix.LineId
station := relayGi.UniqueIdPrefix.BelongsConcentrationStation
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,
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
}
ciecs := stationMap[stationUid] //联锁集中站
if ciecs == nil {
panic(fmt.Errorf("联锁集中站[%s]不存在", stationUid))
}
for _, relationship := range relayGi.DeviceRelateRelayList {
switch relationship.DeviceType {
case graphicData.RelatedRef_Turnout:
turnout := turnoutMap[GenerateElementUid(city, lineId, []string{station}, relationship.Code)]
if turnout == nil {
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)
}
turnout.ElectronicComponentGroups = append(turnout.ElectronicComponentGroups,
&proto.ElectronicComponentGroup{
Code: group.Code,
ComponentIds: componentIds,
})
}
case graphicData.RelatedRef_signal:
signal := signalMap[GenerateElementUid(city, lineId, []string{station}, relationship.Code)]
if signal == nil {
continue
}
//信号机只有一个组合类型
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 {
continue
}
componentIds = append(componentIds, relayUidStructure.RelayIds[relayId].Uid)
}
signal.Code = group.Code
signal.ElectronicComponentGroups = append(signal.ElectronicComponentGroups,
&proto.ElectronicComponentGroup{
Code: group.Code,
ComponentIds: componentIds,
})
case graphicData.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 {
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 graphicData.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 graphicData.RelatedRef_SignalFaultAlarm: // 信号机故障报警仪设备组合
{
egs := buildEgs(relationship.Combinationtypes, relayUidStructure)
ciecs.Deccs = append(ciecs.Deccs, &proto.DeviceEcc{
DeviceType: proto.DeviceType_DeviceType_SignalFaultAlarm,
Egs: egs,
})
}
case graphicData.RelatedRef_Breakers: // 断路器
{
egs := buildEgs(relationship.Combinationtypes, relayUidStructure)
ciecs.Deccs = append(ciecs.Deccs, &proto.DeviceEcc{
DeviceType: proto.DeviceType_DeviceType_Breakers,
Egs: egs,
})
}
case graphicData.RelatedRef_PowerScreen: // 电源屏
{
egs := buildEgs(relationship.Combinationtypes, relayUidStructure)
ciecs.Deccs = append(ciecs.Deccs, &proto.DeviceEcc{
DeviceType: proto.DeviceType_DeviceType_PowerScreen,
Egs: egs,
})
}
}
}
//门控箱
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
}
}
}
}
}
}
//cis := stationMap[stationUid]
//// 零散组合
//for _, com := range relayGi.CombinationtypeList {
// if com.Code == "LS" { // 零散组合
// d := &proto.ElectronicGroup{Code: com.Code}
// for _, relayId := range com.RefRelays {
// if relayUidStructure.RelayIds[relayId] == nil {
// continue
// }
// d.Components = append(d.Components, &proto.ElectronicComponent{
// Id: relayUidStructure.RelayIds[relayId].Uid,
// DeviceType: proto.DeviceType_DeviceType_Relay,
// })
// }
// cis.ElectronicGroup = append(cis.ElectronicGroup, d)
// fmt.Println("构建零散组合结果:", d)
// }
//}
// 处理该集中站采集、驱动配置信息
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 []*graphicData.Combinationtype, relayUidStructure *RelayUidStructure) []*proto.ElectronicComponentGroup {
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
}
}
})
}
// 查询集中站配置信息
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 *graphicData.CiCj) []*proto.CjData {
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 {
panic(sys_error.New(fmt.Sprintf("集中站【id:%s】不存在继电器的【comId:%s】UID映射关系", stationId, j.RelayId)))
}
d := &proto.CjDataItem{RelayId: u.Uid}
if j.Position == graphicData.CjDataItem_H {
d.Q = false
} else {
d.Q = true
}
r.RefRelays = append(r.RefRelays, d)
}
}
cjList[index] = r
index++
}
}
return cjList
}
// 处理继电器驱动信息
func handlerRelayGiQd(uidsMap *RelayUidStructure, stationId string, ciQd *graphicData.CiQd) []*proto.QdData {
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 {
panic(sys_error.New(fmt.Sprintf("集中站【id:%s】不存在继电器的【comId:%s】UID映射关系", stationId, j)))
}
r.RefRelays = append(r.RefRelays, u.Uid)
}
}
qdList[index] = r
index++
}
}
return qdList
}
func convertRelayModel(modelType graphicData.Relay_ModelType) proto.Relay_Model {
switch modelType {
case graphicData.Relay_Unknown:
return proto.Relay_Unknown
case graphicData.Relay_JPXC_1000:
return proto.Relay_JPXC_1000
case graphicData.Relay_JPXC_1700:
return proto.Relay_JPXC_1700
case graphicData.Relay_JWJXC_480:
return proto.Relay_JWJXC_480
case graphicData.Relay_JWJXC_H125_80:
return proto.Relay_JWJXC_H125_80
case graphicData.Relay_JWXC_1700:
return proto.Relay_JWXC_1700
case graphicData.Relay_JWXC_H340:
return proto.Relay_JWXC_H340
case graphicData.Relay_JYJXC_160_260:
return proto.Relay_JYJXC_160_260
case graphicData.Relay_JZXC_H18:
return proto.Relay_JZXC_H18
default:
panic(fmt.Sprintf("意料之外的继电器型号:%s", modelType))
}
}
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)
for _, data := range storage.AxleCountings {
id := GetMapElementId(data.Common)
axleCountingMap[id] = data
cpType := proto.CheckPointType_AxleCounter
if data.Type == graphicData.AxleCounting_SectionBoundary {
cpType = proto.CheckPointType_Boundary
}
cp := &proto.CheckPoint{
Id: id,
Km: convertKm(data.KilometerSystem),
Type: cpType,
DevicePorts: convertDevicePorts(data.AxleCountingRef),
}
repo.CheckPoints = append(repo.CheckPoints, converCheckPointUid(cp, uidsMap))
}
for _, data := range storage.Section {
var turnoutIds []string
if data.SectionType == graphicData.Section_TurnoutPhysical {
turnoutIds = findTurnoutIds(axleCountingMap, data.AxleCountings)
}
centralizedStation := ""
if len(data.CentralizedStations) > 0 {
s := uidsMap.StationIds[data.CentralizedStations[0]]
if s != nil {
centralizedStation = s.Code
} else {
centralizedStation = data.CentralizedStations[0]
}
}
physicalSection := &proto.PhysicalSection{
Id: GetMapElementId(data.Common),
ADevicePort: convertDevicePort(data.PaRef),
BDevicePort: convertDevicePort(data.PbRef),
TurnoutIds: turnoutIds,
CentralizedStation: centralizedStation,
}
repo.PhysicalSections = append(repo.PhysicalSections, converSectionUid(physicalSection, uidsMap))
}
for _, data := range storage.Turnouts {
var km *proto.Kilometer
for _, ks := range data.KilometerSystem {
if ks.Kilometer != 0 {
km = convertKm(ks)
break
}
}
var switchMachineType proto.Turnout_SwitchMachineType
switch data.SwitchMachineType {
case graphicData.Turnout_ZDJ9_Single:
switchMachineType = proto.Turnout_ZDJ9_Single
case graphicData.Turnout_ZDJ9_Double:
switchMachineType = proto.Turnout_ZDJ9_Double
}
turnout := &proto.Turnout{
Id: GetMapElementId(data.Common),
Km: km,
ADevicePort: convertDevicePort(data.PaRef),
BDevicePort: convertDevicePort(data.PbRef),
CDevicePort: convertDevicePort(data.PcRef),
SwitchMachineType: switchMachineType,
}
repo.Turnouts = append(repo.Turnouts, converTurnoutUid(turnout, uidsMap))
}
for _, data := range storage.Signals {
var sectionId string
var turnoutPort *proto.DevicePort
switch data.RefDev.DeviceType {
case graphicData.RelatedRef_Section:
sectionId = data.RefDev.Id
case graphicData.RelatedRef_Turnout:
turnoutPort = convertDevicePort(data.RefDev)
}
signal := &proto.Signal{
Id: GetMapElementId(data.Common),
Km: convertKm(data.KilometerSystem),
SectionId: sectionId,
TurnoutPort: turnoutPort,
Model: convertToProtoSignalModel(data.Mt),
}
repo.Signals = append(repo.Signals, converSignalUid(signal, uidsMap))
}
stm := make(map[string][]string)
for _, data := range storage.Transponders {
var sectionId string
var turnoutPort *proto.DevicePort
switch data.TransponderRef.DeviceType {
case graphicData.RelatedRef_Section:
sectionId = data.TransponderRef.Id
case graphicData.RelatedRef_Turnout:
turnoutPort = convertDevicePort(data.TransponderRef)
}
responder := &proto.Transponder{
Id: GetMapElementId(data.Common),
Km: convertKm(data.KilometerSystem),
SectionId: sectionId,
TurnoutPort: turnoutPort,
FixedTelegram: data.FixedTelegram,
Type: convertToProtoBaliseType(data.Type),
}
repo.Transponders = append(repo.Transponders, converTransponderUid(responder, uidsMap))
for _, stationId := range data.CentralizedStations {
var stationName string
if uidsMap.StationIds[stationId] == nil {
stationName = stationId
} else {
stationName = uidsMap.StationIds[stationId].Code
}
if stm[stationName] == nil {
stm[stationName] = []string{responder.Id}
} else {
stm[stationName] = append(stm[stationName], responder.Id)
}
}
}
slopeKsMap := make(map[string]*graphicData.SlopeKiloMarker)
for _, data := range storage.SlopeKiloMarker {
slopeKsMap[GetMapElementId(data.Common)] = data
}
curveKsMap := make(map[string]*graphicData.CurvatureKiloMarker)
for _, data := range storage.CurvatureKiloMarker {
curveKsMap[GetMapElementId(data.Common)] = data
}
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{
Id: GetMapElementId(data.Common),
Kms: kms,
Degree: data.SlopeNumber,
}
repo.Slopes = append(repo.Slopes, converSlopeUid(slope, uidsMap))
}
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{
Id: GetMapElementId(data.Common),
Kms: kms,
Radius: data.CurvatureNumber,
}
repo.SectionalCurvatures = append(repo.SectionalCurvatures, converCurvatureUid(slope, uidsMap))
}
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]*graphicData.StationRelateDevice)
for _, data := range storage.StationRelateDeviceList {
relateMap[data.Code] = data
}
// 处理车站信息
for _, data := range storage.Stations {
station := &proto.Station{
Id: uidsMap.StationIds[GetMapElementId(data.Common)].Uid,
Code: data.StationName,
}
// 关联车站的设备
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)
}
}
// 处理车站关联IBP的设备
handlerIBPDeviceToStation(station, repo, data.RefIbpMapCode)
repo.Stations = append(repo.Stations, station)
// 处理集中站的信息
if stm[station.Code] != nil {
ref := queryCentralizedStationRef(station.Id, repo)
ref.TransponderId = append(ref.TransponderId, stm[station.Code]...)
}
}
//门控箱
for _, data := range storage.GateBoxs {
boxUidInfo := uidsMap.GateBoxIds[GetMapElementId(data.Common)]
mkx := &proto.Mkx{
Id: boxUidInfo.Uid,
PsdId: uidsMap.PsdIds[data.RefScreenDoor].Uid,
}
repo.Mkxs = append(repo.Mkxs, mkx)
pslMapId := QueryGiId(data.RefGatedBoxMapCode)
pslStorage := QueryGiData[*graphicData.PslGraphicStorage](pslMapId)
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.PcbButtonId = repoButton.Id
case "POB":
mkx.PobButtonId = repoButton.Id
case "PAB":
mkx.PabButtonId = repoButton.Id
}
}
}
//站台
platformMap := make(map[string]*graphicData.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
}
//屏蔽门
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,
}
repo.Psds = append(repo.Psds, psd)
}
}
// 将IBP的设备关联到车站中
func handlerIBPDeviceToStation(station *proto.Station, repo *proto.Repository, ibpMapCode string) {
mapId, storage := GetStorageIBPMapData(ibpMapCode)
if storage == nil {
return
}
uidMap := QueryUidStructure[*IBPUidStructure](mapId)
deviceMap := make(map[string]*proto.ElectronicComponent) // 对应的设备类型
for _, data := range storage.IbpButtons { // 处理按钮
id := GetMapElementId(data.Common)
b := &proto.Button{
Id: station.Id + "_" + uidMap.IbpButtonIds[id].Uid,
Code: data.Code,
ButtonType: proto.Button_NO_Reset_Press,
HasLight: data.HasLight,
}
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)
b := &proto.Key{
Id: station.Id + "_" + uidMap.IbpKeyIds[id].Uid,
Code: data.Code,
Gear: 2,
}
deviceMap[id] = &proto.ElectronicComponent{
Id: b.Id,
DeviceType: proto.DeviceType_DeviceType_Key,
}
repo.Keys = append(repo.Keys, b)
}
for _, data := range storage.IbpAlarms { // 报警器
id := GetMapElementId(data.Common)
b := &proto.Alarm{
Id: station.Id + "_" + 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)
}
for _, data := range storage.IbpLights { // 指示灯,
id := GetMapElementId(data.Common)
b := &proto.Light{
Id: station.Id + "_" + uidMap.IbpLightIds[id].Uid,
Code: data.Code,
}
deviceMap[id] = &proto.ElectronicComponent{
Id: b.Id,
DeviceType: proto.DeviceType_DeviceType_Light,
}
repo.Lights = append(repo.Lights, b)
}
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 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)
}
return data
}
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)
}
if data.BDevicePort != nil {
data.BDevicePort.DeviceId = converRefUid(data.BDevicePort.DeviceId, data.BDevicePort.DeviceType, uidsMap)
}
tids := make([]string, len(data.TurnoutIds))
for i, tid := range data.TurnoutIds {
tids[i] = converRefUid(tid, proto.DeviceType_DeviceType_Turnout, uidsMap)
}
data.TurnoutIds = tids
return data
}
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)
}
if data.BDevicePort != nil {
data.BDevicePort.DeviceId = converRefUid(data.BDevicePort.DeviceId, data.BDevicePort.DeviceType, uidsMap)
}
if data.CDevicePort != nil {
data.CDevicePort.DeviceId = converRefUid(data.CDevicePort.DeviceId, data.CDevicePort.DeviceType, uidsMap)
}
return data
}
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)
}
if data.TurnoutPort != nil {
data.TurnoutPort.DeviceId = converRefUid(data.TurnoutPort.DeviceId, data.TurnoutPort.DeviceType, uidsMap)
}
return data
}
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)
}
if data.TurnoutPort != nil {
data.TurnoutPort.DeviceId = converRefUid(data.TurnoutPort.DeviceId, data.TurnoutPort.DeviceType, uidsMap)
}
return data
}
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 {
data.Id = uidsMap.CurvatureIds[data.Id].Uid
return data
}
func converRefUid(id string, d proto.DeviceType, uidsMap *StationUidStructure) string {
var elementId *elementIdStructure
switch d {
case proto.DeviceType_DeviceType_CheckPoint:
elementId = uidsMap.AxlePointIds[id]
case proto.DeviceType_DeviceType_PhysicalSection:
elementId = uidsMap.PhysicalSectionIds[id]
case proto.DeviceType_DeviceType_SectionalCurvature:
elementId = uidsMap.CurvatureIds[id]
case proto.DeviceType_DeviceType_Signal:
elementId = uidsMap.SignalIds[id]
case proto.DeviceType_DeviceType_Slope:
elementId = uidsMap.SlopeIds[id]
case proto.DeviceType_DeviceType_Transponder:
elementId = uidsMap.TransponderIds[id]
case proto.DeviceType_DeviceType_Turnout:
elementId = uidsMap.TurnoutIds[id]
default:
panic(&dto.ErrorDto{Code: dto.ArgumentParseError, Message: "异常的设备类型-" + d.String()})
}
if elementId == nil {
return ""
}
return elementId.Uid
}
func convertKm(ks *graphicData.KilometerSystem) *proto.Kilometer {
var dir proto.Direction
switch ks.Direction {
case graphicData.KilometerSystem_LEFT:
dir = proto.Direction_LEFT
case graphicData.KilometerSystem_RIGHT:
dir = proto.Direction_RIGHT
}
return &proto.Kilometer{
Value: ks.Kilometer,
CoordinateSystem: ks.CoordinateSystem,
Direction: dir,
}
}
func convertDevicePort(ref *graphicData.RelatedRef) *proto.DevicePort {
if ref == nil {
return nil
}
var deviceType proto.DeviceType
var port proto.Port
switch ref.DevicePort {
case graphicData.RelatedRef_A:
port = proto.Port_A
case graphicData.RelatedRef_B:
port = proto.Port_B
case graphicData.RelatedRef_C:
port = proto.Port_C
}
switch ref.DeviceType {
case graphicData.RelatedRef_Section:
deviceType = proto.DeviceType_DeviceType_PhysicalSection
case graphicData.RelatedRef_Turnout:
deviceType = proto.DeviceType_DeviceType_Turnout
default:
panic(fmt.Sprintf("异常的设备类型-%s", ref.DeviceType))
}
return &proto.DevicePort{
DeviceId: ref.Id,
DeviceType: deviceType,
Port: port,
}
}
func convertDevicePorts(refList []*graphicData.RelatedRef) []*proto.DevicePort {
var dps []*proto.DevicePort
for _, ref := range refList {
dps = append(dps, convertDevicePort(ref))
}
return dps
}
func findTurnoutIds(axleCountingMap map[string]*graphicData.AxleCounting, axleIds []string) []string {
if len(axleIds) <= 2 {
return nil
}
turnoutMap := make(map[string]int)
for _, axleId := range axleIds {
axle := axleCountingMap[axleId]
for _, ref := range axle.AxleCountingRef {
if ref.DeviceType == graphicData.RelatedRef_Turnout {
turnoutMap[ref.Id] = turnoutMap[ref.Id] + 1
}
}
}
var turnoutIds []string
for id, num := range turnoutMap {
if num > 1 {
turnoutIds = append(turnoutIds, id)
}
}
return turnoutIds
}
/*
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 graphicData.Signal_Model) proto.Signal_Model {
switch gSmt {
case graphicData.Signal_HL:
return proto.Signal_HL
case graphicData.Signal_HLU_FU:
return proto.Signal_HLU_FU
case graphicData.Signal_HLU_DU_YY:
return proto.Signal_HLU_DU_YY
case graphicData.Signal_HLU_YY:
return proto.Signal_HLU_YY
case graphicData.Signal_HLU_FL_DU_YY:
return proto.Signal_HLU_FL_DU_YY
case graphicData.Signal_HLU_DU:
return proto.Signal_HLU_DU
case graphicData.Signal_AB:
return proto.Signal_AB
case graphicData.Signal_HBU_DU:
return proto.Signal_HBU_DU
default:
panic(fmt.Sprintf("graphicData.Signal_Model[%d]无法映射到proto.Signal_Model", gSmt))
}
}
func convertToProtoBaliseType(bt graphicData.Transponder_TransponderTypeEnum) proto.Transponder_Type {
switch bt {
case graphicData.Transponder_FB:
return proto.Transponder_FB
case graphicData.Transponder_WB:
return proto.Transponder_WB
case graphicData.Transponder_DB:
return proto.Transponder_DB
case graphicData.Transponder_VB:
return proto.Transponder_VB
case graphicData.Transponder_IB:
return proto.Transponder_IB
default:
panic(fmt.Sprintf("graphicData.Transponder_TransponderTypeEnum[%d]无法映射到proto.Transponder_Type", bt))
}
}
// VerifyEvn 测试环境
type VerifyEvn interface {
EvnWorld() ecs.World
}