首次提交完整的python工程代码

This commit is contained in:
2026-06-15 20:38:42 +08:00
commit bca485d748
159 changed files with 248076 additions and 0 deletions

0
converter/__init__.py Normal file
View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

6
converter/a_to_b.py Normal file
View File

@@ -0,0 +1,6 @@
from converter.base_converter import BaseConverter
class A2BConverter(BaseConverter):
def convert(self, data):
# 后续填协议
return data

6
converter/a_to_c.py Normal file
View File

@@ -0,0 +1,6 @@
from converter.base_converter import BaseConverter
class A2CConverter(BaseConverter):
def convert(self, data):
# 后续填协议
return data

181
converter/b_to_d.py Normal file
View File

@@ -0,0 +1,181 @@
# 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

6
converter/b_to_e.py Normal file
View File

@@ -0,0 +1,6 @@
from converter.base_converter import BaseConverter
class B2EConverter(BaseConverter):
def convert(self, data):
# 后续填协议
return data

View File

@@ -0,0 +1,7 @@
from typing import Optional
class BaseConverter:
def convert(self, data: bytes) -> Optional[bytes]:
"""所有转换器必须实现此方法"""
raise NotImplementedError

244
converter/c_to_a.py Normal file
View File

@@ -0,0 +1,244 @@
import struct
from typing import Optional
from converter.base_converter import BaseConverter
from utils.logger import logger
from utils.hex_helper import hex_dump
# ====================== 指令映射表 ======================
CMD_MAP = {
"5555000811110010A5A5A5A5A5A5A5A5A5": "K3008",
"5555000911110010A5A5A5A5A5A5A5A5A5": "K3009",
"5555000A11110010A5A5A5A5A5A5A5A5A5": "K3010",
"5555000B11110010A5A5A5A5A5A5A5A5A5": "K3011",
"88880A0506040004000400A5A5A5A5A5A5": "K6307",
"88880A0506040104010401A5A5A5A5A5A5": "K6308",
"88880A0506040204020402A5A5A5A5A5A5": "K6309",
"88880A0506040304030403A5A5A5A5A5A5": "K6310",
"88880A0506040404040404A5A5A5A5A5A5": "K6311",
"88880A0506040504050405A5A5A5A5A5A5": "K6312",
"88880A0506040604060406A5A5A5A5A5A5": "K6313",
"88880A0506040704070407A5A5A5A5A5A5": "K6314",
"88880A0506040804080408A5A5A5A5A5A5": "K6315",
"88880A0506040904090409A5A5A5A5A5A5": "K6316",
"88880A0506040A040A040AA5A5A5A5A5A5": "K6317",
"88880A0506040B040B040BA5A5A5A5A5A5": "K6318",
"88880A0506040C040C040CA5A5A5A5A5A5": "K6319",
"88880A0506040D040D040DA5A5A5A5A5A5": "K6320",
"88880A0506040E040E040EA5A5A5A5A5A5": "K6321",
"88880A0506040F040F040FA5A5A5A5A5A5": "K6322",
"88880A0506050005000500A5A5A5A5A5A5": "K6323",
"88880A0506050105010501A5A5A5A5A5A5": "K6324",
"88880A0506050205020502A5A5A5A5A5A5": "K6325",
"88880A0506050305030503A5A5A5A5A5A5": "K6326",
"88880A0506050405040504A5A5A5A5A5A5": "K6327",
"88880A0506050505050505A5A5A5A5A5A5": "K6328",
"88880A0506050605060506A5A5A5A5A5A5": "K6329",
"88880A0506050705070507A5A5A5A5A5A5": "K6330",
"88880A0506050805080508A5A5A5A5A5A5": "K6331",
"88880A0506050905090509A5A5A5A5A5A5": "K6332",
"88880A0506050A050A050AA5A5A5A5A5A5": "K6333",
"88880A0506050B050B050BA5A5A5A5A5A5": "K6334",
"88880A0506050C050C050CA5A5A5A5A5A5": "K6335",
"88880A0506050D050D050DA5A5A5A5A5A5": "K6336",
"88880A0506050E050E050EA5A5A5A5A5A5": "K6337",
"88880A0506050F050F050FA5A5A5A5A5A5": "K6338",
"88880A0506060006000600A5A5A5A5A5A5": "K6339",
"88880A0506060106010601A5A5A5A5A5A5": "K6340",
"88880A0506060206020602A5A5A5A5A5A5": "K6341",
"88880A0506060306030603A5A5A5A5A5A5": "K6342",
"88880A0506060406040604A5A5A5A5A5A5": "K6343",
"88880A0506060506050605A5A5A5A5A5A5": "K6344",
"88880A0506060606060606A5A5A5A5A5A5": "K6345",
"88880A0506060706070607A5A5A5A5A5A5": "K6346",
"88880A0506060806080608A5A5A5A5A5A5": "K6347",
"88880A0506060906090609A5A5A5A5A5A5": "K6348",
"88880A0506060A060A060AA5A5A5A5A5A5": "K6349",
"88880A0506060B060B060BA5A5A5A5A5A5": "K6350",
"88880A0506060C060C060CA5A5A5A5A5A5": "K6351",
"88880A0506060D060D060DA5A5A5A5A5A5": "K6352",
"88880A0506060E060E060EA5A5A5A5A5A5": "K6353",
"88880A0506060F060F060FA5A5A5A5A5A5": "K6354",
"88880A0506070007000700A5A5A5A5A5A5": "K6355",
"88880A0506070107010701A5A5A5A5A5A5": "K6356",
"88880A0506070207020702A5A5A5A5A5A5": "K6357",
"88880A0506070307030703A5A5A5A5A5A5": "K6358",
"88880A0506070407040704A5A5A5A5A5A5": "K6359",
"88880A0506070507050705A5A5A5A5A5A5": "K6360",
"88880A0506070607060706A5A5A5A5A5A5": "K6361",
"88880A0506070707070707A5A5A5A5A5A5": "K6362",
"88880A0506070807080708A5A5A5A5A5A5": "K6363",
"88880A0506070907090709A5A5A5A5A5A5": "K6364",
"88880A0506070A070A070AA5A5A5A5A5A5": "K6365",
"88880A0506070B070B070BA5A5A5A5A5A5": "K6366",
"88880A0506070C070C070CA5A5A5A5A5A5": "K6367",
"88880A0506070D070D070DA5A5A5A5A5A5": "K6368",
"88880A0506070E070E070EA5A5A5A5A5A5": "K6369",
"88880A0506070F070F070FA5A5A5A5A5A5": "K6370",
"88880101061111001B0000A5A5A5A5A5A5": "K6155",
"88880101061111001C0000A5A5A5A5A5A5": "K6156",
"88880101061111001F0000A5A5A5A5A5A5": "K6159",
"8888010106111100200000A5A5A5A5A5A5": "K6160",
"8888010106111100620000A5A5A5A5A5A5": "K6225",
"8888010106111100630000A5A5A5A5A5A5": "K6226",
"8888010106111100210000A5A5A5A5A5A5": "K6161",
"8888010106111100220000A5A5A5A5A5A5": "K6162",
"8888010106111100270000A5A5A5A5A5A5": "K6166",
"8888010106111100280000A5A5A5A5A5A5": "K6167",
"8888010106111100330000A5A5A5A5A5A5": "K6178",
"8888010106111100340000A5A5A5A5A5A5": "K6179",
"8888010106111100350000A5A5A5A5A5A5": "K6180",
"8888010106111100360000A5A5A5A5A5A5": "K6181",
"88880101061111006A0000A5A5A5A5A5A5": "K6233",
"88880101061111006B0000A5A5A5A5A5A5": "K6234",
"88880101061111007E0000A5A5A5A5A5A5": "K6253",
"88880101061111007F0000A5A5A5A5A5A5": "K6254",
"88880C1B0C020222BBAAAAAAAAAAAAAA33": "K6557",
"88880C1B0C020222CCAAAAAAAAAAAAAA44": "K6558",
"88880101061111003D0000A5A5A5A5A5A5": "K6188",
"88880101061111003E0000A5A5A5A5A5A5": "K6189",
"88880101061111003F0000A5A5A5A5A5A5": "K6190",
"8888010106111100400000A5A5A5A5A5A5": "K6191",
"8888010106111100410000A5A5A5A5A5A5": "K6192",
"8888010106111100420000A5A5A5A5A5A5": "K6193",
"8888010106111100430000A5A5A5A5A5A5": "K6194",
"8888010106111100440000A5A5A5A5A5A5": "K6195",
"88880C1B0C02021177AAAAAAAAAAAAAACC": "K6451",
"88880C1B0C02021188AAAAAAAAAAAAAA33": "K6452",
"88880101061111000B0000A5A5A5A5A5A5": "K6139",
"88880101061111000C0000A5A5A5A5A5A5": "K6140",
"8888010106111100170000A5A5A5A5A5A5": "K6151",
"8888010106111100180000A5A5A5A5A5A5": "K6152",
"8888010106111100610000A5A5A5A5A5A5": "K6224",
"8888010106111100780000A5A5A5A5A5A5": "K6247",
"8888010106111100790000A5A5A5A5A5A5": "K6248",
#2026/4/13新增
"888810010AA0A00000000000000000A5A5":"K6669",
"888810010A40500000000000000000A5A5":"K6670",
"888810010A50400000000000000000A5A5":"K6671",
"888810010A6070AB180000AB180000A5A5":"K6672",
"888810010A7060AB180000AB180000A5A5":"K6673",
"888810010A00000000000000000000A5A5":"K6674",
"888810010A20300000000000000000A5A5":"K6675",
"888810010A30200000000000000000A5A5":"K6676",
#2026/4/16新增
"888810010A00300000000000000000A5A5":"K6677",
"888810010A00200000000000000000A5A5":"K6678",
"888810010A00500000000000000000A5A5":"K6679",
"888810010A00400000000000000000A5A5":"K6680",
"888810010A007000000000AB180000A5A5":"K6681",
"888810010A006000000000AB180000A5A5":"K6682",
"888810010A00A00000000000000000A5A5":"K6683",
"888810010A20000000000000000000A5A5":"K6684",
"888810010A30000000000000000000A5A5":"K6685",
"888810010A20500000000000000000A5A5":"K6686",
"888810010A30400000000000000000A5A5":"K6687",
"888810010A207000000000AB180000A5A5":"K6688",
"888810010A306000000000AB180000A5A5":"K6689",
"888810010A20A00000000000000000A5A5":"K6690",
"888810010A30A00000000000000000A5A5":"K6691",
"888810010A40000000000000000000A5A5":"K6692",
"888810010A50000000000000000000A5A5":"K6693",
"888810010A40300000000000000000A5A5":"K6694",
"888810010A50200000000000000000A5A5":"K6695",
"888810010A407000000000AB180000A5A5":"K6696",
"888810010A506000000000AB180000A5A5":"K6697",
"888810010A40A00000000000000000A5A5":"K6698",
"888810010A50A00000000000000000A5A5":"K6699",
"888810010A6000AB18000000000000A5A5":"K6700",
"888810010A7000AB18000000000000A5A5":"K6701",
"888810010A6030AB18000000000000A5A5":"K6702",
"888810010A7020AB18000000000000A5A5":"K6703",
"888810010A6050AB18000000000000A5A5":"K6704",
"888810010A7040AB18000000000000A5A5":"K6705",
"888810010A60A0AB18000000000000A5A5":"K6706",
"888810010A70A0AB18000000000000A5A5":"K6707",
"888810010AA0000000000000000000A5A5":"K6708",
"888810010AA0300000000000000000A5A5":"K6709",
"888810010AA0200000000000000000A5A5":"K6710",
"888810010AA0500000000000000000A5A5":"K6711",
"888810010AA0400000000000000000A5A5":"K6712",
"888810010AA07000000000AB180000A5A5":"K6713",
"888810010AA06000000000AB180000A5A5":"K6714",
"888810010A40400000000000000000A5A5":"K6715",
"888810010A50500000000000000000A5A5":"K6716",
"888810010A6060AB180000AB180000A5A5":"K6717",
"888810010A7070AB180000AB180000A5A5":"K6718",
"888810010A20200000000000000000A5A5":"K6719",
"888810010A30300000000000000000A5A5":"K6720",
"888810010A20400000000000000000A5A5":"K6723",
"888810010A30500000000000000000A5A5":"K6724",
"888810010A206000000000AB180000A5A5":"K6725",
"888810010A307000000000AB180000A5A5":"K6726",
"888810010A40200000000000000000A5A5":"K6727",
"888810010A50300000000000000000A5A5":"K6728",
"888810010A406000000000AB180000A5A5":"K6729",
"888810010A507000000000AB180000A5A5":"K6730",
"888810010A6020AB18000000000000A5A5":"K6731",
"888810010A7030AB18000000000000A5A5":"K6732",
"888810010A6040AB18000000000000A5A5":"K6733",
"888810010A7050AB18000000000000A5A5":"K6734",
"BBBBFF0101A5A5A5A5A5A5A5A5A5A5A5A5":"K1085",
"BBBBFF0202A5A5A5A5A5A5A5A5A5A5A5A5":"K1089",
}
class C2AConverter(BaseConverter):
def convert(self, data: bytes) -> Optional[bytes]:
try:
# ========= 1. 截取指令码B48~B64 =========
if len(data) < 65:
logger.warning("帧长度不足,无法解析指令")
return None
# cmd_bytes = data[48:48+17]#遥控通道遥控帧
cmd_bytes = data[54:(54+17)]#地测通道遥控帧
cmd_hex = cmd_bytes.hex().upper()
#logger.info(f"🔍 提取指令码:{cmd_hex}")
# ========= 2. 查询指令是否需要转发 =========
if cmd_hex not in CMD_MAP:
#logger.info(" 指令不在转发列表,不发送给 A")
return None
cmd_code = CMD_MAP[cmd_hex]
logger.info(f"✅ 匹配指令:{cmd_code},准备转发给 A")
# ========= 3. 提取数字4位十进制 =========
num_str = cmd_code[1:] # K3008 → 3008
num = int(num_str)
logger.info(f"✅ 匹配指令:{cmd_code},🔢 指令编号:{num_str}{num}")
# ========= 4. 转 double8字节 大端) =========
double_big = struct.pack('>d', float(num))
# ========= 5. 组 A 软件协议帧 =========
HEADER = 0xEB90EB90
DATA_LEN = 0x08
if num == 1085 or num == 1089:
DIR = 0x02222222 #控制前端到同元
DATA_ID = 0x00330000 #测控
else:
DIR = 0x01111111 #0x02222222改为0x01111111(数字卫星到同元)
DATA_ID = 0x00440000 #SADA
PARAM_TYPE = 0x00222222
SATELLITE = 0x00000001
TAIL = 0x4C3A
frame = (
struct.pack('>I', HEADER)
+ struct.pack('>I', DATA_LEN)
+ struct.pack('>I', DIR)
+ struct.pack('>I', DATA_ID)
+ struct.pack('>I', PARAM_TYPE)
+ struct.pack('>I', SATELLITE)
+ double_big
+ struct.pack('>H', TAIL)
)
hex_dump(frame, f"向A 软件发送帧 [{cmd_code}]")
return frame
except Exception as e:
logger.error(f"C→A 转换失败:{e}", exc_info=True)
return None

10
converter/c_to_b.py Normal file
View File

@@ -0,0 +1,10 @@
from converter.base_converter import BaseConverter
from utils.logger import logger
from utils.hex_helper import hex_dump
class C2BConverter(BaseConverter):
def convert(self, data: bytes):
# 无条件透传给 B
hex_dump(data, "C→B 透传指令")
logger.info("✅ 指令已透传给 B 软件")
return data