From d037dc41f40d07892d5b28d180a5b32fe2e9c819 Mon Sep 17 00:00:00 2001 From: Mark Jessop Date: Fri, 23 Aug 2019 22:00:13 +0930 Subject: [PATCH] Add optional SNR display, if provided in payload summary packet, or via MODEM_STATS message. --- chasemapper/listeners.py | 5 +++++ horusmapper.py | 22 +++++++++++++++++++--- static/js/balloon.js | 12 ++++++++++++ static/js/tables.js | 12 +++++++++++- templates/index.html | 4 ++++ 5 files changed, 51 insertions(+), 4 deletions(-) diff --git a/chasemapper/listeners.py b/chasemapper/listeners.py index a7ae152..8416367 100644 --- a/chasemapper/listeners.py +++ b/chasemapper/listeners.py @@ -103,6 +103,11 @@ class UDPListener(object): if self.bearing_callback is not None: self.bearing_callback(packet_dict) + if packet_dict['type'] == 'MODEM_STATS': + if self.summary_callback is not None: + self.summary_callback(packet_dict) + + except Exception as e: print("Could not parse packet: %s" % str(e)) traceback.print_exc() diff --git a/horusmapper.py b/horusmapper.py index 7381e7d..13d622a 100644 --- a/horusmapper.py +++ b/horusmapper.py @@ -75,7 +75,7 @@ habitat_uploader = None # Copy out any extra fields from incoming telemetry that we want to pass on to the GUI. # At the moment we're really only using the burst timer field. -EXTRA_FIELDS = ['bt', 'temp', 'humidity', 'sats'] +EXTRA_FIELDS = ['bt', 'temp', 'humidity', 'sats', 'snr'] # @@ -203,7 +203,8 @@ def handle_new_payload_position(data): 'burst': [], 'abort_path': [], 'abort_landing': [], - 'max_alt': 0.0 + 'max_alt': 0.0, + 'snr': -255.0 } # Add new data into the payload's track, and get the latest ascent rate. @@ -271,6 +272,13 @@ def handle_new_payload_position(data): chase_logger.add_balloon_telemetry(data) +def handle_modem_stats(data): + """ Basic handling of modem statistics data. If it matches a known payload, send the info to the client. """ + + if data['source'] in current_payloads: + flask_emit_event('modem_stats_event', {'callsign': data['source'], 'snr': data['snr']}) + + # # Predictor Code # @@ -582,8 +590,16 @@ def ozi_listener_callback(data): def udp_listener_summary_callback(data): ''' Handle a Payload Summary Message from UDPListener ''' - # Extract the fields we need. + # Modem stats messages are also passed in via this callback. + # handle them separately. + if data['type'] == 'MODEM_STATS': + handle_modem_stats(data) + return + + # Otherwise, we have a PAYLOAD_SUMMARY message. + + # Extract the fields we need. # Convert to something generic we can pass onwards. output = {} output['lat'] = data['latitude'] diff --git a/static/js/balloon.js b/static/js/balloon.js index 8d1bfe1..6a8f30d 100644 --- a/static/js/balloon.js +++ b/static/js/balloon.js @@ -27,6 +27,7 @@ function add_new_balloon(data){ latest_data: telem, age: 0, colour: colour_values[colour_idx], + snr: -255.0, visible: true }; // Balloon Path @@ -234,6 +235,10 @@ function handleTelemetry(data){ balloon_positions[data.callsign].marker.setIcon(balloonPayloadIcons[balloon_positions[data.callsign].colour]); } + if(data.hasOwnProperty('snr') == true){ + balloon_positions[data.callsign].snr = data.snr; + } + } // Update the telemetry table display @@ -266,6 +271,13 @@ function handleTelemetry(data){ updateSummaryDisplay(); } +function handleModemStats(data){ + // Update balloon positions store with incoming modem statistics data (SNR). + if (balloon_positions.hasOwnProperty(data.callsign) == true){ + balloon_positions[data.callsign].snr = data.snr; + } +} + function hideBalloon(callsign){ if (balloon_positions.hasOwnProperty(callsign) == true){ balloon_positions[callsign].visible = false; diff --git a/static/js/tables.js b/static/js/tables.js index 569b546..e315886 100644 --- a/static/js/tables.js +++ b/static/js/tables.js @@ -154,7 +154,8 @@ function initTables(){ {title:"Longitude", field:"lon", headerSort:false}, {title:"Alt (m)", field:"alt", headerSort:false}, {title:"V_rate (m/s)", field:"vel_v", headerSort:false}, - {title:"Aux", field:'aux', headerSort:false} + {title:"SNR", field:'snr', headerSort:false, visible:false}, + {title:"Aux", field:'aux', headerSort:false, visible:false} ], rowClick:function(e, row){telemetryTableDialog(e, row);}, rowTap:function(e, row){telemetryTableDialog(e, row);} @@ -216,10 +217,19 @@ function updateTelemetryTable(){ // Add in any extra data to the aux field. balloon_call_data.aux = ""; + balloon_call_data.snr = ""; if (balloon_call_data.hasOwnProperty('bt')){ if ((balloon_call_data.bt >= 0) && (balloon_call_data.bt < 65535)) { balloon_call_data.aux += "BT " + new Date(balloon_call_data.bt*1000).toISOString().substr(11, 8) + " "; + $("#telem_table").tabulator("showColumn", "aux"); + } + } + + if (balloon_positions[balloon_call].hasOwnProperty('snr')){ + if (balloon_positions[balloon_call].snr > -255.0){ + balloon_call_data.snr = balloon_positions[balloon_call].snr.toFixed(1); + $("#telem_table").tabulator("showColumn", "snr"); } } diff --git a/templates/index.html b/templates/index.html index 2c60b1f..f692d69 100644 --- a/templates/index.html +++ b/templates/index.html @@ -425,6 +425,10 @@ handleTelemetry(data); }); + socket.on('modem_stats_event', function(data) { + handleModemStats(data); + }); + // Predictor Functions socket.on('predictor_model_update', function(data){ var _model_data = data.model;