From 27d486f913c3ea4e32628ebed57530d554917202 Mon Sep 17 00:00:00 2001 From: Mark Jessop Date: Sun, 22 Nov 2020 11:37:41 +1030 Subject: [PATCH] Add pressure field support, add support for humidity, pressure and battery voltage output to APRS. --- auto_rx/auto_rx.py | 2 +- auto_rx/autorx/aprs.py | 3 +++ auto_rx/autorx/decode.py | 15 +++++++++++++-- auto_rx/autorx/habitat.py | 7 ++++++- auto_rx/autorx/logger.py | 7 ++++--- auto_rx/station.cfg.example | 11 +++++++---- 6 files changed, 34 insertions(+), 11 deletions(-) diff --git a/auto_rx/auto_rx.py b/auto_rx/auto_rx.py index 54556f5..12cb589 100644 --- a/auto_rx/auto_rx.py +++ b/auto_rx/auto_rx.py @@ -534,7 +534,7 @@ def main(): parser.add_argument("-c" ,"--config", default="station.cfg", help="Receive Station Configuration File. Default: station.cfg") parser.add_argument("-l" ,"--log", default="./log/", help="Receive Station Log Path. Default: ./log/") parser.add_argument("-f", "--frequency", type=float, default=0.0, help="Sonde Frequency Override (MHz). This overrides the scan whitelist with the supplied frequency.") - parser.add_argument("-m", "--type", type=str, default=None, help="Immediately start a decoder for a provided sonde type (RS41, RS92, DFM, M10, etc)") + parser.add_argument("-m", "--type", type=str, default=None, help="Immediately start a decoder for a provided sonde type (Valid Types: RS41, RS92, DFM, M10, M20, IMET, LMS6, MK2LMS, MEISEI)") parser.add_argument("-t", "--timeout", type=int, default=0, help="Close auto_rx system after N minutes. Use 0 to run continuously.") parser.add_argument("-v", "--verbose", help="Enable debug output.", action="store_true") parser.add_argument("-e", "--ephemeris", type=str, default="None", help="Use a manually obtained ephemeris file when decoding RS92 Sondes.") diff --git a/auto_rx/autorx/aprs.py b/auto_rx/autorx/aprs.py index fc32afb..72d0e82 100644 --- a/auto_rx/autorx/aprs.py +++ b/auto_rx/autorx/aprs.py @@ -111,6 +111,9 @@ def telemetry_to_aprs_position(sonde_data, object_name="", aprs_comment="BOM _aprs_comment = _aprs_comment.replace("", _freq) _aprs_comment = _aprs_comment.replace("", sonde_data['id']) _aprs_comment = _aprs_comment.replace("", "%.1fC" % sonde_data['temp']) + _aprs_comment = _aprs_comment.replace("", "%.1fhPa" % sonde_data['pressure']) + _aprs_comment = _aprs_comment.replace("", "%.1f" % sonde_data['humidity'] + "%") + _aprs_comment = _aprs_comment.replace("", "%.1fV" % sonde_data['batt']) _aprs_comment = _aprs_comment.replace("", "%.1fm/s" % sonde_data['vel_v']) _aprs_comment = _aprs_comment.replace("", sonde_data['type']) diff --git a/auto_rx/autorx/decode.py b/auto_rx/autorx/decode.py index e519444..1eb4e08 100644 --- a/auto_rx/autorx/decode.py +++ b/auto_rx/autorx/decode.py @@ -59,15 +59,23 @@ class SondeDecoder(object): "datetime_dt" (datetime): Telemetry sentence time, as a datetime object. ''' + # IF we don't have any of the following fields provided, we discard the incoming packet. DECODER_REQUIRED_FIELDS = ['frame', 'id', 'datetime', 'lat', 'lon', 'alt'] + # If we are missing any of the following fields, we add in default values to the telemetry + # object which is passed on to the various other consumers. DECODER_OPTIONAL_FIELDS = { 'temp' : -273.0, - 'humidity' : -1, + 'humidity' : -1.0, + 'pressure' : -1, 'batt' : -1, 'vel_h' : 0.0, 'vel_v' : 0.0, 'heading' : 0.0 } + # Note: The decoders may also supply other fields, such as: + # 'batt' - Battery voltage, in volts. + # 'pressure' - Pressure, in hPa + # 'bt' - RS41 burst timer data. # TODO: Use the global valid sonde type list. VALID_SONDE_TYPES = ['RS92', 'RS41', 'DFM', 'M10', 'M20', 'IMET', 'MK2LMS', 'LMS6', 'MEISEI', 'UDP'] @@ -779,7 +787,10 @@ class SondeDecoder(object): self.log_error("JSON object missing required field %s" % _field) return False - # Check for optional fields, and add them if necessary. + + # Check for fields which we need for logging purposes, but may not always be provided + # in the incoming JSON object. + # These get added in with dummy values. for _field in self.DECODER_OPTIONAL_FIELDS.keys(): if _field not in _telemetry: _telemetry[_field] = self.DECODER_OPTIONAL_FIELDS[_field] diff --git a/auto_rx/autorx/habitat.py b/auto_rx/autorx/habitat.py index cdd96cf..bc079ca 100644 --- a/auto_rx/autorx/habitat.py +++ b/auto_rx/autorx/habitat.py @@ -96,12 +96,17 @@ def sonde_telemetry_to_sentence(telemetry, payload_callsign=None, comment=None): # Add in a comment field, containing the sonde type, serial number, and frequency. _sentence += ",%s %s %s" % (telemetry['type'], telemetry['id'], _freq) + # Add in pressure data, if valid (not -1) + if telemetry['pressure'] > 0.0: + _sentence += " %.1fhPa" % telemetry['pressure'] + # Check for Burst/Kill timer data, and add in. if 'bt' in telemetry: if (telemetry['bt'] != -1) and (telemetry['bt'] != 65535): _sentence += " BT %s" % time.strftime("%H:%M:%S", time.gmtime(telemetry['bt'])) - if 'batt' in telemetry: + # Add in battery voltage, if the field is valid (e.g. not -1) + if telemetry['batt'] > 0.0: _sentence += " %.1fV" % telemetry['batt'] # Add on any custom comment data if provided. diff --git a/auto_rx/autorx/logger.py b/auto_rx/autorx/logger.py index df77bf2..81a67d8 100644 --- a/auto_rx/autorx/logger.py +++ b/auto_rx/autorx/logger.py @@ -36,9 +36,9 @@ class TelemetryLogger(object): FILE_ACTIVITY_TIMEOUT = 300 # We require the following fields to be present in the input telemetry dict. - REQUIRED_FIELDS = ['frame', 'id', 'datetime', 'lat', 'lon', 'alt', 'temp', 'humidity', 'type', 'freq', 'datetime_dt', 'vel_v', 'vel_h', 'heading'] + REQUIRED_FIELDS = ['frame', 'id', 'datetime', 'lat', 'lon', 'alt', 'temp', 'humidity', 'pressure', 'type', 'freq', 'datetime_dt', 'vel_v', 'vel_h', 'heading'] - LOG_HEADER = "timestamp,serial,frame,lat,lon,alt,vel_v,vel_h,heading,temp,humidity,type,freq_mhz,snr,f_error_hz,sats,batt_v,burst_timer,aux_data\n" + LOG_HEADER = "timestamp,serial,frame,lat,lon,alt,vel_v,vel_h,heading,temp,humidity,pressure,type,freq_mhz,snr,f_error_hz,sats,batt_v,burst_timer,aux_data\n" def __init__(self, log_directory = "./log"): @@ -119,7 +119,7 @@ class TelemetryLogger(object): telemetry (dict): Telemetry dictionary to process. """ # timestamp,serial,frame,lat,lon,alt,vel_v,vel_h,heading,temp,humidity,type,freq,other - _log_line = "%s,%s,%d,%.5f,%.5f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%s,%.3f" % ( + _log_line = "%s,%s,%d,%.5f,%.5f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%s,%.3f" % ( telemetry['datetime'], telemetry['id'], telemetry['frame'], @@ -131,6 +131,7 @@ class TelemetryLogger(object): telemetry['heading'], telemetry['temp'], telemetry['humidity'], + telemetry['pressure'], telemetry['type'], telemetry['freq_float']) diff --git a/auto_rx/station.cfg.example b/auto_rx/station.cfg.example index 66d889e..e7ba47e 100644 --- a/auto_rx/station.cfg.example +++ b/auto_rx/station.cfg.example @@ -190,14 +190,17 @@ aprs_use_custom_object_id = False aprs_position_report = False # The APRS-IS beacon comment. The following fields can be included: -# - Sonde Frequency, i.e. 401.520 MHz -# - Sonde Type (RS94/RS41) +# - Sonde Frequency, e.g. 401.520 MHz +# - Sonde Type (e.g. RS41-SG, DFM09, etc....) # - Sonde Serial Number (i.e. M1234567) # - Sonde Vertical Velocity (i.e. -5.1m/s) -# - Sonde reported temperature. If no temp data available, this will report -273 degC. Only works for RS41s. +# - Sonde reported temperature. If no temp data available, this will report -273 degC. +# - Sonde reported humidity. +# - Sonde reported pressure +# - Battery Voltage (e.g. 3.1V) # The default comment (below) is compatible with radiosondy.info's parsers, and should only be modified # if absolutely necessary. -aprs_custom_comment = Clb= t= Type= Radiosonde +aprs_custom_comment = Clb= t= h= p= Type= Radiosonde # APRS Station Location Beaconing