181 lines
6.4 KiB
Python
181 lines
6.4 KiB
Python
# from typing import Optional
|
||
# import struct
|
||
# from converter.base_converter import BaseConverter
|
||
# from utils.logger import logger
|
||
# from utils.checksum import calc_sum
|
||
# from utils.hex_helper import hex_dump
|
||
# from structure.b_frame import B_STAR_TIME_OFFSET, B_STAR_TIME_LEN
|
||
# from structure.d_frame import D_RAW_DATA_LEN
|
||
# from config.settings import FRAME_CONST
|
||
|
||
|
||
# class B2DConverter(BaseConverter):
|
||
# def convert(self, data: bytes) -> Optional[bytes]:
|
||
# try:
|
||
# # 1. 提取星上时
|
||
# star_time = data[B_STAR_TIME_OFFSET:B_STAR_TIME_OFFSET + B_STAR_TIME_LEN]
|
||
# if len(star_time) != 6:
|
||
# return None
|
||
|
||
# sec = star_time[:4]
|
||
# ms = star_time[4:]
|
||
# ms_4b = ms + b"\x00\x00"
|
||
|
||
# logger.info(f"星上时: {sec.hex()} {ms.hex()} → {ms_4b.hex()}")
|
||
|
||
# # 2. 拼装原始数据
|
||
# raw = sec + ms
|
||
# raw += b"\x00" * (D_RAW_DATA_LEN - len(raw))
|
||
|
||
# # 3. 校验域
|
||
# src = FRAME_CONST["SRC"]
|
||
# dst = FRAME_CONST["DST"]
|
||
# it = FRAME_CONST["IF_TYPE"]
|
||
# wa = FRAME_CONST["WORD_ADDR"]
|
||
# res2 = b"\x00\x00\x00\x00"
|
||
|
||
# check_data = struct.pack("BBBB", src, dst, it, wa) + res2 + raw
|
||
# cs = calc_sum(check_data)
|
||
|
||
# # 4. 组帧
|
||
# frame = (
|
||
# struct.pack(">H", FRAME_CONST["HEAD"])
|
||
# + struct.pack(">H", FRAME_CONST["SIM_ID"])
|
||
# + struct.pack(">H", 0x0000)
|
||
# + struct.pack(">H", FRAME_CONST["DATA_LEN"])
|
||
# + check_data
|
||
# + struct.pack(">H", cs)
|
||
# + struct.pack(">H", FRAME_CONST["TAIL"])
|
||
# )
|
||
|
||
# hex_dump(frame, "发送D帧")
|
||
# return frame
|
||
|
||
# except Exception as e:
|
||
# logger.error(f"B→D转换失败: {e}")
|
||
# return None
|
||
|
||
# @staticmethod
|
||
# def extract_bits(data: bytes, start_bit: int, bit_len: int) -> bytes:
|
||
# """
|
||
# 从字节流中精确提取 [start_bit, start_bit+bit_len) 比特
|
||
# 大端序、比特紧密对齐
|
||
# """
|
||
# bit_str = ''
|
||
# for byte in data:
|
||
# bit_str += f'{byte:08b}'
|
||
|
||
# end_bit = start_bit + bit_len
|
||
# selected = bit_str[start_bit:end_bit]
|
||
|
||
# # 不足补0
|
||
# if len(selected) < bit_len:
|
||
# selected += '0' * (bit_len - len(selected))
|
||
|
||
# # 转回 bytes
|
||
# res = b''
|
||
# for i in range(0, len(selected), 8):
|
||
# byte_bits = selected[i:i+8].ljust(8, '0')
|
||
# res += int(byte_bits, 2).to_bytes(1, byteorder='big')
|
||
|
||
# return res
|
||
|
||
from typing import Optional
|
||
import struct
|
||
from converter.base_converter import BaseConverter
|
||
from utils.logger import logger
|
||
from utils.checksum import calc_sum
|
||
from utils.hex_helper import hex_dump
|
||
from structure.d_frame import D_RAW_DATA_LEN
|
||
from config.settings import FRAME_CONST
|
||
|
||
class B2DConverter(BaseConverter):
|
||
def convert(self, data: bytes) -> Optional[bytes]:
|
||
try:
|
||
# ==============================================
|
||
# 【2026新版B遥测协议】星上时精确偏移
|
||
# ==============================================
|
||
START_BIT = 608 # 新版协议:星上时起始比特
|
||
STAR_TIME_BITS = 48 # 6B = 48b
|
||
|
||
# 从比特流中精确提取星上时
|
||
star_time_bytes = self.extract_bits(data, START_BIT, STAR_TIME_BITS)
|
||
if len(star_time_bytes) != 6:
|
||
logger.warning(f"星上时长度异常:{len(star_time_bytes)}B")
|
||
return None
|
||
|
||
# ==============================================
|
||
# 拆分:4B秒 + 2B毫秒 → 毫秒扩展为4B
|
||
# ==============================================
|
||
seconds = star_time_bytes[:4]
|
||
ms = star_time_bytes[4:]
|
||
# ✅ 大端序:高位补 0x0000(你要求的正确方式)
|
||
ms_4b = b"\x00\x00" + ms
|
||
|
||
logger.info("✅ 星上时解析成功(新版协议)")
|
||
logger.info(f" 原始6B:{star_time_bytes.hex()}")
|
||
logger.info(f" 秒值(4B):{seconds.hex()}")
|
||
logger.info(f" 毫秒(2B→4B):{ms.hex()} → {ms_4b.hex()}")
|
||
|
||
# ==============================================
|
||
# 封装 D 软件帧
|
||
# ==============================================
|
||
#raw_data = seconds + ms
|
||
raw_data = seconds + ms_4b
|
||
raw_data += b"\x00" * (D_RAW_DATA_LEN - len(raw_data))
|
||
|
||
src = FRAME_CONST["SRC"]#源
|
||
dst = FRAME_CONST["DST"]#宿
|
||
if_type = FRAME_CONST["IF_TYPE"]#接口类型
|
||
word_addr = FRAME_CONST["WORD_ADDR"]#字地址
|
||
reserved2 = b"\x00\x00\x00\x00"#保留
|
||
|
||
check_data = (
|
||
struct.pack("BBBB", src, dst, if_type, word_addr)
|
||
+ reserved2
|
||
+ raw_data
|
||
)
|
||
checksum = calc_sum(check_data)
|
||
|
||
frame = (
|
||
struct.pack(">H", FRAME_CONST["HEAD"])
|
||
+ struct.pack(">H", FRAME_CONST["SIM_ID"])
|
||
+ struct.pack(">H", 0x0000)
|
||
+ struct.pack(">H", FRAME_CONST["DATA_LEN"])
|
||
+ check_data
|
||
+ struct.pack(">H", checksum)
|
||
+ struct.pack(">H", FRAME_CONST["TAIL"])
|
||
)
|
||
|
||
hex_dump(frame, "发送D软件完整帧")
|
||
return frame
|
||
|
||
except Exception as e:
|
||
logger.error(f"B→D转换失败:{e}", exc_info=True)
|
||
return None
|
||
|
||
@staticmethod
|
||
def extract_bits(data: bytes, start_bit: int, bit_len: int) -> bytes:
|
||
"""
|
||
大端序、比特紧密对齐
|
||
从data的 start_bit 位置,提取 bit_len 长度比特 → 返回bytes
|
||
"""
|
||
# 把所有字节转成连续的01比特字符串
|
||
bitstream = ""
|
||
for byte in data:
|
||
bitstream += f"{byte:08b}"
|
||
|
||
# 截取需要的部分
|
||
selected_bits = bitstream[start_bit : start_bit + bit_len]
|
||
|
||
# 不足补0
|
||
if len(selected_bits) < bit_len:
|
||
selected_bits = selected_bits.ljust(bit_len, "0")
|
||
|
||
# 转回字节
|
||
result = b""
|
||
for i in range(0, len(selected_bits), 8):
|
||
segment = selected_bits[i:i+8].ljust(8, "0")
|
||
result += int(segment, 2).to_bytes(1, byteorder="big")
|
||
|
||
return result |