From 6b5932c617b46cc168b65f41ae86ac3ee85f90ae Mon Sep 17 00:00:00 2001 From: tiger_zhou Date: Fri, 24 May 2024 09:00:43 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=97=E8=BD=A6pc=E4=BB=BF=E7=9C=9F=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E6=94=AF=E6=8C=81=E5=A4=9A=E4=B8=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 + config/config.go | 11 +- rts-sim-testing-message | 2 +- third_party/tcp/tcp_client.go | 25 +- third_party/train_pc_sim/train_pc_sim.go | 281 +++++++++++++----- .../wayside/memory/wayside_memory_train.go | 14 +- .../wayside/memory/wayside_simulation.go | 15 +- .../memory/wayside_simulation_train_pc.go | 60 ++-- 8 files changed, 297 insertions(+), 114 deletions(-) diff --git a/README.md b/README.md index 4e326a9..d6ceb7f 100644 --- a/README.md +++ b/README.md @@ -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 目录下添加路由及请求数据解析返回 diff --git a/config/config.go b/config/config.go index 9133f18..73c9a22 100644 --- a/config/config.go +++ b/config/config.go @@ -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仿真平台通信端口"` diff --git a/rts-sim-testing-message b/rts-sim-testing-message index aac1484..189cabe 160000 --- a/rts-sim-testing-message +++ b/rts-sim-testing-message @@ -1 +1 @@ -Subproject commit aac1484a6f64cc43146cabd89784b92c933a0298 +Subproject commit 189cabea725167f98c15d0971ee20d01b044ce05 diff --git a/third_party/tcp/tcp_client.go b/third_party/tcp/tcp_client.go index ef55d4a..dacc61b 100644 --- a/third_party/tcp/tcp_client.go +++ b/third_party/tcp/tcp_client.go @@ -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 { diff --git a/third_party/train_pc_sim/train_pc_sim.go b/third_party/train_pc_sim/train_pc_sim.go index 0ce20e0..2c9bfe1 100644 --- a/third_party/train_pc_sim/train_pc_sim.go +++ b/third_party/train_pc_sim/train_pc_sim.go @@ -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]) } diff --git a/ts/simulation/wayside/memory/wayside_memory_train.go b/ts/simulation/wayside/memory/wayside_memory_train.go index 0d6fe89..cd48588 100644 --- a/ts/simulation/wayside/memory/wayside_memory_train.go +++ b/ts/simulation/wayside/memory/wayside_memory_train.go @@ -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仿真,无法断开连接")) diff --git a/ts/simulation/wayside/memory/wayside_simulation.go b/ts/simulation/wayside/memory/wayside_simulation.go index e68790e..2f633d1 100644 --- a/ts/simulation/wayside/memory/wayside_simulation.go +++ b/ts/simulation/wayside/memory/wayside_simulation.go @@ -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 } diff --git a/ts/simulation/wayside/memory/wayside_simulation_train_pc.go b/ts/simulation/wayside/memory/wayside_simulation_train_pc.go index bf6594f..ad5efd4 100644 --- a/ts/simulation/wayside/memory/wayside_simulation_train_pc.go +++ b/ts/simulation/wayside/memory/wayside_simulation_train_pc.go @@ -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应答帧、数据帧编码失败") }