[bug]北京12号线计轴通信编解码bug

This commit is contained in:
thesai 2024-07-11 09:20:51 +08:00
parent 8a6de531c8
commit aa04a9fbf4
4 changed files with 146 additions and 54 deletions

37
config/bj_local_pxf_2.yml Normal file
View File

@ -0,0 +1,37 @@
# 服务配置
server:
# 服务端口
port: 9092
# 数据源
datasource:
# 数据库访问url
dsn: root:Joylink@0503@tcp(172.29.5.167:3306)/bj-rtsts?charset=utf8mb4&parseTime=true&loc=UTC
# 日志配置
logging:
# 日志级别
level: info
# 格式化
# format: json
# 日志文件路径
path: /home/joylink/logs/bjrtsts2
# 日志文件名
fileName: bjrtsts.log
# 单个日志文件大小,单位mb,超过会自动滚动
fileMaxSize: 50
# 日志文件最大备份数量
fileMaxBackups: 100
# 日志文件最大保留时间,单位 天
maxAge: 30
# 是否压缩日志
compress: false
# 控制台是否输出
stdout: false
# 消息配置
messaging:
mqtt:
address: tcp://172.29.5.168:1883
username: rtsts_service
password: joylink@0503

View File

@ -21,13 +21,13 @@ type RsdMsg struct {
func (r *RsdMsg) Encode() []byte {
data := r.MsgHeader.encode()
data = binary.BigEndian.AppendUint32(data, r.SeqNum)
data = binary.BigEndian.AppendUint16(data, r.UserDataLen)
data = binary.BigEndian.AppendUint32(data, r.Svc1)
data = binary.BigEndian.AppendUint32(data, r.Svc2)
data = binary.LittleEndian.AppendUint32(data, r.SeqNum)
data = binary.LittleEndian.AppendUint16(data, r.UserDataLen)
data = binary.LittleEndian.AppendUint32(data, r.Svc1)
data = binary.LittleEndian.AppendUint32(data, r.Svc2)
data = append(data, r.UserData...)
r.Tail = message.Rssp_I_Crc16(r.UserData)
data = binary.BigEndian.AppendUint16(data, r.Tail)
r.Tail = message.Rssp_I_Crc16(data)
data = binary.LittleEndian.AppendUint16(data, r.Tail)
return data
}

View File

@ -38,21 +38,24 @@ type serviceContext struct {
cancelFunc context.CancelFunc
ciSectionIndexConfigs []*proto.CiSectionCodePoint
remoteAddr uint16 //联锁地址 从配置中的16进制字符串转来的
localAddr uint16 //计轴地址 从配置中的16进制字符串转来的
sid1 uint32 //联锁SID1 从配置中的16进制字符串转来的
sid2 uint32 //联锁SID2 从配置中的16进制字符串转来的
localSid1 uint32 //计轴SID1 从配置中的16进制字符串转来的
localSid2 uint32 //计轴SID2 从配置中的16进制字符串转来的
sinit1 uint32 //SINT16 从配置中的16进制字符串转来的
sinit2 uint32 //SINT26 从配置中的16进制字符串转来的
msgChan <-chan []byte //消息队列
seqNum uint32 //当前的序列号
lastSeqParam uint32 //最近一次的有效时序参数
lfsr1 lfsr //用来计算时间戳的lfsr
lfsr2 lfsr //用来计算时间戳的lfsr
sseMsg *msg.SseMsg //发送出去的时序校验请求
sseWaitTimer <-chan time.Time //sse超时定时器
remoteAddr uint16 //联锁地址 从配置中的16进制字符串转来的
localAddr uint16 //计轴地址 从配置中的16进制字符串转来的
sid1 uint32 //联锁SID1 从配置中的16进制字符串转来的
sid2 uint32 //联锁SID2 从配置中的16进制字符串转来的
localSid1 uint32 //计轴SID1 从配置中的16进制字符串转来的
localSid2 uint32 //计轴SID2 从配置中的16进制字符串转来的
sinit1 uint32 //SINT16 从配置中的16进制字符串转来的
sinit2 uint32 //SINT26 从配置中的16进制字符串转来的
dataver1 uint32 //DATAVER1 从配置中的16进制字符串转来的
dataver2 uint32 //DATAVER2 从配置中的16进制字符串转来的
msgChan <-chan []byte //消息队列
seqNum uint32 //当前的序列号
lastSeqParam1 uint32 //最近一次的有效时序参数 sid1^t1(n)
lastSeqParam2 uint32 //最近一次的有效时序参数 sid2^t2(n)
lfsr1 *lfsr //用来计算时间戳的lfsr
lfsr2 *lfsr //用来计算时间戳的lfsr
sseMsg *msg.SseMsg //发送出去的时序校验请求
sseWaitTimer <-chan time.Time //sse超时定时器
}
func Start(simulation *memory.VerifySimulation) {
@ -110,6 +113,14 @@ func Start(simulation *memory.VerifySimulation) {
if err != nil {
panic(sys_error.New(fmt.Sprintf("%s集中站[%s]解析SINT2[%s]出错", logTag, rsspConfig.StationCode, rsspConfig.NetAConfig.Sinit2)))
}
dataver1, err := strconv.ParseUint(rsspConfig.NetAConfig.DataVer1, 16, 32)
if err != nil {
panic(sys_error.New(fmt.Sprintf("%s集中站[%s]解析DATAVER_1[%s]出错", logTag, rsspConfig.StationCode, rsspConfig.NetAConfig.DataVer1)))
}
dataver2, err := strconv.ParseUint(rsspConfig.NetAConfig.DataVer2, 16, 32)
if err != nil {
panic(sys_error.New(fmt.Sprintf("%s集中站[%s]解析DATAVER_2[%s]出错", logTag, rsspConfig.StationCode, rsspConfig.NetAConfig.DataVer2)))
}
//服务初始化及启动
msgChan := make(chan []byte, 100)
serviceCtx := &serviceContext{
@ -124,13 +135,15 @@ func Start(simulation *memory.VerifySimulation) {
localSid2: uint32(localSid2),
sinit1: uint32(sinit1),
sinit2: uint32(sinit2),
dataver1: uint32(dataver1),
dataver2: uint32(dataver2),
msgChan: msgChan,
seqNum: 1,
lfsr1: lfsr{value: uint32(localSid1)},
lfsr2: lfsr{value: uint32(localSid2)},
lfsr1: &lfsr{value: uint32(localSid1), poly: msg.T_POLY_1},
lfsr2: &lfsr{value: uint32(localSid2), poly: msg.T_POLY_2},
}
netAConfig := rsspConfig.NetAConfig
server := udp.NewServer(fmt.Sprintf("%s:%d", netAConfig.LocalIp, netAConfig.LocalPort), func(b []byte) {
logger().Info(fmt.Sprintf("收到数据:%x", b))
msgChan <- b
})
client := udp.NewClient(fmt.Sprintf("%s:%d", netAConfig.RemoteIp, netAConfig.RemotePort))
@ -147,6 +160,13 @@ func Start(simulation *memory.VerifySimulation) {
serviceCtx.runCollectTask(cancelCtx)
serviceCtx.runHandleMsgTask(cancelCtx)
contextMap[rsspConfig.StationCode] = serviceCtx
////sse测试测完删除
//time.Sleep(1 * time.Second)
//serviceCtx.seqNum++
//serviceCtx.lfsr1.add(0)
//serviceCtx.lfsr2.add(0)
//serviceCtx.startSeeProgress()
}
func Stop(simulation *memory.VerifySimulation) {
@ -179,15 +199,18 @@ func (s *serviceContext) runCollectTask(ctx context.Context) {
s.runCollectTask(ctx)
}
}()
for range time.Tick(time.Millisecond * time.Duration(s.config.NetAConfig.Period) * time.Millisecond) {
for range time.Tick(time.Duration(s.config.NetAConfig.Period) * time.Millisecond) {
select {
case <-ctx.Done():
return
default:
frame := s.collect()
err := s.client.Send(frame.Encode())
data := frame.Encode()
err := s.client.Send(data)
if err != nil {
logger().Error("发送状态数据失败", "error", err)
} else {
logger().Info(fmt.Sprintf("发送数据:%x", data))
}
}
}
@ -245,7 +268,13 @@ func (s *serviceContext) collect() *msg.RsdMsgBuilder {
RJT: sectionRuntime.Rjt,
})
}
userData := stateInfos.Encode()
userData := []byte{0x00} //检查字节
userData = append(userData, stateInfos.Encode()...)
//更新序列号及时间戳
s.seqNum++
s.lfsr1.add(0)
s.lfsr2.add(0)
//构建消息
builder := &msg.RsdMsgBuilder{
MsgHeader: msg.MsgHeader{
ProtocolType: msg.ProtocolType_Sync,
@ -258,22 +287,15 @@ func (s *serviceContext) collect() *msg.RsdMsgBuilder {
Svc2: s.calculateSvc2(userData),
UserData: userData,
}
s.seqNum++
return builder
}
func (s *serviceContext) calculateSvc1(userData []byte) uint32 {
return s.calculateSvc(userData, s.localSid1, msg.SCW_1, s.lfsr1)
return message.Rssp_I_Crc32C1(userData) ^ s.localSid1 ^ s.lfsr1.value ^ msg.SCW_1
}
func (s *serviceContext) calculateSvc2(userData []byte) uint32 {
return s.calculateSvc(userData, s.localSid2, msg.SCW_2, s.lfsr2)
}
func (s *serviceContext) calculateSvc(userData []byte, sid uint32, scw uint32, l lfsr) uint32 {
crc := message.Rssp_I_Crc32C1(userData)
l.add(0)
return crc ^ sid ^ l.value ^ scw
return message.Rssp_I_Crc32C2(userData) ^ s.localSid2 ^ s.lfsr2.value ^ msg.SCW_2
}
func (s *serviceContext) handleRsdMsg(data []byte) {
@ -297,7 +319,7 @@ func (s *serviceContext) handleRsdMsg(data []byte) {
}
//流程处理
cmdInfos := msg.CmdInfos{}
err = cmdInfos.Decode(rsdMsg.UserData)
err = cmdInfos.Decode(rsdMsg.UserData[1:]) //用户数据第一个字节是[检查字节]
if err != nil {
logger().Error("解析命令信息出错", "error", err)
return
@ -325,10 +347,11 @@ func (s *serviceContext) handleSseMsg(data []byte) {
}
//校验
if !s.validateSseMsg(sseMsg) {
logger().Error("SSE数据校验失败")
return
}
logger().Info("SSE数据通过校验")
//回复
s.lastSeqParam = sseMsg.SeqNum
ssrMsg := msg.SsrMsg{
MsgHeader: msg.MsgHeader{
ProtocolType: msg.ProtocolType_Sync,
@ -342,14 +365,21 @@ func (s *serviceContext) handleSseMsg(data []byte) {
SeqInit2: s.calculateSeqInit1(sseMsg.SeqEnq1),
DataVer: 0x01,
}
err = s.client.Send(ssrMsg.Encode())
ssrBytes := ssrMsg.Encode()
err = s.client.Send(ssrBytes)
if err != nil {
logger().Error("发送SSR数据失败", "error", err)
} else {
logger().Info(fmt.Sprintf("发送SSR数据%x", ssrBytes))
//更新本地数据
s.lastSeqParam1 = sseMsg.SeqEnq1
s.lastSeqParam2 = sseMsg.SeqEnq2
}
}
func (s *serviceContext) handleSsrMsg(data []byte) {
if s.sseMsg == nil { //不在时序校正过程中
logger().Warn("不在时序校正流程中丢弃SSR数据")
return
}
ssrMsg := &msg.SsrMsg{}
@ -360,11 +390,13 @@ func (s *serviceContext) handleSsrMsg(data []byte) {
}
//校验
if !s.validateSsrMsg(ssrMsg) {
logger().Error("SSR数据校验失败")
return
}
logger().Info("SSR数据通过校验")
//完成校正时序
s.sseMsg = nil
s.lastSeqParam = ssrMsg.SeqNumSsr
s.lastSeqParam1 = ssrMsg.SeqNumSsr
}
// 启动SSE流程
@ -380,10 +412,12 @@ func (s *serviceContext) startSeeProgress() {
SeqEnq1: s.calculateSeqEnq1(),
SeqEnq2: s.calculateSeqEnq2(),
}
err := s.client.Send(sseMsg.Encode())
sseBytes := sseMsg.Encode()
err := s.client.Send(sseBytes)
if err != nil {
logger().Error("发送SSE数据失败", "error", err)
} else {
logger().Info(fmt.Sprintf("发送SSE数据%x", sseBytes))
s.sseMsg = sseMsg
s.sseWaitTimer = time.After(time.Duration(s.config.NetAConfig.Period*msg.Twait_sse) * time.Millisecond)
}
@ -400,8 +434,8 @@ func (s *serviceContext) validateRsdMsg(rsdMsg *msg.RsdMsg) int {
logger().Error(fmt.Sprintf("目的地址[%x]不正确[%s]", rsdMsg.TargetAddr, s.config.NetAConfig.LocalAddr))
return 0
}
if len(rsdMsg.UserData) != len(s.ciSectionIndexConfigs) {
logger().Error(fmt.Sprintf("用户数据长度[%d]与配置长度[%d]不符", len(rsdMsg.UserData), len(s.ciSectionIndexConfigs)))
if len(rsdMsg.UserData)-1 != len(s.ciSectionIndexConfigs) { //用户数据第一个字节是[检查字节]
logger().Error(fmt.Sprintf("命令数据长度[%d]与配置长度[%d]不符", len(rsdMsg.UserData), len(s.ciSectionIndexConfigs)))
return 0
}
if message.Rssp_I_Crc16(rsdMsg.UserData) != rsdMsg.Tail {
@ -432,22 +466,22 @@ func (s *serviceContext) validateSsrMsg(ssrMsg *msg.SsrMsg) bool {
}
func (s *serviceContext) validateSvc1(svc uint32, userData []byte) bool {
return s.validateSvc(svc, msg.SCW_1, message.Rssp_I_Crc32C1(userData), s.sid1, s.sinit1)
return s.validateSvc(svc, msg.SCW_1, message.Rssp_I_Crc32C1(userData), s.sid1, s.sinit1, &s.lastSeqParam1)
}
func (s *serviceContext) validateSvc2(svc uint32, userData []byte) bool {
return s.validateSvc(svc, msg.SCW_2, message.Rssp_I_Crc32C2(userData), s.sid2, s.sinit2)
return s.validateSvc(svc, msg.SCW_2, message.Rssp_I_Crc32C2(userData), s.sid2, s.sinit2, &s.lastSeqParam2)
}
func (s *serviceContext) validateSvc(svc uint32, scw uint32, crc1 uint32, sid uint32, sinit uint32) bool {
func (s *serviceContext) validateSvc(svc uint32, scw uint32, crc1 uint32, sid uint32, sinit uint32, lastSeqParam *uint32) bool {
seqParam := crc1 ^ svc ^ scw
if s.lastSeqParam == 0 {
s.lastSeqParam = seqParam
if *lastSeqParam == 0 {
*lastSeqParam = seqParam
return true
}
for i := 0; i < s.config.NetAConfig.MaxDeviation; i++ {
seqLfsr := lfsr{value: sinit}
seqLfsr.add(s.lastSeqParam)
seqLfsr.add(*lastSeqParam)
constLfsr := lfsr{value: sinit}
constLfsr.add(sid)
for j := 0; j < i; j++ {
@ -455,6 +489,7 @@ func (s *serviceContext) validateSvc(svc uint32, scw uint32, crc1 uint32, sid ui
constLfsr.add(0)
}
if seqLfsr.add(seqParam) == seqLfsr.add(sid) {
*lastSeqParam = seqParam
return true
}
}
@ -462,23 +497,24 @@ func (s *serviceContext) validateSvc(svc uint32, scw uint32, crc1 uint32, sid ui
}
func (s *serviceContext) calculateSeqEnq1() uint32 {
return 0
return s.localSid1 ^ s.lfsr1.value
}
func (s *serviceContext) calculateSeqEnq2() uint32 {
return 0
return s.localSid2 ^ s.lfsr2.value
}
func (s *serviceContext) calculateSeqInit1(seqEnq1 uint32) uint32 {
return 0
return seqEnq1 ^ s.sid1 ^ s.dataver1 ^ s.lfsr1.value
}
func (s *serviceContext) calculateSeqInit2(seqEnq2 uint32) uint32 {
return 0
return seqEnq2 ^ s.sid2 ^ s.dataver2 ^ s.lfsr2.value
}
type lfsr struct {
value uint32
poly uint32 //时间戳生成多项式
}
func (l *lfsr) add(x uint32) uint32 {
@ -488,7 +524,7 @@ func (l *lfsr) add(x uint32) uint32 {
carry = l.value&0x80000000 != 0
l.value = l.value << 1
if carry {
l.value ^= msg.T_POLY_1
l.value ^= l.poly
}
}
return l.value

View File

@ -0,0 +1,19 @@
package beijing12
import (
"fmt"
"joylink.club/bj-rtsts-server/third_party/axle_device/beijing12/msg"
"testing"
)
func Test_serviceContext_calculateSvc1(t *testing.T) {
serviceCtx := &serviceContext{
localSid1: 0x7665986c,
localSid2: 0x67da286e,
lfsr1: &lfsr{value: uint32(0x7665986c), poly: msg.T_POLY_1},
lfsr2: &lfsr{value: uint32(0x67da286e), poly: msg.T_POLY_2},
}
userData := []byte{00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00}
fmt.Printf("%x\n", serviceCtx.calculateSvc1(userData))
fmt.Printf("%x\n", serviceCtx.calculateSvc2(userData))
}