package memory import ( "encoding/binary" "encoding/hex" "fmt" "joylink.club/bj-rtsts-server/config" "joylink.club/bj-rtsts-server/const/balise_const" "joylink.club/bj-rtsts-server/dto/data_proto" "joylink.club/bj-rtsts-server/dto/request_proto" "joylink.club/bj-rtsts-server/dto/state_proto" "joylink.club/bj-rtsts-server/sys_error" "joylink.club/bj-rtsts-server/third_party/can_btm" "joylink.club/bj-rtsts-server/third_party/electrical_machinery" "joylink.club/bj-rtsts-server/third_party/message" train_pc_sim "joylink.club/bj-rtsts-server/third_party/train_pc_sim" "log/slog" "strings" "time" ) func (s *VerifySimulation) GetTrainPcSimConfig() []config.VehiclePCSimConfig { return s.runConfig.PcSimConfigs } // 列车控制 func ControlTrainUpdate(s *VerifySimulation, ct *request_proto.TrainControl) { allTrainMap := &s.Memory.Status.TrainStateMap data, ok := allTrainMap.Load(ct.TrainId) if !ok { panic(sys_error.New(fmt.Sprintf("列车【%s】不存在", ct.TrainId))) } tccGraphicData := findTrainTccGraphicData(s) if tccGraphicData == nil { slog.Error("列车控制未找到TCC图形数据") panic(sys_error.New("未找到TCC图形数据")) } sta := data.(*state_proto.TrainState) vobc := sta.VobcState tcc := sta.Tcc var tce []train_pc_sim.TrainControlEvent = nil if ct.ControlType == request_proto.TrainControl_EMERGENT_BUTTON { tce = trainControlEB(vobc, tcc, ct.Button, ct.DeviceId, tccGraphicData) } else if ct.ControlType == request_proto.TrainControl_DRIVER_KEY_SWITCH { tce = trainControlDriverKey(sta, ct.DriverKey, ct.DeviceId, tccGraphicData) //train_pc_sim.Default().SendDriverActive(sta) } else if ct.ControlType == request_proto.TrainControl_DIRECTION_KEY_SWITCH { tce = trainControlDirKey(sta.DynamicState.Speed, vobc, tcc, ct.DirKey, ct.DeviceId, tccGraphicData) //此处先注释,根据现场调试情况 2024-4-16 train_pc_sim.Default().SendTrainDirection(sta, sta.VobcState.DirectionForward, sta.VobcState.DirectionBackward) } else if ct.ControlType == request_proto.TrainControl_HANDLER { oldTraction := sta.VobcState.TractionForce oldBrakeForce := sta.VobcState.BrakeForce isTraction := ct.Handler.Val > 0 //是否制动 tce = trainControlHandle(vobc, tcc, ct.Handler, ct.DeviceId, tccGraphicData) train_pc_sim.Default().SendHandleSwitch(oldTraction, oldBrakeForce, isTraction, sta) } if !vobc.DirectionForward && !vobc.DirectionBackward { vobc.TractionStatus = false vobc.TractionForce = 0 } if vobc.EmergencyBrakingStatus { vobc.TractionForce = 0 } if sta.ConnState.Conn && (sta.ConnState.ConnType == state_proto.TrainConnState_PC_SIM_A || sta.ConnState.ConnType == state_proto.TrainConnState_PC_SIM_B) && tce != nil { train_pc_sim.Default().PublishTrainControlEvent(sta, tce) } } func trainControlEB(vobc *state_proto.TrainVobcState, tcc *state_proto.TrainControlState, request *request_proto.TrainControl_EmergentButton, deviceId uint32, tccGraphic *data_proto.TccGraphicStorage) []train_pc_sim.TrainControlEvent { if !request.Active { return nil } if tcc.Ebutton != nil && tcc.Ebutton.Passed { return nil } _, find := findTrainTccGraphicDataButton(tccGraphic, deviceId) if !find { slog.Error("未找到对应的紧急停车摁钮,deviceId:", deviceId) return nil } if tcc.Ebutton == nil { tcc.Ebutton = &state_proto.TrainControlState_EmergentButton{Id: deviceId} } tcc.Ebutton.Passed = request.Active vobc.EmergencyBrakingStatus = true vobc.TractionForce = 0 vobc.BrakeForce = DEFAULT_BRAKE_FORCE return []train_pc_sim.TrainControlEvent{{Command: message.OUTER_EMERGENCY_BRAKE, Status: 1}, {Command: message.TRAIN_BRAKE_STATE, Status: 1}} //紧急制动 //return []train_pc_sim.TrainControlEvent{{Command: message.CONFIRM, Status: 1}} //紧急制动 } // 列车方向 func trainControlDirKey(trainSpeed int32, vobc *state_proto.TrainVobcState, tcc *state_proto.TrainControlState, request *request_proto.TrainControl_DirectionKeySwitch, deviceId uint32, tccGraphic *data_proto.TccGraphicStorage) []train_pc_sim.TrainControlEvent { _, find := findTrainTccGraphicDataKey(tccGraphic, deviceId) if !find { slog.Error("未找到对应的列车方向键deviceId:", deviceId) panic(sys_error.New("未找到对应的列车方向键")) } if tcc.DirKey == nil { tcc.DirKey = &state_proto.TrainControlState_DirectionKeySwitch{Id: deviceId} } direction := request_proto.TrainControl_Direction(request.Val) if trainSpeed > 0 { panic(sys_error.New("列车未停稳时,不能变更方向")) } vobc.DirectionBackward = false vobc.DirectionForward = false if direction == request_proto.TrainControl_FORWARD { vobc.DirectionForward = true } else if direction == request_proto.TrainControl_BACKWARD { vobc.DirectionBackward = true } tcc.DirKey.Val = request.Val tce := make([]train_pc_sim.TrainControlEvent, 0) tce = append(tce, train_pc_sim.TrainControlEvent{Command: message.HANDLE_BACKWORD, Status: message.IsTrue(vobc.DirectionBackward)}) tce = append(tce, train_pc_sim.TrainControlEvent{Command: message.HANDLE_FORWORD, Status: message.IsTrue(vobc.DirectionForward)}) if vobc.DirectionForward { tce = append(tce, train_pc_sim.TrainControlEvent{Command: message.DIR_ZERO_FORWARD, Status: 1}) } else { tce = append(tce, train_pc_sim.TrainControlEvent{Command: message.DIR_ZERO_FORWARD, Status: 0}) } return tce } // 列车驾驶端激活 func trainControlDriverKey(train *state_proto.TrainState, request *request_proto.TrainControl_DriverKeySwitch, deviceId uint32, tccGraphic *data_proto.TccGraphicStorage) []train_pc_sim.TrainControlEvent { obj, find := findTrainTccGraphicDataKey(tccGraphic, deviceId) if !find { slog.Error("未找到对应的驾驶端激活设备deviceId:", deviceId) return nil } if train.DynamicState.Speed != 0 { panic(sys_error.New("因列车未停稳,不支持此操作")) } vobc := train.VobcState tcc := train.Tcc if obj.Code == SKQYS1 { vobc.Tc1Active = request.Val } else if obj.Code == SKQYS2 { vobc.Tc2Active = request.Val } if vobc.Tc1Active && vobc.Tc2Active { if obj.Code == SKQYS1 { vobc.Tc1Active = false } else if obj.Code == SKQYS2 { vobc.Tc2Active = false } panic(sys_error.New("驾驶端不能同时激活")) } var addNew = true for _, k := range tcc.DriverKey { if k.Id == deviceId { k.Id = deviceId k.Val = request.Val addNew = false break } } if addNew { tcc.DriverKey = append(tcc.DriverKey, &state_proto.TrainControlState_DriverKeySwitch{Id: deviceId, Val: request.Val}) } return []train_pc_sim.TrainControlEvent{{Command: message.KEY_STATE, Status: message.IsTrue(request.Val)}} } // 列车牵引控制 func trainControlHandle(vobc *state_proto.TrainVobcState, tcc *state_proto.TrainControlState, request *request_proto.TrainControl_PushHandler, deviceId uint32, tccGraphic *data_proto.TccGraphicStorage) []train_pc_sim.TrainControlEvent { _, find := findTrainTccGraphicDataHandler(tccGraphic, deviceId) if !find { slog.Error("未找到对应的牵引制动手柄设备deviceId:", deviceId) return nil } vobc.TractionStatus = false vobc.TractionForce = 0 vobc.BrakingStatus = false vobc.BrakeForce = 0 vobc.MaintainBrakeStatus = false tce := make([]train_pc_sim.TrainControlEvent, 0) tce = append(tce, train_pc_sim.TrainControlEvent{Command: message.HANDLE_TO_ZERO, Status: 0}) if request.Val > 0 { vobc.TractionStatus = true vobc.TractionForce = int64(request.Val * 180) tce = append(tce, train_pc_sim.TrainControlEvent{Command: message.TRAIN_BRAKE_STATE, Status: 0}) } else if request.Val < 0 { vobc.BrakingStatus = true vobc.BrakeForce = int64(-request.Val * 180) vobc.EmergencyBrakingStatus = false if tcc.Ebutton != nil { tcc.Ebutton.Passed = false } tce = append(tce, train_pc_sim.TrainControlEvent{Command: message.TRAIN_BRAKE_STATE, Status: 1}) tce = append(tce, train_pc_sim.TrainControlEvent{Command: message.OUTER_EMERGENCY_BRAKE, Status: 0}) } else { tce = append(tce, train_pc_sim.TrainControlEvent{Command: message.HANDLE_TO_ZERO, Status: 1}) } if tcc.PushHandler == nil { tcc.PushHandler = &state_proto.TrainControlState_PushHandler{Id: deviceId} } tcc.PushHandler.Val = request.Val return tce } /*func (s *VerifySimulation) GetConnTrain() *state_proto.TrainState { return s.findConnTrain(state_proto.TrainConnState_PC_SIM) }*/ func (s *VerifySimulation) GetConnTrain2() []*state_proto.TrainState { return s.findConnTrain2(state_proto.TrainConnState_PC_SIM_A, state_proto.TrainConnState_PC_SIM_B) } func (s *VerifySimulation) findConnTrain2(ct1, ct2 state_proto.TrainConnState_TrainConnType) []*state_proto.TrainState { var trains = make([]*state_proto.TrainState, 0) s.Memory.Status.TrainStateMap.Range(func(k, v any) bool { train := v.(*state_proto.TrainState) if train.Show { connState := train.ConnState if connState.ConnType == ct1 || connState.ConnType == ct2 { trains = append(trains, train) } } return true }) return trains } func (s *VerifySimulation) FindConnTrain(ct state_proto.TrainConnState_TrainConnType) *state_proto.TrainState { var findTrain *state_proto.TrainState s.Memory.Status.TrainStateMap.Range(func(k, v any) bool { train := v.(*state_proto.TrainState) connState := train.ConnState if connState.ConnType == ct { findTrain = train return false } return true }) return findTrain } // 4.4.1. 车载输出数字量信息报文内容 func (s *VerifySimulation) TrainPcSimDigitalOutInfoHandle(connType state_proto.TrainConnState_TrainConnType, data []byte) { slog.Info(fmt.Sprintf("处理车载输出数字量信息报文内容:%v", hex.EncodeToString(data))) train := s.FindConnTrain(connType) if train == nil { slog.Error("车载输出数字量,未找到连接车载pc仿真的列车") return } if !train.ConnState.Conn { slog.Error("车载输出数字量,,列车未连接车载pc仿真") return } vobc := train.VobcState trainPcSimDigitalOutInfoHandleCode39_32(data[4], vobc) trainPcSimDigitalOutInfoHandleCode31_24(connType, data[3], vobc) trainPcSimDigitalOutInfoHandleCode23_16(data[2], vobc) trainPcSimDigitalOutInfoHandleCode15_8(data[1], vobc) trainPcSimDigitalOutInfoHandleCode7_0(data[0], vobc) } func trainPcSimDigitalOutInfoHandleCode39_32(d byte, vobc *state_proto.TrainVobcState) { vobc.MostUseBrake = message.IsTrueForByte(message.GetBit(d, 0)) //? 常用制动 vobc.SplittingOut = message.IsTrueForByte(message.GetBit(d, 1)) //? 过分相输出 vobc.ModeRelay = message.IsTrueForByte(message.GetBit(d, 2)) //? 模式继电器 vobc.TractionEffective = message.IsTrueForByte(message.GetBit(d, 3)) //? 牵引有效 vobc.BrakeEffective = message.IsTrueForByte(message.GetBit(d, 4)) //? 制动有效 vobc.LifeDoorState = message.IsTrueForByte(message.GetBit(d, 5)) //?逃生门使能 vobc.BrakeQuarantine = message.IsTrueForByte(message.GetBit(d, 6)) //? 制动隔离 vobc.StopNotAllBrake = message.IsTrueForByte(message.GetBit(d, 7)) //? 停放制动缓解 } func trainPcSimDigitalOutInfoHandleCode31_24(connType state_proto.TrainConnState_TrainConnType, d byte, vobc *state_proto.TrainVobcState) { vobc.AtoOpenLeftDoor = message.IsTrueForByte(message.GetBit(d, 0)) //?//ATO开左门 vobc.AtoOpenRightDoor = message.IsTrueForByte(message.GetBit(d, 1)) //?//ATO开右门 vobc.AtoCloseLeftDoor = message.IsTrueForByte(message.GetBit(d, 2)) //?//ATO关左门 if connType == state_proto.TrainConnState_PC_SIM_A { vobc.Tc1Active = message.IsTrueForByte(message.GetBit(d, 3)) } else { vobc.Tc2Active = message.IsTrueForByte(message.GetBit(d, 3)) } //驾驶室激活 vobc.NoSpeedSigle = message.IsTrueForByte(message.GetBit(d, 4)) //?//零速信号 vobc.Fam = message.IsTrueForByte(message.GetBit(d, 5)) //FAM模式 vobc.Cam = message.IsTrueForByte(message.GetBit(d, 6)) //CAM模式 vobc.TrainStartedLed = message.IsTrueForByte(message.GetBit(d, 7)) //?//列车启动指示灯 } func trainPcSimDigitalOutInfoHandleCode23_16(d byte, vobc *state_proto.TrainVobcState) { vobc.DirectionForward = message.IsTrueForByte(message.GetBit(d, 0)) //列车方向1 vobc.DirectionBackward = message.IsTrueForByte(message.GetBit(d, 1)) //列车方向2 vobc.AtoLazyCommandOut = message.IsTrueForByte(message.GetBit(d, 2)) //?ATO惰行命令输出 vobc.SleepBtn = message.IsTrueForByte(message.GetBit(d, 3)) //?休眠指令 vobc.WakeUpBtn = message.IsTrueForByte(message.GetBit(d, 4)) //?唤醒指令 vobc.AtoSendTrainBtn = message.IsTrueForByte(message.GetBit(d, 5)) //?ATO发车指示灯 vobc.TurnbackStatus = message.IsTrueForByte(message.GetBit(d, 6)) //?AR灯命令 vobc.AtoAlwaysBrake = message.IsTrueForByte(message.GetBit(d, 7)) //? ATO保持制动 } func trainPcSimDigitalOutInfoHandleCode15_8(d byte, vobc *state_proto.TrainVobcState) { vobc.LocalAtpControl = message.IsTrueForByte(message.GetBit(d, 0)) //?本端ATP控车 vobc.Ato = message.IsTrueForByte(message.GetBit(d, 1)) //ATO模式 vobc.AtoTractionCommandOut = message.IsTrueForByte(message.GetBit(d, 2)) //?ATO牵引命令输出 vobc.AtoTractionCommand1 = message.IsTrueForByte(message.GetBit(d, 3)) //?ATO牵引指令1 vobc.AtoTractionCommand2 = message.IsTrueForByte(message.GetBit(d, 4)) //?ATO牵引指令2 vobc.AtoTractionCommand3 = message.IsTrueForByte(message.GetBit(d, 5)) //?ATO牵引指令3 vobc.AtoBrakeCommand = message.IsTrueForByte(message.GetBit(d, 6)) //?ATO制动命令输出 vobc.JumpStatus = message.IsTrueForByte(message.GetBit(d, 7)) //跳跃指令 } func trainPcSimDigitalOutInfoHandleCode7_0(d byte, vobc *state_proto.TrainVobcState) { vobc.TractionSafetyCircuit = message.AtpLowPowerByte(message.GetBit(d, 0)) //切牵引 vobc.TrainDoorOutLed = message.IsTrueForByte(message.GetBit(d, 1)) //? 车门外指示灯 vobc.ParkingBrakeStatus = message.IsTrueForByte(message.GetBit(d, 2)) //停放制动施加 vobc.EmergencyBrakingStatus = message.AtpLowPowerByte(message.GetBit(d, 3)) //紧急制动 vobc.LeftDoorOpenCommand = message.IsTrueForByte(message.GetBit(d, 4)) //开左门允许 vobc.RightDoorOpenCommand = message.IsTrueForByte(message.GetBit(d, 5)) //开右门允许 vobc.RightDoorCloseCommand = message.IsTrueForByte(message.GetBit(d, 6)) //关右门 vobc.AllDoorClose = message.IsTrueForByte(message.GetBit(d, 7)) //车门保持关闭 } // 4.4.2. 车载输出数字反馈量信息报文内容 func (s *VerifySimulation) TrainPcSimDigitalReportHandle(connType state_proto.TrainConnState_TrainConnType, data []byte) { slog.Info(fmt.Sprintf("车载输出数字量反馈信息", hex.EncodeToString(data))) train := s.FindConnTrain(connType) if train == nil { slog.Error("车载输出数字反馈量信息,未找到连接车载pc仿真的列车") return } if !train.ConnState.Conn { slog.Error("车载输出数字反馈量信息,列车未连接车载pc仿真") return } vobc := train.VobcState //buf := bytes.NewBuffer(data) //localEndAct, _ := buf.ReadByte() //direction1, _ := buf.ReadByte() //direction2, _ := buf.ReadByte() //vobc.Tc1Active = message.IsTrueForByte(localEndAct) //本端驾驶室激活(钥匙) //vobc.DirectionForward = message.IsTrueForByte(direction1) //方向手柄进位 //vobc.DirectionBackward = message.IsTrueForByte(direction2) //方向手柄退位 buf := data[0] vobc.Tc1Active = message.IsTrueForByte(message.GetBit(buf, 0)) //本端驾驶室激活(钥匙) vobc.DirectionForward = message.IsTrueForByte(message.GetBit(buf, 1)) //方向手柄进位 vobc.DirectionBackward = message.IsTrueForByte(message.GetBit(buf, 2)) //方向手柄退位 } // 创建/删除列车 func TrainPcSimConnOrRemoveHandle(train *state_proto.TrainState, create bool) error { connState := train.ConnState if connState.ConnType == state_proto.TrainConnState_PC_SIM_A || connState.ConnType == state_proto.TrainConnState_PC_SIM_B { crErr := train_pc_sim.Default().CreateOrRemoveTrain(train, create) if crErr != nil { return crErr } train_pc_sim.Default().CreateOrRemoveSpeedPLace(train) } else if connState.ConnType == state_proto.TrainConnState_VOBC { electrical_machinery.Default().ClearOrRemoveTrain(train) } return nil } // 门模式 /*func TrainDoorModeHandle(train *state_proto.TrainState) { if !train.ConnState.Conn { slog.Error("车载pc仿真门模式,列车未连接车载pc仿真") return } switch state { case 0x00: //0x00表示自开自关(AA) train.VobcState.DoorModeAA = true case 0x01: //0x01表示自开人关(AM) train.VobcState.DoorModeAM = true case 0x02: //0x02表示人开人关(MM) train.VobcState.DoorModeMM = true } }*/ // 4.4.3. 车载输出模拟量信息报文内容(0x03) func (s *VerifySimulation) TrainPcSimMockInfo(connType state_proto.TrainConnState_TrainConnType, data []byte) { train := s.FindConnTrain(connType) if train == nil { slog.Error("车载输出模拟量,未找到连接车载pc仿真的列车") return } if !train.ConnState.Conn { slog.Error("车载输出模拟量,列车未连接车载pc仿真") return } mockData := binary.BigEndian.Uint16(data) train.VobcState.MockInfo = uint32(mockData) } // 4.4.4. 车载输出BTM查询同步帧报文内容(0x04) func (s *VerifySimulation) TrainBtmQuery(connType state_proto.TrainConnState_TrainConnType, data []byte) { slog.Info(fmt.Sprintf("收到车载输出BTM查询同步帧报文内容:%v", hex.EncodeToString(data))) if len(data) < 12 { slog.Error("列车btm查询报文长度错误:", len(data)) return } train := s.FindConnTrain(connType) if train == nil { slog.Error("车载输出btm查询,未找到连接车载pc仿真的列车") return } if !train.ConnState.Conn { slog.Error("车载输出btm查询,列车未连接车载pc仿真") return } trainAtm := message.NewCanetFrame2(data, true) atpReq := &message.AtpRequestFrame{IsTrainPcSim: true} if !atpReq.Decode(trainAtm) { slog.Warn("列车pc驾驶模拟-CanetFrame解码成AtpRequestFrame失败", "CanetFrame", trainAtm.String()) return } cl := clock(atpReq) btmRepFrame := createBtmStatus(trainAtm.CanId.ID4, train.BtmState, atpReq, cl) if atpReq.ResendRequest == 2 { //重新发送 if len(train.BtmState.BaliseTelegramForPcSimResend) > 0 { dd, _ := hex.DecodeString(train.BtmState.BaliseTelegramForPcSimResend) train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_HAS_DATA, dd) } } else { timeSyncF := message.NewBtmTimeSyncCheckFrame(trainAtm.CanId.ID4, true) timeSyncF.T2 = cl.BtmTk timeSyncF.T3 = cl.TkNow() telCount := strings.Count(train.BtmState.Telegram, "00") if telCount >= balise_const.UserTelegramByteLen { //无数据 queryDataStr := make([]string, 0) queryDataStr = append(queryDataStr, hex.EncodeToString(btmRepFrame.Encode().Encode2())) queryDataStr = append(queryDataStr, hex.EncodeToString(timeSyncF.Encode().Encode2())) train_pc_sim.Default().SendBaliseData2(train, message.RECIVE_TRAIN_BTM_NOT_DATA, queryDataStr) /* queryData := make([]byte, 0) queryData = append(queryData, btmRepFrame.Encode().Encode()...) queryData = append(queryData, timeSyncF.Encode().Encode()...) train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_NOT_DATA, queryData)*/ } else { //有数据 aliseData, _ := hex.DecodeString(train.BtmState.Telegram) statusDataCf, statusDataCfOk := message.CreateBtmRspFramesData(btmRepFrame, aliseData, false, cl.TkNow(), cl.TkNow(), cl.TkNow(), true) if statusDataCfOk { queryData := make([]byte, 0) queryData = append(queryData, btmRepFrame.Encode().Encode2()...) queryData = append(queryData, timeSyncF.Encode().Encode2()...) queryData = append(queryData, statusDataCf...) //数据帧包含结束帧 train.BtmState.BaliseTelegramForPcSimResend = fmt.Sprintf("%X", statusDataCf) train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_HAS_DATA, queryData) } else { slog.Error("列车pc仿真 BtmCanetClient应答帧、数据帧编码失败") } } } } func createBtmStatus(canIdSn byte, btmState *state_proto.BTMState, atpReq *message.AtpRequestFrame, cl can_btm.BtmClock) *message.BtmStatusRspFrame { statusF := message.NewBtmStatusRspFrame(canIdSn, atpReq.IsTrainPcSim) //btmStatus := aa(train, atpReq) statusF.PowerAmplifierOn = true statusF.PowerAmplifierFailure = false statusF.AtpReqCrcCheckWrong = !atpReq.Crc16CheckOk statusF.AntennaFault = false statusF.BaliseCounter = byte(btmState.BaliseCount) statusF.MessageCounter = byte(btmState.MessageCounter) statusF.TkTimeA = cl.TkNow() statusF.DetailedCode = 0 if btmState.AboveBalise { statusF.DetailedCode = 0x07 } dsn := byte(btmState.DataSerialNumber) + 1 btmState.DataSerialNumber = uint32(dsn) statusF.Dsn = dsn return statusF } func clock(atpReq *message.AtpRequestFrame) can_btm.BtmClock { now := time.Now() return can_btm.BtmClock{BtmTk: atpReq.Time, SysTk: now} } func (s *VerifySimulation) ObtainTrainDigitalMockData(train *state_proto.TrainState) []message.TrainPcSimBaseMessage { msgArr := make([]message.TrainPcSimBaseMessage, 0) vs := train.VobcState tcc := train.Tcc if vs.Tc1Active || vs.Tc2Active { msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.KEY_STATE, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //钥匙激活 } if vs.BrakingStatus { msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.TRAIN_BRAKE_STATE, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //列车制动状态 } if vs.EmergencyBrakingStatus { msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.OUTER_EMERGENCY_BRAKE, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //紧急制动 } dir := request_proto.TrainControl_Direction(tcc.DirKey.Val) if dir == request_proto.TrainControl_FORWARD { msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.DIR_ZERO_FORWARD, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //手柄零位方向向前 msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.HANDLE_FORWORD, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //方向手柄向前控制 msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.HANDLE_BACKWORD, 0}, Type: message.SENDER_TRAIN_OUTR_INFO}) //方向手柄向前控制 } else if dir == request_proto.TrainControl_BACKWARD { msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.HANDLE_FORWORD, 0}, Type: message.SENDER_TRAIN_OUTR_INFO}) //方向手柄向前控制 msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.DIR_ZERO_FORWARD, 0}, Type: message.SENDER_TRAIN_OUTR_INFO}) //手柄零位方向向前 msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.HANDLE_BACKWORD, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //方向手柄向前控制 } msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.CLOSE_RIGHT_DOOR, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //关右门按钮 msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.CLOSE_LEFT_DOOR, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //关左门按钮 msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.TRAIN_INTEGRITY, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //列车完整性 msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.DOOR_LOCK_STATE, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //车门锁闭状态 msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.OBSTACLE_CHECK, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //障碍物检测按钮 msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.BRAKE_HEAVY_FAULT, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //制动重故障 msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.EMERGENT_HANDLE_DOWN, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //紧急手柄拉下 msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.LIFE_DOOR, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //逃生门状态 msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.ATP_CUT, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //atp切除 msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{39, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //非制动 //msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{40, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //本端机械钩 //msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{41, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //对端机械钩 msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{}, Type: message.RECIVE_TRAIN_BTN_CLEAR_ALL_PRE_DATA}) //清空应答器 train.BtmState = nil return msgArr }