179 lines
4.3 KiB
Go
179 lines
4.3 KiB
Go
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")
|
||
}
|
||
}
|
||
}
|