2024-04-02 18:20:10 +08:00
|
|
|
|
package memory
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"encoding/binary"
|
|
|
|
|
"encoding/hex"
|
|
|
|
|
"fmt"
|
|
|
|
|
"joylink.club/bj-rtsts-server/config"
|
|
|
|
|
"joylink.club/bj-rtsts-server/const/balise_const"
|
2024-04-09 10:40:18 +08:00
|
|
|
|
"joylink.club/bj-rtsts-server/dto/data_proto"
|
2024-04-02 18:20:10 +08:00
|
|
|
|
"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/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.PcSimConfig
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 列车控制
|
2024-04-09 10:40:18 +08:00
|
|
|
|
func ControlTrainUpdate(s *VerifySimulation, ct *request_proto.TrainControl) {
|
2024-04-02 18:20:10 +08:00
|
|
|
|
allTrainMap := &s.Memory.Status.TrainStateMap
|
|
|
|
|
data, ok := allTrainMap.Load(ct.TrainId)
|
|
|
|
|
if !ok {
|
|
|
|
|
panic(sys_error.New(fmt.Sprintf("列车【%s】不存在", ct.TrainId)))
|
|
|
|
|
}
|
2024-04-09 10:40:18 +08:00
|
|
|
|
tccGraphicData := findTrainTccGraphicData(s)
|
|
|
|
|
if tccGraphicData == nil {
|
|
|
|
|
slog.Error("列车控制未找到TCC图形数据")
|
|
|
|
|
panic(sys_error.New("未找到TCC图形数据"))
|
|
|
|
|
}
|
2024-04-02 18:20:10 +08:00
|
|
|
|
sta := data.(*state_proto.TrainState)
|
|
|
|
|
var tce []train_pc_sim.TrainControlEvent = nil
|
|
|
|
|
if ct.ControlType == request_proto.TrainControl_EMERGENT_BUTTON {
|
2024-04-16 17:26:37 +08:00
|
|
|
|
tce = trainControlEB(sta, ct.Button, ct.DeviceId, tccGraphicData)
|
2024-04-02 18:20:10 +08:00
|
|
|
|
} else if ct.ControlType == request_proto.TrainControl_DRIVER_KEY_SWITCH {
|
2024-04-09 10:40:18 +08:00
|
|
|
|
tce = trainControlDriverKey(sta, ct.DriverKey, ct.DeviceId, tccGraphicData)
|
2024-04-02 18:20:10 +08:00
|
|
|
|
train_pc_sim.Default().SendDriverActive(sta.ConnState, sta.VobcState)
|
|
|
|
|
} else if ct.ControlType == request_proto.TrainControl_DIRECTION_KEY_SWITCH {
|
2024-04-16 17:26:37 +08:00
|
|
|
|
tce = trainControlDirKey(sta, ct.DirKey, ct.DeviceId, tccGraphicData)
|
2024-04-17 09:32:25 +08:00
|
|
|
|
//此处先注释,根据现场调试情况 2024-4-16
|
|
|
|
|
//train_pc_sim.Default().SendTrainDirection(sta.VobcState.DirectionForward, sta.VobcState.DirectionBackward)
|
2024-04-02 18:20:10 +08:00
|
|
|
|
} else if ct.ControlType == request_proto.TrainControl_HANDLER {
|
|
|
|
|
oldTraction := sta.VobcState.TractionForce
|
|
|
|
|
oldBrakeForce := sta.VobcState.BrakeForce
|
2024-04-16 17:26:37 +08:00
|
|
|
|
isBrake := ct.Handler.Val < 0 //是否制动
|
2024-04-09 10:40:18 +08:00
|
|
|
|
tce = trainControlHandle(sta, ct.Handler, ct.DeviceId, tccGraphicData)
|
2024-04-16 17:26:37 +08:00
|
|
|
|
train_pc_sim.Default().SendHandleSwitch(oldTraction, oldBrakeForce, isBrake, sta.ConnState, sta.VobcState)
|
2024-04-02 18:20:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-04-09 10:40:18 +08:00
|
|
|
|
if sta.ConnState.Conn && sta.ConnState.ConnType == state_proto.TrainConnState_PC_SIM && tce != nil {
|
2024-04-09 08:55:33 +08:00
|
|
|
|
train_pc_sim.Default().PublishTrainControlEvent(s.World, tce)
|
2024-04-02 18:20:10 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-16 17:26:37 +08:00
|
|
|
|
func trainControlEB(trainState *state_proto.TrainState, request *request_proto.TrainControl_EmergentButton, deviceId uint32, tccGraphic *data_proto.TccGraphicStorage) []train_pc_sim.TrainControlEvent {
|
2024-04-09 10:40:18 +08:00
|
|
|
|
|
|
|
|
|
_, find := findTrainTccGraphicDataButton(tccGraphic, deviceId)
|
|
|
|
|
if !find {
|
|
|
|
|
slog.Error("未找到对应的紧急停车摁钮,deviceId:", deviceId)
|
2024-04-16 17:26:37 +08:00
|
|
|
|
return nil
|
2024-04-09 10:40:18 +08:00
|
|
|
|
}
|
2024-04-02 18:20:10 +08:00
|
|
|
|
trainState.VobcState.EmergencyBrakingStatus = request.Active
|
|
|
|
|
if trainState.Tcc.Ebutton == nil {
|
|
|
|
|
trainState.Tcc.Ebutton = &state_proto.TrainControlState_EmergentButton{Id: deviceId, Passed: request.Active}
|
|
|
|
|
} else {
|
|
|
|
|
trainState.Tcc.Ebutton.Passed = request.Active
|
|
|
|
|
}
|
2024-04-16 17:26:37 +08:00
|
|
|
|
return nil
|
|
|
|
|
//return []train_pc_sim.TrainControlEvent{{Command: message.KEY_STATE, Status: message.IsTrue(request.Val)}}
|
2024-04-02 18:20:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 列车方向
|
2024-04-16 17:26:37 +08:00
|
|
|
|
func trainControlDirKey(trainState *state_proto.TrainState, request *request_proto.TrainControl_DirectionKeySwitch, deviceId uint32, tccGraphic *data_proto.TccGraphicStorage) []train_pc_sim.TrainControlEvent {
|
2024-04-09 10:40:18 +08:00
|
|
|
|
_, find := findTrainTccGraphicDataKey(tccGraphic, deviceId)
|
|
|
|
|
if !find {
|
|
|
|
|
slog.Error("未找到对应的列车方向键deviceId:", deviceId)
|
2024-04-16 17:26:37 +08:00
|
|
|
|
return nil
|
2024-04-09 10:40:18 +08:00
|
|
|
|
}
|
2024-04-16 17:26:37 +08:00
|
|
|
|
|
2024-04-02 18:20:10 +08:00
|
|
|
|
trainState.VobcState.DirectionForward = false
|
|
|
|
|
trainState.VobcState.DirectionBackward = false
|
2024-04-16 17:26:37 +08:00
|
|
|
|
|
2024-04-02 18:20:10 +08:00
|
|
|
|
if request.Val == 1 {
|
|
|
|
|
trainState.VobcState.DirectionForward = true
|
|
|
|
|
} else if request.Val == 0 {
|
2024-04-09 08:55:33 +08:00
|
|
|
|
trainState.VobcState.DirectionBackward = true
|
2024-04-02 18:20:10 +08:00
|
|
|
|
}
|
|
|
|
|
if trainState.Tcc.DirKey == nil {
|
|
|
|
|
trainState.Tcc.DirKey = &state_proto.TrainControlState_DirectionKeySwitch{Id: deviceId, Val: request.Val}
|
|
|
|
|
} else {
|
|
|
|
|
trainState.Tcc.DirKey.Val = request.Val
|
|
|
|
|
}
|
2024-04-16 17:26:37 +08:00
|
|
|
|
return nil
|
2024-04-02 18:20:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 列车驾驶端激活
|
2024-04-09 10:40:18 +08:00
|
|
|
|
func trainControlDriverKey(trainState *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 obj.Code == "SKQYS1" {
|
2024-04-02 18:20:10 +08:00
|
|
|
|
trainState.VobcState.Tc1Active = request.Val
|
2024-04-09 10:40:18 +08:00
|
|
|
|
} else if obj.Code == "SKQYS2" {
|
2024-04-02 18:20:10 +08:00
|
|
|
|
trainState.VobcState.Tc2Active = request.Val
|
|
|
|
|
}
|
|
|
|
|
var addNew = true
|
|
|
|
|
for _, k := range trainState.Tcc.DriverKey {
|
|
|
|
|
if k.Id == deviceId {
|
|
|
|
|
k.Id = deviceId
|
|
|
|
|
k.Val = request.Val
|
|
|
|
|
addNew = false
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if addNew {
|
|
|
|
|
trainState.Tcc.DriverKey = append(trainState.Tcc.DriverKey, &state_proto.TrainControlState_DriverKeySwitch{Id: deviceId, Val: request.Val})
|
|
|
|
|
}
|
2024-04-09 08:55:33 +08:00
|
|
|
|
return []train_pc_sim.TrainControlEvent{{Command: message.KEY_STATE, Status: message.IsTrue(request.Val)}}
|
2024-04-02 18:20:10 +08:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 列车牵引控制
|
2024-04-09 10:40:18 +08:00
|
|
|
|
func trainControlHandle(trainState *state_proto.TrainState, 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
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-02 18:20:10 +08:00
|
|
|
|
trainState.VobcState.TractionStatus = false
|
|
|
|
|
trainState.VobcState.TractionForce = 0
|
|
|
|
|
trainState.VobcState.BrakingStatus = false
|
|
|
|
|
trainState.VobcState.BrakeForce = 0
|
2024-04-16 17:26:37 +08:00
|
|
|
|
trainState.VobcState.MaintainBrakeStatus = false
|
2024-04-02 18:20:10 +08:00
|
|
|
|
tce := make([]train_pc_sim.TrainControlEvent, 0)
|
2024-04-09 08:55:33 +08:00
|
|
|
|
tce = append(tce, train_pc_sim.TrainControlEvent{Command: message.HANDLE_FORWORD, Status: 0})
|
|
|
|
|
tce = append(tce, train_pc_sim.TrainControlEvent{Command: message.HANDLE_BACKWORD, Status: 0})
|
|
|
|
|
tce = append(tce, train_pc_sim.TrainControlEvent{Command: message.HANDLE_TO_ZERO, Status: 0})
|
2024-04-02 18:20:10 +08:00
|
|
|
|
if request.Val > 0 {
|
|
|
|
|
trainState.VobcState.TractionStatus = true
|
2024-04-13 09:40:25 +08:00
|
|
|
|
trainState.VobcState.TractionForce = int64(request.Val * 180)
|
2024-04-09 08:55:33 +08:00
|
|
|
|
tce = append(tce, train_pc_sim.TrainControlEvent{Command: message.HANDLE_FORWORD, Status: 1})
|
2024-04-02 18:20:10 +08:00
|
|
|
|
} else if request.Val < 0 {
|
|
|
|
|
trainState.VobcState.BrakingStatus = true
|
2024-04-13 09:40:25 +08:00
|
|
|
|
trainState.VobcState.BrakeForce = int64(-request.Val * 180)
|
2024-04-09 08:55:33 +08:00
|
|
|
|
tce = append(tce, train_pc_sim.TrainControlEvent{Command: message.HANDLE_BACKWORD, Status: 1})
|
2024-04-16 17:26:37 +08:00
|
|
|
|
tce = append(tce, train_pc_sim.TrainControlEvent{Command: message.TRAIN_BRAKE_STATE, Status: 1})
|
2024-04-02 18:20:10 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
2024-04-09 08:55:33 +08:00
|
|
|
|
tce = append(tce, train_pc_sim.TrainControlEvent{Command: message.HANDLE_TO_ZERO, Status: 1})
|
2024-04-02 18:20:10 +08:00
|
|
|
|
}
|
|
|
|
|
if trainState.Tcc.PushHandler == nil {
|
|
|
|
|
trainState.Tcc.PushHandler = &state_proto.TrainControlState_PushHandler{Id: deviceId, Val: request.Val}
|
|
|
|
|
} else {
|
|
|
|
|
trainState.Tcc.PushHandler.Val = request.Val
|
|
|
|
|
}
|
|
|
|
|
return tce
|
|
|
|
|
}
|
2024-04-09 08:55:33 +08:00
|
|
|
|
|
|
|
|
|
func (s *VerifySimulation) GetConnTrain() *state_proto.TrainState {
|
|
|
|
|
return s.findConnTrain(state_proto.TrainConnState_PC_SIM)
|
|
|
|
|
}
|
2024-04-02 18:20:10 +08:00
|
|
|
|
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(data []byte) {
|
|
|
|
|
train := s.findConnTrain(state_proto.TrainConnState_PC_SIM)
|
|
|
|
|
if train == nil {
|
|
|
|
|
slog.Error("车载输出数字量,未找到连接车载pc仿真的列车")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if !train.ConnState.Conn {
|
|
|
|
|
slog.Error("车载输出数字量,,列车未连接车载pc仿真")
|
|
|
|
|
return
|
|
|
|
|
}
|
2024-04-11 08:55:12 +08:00
|
|
|
|
//buf := bytes.NewBuffer(data)
|
2024-04-02 18:20:10 +08:00
|
|
|
|
vobc := train.VobcState
|
2024-04-11 08:55:12 +08:00
|
|
|
|
|
|
|
|
|
//cutTraction, _ := buf.ReadByte() //切牵引
|
|
|
|
|
//trainDoorOutLed, _ := buf.ReadByte() //车门外指示灯
|
|
|
|
|
//stopBrakeAppend, _ := buf.ReadByte() //停放制动施加
|
|
|
|
|
//emergentBrake, _ := buf.ReadByte() //紧急制动
|
|
|
|
|
//leftOpenDoor, _ := buf.ReadByte() //开左门允许
|
|
|
|
|
//rightOpenDoor, _ := buf.ReadByte() //开右门允许
|
|
|
|
|
//closeRightDoor, _ := buf.ReadByte() //关右门
|
|
|
|
|
//doorAlwaysClosed, _ := buf.ReadByte() //车门保持关闭
|
|
|
|
|
//localAtpControl, _ := buf.ReadByte() //本端ATP控车
|
|
|
|
|
//atoMode, _ := buf.ReadByte() //ATO模式
|
|
|
|
|
//atoTractionCommandOut, _ := buf.ReadByte() //ATO牵引命令输出
|
|
|
|
|
//atoTractionCommand1, _ := buf.ReadByte() //ATO牵引指令1
|
|
|
|
|
//atoTractionCommand2, _ := buf.ReadByte() //ATO牵引指令2
|
|
|
|
|
//atoTractionCommand3, _ := buf.ReadByte() //ATO牵引指令3
|
|
|
|
|
//atoBrakeCommand, _ := buf.ReadByte() //ATO制动命令输出
|
|
|
|
|
//skipCommand, _ := buf.ReadByte() //跳跃指令
|
|
|
|
|
//direction1, _ := buf.ReadByte() //列车方向1
|
|
|
|
|
//direction2, _ := buf.ReadByte() //列车方向2
|
|
|
|
|
//atoLazyCommandOut, _ := buf.ReadByte() //ATO惰行命令输出
|
|
|
|
|
//sleepCommand, _ := buf.ReadByte() //休眠指令
|
|
|
|
|
//wakeUpCommand, _ := buf.ReadByte() //唤醒指令
|
|
|
|
|
//toPullTrainLed, _ := buf.ReadByte() //ATO发车指示灯
|
|
|
|
|
//arLightCommand, _ := buf.ReadByte() //AR灯命令
|
|
|
|
|
//atoAlwaysBrake, _ := buf.ReadByte() //ATO保持制动
|
|
|
|
|
//atoOpenLeftDoor, _ := buf.ReadByte() //ATO开左门
|
|
|
|
|
//atoOpenRightDoor, _ := buf.ReadByte() //ATO开右门
|
|
|
|
|
//atoCloseLeftDoor, _ := buf.ReadByte() //ATO关左门
|
|
|
|
|
//ariverActive, _ := buf.ReadByte() //驾驶室激活
|
|
|
|
|
//noSpeedSigle, _ := buf.ReadByte() //零速信号
|
|
|
|
|
//famMode, _ := buf.ReadByte() //FAM模式
|
|
|
|
|
//camMode, _ := buf.ReadByte() //CAM模式
|
|
|
|
|
//trainStartedLed, _ := buf.ReadByte() //列车启动指示灯
|
|
|
|
|
//mostUseBrake, _ := buf.ReadByte() //常用制动
|
|
|
|
|
//splittingOut, _ := buf.ReadByte() //过分相输出
|
|
|
|
|
//modeRelay, _ := buf.ReadByte() //模式继电器
|
|
|
|
|
//tractionEffective, _ := buf.ReadByte() //牵引有效
|
|
|
|
|
//brakeEffective, _ := buf.ReadByte() //制动有效
|
|
|
|
|
//lifeDoorUsed, _ := buf.ReadByte() //逃生门使能
|
|
|
|
|
//brakeQuarantine, _ := buf.ReadByte() //制动隔离
|
|
|
|
|
//stopNotAllBrake, _ := buf.ReadByte() //停放制动缓解
|
|
|
|
|
|
|
|
|
|
//vobc.TractionSafetyCircuit = message.IsTrueForByte(cutTraction)
|
|
|
|
|
//vobc.TrainDoorOutLed = message.IsTrueForByte(trainDoorOutLed) //? 说明暂无此属性
|
|
|
|
|
//vobc.ParkingBrakeStatus = message.IsTrueForByte(stopBrakeAppend)
|
|
|
|
|
//vobc.EmergencyBrakingStatus = message.IsTrueForByte(emergentBrake)
|
|
|
|
|
//vobc.LeftDoorOpenCommand = message.IsTrueForByte(leftOpenDoor)
|
|
|
|
|
//vobc.RightDoorOpenCommand = message.IsTrueForByte(rightOpenDoor)
|
|
|
|
|
//vobc.RightDoorCloseCommand = message.IsTrueForByte(closeRightDoor)
|
|
|
|
|
//vobc.AllDoorClose = message.IsTrueForByte(doorAlwaysClosed)
|
|
|
|
|
|
|
|
|
|
//vobc.LocalAtpControl = message.IsTrueForByte(localAtpControl) //?
|
|
|
|
|
//vobc.Ato = message.IsTrueForByte(atoMode)
|
|
|
|
|
//vobc.AtoTractionCommandOut = message.IsTrueForByte(atoTractionCommandOut) //?
|
|
|
|
|
//vobc.AtoTractionCommand1 = message.IsTrueForByte(atoTractionCommand1) //?
|
|
|
|
|
//vobc.AtoTractionCommand2 = message.IsTrueForByte(atoTractionCommand2) //?
|
|
|
|
|
//vobc.AtoTractionCommand3 = message.IsTrueForByte(atoTractionCommand3) //?
|
|
|
|
|
//vobc.AtoBrakeCommand = message.IsTrueForByte(atoBrakeCommand) //?
|
|
|
|
|
//vobc.JumpStatus = message.IsTrueForByte(skipCommand)
|
|
|
|
|
|
|
|
|
|
//vobc.DirectionForward = message.IsTrueForByte(direction1)
|
|
|
|
|
//vobc.DirectionBackward = message.IsTrueForByte(direction2)
|
|
|
|
|
//vobc.AtoLazyCommandOut = message.IsTrueForByte(atoLazyCommandOut) //?
|
|
|
|
|
//vobc.SleepBtn = message.IsTrueForByte(sleepCommand)
|
|
|
|
|
//vobc.WakeUpBtn = message.IsTrueForByte(wakeUpCommand)
|
|
|
|
|
//vobc.AtoSendTrainBtn = message.IsTrueForByte(toPullTrainLed)
|
|
|
|
|
//vobc.TurnbackStatus = message.IsTrueForByte(arLightCommand) //?
|
|
|
|
|
//vobc.AtoAlwaysBrake = message.IsTrueForByte(atoAlwaysBrake) //?
|
|
|
|
|
|
|
|
|
|
//vobc.AtoOpenLeftDoor = message.IsTrueForByte(atoOpenLeftDoor) //?
|
|
|
|
|
//vobc.AtoOpenRightDoor = message.IsTrueForByte(atoOpenRightDoor) //?
|
|
|
|
|
//vobc.AtoCloseLeftDoor = message.IsTrueForByte(atoCloseLeftDoor) //?
|
|
|
|
|
//vobc.Tc1Active = message.IsTrueForByte(ariverActive)
|
|
|
|
|
//vobc.NoSpeedSigle = message.IsTrueForByte(noSpeedSigle) //?
|
|
|
|
|
//vobc.Fam = message.IsTrueForByte(famMode)
|
|
|
|
|
//vobc.Cam = message.IsTrueForByte(camMode)
|
|
|
|
|
//vobc.TrainStartedLed = message.IsTrueForByte(trainStartedLed) //?
|
|
|
|
|
|
|
|
|
|
//vobc.MostUseBrake = message.IsTrueForByte(mostUseBrake) //? //常用制动
|
|
|
|
|
//vobc.SplittingOut = message.IsTrueForByte(splittingOut) //? //过分相输出
|
|
|
|
|
//vobc.ModeRelay = message.IsTrueForByte(modeRelay) //? //模式继电器
|
|
|
|
|
//vobc.TractionEffective = message.IsTrueForByte(tractionEffective) //? //牵引有效
|
|
|
|
|
//vobc.BrakeEffective = message.IsTrueForByte(brakeEffective) //? //制动有效
|
|
|
|
|
//vobc.LifeDoorState = message.IsTrueForByte(lifeDoorUsed) //逃生门使能
|
|
|
|
|
//vobc.BrakeQuarantine = message.IsTrueForByte(brakeQuarantine) //? //制动隔离
|
|
|
|
|
//vobc.StopNotAllBrake = message.IsTrueForByte(stopNotAllBrake) //? //停放制动缓解
|
|
|
|
|
trainPcSimDigitalOutInfoHandleCode39_32(data[0], vobc)
|
|
|
|
|
trainPcSimDigitalOutInfoHandleCode31_24(data[1], vobc)
|
|
|
|
|
trainPcSimDigitalOutInfoHandleCode23_16(data[2], vobc)
|
|
|
|
|
trainPcSimDigitalOutInfoHandleCode15_8(data[3], vobc)
|
|
|
|
|
trainPcSimDigitalOutInfoHandleCode7_0(data[4], vobc)
|
2024-04-13 09:40:25 +08:00
|
|
|
|
//cm := &message.TrainControlMsg{TrainId: train.Id, ControlInfo: vobc}
|
|
|
|
|
//dynamics.Default().SendTrainControl(cm)
|
2024-04-02 18:20:10 +08:00
|
|
|
|
}
|
2024-04-11 08:55:12 +08:00
|
|
|
|
func trainPcSimDigitalOutInfoHandleCode39_32(d byte, vobc *state_proto.TrainVobcState) {
|
2024-04-16 17:26:37 +08:00
|
|
|
|
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)) //? 停放制动缓解
|
2024-04-11 08:55:12 +08:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
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关左门
|
|
|
|
|
vobc.Tc1Active = 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
|
2024-04-16 17:26:37 +08:00
|
|
|
|
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保持制动
|
2024-04-11 08:55:12 +08:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
func trainPcSimDigitalOutInfoHandleCode15_8(d byte, vobc *state_proto.TrainVobcState) {
|
2024-04-16 17:26:37 +08:00
|
|
|
|
vobc.LocalAtpControl = message.IsTrueForByte(message.GetBit(d, 0)) //?本端ATP控车
|
2024-04-11 08:55:12 +08:00
|
|
|
|
vobc.Ato = message.IsTrueForByte(message.GetBit(d, 1)) //ATO模式
|
2024-04-16 17:26:37 +08:00
|
|
|
|
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制动命令输出
|
2024-04-11 08:55:12 +08:00
|
|
|
|
vobc.JumpStatus = message.IsTrueForByte(message.GetBit(d, 7)) //跳跃指令
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
func trainPcSimDigitalOutInfoHandleCode7_0(d byte, vobc *state_proto.TrainVobcState) {
|
|
|
|
|
vobc.TractionSafetyCircuit = message.IsTrueForByte(message.GetBit(d, 0)) //切牵引
|
2024-04-16 17:26:37 +08:00
|
|
|
|
vobc.TrainDoorOutLed = message.IsTrueForByte(message.GetBit(d, 1)) //? 车门外指示灯
|
2024-04-11 08:55:12 +08:00
|
|
|
|
vobc.ParkingBrakeStatus = message.IsTrueForByte(message.GetBit(d, 2)) //停放制动施加
|
|
|
|
|
vobc.EmergencyBrakingStatus = message.IsTrueForByte(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)) //车门保持关闭
|
|
|
|
|
|
|
|
|
|
}
|
2024-04-02 18:20:10 +08:00
|
|
|
|
|
|
|
|
|
// 4.4.2. 车载输出数字反馈量信息报文内容
|
|
|
|
|
func (s *VerifySimulation) TrainPcSimDigitalReportHandle(data []byte) {
|
|
|
|
|
train := s.findConnTrain(state_proto.TrainConnState_PC_SIM)
|
|
|
|
|
if train == nil {
|
|
|
|
|
slog.Error("车载输出数字反馈量信息,未找到连接车载pc仿真的列车")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if !train.ConnState.Conn {
|
|
|
|
|
slog.Error("车载输出数字反馈量信息,列车未连接车载pc仿真")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
vobc := train.VobcState
|
2024-04-11 08:55:12 +08:00
|
|
|
|
|
|
|
|
|
//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)) //方向手柄退位
|
2024-04-02 18:20:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 创建/删除列车
|
2024-04-13 09:40:25 +08:00
|
|
|
|
func TrainPcSimConnOrRemoveHandle(train *state_proto.TrainState) {
|
|
|
|
|
var data byte = 0x01
|
|
|
|
|
if train.ConnState.Conn == false {
|
|
|
|
|
data = 0x00
|
2024-04-02 18:20:10 +08:00
|
|
|
|
}
|
2024-04-13 09:40:25 +08:00
|
|
|
|
train_pc_sim.Default().CreateOrRemoveTrain(train_pc_sim.RECIVE_TRAIN_CREATE_REMOVE, []byte{data})
|
2024-04-09 08:55:33 +08:00
|
|
|
|
train_pc_sim.Default().CreateOrRemoveSpeedPLace(train)
|
2024-04-02 18:20:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 门模式
|
2024-04-13 09:40:25 +08:00
|
|
|
|
/*func TrainDoorModeHandle(train *state_proto.TrainState) {
|
2024-04-02 18:20:10 +08:00
|
|
|
|
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
|
|
|
|
|
}
|
2024-04-13 09:40:25 +08:00
|
|
|
|
}*/
|
2024-04-02 18:20:10 +08:00
|
|
|
|
|
|
|
|
|
// 4.4.3. 车载输出模拟量信息报文内容(0x03)
|
|
|
|
|
func (s *VerifySimulation) TrainPcSimMockInfo(data []byte) {
|
|
|
|
|
train := s.findConnTrain(state_proto.TrainConnState_PC_SIM)
|
|
|
|
|
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(data []byte) {
|
|
|
|
|
if len(data) < 12 {
|
|
|
|
|
slog.Error("列车btm查询报文长度错误:", len(data))
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
train := s.findConnTrain(state_proto.TrainConnState_PC_SIM)
|
|
|
|
|
if train == nil {
|
|
|
|
|
slog.Error("车载输出btm查询,未找到连接车载pc仿真的列车")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if !train.ConnState.Conn {
|
|
|
|
|
slog.Error("车载输出btm查询,列车未连接车载pc仿真")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
trainAtm := message.NewCanetFrame(data, true)
|
|
|
|
|
atpReq := &message.AtpRequestFrame{}
|
|
|
|
|
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_pc_sim.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 {
|
|
|
|
|
//无数据
|
|
|
|
|
queryData := make([]byte, 0)
|
|
|
|
|
queryData = append(queryData, btmRepFrame.Encode().Encode()...)
|
|
|
|
|
queryData = append(queryData, timeSyncF.Encode().Encode()...)
|
|
|
|
|
train_pc_sim.Default().SendBaliseData(train_pc_sim.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().Encode()...)
|
|
|
|
|
queryData = append(queryData, timeSyncF.Encode().Encode()...)
|
|
|
|
|
queryData = append(queryData, statusDataCf...) //数据帧包含结束帧
|
|
|
|
|
train.BtmState.BaliseTelegramForPcSimResend = fmt.Sprintf("%X", statusDataCf)
|
|
|
|
|
train_pc_sim.Default().SendBaliseData(train_pc_sim.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, true)
|
|
|
|
|
//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
|
|
|
|
|
}
|
|
|
|
|
statusF.Dsn = byte(btmState.DataSerialNumber)
|
|
|
|
|
return statusF
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func clock(atpReq *message.AtpRequestFrame) can_btm.BtmClock {
|
|
|
|
|
now := time.Now()
|
|
|
|
|
return can_btm.BtmClock{BtmTk: atpReq.Time, SysTk: now}
|
|
|
|
|
}
|