Merge branch 'develop' into local-test
This commit is contained in:
commit
c919c59b49
@ -14,6 +14,9 @@
|
||||
- viper 配置管理
|
||||
- swagger 文档生成(基于[swaggo](https://github.com/swaggo/swag))(需要安装 go install github.com/swaggo/swag/cmd/swag@latest,在项目根目录(即 bj-rtsts-server-go)执行 swag init,然后启动项目即可,启动后访问 http://{ip}:{port}/swagger/index.html)
|
||||
|
||||
# 动力学
|
||||
- dotnet.exe publish -r win-x64 -p:PublishSingleFile=true
|
||||
|
||||
# 开发说明
|
||||
|
||||
- 在 api 目录下添加路由及请求数据解析返回
|
||||
|
@ -72,7 +72,8 @@ type ThridPartyConfig struct {
|
||||
CidcModbus []CidcModbusConfig `json:"cidcModbus" description:"联锁驱采Modbus接口配置"`
|
||||
Radar RadarConfig `json:"radar" description:"车载雷达相关配置"`
|
||||
Acc AccConfig `json:"acc" description:"车载加速计"`
|
||||
PcSimConfig VehiclePCSimConfig `json:"pcSimConfig" description:"车载pc仿真平台通信"`
|
||||
//PcSimConfig VehiclePCSimConfig `json:"pcSimConfig" description:"车载pc仿真平台通信"`
|
||||
PcSimConfigs []VehiclePCSimConfig `json:"pcSimConfigs" description:"车载pc仿真平台通信"`
|
||||
}
|
||||
type RadarConfig struct {
|
||||
Open bool `json:"open" description:"是否开启"`
|
||||
@ -170,8 +171,16 @@ type RsspConfig struct {
|
||||
RemoteUdpPort int `json:"remoteUdpPort" description:"远程服务器端口"` //远程服务器端口
|
||||
LocalUdpPort int `json:"localUdpPort" description:"本地服务器端口"` //本地服务器端口
|
||||
}
|
||||
type VehiclePCSimConfig2 struct {
|
||||
TrainEnds bool `json:"trainEnds" description:"列车端点A"`
|
||||
Open bool `json:"open" description:"是否开启"`
|
||||
PcSimIp string `json:"pcSimIp" description:"pc仿真平台通信ip"`
|
||||
PcSimPort uint32 `json:"pcSimPort" description:"pc仿真平台通信端口"`
|
||||
LocalTestingPort uint32 `json:"localTestingPort" description:"本地测试端口"`
|
||||
}
|
||||
|
||||
type VehiclePCSimConfig struct {
|
||||
TrainEnds bool `json:"trainEnds" description:"列车端点A?"`
|
||||
Open bool `json:"open" description:"是否开启"`
|
||||
PcSimIp string `json:"pcSimIp" description:"pc仿真平台通信ip"`
|
||||
PcSimPort uint32 `json:"pcSimPort" description:"pc仿真平台通信端口"`
|
||||
|
4
third_party/interlock/beijing12/interlock.go
vendored
4
third_party/interlock/beijing12/interlock.go
vendored
@ -79,7 +79,7 @@ func (i *interlockProxy) Start(manager InterlockMessageManager) {
|
||||
}
|
||||
|
||||
// 采集电路状态发送间隔,单位ms
|
||||
const InterlockMessageSendInterval = 50
|
||||
const InterlockMessageSendInterval = 300
|
||||
|
||||
// 序列号
|
||||
var serialNumber uint8
|
||||
@ -106,7 +106,7 @@ func (i *interlockProxy) collectInfoStateTask(ctx context.Context) {
|
||||
if err != nil {
|
||||
slog.Error("向联锁发送继电器状态失败:", err)
|
||||
} else {
|
||||
slog.Error(fmt.Sprintf("向联锁发送继电器数据成功:%x", collectInfoState.Encode()))
|
||||
slog.Info(fmt.Sprintf("向联锁发送继电器数据成功:%x", collectInfoState.Encode()))
|
||||
}
|
||||
}
|
||||
time.Sleep(time.Millisecond * InterlockMessageSendInterval)
|
||||
|
25
third_party/tcp/tcp_client.go
vendored
25
third_party/tcp/tcp_client.go
vendored
@ -9,12 +9,14 @@ import (
|
||||
)
|
||||
|
||||
type TcpClient struct {
|
||||
conn *net.TCPConn
|
||||
handler func(n int, data []byte)
|
||||
ctx context.CancelFunc
|
||||
conn *net.TCPConn
|
||||
handler func(n int, data []byte)
|
||||
ctx context.CancelFunc
|
||||
conning bool
|
||||
properties map[string]interface{}
|
||||
}
|
||||
|
||||
func StartTcpClient(rAddr string, handler func(n int, data []byte), readErr func(err error)) (*TcpClient, error) {
|
||||
func StartTcpClient(rAddr string, properties map[string]interface{}, handler func(n int, data []byte, clientProperties map[string]interface{}), readErr func(err error)) (*TcpClient, error) {
|
||||
raddr, addErr := net.ResolveTCPAddr("tcp", rAddr)
|
||||
if addErr != nil {
|
||||
return nil, addErr
|
||||
@ -25,6 +27,7 @@ func StartTcpClient(rAddr string, handler func(n int, data []byte), readErr func
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client := &TcpClient{conn: conn, ctx: ctxFun, properties: properties}
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
@ -37,17 +40,21 @@ func StartTcpClient(rAddr string, handler func(n int, data []byte), readErr func
|
||||
if err != nil {
|
||||
if opErr, ok := err.(*net.OpError); ok {
|
||||
slog.Error(fmt.Sprintf("TCP客户端[rAddr:%s]读取数据异常连接可能断开:", rAddr), opErr)
|
||||
client.conning = false
|
||||
readErr(err)
|
||||
}
|
||||
if err == io.EOF {
|
||||
slog.Warn(fmt.Sprintf("TCP客户端[rAddr:%s]断开连接:", rAddr))
|
||||
client.conning = false
|
||||
readErr(err)
|
||||
}
|
||||
}
|
||||
handler(l, data)
|
||||
client.conning = true
|
||||
handler(l, data, client.properties)
|
||||
}
|
||||
}()
|
||||
return &TcpClient{conn: conn, ctx: ctxFun}, nil
|
||||
client.conning = true
|
||||
return client, nil
|
||||
}
|
||||
func (c *TcpClient) Close() {
|
||||
if c != nil && c.conn != nil {
|
||||
@ -57,6 +64,12 @@ func (c *TcpClient) Close() {
|
||||
c.conn = nil
|
||||
}
|
||||
}
|
||||
func (c *TcpClient) IsConning() bool {
|
||||
if c != nil && c.conn != nil {
|
||||
return c.conning
|
||||
}
|
||||
return false
|
||||
}
|
||||
func (c *TcpClient) Send(data []byte) error {
|
||||
|
||||
if c == nil || c.conn == nil {
|
||||
|
281
third_party/train_pc_sim/train_pc_sim.go
vendored
281
third_party/train_pc_sim/train_pc_sim.go
vendored
@ -8,9 +8,7 @@ import (
|
||||
"joylink.club/bj-rtsts-server/third_party/message"
|
||||
"joylink.club/bj-rtsts-server/third_party/tcp"
|
||||
"joylink.club/bj-rtsts-server/third_party/tpapi"
|
||||
"joylink.club/ecs"
|
||||
"log/slog"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
@ -20,47 +18,57 @@ type TrainControlEvent struct {
|
||||
Status byte
|
||||
}
|
||||
|
||||
var FireTrainControlEventType = ecs.NewEventType[TrainControlEvent]()
|
||||
//var FireTrainControlEventType = ecs.NewEventType[TrainControlEvent]()
|
||||
|
||||
type TrainPcSim interface {
|
||||
tpapi.ThirdPartyApiService
|
||||
Start(pcSimManage TrainPcSimManage)
|
||||
Stop()
|
||||
// SendDriverActive 发送驾驶端激活
|
||||
SendDriverActive(tc *state_proto.TrainConnState, vobc *state_proto.TrainVobcState)
|
||||
SendDriverActive(train *state_proto.TrainState)
|
||||
// SendHandleSwitch 发送牵引制动手柄
|
||||
SendHandleSwitch(oldTraction, oldBrakeForce int64, tractionState bool, tc *state_proto.TrainConnState, vobc *state_proto.TrainVobcState)
|
||||
SendHandleSwitch(oldTraction, oldBrakeForce int64, tractionState bool, train *state_proto.TrainState)
|
||||
// SendTrainDirection 列车运行方向
|
||||
//因文档说明不清楚,在调用的时候目前是注释状态,现场调试可能会用到
|
||||
SendTrainDirection(trainForward, trainBackward bool)
|
||||
SendTrainDirection(train *state_proto.TrainState, trainForward, trainBackward bool)
|
||||
//发送应答器信息数据
|
||||
SendBaliseData(msgType uint16, data []byte)
|
||||
SendBaliseData(train *state_proto.TrainState, msgType uint16, data []byte)
|
||||
//发布列车控制的相关事件
|
||||
PublishTrainControlEvent(events []TrainControlEvent)
|
||||
PublishTrainControlEvent(train *state_proto.TrainState, events []TrainControlEvent)
|
||||
// CreateOrRemoveSpeedPLace 创建或删除速度位置信息
|
||||
CreateOrRemoveSpeedPLace(train *state_proto.TrainState)
|
||||
// CreateOrRemoveTrain 创建或删除列车
|
||||
CreateOrRemoveTrain(msgType byte, data []byte) error
|
||||
CreateOrRemoveTrain(train *state_proto.TrainState, msgType byte, data []byte) error
|
||||
}
|
||||
|
||||
type TrainPcSimManage interface {
|
||||
GetTrainPcSimConfig() config.VehiclePCSimConfig
|
||||
GetConnTrain() *state_proto.TrainState
|
||||
GetTrainPcSimConfig() []config.VehiclePCSimConfig
|
||||
//GetConnTrain() *state_proto.TrainState
|
||||
GetConnTrain2() []*state_proto.TrainState
|
||||
// TrainPcSimDigitalOutInfoHandle 4.4.1. 车载输出数字量信息报文内容
|
||||
TrainPcSimDigitalOutInfoHandle(data []byte)
|
||||
TrainPcSimDigitalOutInfoHandle(connType state_proto.TrainConnState_TrainConnType, data []byte)
|
||||
// TrainPcSimDigitalReportHandle 4.4.2. 车载输出数字反馈量信息报文内容
|
||||
TrainPcSimDigitalReportHandle(data []byte)
|
||||
TrainPcSimDigitalReportHandle(connType state_proto.TrainConnState_TrainConnType, data []byte)
|
||||
|
||||
// TrainPcSimMockInfo 门模式
|
||||
//TrainDoorModeHandle(state byte)
|
||||
//处理列车pc仿真模拟量数据
|
||||
TrainPcSimMockInfo(data []byte)
|
||||
TrainPcSimMockInfo(connType state_proto.TrainConnState_TrainConnType, data []byte)
|
||||
// TrainBtmQuery 处理列车btm查询
|
||||
TrainBtmQuery(data []byte)
|
||||
TrainBtmQuery(connType state_proto.TrainConnState_TrainConnType, data []byte)
|
||||
}
|
||||
|
||||
const Name = "车载pc仿真"
|
||||
const CLIENT_KEY = "clientKey"
|
||||
|
||||
func FindTrainPcSimClientKey(t *state_proto.TrainState) string {
|
||||
if t.ConnState.ConnType == state_proto.TrainConnState_PC_SIM_A {
|
||||
return "A"
|
||||
} else if t.ConnState.ConnType == state_proto.TrainConnState_PC_SIM_B {
|
||||
return "B"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
func (d *trainPcSimService) Name() string {
|
||||
return Name
|
||||
}
|
||||
@ -86,80 +94,149 @@ func Default() TrainPcSim {
|
||||
}
|
||||
|
||||
type trainPcSimService struct {
|
||||
state tpapi.ThirdPartyApiServiceState
|
||||
pcSimClient *tcp.TcpClient
|
||||
state tpapi.ThirdPartyApiServiceState
|
||||
//pcSimClient *tcp.TcpClient
|
||||
pcSimClientMap map[string]*tcp.TcpClient
|
||||
cancleContext context.CancelFunc
|
||||
trainPcSimManage TrainPcSimManage
|
||||
speedPlace *message.TrainSpeedPlaceReportMsg
|
||||
config config.VehiclePCSimConfig
|
||||
configs []config.VehiclePCSimConfig
|
||||
}
|
||||
|
||||
// 接受来自pc仿真的消息
|
||||
func (d *trainPcSimService) readError(err error) {
|
||||
slog.Error("连接车载pc仿真tcp服务断开", err)
|
||||
d.updateState(tpapi.ThirdPartyState_Broken)
|
||||
d.pcSimClient.Close()
|
||||
d.connTrainPcSim()
|
||||
|
||||
}
|
||||
func (d *trainPcSimService) connTrainPcSim() {
|
||||
reconnIndex := 0
|
||||
ctx, ctxFun := context.WithCancel(context.Background())
|
||||
|
||||
func (d *trainPcSimService) closeAllConn() {
|
||||
for key, client := range d.pcSimClientMap {
|
||||
if client != nil {
|
||||
client.Close()
|
||||
}
|
||||
delete(d.pcSimClientMap, key)
|
||||
}
|
||||
|
||||
}
|
||||
func (d *trainPcSimService) closeConn(clientKey string) {
|
||||
if d.pcSimClientMap[clientKey] != nil {
|
||||
d.pcSimClientMap[clientKey].Close()
|
||||
delete(d.pcSimClientMap, clientKey)
|
||||
}
|
||||
}
|
||||
func (d *trainPcSimService) findConfig(tcChar string) (*config.VehiclePCSimConfig, error) {
|
||||
configFlag := false
|
||||
if tcChar == "A" {
|
||||
configFlag = true
|
||||
} else if tcChar == "B" {
|
||||
configFlag = false
|
||||
} else {
|
||||
return nil, fmt.Errorf("")
|
||||
}
|
||||
for _, config := range d.configs {
|
||||
if config.Open && config.TrainEnds == configFlag {
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
}
|
||||
return nil, fmt.Errorf("")
|
||||
}
|
||||
func (d *trainPcSimService) connTrainPcSim(ctx context.Context) {
|
||||
//reconnIndex := 0
|
||||
//ctx, ctxFun := context.WithCancel(context.Background())
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
d.closeAllConn()
|
||||
return
|
||||
default:
|
||||
}
|
||||
d.pcSimClient.Close()
|
||||
client, err := tcp.StartTcpClient(fmt.Sprintf("%v:%v", d.config.PcSimIp, d.config.PcSimPort), d.reivceData, d.readError)
|
||||
if err != nil {
|
||||
reconnIndex++
|
||||
d.updateState(tpapi.ThirdPartyState_Broken)
|
||||
if reconnIndex%10 == 0 {
|
||||
slog.Error("连接车载pc平台失败,尝试=", strconv.Itoa(reconnIndex), err)
|
||||
trains := d.trainPcSimManage.GetConnTrain2()
|
||||
if len(trains) > 0 {
|
||||
for _, t := range trains {
|
||||
clientKey := FindTrainPcSimClientKey(t)
|
||||
if clientKey == "" {
|
||||
slog.Error("未找到对应的pc仿真连接,trainId:", t.Id, "删除对应客户端")
|
||||
d.closeConn(clientKey)
|
||||
continue
|
||||
}
|
||||
|
||||
client := d.pcSimClientMap[clientKey]
|
||||
if !client.IsConning() {
|
||||
client.Close()
|
||||
d.initConn(clientKey)
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
d.pcSimClient = client
|
||||
ctxFun()
|
||||
return
|
||||
}
|
||||
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}()
|
||||
|
||||
}
|
||||
|
||||
func (d *trainPcSimService) initConn(clientKey string) {
|
||||
|
||||
client := d.pcSimClientMap[clientKey]
|
||||
if d.pcSimClientMap[clientKey] == nil {
|
||||
client = &tcp.TcpClient{}
|
||||
d.pcSimClientMap[clientKey] = client
|
||||
}
|
||||
config, _ := d.findConfig(clientKey)
|
||||
addr := fmt.Sprintf("%v:%v", config.PcSimIp, config.PcSimPort)
|
||||
properties := map[string]interface{}{
|
||||
CLIENT_KEY: clientKey,
|
||||
}
|
||||
fmt.Println(properties[CLIENT_KEY])
|
||||
client2, err := tcp.StartTcpClient(addr, properties, d.reivceData, d.readError)
|
||||
if err != nil {
|
||||
d.updateState(tpapi.ThirdPartyState_Broken)
|
||||
|
||||
} else {
|
||||
d.pcSimClientMap[clientKey] = client2
|
||||
}
|
||||
}
|
||||
func (d *trainPcSimService) Start(pcSimManage TrainPcSimManage) {
|
||||
config := pcSimManage.GetTrainPcSimConfig()
|
||||
if config.PcSimIp == "" || !config.Open {
|
||||
configs := pcSimManage.GetTrainPcSimConfig()
|
||||
d.pcSimClientMap = map[string]*tcp.TcpClient{}
|
||||
if len(configs) <= 0 {
|
||||
slog.Info("车载pc仿真配置未开启")
|
||||
return
|
||||
}
|
||||
d.config = config
|
||||
d.connTrainPcSim()
|
||||
allClosed := true
|
||||
for _, c := range configs {
|
||||
if !c.Open {
|
||||
allClosed = false
|
||||
}
|
||||
}
|
||||
if !allClosed {
|
||||
slog.Info("车载pc仿真配置未开启")
|
||||
return
|
||||
}
|
||||
|
||||
d.configs = configs
|
||||
ctx, ctxFun := context.WithCancel(context.Background())
|
||||
d.cancleContext = ctxFun
|
||||
d.trainPcSimManage = pcSimManage
|
||||
d.connTrainPcSim(ctx)
|
||||
|
||||
//FireTrainControlEventType.Subscribe(wd, d.trainControlEventHandle)
|
||||
d.updateState(tpapi.ThirdPartyState_Normal)
|
||||
go d.sendTrainLocationAndSpeedTask(ctx)
|
||||
|
||||
}
|
||||
func (d *trainPcSimService) Stop() {
|
||||
d.updateState(tpapi.ThirdPartyState_Closed)
|
||||
if d.cancleContext != nil {
|
||||
d.cancleContext()
|
||||
|
||||
d.cancleContext = nil
|
||||
}
|
||||
if d.pcSimClient != nil {
|
||||
//d.pcSimClient.
|
||||
d.pcSimClient.Close()
|
||||
}
|
||||
d.closeAllConn()
|
||||
}
|
||||
func (d *trainPcSimService) CreateOrRemoveSpeedPLace(train *state_proto.TrainState) {
|
||||
if train.ConnState.Conn {
|
||||
if train.ConnState.Conn && (train.ConnState.ConnType == state_proto.TrainConnState_PC_SIM_A || train.ConnState.ConnType == state_proto.TrainConnState_PC_SIM_B) {
|
||||
train.PluseCount = &state_proto.SensorSpeedPulseCount{}
|
||||
d.speedPlace = &message.TrainSpeedPlaceReportMsg{TrainId: train.Id}
|
||||
} else {
|
||||
@ -167,10 +244,20 @@ func (d *trainPcSimService) CreateOrRemoveSpeedPLace(train *state_proto.TrainSta
|
||||
d.speedPlace = nil
|
||||
}
|
||||
}
|
||||
func (d *trainPcSimService) CreateOrRemoveTrain(msgType byte, data []byte) error {
|
||||
msg := &message.TrainPcSimBaseMessage{Data: data, Type: uint16(msgType)}
|
||||
return d.pcSimClient.Send(msg.Encode())
|
||||
func (d *trainPcSimService) CreateOrRemoveTrain(train *state_proto.TrainState, msgType byte, data []byte) error {
|
||||
clientKey := FindTrainPcSimClientKey(train)
|
||||
if msgType == RECIVE_TRAIN_CREATE_REMOVE && data[0] == 0x01 {
|
||||
d.initConn(clientKey)
|
||||
}
|
||||
|
||||
msg := &message.TrainPcSimBaseMessage{Data: data, Type: uint16(msgType)}
|
||||
client := d.pcSimClientMap[clientKey]
|
||||
err := client.Send(msg.Encode())
|
||||
if data[0] != 0x01 {
|
||||
d.closeConn(clientKey)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// 依据文档80ms发送列车速度位置
|
||||
@ -181,36 +268,57 @@ func (d *trainPcSimService) sendTrainLocationAndSpeedTask(ctx context.Context) {
|
||||
return
|
||||
default:
|
||||
}
|
||||
train := d.trainPcSimManage.GetConnTrain()
|
||||
if train != nil && train.ConnState.Conn && train.PluseCount != nil {
|
||||
trains := d.trainPcSimManage.GetConnTrain2()
|
||||
for _, train := range trains {
|
||||
if train.ConnState.Conn && train.PluseCount != nil {
|
||||
clientKey := FindTrainPcSimClientKey(train)
|
||||
|
||||
client := d.pcSimClientMap[clientKey]
|
||||
s1, s2 := train.PluseCount.PulseCount1, train.PluseCount.PulseCount2
|
||||
d.speedPlace.ParsePulseCount1(s1, s2)
|
||||
data := d.speedPlace.Encode(train.TrainRunUp, s1, s2)
|
||||
bm := &message.TrainPcSimBaseMessage{Type: SENDER_TRAIN_LOCATION_INFO, Data: data}
|
||||
train.PluseCount.PulseCount1 = 0
|
||||
train.PluseCount.PulseCount2 = 0
|
||||
client.Send(bm.Encode())
|
||||
}
|
||||
|
||||
s1, s2 := train.PluseCount.PulseCount1, train.PluseCount.PulseCount2
|
||||
d.speedPlace.ParsePulseCount1(s1, s2)
|
||||
data := d.speedPlace.Encode(train.TrainRunUp, s1, s2)
|
||||
bm := &message.TrainPcSimBaseMessage{Type: SENDER_TRAIN_LOCATION_INFO, Data: data}
|
||||
train.PluseCount.PulseCount1 = 0
|
||||
train.PluseCount.PulseCount2 = 0
|
||||
d.pcSimClient.Send(bm.Encode())
|
||||
}
|
||||
|
||||
time.Sleep(time.Millisecond * 80)
|
||||
}
|
||||
}
|
||||
|
||||
// 发送驾驶激活
|
||||
func (d *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 {
|
||||
func (d *trainPcSimService) SendDriverActive(train *state_proto.TrainState) {
|
||||
vobc := train.VobcState
|
||||
|
||||
clientKey := FindTrainPcSimClientKey(train)
|
||||
client := d.pcSimClientMap[clientKey]
|
||||
defulatBuf := make([]byte, 0)
|
||||
msg := &message.TrainPcSimBaseMessage{Data: defulatBuf}
|
||||
if train.TrainRunUp {
|
||||
if vobc.Tc1Active {
|
||||
msg.Type = SENDER_TRAIN_TC_ACTIVE
|
||||
} else if vobc.Tc1Active == false && vobc.Tc2Active == false {
|
||||
} else if vobc.Tc1Active == false {
|
||||
msg.Type = SENDER_TRAIN_TC_NOT_ACTIVE
|
||||
}
|
||||
} else if !train.TrainRunUp {
|
||||
if vobc.Tc2Active {
|
||||
msg.Type = SENDER_TRAIN_TC_ACTIVE
|
||||
} else if vobc.Tc2Active == false {
|
||||
msg.Type = SENDER_TRAIN_TC_NOT_ACTIVE
|
||||
}
|
||||
d.pcSimClient.Send(msg.Encode())
|
||||
}
|
||||
|
||||
client.Send(msg.Encode())
|
||||
}
|
||||
func (d *trainPcSimService) SendHandleSwitch(oldTraction, oldBrakeForce int64, tractionState bool, tc *state_proto.TrainConnState, vobc *state_proto.TrainVobcState) {
|
||||
if tc.Conn && tc.ConnType == state_proto.TrainConnState_PC_SIM {
|
||||
func (d *trainPcSimService) SendHandleSwitch(oldTraction, oldBrakeForce int64, tractionState bool, train *state_proto.TrainState) {
|
||||
tc := train.ConnState
|
||||
if tc.Conn {
|
||||
vobc := train.VobcState
|
||||
clientKey := FindTrainPcSimClientKey(train)
|
||||
client := d.pcSimClientMap[clientKey]
|
||||
msg := &message.TrainPcSimBaseMessage{}
|
||||
newTraction := vobc.TractionForce
|
||||
newBrake := -vobc.BrakeForce
|
||||
@ -239,10 +347,10 @@ func (d *trainPcSimService) SendHandleSwitch(oldTraction, oldBrakeForce int64, t
|
||||
msg.Type = RECIVE_TRAIN_HAND_KEY_BACKWARD
|
||||
}
|
||||
}
|
||||
d.pcSimClient.Send(msg.Encode())
|
||||
client.Send(msg.Encode())
|
||||
}
|
||||
}
|
||||
func (d *trainPcSimService) SendTrainDirection(trainForward, trainBackward bool) {
|
||||
func (d *trainPcSimService) SendTrainDirection(train *state_proto.TrainState, trainForward, trainBackward bool) {
|
||||
|
||||
baseMsgs := make([]*message.TrainPcSimBaseMessage, 0)
|
||||
if !trainForward && !trainBackward {
|
||||
@ -253,18 +361,22 @@ func (d *trainPcSimService) SendTrainDirection(trainForward, trainBackward bool)
|
||||
} else if trainBackward {
|
||||
baseMsgs = append(baseMsgs, &message.TrainPcSimBaseMessage{Type: RECIVE_TRAIN_HAND_KEY_BACKWARD})
|
||||
}
|
||||
clientKey := FindTrainPcSimClientKey(train)
|
||||
client := d.pcSimClientMap[clientKey]
|
||||
for _, msg := range baseMsgs {
|
||||
d.pcSimClient.Send(msg.Encode())
|
||||
client.Send(msg.Encode())
|
||||
}
|
||||
}
|
||||
|
||||
func (d *trainPcSimService) SendBaliseData(msgType uint16, data []byte) {
|
||||
func (d *trainPcSimService) SendBaliseData(train *state_proto.TrainState, msgType uint16, data []byte) {
|
||||
msg := &message.TrainPcSimBaseMessage{}
|
||||
msg.Type = msgType
|
||||
msg.Data = data
|
||||
clientKey := FindTrainPcSimClientKey(train)
|
||||
client := d.pcSimClientMap[clientKey]
|
||||
//fmt.Println(fmt.Sprintf("%X", msg.Encode()))
|
||||
|
||||
d.pcSimClient.Send(msg.Encode())
|
||||
client.Send(msg.Encode())
|
||||
}
|
||||
|
||||
/*
|
||||
@ -276,24 +388,37 @@ func (d *trainPcSimService) SendBaliseData(msgType uint16, data []byte) {
|
||||
d.pcSimClient.Send(msg.Encode())
|
||||
}
|
||||
*/
|
||||
func (d *trainPcSimService) PublishTrainControlEvent(events []TrainControlEvent) {
|
||||
func (d *trainPcSimService) PublishTrainControlEvent(train *state_proto.TrainState, events []TrainControlEvent) {
|
||||
if len(events) <= 0 {
|
||||
slog.Warn("发布事件数量为空")
|
||||
return
|
||||
}
|
||||
clientKey := FindTrainPcSimClientKey(train)
|
||||
client := d.pcSimClientMap[clientKey]
|
||||
for _, event := range events {
|
||||
msg := &message.TrainPcSimBaseMessage{}
|
||||
msg.Type = SENDER_TRAIN_OUTR_INFO
|
||||
data := []byte{event.Command, event.Status}
|
||||
msg.Data = data
|
||||
d.pcSimClient.Send(msg.Encode())
|
||||
client.Send(msg.Encode())
|
||||
//FireTrainControlEventType.Publish(world, &event)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 接受来自pc仿真的消息
|
||||
func (d *trainPcSimService) reivceData(len int, data []byte) {
|
||||
func (d *trainPcSimService) reivceData(len int, data []byte, properties map[string]interface{}) {
|
||||
clientKey := properties[CLIENT_KEY]
|
||||
ck := fmt.Sprintf("%v", clientKey)
|
||||
if d.pcSimClientMap[ck] == nil {
|
||||
slog.Error(fmt.Sprintf("不存在%v的客户端,数据解析不予处理", ck))
|
||||
return
|
||||
}
|
||||
|
||||
connType := state_proto.TrainConnState_PC_SIM_A
|
||||
if clientKey == "B" {
|
||||
connType = state_proto.TrainConnState_PC_SIM_B
|
||||
}
|
||||
baseMsg := &message.TrainPcSimBaseMessage{}
|
||||
err := baseMsg.Decode(data)
|
||||
if err != nil {
|
||||
@ -305,13 +430,13 @@ func (d *trainPcSimService) reivceData(len int, data []byte) {
|
||||
//case RECIVE_TRAIN_CREATE_REMOVE:
|
||||
// pc.trainPcSimManage.TrainPcSimConnOrRemoveHandle(baseMsg.Data[0])
|
||||
case RECIVE_TRAIN_INTERFACE_CABINET_OUTR:
|
||||
d.trainPcSimManage.TrainPcSimDigitalOutInfoHandle(baseMsg.Data)
|
||||
d.trainPcSimManage.TrainPcSimDigitalOutInfoHandle(connType, baseMsg.Data)
|
||||
case RECIVE_TRAIN_INTERFACE_CABINET_OUTR_BACK:
|
||||
d.trainPcSimManage.TrainPcSimDigitalReportHandle(baseMsg.Data)
|
||||
d.trainPcSimManage.TrainPcSimDigitalReportHandle(connType, baseMsg.Data)
|
||||
case RECIVE_TRAIN_QUERY_STATUS:
|
||||
d.trainPcSimManage.TrainBtmQuery(baseMsg.Data)
|
||||
d.trainPcSimManage.TrainBtmQuery(connType, baseMsg.Data)
|
||||
case RECIVE_TRAIN_MOCK_DATA:
|
||||
d.trainPcSimManage.TrainPcSimMockInfo(baseMsg.Data)
|
||||
d.trainPcSimManage.TrainPcSimMockInfo(connType, baseMsg.Data)
|
||||
//case RECIVE_TRAIN_DOOR_MODE:
|
||||
// pc.trainPcSimManage.TrainDoorModeHandle(baseMsg.Data[0])
|
||||
}
|
||||
|
@ -151,8 +151,10 @@ func TrainConnTypeUpdate(vs *VerifySimulation, ct *dto.TrainConnThirdDto) {
|
||||
tmpTrain := v.(*state_proto.TrainState)
|
||||
if tmpTrain.ConnState.Conn {
|
||||
connTypeName := "半实物"
|
||||
if tmpTrain.ConnState.ConnType == state_proto.TrainConnState_PC_SIM {
|
||||
connTypeName = "车载pc仿真"
|
||||
if tmpTrain.ConnState.ConnType == state_proto.TrainConnState_PC_SIM_A {
|
||||
connTypeName = "车载pc仿真-A"
|
||||
} else if tmpTrain.ConnState.ConnType == state_proto.TrainConnState_PC_SIM_A {
|
||||
connTypeName = "车载pc仿真-B"
|
||||
}
|
||||
panic(sys_error.New(fmt.Sprintf("列车[%s]已经连接 [%v],此列车无法连接", k, connTypeName)))
|
||||
return false
|
||||
@ -162,14 +164,14 @@ func TrainConnTypeUpdate(vs *VerifySimulation, ct *dto.TrainConnThirdDto) {
|
||||
}
|
||||
train.ConnState.Conn = true
|
||||
train.ConnState.ConnType = ct.ConnType
|
||||
if ct.ConnType == state_proto.TrainConnState_PC_SIM {
|
||||
if ct.ConnType == state_proto.TrainConnState_PC_SIM_A || ct.ConnType == state_proto.TrainConnState_PC_SIM_B {
|
||||
err := TrainPcSimConnOrRemoveHandle(train)
|
||||
if err != nil {
|
||||
train.ConnState.Conn = false
|
||||
train.ConnState.ConnType = state_proto.TrainConnState_NONE
|
||||
panic(sys_error.New(err.Error()))
|
||||
}
|
||||
train_pc_sim.Default().SendDriverActive(train.ConnState, train.VobcState)
|
||||
train_pc_sim.Default().SendDriverActive(train)
|
||||
}
|
||||
|
||||
}
|
||||
@ -184,8 +186,8 @@ func TrainUnConn(vs *VerifySimulation, trainId string) {
|
||||
train := data.(*state_proto.TrainState)
|
||||
oldType := train.ConnState.ConnType
|
||||
train.ConnState.Conn = false
|
||||
train.ConnState.ConnType = state_proto.TrainConnState_NONE
|
||||
if oldType == state_proto.TrainConnState_PC_SIM {
|
||||
//train.ConnState.ConnType = state_proto.TrainConnState_NONE
|
||||
if oldType == state_proto.TrainConnState_PC_SIM_A || oldType == state_proto.TrainConnState_PC_SIM_B {
|
||||
err := TrainPcSimConnOrRemoveHandle(train)
|
||||
if err != nil {
|
||||
panic(sys_error.New("未连接车载PC仿真,无法断开连接"))
|
||||
|
@ -494,14 +494,25 @@ func (s *VerifySimulation) CollectInterlockRelayInfo(code string) *message.Inter
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获取列车可用连接半实物类型
|
||||
func (s *VerifySimulation) FindTrainConnTypes() []dto.TrainConnTypeConfigDto {
|
||||
typeConfig := make([]dto.TrainConnTypeConfigDto, 0)
|
||||
if s.runConfig.Vobc.Open /*&& s.runConfig.Vobc.Ip != ""*/ {
|
||||
typeConfig = append(typeConfig, dto.TrainConnTypeConfigDto{ConnType: state_proto.TrainConnState_VOBC})
|
||||
}
|
||||
if s.runConfig.PcSimConfig.Open /*&& s.runConfig.PcSimConfig.PcSimIp != ""*/ {
|
||||
typeConfig = append(typeConfig, dto.TrainConnTypeConfigDto{ConnType: state_proto.TrainConnState_PC_SIM})
|
||||
|
||||
for _, pcSim := range s.runConfig.PcSimConfigs {
|
||||
dto := dto.TrainConnTypeConfigDto{ConnType: state_proto.TrainConnState_PC_SIM_A}
|
||||
if !pcSim.TrainEnds {
|
||||
dd := &dto
|
||||
dd.ConnType = state_proto.TrainConnState_PC_SIM_B
|
||||
}
|
||||
typeConfig = append(typeConfig, dto)
|
||||
}
|
||||
/* if s.runConfig.PcSimConfig.Open {
|
||||
typeConfig = append(typeConfig, dto.TrainConnTypeConfigDto{ConnType: state_proto.TrainConnState_PC_SIM})
|
||||
}*/
|
||||
return typeConfig
|
||||
}
|
||||
|
||||
|
@ -18,8 +18,8 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func (s *VerifySimulation) GetTrainPcSimConfig() config.VehiclePCSimConfig {
|
||||
return s.runConfig.PcSimConfig
|
||||
func (s *VerifySimulation) GetTrainPcSimConfig() []config.VehiclePCSimConfig {
|
||||
return s.runConfig.PcSimConfigs
|
||||
}
|
||||
|
||||
// 列车控制
|
||||
@ -42,7 +42,7 @@ func ControlTrainUpdate(s *VerifySimulation, ct *request_proto.TrainControl) {
|
||||
tce = trainControlEB(vobc, tcc, ct.Button, ct.DeviceId, tccGraphicData)
|
||||
} else if ct.ControlType == request_proto.TrainControl_DRIVER_KEY_SWITCH {
|
||||
tce = trainControlDriverKey(sta, ct.DriverKey, ct.DeviceId, tccGraphicData)
|
||||
train_pc_sim.Default().SendDriverActive(sta.ConnState, sta.VobcState)
|
||||
train_pc_sim.Default().SendDriverActive(sta)
|
||||
} else if ct.ControlType == request_proto.TrainControl_DIRECTION_KEY_SWITCH {
|
||||
tce = trainControlDirKey(sta.DynamicState.Speed, vobc, tcc, ct.DirKey, ct.DeviceId, tccGraphicData)
|
||||
//此处先注释,根据现场调试情况 2024-4-16
|
||||
@ -52,7 +52,7 @@ func ControlTrainUpdate(s *VerifySimulation, ct *request_proto.TrainControl) {
|
||||
oldBrakeForce := sta.VobcState.BrakeForce
|
||||
isTraction := ct.Handler.Val > 0 //是否制动
|
||||
tce = trainControlHandle(vobc, tcc, ct.Handler, ct.DeviceId, tccGraphicData)
|
||||
train_pc_sim.Default().SendHandleSwitch(oldTraction, oldBrakeForce, isTraction, sta.ConnState, sta.VobcState)
|
||||
train_pc_sim.Default().SendHandleSwitch(oldTraction, oldBrakeForce, isTraction, sta)
|
||||
}
|
||||
|
||||
if !vobc.DirectionForward && !vobc.DirectionBackward {
|
||||
@ -62,8 +62,8 @@ func ControlTrainUpdate(s *VerifySimulation, ct *request_proto.TrainControl) {
|
||||
if vobc.EmergencyBrakingStatus {
|
||||
vobc.TractionForce = 0
|
||||
}
|
||||
if sta.ConnState.Conn && sta.ConnState.ConnType == state_proto.TrainConnState_PC_SIM && tce != nil {
|
||||
train_pc_sim.Default().PublishTrainControlEvent(tce)
|
||||
if sta.ConnState.Conn && (sta.ConnState.ConnType == state_proto.TrainConnState_PC_SIM_A || sta.ConnState.ConnType == state_proto.TrainConnState_PC_SIM_B) && tce != nil {
|
||||
train_pc_sim.Default().PublishTrainControlEvent(sta, tce)
|
||||
}
|
||||
}
|
||||
|
||||
@ -226,8 +226,27 @@ func trainControlHandle(vobc *state_proto.TrainVobcState, tcc *state_proto.Train
|
||||
return tce
|
||||
}
|
||||
|
||||
func (s *VerifySimulation) GetConnTrain() *state_proto.TrainState {
|
||||
/*func (s *VerifySimulation) GetConnTrain() *state_proto.TrainState {
|
||||
return s.findConnTrain(state_proto.TrainConnState_PC_SIM)
|
||||
}*/
|
||||
|
||||
func (s *VerifySimulation) GetConnTrain2() []*state_proto.TrainState {
|
||||
return s.findConnTrain2(state_proto.TrainConnState_PC_SIM_A, state_proto.TrainConnState_PC_SIM_B)
|
||||
}
|
||||
|
||||
func (s *VerifySimulation) findConnTrain2(ct1, ct2 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
|
||||
if connState.ConnType == ct1 || connState.ConnType == ct2 {
|
||||
trains = append(trains, train)
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
return trains
|
||||
}
|
||||
func (s *VerifySimulation) findConnTrain(ct state_proto.TrainConnState_TrainConnType) *state_proto.TrainState {
|
||||
var findTrain *state_proto.TrainState
|
||||
@ -244,8 +263,8 @@ func (s *VerifySimulation) findConnTrain(ct state_proto.TrainConnState_TrainConn
|
||||
}
|
||||
|
||||
// 4.4.1. 车载输出数字量信息报文内容
|
||||
func (s *VerifySimulation) TrainPcSimDigitalOutInfoHandle(data []byte) {
|
||||
train := s.findConnTrain(state_proto.TrainConnState_PC_SIM)
|
||||
func (s *VerifySimulation) TrainPcSimDigitalOutInfoHandle(connType state_proto.TrainConnState_TrainConnType, data []byte) {
|
||||
train := s.findConnTrain(connType)
|
||||
if train == nil {
|
||||
slog.Error("车载输出数字量,未找到连接车载pc仿真的列车")
|
||||
return
|
||||
@ -407,8 +426,8 @@ func trainPcSimDigitalOutInfoHandleCode7_0(d byte, vobc *state_proto.TrainVobcSt
|
||||
}
|
||||
|
||||
// 4.4.2. 车载输出数字反馈量信息报文内容
|
||||
func (s *VerifySimulation) TrainPcSimDigitalReportHandle(data []byte) {
|
||||
train := s.findConnTrain(state_proto.TrainConnState_PC_SIM)
|
||||
func (s *VerifySimulation) TrainPcSimDigitalReportHandle(connType state_proto.TrainConnState_TrainConnType, data []byte) {
|
||||
train := s.findConnTrain(connType)
|
||||
if train == nil {
|
||||
slog.Error("车载输出数字反馈量信息,未找到连接车载pc仿真的列车")
|
||||
return
|
||||
@ -439,8 +458,9 @@ func TrainPcSimConnOrRemoveHandle(train *state_proto.TrainState) error {
|
||||
if train.ConnState.Conn == false {
|
||||
data = 0x00
|
||||
}
|
||||
if train.ConnState.ConnType == state_proto.TrainConnState_PC_SIM {
|
||||
crErr := train_pc_sim.Default().CreateOrRemoveTrain(train_pc_sim.RECIVE_TRAIN_CREATE_REMOVE, []byte{data})
|
||||
if train.ConnState.ConnType == state_proto.TrainConnState_PC_SIM_A || train.ConnState.ConnType == state_proto.TrainConnState_PC_SIM_B {
|
||||
|
||||
crErr := train_pc_sim.Default().CreateOrRemoveTrain(train, train_pc_sim.RECIVE_TRAIN_CREATE_REMOVE, []byte{data})
|
||||
if crErr != nil {
|
||||
return crErr
|
||||
}
|
||||
@ -469,8 +489,8 @@ func TrainPcSimConnOrRemoveHandle(train *state_proto.TrainState) error {
|
||||
}*/
|
||||
|
||||
// 4.4.3. 车载输出模拟量信息报文内容(0x03)
|
||||
func (s *VerifySimulation) TrainPcSimMockInfo(data []byte) {
|
||||
train := s.findConnTrain(state_proto.TrainConnState_PC_SIM)
|
||||
func (s *VerifySimulation) TrainPcSimMockInfo(connType state_proto.TrainConnState_TrainConnType, data []byte) {
|
||||
train := s.findConnTrain(connType)
|
||||
if train == nil {
|
||||
slog.Error("车载输出模拟量,未找到连接车载pc仿真的列车")
|
||||
return
|
||||
@ -484,12 +504,12 @@ func (s *VerifySimulation) TrainPcSimMockInfo(data []byte) {
|
||||
}
|
||||
|
||||
// 4.4.4. 车载输出BTM查询同步帧报文内容(0x04)
|
||||
func (s *VerifySimulation) TrainBtmQuery(data []byte) {
|
||||
func (s *VerifySimulation) TrainBtmQuery(connType state_proto.TrainConnState_TrainConnType, data []byte) {
|
||||
if len(data) < 12 {
|
||||
slog.Error("列车btm查询报文长度错误:", len(data))
|
||||
return
|
||||
}
|
||||
train := s.findConnTrain(state_proto.TrainConnState_PC_SIM)
|
||||
train := s.findConnTrain(connType)
|
||||
if train == nil {
|
||||
slog.Error("车载输出btm查询,未找到连接车载pc仿真的列车")
|
||||
return
|
||||
@ -511,7 +531,7 @@ func (s *VerifySimulation) TrainBtmQuery(data []byte) {
|
||||
//重新发送
|
||||
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)
|
||||
train_pc_sim.Default().SendBaliseData(train, train_pc_sim.RECIVE_TRAIN_BTM_HAS_DATA, dd)
|
||||
}
|
||||
} else {
|
||||
timeSyncF := message.NewBtmTimeSyncCheckFrame(trainAtm.CanId.ID4, true)
|
||||
@ -523,7 +543,7 @@ func (s *VerifySimulation) TrainBtmQuery(data []byte) {
|
||||
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)
|
||||
train_pc_sim.Default().SendBaliseData(train, train_pc_sim.RECIVE_TRAIN_BTM_NOT_DATA, queryData)
|
||||
} else {
|
||||
//有数据
|
||||
aliseData, _ := hex.DecodeString(train.BtmState.Telegram)
|
||||
@ -534,7 +554,7 @@ func (s *VerifySimulation) TrainBtmQuery(data []byte) {
|
||||
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)
|
||||
train_pc_sim.Default().SendBaliseData(train, train_pc_sim.RECIVE_TRAIN_BTM_HAS_DATA, queryData)
|
||||
} else {
|
||||
slog.Error("列车pc仿真 BtmCanetClient应答帧、数据帧编码失败")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user