rts-sim-testing-service/ts/simulation/wayside/memory/wayside_simulation_train_pc.go
2024-07-25 14:55:46 +08:00

853 lines
36 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

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

package memory
import (
"encoding/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 baseMsg []message.TrainPcSimBaseMessage = nil
if ct.ControlType == request_proto.TrainControl_EMERGENT_BUTTON {
baseMsg = trainControlButton(vobc, tcc.Buttons, 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.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 {
if vobc.Tc1Active && vobc.Tc2Active {
panic(sys_error.New("TC1和TC2都未激活不能搬动牵引制动手柄 "))
}
oldTraction := sta.VobcState.TractionForce
oldBrakeForce := sta.VobcState.BrakeForce
isTraction := ct.Handler.Val > 0 //是否制动
baseMsg = trainControlHandle(vobc, tcc, ct.Handler, ct.DeviceId, tccGraphicData)
train_pc_sim.Default().SendHandleSwitch(oldTraction, oldBrakeForce, isTraction, sta)
}
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().SendTrainControlMsg(sta, baseMsg)
}
}
func trainControlButton(vobc *state_proto.TrainVobcState, buttonMap map[string]*state_proto.TrainControlState_ControlButton, deviceId uint32, active bool, tccGraphic *data_proto.TccGraphicStorage) []message.TrainPcSimBaseMessage {
if graphicBtn, ok := findTrainTccGraphicDataButton(tccGraphic, deviceId); ok {
btn := buttonMap[graphicBtn.Code]
if btn == nil {
slog.Error("未找到对应的车载摁钮code:", graphicBtn.Code, "设备id:", deviceId)
return nil
}
switch graphicBtn.Code {
case JJZD: // 紧急制动
return controlEBBtn(vobc, active, btn)
case ATPQCKG: //atp切除
return controlAtpBtn(vobc, active, btn)
/* case "WBJJZDFK": //外部紧急制动反馈
return controlOutEbReportBtn(vobc, active, btn)*/
case KZM: //开左门按钮
return controlLeftDoorBtn(vobc, active, btn)
case GZM: //关左门按钮
return controlLeftDoorCloseBtn(vobc, active, btn)
case KYM: //开右门按钮
return controlRightDoorBtn(vobc, active, btn)
case GYM: //关右门按钮
return controlRightDoorCloseBtn(vobc, active, btn)
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)
default:
return nil
}
} else {
return nil
}
}
// 应急摁钮
func controlEBBtn(vobc *state_proto.TrainVobcState, active bool, tccBtn *state_proto.TrainControlState_ControlButton) []message.TrainPcSimBaseMessage {
if !active {
return nil
}
tccBtn.Passed = active
vobc.EmergencyBrakingStatus = true
vobc.TractionForce = 0
vobc.BrakeForce = DEFAULT_BRAKE_FORCE
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 controlLeftDoorBtn(vobc *state_proto.TrainVobcState, active bool, tccBtn *state_proto.TrainControlState_ControlButton) []message.TrainPcSimBaseMessage {
var status byte = 0
if active {
status = 1
}
vobc.LeftDoorOpenCommand = active
tccBtn.Passed = active
return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.LEFT_OPEN_DOOR, status}}}
}
// 关左门按钮
func controlLeftDoorCloseBtn(vobc *state_proto.TrainVobcState, active bool, tccBtn *state_proto.TrainControlState_ControlButton) []message.TrainPcSimBaseMessage {
var status byte = 0
if active {
status = 1
}
vobc.LeftDoorCloseCommand = active
tccBtn.Passed = active
return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.CLOSE_LEFT_DOOR, status}}}
}
// 开右门
func controlRightDoorBtn(vobc *state_proto.TrainVobcState, active bool, tccBtn *state_proto.TrainControlState_ControlButton) []message.TrainPcSimBaseMessage {
var status byte = 0
if active {
status = 1
}
vobc.RightDoorOpenCommand = active
tccBtn.Passed = active
return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.OPEN_RIGHT_DOOR, status}}}
}
// 关右门按钮
func controlRightDoorCloseBtn(vobc *state_proto.TrainVobcState, active bool, tccBtn *state_proto.TrainControlState_ControlButton) []message.TrainPcSimBaseMessage {
var status byte = 0
if active {
status = 1
}
vobc.RightDoorCloseCommand = active
tccBtn.Passed = active
return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.CLOSE_RIGHT_DOOR, status}}}
}
// 折返
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 trainControlDirKey(trainSpeed int32, vobc *state_proto.TrainVobcState, tcc *state_proto.TrainControlState, request *request_proto.TrainControl_DirectionKeySwitch, deviceId uint32, tccGraphic *data_proto.TccGraphicStorage) []message.TrainPcSimBaseMessage {
_, 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
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
} 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 []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.KEY_STATE, 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) []message.TrainPcSimBaseMessage {
_, find := findTrainTccGraphicDataHandler(tccGraphic, deviceId)
if !find {
slog.Error("未找到对应的牵引制动手柄设备deviceId:", deviceId)
return nil
}
jjzdBtn := tcc.Buttons[JJZD]
vobc.TractionStatus = false
vobc.TractionForce = 0
vobc.BrakingStatus = false
vobc.BrakeForce = 0
vobc.MaintainBrakeStatus = false
var zeroState byte = 0
var brakeState byte = 0
if request.Val > 0 {
vobc.TractionStatus = true
vobc.TractionForce = int64(request.Val * 180)
} else if request.Val < 0 {
vobc.BrakingStatus = true
vobc.BrakeForce = int64(-request.Val * 180)
vobc.EmergencyBrakingStatus = false
jjzdBtn.Passed = false
brakeState = 1
} else {
zeroState = 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}}}
}
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) reportTrainMockInitMsg(train *state_proto.TrainState, data1, data3 byte, trainInit bool) bool {
vobc := train.VobcState
tcc := train.Tcc
tce := make([]message.TrainPcSimBaseMessage, 0)
tcc.Line12ConnErr = false
initResult := trainInit
if vobc.Tc1Active || vobc.Tc2Active {
state := message.GetBit(data1, 3)
if trainInit {
if data1 == 0 {
tcc.Line12ConnErr = true
slog.Warn("接受atp模拟量数据data[4]=0模拟断开")
}
if state == 0 {
train_pc_sim.Default().ResetPluseCount(train)
jjzdBtn := tcc.Buttons[JJZD]
ebTce := controlEBBtn(vobc, true, jjzdBtn)
tce = append(tce, ebTce...)
}
} else {
initResult = true
if tcc.LineInitTimeStamp12 <= 0 {
tcc.LineInitTimeStamp12 = time.Now().Add(time.Second * 6).Unix()
}
if tcc.LineInitTimeStamp12 > 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...)
initResult = false
}
}
//驾驶室激活反馈
if message.GetBit(data3, 3) == 0 {
tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.DRIVER_ACTIVE_REPORT, 1}})
}
tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.TRAIN_INTEGRITY, 1}})
}
train_pc_sim.Default().SendTrainControlMsg(train, tce)
return initResult
}
// 4.4.1. 车载输出数字量信息报文内容
func (s *VerifySimulation) TrainPcSimDigitalOutInfoHandle(train *state_proto.TrainState, trainInit bool, data []byte) bool {
/*for i, d := range data {
slog.Info(fmt.Sprintf("atp模拟量分析index:%v ,bin:%2b,trainInit:%v", i, d, trainInit))
}*/
initResult := s.reportTrainMockInitMsg(train, data[4], data[1], trainInit)
vobc := train.VobcState
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)
return initResult
}
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.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.LeftDoorState = message.IsTrueForByte(message.GetBit(d, 4)) //开左门允许
vobc.RightDoorState = message.IsTrueForByte(message.GetBit(d, 5)) //开右门允许
vobc.RightDoorCloseCommand = message.IsTrueForByte(message.GetBit(d, 6)) //关右门
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) TrainBtmQuery(train *state_proto.TrainState, data []byte) {
//time.Sleep(time.Millisecond * 50)
slog.Info(fmt.Sprintf("收到车载输出BTM查询同步帧报文内容:%v", hex.EncodeToString(data)))
if len(data) < 12 {
slog.Error("列车btm查询报文长度错误:", len(data))
return
}
if train.BtmState == nil {
slog.Warn(fmt.Sprintf("列车暂时未获取到应答器信息,无法进行btm查询列车id:%v", train.Id))
return
}
trainAtm := message.NewBtmHeadFrame(data)
atpReq := &message.AtpRequestFrame{}
if !atpReq.Decode2(trainAtm) {
slog.Warn("列车pc驾驶模拟-CanetFrame解码成AtpRequestFrame失败", "CanetFrame", trainAtm.String())
return
}
cl := clock(atpReq)
dsn := train_pc_sim.Default().DsnAddAndReturn()
btmRepFrame := createBtmStatus(trainAtm.CanId.ID4, train.BtmState, atpReq, cl, dsn)
//slog.Info(fmt.Sprintf("id1:%x,id2:%x,id3:%x,id4:%x,resendRequest:%v,reqTime:%v,dsn:%v", trainAtm.CanId.ID1, trainAtm.CanId.ID2, trainAtm.CanId.ID3, trainAtm.CanId.ID4, atpReq.ResendRequest, atpReq.Time, dsn))
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)
timeSyncF.T2 = cl.BtmTk
timeSyncF.T3 = cl.TkNow()
queryData := make([]byte, 0)
queryData = append(queryData, btmRepFrame.EncodeBtmAtp().Encode()...)
queryData = append(queryData, timeSyncF.Encode().Encode()...)
train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_NOT_DATA, queryData)
}
} else {
timeSyncF := message.NewBtmTimeSyncCheckFrame(trainAtm.CanId.ID4)
timeSyncF.T2 = cl.BtmTk
timeSyncF.T3 = cl.TkNow()
telCount := strings.Count(train.BtmState.Telegram, "00")
if telCount >= balise_const.UserTelegramByteLen {
queryData := make([]byte, 0)
queryData = append(queryData, btmRepFrame.EncodeBtmAtp().Encode()...)
queryData = append(queryData, timeSyncF.EncodeBtmAtp().Encode()...)
train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_NOT_DATA, queryData)
} else {
//有数据
aliseData, _ := hex.DecodeString(train.BtmState.Telegram)
stateRepFrame := btmRepFrame.EncodeBtmAtp()
statusDataCf, statusDataCfOk := message.CreateBtmAtpDataRspFramesData(stateRepFrame, aliseData, false, 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...) //数据帧包含结束帧
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, dsn byte) *message.BtmStatusRspFrame {
statusF := message.NewBtmStatusRspFrame(canIdSn)
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.TkTimeA = cl.BtmTk
statusF.DetailedCode = 0
if btmState.AboveBalise {
statusF.DetailedCode = 0x07
}
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) ObtainTrainDigitalMockDataForStatus(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}) //钥匙激活
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}) //紧急制动
}
dir := request_proto.TrainControl_Direction(tcc.DirKey.Val)
/*if vs.DirectionForward && vs.TractionForce == 0 {
msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.DIR_ZERO_FORWARD, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //手柄零位方向向前
} else*/if dir == request_proto.TrainControl_FORWARD {
//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_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.DIR_ZERO_FORWARD, 0}, Type: message.SENDER_TRAIN_OUTR_INFO}) //手柄零位方向向前
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 {
msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.DOOR_LOCK_STATE, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //车门锁闭状态
}
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)
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}) //对端机械钩
train.BtmState = nil
return msgArr
}