package memory import ( "encoding/binary" "encoding/hex" "fmt" "joylink.club/bj-rtsts-server/config" "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" "joylink.club/bj-rtsts-server/third_party/tcp" train_pc_sim "joylink.club/bj-rtsts-server/third_party/train_pc_sim" "log/slog" "math" "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 if ct.ControlType != request_proto.TrainControl_DRIVER_KEY_SWITCH && vobc.Tc1Active == false && vobc.Tc2Active == false { panic(sys_error.New("请先上驾驶端钥匙")) } var baseMsg []message.TrainPcSimBaseMessage = nil if ct.ControlType == request_proto.TrainControl_EMERGENT_BUTTON { baseMsg = trainControlButton(sta, ct.DeviceId, ct.ControlButton.Active, tccGraphicData) } else if ct.ControlType == request_proto.TrainControl_DRIVER_KEY_SWITCH { baseMsg = trainControlDriverKey(sta, ct.DriverKey, ct.DeviceId, tccGraphicData) //train_pc_sim.Default().SendDriverActive(sta) } else if ct.ControlType == request_proto.TrainControl_DIRECTION_KEY_SWITCH { baseMsg = trainControlDirKey(sta.DynamicState.Speed, vobc, tcc, ct.SwitchKey, 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 { if !vobc.Tc1Active && !vobc.Tc2Active { panic(sys_error.New("TC1和TC2都未激活不能搬动牵引制动手柄 ")) } if vobc.TractionSafetyCircuit { panic(sys_error.New("牵引切除,不能进行列车控制")) } //oldTraction := sta.VobcState.TractionForce //oldBrakeForce := sta.VobcState.BrakeForce //isTraction := ct.Handler.Val > 0 //是否制动 baseMsg = trainControlHandle(sta, ct.Handler, ct.DeviceId, tccGraphicData) //train_pc_sim.Default().SendHandleSwitch(oldTraction, oldBrakeForce, isTraction, sta) } else if ct.ControlType == request_proto.TrainControl_TRAIN_DOOR_MODE_CHANGE { baseMsg = trainDoorModeChangeHandle(vobc, tcc, ct.SwitchKey, ct.DeviceId, tccGraphicData) } if vobc.DirectionForward && vobc.TractionForce == 0 { baseMsg = append(baseMsg, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.DIR_ZERO_FORWARD, 1}}) } else { baseMsg = append(baseMsg, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.DIR_ZERO_FORWARD, 0}}) } 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) && baseMsg != nil { train_pc_sim.Default().SendTrainControlMsg2(sta, baseMsg, sta.TrainPort) if vobc.Tc1Active == false && vobc.Tc2Active == false { sta.TrainPort = state_proto.TrainState_PORT_NONE } } } func trainControlButton(train *state_proto.TrainState, deviceId uint32, active bool, tccGraphic *data_proto.TccGraphicStorage) []message.TrainPcSimBaseMessage { if graphicBtn, ok := findTrainTccGraphicDataButton(tccGraphic, deviceId); ok { btn := train.Tcc.Buttons[graphicBtn.Code] if btn == nil { slog.Error("未找到对应的车载摁钮code:", graphicBtn.Code, "设备id:", deviceId) return nil } vobc := train.VobcState switch graphicBtn.Code { case JJZD: // 紧急制动 return controlEBBtn(train, active, btn) case ATPQCKG: //atp切除 return controlAtpBtn(vobc, active, btn) case KZM, KYM: //开左门按钮 return controlDoorOpenBtn(vobc, active, btn, graphicBtn.Code == KZM, true) case GZM, GYM: //关左门按钮 return controlDoorCloseBtn(vobc, active, btn, graphicBtn.Code == GZM, true) case ZF: //折返按钮 return controlReverseBtn(vobc, active, btn) case QZMYX: //强制门允许 return controlDoorAllowBtn(vobc, active, btn) case MSJJ: //模式降级按钮 return controlModeDownBtn(vobc, active, btn) case MSSJ: //模式升级按钮 return controlModeUpBtn(vobc, active, btn) case MSQR: //模式确认按钮 return controlModeConfirmBtn(vobc, active, btn) case ZAWTGJC: //障碍物/脱轨检测 return controlObstacleDetectionBtn(vobc, active, btn) case ZDZGZ: //制动重故障 return controlBrakeHeavyBtn(vobc, active, btn) case ATPSD: //ATP上电按钮 return controlAtpPowerBtn(vobc, active, btn) case HX: //唤醒按钮 return controlWakeUpBtn(vobc, active, btn) case JX: //检修按钮 return controlOverhaulBtn(vobc, active, btn) case XM: //休眠按钮 return controlSleepBtn(vobc, active, btn) case ATOQD: return controlAtoSenderBtn(vobc, active, btn) default: return nil } } else { return nil } } // 应急摁钮 func controlEBBtn(train *state_proto.TrainState, active bool, tccBtn *state_proto.TrainControlState_ControlButton) []message.TrainPcSimBaseMessage { if !active { return nil } tccBtn.Passed = active vobc := train.VobcState vobc.TractionStatus = false vobc.EmergencyBrakingStatus = true vobc.TractionForce = 0 vobc.BrakeForce = trainBraking(train.TrainLoad, 100, train.TrainEmergencyBrake) / 1000 * 100 vobc.BrakingStatus = true return []message.TrainPcSimBaseMessage{ {Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.OUTER_EMERGENCY_BRAKE, 0}}, {Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.TRAIN_BRAKE_STATE, 1}}} } // atp 切除 func controlAtpBtn(vobc *state_proto.TrainVobcState, active bool, tccBtn *state_proto.TrainControlState_ControlButton) []message.TrainPcSimBaseMessage { var status byte = 0 if active { status = 1 } vobc.AtpCutSwitch = active tccBtn.Passed = active return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.ATP_CUT, status}}} } func controlDoorCloseBtn(vobc *state_proto.TrainVobcState, active bool, tccBtn *state_proto.TrainControlState_ControlButton, isLeft bool, onbtn bool) []message.TrainPcSimBaseMessage { status := message.IsTrue(active) if onbtn { tccBtn.Passed = active } var doorAct byte = message.CLOSE_LEFT_DOOR var doorState byte = message.LEFT_DOOR_STATE msg := make([]message.TrainPcSimBaseMessage, 0) if isLeft { vobc.LeftDoorCloseCommand = active } else { vobc.RightDoorCloseCommand = active doorAct = message.CLOSE_RIGHT_DOOR doorState = message.RIGHT_DOOR_STATE } msg = append(msg, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{doorAct, status}}) if vobc.LeftDoorCloseCommand && vobc.RightDoorCloseCommand { msg = append(msg, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.DOOR_LOCK_STATE, 1}}) } msg = append(msg, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{doorState, 0}}) //msg = append(msg, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{doorAct, 0}}) return msg } // 开车门 func controlDoorOpenBtn(vobc *state_proto.TrainVobcState, active bool, tccBtn *state_proto.TrainControlState_ControlButton, isLeft bool, onbtn bool) []message.TrainPcSimBaseMessage { status := message.IsTrue(active) msg := make([]message.TrainPcSimBaseMessage, 0) if onbtn { tccBtn.Passed = active } var doorAct byte = message.LEFT_OPEN_DOOR var doorState byte = message.LEFT_DOOR_STATE if isLeft { vobc.LeftDoorOpenCommand = active //vobc.LeftDoorCloseCommand = false } else { vobc.RightDoorOpenCommand = active //vobc.RightDoorCloseCommand = false doorAct = message.OPEN_RIGHT_DOOR doorState = message.RIGHT_DOOR_STATE } msg = append(msg, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{doorAct, status}}) if active { msg = append(msg, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.DOOR_LOCK_STATE, 0}}) msg = append(msg, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{doorState, status}}) } return msg } // 折返 func controlReverseBtn(vobc *state_proto.TrainVobcState, active bool, tccBtn *state_proto.TrainControlState_ControlButton) []message.TrainPcSimBaseMessage { var status byte = 0 if active { status = 1 } //vobc.RightDoorCloseCommand = active vobc.TurnbackStatus = active tccBtn.Passed = active return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.TURN_BACK, status}}} } // 强制门允许 func controlDoorAllowBtn(vobc *state_proto.TrainVobcState, active bool, tccBtn *state_proto.TrainControlState_ControlButton) []message.TrainPcSimBaseMessage { var status byte = 0 if active { status = 1 } tccBtn.Passed = active vobc.ForceDoorAllow = active return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.FORCE_DOOR_ALLOW, status}}} } // 模式降级按钮 func controlModeDownBtn(vobc *state_proto.TrainVobcState, active bool, tccBtn *state_proto.TrainControlState_ControlButton) []message.TrainPcSimBaseMessage { var status byte = 0 if active { status = 1 } tccBtn.Passed = active vobc.ModeLevelDownBtn = active return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.TRAIN_MODE_DOWN, status}}} } // 模式升级按钮 func controlModeUpBtn(vobc *state_proto.TrainVobcState, active bool, tccBtn *state_proto.TrainControlState_ControlButton) []message.TrainPcSimBaseMessage { var status byte = 0 if active { status = 1 } tccBtn.Passed = active vobc.ModeLevelUpBtn = active return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.TRAIN_MODE_UP, status}}} } // 模式确认按钮 func controlModeConfirmBtn(vobc *state_proto.TrainVobcState, active bool, tccBtn *state_proto.TrainControlState_ControlButton) []message.TrainPcSimBaseMessage { var status byte = 0 if active { status = 1 } tccBtn.Passed = active vobc.ConfirmBtn = active return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.CONFIRM, status}}} } // 障碍物/脱轨检测 func controlObstacleDetectionBtn(vobc *state_proto.TrainVobcState, active bool, tccBtn *state_proto.TrainControlState_ControlButton) []message.TrainPcSimBaseMessage { var status byte = 0 if active { status = 1 } tccBtn.Passed = active vobc.ObstacleCheckBtn = active return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.OBSTACLE_CHECK, status}}} } // 制动重故障 func controlBrakeHeavyBtn(vobc *state_proto.TrainVobcState, active bool, tccBtn *state_proto.TrainControlState_ControlButton) []message.TrainPcSimBaseMessage { var status byte = 0 if active { status = 1 } tccBtn.Passed = active vobc.BrakeHeavyFault = active return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.BRAKE_HEAVY_FAULT, status}}} } // ATP上电按钮 func controlAtpPowerBtn(vobc *state_proto.TrainVobcState, active bool, tccBtn *state_proto.TrainControlState_ControlButton) []message.TrainPcSimBaseMessage { var status byte = 0 if active { status = 1 } tccBtn.Passed = active vobc.AtpPowerOnBtn = active return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.ATP_POWER_ON, status}}} } // 唤醒按钮 func controlWakeUpBtn(vobc *state_proto.TrainVobcState, active bool, tccBtn *state_proto.TrainControlState_ControlButton) []message.TrainPcSimBaseMessage { var status byte = 0 if active { status = 1 } tccBtn.Passed = active vobc.WakeUpBtn = active return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.WAKE_UP, status}}} } // 检修按钮 func controlOverhaulBtn(vobc *state_proto.TrainVobcState, active bool, tccBtn *state_proto.TrainControlState_ControlButton) []message.TrainPcSimBaseMessage { var status byte = 0 if active { status = 1 } tccBtn.Passed = active vobc.OverhaulBtn = active return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.OVERHAUL, status}}} } // 休眠按钮 func controlSleepBtn(vobc *state_proto.TrainVobcState, active bool, tccBtn *state_proto.TrainControlState_ControlButton) []message.TrainPcSimBaseMessage { var status byte = 0 if active { status = 1 } tccBtn.Passed = active vobc.SleepBtn = active return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.SLEEP, status}}} } func controlAtoSenderBtn(vobc *state_proto.TrainVobcState, active bool, tccBtn *state_proto.TrainControlState_ControlButton) []message.TrainPcSimBaseMessage { var status byte = 0 if active { status = 1 } tccBtn.Passed = active vobc.AtoSendTrainBtn = active return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.ATO_SEND_TRAIN, status}}} } // 列车方向 func trainControlDirKey(trainSpeed int32, vobc *state_proto.TrainVobcState, tcc *state_proto.TrainControlState, request *request_proto.TrainControl_SwitchKeyChange, deviceId uint32, tccGraphic *data_proto.TccGraphicStorage) []message.TrainPcSimBaseMessage { dirKey, find := findTrainTccGraphicDataKey(tccGraphic, deviceId) if !find { slog.Error("未找到对应的列车方向键deviceId:", deviceId) panic(sys_error.New("未找到对应的列车方向键")) } direction := request_proto.TrainControl_KeyLocation(request.Val) if trainSpeed > 0 { panic(sys_error.New("列车未停稳时,不能变更方向")) } vobc.DirectionBackward = false vobc.DirectionForward = false if direction == request_proto.TrainControl_KL_FONT { vobc.DirectionForward = true } else if direction == request_proto.TrainControl_KL_END { vobc.DirectionBackward = true } tcc.SwitchKeyMap[dirKey.Code].Val = request.Val return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.HANDLE_BACKWORD, message.IsTrue(vobc.DirectionBackward)}}, {Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.HANDLE_FORWORD, message.IsTrue(vobc.DirectionForward)}}} } // 列车驾驶端激活 func trainControlDriverKey(train *state_proto.TrainState, request *request_proto.TrainControl_DriverKeySwitch, deviceId uint32, tccGraphic *data_proto.TccGraphicStorage) []message.TrainPcSimBaseMessage { 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 train.TrainPort = state_proto.TrainState_PORT_A train.BtmBaliseCacheA = &state_proto.TrainBtmCache{BaliseList: make([]*state_proto.BTMState, 3)} } else if obj.Code == SKQYS2 { vobc.Tc2Active = request.Val train.TrainPort = state_proto.TrainState_PORT_B train.BtmBaliseCacheB = &state_proto.TrainBtmCache{BaliseList: make([]*state_proto.BTMState, 3)} } if vobc.Tc1Active && vobc.Tc2Active { if obj.Code == SKQYS1 { vobc.Tc1Active = false } else if obj.Code == SKQYS2 { vobc.Tc2Active = false } panic(sys_error.New("驾驶端不能同时激活")) } for _, k := range tcc.DriverKey { if k.Id == deviceId { k.Id = deviceId k.Val = request.Val break } } tce := make([]message.TrainPcSimBaseMessage, 0) tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.KEY_STATE, message.IsTrue(request.Val)}}) train.OldLink = "" train.OldLinkOffset = 0 train.OldTailLink = "" train.OldTailLinkOffset = 0 if request.Val { tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_TC_ACTIVE}) } else { tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_TC_NOT_ACTIVE}) } return tce } func trainDoorModeChangeHandle(vobc *state_proto.TrainVobcState, tcc *state_proto.TrainControlState, request *request_proto.TrainControl_SwitchKeyChange, deviceId uint32, tccGraphic *data_proto.TccGraphicStorage) []message.TrainPcSimBaseMessage { sk, find := findTrainTccGraphicDataKey(tccGraphic, deviceId) if !find { slog.Error("未找到对应的牵引制动手柄设备deviceId:", deviceId) return nil } msg := make([]message.TrainPcSimBaseMessage, 0) kl := request_proto.TrainControl_KeyLocation(request.Val) msg = append(msg, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.DOOR_MODE_AA, 0}}) msg = append(msg, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.DOOR_MODE_AM, 0}}) msg = append(msg, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.DOOR_MODE_MM, 0}}) switch kl { case request_proto.TrainControl_KL_END: vobc.DoorModeMM = true msg = append(msg, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.DOOR_MODE_MM, 1}}) case request_proto.TrainControl_KL_CENTER: vobc.DoorModeAM = true msg = append(msg, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.DOOR_MODE_AM, 1}}) case request_proto.TrainControl_KL_FONT: msg = append(msg, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.DOOR_MODE_AA, 1}}) vobc.DoorModeAA = true } tcc.SwitchKeyMap[sk.Code].Val = request.Val return msg } func trainBraking(trainLoad int32, handleVal int32, brakePower float32) int64 { tl := trainLoad * 1000 //列车初始化已经 * 100,再*10 就是对应的kg //F=ma 单位 F单位:牛顿,m单位:千克,a单位:米/秒² totalPower := float64(tl) * float64(brakePower) n := int64(math.Abs(float64(handleVal)) / 100 * totalPower) return n } func trainTractionPower(trainLoad int32, handleVal int32, speedKM int32, trainMaxAcc, trainMaxSpeed float32) int64 { //f(牛) = m(质量) * (加速度* 牵引杆%* (1 - 速度(米/秒)/(最大速度(米/秒) * 牵引杆%))) // m := trainLoad * 1000 speedM := float64(speedKM) / 3.6 / 100 acc := math.Abs(float64(handleVal)) / 100 * float64(trainMaxAcc) sp := math.Abs(float64(handleVal)) / 100 * float64(trainMaxSpeed/3.6) if speedM > sp { return 0 } f := float64(m) * (acc * (1 - speedM/sp)) return int64(f) } func trainBrakeAtoStepLevel(trainLoad int32, stepLevel int32, brakePower float32) int64 { tl := trainLoad * 1000 //列车初始化已经 * 100,再*10 就是对应的kg //F=ma 单位 F单位:牛顿,m单位:千克,a单位:米/秒² totalPower := float64(tl) * float64(brakePower) n := totalPower / 7 * float64(stepLevel) return int64(n) } func trainTractionPowerAtoStepLevel(trainLoad int32, speedKM int32, stepLevel int32, trainMaxAcc, trainMaxSpeed float32) int64 { //f(牛) = m(质量) * (加速度* 牵引杆%* (1 - 速度(米/秒)/(最大速度(米/秒) * 牵引杆%))) // m := trainLoad * 1000 sl := float64(stepLevel) speedM := float64(speedKM) / 3.6 / 100 acc := float64(trainMaxAcc) / 7 * sl sp := float64(trainMaxSpeed/3.6) / 7 * sl if speedM > sp { return 0 } f := float64(m) * (acc * (1 - speedM/sp)) return int64(f) } func trainAtoControlTractionAndBrake(train *state_proto.TrainState) { vs := train.VobcState vs.TractionStatus = false vs.TractionForce = 0 vs.BrakingStatus = false vs.BrakeForce = 0 vs.MaintainBrakeStatus = false var brakeState byte = 0 var notBreak byte = 0 if vs.AtoTractionCommandOut && vs.AtoBrakeCommand { f := trainBrakeAtoStepLevel(train.TrainLoad, int32(vs.AtoStepLevel.Number()), train.TrainMaxBrake) vs.BrakeForce = f / 1000 * 100 vs.BrakingStatus = true brakeState = 1 } else if vs.AtoTractionCommandOut { f := trainTractionPowerAtoStepLevel(train.TrainLoad, train.DynamicState.Speed, int32(vs.AtoStepLevel.Number()), train.TrainMaxAcc, train.TrainMaxSpeed) vs.TractionForce = f / 1000 * 100 vs.TractionStatus = true notBreak = 1 } else if vs.AtoBrakeCommand { f := trainBrakeAtoStepLevel(train.TrainLoad, int32(vs.AtoStepLevel.Number()), train.TrainMaxBrake) vs.BrakeForce = f / 1000 * 100 vs.BrakingStatus = true brakeState = 1 } msg := []message.TrainPcSimBaseMessage{ {Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.TRAIN_BRAKE_STATE, brakeState}}, {Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.NOT_BREAK, notBreak}}, } slog.Info(fmt.Sprintf("列车 id:%v,ato:%v,AtoLevle:%v,牵引:%v,制动:%v,牵引力:%v,制动力%v", train.Id, vs.Ato, vs.AtoStepLevel, vs.AtoTractionCommandOut, vs.AtoBrakeCommand, vs.TractionForce, vs.BrakeForce)) train_pc_sim.Default().SendTrainControlMsg2(train, msg, train.TrainPort) } // 列车牵引控制 func trainControlHandle(train *state_proto.TrainState, request *request_proto.TrainControl_PushHandler, deviceId uint32, tccGraphic *data_proto.TccGraphicStorage) []message.TrainPcSimBaseMessage { _, find := findTrainTccGraphicDataHandler(tccGraphic, deviceId) if !find { slog.Error("未找到对应的牵引制动手柄设备deviceId:", deviceId) return nil } tcc := train.Tcc vobc := train.VobcState jjzdBtn := tcc.Buttons[JJZD] vobc.TractionStatus = false vobc.TractionForce = 0 vobc.BrakingStatus = false vobc.BrakeForce = 0 vobc.MaintainBrakeStatus = false var notBreak byte = 0 var zeroState byte = 0 var brakeState byte = 0 //var traction byte = 0 if request.Val > 0 { vobc.TractionStatus = true vobc.TractionForce = trainTractionPower(train.TrainLoad, request.Val, train.DynamicState.Speed, train.TrainMaxAcc, train.TrainMaxSpeed) / 1000 * 100 notBreak = 1 //traction = 1 } else if request.Val < 0 { vobc.BrakingStatus = true vobc.BrakeForce = trainBraking(train.TrainLoad, request.Val, train.TrainMaxBrake) / 1000 * 100 vobc.EmergencyBrakingStatus = false jjzdBtn.Passed = false brakeState = 1 } else { zeroState = 1 brakeState = 1 } if tcc.PushHandler == nil { tcc.PushHandler = &state_proto.TrainControlState_PushHandler{Id: deviceId} } tcc.PushHandler.Val = request.Val return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.HANDLE_TO_ZERO, zeroState}}, {Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.TRAIN_BRAKE_STATE, brakeState}}, /*{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.OUTER_EMERGENCY_BRAKE, 1}},*/ {Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.NOT_BREAK, notBreak}}, /*{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{38, traction}}*/} } func (s *VerifySimulation) GetConnTrain2() []*state_proto.TrainState { return s.findConnTrain2(state_proto.TrainConnState_PC_SIM) } func (s *VerifySimulation) findConnTrain2(ct1 ...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 finded := index(ct1, connState.ConnType) if finded >= 0 { trains = append(trains, train) } } return true }) return trains } func index(arr []state_proto.TrainConnState_TrainConnType, search state_proto.TrainConnState_TrainConnType) int { for i, v := range arr { if v == search { return i } } return -1 } 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 } // 反馈atp输出数字量数据 func (s *VerifySimulation) reportTrainMockInitMsg2(driverActive, initConn bool, initTimeStamp int64, trainClientPort state_proto.TrainState_TrainPort, train *state_proto.TrainState, data1, data3 byte) (int64, bool, bool, []message.TrainPcSimBaseMessage) { tcc := train.Tcc tce := make([]message.TrainPcSimBaseMessage, 0) connErr := false state := message.GetBit(data1, 3) //slog.Info(fmt.Sprintf("act:%v ,t1:%v ,a1 :%v,t2:%v,a2:%v,init:%v,ts:%v", act, train.VobcState.Tc1Active, tcc.ActiveTrainA, train.VobcState.Tc2Active, tcc.ActiveTrainB, initConn, initTimeStamp), aport) if message.GetBit(data3, 3) == 0 { actt := byte(0) if driverActive { actt = 1 } tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.DRIVER_ACTIVE_REPORT, actt}}) } tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.TRAIN_INTEGRITY, 1}}) if driverActive == false { return initTimeStamp, initConn, false, tce } if initConn { if data1 == 0 { connErr = true } if state == 0 { jjzdBtn := tcc.Buttons[JJZD] ebTce := controlEBBtn(train, true, jjzdBtn) tce = append(tce, ebTce...) } else if message.GetBit(data1, 0) == 0 { jjzdBtn := tcc.Buttons[JJZD] ebTce := controlEBBtn(train, true, jjzdBtn) tce = append(tce, ebTce...) tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.OUTER_EMERGENCY_BRAKE, state}}) tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.TRAIN_TRACTION_CUTED, 1}}) } } else { initConn = true if initTimeStamp <= 0 { initTimeStamp = time.Now().Add(time.Second * 6).Unix() } if initTimeStamp > time.Now().Unix() { tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.OUTER_EMERGENCY_BRAKE, state}}) initData := s.ObtainTrainDigitalMockDataForStatus(train) tce = append(tce, initData...) /* if trainClientPort == state_proto.TrainState_PORT_A { tcc.ActiveTrainA = true } else if trainClientPort == state_proto.TrainState_PORT_A { tcc.ActiveTrainB = true }*/ initConn = false } } return initTimeStamp, initConn, connErr, tce } func trainAtoLevel(at3, at2, at1 bool) state_proto.TrainVobcState_AtoStepLevel { switch { case at3 == false && at2 == false && at1 == true: return state_proto.TrainVobcState_ATO_STEP_LEVEL_1 case at3 == false && at2 == true && at1 == true: return state_proto.TrainVobcState_ATO_STEP_LEVEL_2 case at3 == false && at2 == true && at1 == false: return state_proto.TrainVobcState_ATO_STEP_LEVEL_3 case at3 == true && at2 == true && at1 == false: return state_proto.TrainVobcState_ATO_STEP_LEVEL_4 case at3 == true && at2 == false && at1 == false: return state_proto.TrainVobcState_ATO_STEP_LEVEL_5 case at3 == true && at2 == false && at1 == true: return state_proto.TrainVobcState_ATO_STEP_LEVEL_6 case at3 == true && at2 == true && at1 == true: return state_proto.TrainVobcState_ATO_STEP_LEVEL_7 default: return state_proto.TrainVobcState_ATO_STEP_LEVEL_NONE } } func (s *VerifySimulation) shuziliang(client *tcp.TcpClient, baseMessage []message.TrainPcSimBaseMessage) { for _, msg := range baseMessage { dd := msg.Encode() //slog.Info(fmt.Sprintf("发送列车控制信息:%x", dd), aport) client.Send(dd) } } // 4.4.1. 车载输出数字量信息报文内容 func (s *VerifySimulation) TrainPcSimDigitalOutInfoHandle(pc *train_pc_sim.TrainPcReciverData, train *state_proto.TrainState, data []byte) bool { //slog.Info("开始接受atp输出模拟量==============%v", aport) /* for i, d := range data { dd := &strings.Builder{} for j := 0; j < 8; j++ { dd.WriteString(fmt.Sprintf(" bit%v val:%v , ", j, message.GetBit(d, uint(j)))) } slog.Info(fmt.Sprintf("接受atp模拟量id:%v,data:%b,bits:%v", i, d, dd.String())) }*/ //slog.Info(fmt.Sprintf("%v", dd.String()), aport) //slog.Info("结束接受atp输出模拟量eeeeeeeeeeeeeeeeee", aport) //s.reportTrainMockInitMsg(aport, client, train, data[4], data[1]) vobc := train.VobcState act := vobc.Tc1Active if pc.RealTrainPort == state_proto.TrainState_PORT_B { act = vobc.Tc2Active } ts, initConn, connErr, tce := s.reportTrainMockInitMsg2(act, pc.TrainConnInitComplate, pc.LineInitTimeStamp, pc.RealTrainPort, train, data[4], data[1]) pc.TrainConnInitComplate = initConn pc.LineInitTimeStamp = ts pc.ConnErr = connErr train_pc_sim.Default().SendTrainControlMsg2(train, tce, pc.RealTrainPort) if act { trainPcSimDigitalOutInfoHandleCode7_0(data[4], vobc) trainPcSimDigitalOutInfoHandleCode15_8(data[3], vobc) trainPcSimDigitalOutInfoHandleCode23_16(data[2], vobc) trainPcSimDigitalOutInfoHandleCode31_24(data[1], vobc) trainPcSimDigitalOutInfoHandleCode39_32(data[0], vobc) if vobc.Ato { vobc.AtoStepLevel = trainAtoLevel(vobc.AtoTractionCommand3, vobc.AtoTractionCommand2, vobc.AtoTractionCommand1) } } /* if pc.RealTrainPort == state_proto.TrainState_PORT_A { ts, initConn, connErr, tce := s.reportTrainMockInitMsg2(vobc.Tc1Active, pc.TrainConnInitComplate, pc.LineInitTimeStamp, pc.RealTrainPort, train, data[4], data[1]) pc.TrainConnInitComplate = initConn pc.LineInitTimeStamp = ts pc.ConnErr = connErr train_pc_sim.Default().SendTrainControlMsg2(train, tce, pc.RealTrainPort) if train.VobcState.Tc1Active { trainPcSimDigitalOutInfoHandleCode7_0(data[4], vobc) trainPcSimDigitalOutInfoHandleCode15_8(data[3], vobc) trainPcSimDigitalOutInfoHandleCode23_16(data[2], vobc) trainPcSimDigitalOutInfoHandleCode31_24(data[1], vobc) trainPcSimDigitalOutInfoHandleCode39_32(data[0], vobc) if vobc.Ato { vobc.AtoStepLevel = trainAtoLevel(vobc.AtoTractionCommand3, vobc.AtoTractionCommand2, vobc.AtoTractionCommand1) } } } else if pc.RealTrainPort == state_proto.TrainState_PORT_B { ts, initConn, connErr, tce := s.reportTrainMockInitMsg2(vobc.Tc2Active, pc.TrainConnInitComplate, pc.LineInitTimeStamp, pc.RealTrainPort, train, data[4], data[1]) pc.TrainConnInitComplate = initConn pc.LineInitTimeStamp = ts pc.ConnErr = connErr train_pc_sim.Default().SendTrainControlMsg2(train, tce, pc.RealTrainPort) if train.VobcState.Tc2Active { trainPcSimDigitalOutInfoHandleCode7_0(data[4], vobc) trainPcSimDigitalOutInfoHandleCode15_8(data[3], vobc) trainPcSimDigitalOutInfoHandleCode23_16(data[2], vobc) trainPcSimDigitalOutInfoHandleCode31_24(data[1], vobc) trainPcSimDigitalOutInfoHandleCode39_32(data[0], vobc) if vobc.Ato { vobc.AtoStepLevel = trainAtoLevel(vobc.AtoTractionCommand3, vobc.AtoTractionCommand2, vobc.AtoTractionCommand1) } } }*/ return true } 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(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.LightDriverActive = 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.LightDir1 = message.IsTrueForByte(message.GetBit(d, 0)) //列车方向1 vobc.LightDir2 = message.IsTrueForByte(message.GetBit(d, 1)) //列车方向1 //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.LightAtoSend = 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.AtpLowPowerByte(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.LeftDoorState = message.IsTrueForByte(message.GetBit(d, 4)) //开左门允许 vobc.RightDoorState = message.IsTrueForByte(message.GetBit(d, 5)) //开右门允许 vobc.AtoCloseRightDoor = message.IsTrueForByte(message.GetBit(d, 6)) //ATO关右门 vobc.AllDoorClose = message.IsTrueForByte(message.GetBit(d, 7)) //车门保持关闭 vobc.LightTractionSafetyCircuit = vobc.TractionSafetyCircuit //切牵引 vobc.LightEmergencyBrakingStatus = vobc.EmergencyBrakingStatus //紧急制动 } // 4.4.2. 车载输出数字反馈量信息报文内容 func (s *VerifySimulation) TrainPcSimDigitalReportHandle(train *state_proto.TrainState, data []byte) { slog.Info(fmt.Sprintf("车载输出数字量反馈信息", hex.EncodeToString(data))) 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 { crErr := train_pc_sim.Default().CreateOrRemoveTrain(train, create) //train_pc_sim.Default().CreateOrRemoveSpeedPLace(train) if crErr != nil { return crErr } } 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(train *state_proto.TrainState, 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) TrainBtmQuery2(train *state_proto.TrainState, data []byte, trainClientPort state_proto.TrainState_TrainPort) { ts := time.Now().UnixMilli() if len(data) < 12 { slog.Error("列车btm查询报文长度错误:", len(data)) return } trainAtm := message.NewBtmHeadFrame(data) atpReq := &message.AtpRequestFrame{} if !atpReq.Decode2(trainAtm) { slog.Warn("列车pc驾驶模拟-CanetFrame解码成AtpRequestFrame失败", "CanetFrame", trainAtm.String()) return } var balise *state_proto.BTMState var dsn, bc, mc byte btmCache := train.BtmBaliseCacheA if train.TrainPort != trainClientPort { btmCache = train.BtmBaliseCacheB } if atpReq.IsResend() { balise, dsn, bc, mc = can_btm.FindBaliseResend(btmCache, true) } else { balise, dsn, bc, mc = can_btm.FindBaliseByNotSend(btmCache, true) } cl := clock(atpReq) btmRepFrame := createBtmStatus(trainAtm.CanId.ID4, balise, atpReq, cl, dsn, bc, mc) timeSyncF := message.NewBtmTimeSyncCheckFrame(trainAtm.CanId.ID4) timeSyncF.T2 = cl.BtmTk timeSyncF.T3 = cl.TkNow() if balise == nil { queryData := createLine12EmptyBaliseData(btmRepFrame, timeSyncF) sendLine12EmptyBaliseData(train, trainClientPort, queryData) //slog.Info(fmt.Sprintf("接受应答器查询:%x发送无应答器数据,id:%v,数据:%X", data, trainAtm.CanId.ID4, queryData)) } else { logstr := "" if atpReq.IsResend() { logstr = fmt.Sprintf("准备重新发送应答id:%v,接受时间:%v,发送时间:%v , 数据:%v 经过:%v,解报文:%v,接受应答器报文:%X clientPoret:%v trainPort:%v", balise.BaliseId, ts, time.Now().UnixMilli(), balise.Telegram, bc, mc, data, trainClientPort.String(), train.TrainPort.String()) } else if !balise.IsSend { balise.IsSend = true logstr = fmt.Sprintf("准备发送应答id:%v,接受时间:%v,发送时间:%v , 数据:%v 经过:%v,解报文:%v,接受应答器报文:%X clientPoret:%v trainPort:%v", balise.BaliseId, ts, time.Now().UnixMilli(), balise.Telegram, bc, mc, data, trainClientPort.String(), train.TrainPort.String()) } /*else { queryData := createLine12EmptyBaliseData(btmRepFrame, timeSyncF) sendLine12EmptyBaliseData(train, trainClientPort, queryData) return }*/ slog.Info(logstr, trainClientPort.String()) aliseData, _ := hex.DecodeString(balise.Telegram) stateRepFrame := btmRepFrame.EncodeBtmAtp() statusDataCf, statusDataCfOk := message.CreateBtmAtpDataRspFramesData(stateRepFrame, aliseData, false, balise.HasData, cl.BtmTk, cl.BtmTk, cl.BtmTk) if statusDataCfOk { timeSyncF.T2 = cl.BtmTk timeSyncF.T3 = cl.TkNow() queryData := make([]byte, 0) queryData = append(queryData, stateRepFrame.Encode()...) queryData = append(queryData, timeSyncF.EncodeBtmAtp().Encode()...) queryData = append(queryData, statusDataCf...) //数据帧包含结束帧 balise.BaliseTelegramForPcSimResend = fmt.Sprintf("%X", statusDataCf) train_pc_sim.Default().SendBaliseData2(train, trainClientPort, message.RECIVE_TRAIN_BTM_HAS_DATA, queryData) } else { slog.Error("列车pc仿真 BtmCanetClient应答帧、数据帧编码失败") } } } func sendLine12EmptyBaliseData(train *state_proto.TrainState, trainClientPort state_proto.TrainState_TrainPort, emptyBaliseData []byte) { train_pc_sim.Default().SendBaliseData2(train, trainClientPort, message.RECIVE_TRAIN_BTM_NOT_DATA, emptyBaliseData) } func createLine12EmptyBaliseData(btmRepFrame *message.BtmStatusRspFrame, timeSyncFrame *message.BtmTimeSyncCheckFrame) []byte { queryData := make([]byte, 0) queryData = append(queryData, btmRepFrame.EncodeBtmAtp().Encode()...) queryData = append(queryData, timeSyncFrame.EncodeBtmAtp().Encode()...) return queryData } func createBtmStatus(canIdSn byte, btmState *state_proto.BTMState, atpReq *message.AtpRequestFrame, cl can_btm.BtmClock, dsn, baliseCount, messageCount byte) *message.BtmStatusRspFrame { statusF := message.NewBtmStatusRspFrame(canIdSn) statusF.PowerAmplifierOn = true statusF.PowerAmplifierFailure = false statusF.AtpReqCrcCheckWrong = !atpReq.Crc16CheckOk statusF.AntennaFault = false statusF.BaliseCounter = baliseCount statusF.MessageCounter = messageCount //statusF.TkTimeA = cl.TkNow() statusF.TkTimeA = cl.BtmTk statusF.DetailedCode = 0 if btmState != nil && btmState.AboveBalise { statusF.DetailedCode = 0x07 } 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) ObtainTrainDigitalMockDataForStatus(train *state_proto.TrainState) []message.TrainPcSimBaseMessage { msgArr := make([]message.TrainPcSimBaseMessage, 0) vs := train.VobcState if vs.Tc1Active || vs.Tc2Active { msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.KEY_STATE, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //钥匙激活 //msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.DRIVER_ACTIVE_REPORT, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //列车完整性 } /* else { msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.DRIVER_ACTIVE_REPORT, 0}, Type: message.SENDER_TRAIN_OUTR_INFO}) //列车完整性 }*/ if vs.BrakeForce == 0 { msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.HANDLE_TO_ZERO, 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, 0}, Type: message.SENDER_TRAIN_OUTR_INFO}) //紧急制动 } if vs.DirectionForward { 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 vs.DirectionForward { 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.HANDLE_BACKWORD, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //方向手柄向前控制 } /* if vs.RightDoorCloseCommand { msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.CLOSE_RIGHT_DOOR, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //关右门按钮 } if vs.LeftDoorCloseCommand { msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.CLOSE_LEFT_DOOR, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //关左门按钮 } if vs.AllDoorClose { }*/ if vs.ObstacleCheckBtn { msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.OBSTACLE_CHECK, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //障碍物检测按钮 } if vs.BrakeHeavyFault { msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.BRAKE_HEAVY_FAULT, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //制动重故障 } if vs.AtpCutSwitch { msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.ATP_CUT, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //atp切除 } if vs.AtpPowerOnBtn { msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.ATP_POWER_ON, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //atp上电 } if vs.TurnbackStatus { msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.TURN_BACK, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //atp上电 } 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.EMERGENT_HANDLE_DOWN, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //紧急手柄拉下 msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.TRAIN_TRACTION_CUTED, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //紧急手柄拉下 return msgArr } func (s *VerifySimulation) ObtainTrainDigitalMockData(train *state_proto.TrainState) []message.TrainPcSimBaseMessage { msgArr := make([]message.TrainPcSimBaseMessage, 0) vs := train.VobcState stateArr := s.ObtainTrainDigitalMockDataForStatus(train) msgArr = append(msgArr, stateArr...) msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.ATO_SEND_TRAIN, 0}, Type: message.SENDER_TRAIN_OUTR_INFO}) //ATO发车按钮 msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.LEFT_DOOR_STATE, 0}, Type: message.SENDER_TRAIN_OUTR_INFO}) //左门状态按钮 msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.RIGHT_DOOR_STATE, 0}, Type: message.SENDER_TRAIN_OUTR_INFO}) //列车完整性 msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.CONFIRM, 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.NOT_BREAK, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //非制动 msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{38, 0}, 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{message.DOOR_LOCK_STATE, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //车门锁闭状态 var modeAA, modeAM, modeMM byte = 0, 0, 0 if vs.DoorModeAA { modeAA = 1 } if vs.DoorModeAM { modeAM = 1 } if vs.DoorModeMM { modeMM = 1 } msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.DOOR_MODE_AA, modeAA}, Type: message.SENDER_TRAIN_OUTR_INFO}) msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.DOOR_MODE_AM, modeAM}, Type: message.SENDER_TRAIN_OUTR_INFO}) msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.DOOR_MODE_MM, modeMM}, Type: message.SENDER_TRAIN_OUTR_INFO}) return msgArr }