This commit is contained in:
weizhihong 2023-11-07 09:22:54 +08:00
commit 0cc01420ba
4 changed files with 142 additions and 13 deletions

View File

@ -1,5 +1,7 @@
package axle_device package axle_device
import "joylink.club/bj-rtsts-server/third_party/message"
// RsspConfig CI系统与计轴设备的安全通信协议配置参数 // RsspConfig CI系统与计轴设备的安全通信协议配置参数
// 计轴设备(管理一个集中站的所有计轴器)配置 // 计轴设备(管理一个集中站的所有计轴器)配置
type RsspConfig struct { type RsspConfig struct {
@ -15,6 +17,13 @@ type RsspConfig struct {
SsrRsspTimeout uint32 //等待SSR回应的定时器超时值,为RsspTimer时间,1=SendingPeriod SsrRsspTimeout uint32 //等待SSR回应的定时器超时值,为RsspTimer时间,1=SendingPeriod
Mtv uint32 //每个安全通信会话可容忍的最大时序偏差,即当前接收的RSD的序列号与上一次RSD的序列号最大允许差值 Mtv uint32 //每个安全通信会话可容忍的最大时序偏差,即当前接收的RSD的序列号与上一次RSD的序列号最大允许差值
Udl uint32 //每个安全通信会话RSD应用数据长度发送和接收的配置值支持固定长度和可变长度;0-可变长度大于0即固定长度 Udl uint32 //每个安全通信会话RSD应用数据长度发送和接收的配置值支持固定长度和可变长度;0-可变长度大于0即固定长度
PicType message.PicType //协议交互类别
DeviceA bool //true-A机false-B机
RemoteIp string //远程服务器ip
RemoteUdpPort int //远程服务器端口
LocalUdpPort int //本地服务器端口
} }
// CheckAddress 检测目标源地址目的地址是否在配置中 // CheckAddress 检测目标源地址目的地址是否在配置中

74
third_party/axle_device/rssp_axle.go vendored Normal file
View File

@ -0,0 +1,74 @@
package axle_device
import "joylink.club/bj-rtsts-server/third_party/message"
//计轴设备与联锁系统安全通信应用层实现
type RsspAxle interface {
//Start 启动计轴设备与联锁系统安全通信服务
Start(amm AxleMessageManager) error
//Stop 停止计轴设备与联锁系统安全通信服务
Stop()
//SendStatusMsg 将计轴区段状态发生给联锁系统
SendStatusMsg(msg *message.SectionStatusMsgPack)
}
type AxleMessageManager interface {
//HandleCmdMsg 计轴设备接收到联锁发送来的控制命令
HandleCmdMsg(msg *message.SectionCmdMsgPack)
}
type rsspAxle struct {
//主安全通道
masterRssp *RsspChannel
//备安全通道
slaveRssp *RsspChannel
//收到应用层消息回调
messageManager AxleMessageManager
}
func NewRsspAxle(masterRssp *RsspChannel, slaveRssp *RsspChannel) RsspAxle {
return &rsspAxle{masterRssp: masterRssp, slaveRssp: slaveRssp}
}
// rssp 安全层执行
func (s *rsspAxle) rcvCmdMsg(data []byte) {
msg := &message.SectionCmdMsgPack{}
msg.Decode(data)
s.messageManager.HandleCmdMsg(msg)
}
func (s *rsspAxle) Start(amm AxleMessageManager) error {
s.messageManager = amm
//设置安全通道层
if s.masterRssp != nil {
s.masterRssp.handleUserData = s.rcvCmdMsg
s.masterRssp.Start()
}
if s.slaveRssp != nil {
s.slaveRssp.handleUserData = s.rcvCmdMsg
s.slaveRssp.Start()
}
//
return nil
}
func (s *rsspAxle) Stop() {
if s.masterRssp != nil {
s.masterRssp.Stop()
}
if s.slaveRssp != nil {
s.slaveRssp.Stop()
}
}
func (s *rsspAxle) SendStatusMsg(msg *message.SectionStatusMsgPack) {
data := msg.Encode()
//向备通道发送
if s.slaveRssp != nil {
data_s := make([]byte, len(data))
copy(data_s, data)
s.slaveRssp.sendUserData(data_s)
}
//向主通道发送
if s.masterRssp != nil {
s.masterRssp.sendUserData(data)
}
}

View File

@ -1,12 +1,25 @@
package axle_device package axle_device
import ( import (
"fmt"
"joylink.club/bj-rtsts-server/third_party/message" "joylink.club/bj-rtsts-server/third_party/message"
"joylink.club/bj-rtsts-server/third_party/udp"
"log/slog" "log/slog"
) )
// 铁路信号安全通信协议实现
// HandleUserData 回调应用层
type HandleUserData func([]byte)
// RsspChannel 实现rssp通信 // RsspChannel 实现rssp通信
type RsspChannel struct { type RsspChannel struct {
//udp
udpServer udp.UdpServer
//udp
udpClient udp.UdpClient
//回调应用层
handleUserData HandleUserData
//rssp安全通信配置 //rssp安全通信配置
config *RsspConfig config *RsspConfig
//rssp时钟 //rssp时钟
@ -17,10 +30,6 @@ type RsspChannel struct {
ch1Ts *message.RsspLFSR ch1Ts *message.RsspLFSR
//安全通道2时间戳 //安全通道2时间戳
ch2Ts *message.RsspLFSR ch2Ts *message.RsspLFSR
//协议交互类别
picType message.PicType
//true-A机false-B机
deviceA bool
//最近一次接收到的报文的安全通道1时间戳 //最近一次接收到的报文的安全通道1时间戳
rcvCh1Ts uint32 rcvCh1Ts uint32
//最近一次接收到的报文的安全通道2时间戳 //最近一次接收到的报文的安全通道2时间戳
@ -31,6 +40,29 @@ type RsspChannel struct {
sendSseRecord *SseFireRecord sendSseRecord *SseFireRecord
} }
func (s *RsspChannel) Init(config *RsspConfig) {
s.config = config
}
// Start 启动安全通道
func (s *RsspChannel) Start() {
//
s.udpServer = udp.NewServer(fmt.Sprintf(":%d", s.config.LocalUdpPort), s.handleRsspMsg)
s.udpServer.Listen()
//
s.udpClient = udp.NewClient(fmt.Sprintf("%s:%d", s.config.RemoteIp, s.config.RemoteUdpPort))
}
// Stop 关闭安全通道
func (s *RsspChannel) Stop() {
if s.udpServer != nil {
s.udpServer.Close()
}
if s.udpClient != nil {
s.udpClient.Close()
}
}
// RsspTimer rssp时钟每一个tick周期为config.SendingPeriod // RsspTimer rssp时钟每一个tick周期为config.SendingPeriod
type RsspTimer struct { type RsspTimer struct {
t uint64 t uint64
@ -62,6 +94,7 @@ func (s *SseFireRecord) hasRecord() bool {
} }
// 处理接收到的rssp报文 // 处理接收到的rssp报文
// 注意本函数由udp socket 协程执行
func (s *RsspChannel) handleRsspMsg(pack []byte) { func (s *RsspChannel) handleRsspMsg(pack []byte) {
//报文头校验 //报文头校验
head := &message.RsspHead{} head := &message.RsspHead{}
@ -139,12 +172,7 @@ func (s *RsspChannel) handleRsspRsd(rsd *message.RsspRsd) {
s.rcvCh1Ts = c1SidTs ^ s.config.SID1 s.rcvCh1Ts = c1SidTs ^ s.config.SID1
s.rcvCh2Ts = c2SidTs ^ s.config.SID2 s.rcvCh2Ts = c2SidTs ^ s.config.SID2
//通知应用层接收应用数据 //通知应用层接收应用数据
s.rcvUserData(rsd.Sad) s.handleUserData(rsd.Sad)
}
// 从安全通道成功接收到应用层数据
func (s *RsspChannel) rcvUserData(userData []byte) {
} }
// 触发时序校正请求 // 触发时序校正请求
@ -221,8 +249,8 @@ func (s *RsspChannel) sendSse() {
// 发送用户数据即通过rssp安全通道发送应用层数据通过rssp的RSD报文发送 // 发送用户数据即通过rssp安全通道发送应用层数据通过rssp的RSD报文发送
func (s *RsspChannel) sendUserData(userData []byte) { func (s *RsspChannel) sendUserData(userData []byte) {
rsd := &message.RsspRsd{} rsd := &message.RsspRsd{}
rsd.Pic = s.picType rsd.Pic = s.config.PicType
if s.deviceA { if s.config.DeviceA {
rsd.Mc = message.RSD_A rsd.Mc = message.RSD_A
} else { } else {
rsd.Mc = message.RSD_B rsd.Mc = message.RSD_B
@ -252,5 +280,5 @@ func (s *RsspChannel) createSeqNeq(sid uint32, ts uint32) uint32 {
// 通过网络发送数据 // 通过网络发送数据
func (s *RsspChannel) sendPack(rsspPack []byte) { func (s *RsspChannel) sendPack(rsspPack []byte) {
s.udpClient.Send(rsspPack)
} }

View File

@ -649,6 +649,24 @@ func buildAndRelateElectronicComponent(repo *proto.Repository, relayGi *graphicD
} }
} }
} }
cis := stationMap[stationUid]
// 零散组合
for _, com := range relayGi.CombinationtypeList {
if com.Code == "LS" { // 零散组合
d := &proto.ElectronicGroup{Code: com.Code}
for _, relayId := range com.RefRelays {
if uidsMap.RelayIds[relayId] == nil {
continue
}
d.Components = append(d.Components, &proto.ElectronicComponent{
Id: uidsMap.RelayIds[relayId].Uid,
DeviceType: proto.DeviceType_DeviceType_Relay,
})
}
cis.ElectronicGroup = append(cis.ElectronicGroup, d)
fmt.Println("构建零散组合结果:", d)
}
}
// 处理该集中站采集、驱动配置信息 // 处理该集中站采集、驱动配置信息
centralizedStationId := GenerateElementUid(city, lineId, nil, station) centralizedStationId := GenerateElementUid(city, lineId, nil, station)
ref := queryCentralizedStationRef(centralizedStationId, repo) ref := queryCentralizedStationRef(centralizedStationId, repo)