package message_server import ( "fmt" "log/slog" "time" "google.golang.org/protobuf/proto" "joylink.club/bj-rtsts-server/message_server/ms_api" "joylink.club/bj-rtsts-server/ts/protos/graphicData" "joylink.club/bj-rtsts-server/ts/protos/state" "joylink.club/bj-rtsts-server/ts/simulation/wayside/memory" "joylink.club/ecs" "joylink.club/rtsssimulation/component" "joylink.club/rtsssimulation/entity" ) // 综合后备盘IBP消息服务 type IbpMs struct { vs *memory.VerifySimulation mapId int32 } func NewIBPMs(vs *memory.VerifySimulation, mapId int32) *IbpMs { return &IbpMs{vs: vs, mapId: mapId} } func (ms *IbpMs) GetChannel() string { return SimulationIbpTopic // return "simulation-ibp-%s_%d_%s-status" } func (ms *IbpMs) GetInterval() time.Duration { return 200 * time.Millisecond } func (ms *IbpMs) OnTick() ([]*ms_api.TopicMsg, error) { var msgArr []*ms_api.TopicMsg mapData := memory.QueryGiData[*graphicData.RtssGraphicStorage](ms.mapId) for _, station := range mapData.Stations { channel := ms.handlerIBPChannelName(station.Common.Id) stationIbpState, err := ms.collectStationIbpState(station) if err != nil { return nil, err } b, err := proto.Marshal(stationIbpState) if err != nil { return nil, fmt.Errorf("IBP设备状态消息服务数据序列化失败: %s", err) } msgArr = append(msgArr, ms_api.NewTopicMsg(channel, b)) } return msgArr, nil } // 当发生错误时执行的逻辑 func (ms *IbpMs) OnError(err error) { } func (ms *IbpMs) collectStationIbpState(station *graphicData.Station) (*state.PushedDevicesStatus, error) { if station.RefIbpMapCode == "" { return nil, nil } stationUid := memory.QueryUidByMidAndComId(ms.mapId, station.Common.Id, &graphicData.Station{}) ibpMapId, ibpStorage := memory.GetStorageIBPMapData(station.RefIbpMapCode) ibpUidsMap := memory.QueryUidStructure[*memory.IBPUidStructure](ibpMapId) buttonStates, err := ms.collectIBPButtonState(stationUid, ibpUidsMap, ibpStorage.IbpButtons) if err != nil { return nil, err } alarmStates, err := ms.collectIBPAlarmState(stationUid, ibpUidsMap, ibpStorage.IbpAlarms) if err != nil { return nil, err } lightStates, err := ms.collectIBPLightState(stationUid, ibpUidsMap, ibpStorage.IbpLights) if err != nil { return nil, err } keyStates, err := ms.collectIBPKeyState(stationUid, ibpUidsMap, ibpStorage.IbpKeys) if err != nil { return nil, err } return &state.PushedDevicesStatus{ All: true, AllStatus: &state.AllDevicesStatus{ ButtonState: buttonStates, AlarmState: alarmStates, LightState: lightStates, KeyState: keyStates, }, }, nil } // 收集IBP按钮状态 func (ms *IbpMs) collectIBPButtonState(stationUid string, uidsMap *memory.IBPUidStructure, ibpButtons []*graphicData.IBPButton) ([]*state.ButtonState, error) { var states []*state.ButtonState for _, data := range ibpButtons { // 按钮 uid := stationUid + "_" + uidsMap.IbpButtonIds[data.Common.Id].Uid entry, ok := entity.GetEntityByUid(ms.vs.World, uid) if !ok { slog.Warn("ibp按钮实体不存在: World id=%d, uid=%s", ms.vs.World.Id(), uid) continue } if entry.HasComponent(component.ButtonTag) { states = append(states, getIBPButtonState(data.Common.Id, entry)) } } return states, nil } // 获取IBP盘按钮状态 func getIBPButtonState(id string, entry *ecs.Entry) *state.ButtonState { status := &state.ButtonState{Id: id} bit := component.BitStateType.Get(entry) status.Down = bit.Val // 如果按钮包含灯 if entry.HasComponent(component.SingleLightType) { lightComponent := component.SingleLightType.Get(entry) status.Active = component.BitStateType.Get(lightComponent.Light).Val } return status } // 收集报警器状态 func (ms *IbpMs) collectIBPAlarmState(stationUid string, uidsMap *memory.IBPUidStructure, ibpAlarms []*graphicData.IbpAlarm) ([]*state.AlarmState, error) { var states []*state.AlarmState for _, data := range ibpAlarms { // 报警器 uid := stationUid + "_" + uidsMap.IbpAlarmIds[data.Common.Id].Uid entry, ok := entity.GetEntityByUid(ms.vs.World, uid) if !ok { slog.Warn("ibp报警器实体不存在: World id=%d, uid=%s", ms.vs.World.Id(), uid) continue } if entry.HasComponent(component.AlarmTag) { states = append(states, &state.AlarmState{Id: data.Common.Id, Active: component.BitStateType.Get(entry).Val}) } } return states, nil } // 收集灯状态信息 func (ms *IbpMs) collectIBPLightState(stationUid string, uidsMap *memory.IBPUidStructure, ibpLights []*graphicData.IbpLight) ([]*state.LightState, error) { var states []*state.LightState for _, data := range ibpLights { // 指示灯 uid := stationUid + "_" + uidsMap.IbpLightIds[data.Common.Id].Uid entry, ok := entity.GetEntityByUid(ms.vs.World, uid) if !ok { slog.Warn("ibp指示灯实体不存在: World id=%d, uid=%s", ms.vs.World.Id(), uid) continue } if entry.HasComponent(component.LightTag) { states = append(states, &state.LightState{Id: data.Common.Id, Active: component.BitStateType.Get(entry).Val}) } } return states, nil } // 收集钥匙状态 func (ms *IbpMs) collectIBPKeyState(stationUid string, uidsMap *memory.IBPUidStructure, ibpKeys []*graphicData.IbpKey) ([]*state.KeyState, error) { var states []*state.KeyState for _, data := range ibpKeys { // 钥匙 uid := stationUid + "_" + uidsMap.IbpKeyIds[data.Common.Id].Uid entry, ok := entity.GetEntityByUid(ms.vs.World, uid) if !ok { slog.Warn("ibp钥匙实体不存在: World id=%d, uid=%s", ms.vs.World.Id(), uid) continue } if entry.HasComponent(component.KeyTag) { states = append(states, &state.KeyState{Id: data.Common.Id, Gear: component.GearStateType.Get(entry).Val}) } } return states, nil } // 处理订阅通道名称 func (ms *IbpMs) handlerIBPChannelName(stationId string) string { return fmt.Sprintf(SimulationIbpTopic, ms.vs.SimulationId, ms.mapId, stationId) }