Merge branch 'develop' into local-test
All checks were successful
local-test分支打包构建docker并发布运行 / Docker-Build (push) Successful in 1m38s

# Conflicts:
#	third_party/interlock/beijing12/interlock.go
This commit is contained in:
tiger_zhou 2024-06-13 14:17:17 +08:00
commit 081581140e
16 changed files with 435 additions and 219 deletions

View File

@ -190,11 +190,11 @@ type VehiclePCSimConfig2 struct {
}
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仿真平台通信端口"`
LocalTestingPort uint32 `json:"localTestingPort" description:"本地测试端口"`
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:"本地测试端口"`
}
// CheckAddress 检测目标源地址目的地址是否在配置中

View File

@ -5403,8 +5403,8 @@ type LianSuoIndexData struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` // 设备id
Index int32 `protobuf:"varint,2,opt,name=index,proto3" json:"index,omitempty"` //设备联锁编号
Id uint32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` // 设备id
Index uint32 `protobuf:"varint,2,opt,name=index,proto3" json:"index,omitempty"` //设备联锁编号
}
func (x *LianSuoIndexData) Reset() {
@ -5439,14 +5439,14 @@ func (*LianSuoIndexData) Descriptor() ([]byte, []int) {
return file_stationLayoutGraphics_proto_rawDescGZIP(), []int{54}
}
func (x *LianSuoIndexData) GetId() int32 {
func (x *LianSuoIndexData) GetId() uint32 {
if x != nil {
return x.Id
}
return 0
}
func (x *LianSuoIndexData) GetIndex() int32 {
func (x *LianSuoIndexData) GetIndex() uint32 {
if x != nil {
return x.Index
}
@ -6661,8 +6661,8 @@ var file_stationLayoutGraphics_proto_rawDesc = []byte{
0x12, 0x10, 0x0a, 0x03, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x03, 0x69,
0x64, 0x73, 0x22, 0x38, 0x0a, 0x10, 0x4c, 0x69, 0x61, 0x6e, 0x53, 0x75, 0x6f, 0x49, 0x6e, 0x64,
0x65, 0x78, 0x44, 0x61, 0x74, 0x61, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18,
0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x83, 0x06, 0x0a,
0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18,
0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x83, 0x06, 0x0a,
0x0b, 0x4c, 0x69, 0x61, 0x6e, 0x53, 0x75, 0x6f, 0x44, 0x61, 0x74, 0x61, 0x12, 0x39, 0x0a, 0x08,
0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d,
0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x4c, 0x69, 0x61,

View File

@ -20,7 +20,7 @@ var (
func main() {
//先安装以下插件
//go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
//go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.33.0
protoFiles := getProtoFiles()
// 编译proto文件为Go文件

@ -1 +1 @@
Subproject commit c1499de7bb6e41b56f53c982d516da30988fbd44
Subproject commit 0844608c8674ec2988c06ba61e73e7b6afe7d660

View File

@ -8,7 +8,6 @@ import (
"joylink.club/rtsssimulation/fi"
"joylink.club/rtsssimulation/repository"
"joylink.club/rtsssimulation/repository/model/proto"
"log/slog"
"math"
"sort"
"sync"
@ -72,7 +71,7 @@ func (t *BaliseDetector) tryRebind(th *TrainHeadPositionInfo) {
t.clearExpectedBalise()
t.baliseCounter = 0
t.messageCounter = 0
slog.Debug(fmt.Sprintf("列车[%s]与CAN-BTM绑定", t.trianId))
//slog.Debug(fmt.Sprintf("列车[%s]与CAN-BTM绑定", t.trianId))
}
}

View File

@ -1,63 +0,0 @@
// Package beijing11 北京11号线联锁通信
package beijing11
import (
"encoding/json"
"fmt"
"joylink.club/bj-rtsts-server/config"
"joylink.club/bj-rtsts-server/third_party/udp"
"log/slog"
"sync"
)
var (
initMutex = sync.Mutex{}
logTag = "[北京11号线联锁通信]"
running = false
server udp.UdpServer
)
func Start(interlockConfig *config.InterlockConfig) {
if interlockConfig == nil || interlockConfig.Ip == "" || !interlockConfig.Open {
return
}
if running {
return
}
initMutex.Lock()
defer initMutex.Unlock()
if running {
return
}
//UDP通信设施
server = udp.NewServer(fmt.Sprintf(":%d", interlockConfig.LocalPort), func(b []byte) {
slog.Info(fmt.Sprintf("%s收到消息%x", logTag, b))
frame := &FromInterlockFrame{}
err := frame.Decode(b)
if err != nil {
slog.Error(fmt.Sprintf("%s解析数据出错%s", logTag, err))
} else {
marshal, err := json.Marshal(frame)
if err != nil {
slog.Error(fmt.Sprintf("%s解析为json出错%s", logTag, err))
} else {
slog.Info(fmt.Sprintf("%s解析为json%s", logTag, string(marshal)))
}
}
})
err := server.Listen()
if err != nil {
panic(fmt.Sprintf("%s启动UDP服务失败%s", logTag, err))
}
running = true
}
func Stop() {
initMutex.Lock()
defer initMutex.Unlock()
running = false
if server != nil {
server.Close()
server = nil
}
}

34
third_party/interlock/beijing11/repo.go vendored Normal file
View File

@ -0,0 +1,34 @@
package beijing11
// StationDeviceIndexRepo 联锁站设备索引映射
type StationDeviceIndexRepo struct {
StationName string
TurnoutMap map[uint32]string
PsdMap map[uint32]string
EsbMap map[uint32]string
HoldTrainMap map[uint32]string
SignalMap map[uint32]string
AxleSectionMap map[uint32]string
WrzfMap map[uint32]string
FymMap map[uint32]string
SpksMap map[uint32]string
CkmMap map[uint32]string
XcjMap map[uint32]string
}
func NewStationDeviceIndexRepo() *StationDeviceIndexRepo {
return &StationDeviceIndexRepo{
StationName: "",
TurnoutMap: make(map[uint32]string),
PsdMap: make(map[uint32]string),
EsbMap: make(map[uint32]string),
HoldTrainMap: make(map[uint32]string),
SignalMap: make(map[uint32]string),
AxleSectionMap: make(map[uint32]string),
WrzfMap: make(map[uint32]string),
FymMap: make(map[uint32]string),
SpksMap: make(map[uint32]string),
CkmMap: make(map[uint32]string),
XcjMap: make(map[uint32]string),
}
}

View File

@ -0,0 +1,107 @@
// Package beijing11 北京11号线联锁通信
package beijing11
import (
"encoding/json"
"fmt"
"joylink.club/bj-rtsts-server/config"
"joylink.club/bj-rtsts-server/dto/data_proto"
"joylink.club/bj-rtsts-server/third_party/udp"
"joylink.club/bj-rtsts-server/ts/simulation/wayside/memory"
"log/slog"
"sync"
)
const logTag = "[北京11号线联锁通信]"
var (
initMutex = sync.Mutex{}
running = false
server udp.UdpServer
sim *memory.VerifySimulation //启动服务所使用的仿真
iConfig *config.InterlockConfig //启动服务使用的联锁配置
//联锁区设备的联锁编号与uid的映射
stationMap map[string]*StationDeviceIndexRepo
)
func init() {
memory.RegisterListener(func(uidStructure *memory.StationUidStructure, data *data_proto.RtssGraphicStorage) {
//if data.LianSuoData == nil {
// return
//}
////初始化所有集中站设备映射结构体
//for _, station := range data.Stations {
// stationMap[station.StationName] = NewStationDeviceIndexRepo()
//}
////填充
//stationIdMap := uidStructure.StationIds
////道岔
//turnoutUidMap := uidStructure.TurnoutIds
//turnoutIndexMap := make(map[uint32]uint32)
//for _, turnout := range data.LianSuoData.Switchs {
// turnoutIndexMap[turnout.Id] =
//}
//for _, turnout := range data.Turnouts {
// for _, stationCid := range turnout.CentralizedStations {
// stationIdStruct := stationIdMap[stationCid]
// stationDeviceIndexRepo := stationMap[stationIdStruct.Code]
// stationDeviceIndexRepo.TurnoutMap[]
// }
//}
})
}
func Start(interlockConfig *config.InterlockConfig, simulation *memory.VerifySimulation) {
if interlockConfig == nil || interlockConfig.Ip == "" || !interlockConfig.Open {
return
}
if running {
return
}
initMutex.Lock()
defer initMutex.Unlock()
if running {
return
}
//UDP通信设施
server = udp.NewServer(fmt.Sprintf(":%d", interlockConfig.LocalPort), func(b []byte) {
slog.Info(fmt.Sprintf("%s收到消息%x", logTag, b))
frame := &FromInterlockFrame{}
err := frame.Decode(b)
if err != nil {
slog.Error(fmt.Sprintf("%s解析数据出错%s", logTag, err))
} else {
marshal, err := json.Marshal(frame)
if err != nil {
slog.Error(fmt.Sprintf("%s解析为json出错%s", logTag, err))
} else {
slog.Info(fmt.Sprintf("%s解析为json%s", logTag, string(marshal)))
}
}
})
err := server.Listen()
if err != nil {
panic(fmt.Sprintf("%s启动UDP服务失败%s", logTag, err))
}
running = true
sim = simulation
iConfig = interlockConfig
}
func Stop() {
initMutex.Lock()
defer initMutex.Unlock()
running = false
if server != nil {
server.Close()
server = nil
}
}
//func CollectRelayInfo() *FromInterlockFrame {
// sim.World
//}
//
//func HandleDriveInfo(frame *FromInterlockFrame) {
//
//}

View File

@ -4,6 +4,7 @@ package beijing12
import (
"context"
"fmt"
"joylink.club/bj-rtsts-server/third_party/tcp"
"log/slog"
"runtime/debug"
"sync"
@ -11,12 +12,9 @@ import (
"joylink.club/bj-rtsts-server/config"
"joylink.club/bj-rtsts-server/third_party/message"
"joylink.club/bj-rtsts-server/third_party/udp"
)
const (
logTag = "[北京12号线联锁通信]"
)
const logTag = "[北京12号线联锁通信]"
// 联锁代理通信接口
type InterlockMessageManager interface {
@ -30,8 +28,6 @@ type InterlockProxy interface {
Start(manager InterlockMessageManager)
// 停止联锁消息功能
Stop()
// 发送联锁采集消息
SendCollectMessage(b []byte)
}
var interlockMap = make(map[string]InterlockProxy)
@ -47,8 +43,7 @@ func Default(c *config.InterlockConfig) InterlockProxy {
}
type interlockProxy struct {
driveInfoUdpServer udp.UdpServer
sendCollectUdpClient udp.UdpClient
tcpClient *tcp.TcpClient
manager InterlockMessageManager
collectInfoTaskCancel context.CancelFunc
@ -69,17 +64,17 @@ func (i *interlockProxy) Start(manager InterlockMessageManager) {
return
}
if manager == nil {
panic("启动联锁消息服务错误: InterlockMessageManager不能为nil")
panic(fmt.Sprintf("%s启动联锁消息服务错误: InterlockMessageManager不能为nil", logTag))
}
if i.manager != nil {
panic("启动联锁消息服务错误: 存在正在运行的任务")
panic(fmt.Sprintf("%s启动联锁消息服务错误: 存在正在运行的任务", logTag))
}
i.manager = manager
// 初始化客户端、服务端
i.initInterlockProxy()
ctx, cancle := context.WithCancel(context.Background())
ctx, cancel := context.WithCancel(context.Background())
go i.collectInfoStateTask(ctx)
i.collectInfoTaskCancel = cancle
i.collectInfoTaskCancel = cancel
}
// 采集电路状态发送间隔,单位ms
@ -92,7 +87,7 @@ var serialNumber uint8
func (i *interlockProxy) collectInfoStateTask(ctx context.Context) {
defer func() {
if err := recover(); err != nil {
slog.Error("定时发送道岔状态任务异常", "error", err, "stack", string(debug.Stack()))
slog.Error(logTag+"定时发送道岔状态任务异常", "error", err, "stack", string(debug.Stack()))
debug.PrintStack()
}
}()
@ -106,11 +101,11 @@ func (i *interlockProxy) collectInfoStateTask(ctx context.Context) {
if collectInfoState != nil {
serialNumber++
collectInfoState.SetSerialNumber(serialNumber)
err := i.sendCollectUdpClient.SendMsg(collectInfoState)
err := i.tcpClient.Send(collectInfoState.Encode())
if err != nil {
slog.Error("向联锁发送继电器状态失败:", err)
slog.Error(fmt.Sprintf("%s向联锁发送继电器状态失败%s", logTag, err))
} else {
slog.Info(fmt.Sprintf("向联锁发送继电器数据成功:%x", collectInfoState.Encode()))
slog.Info(fmt.Sprintf("%s向联锁发送继电器数据成功:%x", logTag, collectInfoState.Encode()))
}
}
time.Sleep(time.Millisecond * InterlockMessageSendInterval)
@ -121,11 +116,9 @@ func (i *interlockProxy) Stop() {
initMutex.Lock()
defer initMutex.Unlock()
delete(interlockMap, i.runConfig.Code)
if i.sendCollectUdpClient != nil {
i.sendCollectUdpClient.Close()
}
if i.driveInfoUdpServer != nil {
i.driveInfoUdpServer.Close()
i.collectInfoTaskCancel()
if i.tcpClient != nil {
i.tcpClient.Close()
}
if i.collectInfoTaskCancel != nil {
i.collectInfoTaskCancel()
@ -133,12 +126,21 @@ func (i *interlockProxy) Stop() {
i.manager = nil
}
func (i *interlockProxy) SendCollectMessage(b []byte) {
i.sendCollectUdpClient.Send(b)
func (i *interlockProxy) initInterlockProxy() {
client, err := tcp.StartTcpClient(fmt.Sprintf("%s:%d", i.runConfig.Ip, i.runConfig.RemotePort), i.handleDriveInfo, func(err error) {
slog.Error(fmt.Sprintf("%sTCP客户端读取数据出错终止通信服务%s", logTag, err))
i.Stop()
})
if err != nil {
panic(fmt.Sprintf("%s启动TCP客户端失败%s", logTag, err))
}
i.tcpClient = client
}
func (i *interlockProxy) initInterlockProxy() {
i.sendCollectUdpClient = udp.NewClient(fmt.Sprintf("%v:%v", i.runConfig.Ip, i.runConfig.RemotePort))
i.driveInfoUdpServer = udp.NewServer(fmt.Sprintf(":%d", i.runConfig.LocalPort), i.handleDriverInfo)
i.driveInfoUdpServer.Listen()
func (i *interlockProxy) handleDriveInfo(n int, data []byte) {
data = data[:n]
slog.Info(fmt.Sprintf("%s收到联锁驱动继电器数据%x", logTag, data))
if i.manager != nil {
i.manager.HandleInterlockDriverInfo(i.runConfig.Code, data)
}
}

View File

@ -9,25 +9,26 @@ import (
)
type TcpClient struct {
conn *net.TCPConn
handler func(n int, data []byte)
ctx context.CancelFunc
conning bool
properties map[string]interface{}
conn *net.TCPConn
handler func(n int, data []byte)
ctx context.CancelFunc
conning bool
}
func StartTcpClient(rAddr string, properties map[string]interface{}, handler func(n int, data []byte, clientProperties map[string]interface{}), readErr func(err error)) (*TcpClient, error) {
func StartTcpClient(rAddr string, handler func(n int, data []byte), readErr func(err error)) (*TcpClient, error) {
raddr, addErr := net.ResolveTCPAddr("tcp", rAddr)
if addErr != nil {
return nil, addErr
}
conn, err := net.DialTCP("tcp", nil, raddr)
ctx, ctxFun := context.WithCancel(context.Background())
client := &TcpClient{conn: conn, ctx: ctxFun}
if err != nil {
client.ctx = ctxFun
client.conning = false
return nil, err
}
client := &TcpClient{conn: conn, ctx: ctxFun, properties: properties}
go func() {
for {
select {
@ -36,21 +37,25 @@ func StartTcpClient(rAddr string, properties map[string]interface{}, handler fun
default:
}
data := make([]byte, 1024)
l, err := conn.Read(data)
if err != nil {
if opErr, ok := err.(*net.OpError); ok {
l, readDataErr := conn.Read(data)
if readDataErr != nil {
if opErr, ok := readDataErr.(*net.OpError); ok {
slog.Error(fmt.Sprintf("TCP客户端[rAddr:%s]读取数据异常连接可能断开:", rAddr), opErr)
client.conning = false
readErr(err)
}
if err == io.EOF {
readErr(readDataErr)
} else if readDataErr == io.EOF {
slog.Warn(fmt.Sprintf("TCP客户端[rAddr:%s]断开连接:", rAddr))
client.conning = false
readErr(err)
readErr(readDataErr)
} else {
slog.Error(fmt.Sprintf("TCP客户端[rAddr:%s]读数据出错:%s", raddr, readDataErr))
client.conning = false
readErr(readDataErr)
}
return
}
client.conning = true
handler(l, data, client.properties)
handler(l, data)
}
}()
client.conning = true
@ -73,12 +78,12 @@ func (c *TcpClient) IsConning() bool {
func (c *TcpClient) Send(data []byte) error {
if c == nil || c.conn == nil {
slog.Error("tcp client send error,conn is nil")
return fmt.Errorf("TCP未连接车载PC仿真")
//slog.Error("tcp client send error,conn is nil")
return fmt.Errorf("tcp client send error,conn is nil")
}
_, err := c.conn.Write(data)
if err != nil {
slog.Error("tcp client send error", "error", err)
//slog.Error("tcp client send error", "error", err)
return err
}
return nil

View File

@ -9,6 +9,7 @@ import (
"log/slog"
"net"
"strconv"
"strings"
)
type TcpConnHandler = func(conn net.Conn)
@ -68,12 +69,13 @@ func StartTcpServer(port int, connHandler TcpConnHandler, msgHandler TcpMsgHandl
return listen, err
}
var serConn net.Conn
var serConnMap map[int]net.Conn = make(map[int]net.Conn)
func createServer(h TcpMsgHandler) {
StartTcpServer(5600, func(conn net.Conn) {
func createServer(port int, h TcpMsgHandler) {
StartTcpServer(port, func(conn net.Conn) {
fmt.Println("TCP服务端接收到连接")
serConn = conn
serConnMap[port] = conn
}, h)
}
func connTrain() *message.TrainPcSimBaseMessage {
@ -162,20 +164,18 @@ func pcSimNumReportOut() *message.TrainPcSimBaseMessage {
})
select {}
}*/
func main() {
createServer(func(n int, data []byte) {
func startService(port int) {
createServer(port, func(n int, data []byte) {
msg := &message.TrainPcSimBaseMessage{}
d := data[:n]
msg.Decode(d)
pd := fmt.Sprintf("%X", d)
if msg.Type == train_pc_sim.SENDER_TRAIN_TC_ACTIVE {
fmt.Println("接收驾驶端激活")
fmt.Println(pd)
fmt.Println("接收驾驶端激活 port:", port)
} else if msg.Type == train_pc_sim.SENDER_TRAIN_TC_NOT_ACTIVE {
fmt.Println("接收驾驶端未激活")
fmt.Println("接收驾驶端未激活 port:", port)
fmt.Println(pd)
} else if msg.Type == train_pc_sim.SENDER_TRAIN_OUTR_INFO {
fmt.Println(pd)
@ -194,31 +194,31 @@ func main() {
case 4:
tt = "制动状态"
}
fmt.Println("接受列车输出数字量", tt, s)
fmt.Println("接受列车输出数字量", tt, s, port)
fmt.Println(pd)
} else if msg.Type == train_pc_sim.RECIVE_TRAIN_CREATE_REMOVE {
state := msg.Data[0]
if state == 0x01 {
fmt.Println("创建列车")
fmt.Println("创建列车 port:", port)
} else if state == 0x00 {
fmt.Println("删除列车")
fmt.Println("删除列车 port:", port)
}
fmt.Println(pd)
} else if msg.Type == train_pc_sim.SENDER_TRAIN_HAND_KEY_FORWARD {
fmt.Println("列车手柄向前")
fmt.Println("列车手柄向前 port:", port)
fmt.Println(pd)
} else if msg.Type == train_pc_sim.RECIVE_TRAIN_HAND_KEY_CANCLE_FORWARD {
fmt.Println("列车手柄取消向前")
fmt.Println("列车手柄取消向前 port:", port)
fmt.Println(pd)
} else if msg.Type == train_pc_sim.RECIVE_TRAIN_HAND_KEY_BACKWARD {
fmt.Println("列车手柄向后")
fmt.Println("列车手柄向后 port:", port)
fmt.Println(pd)
} else if msg.Type == train_pc_sim.RECIVE_TRAIN_HAND_KEY_CACLE_BACKWARD {
fmt.Println("列车手柄取消向后")
fmt.Println("列车手柄取消向后 port:", port)
fmt.Println(pd)
} else if msg.Type == train_pc_sim.RECIVE_TRAIN_BTM_HAS_DATA {
fmt.Println("有数据应答")
fmt.Println("有数据应答 port:", port)
fmt.Println(pd)
} else if msg.Type == train_pc_sim.RECIVE_TRAIN_BTM_NOT_DATA {
@ -231,18 +231,30 @@ func main() {
}*/
})
}
func main() {
port1 := 5600
port2 := 5601
go startService(port1)
go startService(port2)
//reader := bufio.NewReader(os.Stdin)
var command string
for {
if serConn == nil {
continue
}
fmt.Scanln(&command)
if command != "" {
fmt.Println(command)
}
strs := strings.Split(command, ",")
if len(strs) < 2 {
fmt.Println("eeeeeeee")
command = ""
continue
}
p1s, comm := strs[0], strs[1]
portInt, _ := strconv.Atoi(p1s)
serConn := serConnMap[portInt]
command = comm
if command == "create-train" {
msg := connTrain()
serConn.Write(msg.Encode())

View File

@ -58,6 +58,40 @@ type TrainPcSimManage interface {
// TrainBtmQuery 处理列车btm查询
TrainBtmQuery(connType state_proto.TrainConnState_TrainConnType, data []byte)
}
type trainPcReciverData struct {
clientKey string
tcpClient *tcp.TcpClient
pcSimManage TrainPcSimManage
}
func (rd *trainPcReciverData) receiverDataHandle(n int, data []byte) {
connType := state_proto.TrainConnState_PC_SIM_A
if rd.clientKey == "B" {
connType = state_proto.TrainConnState_PC_SIM_B
}
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:
rd.pcSimManage.TrainPcSimDigitalOutInfoHandle(connType, baseMsg.Data)
case RECIVE_TRAIN_INTERFACE_CABINET_OUTR_BACK:
rd.pcSimManage.TrainPcSimDigitalReportHandle(connType, baseMsg.Data)
case RECIVE_TRAIN_QUERY_STATUS:
rd.pcSimManage.TrainBtmQuery(connType, baseMsg.Data)
case RECIVE_TRAIN_MOCK_DATA:
rd.pcSimManage.TrainPcSimMockInfo(connType, baseMsg.Data)
//case RECIVE_TRAIN_DOOR_MODE:
// pc.trainPcSimManage.TrainDoorModeHandle(baseMsg.Data[0])
}
}
const Name = "车载pc仿真"
const CLIENT_KEY = "clientKey"
@ -97,35 +131,52 @@ func Default() TrainPcSim {
type trainPcSimService struct {
state tpapi.ThirdPartyApiServiceState
//pcSimClient *tcp.TcpClient
pcSimClientMap map[string]*tcp.TcpClient
cancleContext context.CancelFunc
trainPcSimManage TrainPcSimManage
speedPlace *message.TrainSpeedPlaceReportMsg
configs []config.VehiclePCSimConfig
//pcSimClientMap map[string]*tcp.TcpClient
newPcSimclientMap map[string]*trainPcReciverData
cancleContext context.CancelFunc
trainPcSimManage TrainPcSimManage
speedPlace *message.TrainSpeedPlaceReportMsg
configs []config.VehiclePCSimConfig
}
// 接受来自pc仿真的消息
func (d *trainPcSimService) readError(err error) {
slog.Error("连接车载pc仿真tcp服务断开", err)
d.updateState(tpapi.ThirdPartyState_Broken)
}
func (d *trainPcSimService) closeAllConn() {
for key, client := range d.pcSimClientMap {
if client != nil {
client.Close()
func (d *trainPcSimService) newCloseAllConn() {
for _, rd := range d.newPcSimclientMap {
if rd != nil {
rd.tcpClient.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) closeAllConn() {
for key, client := range d.pcSimClientMap {
if client != nil {
client.Close()
}
delete(d.pcSimClientMap, key)
}
}
*/
func (d *trainPcSimService) newCloseConn(clientKey string) {
rd := d.newPcSimclientMap[clientKey]
if rd != nil {
rd.tcpClient.Close()
}
}
/*
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" {
@ -144,13 +195,13 @@ func (d *trainPcSimService) findConfig(tcChar string) (*config.VehiclePCSimConfi
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()
//d.closeAllConn()
d.newCloseAllConn()
return
default:
}
@ -160,15 +211,22 @@ func (d *trainPcSimService) connTrainPcSim(ctx context.Context) {
clientKey := FindTrainPcSimClientKey(t)
if clientKey == "" {
slog.Error("未找到对应的pc仿真连接,trainId:", t.Id, "删除对应客户端")
d.closeConn(clientKey)
//d.closeConn(clientKey)
d.newCloseConn(clientKey)
continue
}
client := d.pcSimClientMap[clientKey]
if !client.IsConning() {
client.Close()
d.initConn(clientKey)
//client := d.pcSimClientMap[clientKey]
rd := d.newPcSimclientMap[clientKey]
if rd == nil {
d.newPcSimclientMap[clientKey] = &trainPcReciverData{pcSimManage: d.trainPcSimManage, clientKey: clientKey, tcpClient: &tcp.TcpClient{}}
}
if !rd.tcpClient.IsConning() {
//client.Close()
d.newCloseConn(clientKey)
d.initConn(clientKey)
}
}
}
@ -181,29 +239,45 @@ func (d *trainPcSimService) connTrainPcSim(ctx context.Context) {
func (d *trainPcSimService) initConn(clientKey string) {
client := d.pcSimClientMap[clientKey]
if d.pcSimClientMap[clientKey] == nil {
client = &tcp.TcpClient{}
d.pcSimClientMap[clientKey] = client
rd := d.newPcSimclientMap[clientKey]
if rd == nil {
rd = &trainPcReciverData{pcSimManage: d.trainPcSimManage, clientKey: clientKey, tcpClient: &tcp.TcpClient{}}
d.newPcSimclientMap[clientKey] = rd
}
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)
cfg, _ := d.findConfig(clientKey)
addr := fmt.Sprintf("%v:%v", cfg.PcSimIp, cfg.PcSimPort)
client2, err := tcp.StartTcpClient(addr, rd.receiverDataHandle, d.readError)
if err != nil {
slog.Error("车载pc连接失败 clientKey:", clientKey, "error:", err.Error())
d.updateState(tpapi.ThirdPartyState_Broken)
} else {
d.pcSimClientMap[clientKey] = client2
rd.tcpClient = client2
}
/*if d.pcSimClientMap[clientKey] != nil {
return
}
cfg, _ := d.findConfig(clientKey)
addr := fmt.Sprintf("%v:%v", cfg.PcSimIp, cfg.PcSimPort)
properties := map[string]interface{}{
CLIENT_KEY: clientKey,
}
client2, err := tcp.StartTcpClient(addr, properties, d.reivceData, d.readError)
if err != nil {
slog.Error("车载pc连接失败 clientKey:", clientKey, "error:", err.Error())
d.updateState(tpapi.ThirdPartyState_Broken)
} else {
d.pcSimClientMap[clientKey] = client2
}*/
}
func (d *trainPcSimService) Start(pcSimManage TrainPcSimManage) {
configs := pcSimManage.GetTrainPcSimConfig()
d.pcSimClientMap = map[string]*tcp.TcpClient{}
d.newPcSimclientMap = make(map[string]*trainPcReciverData)
//d.pcSimClientMap = map[string]*tcp.TcpClient{}
if len(configs) <= 0 {
slog.Info("车载pc仿真配置未开启")
return
@ -218,7 +292,6 @@ func (d *trainPcSimService) Start(pcSimManage TrainPcSimManage) {
slog.Info("车载pc仿真配置未开启")
return
}
d.configs = configs
ctx, ctxFun := context.WithCancel(context.Background())
d.cancleContext = ctxFun
@ -235,7 +308,8 @@ func (d *trainPcSimService) Stop() {
d.cancleContext()
d.cancleContext = nil
}
d.closeAllConn()
//d.closeAllConn()
d.newCloseAllConn()
}
func (d *trainPcSimService) CreateOrRemoveSpeedPLace(train *state_proto.TrainState) {
if train.ConnState.Conn && (train.ConnState.ConnType == state_proto.TrainConnState_PC_SIM_A || train.ConnState.ConnType == state_proto.TrainConnState_PC_SIM_B) {
@ -248,18 +322,31 @@ func (d *trainPcSimService) CreateOrRemoveSpeedPLace(train *state_proto.TrainSta
}
func (d *trainPcSimService) CreateOrRemoveTrain(train *state_proto.TrainState, msgType byte, data []byte) error {
clientKey := FindTrainPcSimClientKey(train)
log := "删除列车"
if msgType == RECIVE_TRAIN_CREATE_REMOVE && data[0] == 0x01 {
log = "创建列车"
d.initConn(clientKey)
}
msg := &message.TrainPcSimBaseMessage{Data: data, Type: uint16(msgType)}
client := d.pcSimClientMap[clientKey]
rd := d.newPcSimclientMap[clientKey]
if rd != nil {
sd := msg.Encode()
slog.Info(fmt.Sprintf("%v-列车号:%v,发送数据:%v", log, train.Id, hex.EncodeToString(sd)))
err := rd.tcpClient.Send(sd)
if err != nil {
return err
}
if data[0] != 0x01 {
d.newCloseConn(clientKey)
}
}
/*client := d.pcSimClientMap[clientKey]
err := client.Send(msg.Encode())
if data[0] != 0x01 {
d.closeConn(clientKey)
}
}*/
return err
return nil
}
// 依据文档80ms发送列车速度位置
@ -274,15 +361,24 @@ func (d *trainPcSimService) sendTrainLocationAndSpeedTask(ctx context.Context) {
for _, train := range trains {
if train.ConnState.Conn && train.PluseCount != nil {
clientKey := FindTrainPcSimClientKey(train)
rd := d.newPcSimclientMap[clientKey]
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())
rd.tcpClient.Send(bm.Encode())
/*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())*/
}
}
@ -296,7 +392,8 @@ func (d *trainPcSimService) SendDriverActive(train *state_proto.TrainState) {
vobc := train.VobcState
clientKey := FindTrainPcSimClientKey(train)
client := d.pcSimClientMap[clientKey]
//client := d.pcSimClientMap[clientKey]
rd := d.newPcSimclientMap[clientKey]
defulatBuf := make([]byte, 0)
msg := &message.TrainPcSimBaseMessage{Data: defulatBuf}
if train.TrainRunUp {
@ -313,10 +410,11 @@ func (d *trainPcSimService) SendDriverActive(train *state_proto.TrainState) {
}
}
da := msg.Encode()
slog.Info("发送驾驶激活 列车", train.Id, "数据", hex.EncodeToString(da))
err := client.Send(da)
slog.Info("发送驾驶激活列车", train.Id, "数据", hex.EncodeToString(da))
err := rd.tcpClient.Send(da)
//err := client.Send(da)
if err != nil {
slog.Error("发送驾驶激活 列车", train.Id, "数据", hex.EncodeToString(da), err)
slog.Error("发送驾驶激活列车", train.Id, "数据", hex.EncodeToString(da), err)
}
}
func (d *trainPcSimService) SendHandleSwitch(oldTraction, oldBrakeForce int64, tractionState bool, train *state_proto.TrainState) {
@ -324,7 +422,9 @@ func (d *trainPcSimService) SendHandleSwitch(oldTraction, oldBrakeForce int64, t
if tc.Conn {
vobc := train.VobcState
clientKey := FindTrainPcSimClientKey(train)
client := d.pcSimClientMap[clientKey]
rd := d.newPcSimclientMap[clientKey]
//client := d.pcSimClientMap[clientKey]
msg := &message.TrainPcSimBaseMessage{}
newTraction := vobc.TractionForce
newBrake := -vobc.BrakeForce
@ -355,7 +455,8 @@ func (d *trainPcSimService) SendHandleSwitch(oldTraction, oldBrakeForce int64, t
}
da := msg.Encode()
slog.Info("发送列车手柄消息", "clientKey", clientKey, "msg", hex.EncodeToString(da))
err := client.Send(da)
err := rd.tcpClient.Send(da)
//err := client.Send(da)
if err != nil {
slog.Error("发送列车手柄消息失败", "clientKey", clientKey, "msg", hex.EncodeToString(da))
}
@ -373,11 +474,13 @@ func (d *trainPcSimService) SendTrainDirection(train *state_proto.TrainState, tr
baseMsgs = append(baseMsgs, &message.TrainPcSimBaseMessage{Type: RECIVE_TRAIN_HAND_KEY_BACKWARD})
}
clientKey := FindTrainPcSimClientKey(train)
client := d.pcSimClientMap[clientKey]
rd := d.newPcSimclientMap[clientKey]
//client := d.pcSimClientMap[clientKey]
for _, msg := range baseMsgs {
da := msg.Encode()
slog.Info("发送列车方向列车", train.Id, "数据", hex.EncodeToString(da))
err := client.Send(da)
err := rd.tcpClient.Send(da)
//err := client.Send(da)
if err != nil {
slog.Error("发送列车方向失败列车", train.Id, "数据", hex.EncodeToString(da))
}
@ -389,11 +492,13 @@ func (d *trainPcSimService) SendBaliseData(train *state_proto.TrainState, msgTyp
msg.Type = msgType
msg.Data = data
clientKey := FindTrainPcSimClientKey(train)
client := d.pcSimClientMap[clientKey]
rd := d.newPcSimclientMap[clientKey]
//client := d.pcSimClientMap[clientKey]
da := msg.Encode()
slog.Info("发送列车PC仿真应答器信息,数据", hex.EncodeToString(da))
err := client.Send(da)
err := rd.tcpClient.Send(da)
if err != nil {
slog.Info("发送列车PC仿真应答器信息失败,数据", hex.EncodeToString(da))
}
@ -414,20 +519,23 @@ func (d *trainPcSimService) PublishTrainControlEvent(train *state_proto.TrainSta
return
}
clientKey := FindTrainPcSimClientKey(train)
client := d.pcSimClientMap[clientKey]
rd := d.newPcSimclientMap[clientKey]
//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
client.Send(msg.Encode())
rd.tcpClient.Send(msg.Encode())
//client.Send(msg.Encode())
//FireTrainControlEventType.Publish(world, &event)
}
}
// 接受来自pc仿真的消息
func (d *trainPcSimService) reivceData(len int, data []byte, properties map[string]interface{}) {
/*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 {
@ -460,4 +568,4 @@ func (d *trainPcSimService) reivceData(len int, data []byte, properties map[stri
//case RECIVE_TRAIN_DOOR_MODE:
// pc.trainPcSimManage.TrainDoorModeHandle(baseMsg.Data[0])
}
}
}*/

View File

@ -13,6 +13,15 @@ import (
"joylink.club/rtsssimulation/repository"
)
// 地图数据处理方法。目前用于不同通信协议所需数据的预处理
type MapDataHandler func(uidStructure *StationUidStructure, data *data_proto.RtssGraphicStorage)
var mapDataHandlerList = make([]MapDataHandler, 0)
func RegisterListener(handler MapDataHandler) {
mapDataHandlerList = append(mapDataHandlerList, handler)
}
var giUidMap sync.Map
type elementIdStructure struct {
@ -426,6 +435,10 @@ func initStationUid(data *data_proto.RtssGraphicStorage) *StationUidStructure {
Uid: GenerateElementUid(city, lineId, nil, xcj.Code),
}
}
//通信协议预处理所需数据
for _, handler := range mapDataHandlerList {
handler(gus, data)
}
return gus
}

View File

@ -153,7 +153,7 @@ func TrainConnTypeUpdate(vs *VerifySimulation, ct *dto.TrainConnThirdDto) {
connTypeName := "半实物"
if tmpTrain.ConnState.ConnType == state_proto.TrainConnState_PC_SIM_A {
connTypeName = "车载pc仿真-A"
} else if tmpTrain.ConnState.ConnType == state_proto.TrainConnState_PC_SIM_A {
} else if tmpTrain.ConnState.ConnType == state_proto.TrainConnState_PC_SIM_B {
connTypeName = "车载pc仿真-B"
}
panic(sys_error.New(fmt.Sprintf("列车[%s]已经连接 [%v],此列车无法连接", k, connTypeName)))
@ -165,7 +165,7 @@ func TrainConnTypeUpdate(vs *VerifySimulation, ct *dto.TrainConnThirdDto) {
train.ConnState.Conn = true
train.ConnState.ConnType = ct.ConnType
if ct.ConnType == state_proto.TrainConnState_PC_SIM_A || ct.ConnType == state_proto.TrainConnState_PC_SIM_B {
err := TrainPcSimConnOrRemoveHandle(train)
err := TrainPcSimConnOrRemoveHandle(train, true)
if err != nil {
train.ConnState.Conn = false
train.ConnState.ConnType = state_proto.TrainConnState_NONE
@ -184,7 +184,7 @@ func TrainUnConn(vs *VerifySimulation, trainId string) {
panic(sys_error.New(fmt.Sprintf("列车【%s】不存在", trainId)))
}
train := data.(*state_proto.TrainState)
err := TrainPcSimConnOrRemoveHandle(train)
err := TrainPcSimConnOrRemoveHandle(train, false)
if err != nil {
panic(sys_error.New("未连接车载PC仿真无法断开连接"))
}
@ -462,7 +462,7 @@ func removeTrain(vs *VerifySimulation, trainId string, train *state_proto.TrainS
}
if train.ConnState.Conn {
train.ConnState.Conn = false
err = TrainPcSimConnOrRemoveHandle(train)
err = TrainPcSimConnOrRemoveHandle(train, false)
if err != nil {
train.ConnState.Conn = true
return err

View File

@ -458,15 +458,14 @@ func (s *VerifySimulation) TrainPcSimDigitalReportHandle(connType state_proto.Tr
}
// 创建/删除列车
func TrainPcSimConnOrRemoveHandle(train *state_proto.TrainState) error {
func TrainPcSimConnOrRemoveHandle(train *state_proto.TrainState, create bool) error {
var data byte = 0x01
if train.ConnState.Conn == false {
data = 0x00
var data byte = 0x00
if create {
data = 0x01
}
connState := train.ConnState
if connState.ConnType == state_proto.TrainConnState_PC_SIM_A || 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

View File

@ -124,7 +124,7 @@ func runThirdParty(s *memory.VerifySimulation) error {
for _, c := range s.GetInterlockCodes() {
switch c.Line {
case "11":
beijing11.Start(c)
beijing11.Start(c, s)
default:
beijing12.Default(c).Start(s)
}