rts-sim-testing-service/third_party/train_pc_sim/train_pc_sim.go
2024-04-02 18:20:10 +08:00

192 lines
5.6 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 train_pc_sim
import (
"context"
"fmt"
"joylink.club/bj-rtsts-server/config"
"joylink.club/bj-rtsts-server/dto/state_proto"
"joylink.club/bj-rtsts-server/third_party/tcp"
"joylink.club/bj-rtsts-server/ts/simulation/wayside/memory"
"joylink.club/ecs"
"log/slog"
"sync"
"time"
)
type TrainPcSim interface {
Start(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)
}
type TrainPcSimManage interface {
GetTrainPcSimConfig() config.VehiclePCSimConfig
//4.4.1. 车载输出数字量信息报文内容
TrainPcSimDigitalOutInfoHandle(data []byte)
//4.4.2. 车载输出数字反馈量信息报文内容
TrainPcSimDigitalReportHandle(data []byte)
//创建/删除列车
TrainPcSimConnOrRemoveHandle(state byte)
//门模式
TrainDoorModeHandle(state byte)
TrainPcSimMockInfo(data []byte)
TrainBtmQuery(data []byte)
}
var (
initLock = &sync.Mutex{}
singleObj *trainPcSimService
)
func Default() TrainPcSim {
defer initLock.Unlock()
initLock.Lock()
if singleObj == nil {
singleObj = &trainPcSimService{}
}
return singleObj
}
type trainPcSimService struct {
pcSimClient *tcp.TcpClient
cancleContext context.CancelFunc
trainPcSimManage TrainPcSimManage
}
func (pc *trainPcSimService) Start(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)
if err != nil {
slog.Error("连接车载pc平台失败", err)
return
}
pc.pcSimClient = client
ctx, ctxFun := context.WithCancel(context.Background())
pc.cancleContext = ctxFun
pc.trainPcSimManage = pcSimManage
vs := pcSimManage.(*memory.VerifySimulation)
FireTrainControlEventType.Subscribe(vs.World, pc.trainControlEventHandle)
go pc.sendTrainLocationAndSpeedTask(ctx)
}
func (pc *trainPcSimService) Stop() {
if pc.cancleContext != nil {
pc.cancleContext()
pc.cancleContext = nil
}
pc.pcSimClient.Close()
}
// 依据文档80ms发送列车速度位置
func (pc *trainPcSimService) sendTrainLocationAndSpeedTask(ctx context.Context) {
for {
select {
case <-ctx.Done():
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)})
}*/
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}
if vobc.Tc1Active || vobc.Tc2Active {
msg.Type = SENDER_TRAIN_TC_ACTIVE
} else if vobc.Tc1Active == false && vobc.Tc2Active == false {
msg.Type = SENDER_TRAIN_TC_NOT_ACTIVE
}
pc.pcSimClient.Send(msg.Encode())
}
}
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{}
newTraction := vobc.TractionForce
newBrake := vobc.BrakeForce
if newTraction <= oldTraction && newTraction == 0 {
//手柄取消前进
msg.Type = RECIVE_TRAIN_HAND_KEY_CANCLE_FORWARD
} else if newTraction > oldTraction {
//手柄前进
msg.Type = SENDER_TRAIN_HAND_KEY_FORWARD
} else if newBrake >= oldBrakeForce && newBrake == 0 {
//手柄取消后退
msg.Type = RECIVE_TRAIN_HAND_KEY_CACLE_BACKWARD
} else if newBrake < oldBrakeForce {
//手柄后退
msg.Type = RECIVE_TRAIN_HAND_KEY_BACKWARD
} else {
slog.Error("")
return
}
pc.pcSimClient.Send(msg.Encode())
}
}
func (pc *trainPcSimService) SendBaliseData(msgType uint16, data []byte) {
msg := &TrainPcSimBaseMessage{}
msg.Type = msgType
msg.Data = data
pc.pcSimClient.Send(msg.Encode())
}
func (pc *trainPcSimService) trainControlEventHandle(w ecs.World, event TrainControlEvent) {
msg := &TrainPcSimBaseMessage{}
msg.Type = SENDER_TRAIN_OUTR_INFO
data := []byte{event.Command, event.Status}
msg.Data = data
pc.pcSimClient.Send(msg.Encode())
}
func (pc *trainPcSimService) PublishTrainControlEvent(world ecs.World, events []TrainControlEvent) {
if len(events) <= 0 {
slog.Warn("")
return
}
for _, event := range events {
FireTrainControlEventType.Publish(world, &event)
}
}
// 接受来自pc仿真的消息
func (pc *trainPcSimService) reivceData(len int, data []byte) {
baseMsg := &TrainPcSimBaseMessage{}
err := baseMsg.Decode(data)
if err != nil {
slog.Error("车载pc仿真接受数据解析失败 ")
return
}
switch baseMsg.Type {
case RECIVE_TRAIN_CREATE_REMOVE:
pc.trainPcSimManage.TrainPcSimConnOrRemoveHandle(data[0])
case RECIVE_TRAIN_INTERFACE_CABINET_OUTR:
pc.trainPcSimManage.TrainPcSimDigitalOutInfoHandle(data)
case RECIVE_TRAIN_INTERFACE_CABINET_OUTR_BACK:
pc.trainPcSimManage.TrainPcSimDigitalReportHandle(data)
case RECIVE_TRAIN_QUERY_STATUS:
pc.trainPcSimManage.TrainBtmQuery(data)
case RECIVE_TRAIN_MOCK_DATA:
pc.trainPcSimManage.TrainPcSimMockInfo(data)
case RECIVE_TRAIN_DOOR_MODE:
pc.trainPcSimManage.TrainDoorModeHandle(data[0])
}
}