rts-sim-testing-service/third_party/train_pc_sim/train_pc_sim.go
tiger_zhou 7de95e55f2
All checks were successful
local-test分支打包构建docker并发布运行 / Docker-Build (push) Successful in 1m35s
列车pc仿真测试调整
2024-04-09 08:55:33 +08:00

233 lines
6.9 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/message"
"joylink.club/bj-rtsts-server/third_party/tcp"
"joylink.club/ecs"
"log/slog"
"sync"
"time"
)
type TrainControlEvent struct {
Command byte
Status byte
}
var FireTrainControlEventType = ecs.NewEventType[TrainControlEvent]()
type TrainPcSim interface {
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. 车载输出数字反馈量信息报文内容
TrainPcSimDigitalReportHandle(data []byte)
//创建/删除列车
TrainPcSimConnOrRemoveHandle(state byte)
//门模式
TrainDoorModeHandle(state byte)
//处理列车pc仿真模拟量数据
TrainPcSimMockInfo(data []byte)
//处理列车btm查询
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
speedPlace *message.TrainSpeedPlaceReportMsg
}
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)
if err != nil {
slog.Error("连接车载pc平台失败", err)
return
}
pc.pcSimClient = client
ctx, ctxFun := context.WithCancel(context.Background())
pc.cancleContext = ctxFun
pc.trainPcSimManage = pcSimManage
FireTrainControlEventType.Subscribe(wd, pc.trainControlEventHandle)
go pc.sendTrainLocationAndSpeedTask(ctx)
}
func (pc *trainPcSimService) Stop() {
if pc.cancleContext != nil {
pc.cancleContext()
pc.cancleContext = nil
}
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发送列车速度位置
func (pc *trainPcSimService) sendTrainLocationAndSpeedTask(ctx context.Context) {
for {
select {
case <-ctx.Done():
return
default:
}
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 := &message.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 := &message.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 := &message.TrainPcSimBaseMessage{}
msg.Type = msgType
msg.Data = data
pc.pcSimClient.Send(msg.Encode())
}
func (pc *trainPcSimService) trainControlEventHandle(w ecs.World, event TrainControlEvent) {
fmt.Println(event.Status)
msg := &message.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 := &message.TrainPcSimBaseMessage{}
err := baseMsg.Decode(data)
if err != nil {
slog.Error("车载pc仿真接受数据解析失败 ")
return
}
switch baseMsg.Type {
case RECIVE_TRAIN_CREATE_REMOVE:
pc.trainPcSimManage.TrainPcSimConnOrRemoveHandle(baseMsg.Data[0])
case RECIVE_TRAIN_INTERFACE_CABINET_OUTR:
pc.trainPcSimManage.TrainPcSimDigitalOutInfoHandle(baseMsg.Data)
case RECIVE_TRAIN_INTERFACE_CABINET_OUTR_BACK:
pc.trainPcSimManage.TrainPcSimDigitalReportHandle(baseMsg.Data)
case RECIVE_TRAIN_QUERY_STATUS:
pc.trainPcSimManage.TrainBtmQuery(baseMsg.Data)
case RECIVE_TRAIN_MOCK_DATA:
pc.trainPcSimManage.TrainPcSimMockInfo(baseMsg.Data)
case RECIVE_TRAIN_DOOR_MODE:
pc.trainPcSimManage.TrainDoorModeHandle(baseMsg.Data[0])
}
}