rts-sim-testing-service/message_server/sfp_ms.go
thesai 4044b7f4c2
All checks were successful
local-test分支打包构建docker并发布运行 / Docker-Build (push) Successful in 1m44s
[新增]计轴区段的模型、ecs实体、ecs系统、发给前端的状态
2024-08-12 18:57:36 +08:00

767 lines
29 KiB
Go

package message_server
import (
"fmt"
"joylink.club/bj-rtsts-server/sys_error"
"log/slog"
"reflect"
"runtime/debug"
"strings"
"time"
"joylink.club/bj-rtsts-server/dto/request_proto"
"joylink.club/bj-rtsts-server/dto/state_proto"
"joylink.club/rtsssimulation/repository/model/proto"
"joylink.club/bj-rtsts-server/dto/data_proto"
"joylink.club/bj-rtsts-server/message_server/ms_api"
"joylink.club/bj-rtsts-server/mqtt"
appcomponent "joylink.club/bj-rtsts-server/ts/simulation/app_component"
"joylink.club/bj-rtsts-server/ts/simulation/wayside/memory"
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
)
// 信号平面布置图消息服务
func NewSfpMs(vs *memory.VerifySimulation, mapId int32) ms_api.MsgTask {
return ms_api.NewScheduleTask(fmt.Sprintf("信号平面布置图[%d]状态", mapId), func() error {
turnoutStates, err := collectTurnoutStates(vs, mapId)
if err != nil {
return err
}
signalStates, err := collectSignalStates(vs.World, mapId)
if err != nil {
return err
}
//buttonStates, err := collectStationButtonStates(vs.World, mapId)
//if err != nil {
// return err
//}
psdStates, err := collectPsdStates(vs.World, mapId)
if err != nil {
return err
}
sectionStates, err := collectPhysicalSectionStates(vs.World, mapId)
if err != nil {
return err
}
platformStates, err := collectPlatformStates(vs.World, mapId)
if err != nil {
return err
}
trainState, err := collectTrainStates(vs)
if err != nil {
return err
}
baliseStates, err := collectBaliseStates(vs.World, mapId)
if err != nil {
return err
}
ckmStates, err := collectCkmStates(vs.World, mapId)
if err != nil {
return err
}
fymStates, err := collectFymStates(vs.World, mapId)
if err != nil {
return err
}
xcjStates, err := collectXcjStates(vs.World, mapId)
if err != nil {
return err
}
axleCountingSectionStates, err := collectAxleCountingSectionStates(vs.World, mapId)
if err != nil {
return err
}
ststes := &state_proto.PushedDevicesStatus{
All: true,
AllStatus: &state_proto.AllDevicesStatus{
TrainState: trainState,
SwitchState: turnoutStates,
SignalState: signalStates,
//ButtonState: buttonStates,
PsdState: psdStates,
SectionState: sectionStates,
PlatformState: platformStates,
BaliseState: baliseStates,
CkmStates: ckmStates,
FymStates: fymStates,
XcjStates: xcjStates,
AxleCountingSection: axleCountingSectionStates,
},
}
err = mqtt.GetMsgClient().PubSfpState(vs.SimulationId, mapId, ststes)
if err != nil {
return sys_error.New("发送状态消息异常", err)
}
return nil
}, 1000*time.Millisecond)
}
func collectAxleCountingSectionStates(world ecs.World, mapId int32) ([]*state_proto.AxleCountingSectionState, error) {
uidMap := memory.QueryMapUidMapByType(mapId, &data_proto.AxleCountingSection{})
var stateArr []*state_proto.AxleCountingSectionState
wd := entity.GetWorldData(world)
for _, u := range uidMap {
entry := wd.EntityMap[u.Uid]
if entry == nil {
continue
}
stateArr = append(stateArr, &state_proto.AxleCountingSectionState{
Id: u.CommonId,
Occupied: component.AxleCountingSectionStateType.Get(entry).Occupied,
})
}
return stateArr, nil
}
func collectXcjStates(world ecs.World, mapId int32) ([]*state_proto.XcjState, error) {
uidStructure := memory.QueryUidStructure[*memory.StationUidStructure](mapId)
var xcjStates []*state_proto.XcjState
for _, xcj := range uidStructure.XcjIds {
entry, ok := entity.GetEntityByUid(world, xcj.Uid)
if ok {
state := &state_proto.XcjState{Id: xcj.CommonId}
xcjStates = append(xcjStates, state)
//设置参数
var xcjParam *request_proto.XcjParam
if entry.HasComponent(appcomponent.XcjParamType) {
xcjParam = appcomponent.XcjParamType.Get(entry)
} else {
xcjParam = &request_proto.XcjParam{}
}
state.Param = xcjParam
//继电器状态
if entry.HasComponent(component.XcjCircuitType) {
circuit := component.XcjCircuitType.Get(entry)
state.Xqj = component.BitStateType.Get(circuit.XQJ).Val
for _, twj := range circuit.TWJList {
state.TwjList = append(state.TwjList, component.BitStateType.Get(twj).Val)
}
state.Tgqj = component.BitStateType.Get(circuit.TGQJ).Val
state.Xcjxj = component.BitStateType.Get(circuit.XCJXJ).Val
state.Xcyxj = component.BitStateType.Get(circuit.XCYXJ).Val
for _, cfj := range circuit.CFJList {
state.CfjList = append(state.CfjList, component.BitStateType.Get(cfj).Val)
}
state.Jtj = component.BitStateType.Get(circuit.JTJ).Val
state.Tgyxj = component.BitStateType.Get(circuit.TGYXJ).Val
}
}
}
return xcjStates, nil
}
func collectFymStates(world ecs.World, mapId int32) ([]*state_proto.CkmState, error) {
mapData := memory.QueryGiData[*data_proto.RtssGraphicStorage](mapId)
return collectCkmOrFymStates(world, mapId, mapData.FloodGates)
}
func collectCkmStates(world ecs.World, mapId int32) ([]*state_proto.CkmState, error) {
mapData := memory.QueryGiData[*data_proto.RtssGraphicStorage](mapId)
return collectCkmOrFymStates(world, mapId, mapData.GarageDoors)
}
func collectCkmOrFymStates(world ecs.World, mapId int32, gates []*data_proto.GarageDoor) ([]*state_proto.CkmState, error) {
uidStructure := memory.QueryUidStructure[*memory.StationUidStructure](mapId)
ckmUidMap := uidStructure.CkmIds
var ckmStates []*state_proto.CkmState
for _, ckm := range gates {
commonId := ckm.Common.Id
entry, ok := entity.GetEntityByUid(world, ckmUidMap[commonId].Uid)
if ok {
mgj := false
local := false
mplj := false
if entry.HasComponent(component.CkmCircuitType) {
circuit := component.CkmCircuitType.Get(entry)
mgj = component.BitStateType.Get(circuit.MGJ).Val
local = component.BitStateType.Get(circuit.MMSJ).Val
mplj = component.BitStateType.Get(circuit.MPLJ).Val
}
var ckmParam *request_proto.CkmParam
if entry.HasComponent(appcomponent.CkmParamType) {
ckmParam = appcomponent.CkmParamType.Get(entry)
} else {
ckmParam = &request_proto.CkmParam{}
}
ckmStates = append(ckmStates, &state_proto.CkmState{
Id: commonId,
Mgj: mgj,
Param: ckmParam,
Local: local,
Mplj: mplj,
})
}
}
return ckmStates, nil
}
// 收集应答器状态
func collectBaliseStates(world ecs.World, mapId int32) ([]*state_proto.BaliseState, error) {
uidStructure := memory.QueryUidStructure[*memory.StationUidStructure](mapId)
var transponderStates []*state_proto.BaliseState
for id, structure := range uidStructure.TransponderIds {
entry, ok := entity.GetEntityByUid(world, structure.Uid)
if ok {
baliseFixedTelegram := component.BaliseFixedTelegramType.Get(entry)
baliseWorkState := component.BaliseWorkStateType.Get(entry)
baliseState := &state_proto.BaliseState{
Id: id,
FixedTelegram: fmt.Sprintf("%X", baliseFixedTelegram.Telegram),
FixedUserTelegram: fmt.Sprintf("%X", baliseFixedTelegram.UserTelegram),
Work: baliseWorkState.Work,
}
if entry.HasComponent(component.BaliseVariableTelegramType) {
baliseVariableTelegram := component.BaliseVariableTelegramType.Get(entry)
baliseState.VariableTelegram = fmt.Sprintf("%X", baliseVariableTelegram.Telegram)
baliseState.VariableUserTelegram = fmt.Sprintf("%X", baliseVariableTelegram.UserTelegram)
}
transponderStates = append(transponderStates, baliseState)
km := component.KmType.Get(entry)
baliseState.Km = &data_proto.KilometerSystem{
Kilometer: km.Value,
CoordinateSystem: km.CoordinateSystem,
}
if km.Direction == proto.Direction_LEFT {
baliseState.Km.Direction = data_proto.KilometerSystem_LEFT
} else if km.Direction == proto.Direction_RIGHT {
baliseState.Km.Direction = data_proto.KilometerSystem_RIGHT
}
}
}
return transponderStates, nil
}
// 收集屏蔽门状态
func collectPsdStates(world ecs.World, mapId int32) ([]*state_proto.PsdState, error) {
uidStructure := memory.QueryUidStructure[*memory.StationUidStructure](mapId)
data := memory.QueryGiData[*data_proto.RtssGraphicStorage](mapId)
var psdStateArr []*state_proto.PsdState
for _, door := range data.ScreenDoors {
did := memory.GetMapElementId(door.Common)
uid := uidStructure.PsdIds[did].Uid
psdEntry, ok := entity.GetEntityByUid(world, uid)
if ok {
list := component.AsdListType.Get(psdEntry).List
asdStates := make([]*state_proto.AsdState, len(list))
for i, asdEntry := range list {
asdState := component.AsdStateType.Get(asdEntry)
asdStates[i] = &state_proto.AsdState{
Code: int32(i + 1),
Kmdw: asdState.Kmdw,
Gmdw: asdState.Gmdw,
Mgj: asdState.Mgj,
Zaw: asdState.Zaw,
Force: asdState.Force,
}
}
var param *request_proto.PsdParam
if psdEntry.HasComponent(appcomponent.PsdParamType) {
param = appcomponent.PsdParamType.Get(psdEntry)
} else {
param = &request_proto.PsdParam{}
}
psdStateArr = append(psdStateArr, &state_proto.PsdState{
Id: did,
AsdStates: asdStates,
Mgj: component.PsdStateType.Get(psdEntry).Close,
Param: param,
Zaw: component.PsdStateType.Get(psdEntry).Obstacle,
})
}
}
return psdStateArr, nil
}
// 收集区段状态
func collectPhysicalSectionStates(world ecs.World, mapId int32) ([]*state_proto.SectionState, error) {
uidMap := memory.QueryMapUidMapByType(mapId, &data_proto.Section{})
var sectionArr []*state_proto.SectionState
for _, u := range uidMap {
s := handlerSectionState(world, u.Uid)
if s == nil {
continue
}
s.Id = u.CommonId
sectionArr = append(sectionArr, s)
}
return sectionArr, nil
}
func handlerSectionState(w ecs.World, uid string) *state_proto.SectionState {
entry, ok := entity.GetEntityByUid(w, uid)
if !ok {
//fmt.Printf("id=%s的信号机不存在", uid)
return nil
}
if entry.HasComponent(component.PhysicalSectionManagerType) { //计轴区段
axleManager := component.PhysicalSectionManagerType.Get(entry)
sectionState := &state_proto.SectionState{
Occupied: axleManager.Occupied,
AxleFault: entry.HasComponent(component.PhysicalSectionForceOccupied),
AxleDrst: false,
AxlePdrst: axleManager.PDRST,
}
sectionState.Occupied = axleManager.Occupied
sectionState.AxleFault = entry.HasComponent(component.PhysicalSectionForceOccupied)
return sectionState
} else if entry.HasComponent(component.TrackCircuitType) { //轨道电路
sectionState := &state_proto.SectionState{
Occupied: component.BitStateType.Get(component.TrackCircuitType.Get(entry).GJ).Val,
AxleFault: false,
AxleDrst: false,
AxlePdrst: false,
}
return sectionState
}
return nil
}
// 收集车站按钮状态
func collectStationButtonStates(world ecs.World, mapId int32) ([]*state_proto.ButtonState, error) {
// 获取地图上的按钮状态
uidMap := memory.QueryMapUidMapByType(mapId, &data_proto.EsbButton{})
var btnStateArr []*state_proto.ButtonState
for _, u := range uidMap {
entry, ok := entity.GetEntityByUid(world, u.Uid)
if !ok {
return nil, fmt.Errorf("ESB按钮实体不存在: World id=%d, uid=%s", world.Id(), u.Uid)
}
if entry.HasComponent(component.ButtonTag) { // 按钮
bit := component.BitStateType.Get(entry)
btnStateArr = append(btnStateArr, &state_proto.ButtonState{ /*Bypass: bit.BypassEnable,*/ Id: u.CommonId, Down: bit.Val})
}
}
return btnStateArr, nil
}
// 收集信号机状态
func collectSignalStates(world ecs.World, mapId int32) ([]*state_proto.SignalState, error) {
uidMap := memory.QueryMapUidMapByType(mapId, &data_proto.Signal{})
var signalArr []*state_proto.SignalState
for _, u := range uidMap {
s, err := handlerSignalState(world, u.Uid)
if err != nil {
return nil, err
}
s.Id = u.CommonId
signalArr = append(signalArr, s)
}
return signalArr, nil
}
func handlerSignalState(w ecs.World, uid string) (*state_proto.SignalState, error) {
entry, ok := entity.GetEntityByUid(w, uid)
if !ok {
return nil, fmt.Errorf("信号机不存在: World id=%d, 信号机id=%s", w.Id(), uid)
}
if !entry.HasComponent(component.SignalLightsType) { //信号机灯列表
return nil, fmt.Errorf("信号机没有SignalLights组件: World id=%d, 信号机id=%s", w.Id(), uid)
}
signalState := &state_proto.SignalState{}
lights := component.SignalLightsType.Get(entry)
isL := false
isH := false
isU := false
isA := false
isB := false
for _, light := range lights.Lights {
switch {
case light.HasComponent(component.LdTag):
isL = component.BitStateType.Get(light).Val
case light.HasComponent(component.HdTag):
isH = component.BitStateType.Get(light).Val
case light.HasComponent(component.UdTag):
isU = component.BitStateType.Get(light).Val
case light.HasComponent(component.BdTag):
isB = component.BitStateType.Get(light).Val
case light.HasComponent(component.AdTag):
isA = component.BitStateType.Get(light).Val
}
}
if isH && isU {
signalState.Aspect = state_proto.Signal_HU
} else {
switch {
case isL:
signalState.Aspect = state_proto.Signal_L
case isH:
signalState.Aspect = state_proto.Signal_H
case isU:
signalState.Aspect = state_proto.Signal_U
case isB:
signalState.Aspect = state_proto.Signal_B
case isA:
signalState.Aspect = state_proto.Signal_A
}
}
if entry.HasComponent(appcomponent.SignalParamType) {
signalState.Param = appcomponent.SignalParamType.Get(entry)
} else {
signalState.Param = &request_proto.SignalParam{}
}
if entry.HasComponent(component.Signal2XH1ElectronicType) { // 2XH1信号机
signal2XH1 := component.Signal2XH1ElectronicType.Get(entry)
signalState.RelayStateMap = make(map[string]bool, 3)
signalState.RelayStateMap["DDJ"] = component.BitStateType.Get(signal2XH1.Z2XH1_DDJ).Val
signalState.RelayStateMap["LXJ"] = component.BitStateType.Get(signal2XH1.Z2XH1_LXJ).Val
signalState.RelayStateMap["DJ"] = component.BitStateType.Get(signal2XH1.Z2XH1_DJ).Val
} else if entry.HasComponent(component.Signal3XH1ElectronicType) { // 3XH1信号机
signal3XH1 := component.Signal3XH1ElectronicType.Get(entry)
signalState.RelayStateMap = make(map[string]bool, 6)
signalState.RelayStateMap["DDJ"] = component.BitStateType.Get(signal3XH1.Z3XH1_DDJ).Val
signalState.RelayStateMap["ZXJ"] = component.BitStateType.Get(signal3XH1.Z3XH1_ZXJ).Val
signalState.RelayStateMap["LXJ"] = component.BitStateType.Get(signal3XH1.Z3XH1_LXJ).Val
signalState.RelayStateMap["YXJ"] = component.BitStateType.Get(signal3XH1.Z3XH1_YXJ).Val
signalState.RelayStateMap["DJ"] = component.BitStateType.Get(signal3XH1.Z3XH1_DJ).Val
signalState.RelayStateMap["2DJ"] = component.BitStateType.Get(signal3XH1.Z3XH1_2DJ).Val
} else if entry.HasComponent(component.Signal3XH2ElectronicType) { // 3XH2信号机
signal3XH2 := component.Signal3XH2ElectronicType.Get(entry)
signalState.RelayStateMap = make(map[string]bool, 5)
signalState.RelayStateMap["DDJ"] = component.BitStateType.Get(signal3XH2.Z3XH2_DDJ).Val
signalState.RelayStateMap["LXJ"] = component.BitStateType.Get(signal3XH2.Z3XH2_LXJ).Val
signalState.RelayStateMap["YXJ"] = component.BitStateType.Get(signal3XH2.Z3XH2_YXJ).Val
signalState.RelayStateMap["DJ"] = component.BitStateType.Get(signal3XH2.Z3XH2_DJ).Val
signalState.RelayStateMap["2DJ"] = component.BitStateType.Get(signal3XH2.Z3XH2_2DJ).Val
} else if entry.HasComponent(component.Signal3XH3ElectronicType) { // 3XH3信号机
signal3XH3 := component.Signal3XH3ElectronicType.Get(entry)
signalState.RelayStateMap = make(map[string]bool, 5)
signalState.RelayStateMap["DDJ"] = component.BitStateType.Get(signal3XH3.Z3XH3_DDJ).Val
signalState.RelayStateMap["LXJ"] = component.BitStateType.Get(signal3XH3.Z3XH3_LXJ).Val
signalState.RelayStateMap["YXJ"] = component.BitStateType.Get(signal3XH3.Z3XH3_YXJ).Val
signalState.RelayStateMap["DJ"] = component.BitStateType.Get(signal3XH3.Z3XH3_DJ).Val
signalState.RelayStateMap["2DJ"] = component.BitStateType.Get(signal3XH3.Z3XH3_2DJ).Val
} else if entry.HasComponent(component.Signal3XH4ElectronicType) { // 3XH4信号机
signal3XH4 := component.Signal3XH4ElectronicType.Get(entry)
signalState.RelayStateMap = make(map[string]bool, 4)
signalState.RelayStateMap["DDJ"] = component.BitStateType.Get(signal3XH4.Z3XH4_DDJ).Val
signalState.RelayStateMap["LXJ"] = component.BitStateType.Get(signal3XH4.Z3XH4_LXJ).Val
signalState.RelayStateMap["ZXJ"] = component.BitStateType.Get(signal3XH4.Z3XH4_ZXJ).Val
signalState.RelayStateMap["DJ"] = component.BitStateType.Get(signal3XH4.Z3XH4_DJ).Val
}
return signalState, nil
}
// 收集列车状态
func collectTrainStates(vs *memory.VerifySimulation) ([]*state_proto.TrainMapState, error) {
allTrainMap := &vs.Memory.Status.TrainStateMap
var trainArr []*state_proto.TrainMapState
allTrainMap.Range(func(_, v any) bool {
trainArr = append(trainArr, convertTrainState(v.(*state_proto.TrainState)))
return true
})
return trainArr, nil
}
func convertTrainState(v *state_proto.TrainState) *state_proto.TrainMapState {
t := &state_proto.TrainMapState{
Id: v.Id,
Up: v.Up,
InitialSpeed: v.Speed,
TrainLength: v.TrainLength,
Show: v.Show,
HeadDeviceId: v.HeadDeviceId,
HeadOffset: v.HeadOffset,
DevicePort: v.DevicePort,
DriftTo: v.DriftTo,
TrainRunUp: v.TrainRunUp,
TrainActiveDirection: v.TrainActiveDirection,
TrainKilometer: v.TrainKilometer,
ControlDelayTime: v.ControlDelayTime,
WheelDiameter: v.WheelDiameter,
// 动力学
DynamicHeartbeat: v.DynamicState.Heartbeat,
HeadLinkId: v.DynamicState.HeadLinkId,
HeadLinkOffset: v.DynamicState.HeadLinkOffset,
TailLinkId: v.DynamicState.TailLinkId,
TailLinkOffset: v.DynamicState.TailLinkOffset,
OccupiedLinkIndex: v.DynamicState.OccupiedLinkIndex,
Slope: v.DynamicState.Slope,
Upslope: v.DynamicState.Upslope,
RunningUp: v.DynamicState.RunningUp,
RunningResistanceSum: v.DynamicState.RunningResistanceSum,
AirResistance: v.DynamicState.AirResistance,
RampResistance: v.DynamicState.RampResistance,
CurveResistance: v.DynamicState.CurveResistance,
Speed: v.DynamicState.Speed,
HeadSensorSpeed1: v.DynamicState.HeadSensorSpeed1,
HeadSensorSpeed2: v.DynamicState.HeadSensorSpeed2,
TailSensorSpeed1: v.DynamicState.TailSensorSpeed1,
TailSensorSpeed2: v.DynamicState.TailSensorSpeed2,
HeadRadarSpeed: v.DynamicState.HeadRadarSpeed,
TailRadarSpeed: v.DynamicState.TailRadarSpeed,
DynamicInterruption: v.DynamicState.UdpInterruption,
Acceleration: v.DynamicState.Acceleration,
Displacement: v.DynamicState.Displacement,
// 半实物
VobcLifeSignal: v.VobcState.LifeSignal,
Tc1Active: v.VobcState.Tc1Active,
Tc2Active: v.VobcState.Tc2Active,
DirectionForward: v.VobcState.DirectionForward,
DirectionBackward: v.VobcState.DirectionBackward,
TractionStatus: v.VobcState.TractionStatus,
BrakingStatus: v.VobcState.BrakingStatus,
EmergencyBrakingStatus: v.VobcState.EmergencyBrakingStatus,
TurnbackStatus: v.VobcState.TurnbackStatus,
JumpStatus: v.VobcState.JumpStatus,
Ato: v.VobcState.Ato,
Fam: v.VobcState.Fam,
Cam: v.VobcState.Cam,
TractionSafetyCircuit: v.VobcState.TractionSafetyCircuit,
ParkingBrakeStatus: v.VobcState.ParkingBrakeStatus,
MaintainBrakeStatus: v.VobcState.MaintainBrakeStatus,
TractionForce: v.VobcState.TractionForce,
BrakeForce: v.VobcState.BrakeForce,
TrainLoad: v.VobcState.TrainLoad,
LeftDoorOpenCommand: v.VobcState.LeftDoorOpenCommand,
RightDoorOpenCommand: v.VobcState.RightDoorOpenCommand,
LeftDoorCloseCommand: v.VobcState.LeftDoorCloseCommand,
RightDoorCloseCommand: v.VobcState.RightDoorCloseCommand,
AllDoorClose: v.VobcState.AllDoorClose,
VobcInterruption: v.VobcState.UdpInterruption,
TrainEndsA: &state_proto.TrainEndsStateMqtt{},
TrainEndsB: &state_proto.TrainEndsStateMqtt{},
TrainDynamicConfig: &state_proto.TrainDynamicConfigMqtt{},
TailDeviceId: v.TailDeviceId,
TailOffset: v.TailOffset,
TailDevicePort: v.TailDevicePort,
BtmState: v.BtmState,
ConnState: v.ConnState,
}
convertDynamicConfig(v.TrainDynamicConfig, t.TrainDynamicConfig)
convertDynamicConfig(v.TrainEndsA, t.TrainEndsA)
convertDynamicConfig(v.TrainEndsB, t.TrainEndsB)
//now := time.Now().Unix()
return t
}
func convertDynamicConfig(config, dest interface{}) {
configType := reflect.TypeOf(config).Elem()
for index := 0; index < configType.NumField(); index++ {
field := configType.Field(index)
if field.IsExported() {
fieldName := field.Name
setVal(config, dest, fieldName)
}
}
}
func setVal(source, dest interface{}, fieldName string) {
destVal := reflect.ValueOf(dest).Elem().FieldByName(fieldName)
sourceType := reflect.ValueOf(source).Elem().FieldByName(fieldName)
sourceData := sourceType.Interface()
defer func() {
err := recover()
if err != nil {
slog.Error(fieldName, "赋值失败,源数据类型", sourceType.Kind().String(), "目标数据类型:", destVal.Kind().String(), " 异常错误提示:", err)
debug.PrintStack()
}
}()
if destVal.Kind() == reflect.Invalid {
//slog.Warn(fieldName, "赋值失败,源数据类型", sourceType.Kind().String(), "目标数据类型:", destVal.Kind().String())
return
}
if destVal.Kind() == reflect.String {
destVal.Set(reflect.ValueOf(fmt.Sprintf("%v", sourceData)))
} else {
destVal.Set(reflect.ValueOf(sourceData))
}
}
/*
func convertEnds(ends *common_proto.TrainEndsState) *state_proto.TrainEndsStateMqtt {
return &state_proto.TrainEndsStateMqtt{SpeedSensorEnableA: ends.SpeedSensorEnableA,
SpeedSensorEnableB: ends.SpeedSensorEnableB,
RadarEnable: ends.RadarEnable,
RadarCheckSpeedDiff: floatToString(ends.RadarCheckSpeedDiff),
RadarCheckTime: ends.RadarCheckTime,
AccEnable: ends.AccEnable,
AccCheckSpeedDiff: floatToString(ends.AccCheckSpeedDiff),
AccCheckTime: ends.AccCheckTime,
}
}
*/
// 收集道岔状态
func collectTurnoutStates(sim *memory.VerifySimulation, mapId int32) ([]*state_proto.SwitchState, error) {
uidMap := memory.QueryMapUidMapByType(mapId, &data_proto.Turnout{})
wd := entity.GetWorldData(sim.World)
var switchArr []*state_proto.SwitchState
for _, u := range uidMap {
entry, ok := entity.GetEntityByUid(sim.World, u.Uid)
if !ok {
return nil, fmt.Errorf("道岔不存在: World id=%d,道岔id=%s", sim.World.Id(), u.Uid)
}
if !entry.HasComponent(component.TurnoutPositionType) {
return nil, fmt.Errorf("道岔没有TurnoutPosition组件: World id=%d,道岔id=%s", sim.World.Id(), u.Uid)
}
pos := component.TurnoutPositionType.Get(entry)
s := &state_proto.SwitchState{
Id: u.CommonId,
Normal: pos.Db,
Reverse: pos.Fb,
Dw: pos.Dw,
Fw: pos.Fw,
}
if entry.HasComponent(appcomponent.PointsParamType) {
s.Param = appcomponent.PointsParamType.Get(entry)
} else {
s.Param = &request_proto.PointsParam{}
}
// // 强制(联锁驱动无效)
// s.Force = entry.HasComponent(component.TurnoutFaultCiqdType)
// // 失表
// s.Sb = entry.HasComponent(component.TurnoutFaultSbType)
// // 定位失表
// s.Dwsb = entry.HasComponent(component.TurnoutFaultDwsbType)
// // 反位失表
// s.Fwsb = entry.HasComponent(component.TurnoutFaultFwsbType)
// jc := false
// zzj := component.TurnoutZzjType.Get(entry)
// for _, e := range zzj.ZzjList {
// if e.HasComponent(component.TurnoutFaultJcType) {
// jc = true
// break
// }
// }
// // 挤岔
// s.Jc = jc
if entry.HasComponent(component.Zdj9TwoElectronicType) {
elec := component.Zdj9TwoElectronicType.Get(entry)
dcj := component.BitStateType.Get(elec.TDC_DCJ)
s.Dc = dcj.Val
qdc, err := wd.QueryQdBit(component.UidType.Get(elec.TDC_DCJ).Id)
if err == nil {
s.Qdc = qdc
}
fcj := component.BitStateType.Get(elec.TDC_FCJ)
s.Fc = fcj.Val
qfc, err := wd.QueryQdBit(component.UidType.Get(elec.TDC_FCJ).Id)
if err == nil {
s.Qfc = qfc
}
ycj := component.BitStateType.Get(elec.TDC_YCJ)
s.Yc = ycj.Val
qyc, err := wd.QueryQdBit(component.UidType.Get(elec.TDC_YCJ).Id)
if err == nil {
s.Qyc = qyc
}
}
// 查看道岔是否被占用
turnout := sim.Repo.FindTurnout(u.Uid)
if turnout == nil {
return nil, fmt.Errorf("道岔不存在: World id=%d,道岔id=%s", sim.World.Id(), u.Uid)
}
if turnout.GetPhysicalSection() == nil {
return nil, fmt.Errorf("道岔关联的物理区段不存在: World id=%d,道岔id=%s", sim.World.Id(), u.Uid)
}
sectionState := handlerSectionState(sim.World, turnout.GetPhysicalSection().Id())
s.Occupied = sectionState.Occupied
switchArr = append(switchArr, s)
}
return switchArr, nil
}
// 收集站台状态
func collectPlatformStates(world ecs.World, mapId int32) ([]*state_proto.PlatformState, error) {
var states []*state_proto.PlatformState
mapData := memory.QueryGiData[*data_proto.RtssGraphicStorage](mapId)
uidsMap := memory.QueryUidStructure[*memory.StationUidStructure](mapId)
platformScreenDoorMap := wrapScreenDoorToPlatform(mapData)
for _, platform := range mapData.Platforms {
pid := memory.GetMapElementId(platform.Common)
stationCommonId := platform.RefStationId
if stationCommonId == 0 {
return nil, fmt.Errorf("站台没有绑定车站:id=%v", pid)
}
uidInfo := uidsMap.StationIds[stationCommonId]
if uidInfo == nil {
return nil, fmt.Errorf("车站实体不存在uid映射:id=%v", stationCommonId)
}
entry, ok := entity.GetEntityByUid(world, uidInfo.Uid)
if !ok {
return nil, fmt.Errorf("车站实体不存在: World id=%d, uid=%s", world.Id(), uidInfo.Uid)
}
sta := &state_proto.PlatformState{Id: pid}
isX := strings.Contains(platform.Code, "下行站台") //下行站台
if entry.HasComponent(component.EmpElectronicType) { // 紧急停车继电器
empElectronic := component.EmpElectronicType.Get(entry)
deviceElectronic := empElectronic.EMPJMap[platform.GetRefEsbRelayCode()]
if deviceElectronic != nil {
sta.Empj = getRelayXqVal(deviceElectronic.EMPJ)
}
}
if entry.HasComponent(component.SpkElectronicType) { // SPKS继电器
spkElectronic := component.SpkElectronicType.Get(entry)
if isX {
if spkElectronic.SPKSXPLAJ != nil {
sta.SpksState = append(sta.SpksState, &state_proto.ReplyState{Code: "SPKSX旁路", Xh: getRelayXqVal(spkElectronic.SPKSXPLAJ)})
}
if spkElectronic.SPKSX1J != nil {
sta.SpksState = append(sta.SpksState, &state_proto.ReplyState{Code: "SPKS1", Xh: getRelayXqVal(spkElectronic.SPKSX1J)})
}
if spkElectronic.SPKSX3J != nil {
sta.SpksState = append(sta.SpksState, &state_proto.ReplyState{Code: "SPKS3", Xh: getRelayXqVal(spkElectronic.SPKSX3J)})
}
} else {
if spkElectronic.SPKSSPLAJ != nil {
sta.SpksState = append(sta.SpksState, &state_proto.ReplyState{Code: "SPKSS旁路", Xh: getRelayXqVal(spkElectronic.SPKSSPLAJ)})
}
if spkElectronic.SPKSS2J != nil {
sta.SpksState = append(sta.SpksState, &state_proto.ReplyState{Code: "SPKS2", Xh: getRelayXqVal(spkElectronic.SPKSS2J)})
}
if spkElectronic.SPKSS4J != nil {
sta.SpksState = append(sta.SpksState, &state_proto.ReplyState{Code: "SPKS4", Xh: getRelayXqVal(spkElectronic.SPKSS4J)})
}
}
}
psdId := platformScreenDoorMap[pid]
if psdId != 0 {
psdUid, ok := uidsMap.PsdIds[psdId]
if !ok {
continue
}
psdEntry, ok := entity.GetEntityByUid(world, psdUid.Uid)
if !ok {
return nil, fmt.Errorf("屏蔽门实体不存在: World id=%d, uid=%s", world.Id(), psdUid.Uid)
}
if psdEntry.HasComponent(component.PlatformMkxCircuitType) {
mkxCircuit := component.PlatformMkxCircuitType.Get(psdEntry)
mkxj := &state_proto.MkxJState{Code: psdUid.Code}
if mkxCircuit.PABJ != nil {
mkxj.ReplyState = append(mkxj.ReplyState, &state_proto.ReplyState{Code: "站台确认继电器", Xh: getRelayXqVal(mkxCircuit.PABJ)})
}
if mkxCircuit.PCBJ != nil {
mkxj.ReplyState = append(mkxj.ReplyState, &state_proto.ReplyState{Code: "站台关门继电器", Xh: getRelayXqVal(mkxCircuit.PCBJ)})
}
if mkxCircuit.POBJ != nil {
mkxj.ReplyState = append(mkxj.ReplyState, &state_proto.ReplyState{Code: "站台开门继电器", Xh: getRelayXqVal(mkxCircuit.POBJ)})
}
sta.MkxJState = mkxj
}
}
states = append(states, sta)
}
return states, nil
}
// 将屏蔽门关联到站台
func wrapScreenDoorToPlatform(mapData *data_proto.RtssGraphicStorage) map[uint32]uint32 {
platformMap := make(map[uint32]uint32, len(mapData.Platforms))
for _, s := range mapData.ScreenDoors {
platformMap[s.RefPlatformId] = memory.GetMapElementId(s.Common)
}
return platformMap
}
// 获取继电器吸起状态
func getRelayXqVal(entry *ecs.Entry) bool {
relay := component.BitStateType.Get(entry)
return relay.Val
}