feat(adsb): improve ACARS/VDL2 panels with history, clear, smooth updates, and translation

- Persist ACARS/VDL2 messages across page refresh via new /acars/messages
  and /vdl2/messages endpoints backed by FlightCorrelator
- Add clear buttons to ACARS/VDL2 sidebars and right-panel datalink section
  with /acars/clear and /vdl2/clear endpoints
- Fix right-panel DATALINK MESSAGES flickering by diffing innerHTML before
  updating, with opacity transition for smooth refreshes
- Add aircraft deselect toggle (click selected aircraft again to deselect)
- Enrich VDL2 messages with ACARS label translation (label_description,
  message_type, parsed fields) matching existing ACARS translator

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Mitch Ross
2026-02-20 23:48:50 -05:00
parent 01409cfdea
commit c2405bfe14
4 changed files with 186 additions and 18 deletions
+20
View File
@@ -443,6 +443,26 @@ def stream_acars() -> Response:
return response
@acars_bp.route('/messages')
def get_acars_messages() -> Response:
"""Get recent ACARS messages from correlator (for history reload)."""
from utils.flight_correlator import get_flight_correlator
limit = request.args.get('limit', 50, type=int)
limit = max(1, min(limit, 200))
msgs = get_flight_correlator().get_recent_messages('acars', limit)
return jsonify(msgs)
@acars_bp.route('/clear', methods=['POST'])
def clear_acars_messages() -> Response:
"""Clear stored ACARS messages and reset counter."""
global acars_message_count
from utils.flight_correlator import get_flight_correlator
get_flight_correlator().clear_acars()
acars_message_count = 0
return jsonify({'status': 'cleared'})
@acars_bp.route('/frequencies')
def get_frequencies() -> Response:
"""Get default ACARS frequencies."""
+36
View File
@@ -79,6 +79,22 @@ def stream_vdl2_output(process: subprocess.Popen, is_text_mode: bool = False) ->
data['type'] = 'vdl2'
data['timestamp'] = datetime.utcnow().isoformat() + 'Z'
# Enrich embedded ACARS payload with translated label
try:
vdl2_inner = data.get('vdl2', data)
acars_payload = (vdl2_inner.get('avlc') or {}).get('acars')
if acars_payload and acars_payload.get('label'):
from utils.acars_translator import translate_message
translation = translate_message({
'label': acars_payload.get('label'),
'text': acars_payload.get('msg_text', ''),
})
acars_payload['label_description'] = translation['label_description']
acars_payload['message_type'] = translation['message_type']
acars_payload['parsed'] = translation['parsed']
except Exception:
pass
# Update stats
vdl2_message_count += 1
vdl2_last_message_time = time.time()
@@ -370,6 +386,26 @@ def stream_vdl2() -> Response:
return response
@vdl2_bp.route('/messages')
def get_vdl2_messages() -> Response:
"""Get recent VDL2 messages from correlator (for history reload)."""
from utils.flight_correlator import get_flight_correlator
limit = request.args.get('limit', 50, type=int)
limit = max(1, min(limit, 200))
msgs = get_flight_correlator().get_recent_messages('vdl2', limit)
return jsonify(msgs)
@vdl2_bp.route('/clear', methods=['POST'])
def clear_vdl2_messages() -> Response:
"""Clear stored VDL2 messages and reset counter."""
global vdl2_message_count
from utils.flight_correlator import get_flight_correlator
get_flight_correlator().clear_vdl2()
vdl2_message_count = 0
return jsonify({'status': 'cleared'})
@vdl2_bp.route('/frequencies')
def get_frequencies() -> Response:
"""Get default VDL2 frequencies."""