列车pc仿真测试调整
All checks were successful
local-test分支打包构建docker并发布运行 / Docker-Build (push) Successful in 1m35s

This commit is contained in:
tiger_zhou 2024-04-09 08:55:33 +08:00
parent a24ae0a14e
commit 7de95e55f2
18 changed files with 1694 additions and 1274 deletions

File diff suppressed because it is too large Load Diff

@ -1 +1 @@
Subproject commit e4728f0f732904f543a86aabb2c3da2653dd139f
Subproject commit dd445689f17b65d274b39086ad525ae68d0e75c2

View File

@ -67,6 +67,7 @@ func (acc *accVobcService) sendTask(ctx context.Context) {
}
trainStatus := acc.radarVobcManager.FindAccTrain()
if trainStatus != nil {
// 发送加速度信息
speedAcc := trainStatus.DynamicState.Acceleration
t := speedAcc / accSpeedUnit
acc.vobcClient.SendMsg(&message.Accelerometer{Acc: math.Float32bits(t)})

View File

@ -65,12 +65,16 @@ func (s *btmCanetClient) GetState() state_proto.BTMState {
} else {
telegram = strings.Repeat("00", balise_const.UserTelegramByteLen)
}
var dis int64
if info != nil {
dis = info.Distance
}
return state_proto.BTMState{
DataSerialNumber: uint32(s.dsn),
BaliseCount: uint32(detector.baliseCounter),
MessageCounter: uint32(detector.messageCounter),
Telegram: telegram,
Distance: info.Distance,
Distance: dis,
AboveBalise: detector.aboveBalise,
}
}

View File

@ -41,6 +41,8 @@ type Dynamics interface {
// 发送列车控制消息
SendTrainControlMessage(b []byte)
SendTrainControl(cm *message.TrainControlMsg)
}
var _default *dynamics
@ -329,5 +331,11 @@ func (d *dynamics) sendTurnoutStateTask(ctx context.Context) {
}
func (d *dynamics) SendTrainControlMessage(b []byte) {
d.trainControlUdpClient.Send(b)
if d.trainControlUdpClient != nil {
d.trainControlUdpClient.Send(b)
}
}
func (d *dynamics) SendTrainControl(cm *message.TrainControlMsg) {
d.SendTrainControlMessage(cm.Encode())
}

View File

@ -4,12 +4,67 @@ import (
"encoding/binary"
"joylink.club/bj-rtsts-server/dto/state_proto"
"math"
"strconv"
"time"
)
// 接收到的列车控制信息
type TrainControlMsg struct {
ControlInfo *state_proto.TrainVobcState
TrainId string
}
func (r *TrainControlMsg) Encode() []byte {
data := make([]byte, 0)
data = binary.BigEndian.AppendUint16(data, uint16(r.ControlInfo.LifeSignal))
var b2 byte
b2 = setBit(b2, 0, IsTrue(r.ControlInfo.Tc1Active))
b2 = setBit(b2, 1, IsTrue(r.ControlInfo.Tc2Active))
b2 = setBit(b2, 2, IsTrue(r.ControlInfo.DirectionForward))
b2 = setBit(b2, 3, IsTrue(r.ControlInfo.DirectionBackward))
b2 = setBit(b2, 4, IsTrue(r.ControlInfo.TractionStatus))
b2 = setBit(b2, 5, IsTrue(r.ControlInfo.BrakingStatus))
b2 = setBit(b2, 6, IsTrue(r.ControlInfo.EmergencyBrakingStatus))
b2 = setBit(b2, 7, IsTrue(r.ControlInfo.TurnbackStatus))
var b3 byte
b3 = setBit(b3, 0, IsTrue(r.ControlInfo.JumpStatus))
b3 = setBit(b3, 1, IsTrue(r.ControlInfo.Ato))
b3 = setBit(b3, 2, IsTrue(r.ControlInfo.Fam))
b3 = setBit(b3, 3, IsTrue(r.ControlInfo.Cam))
b3 = setBit(b3, 4, IsTrue(r.ControlInfo.TractionSafetyCircuit))
b3 = setBit(b3, 5, IsTrue(r.ControlInfo.ParkingBrakeStatus))
b3 = setBit(b3, 6, IsTrue(r.ControlInfo.MaintainBrakeStatus))
data = append(data, b2)
data = append(data, b3)
data = binary.BigEndian.AppendUint16(data, uint16(r.ControlInfo.TractionForce))
data = binary.BigEndian.AppendUint16(data, uint16(r.ControlInfo.BrakeForce))
data = binary.BigEndian.AppendUint16(data, uint16(r.ControlInfo.TrainLoad))
data = binary.BigEndian.AppendUint16(data, uint16(0)) //预留
data = binary.BigEndian.AppendUint16(data, uint16(0)) //预留
data = append(data, 0) //预留
var b4 byte
b4 = setBit(b4, 0, IsTrue(r.ControlInfo.LeftDoorOpenCommand))
b4 = setBit(b4, 1, IsTrue(r.ControlInfo.RightDoorOpenCommand))
b4 = setBit(b4, 2, IsTrue(r.ControlInfo.LeftDoorCloseCommand))
b4 = setBit(b4, 3, IsTrue(r.ControlInfo.RightDoorCloseCommand))
b4 = setBit(b4, 4, IsTrue(r.ControlInfo.AllDoorClose))
data = append(data, b4)
data = binary.BigEndian.AppendUint16(data, uint16(0)) //预留
data = append(data, 0) //预留
data = append(data, 0) //预留
ti, _ := strconv.Atoi(r.TrainId)
data = append(data, byte(ti))
return data
}
func setBit(b byte, bitNum int, value byte) byte {
if value != 0 && value != 1 {
panic("value must be 0 or 1")
}
mask := byte(1 << uint(bitNum)) // 创建掩码
b &= ^(mask) // 清除位
b |= (mask & (value << uint(bitNum)))
return b
}
// 解析VOBC列车信息

View File

@ -0,0 +1,191 @@
package message
import (
"bytes"
"encoding/binary"
"fmt"
"github.com/snksoft/crc"
"strconv"
"time"
)
const PC_SIM_HEADER = 0xEB
type TrainPcSimBaseMessage struct {
Type uint16
DataLen byte
Data []byte
Crc uint16 // 校验码
}
// 编码
func (tp *TrainPcSimBaseMessage) Encode() []byte {
pack := make([]byte, 0)
pack = append(pack, PC_SIM_HEADER)
pack = binary.BigEndian.AppendUint16(pack, tp.Type)
pack = append(pack, byte(len(tp.Data)))
dataBufs := bytes.NewBuffer(nil)
binary.Write(dataBufs, binary.BigEndian, tp.Data)
data := dataBufs.Bytes()
pack = append(pack, data...)
pack = binary.BigEndian.AppendUint16(pack, uint16(crc.CalculateCRC(crc.CRC16, data)))
return pack
}
// 解码
func (tp *TrainPcSimBaseMessage) Decode(data []byte) error {
if len(data) < 3 {
return fmt.Errorf("")
}
buf := bytes.NewBuffer(data)
h, _ := buf.ReadByte()
if h != PC_SIM_HEADER {
return fmt.Errorf("")
}
var pcType uint16
binary.Read(buf, binary.BigEndian, &pcType)
len, _ := buf.ReadByte()
if buf.Len() < int(len)+2 {
return fmt.Errorf("")
}
var dd = make([]byte, len)
binary.Read(buf, binary.BigEndian, &dd)
var crcCode uint16
binary.Read(buf, binary.BigEndian, &crcCode)
tp.Type = pcType
tp.DataLen = len
tp.Data = dd
tp.Crc = crcCode
return nil
//crc.CalculateCRC(crc.CRC16, data)
}
func IsTrue(d bool) byte {
if d {
return 1
}
return 0
}
func IsTrueForByte(d byte) bool {
if d == 1 {
return true
}
return false
}
// 列车速度位置报告
type TrainSpeedPlaceReportMsg struct {
//列车id
TrainId string
PulseCount1 uint32
PulseCount2 uint32
}
func (tp *TrainSpeedPlaceReportMsg) ParsePulseCount1(s1, s2 uint32) {
tp.PulseCount1 += s1
tp.PulseCount2 += s2
}
func (tp *TrainSpeedPlaceReportMsg) Encode(runDir bool, s1, s2 uint32) []byte {
data := make([]byte, 0)
binary.BigEndian.AppendUint16(data, uint16(IsTrue(runDir)))
binary.BigEndian.AppendUint32(data, s1)
binary.BigEndian.AppendUint32(data, s2)
binary.BigEndian.AppendUint32(data, tp.PulseCount1)
binary.BigEndian.AppendUint32(data, tp.PulseCount2)
now := time.Now().UTC()
// 将时间转换为毫秒
millis := now.UnixNano() / int64(time.Millisecond)
millisStr := strconv.Itoa(int(millis))
strs := []rune(millisStr)
second, _ := strconv.Atoi(string(strs[:len(strs)-3]))
mm, _ := strconv.Atoi(string(strs[len(strs)-3:]))
binary.BigEndian.AppendUint32(data, uint32(second))
binary.BigEndian.AppendUint16(data, uint16(mm))
return data
}
// 轨旁向列车pc仿真发送的命令码
const (
//钥匙开关状态
KEY_STATE = iota
//手柄向前控制
HANDLE_FORWORD
//手柄向后控制
HANDLE_BACKWORD
//外部紧急制动反馈
OUTER_EMERGENCY_BRAKE
//列车制动状态
TRAIN_BRAKE_STATE
//开左门
LEFT_OPEN_DOOR
//关右门
CLOSE_RIGHT_DOOR
//关左门
CLOSE_LEFT_DOOR
//开右门
OPEN_RIGHT_DOOR
//折返按钮
TURN_BACK
//强制门允许
FORCE_DOOR_ALLOW
//模式降级按钮
TRAIN_MODE_DOWN
//确认按钮
CONFIRM
//模式升级按钮
TRAIN_MODE_UP
//牵引制动手柄零位
HANDLE_TO_ZERO
//ATO发车按钮
ATO_SEND_TRAIN
//列车完整性
TRAIN_INTEGRITY
//车载ATP/ATO旁路状态
ATP_ATO_BYPASS_STATe
//车辆牵引已切除状态
TRAIN_TRACTION_CUTED
//障碍物检测按钮
OBSTACLE_CHECK
//驾驶室激活反馈按钮
DRIVER_ACTIVE_REPORT
//制动重故障按钮
BRAKE_HEAVY_FAULT
//左门状态按钮
LEFT_DOOR_STATE
//右门状态按钮
RIGHT_DOOR_STATE
//唤醒按钮
WAKE_UP
//检修按钮
OVERHAUL
//欠压按钮
UNDERVOLTAGE
//休眠按钮
SLEEP
_
//紧急手柄拉下
EMERGENT_HANDLE_DOWN
//车门锁闭状态
DOOR_LOCK_STATE
//逃生门状态
LIFE_DOOR
//车辆低压上电状态
TRAIN_LOW_POWER
//ATP上电按钮
ATP_POWER_ON
_
//AA自动开关门
DOOR_MODE_AA
//AM自开人关
DOOR_MODE_AM
//MM人开人关
DOOR_MODE_MM
)

135
third_party/train_pc_sim/example/main.go vendored Normal file
View File

@ -0,0 +1,135 @@
package main
import (
"fmt"
"io"
"joylink.club/bj-rtsts-server/third_party/message"
"joylink.club/bj-rtsts-server/third_party/train_pc_sim"
"log/slog"
"net"
)
type TcpConnHandler = func(conn net.Conn)
type TcpMsgHandler = func(n int, data []byte)
func tcpRunAcceptTask(listen net.Listener, port int, connHandler TcpConnHandler, msgHandler TcpMsgHandler) {
go func() {
defer func() {
if err := recover(); err != nil {
slog.Error(fmt.Sprintf("TCP服务端[port:%d]接收连接任务异常:", port), err)
tcpRunAcceptTask(listen, port, connHandler, msgHandler)
}
}()
for {
conn, err := listen.Accept()
if err != nil {
slog.Error(fmt.Sprintf("TCP服务端[port:%d]接收连接出错:", port), err)
}
connHandler(conn)
tcpRunReadTask(conn, port, msgHandler)
}
}()
}
func tcpRunReadTask(conn net.Conn, port int, msgHandler TcpMsgHandler) {
go func() {
defer func() {
if err := recover(); err != nil {
slog.Error(fmt.Sprintf("TCP服务端[port:%d]读数据任务异常:", port), err)
tcpRunReadTask(conn, port, msgHandler)
}
}()
for {
data := make([]byte, 1024)
l, err := conn.Read(data)
if err != nil {
if err == io.EOF {
slog.Warn(fmt.Sprintf("TCP服务端[port:%d]断开[%s]连接:", port, conn.RemoteAddr().String()))
break
}
slog.Error(fmt.Sprintf("TCP服务端[port:%d]读取[%s]数据出错:", port, conn.RemoteAddr().String()), err)
serConn = nil
}
msgHandler(l, data)
}
}()
}
func StartTcpServer(port int, connHandler TcpConnHandler, msgHandler TcpMsgHandler) (net.Listener, error) {
listen, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err != nil {
return nil, err
}
tcpRunAcceptTask(listen, port, connHandler, msgHandler)
return listen, err
}
var serConn net.Conn
func createServer(h TcpMsgHandler) {
StartTcpServer(5600, func(conn net.Conn) {
fmt.Println("TCP服务端接收到连接")
serConn = conn
}, h)
}
func connTrain() *message.TrainPcSimBaseMessage {
msg := &message.TrainPcSimBaseMessage{}
msg.Type = train_pc_sim.RECIVE_TRAIN_CREATE_REMOVE
msg.Data = []byte{0x01}
return msg
}
func changeDoorMode() *message.TrainPcSimBaseMessage {
msg := &message.TrainPcSimBaseMessage{}
msg.Type = train_pc_sim.RECIVE_TRAIN_DOOR_MODE
msg.Data = []byte{0x02}
return msg
}
// 测试创建连接
/*func TestConn(t *testing.T) {
createServer(func(n int, data []byte) {
})
select {}
}*/
func main() {
createServer(func(n int, data []byte) {
msg := &message.TrainPcSimBaseMessage{}
msg.Decode(data)
if msg.Type == train_pc_sim.SENDER_TRAIN_TC_ACTIVE {
fmt.Println("接收驾驶端激活")
} else if msg.Type == train_pc_sim.SENDER_TRAIN_TC_NOT_ACTIVE {
fmt.Println("接收驾驶端未激活")
} else if msg.Type == train_pc_sim.SENDER_TRAIN_OUTR_INFO {
fmt.Println("接受列车输出数字量", msg.Data[0], msg.Data[1])
}
})
//reader := bufio.NewReader(os.Stdin)
var command string
for {
if serConn == nil {
continue
}
fmt.Scanln(&command)
if command != "" {
fmt.Println(command)
}
if command == "create-train" {
msg := connTrain()
serConn.Write(msg.Encode())
} else if command == "door-mode" {
msg := changeDoorMode()
serConn.Write(msg.Encode())
}
command = ""
/*content, _ := reader.ReadString('\n')
if content == "create-train" {
}*/
}
select {}
}

View File

@ -5,6 +5,7 @@ import (
"fmt"
"joylink.club/bj-rtsts-server/config"
"joylink.club/bj-rtsts-server/dto/state_proto"
"joylink.club/bj-rtsts-server/third_party/message"
"joylink.club/bj-rtsts-server/third_party/tcp"
"joylink.club/ecs"
"log/slog"
@ -12,17 +13,31 @@ import (
"time"
)
type TrainControlEvent struct {
Command byte
Status byte
}
var FireTrainControlEventType = ecs.NewEventType[TrainControlEvent]()
type TrainPcSim interface {
Start(pcSimManage TrainPcSimManage)
Start(wd ecs.World, pcSimManage TrainPcSimManage)
Stop()
//发送驾驶端激活
SendDriverActive(tc *state_proto.TrainConnState, vobc *state_proto.TrainVobcState)
//发送牵引制动手柄
SendHandleSwitch(oldTraction, oldBrakeForce int64, tc *state_proto.TrainConnState, vobc *state_proto.TrainVobcState)
//发送应答器信息数据
SendBaliseData(msgType uint16, data []byte)
//发布列车控制的相关事件
PublishTrainControlEvent(world ecs.World, events []TrainControlEvent)
CreateOrRemoveSpeedPLace(train *state_proto.TrainState)
}
type TrainPcSimManage interface {
GetTrainPcSimConfig() config.VehiclePCSimConfig
GetConnTrain() *state_proto.TrainState
//4.4.1. 车载输出数字量信息报文内容
TrainPcSimDigitalOutInfoHandle(data []byte)
//4.4.2. 车载输出数字反馈量信息报文内容
@ -31,8 +46,9 @@ type TrainPcSimManage interface {
TrainPcSimConnOrRemoveHandle(state byte)
//门模式
TrainDoorModeHandle(state byte)
//处理列车pc仿真模拟量数据
TrainPcSimMockInfo(data []byte)
//处理列车btm查询
TrainBtmQuery(data []byte)
}
@ -54,16 +70,17 @@ type trainPcSimService struct {
pcSimClient *tcp.TcpClient
cancleContext context.CancelFunc
trainPcSimManage TrainPcSimManage
speedPlace *message.TrainSpeedPlaceReportMsg
}
func (pc *trainPcSimService) Start(pcSimManage TrainPcSimManage) {
func (pc *trainPcSimService) Start(wd ecs.World, pcSimManage TrainPcSimManage) {
config := pcSimManage.GetTrainPcSimConfig()
if config.PcSimIp == "" || !config.Open {
slog.Info("车载pc仿真配置未开启")
return
}
client, err := tcp.StartTcpClient(fmt.Sprintf("%v%v", config.PcSimIp, config.PcSimPort), pc.reivceData)
client, err := tcp.StartTcpClient(fmt.Sprintf("%v:%v", config.PcSimIp, config.PcSimPort), pc.reivceData)
if err != nil {
slog.Error("连接车载pc平台失败", err)
return
@ -72,8 +89,8 @@ func (pc *trainPcSimService) Start(pcSimManage TrainPcSimManage) {
ctx, ctxFun := context.WithCancel(context.Background())
pc.cancleContext = ctxFun
pc.trainPcSimManage = pcSimManage
//vs := pcSimManage.(*memory.VerifySimulation)
//FireTrainControlEventType.Subscribe(vs.World, pc.trainControlEventHandle)
FireTrainControlEventType.Subscribe(wd, pc.trainControlEventHandle)
go pc.sendTrainLocationAndSpeedTask(ctx)
}
@ -82,7 +99,19 @@ func (pc *trainPcSimService) Stop() {
pc.cancleContext()
pc.cancleContext = nil
}
pc.pcSimClient.Close()
if pc.pcSimClient != nil {
pc.pcSimClient.Close()
}
}
func (pc *trainPcSimService) CreateOrRemoveSpeedPLace(train *state_proto.TrainState) {
if train.ConnState.Conn {
train.PluseCount = &state_proto.SensorSpeedPulseCount{}
pc.speedPlace = &message.TrainSpeedPlaceReportMsg{TrainId: train.Id}
} else {
train.PluseCount = nil
pc.speedPlace = nil
}
}
// 依据文档80ms发送列车速度位置
@ -93,19 +122,31 @@ func (pc *trainPcSimService) sendTrainLocationAndSpeedTask(ctx context.Context)
return
default:
}
/* trainStatus := acc.radarVobcManager.FindAccTrain()
if trainStatus != nil {
speedAcc := trainStatus.DynamicState.Acceleration
t := speedAcc / accSpeedUnit
acc.vobcClient.SendMsg(&message.Accelerometer{Acc: math.Float32bits(t)})
}*/
train := pc.trainPcSimManage.GetConnTrain()
if train != nil && train.ConnState.Conn {
s1, s2 := train.PluseCount.PulseCount1, train.PluseCount.PulseCount2
pc.speedPlace.ParsePulseCount1(s1, s2)
data := pc.speedPlace.Encode(train.RunDirection, s1, s2)
bm := &message.TrainPcSimBaseMessage{Type: SENDER_TRAIN_LOCATION_INFO, Data: data}
train.PluseCount.PulseCount1 = 0
train.PluseCount.PulseCount2 = 0
pc.pcSimClient.Send(bm.Encode())
} else {
m1 := "未找到对应连接车载pc仿真的列车"
if train != nil {
m1 = fmt.Sprintf("对应的列车没有连接上车载pc仿真列车ID%v", train.Id)
}
slog.Info(m1)
}
time.Sleep(time.Millisecond * 80)
}
}
// 发送驾驶激活
func (pc *trainPcSimService) SendDriverActive(tc *state_proto.TrainConnState, vobc *state_proto.TrainVobcState) {
if tc.Conn && tc.ConnType == state_proto.TrainConnState_PC_SIM {
defulatBuf := make([]byte, 0)
msg := &TrainPcSimBaseMessage{Data: defulatBuf}
msg := &message.TrainPcSimBaseMessage{Data: defulatBuf}
if vobc.Tc1Active || vobc.Tc2Active {
msg.Type = SENDER_TRAIN_TC_ACTIVE
} else if vobc.Tc1Active == false && vobc.Tc2Active == false {
@ -116,7 +157,7 @@ func (pc *trainPcSimService) SendDriverActive(tc *state_proto.TrainConnState, vo
}
func (pc *trainPcSimService) SendHandleSwitch(oldTraction, oldBrakeForce int64, tc *state_proto.TrainConnState, vobc *state_proto.TrainVobcState) {
if tc.Conn && tc.ConnType == state_proto.TrainConnState_PC_SIM {
msg := &TrainPcSimBaseMessage{}
msg := &message.TrainPcSimBaseMessage{}
newTraction := vobc.TractionForce
newBrake := vobc.BrakeForce
if newTraction <= oldTraction && newTraction == 0 {
@ -140,14 +181,15 @@ func (pc *trainPcSimService) SendHandleSwitch(oldTraction, oldBrakeForce int64,
}
func (pc *trainPcSimService) SendBaliseData(msgType uint16, data []byte) {
msg := &TrainPcSimBaseMessage{}
msg := &message.TrainPcSimBaseMessage{}
msg.Type = msgType
msg.Data = data
pc.pcSimClient.Send(msg.Encode())
}
func (pc *trainPcSimService) trainControlEventHandle(w ecs.World, event TrainControlEvent) {
msg := &TrainPcSimBaseMessage{}
fmt.Println(event.Status)
msg := &message.TrainPcSimBaseMessage{}
msg.Type = SENDER_TRAIN_OUTR_INFO
data := []byte{event.Command, event.Status}
msg.Data = data
@ -155,7 +197,7 @@ func (pc *trainPcSimService) trainControlEventHandle(w ecs.World, event TrainCon
}
func (pc *trainPcSimService) PublishTrainControlEvent(world ecs.World, events []TrainControlEvent) {
if len(events) <= 0 {
slog.Warn("")
slog.Warn("发布事件数量为空")
return
}
for _, event := range events {
@ -165,7 +207,7 @@ func (pc *trainPcSimService) PublishTrainControlEvent(world ecs.World, events []
// 接受来自pc仿真的消息
func (pc *trainPcSimService) reivceData(len int, data []byte) {
baseMsg := &TrainPcSimBaseMessage{}
baseMsg := &message.TrainPcSimBaseMessage{}
err := baseMsg.Decode(data)
if err != nil {
slog.Error("车载pc仿真接受数据解析失败 ")
@ -174,17 +216,17 @@ func (pc *trainPcSimService) reivceData(len int, data []byte) {
switch baseMsg.Type {
case RECIVE_TRAIN_CREATE_REMOVE:
pc.trainPcSimManage.TrainPcSimConnOrRemoveHandle(data[0])
pc.trainPcSimManage.TrainPcSimConnOrRemoveHandle(baseMsg.Data[0])
case RECIVE_TRAIN_INTERFACE_CABINET_OUTR:
pc.trainPcSimManage.TrainPcSimDigitalOutInfoHandle(data)
pc.trainPcSimManage.TrainPcSimDigitalOutInfoHandle(baseMsg.Data)
case RECIVE_TRAIN_INTERFACE_CABINET_OUTR_BACK:
pc.trainPcSimManage.TrainPcSimDigitalReportHandle(data)
pc.trainPcSimManage.TrainPcSimDigitalReportHandle(baseMsg.Data)
case RECIVE_TRAIN_QUERY_STATUS:
pc.trainPcSimManage.TrainBtmQuery(data)
pc.trainPcSimManage.TrainBtmQuery(baseMsg.Data)
case RECIVE_TRAIN_MOCK_DATA:
pc.trainPcSimManage.TrainPcSimMockInfo(data)
pc.trainPcSimManage.TrainPcSimMockInfo(baseMsg.Data)
case RECIVE_TRAIN_DOOR_MODE:
pc.trainPcSimManage.TrainDoorModeHandle(data[0])
pc.trainPcSimManage.TrainDoorModeHandle(baseMsg.Data[0])
}
}

View File

@ -1,95 +0,0 @@
package train_pc_sim
import (
"bytes"
"encoding/binary"
"fmt"
"github.com/snksoft/crc"
"joylink.club/bj-rtsts-server/third_party/message"
)
const PC_SIM_HEADER = 0xEB
type TrainPcSimBaseMessage struct {
Type uint16
DataLen byte
Data []byte
Crc uint16 // 校验码
}
// 编码
func (tp *TrainPcSimBaseMessage) Encode() []byte {
pack := make([]byte, 0)
pack = append(pack, PC_SIM_HEADER)
pack = binary.BigEndian.AppendUint16(pack, tp.Type)
pack = append(pack, byte(len(tp.Data)))
dataBufs := bytes.NewBuffer(tp.Data)
binary.Write(dataBufs, binary.BigEndian, tp.Data)
data := dataBufs.Bytes()
pack = append(pack, data...)
pack = binary.BigEndian.AppendUint16(pack, uint16(crc.CalculateCRC(crc.CRC16, data)))
return pack
}
// 解码
func (tp *TrainPcSimBaseMessage) Decode(data []byte) error {
if len(data) < 3 {
return fmt.Errorf("")
}
buf := bytes.NewBuffer(data)
h, _ := buf.ReadByte()
if h != PC_SIM_HEADER {
return fmt.Errorf("")
}
var pcType uint16
binary.Read(buf, binary.BigEndian, &pcType)
len, _ := buf.ReadByte()
if buf.Len() < int(len)+2 {
return fmt.Errorf("")
}
var dd = make([]byte, 0, len)
binary.Read(buf, binary.BigEndian, &dd)
var crcCode uint16
binary.Read(buf, binary.BigEndian, &crcCode)
tp.Type = pcType
tp.DataLen = len
tp.Data = dd
tp.Crc = crcCode
return nil
//crc.CalculateCRC(crc.CRC16, data)
}
func IsTrue(d bool) byte {
if d {
return 1
}
return 0
}
func IsTrueForByte(d byte) bool {
if d == 1 {
return true
}
return false
}
// 列车pc仿真btm查询
type TrainPcSimBtmQueryFrame struct {
message.CanetFrame //这里不是用 can 网络的前2帧
}
// func (pc *TrainPcSimBtmQueryFrame) GetCanFrameId() message.CanFrameId {
// return pc.CanId
// }
//
// func (pc *TrainPcSimBtmQueryFrame) GetCanFrameData() []byte {
// return pc.CanData
// }
func (q *TrainPcSimBtmQueryFrame) Decode(d []byte) error {
q.CanId.ID1 = d[0]
q.CanId.ID2 = d[1]
q.CanId.ID3 = d[2]
q.CanId.ID4 = d[3] >> 3
//
q.CanData = d[4:]
return nil
}

View File

@ -1,103 +0,0 @@
package train_pc_sim
import (
"joylink.club/ecs"
)
const (
//钥匙开关状态
KEY_STATE = iota
//手柄向前控制
HANDLE_FORWORD
//手柄向后控制
HANDLE_BACKWORD
//外部紧急制动反馈
OUTER_EMERGENCY_BRAKE
//列车制动状态
TRAIN_BRAKE_STATE
//开左门
LEFT_OPEN_DOOR
//关右门
CLOSE_RIGHT_DOOR
//关左门
CLOSE_LEFT_DOOR
//开右门
OPEN_RIGHT_DOOR
//折返按钮
TURN_BACK
//强制门允许
FORCE_DOOR_ALLOW
//模式降级按钮
TRAIN_MODE_DOWN
//确认按钮
CONFIRM
//模式升级按钮
TRAIN_MODE_UP
//牵引制动手柄零位
HANDLE_TO_ZERO
//ATO发车按钮
ATO_SEND_TRAIN
//列车完整性
TRAIN_INTEGRITY
//车载ATP/ATO旁路状态
ATP_ATO_BYPASS_STATe
//车辆牵引已切除状态
TRAIN_TRACTION_CUTED
//障碍物检测按钮
OBSTACLE_CHECK
//驾驶室激活反馈按钮
DRIVER_ACTIVE_REPORT
//制动重故障按钮
BRAKE_HEAVY_FAULT
//左门状态按钮
LEFT_DOOR_STATE
//右门状态按钮
RIGHT_DOOR_STATE
//唤醒按钮
WAKE_UP
//检修按钮
OVERHAUL
//欠压按钮
UNDERVOLTAGE
//休眠按钮
SLEEP
_
//紧急手柄拉下
EMERGENT_HANDLE_DOWN
//车门锁闭状态
DOOR_LOCK_STATE
//逃生门状态
LIFE_DOOR
//车辆低压上电状态
TRAIN_LOW_POWER
//ATP上电按钮
ATP_POWER_ON
_
//AA自动开关门
DOOR_MODE_AA
//AM自开人关
DOOR_MODE_AM
//MM人开人关
DOOR_MODE_MM
)
type TrainControlEvent struct {
Command byte
Status byte
}
var FireTrainControlEventType = ecs.NewEventType[TrainControlEvent]()
// 应答器组内序号
// 唯一标识组内一个应答器目前固定为1
const PC_SIM_BALISE_NUM uint32 = 1
// 4.3.3. 应答器信息报文内容
type TrainPcSimBtm struct {
BaliseId uint32 //应答器组ID
BaliseLocation float32 //应答器与车头发车位置的距离单位cm
BaliseData []byte //有数据的CAN数据报文
}

View File

@ -6,7 +6,7 @@ const (
//车辆输出数字量信息
SENDER_TRAIN_OUTR_INFO = 0x00
//速度位置信息
sender_train_location_info = 0x01
SENDER_TRAIN_LOCATION_INFO = 0x01
//驾驶室激活
SENDER_TRAIN_TC_ACTIVE = 0x04
//驾驶室未激活

View File

@ -66,9 +66,9 @@ func PublishMapVerifyStructure(graphic *dto.PublishedDto) {
case data_proto.PictureType_IBP:
graphicStorage := message.(*data_proto.IBPGraphicStorage)
giUidMap.Store(graphic.ID, initIBPUid(graphicStorage))
/* case data_proto.PictureType_TrainControlCab:
graphicStorage := message.(*data_proto.TccGraphicStorage)
giUidMap.Store(graphic.ID, initTccUid(graphicStorage))*/
case data_proto.PictureType_TrainControlCab:
graphicStorage := message.(*data_proto.TccGraphicStorage)
giUidMap.Store(graphic.ID, initTccUid(graphicStorage))
}
}

View File

@ -22,11 +22,11 @@ type elementIdStructure struct {
}
// 列车控制
/*type TccUidStructure struct {
type TccUidStructure struct {
ButtonIds map[uint32]*elementIdStructure
Keys map[uint32]*elementIdStructure
Handler map[uint32]*elementIdStructure
}*/
}
// 数组为Index为 common.ButtonCode, index, uid
type StationUidStructure struct {
@ -444,7 +444,7 @@ func fillCkmInfo(ckm *data_proto.GarageDoor, gus *StationUidStructure, city stri
}
// 初始化列车控制
/*func initTccUid(tcc *data_proto.TccGraphicStorage) *TccUidStructure {
func initTccUid(tcc *data_proto.TccGraphicStorage) *TccUidStructure {
tc := &TccUidStructure{ButtonIds: make(map[uint32]*elementIdStructure), Keys: make(map[uint32]*elementIdStructure), Handler: make(map[uint32]*elementIdStructure)}
for _, d := range tcc.TccButtons {
@ -465,7 +465,7 @@ func fillCkmInfo(ckm *data_proto.GarageDoor, gus *StationUidStructure, city stri
}
return tc
}*/
}
// 初始化继电器柜 UID
func initRelayCabinetUid(data *data_proto.RelayCabinetGraphicStorage) *RelayUidStructure {

View File

@ -6,6 +6,7 @@ import (
"joylink.club/bj-rtsts-server/service"
"joylink.club/bj-rtsts-server/third_party/can_btm"
"log/slog"
"math"
"reflect"
"strconv"
"time"
@ -32,6 +33,40 @@ func CreateMsgTrainConfig(trainId int, trainLen int64, configTrainData dto.Confi
StopSign: int(configTrainData.StopSign)}
}
func initTrainTcc(vs *VerifySimulation, runDir bool) *state_proto.TrainControlState {
var tccGI *data_proto.TccGraphicStorage
for _, id := range vs.MapIds {
if QueryGiType(id) == data_proto.PictureType_TrainControlCab {
tccGI = QueryGiData[*data_proto.TccGraphicStorage](id)
break
}
}
tcc := &state_proto.TrainControlState{}
if tccGI != nil {
for _, b := range tccGI.TccButtons {
if b.Code == "JJZD" {
tcc.Ebutton = &state_proto.TrainControlState_EmergentButton{Id: b.Common.Id, Passed: false}
}
}
for _, b := range tccGI.TccHandles {
if b.Code == "QYSB" {
tcc.PushHandler = &state_proto.TrainControlState_PushHandler{Id: b.Common.Id, Val: 0}
}
}
ds := make([]*state_proto.TrainControlState_DriverKeySwitch, 0)
for _, b := range tccGI.TccKeys {
if b.GetType() == data_proto.TccKey_driverControllerActivationClint {
ds = append(ds, &state_proto.TrainControlState_DriverKeySwitch{Id: b.Common.Id, Val: false})
} else if b.GetType() == data_proto.TccKey_frontAndRearDirectionalControl {
tcc.DirKey = &state_proto.TrainControlState_DirectionKeySwitch{Id: b.Common.Id, Val: uint32(message.IsTrue(runDir))}
}
}
tcc.DriverKey = ds
}
return tcc
}
// 增加列车状态
func AddTrainStateNew(vs *VerifySimulation, status *state_proto.TrainState, configTrainData dto.ConfigTrainData, trainEndsA dto.ConfigTrainEnds,
trainEndsB dto.ConfigTrainEnds, mapId int32) *sys_error.BusinessError {
@ -75,7 +110,8 @@ func AddTrainStateNew(vs *VerifySimulation, status *state_proto.TrainState, conf
status.PointTo = pointTo
status.TrainKilometer = kilometer.Value
status.Tcc = &state_proto.TrainControlState{}
//status.Tcc = &state_proto.TrainControlState{}
status.Tcc = initTrainTcc(vs, status.RunDirection)
status.DynamicState = &state_proto.TrainDynamicState{
HeadLinkId: linkId,
HeadLinkOffset: loffset,
@ -89,6 +125,13 @@ func AddTrainStateNew(vs *VerifySimulation, status *state_proto.TrainState, conf
//初始化列车参数状态
createOrUpdateStateDynamicConfig(status, configTrainData, trainEndsA, trainEndsB)
status.VobcState = &state_proto.TrainVobcState{}
if status.RunDirection {
status.VobcState.DirectionForward = true
} else {
status.VobcState.DirectionBackward = true
}
slog.Debug("列车初始化", "trainIndex", trainIndex, "linkId", linkId, "loffset", loffset)
linkIdInt, _ := strconv.Atoi(linkId)
err := dynamics.Default().RequestAddTrain(&message.InitTrainInfo{
@ -124,22 +167,34 @@ func TrainConnTypeUpdate(vs *VerifySimulation, ct *dto.TrainConnThirdDto) {
if !ok {
panic(sys_error.New(fmt.Sprintf("列车【%s】不存在", ct.Id)))
}
train := data.(*state_proto.TrainState)
var conn = true
if ct.ConnType == state_proto.TrainConnState_NONE {
conn = false
}
if conn {
if ct.ConnType != state_proto.TrainConnState_NONE {
//列车连接 半实物或车载pc仿真
allTrainMap.Range(func(k, v any) bool {
tmpTrain := v.(*state_proto.TrainState)
if tmpTrain.ConnState.Conn {
panic(sys_error.New(fmt.Sprintf("列车【%s】已经连接,此列车无法联系", k)))
connTypeName := "半实物"
if tmpTrain.ConnState.ConnType == state_proto.TrainConnState_PC_SIM {
connTypeName = "车载pc仿真"
}
panic(sys_error.New(fmt.Sprintf("列车[%s]已经连接 [%v],此列车无法连接", k, connTypeName)))
return false
}
return true
})
if ct.ConnType == state_proto.TrainConnState_VOBC && conn {
//半实物直接更改连接状态
//车载仿真有创建/删除,列车的操作,通过连接状态区分车载pc是否创建列车
train.ConnState.Conn = true
}
} else {
train.ConnState.Conn = false
}
train := data.(*state_proto.TrainState)
//train.ConnState.Conn = conn
train.ConnState.ConnType = ct.ConnType
}
@ -298,8 +353,35 @@ func UpdateTrainStateByDynamics(vs *VerifySimulation, trainId string, info *mess
sta.DynamicState.TailRadarSpeed = speedParse(info.TailRadarSpeed)
sta.DynamicState.Acceleration = info.Acceleration
sta.DynamicState.Displacement = int32(info.Displacement)
pluseCount(sta)
return sta
}
// 接受动力学时间15毫米
const RECEIVE_DYNAMIC_DATA_RATE = 15
func formatSpeedTime(s int32) int32 {
d3, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", s), 64)
return int32(math.Abs(math.Round(d3)))
}
func pluseCount(sta *state_proto.TrainState) {
if sta.PluseCount == nil {
return
}
if sta.RunDirection {
if sta.TrainEndsA.SpeedSensorEnableA {
sta.PluseCount.PulseCount1 += uint32(formatSpeedTime(sta.DynamicState.HeadSensorSpeed1 * RECEIVE_DYNAMIC_DATA_RATE))
} else if sta.TrainEndsA.SpeedSensorEnableB {
sta.PluseCount.PulseCount2 += uint32(formatSpeedTime(sta.DynamicState.HeadSensorSpeed2 * RECEIVE_DYNAMIC_DATA_RATE))
}
} else {
if sta.TrainEndsB.SpeedSensorEnableA {
sta.PluseCount.PulseCount1 += uint32(formatSpeedTime(sta.DynamicState.TailSensorSpeed1 * RECEIVE_DYNAMIC_DATA_RATE))
} else if sta.TrainEndsB.SpeedSensorEnableB {
sta.PluseCount.PulseCount2 += uint32(formatSpeedTime(sta.DynamicState.TailSensorSpeed2 * RECEIVE_DYNAMIC_DATA_RATE))
}
}
}
func RemoveAllTrain(vs *VerifySimulation) {
allTrainMap := &vs.Memory.Status.TrainStateMap
if allTrainMap == nil {

View File

@ -277,18 +277,11 @@ func (s *VerifySimulation) HandleSectionCmdMsg(city string, lineId string, centr
// 处理动力学列车速度消息
func (s *VerifySimulation) HandleDynamicsTrainInfo(info *message.DynamicsTrainInfo) {
trainId := strconv.Itoa(int(info.Number))
trainData, ok := s.Memory.Status.TrainStateMap.Load(trainId)
_, ok := s.Memory.Status.TrainStateMap.Load(trainId)
if !ok {
return
}
train := trainData.(*state_proto.TrainState)
connType := train.ConnState
//列车连接并且是半实物连接 date 2024-3-15
if connType.Conn && connType.ConnType == state_proto.TrainConnState_VOBC {
// 给半实物仿真发送速度
semi_physical_train.Default().SendTrainControlMessage(info)
}
semi_physical_train.Default().SendTrainControlMessage(info)
// 更新列车状态
trainState := UpdateTrainStateByDynamics(s, trainId, info)
// 更新电机转速
@ -388,13 +381,13 @@ func (s *VerifySimulation) HandleSemiPhysicalTrainControlMsg(b []byte) {
}
connState := train.ConnState
trainId, err := strconv.Atoi(train.Id)
d := append(b, uint8(trainId))
// 发送给动力学,不论列车是否连接三方服务都将数据发送给动力学
dynamics.Default().SendTrainControlMessage(d)
if err != nil {
panic(dto.ErrorDto{Code: dto.ArgumentParseError, Message: err.Error()})
}
if connState.Conn == true && connState.ConnType == state_proto.TrainConnState_VOBC {
d := append(b, uint8(trainId))
// 发送给动力学
dynamics.Default().SendTrainControlMessage(d)
// 存放至列车中
controlMessage := &message.TrainControlMsg{}
controlMessage.Decode(b)

View File

@ -11,6 +11,7 @@ import (
"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/dynamics"
"joylink.club/bj-rtsts-server/third_party/message"
train_pc_sim "joylink.club/bj-rtsts-server/third_party/train_pc_sim"
"log/slog"
@ -36,6 +37,7 @@ func (s *VerifySimulation) ControlTrainUpdate(ct *request_proto.TrainControl) {
} else if ct.ControlType == request_proto.TrainControl_DRIVER_KEY_SWITCH {
tce = trainControlDriverKey(sta, ct.DriverKey, ct.DeviceId)
train_pc_sim.Default().SendDriverActive(sta.ConnState, sta.VobcState)
} else if ct.ControlType == request_proto.TrainControl_DIRECTION_KEY_SWITCH {
trainControlDirKey(sta, ct.DirKey, ct.DeviceId)
} else if ct.ControlType == request_proto.TrainControl_HANDLER {
@ -45,13 +47,15 @@ func (s *VerifySimulation) ControlTrainUpdate(ct *request_proto.TrainControl) {
train_pc_sim.Default().SendHandleSwitch(oldTraction, oldBrakeForce, sta.ConnState, sta.VobcState)
}
if !sta.ConnState.Conn && sta.ConnState.ConnType != state_proto.TrainConnState_PC_SIM {
/* if !sta.ConnState.Conn && sta.ConnState.ConnType != state_proto.TrainConnState_PC_SIM {
slog.Error("当前列车未连接车载pc仿真,", sta.Id)
return
}*/
if sta.ConnState.Conn && sta.ConnState.ConnType == state_proto.TrainConnState_PC_SIM {
train_pc_sim.Default().PublishTrainControlEvent(s.World, tce)
}
train_pc_sim.Default().PublishTrainControlEvent(s.World, tce)
cm := &message.TrainControlMsg{TrainId: ct.TrainId, ControlInfo: sta.VobcState}
dynamics.Default().SendTrainControl(cm)
}
func trainControlEB(trainState *state_proto.TrainState, request *request_proto.TrainControl_EmergentButton, deviceId uint32) {
@ -67,10 +71,15 @@ func trainControlEB(trainState *state_proto.TrainState, request *request_proto.T
func trainControlDirKey(trainState *state_proto.TrainState, request *request_proto.TrainControl_DirectionKeySwitch, deviceId uint32) {
trainState.VobcState.DirectionForward = false
trainState.VobcState.DirectionBackward = false
trainState.RunDirection = false
if request.Val == 1 {
trainState.VobcState.DirectionForward = true
trainState.RunDirection = true
} else if request.Val == 0 {
trainState.VobcState.DirectionBackward = false
trainState.VobcState.DirectionBackward = true
trainState.RunDirection = false
}
if trainState.Tcc.DirKey == nil {
trainState.Tcc.DirKey = &state_proto.TrainControlState_DirectionKeySwitch{Id: deviceId, Val: request.Val}
@ -99,7 +108,7 @@ func trainControlDriverKey(trainState *state_proto.TrainState, request *request_
if addNew {
trainState.Tcc.DriverKey = append(trainState.Tcc.DriverKey, &state_proto.TrainControlState_DriverKeySwitch{Id: deviceId, Val: request.Val})
}
return []train_pc_sim.TrainControlEvent{{Command: train_pc_sim.KEY_STATE, Status: train_pc_sim.IsTrue(request.Val)}}
return []train_pc_sim.TrainControlEvent{{Command: message.KEY_STATE, Status: message.IsTrue(request.Val)}}
}
@ -110,20 +119,20 @@ func trainControlHandle(trainState *state_proto.TrainState, request *request_pro
trainState.VobcState.BrakingStatus = false
trainState.VobcState.BrakeForce = 0
tce := make([]train_pc_sim.TrainControlEvent, 0)
tce = append(tce, train_pc_sim.TrainControlEvent{Command: train_pc_sim.HANDLE_FORWORD, Status: 0})
tce = append(tce, train_pc_sim.TrainControlEvent{Command: train_pc_sim.HANDLE_BACKWORD, Status: 0})
tce = append(tce, train_pc_sim.TrainControlEvent{Command: train_pc_sim.HANDLE_TO_ZERO, Status: 0})
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})
if request.Val > 0 {
trainState.VobcState.TractionStatus = true
trainState.VobcState.TractionForce = int64(request.Val)
tce = append(tce, train_pc_sim.TrainControlEvent{Command: train_pc_sim.HANDLE_FORWORD, Status: 1})
tce = append(tce, train_pc_sim.TrainControlEvent{Command: message.HANDLE_FORWORD, Status: 1})
} else if request.Val < 0 {
trainState.VobcState.BrakingStatus = true
trainState.VobcState.BrakeForce = int64(request.Val)
tce = append(tce, train_pc_sim.TrainControlEvent{Command: train_pc_sim.HANDLE_BACKWORD, Status: 1})
tce = append(tce, train_pc_sim.TrainControlEvent{Command: message.HANDLE_BACKWORD, Status: 1})
} else {
tce = append(tce, train_pc_sim.TrainControlEvent{Command: train_pc_sim.HANDLE_TO_ZERO, Status: 1})
tce = append(tce, train_pc_sim.TrainControlEvent{Command: message.HANDLE_TO_ZERO, Status: 1})
}
if trainState.Tcc.PushHandler == nil {
trainState.Tcc.PushHandler = &state_proto.TrainControlState_PushHandler{Id: deviceId, Val: request.Val}
@ -132,6 +141,10 @@ func trainControlHandle(trainState *state_proto.TrainState, request *request_pro
}
return tce
}
func (s *VerifySimulation) GetConnTrain() *state_proto.TrainState {
return s.findConnTrain(state_proto.TrainConnState_PC_SIM)
}
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 {
@ -200,48 +213,50 @@ func (s *VerifySimulation) TrainPcSimDigitalOutInfoHandle(data []byte) {
brakeQuarantine, _ := buf.ReadByte() //制动隔离
stopNotAllBrake, _ := buf.ReadByte() //停放制动缓解
vobc.TractionSafetyCircuit = train_pc_sim.IsTrueForByte(cutTraction)
vobc.TrainDoorOutLed = train_pc_sim.IsTrueForByte(trainDoorOutLed) //? 说明暂无此属性
vobc.ParkingBrakeStatus = train_pc_sim.IsTrueForByte(stopBrakeAppend)
vobc.EmergencyBrakingStatus = train_pc_sim.IsTrueForByte(emergentBrake)
vobc.LeftDoorOpenCommand = train_pc_sim.IsTrueForByte(leftOpenDoor)
vobc.RightDoorOpenCommand = train_pc_sim.IsTrueForByte(rightOpenDoor)
vobc.RightDoorCloseCommand = train_pc_sim.IsTrueForByte(closeRightDoor)
vobc.AllDoorClose = train_pc_sim.IsTrueForByte(doorAlwaysClosed)
vobc.LocalAtpControl = train_pc_sim.IsTrueForByte(localAtpControl) //?
vobc.Ato = train_pc_sim.IsTrueForByte(atoMode)
vobc.AtoTractionCommandOut = train_pc_sim.IsTrueForByte(atoTractionCommandOut) //?
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 = train_pc_sim.IsTrueForByte(atoTractionCommand1) //?
vobc.AtoTractionCommand2 = train_pc_sim.IsTrueForByte(atoTractionCommand2) //?
vobc.AtoTractionCommand3 = train_pc_sim.IsTrueForByte(atoTractionCommand3) //?
vobc.AtoBrakeCommand = train_pc_sim.IsTrueForByte(atoBrakeCommand) //?
vobc.JumpStatus = train_pc_sim.IsTrueForByte(skipCommand)
vobc.DirectionForward = train_pc_sim.IsTrueForByte(direction1)
vobc.DirectionBackward = train_pc_sim.IsTrueForByte(direction2)
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 = train_pc_sim.IsTrueForByte(atoLazyCommandOut) //?
vobc.SleepBtn = train_pc_sim.IsTrueForByte(sleepCommand)
vobc.WakeUpBtn = train_pc_sim.IsTrueForByte(wakeUpCommand)
vobc.AtoSendTrainBtn = train_pc_sim.IsTrueForByte(toPullTrainLed)
vobc.TurnbackStatus = train_pc_sim.IsTrueForByte(arLightCommand) //?
vobc.AtoAlwaysBrake = train_pc_sim.IsTrueForByte(atoAlwaysBrake) //?
vobc.AtoOpenLeftDoor = train_pc_sim.IsTrueForByte(atoOpenLeftDoor) //?
vobc.AtoOpenRightDoor = train_pc_sim.IsTrueForByte(atoOpenRightDoor) //?
vobc.AtoCloseLeftDoor = train_pc_sim.IsTrueForByte(atoCloseLeftDoor) //?
vobc.Tc1Active = train_pc_sim.IsTrueForByte(ariverActive)
vobc.NoSpeedSigle = train_pc_sim.IsTrueForByte(noSpeedSigle) //?
vobc.Fam = train_pc_sim.IsTrueForByte(famMode)
vobc.Cam = train_pc_sim.IsTrueForByte(camMode)
vobc.TrainStartedLed = train_pc_sim.IsTrueForByte(trainStartedLed) //?
vobc.MostUseBrake = train_pc_sim.IsTrueForByte(mostUseBrake) //? //常用制动
vobc.SplittingOut = train_pc_sim.IsTrueForByte(splittingOut) //? //过分相输出
vobc.ModeRelay = train_pc_sim.IsTrueForByte(modeRelay) //? //模式继电器
vobc.TractionEffective = train_pc_sim.IsTrueForByte(tractionEffective) //? //牵引有效
vobc.BrakeEffective = train_pc_sim.IsTrueForByte(brakeEffective) //? //制动有效
vobc.LifeDoorState = train_pc_sim.IsTrueForByte(lifeDoorUsed) //逃生门使能
vobc.BrakeQuarantine = train_pc_sim.IsTrueForByte(brakeQuarantine) //? //制动隔离
vobc.StopNotAllBrake = train_pc_sim.IsTrueForByte(stopNotAllBrake) //? //停放制动缓解
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) //? //停放制动缓解
cm := &message.TrainControlMsg{TrainId: train.Id, ControlInfo: vobc}
dynamics.Default().SendTrainControl(cm)
}
// 4.4.2. 车载输出数字反馈量信息报文内容
@ -261,9 +276,9 @@ func (s *VerifySimulation) TrainPcSimDigitalReportHandle(data []byte) {
direction1, _ := buf.ReadByte()
direction2, _ := buf.ReadByte()
vobc.Tc1Active = train_pc_sim.IsTrueForByte(localEndAct) //本端驾驶室激活(钥匙)
vobc.DirectionForward = train_pc_sim.IsTrueForByte(direction1) //方向手柄进位
vobc.DirectionBackward = train_pc_sim.IsTrueForByte(direction2) //方向手柄退位
vobc.Tc1Active = message.IsTrueForByte(localEndAct) //本端驾驶室激活(钥匙)
vobc.DirectionForward = message.IsTrueForByte(direction1) //方向手柄进位
vobc.DirectionBackward = message.IsTrueForByte(direction2) //方向手柄退位
}
// 创建/删除列车
@ -279,6 +294,7 @@ func (s *VerifySimulation) TrainPcSimConnOrRemoveHandle(state byte) {
} else {
connState.Conn = false
}
train_pc_sim.Default().CreateOrRemoveSpeedPLace(train)
}
// 门模式

View File

@ -4,6 +4,7 @@ import (
"fmt"
"joylink.club/bj-rtsts-server/third_party/acc"
"joylink.club/bj-rtsts-server/third_party/radar"
"joylink.club/bj-rtsts-server/third_party/train_pc_sim"
"log/slog"
"runtime"
"strconv"
@ -136,7 +137,7 @@ func runThirdParty(s *memory.VerifySimulation) error {
radar.Default().Start(s)
//列车加速计发送vobc
acc.Default().Start(s)
//train_pc_sim.Default().Start(s)
train_pc_sim.Default().Start(s.World, s)
return nil
}
@ -162,6 +163,8 @@ func stopThirdParty(s *memory.VerifySimulation) {
radar.Default().Stop()
// 加速计服务停止
acc.Default().Stop()
//列车PC仿真停止
train_pc_sim.Default().Stop()
}
func createSimulationId(projectId int32) string {