rts-sim-testing-service/third_party/balisecodec/codec.go
thesai f1efd5a2f2 [补充]12号线联锁通信应答器数据解析;
[修改]联锁配置中的车站编号不再改为车站uid
2024-08-08 13:23:25 +08:00

179 lines
4.3 KiB
Go
Raw 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 balisecodec
import (
"encoding/hex"
"fmt"
"log/slog"
"strconv"
)
// 应答器数据编解码器
type Codec interface {
}
const (
Bytes1023 = 128
)
func Decode(byte128 []byte) ([]byte, error) {
if len(byte128) != Bytes1023 {
return nil, buildError("应答器报文长度错误, 期望长度为128字节")
}
bits1023 := convertTo1023Bits(byte128)
// 检查控制位
err := checkCb(bits1023)
if err != nil {
return nil, err
}
// 检查913位数据并将913位数据转换为830位数据
data913 := getRange(bits1023, 1022, 110)
scrambled830, err := convert913To830(data913)
if err != nil {
return nil, err
}
// 根据加扰位计算得到加扰器初始值S
S := calculateS(getRange(bits1023, 106, 95))
// 解扰
descrambled830 := descrambling(scrambled830, S)
// 还原第一个10位值
reverted830 := revertFirst10Bits(descrambled830)
// 转换为左边为最高有效位MSB的字节数组
byte104 := toBytes(reverted830)
return byte104, nil
}
// 解码应答器数据,1023/341位解码
// msg - 128字节数据
// return - 830/210位数据
func DecodeByteString(msg string) ([]byte, error) {
length := len(msg)
if length != 256 {
panic("invalid length")
}
// 字节转换为字节数组
slog.Debug("待解码的1023应答器报文", "msg", msg)
bytes := ConvertByteStringToBytes(msg)
return Decode(bytes)
}
// 转换字节16进制字符串为字节数组
func ConvertByteStringToBytes(msg string) []byte {
bytes, err := hex.DecodeString(msg)
if err != nil {
panic(err)
}
return bytes
}
// 将830位补末尾补1到832位然后转换为左边为最高有效位MSB的字节数组
func toBytes(reverted830 []byte) []byte {
reverted830 = append(reverted830, 1, 1)
byte104 := make([]byte, 104)
for i := 0; i < 104; i++ {
byte104[i] = byte(ToValLeftMsb(reverted830[i*8 : i*8+8]))
}
return byte104
}
func buildError(msg string) error {
return fmt.Errorf("应答器1023解码错误%s", msg)
}
// 检查控制位
func checkCb(bits1023 []byte) error {
cb := getRange(bits1023, 109, 107)
for i, v := range cb {
n := 109 - i
name := "b" + strconv.Itoa(109-i)
slog.Info("cb", name, v)
if n == 109 && v == 1 {
return buildError("控制位cb错误b109应该为0实际为1")
} else if n == 108 && v == 1 {
return buildError("控制位cb错误b108应该为0实际为1")
} else if n == 107 && v == 0 {
return buildError("控制位cb错误b107应该为1实际为0")
}
}
return nil
}
func getRange(bits []byte, start, end int) []byte {
if start < 0 || end < 0 || start < end || start > 1022 {
panic("invalid range")
}
return bits[1022-start : 1022-(end-1)]
}
// 转换128字节数据为1023位数据
func convertTo1023Bits(byte128 []byte) []byte {
if len(byte128) != 128 {
panic("invalid length")
}
// 字节转换为bit数组
bits := make([]byte, 1024)
for i, bt := range byte128 {
for j := 0; j < 8; j++ {
move := 7 - j
idx := i*8 + j
bits[idx] = (bt >> move) & 1
}
}
bits1023 := bits[0:1023]
return bits1023
}
// 由加扰位计算得到的S作为初始状态为S的32位线性反馈移位寄存器对数据进行加扰
func calculateS(sb []byte) uint32 {
// 由加扰计算得到的S作为初始状态为S的32位线性反馈移位寄存器对数据进行加扰
if len(sb) != 12 {
panic("invalid length")
}
B := ToValLeftMsb(sb)
const A uint64 = 2801775573
S := uint32((A * uint64(B)) % (1 << 32))
slog.Info("由12位加扰位计算得到整数S", "B", B, "S", S, "Sb", fmt.Sprintf("%032b", S))
return S
}
// 以11位为一组比较两个913位的报文
func compare913(b913 []byte, compare []byte) {
if len(b913) != 913 {
panic("invalid length")
}
for i := 0; i < 913; i += 11 {
for j := 0; j < 11; j++ {
print(b913[i+j])
}
println()
for j := 0; j < 11; j++ {
print(compare[i+j])
}
println()
println()
}
}
// 比较830位数据
func compare830(b830 []byte, compare830 []byte) {
if len(b830) != 830 {
panic("invalid length")
}
for i := 0; i < 83; i++ {
for j := 0; j < 10; j++ {
fmt.Printf("%01b", b830[i*10+j])
}
println()
for j := 0; j < 10; j++ {
fmt.Printf("%01b", compare830[i*10+j])
}
println()
println()
}
for i := 0; i < 830; i++ {
if b830[i] != compare830[i] {
slog.Info("error", "index", i, "b830", b830[i], "compare", compare830[i])
panic("830 bit compare error")
}
}
}