rts-sim-testing-service/third_party/message/rssp.go
walker 62b44a0cc6 添加UDP网络延时记录器
动力学和半实物接口添加UDP网络监控功能
2024-01-22 13:10:10 +08:00

327 lines
7.2 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package message
import (
"encoding/binary"
"fmt"
"strings"
)
//RSSP-1 V1.0 铁路信号安全通信协议
// RsspHead rssp报文头
type RsspHead struct {
//报文头-协议交互类别(1Byte)
Pic byte
//报文头-报文类别(1Byte)
Mc byte
//报文头-源地址(2Byte)
Sa uint16
//报文头-目地址(2Byte)
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
}
func (h *RsspHead) decode(buf []byte) {
ri := 0
//报文头
h.Pic = buf[ri]
ri++
h.Mc = buf[ri]
ri++
h.Sa = binary.LittleEndian.Uint16(buf[ri : ri+2])
ri += 2
h.Da = binary.LittleEndian.Uint16(buf[ri : ri+2])
ri += 2
}
func (h *RsspHead) encode() []byte {
data := make([]byte, 0, 6)
//报文头
data = append(data, h.Pic)
data = append(data, h.Mc)
data = binary.LittleEndian.AppendUint16(data, h.Sa)
data = binary.LittleEndian.AppendUint16(data, h.Da)
//
return data
}
/////////////////////////////////////////////////
// RsspPackCrc16Check RSSP报文CRC16校验
func RsspPackCrc16Check(pack []byte) bool {
if len(pack) <= 2 { //报文长度不够,校验不通过
return false
}
//
pack16 := binary.LittleEndian.Uint16(pack[len(pack)-2:])
crc16 := Rssp_I_Crc16(pack[:len(pack)-2])
//
return crc16 == pack16
}
/////////////////////////////////////////////////
// RsspRsd 实时安全数据包
type RsspRsd struct {
RsspHead
//安全校验域-序列号(4Byte),可以是一个随时间周期变化的计数器
Sn uint32
//安全校验域-安全数据长度(2Byte)
Sdl uint16
//安全校验域-安全校验通道1(4Byte)
Svc1 uint32
//安全校验域-安全校验通道2(4Byte)
Svc2 uint32
//用户数据包-安全应用数据(总字节数480)
Sad []byte
//报文尾-CRC16(2Byte)
Crc16 uint16
}
func (r *RsspRsd) IsMaster() bool {
return r.Pic == PIC_MASTER
}
func (r *RsspRsd) IsSlave() bool {
return r.Pic == PIC_SLAVE
}
func (r *RsspRsd) Encode() []byte {
data := make([]byte, 0, 6+14+len(r.Sad)+2)
//报文头
data = append(data, r.RsspHead.encode()...)
//安全校验域
data = binary.LittleEndian.AppendUint32(data, r.Sn)
data = binary.LittleEndian.AppendUint16(data, r.Sdl)
data = binary.LittleEndian.AppendUint32(data, r.Svc1)
data = binary.LittleEndian.AppendUint32(data, r.Svc2)
//用户数据包
data = append(data, r.Sad...)
//报文尾-CRC16
r.Crc16 = Rssp_I_Crc16(data)
data = binary.LittleEndian.AppendUint16(data, r.Crc16)
//
return data
}
func (r *RsspRsd) Decode(buf []byte) error {
//报文头
r.RsspHead.decode(buf)
ri := 6
//安全校验域
r.Sn = binary.LittleEndian.Uint32(buf[ri : ri+4])
ri += 4
r.Sdl = binary.LittleEndian.Uint16(buf[ri : ri+2])
ri += 2
r.Svc1 = binary.LittleEndian.Uint32(buf[ri : ri+4])
ri += 4
r.Svc2 = binary.LittleEndian.Uint32(buf[ri : ri+4])
ri += 4
//用户数据
sadLen := int(r.Sdl) - 8
r.Sad = buf[ri : ri+sadLen]
ri += sadLen
//报文尾
r.Crc16 = binary.LittleEndian.Uint16(buf[ri : ri+2])
//
return nil
}
///////////////////////////////////////////////////////////////
// RsspSse 时序校正请求包
type RsspSse struct {
RsspHead
//安全校验域-序列号(4Byte)
Sn uint32
//安全校验域-时序校正请求通道1(4Byte)
SeqEnq1 uint32
//安全校验域-时序校正请求通道2(4Byte)
SeqEnq2 uint32
//报文尾-CRC16(2Byte)
Crc16 uint16
}
func (r *RsspSse) Encode() []byte {
data := make([]byte, 0, 20)
//报文头
data = append(data, r.RsspHead.encode()...)
//安全校验域
data = binary.LittleEndian.AppendUint32(data, r.Sn)
data = binary.LittleEndian.AppendUint32(data, r.SeqEnq1)
data = binary.LittleEndian.AppendUint32(data, r.SeqEnq2)
//报文尾-CRC16
r.Crc16 = Rssp_I_Crc16(data)
data = binary.LittleEndian.AppendUint16(data, r.Crc16)
return data
}
func (r *RsspSse) Decode(buf []byte) error {
//报文头
r.RsspHead.decode(buf)
//安全校验域
ri := 6
r.Sn = binary.LittleEndian.Uint32(buf[ri : ri+4])
ri += 4
r.SeqEnq1 = binary.LittleEndian.Uint32(buf[ri : ri+4])
ri += 4
r.SeqEnq2 = binary.LittleEndian.Uint32(buf[ri : ri+4])
ri += 4
//报文尾
r.Crc16 = binary.LittleEndian.Uint16(buf[ri : ri+2])
//
return nil
}
/////////////////////////////////////////////////////////
// RsspSsr 时序校正应答包用于回应SSE
type RsspSsr struct {
RsspHead
//安全校验域-应答方的序列号(4Byte)
SrSn uint32
//安全校验域-请求方的序列号(4Byte)
SeSn uint32
//安全校验域-时序初始化通道1(4Byte)
Tic1 uint32
//安全校验域-时序初始化通道2(4Byte)
Tic2 uint32
//安全校验域-数据版本号(1Byte)
Dvn byte
//报文尾-CRC16(2Byte)
Crc16 uint16
}
func (r *RsspSsr) Encode() []byte {
data := make([]byte, 0, 25)
//报文头
data = append(data, r.RsspHead.encode()...)
//安全校验域
data = binary.LittleEndian.AppendUint32(data, r.SrSn)
data = binary.LittleEndian.AppendUint32(data, r.SeSn)
data = binary.LittleEndian.AppendUint32(data, r.Tic1)
data = binary.LittleEndian.AppendUint32(data, r.Tic2)
data = append(data, r.Dvn)
//报文尾-CRC16
r.Crc16 = Rssp_I_Crc16(data)
data = binary.LittleEndian.AppendUint16(data, r.Crc16)
return data
}
func (r *RsspSsr) Decode(buf []byte) error {
//报文头
r.RsspHead.decode(buf)
//安全校验域
ri := 6
r.SrSn = binary.LittleEndian.Uint32(buf[ri : ri+4])
ri += 4
r.SeSn = binary.LittleEndian.Uint32(buf[ri : ri+4])
ri += 4
r.Tic1 = binary.LittleEndian.Uint32(buf[ri : ri+4])
ri += 4
r.Tic2 = binary.LittleEndian.Uint32(buf[ri : ri+4])
ri += 4
r.Dvn = buf[ri]
ri += 1
//报文尾
r.Crc16 = binary.LittleEndian.Uint16(buf[ri : ri+2])
//
return nil
}
//////////////////////////////////////////////////////////////
type RsspCodec interface {
Encode() []byte
Decode(buf []byte) error
}
type Rssper interface {
Type() RsspType
}
type RsspType = byte
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:
return true
case RSD_B:
return true
case SSR:
return true
case SSE:
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:
return true
case PIC_SLAVE:
return true
default:
return false
}
}
// ParseRsspPack 解析已经校验的RSSP数据包
func ParseRsspPack(ph *RsspHead, pack []byte) Rssper {
//
var codec RsspCodec
switch ph.Mc {
case RSD_A:
fallthrough
case RSD_B:
codec = &RsspRsd{}
case SSE:
codec = &RsspSse{}
case SSR:
codec = &RsspSsr{}
default:
return nil
}
//
if codec.Decode(pack) == nil {
return codec.(Rssper)
}
return nil
}
// 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()
}
////////////////////////////////////////////////////////////////////