This commit is contained in:
xzb 2023-11-01 17:46:24 +08:00
parent ebc2bc7cc6
commit 5f81e591ef
4 changed files with 118 additions and 6 deletions

23
third_party/axle_device/config.go vendored Normal file
View File

@ -0,0 +1,23 @@
package axle_device
// AxleDeviceConfig CI系统与计轴设备的安全通信协议配置参数
// 计轴设备(管理一个集中站的所有计轴器)配置
type AxleDeviceConfig struct {
SrcAddr uint16 //16位源地址
DstAddr uint16 //16位目的地址
DataVer1 uint32 //通道1数据版本
DataVer2 uint32 //通道2数据版本
SID1 uint32 //通道1源标识
SID2 uint32 //通道2源标识
SINIT1 uint32 //通道1序列初始
SINIT2 uint32 //通道2序列初始
SendingPeriod uint32 //接收方每个安全通信会话对应的发送周期值,单位ms
SSRTimeout uint32 //等待SSR回应的定时器超时值,单位ms
Mtv uint32 //每个安全通信会话可容忍的最大时序偏差
Udl uint32 //每个安全通信会话RSD应用数据长度发送和接收的配置值支持固定长度和可变长度;0-可变长度大于0即固定长度
}
// CheckAddress 检测目标源地址目的地址是否在配置中
func (c *AxleDeviceConfig) CheckAddress(srcAddr uint16, dstAddr uint16) bool {
return true
}

30
third_party/axle_device/rssp_server.go vendored Normal file
View File

@ -0,0 +1,30 @@
package axle_device
import (
"joylink.club/bj-rtsts-server/third_party/message"
)
//实现rssp通信流程
// 处理接收到的rssp报文
func handleRsspMsg(pack []byte, config *AxleDeviceConfig) {
//报文头校验
head := &message.RsspHead{}
if !head.Parse(pack) { //解析报文头失败
return
}
if !message.RsspHeadMcCheck(head) { //报文类别检测未通过
return
}
if !message.RsspHeadPicCheck(head) { //协议交互类别检测未通过
return
}
if !config.CheckAddress(head.Sa, head.Da) { //校验报文头中源地址和目的地址是否包含在已配置列表中
return
}
//报文尾校验
if !message.RsspPackCrc16Check(pack) { //整个报文crc16校验未通过
return
}
}

View File

@ -3,6 +3,7 @@ package message
import (
"encoding/binary"
"fmt"
"strings"
)
//RSSP-1 V1.0 铁路信号安全通信协议
@ -19,6 +20,13 @@ type RsspHead struct {
Da uint16
}
func (h *RsspHead) Parse(buf []byte) bool {
if len(buf) < 6 {
return false
}
h.decode(buf)
return true
}
func (h *RsspHead) Type() RsspType {
return h.Mc
}
@ -47,6 +55,20 @@ func (h *RsspHead) encode() []byte {
/////////////////////////////////////////////////
// RsspPackCrc16Check RSSP报文CRC16校验
func RsspPackCrc16Check(pack []byte) bool {
if len(pack) <= 2 { //报文长度不够,校验不通过
return false
}
//
pack16 := binary.LittleEndian.Uint16(pack[len(pack)-2:])
crc16 := RsspCrc16(pack[:len(pack)-2])
//
return crc16 == pack16
}
/////////////////////////////////////////////////
// RsspRsd 实时安全数据包
type RsspRsd struct {
RsspHead
@ -224,13 +246,40 @@ type Rssper interface {
}
type RsspType = byte
const (
const ( //报文类型
RSD_A = RsspType(0x80)
RSD_B = RsspType(0x81)
SSE = RsspType(0x90)
SSR = RsspType(0x91)
)
// RsspHeadMcCheck 报文类型检测
func RsspHeadMcCheck(head *RsspHead) bool {
switch head.Mc {
case RSD_A | RSD_B | SSE | SSR:
return true
default:
return false
}
}
type PicType = byte
const ( //协议交互类别
PIC_MASTER = PicType(0x01) //主机发送的安全数据
PIC_SLAVE = PicType(0x02) //备机发送的安全数据
)
// RsspHeadPicCheck 协议交互类别检测
func RsspHeadPicCheck(head *RsspHead) bool {
switch head.Pic {
case PIC_MASTER | PIC_SLAVE:
return true
default:
return false
}
}
// ParseRsspPack 解析RSSP数据包
func ParseRsspPack(pack []byte) (Rssper, error) {
// pack 进行CRC16循环冗余校验检测整个包的完整性
@ -258,3 +307,18 @@ func ParseRsspPack(pack []byte) (Rssper, error) {
e := codec.Decode(pack)
return codec.(Rssper), e
}
// PackToString 字节数组转换为16进制字节字符串
func PackToString(pack []byte) string {
b := &strings.Builder{}
first := true
for _, d := range pack {
if first {
b.WriteString(fmt.Sprintf("0x%0X", d))
first = false
} else {
b.WriteString(fmt.Sprintf(",0x%0X", d))
}
}
return b.String()
}

View File

@ -98,11 +98,6 @@ func initWorld(s *memory.VerifySimulation) error {
// 运行仿真第三方模块
func runThirdParty(s *memory.VerifySimulation) error {
/*
if s != nil { //测试时不启动第三方服务
return nil
}
*/
// 动力学启动
err := dynamics.Default().Start(s)
if err != nil {