Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e0b1964

Browse files
authored
Merge pull request #82 from youn-same99/pr81-celestrak-tle
feat(data): 从 Celestrak 导入真实 TLE 星历并支持本地缓存
2 parents acea400 + d1b1f4d commit e0b1964

3 files changed

Lines changed: 545 additions & 0 deletions

File tree

backend/api.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,109 @@ def scenario_compare():
942942
return ok(report)
943943

944944

945+
# ==========================================
946+
# 8b. TLE 导入与缓存 API
947+
# ==========================================
948+
from backend.physics.tle_source import ( # noqa: E402
949+
fetch_group,
950+
fetch_by_catnr,
951+
get_cache_status,
952+
inject_tle_into_constellation,
953+
SUPPORTED_GROUPS,
954+
)
955+
956+
957+
@app.route('/api/tle/import', methods=['POST'])
958+
@require_role('admin')
959+
@rate_limit(5, 60)
960+
def tle_import():
961+
"""从 Celestrak 导入指定分组或编号的 TLE 星历并缓存到本地。
962+
963+
请求体(JSON)::
964+
965+
{
966+
"group": "starlink", # 星座分组名,与 catnr 二选一
967+
"catnr": 25544, # NORAD 卫星编号,与 group 二选一
968+
"force_refresh": false, # 是否强制刷新(可选,默认 false)
969+
"inject": false # 是否将 TLE 注入仿真引擎星座(可选,默认 false)
970+
}
971+
972+
响应示例::
973+
974+
{"code": 0, "data": {
975+
"group": "starlink",
976+
"entry_count": 6000,
977+
"injected": 12,
978+
"first_epoch": "2024-05-01T00:00:00Z",
979+
"cached_at": "2024-05-01T12:00:00Z"
980+
}}
981+
"""
982+
body = request.get_json(silent=True) or {}
983+
group = str(body.get("group", "")).strip()
984+
catnr = body.get("catnr")
985+
force_refresh = bool(body.get("force_refresh", False))
986+
do_inject = bool(body.get("inject", False))
987+
988+
if not group and catnr is None:
989+
return error_response("VALIDATION_ERROR", "必须提供 'group'(星座名)或 'catnr'(NORAD 编号)之一")
990+
991+
try:
992+
if catnr is not None:
993+
try:
994+
catnr_int = int(catnr)
995+
except (TypeError, ValueError):
996+
return error_response("VALIDATION_ERROR", "'catnr' 必须为整数")
997+
entries = fetch_by_catnr(catnr_int, force_refresh=force_refresh)
998+
used_group = f"catnr_{catnr_int}"
999+
else:
1000+
entries = fetch_group(group, force_refresh=force_refresh)
1001+
used_group = group
1002+
1003+
injected = 0
1004+
if do_inject and entries:
1005+
with simulation_engine.lock:
1006+
sats = list(simulation_engine.leo_satellites) + list(simulation_engine.meo_satellites)
1007+
injected = inject_tle_into_constellation(entries, sats)
1008+
1009+
first_epoch = entries[0][3] if entries else ""
1010+
return ok({
1011+
"group": used_group,
1012+
"entry_count": len(entries),
1013+
"injected": injected,
1014+
"first_epoch": first_epoch,
1015+
"supported_groups": SUPPORTED_GROUPS,
1016+
})
1017+
except Exception:
1018+
logger.exception("TLE 导入失败")
1019+
return error_response("INTERNAL_ERROR")
1020+
1021+
1022+
@app.route('/api/tle/status', methods=['GET'])
1023+
def tle_status():
1024+
"""查看本地 TLE 缓存的新鲜度与条目统计。
1025+
1026+
响应示例::
1027+
1028+
{"code": 0, "data": {
1029+
"cache_dir": "/path/to/data/tle_cache",
1030+
"total_groups": 3,
1031+
"total_tles": 18000,
1032+
"entries": [
1033+
{"group": "starlink", "fetched_at": "...", "age_seconds": 300,
1034+
"is_fresh": true, "entry_count": 6000}
1035+
],
1036+
"supported_groups": [...]
1037+
}}
1038+
"""
1039+
try:
1040+
status = get_cache_status()
1041+
status["supported_groups"] = SUPPORTED_GROUPS
1042+
return ok(status)
1043+
except Exception:
1044+
logger.exception("TLE 状态查询失败")
1045+
return error_response("INTERNAL_ERROR")
1046+
1047+
9451048
# ==========================================
9461049
# 9. 仿真快照 / 回放 API
9471050
# ==========================================

0 commit comments

Comments
 (0)