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") } } }