[bug]北京12号线计轴通信编解码bug
This commit is contained in:
parent
8a6de531c8
commit
aa04a9fbf4
37
config/bj_local_pxf_2.yml
Normal file
37
config/bj_local_pxf_2.yml
Normal 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
|
12
third_party/axle_device/beijing12/msg/rsd.go
vendored
12
third_party/axle_device/beijing12/msg/rsd.go
vendored
@ -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
|
||||
}
|
||||
|
||||
|
132
third_party/axle_device/beijing12/service.go
vendored
132
third_party/axle_device/beijing12/service.go
vendored
@ -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
|
||||
|
19
third_party/axle_device/beijing12/service_test.go
vendored
Normal file
19
third_party/axle_device/beijing12/service_test.go
vendored
Normal 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))
|
||||
}
|
Loading…
Reference in New Issue
Block a user