kopia lustrzana https://github.com/projecthorus/radiosonde_auto_rx
Merge branch 'testing' into experimental
commit
01e8ded044
|
|
@ -61,6 +61,10 @@ exporter_objects = [] # This list will hold references to each exporter instan
|
|||
exporter_functions = [] # This list will hold references to the exporter add functions, which will be passed onto the decoders.
|
||||
|
||||
|
||||
# Temporary frequency block list
|
||||
# This contains frequncies that should be blocked for a short amount of time.
|
||||
temporary_block_list = {}
|
||||
|
||||
|
||||
# Scan Result Queue
|
||||
# Scan results are processed asynchronously from the main scanner object.
|
||||
|
|
@ -96,7 +100,7 @@ def allocate_sdr(check_only = False, task_description = ""):
|
|||
|
||||
def start_scanner():
|
||||
""" Start a scanner thread on the first available SDR """
|
||||
global config, scan_results, RS_PATH
|
||||
global config, scan_results, RS_PATH, temporary_block_list
|
||||
|
||||
if 'SCAN' in autorx.task_list:
|
||||
# Already a scanner running! Return.
|
||||
|
|
@ -136,7 +140,9 @@ def start_scanner():
|
|||
gain = autorx.sdr_list[_device_idx]['gain'],
|
||||
ppm = autorx.sdr_list[_device_idx]['ppm'],
|
||||
bias = autorx.sdr_list[_device_idx]['bias'],
|
||||
save_detection_audio = config['save_detection_audio']
|
||||
save_detection_audio = config['save_detection_audio'],
|
||||
temporary_block_list = temporary_block_list,
|
||||
temporary_block_time = config['temporary_block_time']
|
||||
)
|
||||
|
||||
# Add a reference into the sdr_list entry
|
||||
|
|
@ -174,7 +180,19 @@ def start_decoder(freq, sonde_type):
|
|||
sonde_type (str): The radiosonde type ('RS41', 'RS92', 'DFM', 'M10, 'iMet')
|
||||
|
||||
"""
|
||||
global config, RS_PATH, exporter_functions, rs92_ephemeris
|
||||
global config, RS_PATH, exporter_functions, rs92_ephemeris, temporary_block_list
|
||||
|
||||
# Check the frequency is not in our temporary block list
|
||||
# (This may happen from time-to-time depending on the timing of the scan thread)
|
||||
if freq in temporary_block_list.keys():
|
||||
if temporary_block_list[freq] > (time.time()-config['temporary_block_time']*60):
|
||||
logging.error("Task Manager - Attempted to start a decoder on a temporarily blocked frequency (%.3f MHz)" % (freq/1e6))
|
||||
return
|
||||
else:
|
||||
# This frequency should not be blocked any more, remove it from the block list.
|
||||
logging.info("Task Manager - Removed %.3f MHz from temporary block list." % (freq/1e6))
|
||||
temporary_block_list.pop(freq)
|
||||
|
||||
|
||||
# Allocate a SDR.
|
||||
_device_idx = allocate_sdr(task_description="Decoder (%s, %.3f MHz)" % (sonde_type, freq/1e6))
|
||||
|
|
@ -250,6 +268,7 @@ def handle_scan_results():
|
|||
# Break if we don't support this sonde type.
|
||||
if (_check_type not in VALID_SONDE_TYPES):
|
||||
logging.error("Unsupported sonde type: %s" % _check_type)
|
||||
# TODO - Potentially add the frequency of the unsupported sonde to the temporary block list?
|
||||
continue
|
||||
|
||||
if allocate_sdr(check_only=True) is not None :
|
||||
|
|
@ -277,19 +296,40 @@ def clean_task_list():
|
|||
try:
|
||||
_running = autorx.task_list[_key]['task'].running()
|
||||
_task_sdr = autorx.task_list[_key]['device_idx']
|
||||
_exit_state = autorx.task_list[_key]['task'].exit_state
|
||||
except Exception as e:
|
||||
logging.error("Task Manager - Error getting task %s state - %s" % (str(_key),str(e)))
|
||||
continue
|
||||
|
||||
if _running == False:
|
||||
# This task has stopped. Release its associated SDR.
|
||||
# This task has stopped.
|
||||
# Check the exit state of the task for any abnormalities:
|
||||
if _exit_state == "Encrypted":
|
||||
# This task was a decoder, and it has encountered an encrypted sonde.
|
||||
logging.info("Task Manager - Adding temporary block for frequency %.3f MHz" % (_key/1e6))
|
||||
# Add the sonde's frequency to the global temporary block-list
|
||||
temporary_block_list[_key] = time.time()
|
||||
# If there is a scanner currently running, add it to the scanners internal block list.
|
||||
if 'SCAN' in autorx.task_list:
|
||||
auto_rx.task_list['SCAN']['task'].add_temporary_block(_key)
|
||||
|
||||
|
||||
# Release its associated SDR.
|
||||
autorx.sdr_list[_task_sdr]['in_use'] = False
|
||||
autorx.sdr_list[_task_sdr]['task'] = None
|
||||
|
||||
# Pop the task from the task list.
|
||||
autorx.task_list.pop(_key)
|
||||
# Indicate to the web client that the task list has been updated.
|
||||
flask_emit_event('task_event')
|
||||
|
||||
# Clean out the temporary block list of old entries.
|
||||
for _freq in temporary_block_list.keys():
|
||||
if temporary_block_list[_freq] < (time.time() - config['temporary_block_time']*60):
|
||||
temporary_block_list.pop(_freq)
|
||||
logging.info("Task Manager - Removed %.3f MHz from temporary block list." % (_freq/1e6))
|
||||
|
||||
|
||||
# Check if there is a scanner thread still running. If not, and if there is a SDR free, start one up again.
|
||||
if ('SCAN' not in autorx.task_list) and (allocate_sdr(check_only=True) is not None):
|
||||
# We have a SDR free, and we are not running a scan thread. Start one.
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
# MINOR - New sonde type support, other fairly big changes that may result in telemetry or config file incompatability issus.
|
||||
# PATCH - Small changes, or minor feature additions.
|
||||
|
||||
__version__ = "1.1.1-experimental"
|
||||
__version__ = "1.1.2-experimental"
|
||||
|
||||
|
||||
# Global Variables
|
||||
|
|
|
|||
|
|
@ -100,7 +100,8 @@ def read_auto_rx_config(filename):
|
|||
'scan_dwell_time' : 20,
|
||||
'detect_dwell_time' : 5,
|
||||
'scan_delay' : 10,
|
||||
'payload_id_valid' : 5,
|
||||
'payload_id_valid' : 5,
|
||||
'temporary_block_time' : 60,
|
||||
# Rotator Settings
|
||||
'enable_rotator': False,
|
||||
'rotator_update_rate': 30,
|
||||
|
|
@ -245,6 +246,12 @@ def read_auto_rx_config(filename):
|
|||
except:
|
||||
logging.error("Config - Could not find station_code field, using default.")
|
||||
|
||||
# New temporary block time - added 2019-04-14
|
||||
try:
|
||||
auto_rx_config['temporary_block_time'] = config.getint('advanced', 'temporary_block_time')
|
||||
except:
|
||||
logging.error("Config - New advanced settings missing, using defaults.")
|
||||
|
||||
|
||||
# Now we attempt to read in the individual SDR parameters.
|
||||
auto_rx_config['sdr_settings'] = {}
|
||||
|
|
|
|||
|
|
@ -142,6 +142,8 @@ class SondeDecoder(object):
|
|||
# This will become our decoder thread.
|
||||
self.decoder = None
|
||||
|
||||
self.exit_state = "OK"
|
||||
|
||||
# Detect if we have an 'inverted' sonde.
|
||||
if self.sonde_type.startswith('-'):
|
||||
self.inverted = True
|
||||
|
|
@ -407,6 +409,7 @@ class SondeDecoder(object):
|
|||
if time.time() > (_last_packet + self.timeout):
|
||||
# If we have not seen data for a while, break.
|
||||
self.log_error("RX Timed out.")
|
||||
self.exit_state = "Timeout"
|
||||
break
|
||||
else:
|
||||
# Otherwise, sleep for a short time.
|
||||
|
|
@ -486,9 +489,12 @@ class SondeDecoder(object):
|
|||
if _field not in _telemetry:
|
||||
_telemetry[_field] = self.DECODER_OPTIONAL_FIELDS[_field]
|
||||
|
||||
_telemetry['encrypted'] = True
|
||||
|
||||
# Check for an encrypted flag (this indicates a sonde that we cannot decode telemetry from.)
|
||||
if 'encrypted' in _telemetry:
|
||||
self.log_error("Radiosonde %s has encrypted telemetry (possible RS41-SGM)! We cannot decode this, closing decoder." % _telemetry['id'])
|
||||
self.exit_state = "Encrypted"
|
||||
self.decoder_running = False
|
||||
return False
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import platform
|
|||
import subprocess
|
||||
import time
|
||||
import traceback
|
||||
from threading import Thread
|
||||
from threading import Thread, Lock
|
||||
from types import FunctionType, MethodType
|
||||
from .utils import detect_peaks, rtlsdr_test, reset_rtlsdr_by_serial, reset_all_rtlsdrs, peak_decimation
|
||||
try:
|
||||
|
|
@ -358,7 +358,9 @@ class SondeScanner(object):
|
|||
gain = -1,
|
||||
ppm = 0,
|
||||
bias = False,
|
||||
save_detection_audio = False):
|
||||
save_detection_audio = False,
|
||||
temporary_block_list = {},
|
||||
temporary_block_time = 60):
|
||||
""" Initialise a Sonde Scanner Object.
|
||||
|
||||
Apologies for the huge number of args...
|
||||
|
|
@ -390,6 +392,8 @@ class SondeScanner(object):
|
|||
gain (int): SDR Gain setting, in dB. A gain setting of -1 enables the RTLSDR AGC.
|
||||
bias (bool): If True, enable the bias tee on the SDR.
|
||||
save_detection_audio (bool): Save the audio used in each detecton to detect_<device_idx>.wav
|
||||
temporary_block_list (dict): A dictionary where each attribute represents a frequency that should be blacklisted for a set time.
|
||||
temporary_block_time (int): How long (minutes) frequencies in the temporary block list should remain blocked for.
|
||||
"""
|
||||
|
||||
# Thread flag. This is set to True when a scan is running.
|
||||
|
|
@ -420,6 +424,14 @@ class SondeScanner(object):
|
|||
self.callback = callback
|
||||
self.save_detection_audio = save_detection_audio
|
||||
|
||||
# Temporary block list.
|
||||
self.temporary_block_list = temporary_block_list.copy()
|
||||
self.temporary_block_list_lock = Lock()
|
||||
self.temporary_block_time = temporary_block_time
|
||||
|
||||
# Alert the user if there are temporary blocks in place.
|
||||
if len(self.temporary_block_list.keys())>0:
|
||||
self.log_info("Temporary blocks in place for frequencies: %s" % str(self.temporary_block_list.keys()))
|
||||
|
||||
# Error counter.
|
||||
self.error_retries = 0
|
||||
|
|
@ -439,8 +451,11 @@ class SondeScanner(object):
|
|||
if not _rtlsdr_ok:
|
||||
self.log_error("RTLSDR #%s non-functional - exiting." % device_idx)
|
||||
self.sonde_scanner_running = False
|
||||
self.exit_state = "Failed SDR"
|
||||
return
|
||||
|
||||
self.exit_state = "OK"
|
||||
|
||||
if auto_start:
|
||||
self.start()
|
||||
|
||||
|
|
@ -611,6 +626,7 @@ class SondeScanner(object):
|
|||
_, peak_idx = np.unique(peak_frequencies, return_index=True)
|
||||
peak_frequencies = peak_frequencies[np.sort(peak_idx)]
|
||||
|
||||
|
||||
# Remove any frequencies in the blacklist.
|
||||
for _frequency in np.array(self.blacklist)*1e6:
|
||||
_index = np.argwhere(peak_frequencies==_frequency)
|
||||
|
|
@ -623,6 +639,25 @@ class SondeScanner(object):
|
|||
# Append on any frequencies in the supplied greylist
|
||||
peak_frequencies = np.append(np.array(self.greylist)*1e6, peak_frequencies)
|
||||
|
||||
|
||||
# Remove any frequencies in the temporary block list
|
||||
self.temporary_block_list_lock.acquire()
|
||||
for _frequency in self.temporary_block_list.keys():
|
||||
# Check the time the block was added.
|
||||
if self.temporary_block_list[_frequency] > (time.time()-self.temporary_block_time*60):
|
||||
# We should still be blocking this frequency, so remove any peaks with this frequency.
|
||||
_index = np.argwhere(peak_frequencies==_frequency)
|
||||
peak_frequencies = np.delete(peak_frequencies, _index)
|
||||
if len(_index) > 0:
|
||||
self.log_debug("Peak on %.3f MHz was removed due to temporary block." % (_frequency/1e6))
|
||||
|
||||
else:
|
||||
# This frequency doesn't need to be blocked any more, remove it from the block list.
|
||||
self.temporary_block_list.pop(_frequency)
|
||||
self.log_info("Removed %.3f MHz from temporary block list." % (_frequency/1e6))
|
||||
|
||||
self.temporary_block_list_lock.release()
|
||||
|
||||
# Get the level of our peak search results, to send to the web client.
|
||||
# This is actually a bit of a pain to do...
|
||||
_peak_freq = []
|
||||
|
|
@ -734,6 +769,20 @@ class SondeScanner(object):
|
|||
return self.sonde_scanner_running
|
||||
|
||||
|
||||
def add_temporary_block(self, frequency):
|
||||
""" Add a frequency to the temporary block list.
|
||||
|
||||
Args:
|
||||
frequency (float): Frequency to be blocked, in Hz
|
||||
"""
|
||||
# Acquire a lock on the block list, so we don't accidentally modify it
|
||||
# while it is being used in a scan.
|
||||
self.temporary_block_list_lock.acquire()
|
||||
self.temporary_block_list[frequency] = time.time()
|
||||
self.temporary_block_list_lock.release()
|
||||
self.log_info("Adding temporary block for frequency %.3f MHz." % (frequency/1e6))
|
||||
|
||||
|
||||
def log_debug(self, line):
|
||||
""" Helper function to log a debug message with a descriptive heading.
|
||||
Args:
|
||||
|
|
|
|||
|
|
@ -335,6 +335,8 @@ detect_dwell_time = 5
|
|||
scan_delay = 10
|
||||
# Quantize search results to x Hz steps. Useful as most sondes are on 10 kHz frequency steps.
|
||||
quantization = 10000
|
||||
# Temporary Block Time (minutes) - How long to block encrypted or otherwise non-decodable sondes for.
|
||||
temporary_block_time = 60
|
||||
# Upload when (seconds_since_utc_epoch%upload_rate) == 0. Otherwise just delay upload_rate seconds between uploads.
|
||||
# Setting this to True with multple uploaders should give a higher chance of all uploaders uploading the same frame,
|
||||
# however the upload_rate should not be set too low, else there may be a chance of missing upload slots.
|
||||
|
|
|
|||
|
|
@ -82,8 +82,7 @@ typedef struct {
|
|||
int wday;
|
||||
int std; int min; float sek;
|
||||
double lat; double lon; double alt;
|
||||
double vN; double vE; double vU;
|
||||
double vH; double vD; double vD2;
|
||||
double vH; double vD; double vV;
|
||||
float T; float RH;
|
||||
ui32_t crc;
|
||||
ui8_t frame[FRAME_LEN];
|
||||
|
|
@ -96,12 +95,12 @@ typedef struct {
|
|||
float ptu_co2[3]; // { -243.911 , 0.187654 , 8.2e-06 }
|
||||
float ptu_calT2[3]; // calibration T2-Hum
|
||||
float ptu_calH[2]; // calibration Hum
|
||||
ui32_t freq; // freq/kHz
|
||||
ui16_t conf_fw; // firmware
|
||||
ui8_t conf_cd; // kill countdown (sec) (kt or bt)
|
||||
ui16_t conf_kt; // kill timer (sec)
|
||||
ui16_t conf_bt; // burst timer (sec)
|
||||
ui8_t conf_bk; // burst kill
|
||||
ui32_t freq; // freq/kHz
|
||||
ui8_t conf_cd; // kill countdown (sec) (kt or bt)
|
||||
char rstyp[9]; // RS41-SG, RS41-SGP
|
||||
int aux;
|
||||
char xdata[XDATA_LEN+16]; // xdata: aux_str1#aux_str2 ...
|
||||
|
|
@ -248,6 +247,7 @@ static int crc16(gpx_t *gpx, int start, int len) {
|
|||
static int check_CRC(gpx_t *gpx, ui32_t pos, ui32_t pck) {
|
||||
ui32_t crclen = 0,
|
||||
crcdat = 0;
|
||||
// check only pck_type (variable len pcks 0x76, 0x7E)
|
||||
if (((pck>>8) & 0xFF) != gpx->frame[pos]) return -1;
|
||||
crclen = gpx->frame[pos+1];
|
||||
if (pos + crclen + 4 > FRAME_LEN) return -1;
|
||||
|
|
@ -273,62 +273,62 @@ GPS chip: ublox UBX-G6010-ST
|
|||
0x12B: 7Exx AUX-xdata
|
||||
*/
|
||||
|
||||
#define crc_FRAME (1<<0)
|
||||
#define xor_FRAME 0x1713 // ^0x6E3B=0x7928
|
||||
#define pck_FRAME 0x7928
|
||||
#define pos_FRAME 0x039
|
||||
#define pos_FrameNb 0x03B // 2 byte
|
||||
#define pos_SondeID 0x03D // 8 byte
|
||||
#define pos_CalData 0x052 // 1 byte, counter 0x00..0x32
|
||||
#define pos_Calfreq 0x055 // 2 byte, calfr 0x00
|
||||
#define pos_Calburst 0x05E // 1 byte, calfr 0x02
|
||||
#define crc_FRAME (1<<0)
|
||||
#define xor_FRAME 0x1713 // ^0x6E3B=0x7928
|
||||
#define pck_FRAME 0x7928
|
||||
#define pos_FRAME 0x039
|
||||
#define pos_FrameNb 0x03B // 2 byte
|
||||
#define pos_SondeID 0x03D // 8 byte
|
||||
#define pos_CalData 0x052 // 1 byte, counter 0x00..0x32
|
||||
#define pos_Calfreq 0x055 // 2 byte, calfr 0x00
|
||||
#define pos_Calburst 0x05E // 1 byte, calfr 0x02
|
||||
// ? #define pos_Caltimer 0x05A // 2 byte, calfr 0x02 ?
|
||||
#define pos_CalRSTyp 0x05B // 8 byte, calfr 0x21 (+2 byte in 0x22?)
|
||||
#define pos_CalRSTyp 0x05B // 8 byte, calfr 0x21 (+2 byte in 0x22?)
|
||||
// weitere chars in calfr 0x22/0x23; weitere ID
|
||||
|
||||
#define crc_PTU (1<<1)
|
||||
#define xor_PTU 0xE388 // ^0x99A2=0x0x7A2A
|
||||
#define pck_PTU 0x7A2A // PTU
|
||||
#define pos_PTU 0x065
|
||||
#define crc_PTU (1<<1)
|
||||
#define xor_PTU 0xE388 // ^0x99A2=0x0x7A2A
|
||||
#define pck_PTU 0x7A2A // PTU
|
||||
#define pos_PTU 0x065
|
||||
|
||||
#define crc_GPS1 (1<<2)
|
||||
#define xor_GPS1 0x9667 // ^0xEA79=0x7C1E
|
||||
#define pck_GPS1 0x7C1E // RXM-RAW (0x02 0x10)
|
||||
#define pos_GPS1 0x093
|
||||
#define pos_GPSweek 0x095 // 2 byte
|
||||
#define pos_GPSiTOW 0x097 // 4 byte
|
||||
#define pos_satsN 0x09B // 12x2 byte (1: SV, 1: quality,strength)
|
||||
#define crc_GPS1 (1<<2)
|
||||
#define xor_GPS1 0x9667 // ^0xEA79=0x7C1E
|
||||
#define pck_GPS1 0x7C1E // RXM-RAW (0x02 0x10)
|
||||
#define pos_GPS1 0x093
|
||||
#define pos_GPSweek 0x095 // 2 byte
|
||||
#define pos_GPSiTOW 0x097 // 4 byte
|
||||
#define pos_satsN 0x09B // 12x2 byte (1: SV, 1: quality,strength)
|
||||
|
||||
#define crc_GPS2 (1<<3)
|
||||
#define xor_GPS2 0xD7AD // ^0xAAF4=0x7D59
|
||||
#define pck_GPS2 0x7D59 // RXM-RAW (0x02 0x10)
|
||||
#define pos_GPS2 0x0B5
|
||||
#define pos_minPR 0x0B7 // 4 byte
|
||||
#define pos_FF 0x0BB // 1 byte
|
||||
#define pos_dataSats 0x0BC // 12x(4+3) byte (4: pseudorange, 3: doppler)
|
||||
#define crc_GPS2 (1<<3)
|
||||
#define xor_GPS2 0xD7AD // ^0xAAF4=0x7D59
|
||||
#define pck_GPS2 0x7D59 // RXM-RAW (0x02 0x10)
|
||||
#define pos_GPS2 0x0B5
|
||||
#define pos_minPR 0x0B7 // 4 byte
|
||||
#define pos_FF 0x0BB // 1 byte
|
||||
#define pos_dataSats 0x0BC // 12x(4+3) byte (4: pseudorange, 3: doppler)
|
||||
|
||||
#define crc_GPS3 (1<<4)
|
||||
#define xor_GPS3 0xB9FF // ^0xC2EA=0x7B15
|
||||
#define pck_GPS3 0x7B15 // NAV-SOL (0x01 0x06)
|
||||
#define pos_GPS3 0x112
|
||||
#define pos_GPSecefX 0x114 // 4 byte
|
||||
#define pos_GPSecefY 0x118 // 4 byte
|
||||
#define pos_GPSecefZ 0x11C // 4 byte
|
||||
#define pos_GPSecefV 0x120 // 3*2 byte
|
||||
#define pos_numSats 0x126 // 1 byte
|
||||
#define pos_sAcc 0x127 // 1 byte
|
||||
#define pos_pDOP 0x128 // 1 byte
|
||||
#define crc_GPS3 (1<<4)
|
||||
#define xor_GPS3 0xB9FF // ^0xC2EA=0x7B15
|
||||
#define pck_GPS3 0x7B15 // NAV-SOL (0x01 0x06)
|
||||
#define pos_GPS3 0x112
|
||||
#define pos_GPSecefX 0x114 // 4 byte
|
||||
#define pos_GPSecefY 0x118 // 4 byte
|
||||
#define pos_GPSecefZ 0x11C // 4 byte
|
||||
#define pos_GPSecefV 0x120 // 3*2 byte
|
||||
#define pos_numSats 0x126 // 1 byte
|
||||
#define pos_sAcc 0x127 // 1 byte
|
||||
#define pos_pDOP 0x128 // 1 byte
|
||||
|
||||
#define crc_AUX (1<<5)
|
||||
#define pck_AUX 0x7E00 // LEN variable
|
||||
#define pos_AUX 0x12B
|
||||
#define crc_AUX (1<<5)
|
||||
#define pck_AUX 0x7E00 // LEN variable
|
||||
#define pos_AUX 0x12B
|
||||
|
||||
#define crc_ZERO (1<<6) // LEN variable
|
||||
#define pck_ZERO 0x7600
|
||||
#define pck_ZEROstd 0x7611 // NDATA std-frm, no aux
|
||||
#define pos_ZEROstd 0x12B // pos_AUX(0)
|
||||
#define crc_ZERO (1<<6) // LEN variable
|
||||
#define pck_ZERO 0x7600
|
||||
#define pck_ZEROstd 0x7611 // NDATA std-frm, no aux
|
||||
#define pos_ZEROstd 0x12B // pos_AUX(0)
|
||||
|
||||
#define pck_ENCRYPTED 0x80 // Packet type for an Encrypted payload
|
||||
#define pck_ENCRYPTED 0x8000 // Packet type for an Encrypted payload
|
||||
|
||||
/*
|
||||
frame[pos_FRAME-1] == 0x0F: len == NDATA_LEN(320)
|
||||
|
|
@ -344,72 +344,6 @@ static int frametype(gpx_t *gpx) { // -4..+4: 0xF0 -> -4 , 0x0F -> +4
|
|||
return ft;
|
||||
}
|
||||
|
||||
|
||||
const double c = 299.792458e6;
|
||||
const double L1 = 1575.42e6;
|
||||
|
||||
static int get_SatData(gpx_t *gpx) {
|
||||
int i, n;
|
||||
int sv;
|
||||
ui32_t minPR;
|
||||
int numSV;
|
||||
double pDOP, sAcc;
|
||||
|
||||
fprintf(stdout, "[%d]\n", u2(gpx->frame+pos_FrameNb));
|
||||
|
||||
fprintf(stdout, "iTOW: 0x%08X", u4(gpx->frame+pos_GPSiTOW));
|
||||
fprintf(stdout, " week: 0x%04X", u2(gpx->frame+pos_GPSweek));
|
||||
fprintf(stdout, "\n");
|
||||
minPR = u4(gpx->frame+pos_minPR);
|
||||
fprintf(stdout, "minPR: %d", minPR);
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
for (i = 0; i < 12; i++) {
|
||||
n = i*7;
|
||||
sv = gpx->frame[pos_satsN+2*i];
|
||||
if (sv == 0xFF) break;
|
||||
fprintf(stdout, " SV: %2d ", sv);
|
||||
//fprintf(stdout, " (%02x) ", gpx->frame[pos_satsN+2*i+1]);
|
||||
fprintf(stdout, "# ");
|
||||
fprintf(stdout, "prMes: %.1f", u4(gpx->frame+pos_dataSats+n)/100.0 + minPR);
|
||||
fprintf(stdout, " ");
|
||||
fprintf(stdout, "doMes: %.1f", -i3(gpx->frame+pos_dataSats+n+4)/100.0*L1/c);
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
fprintf(stdout, "ECEF-POS: (%d,%d,%d)\n",
|
||||
(i32_t)u4(gpx->frame+pos_GPSecefX),
|
||||
(i32_t)u4(gpx->frame+pos_GPSecefY),
|
||||
(i32_t)u4(gpx->frame+pos_GPSecefZ));
|
||||
fprintf(stdout, "ECEF-VEL: (%d,%d,%d)\n",
|
||||
(i16_t)u2(gpx->frame+pos_GPSecefV+0),
|
||||
(i16_t)u2(gpx->frame+pos_GPSecefV+2),
|
||||
(i16_t)u2(gpx->frame+pos_GPSecefV+4));
|
||||
|
||||
numSV = gpx->frame[pos_numSats];
|
||||
sAcc = gpx->frame[pos_sAcc]/10.0; if (gpx->frame[pos_sAcc] == 0xFF) sAcc = -1.0;
|
||||
pDOP = gpx->frame[pos_pDOP]/10.0; if (gpx->frame[pos_pDOP] == 0xFF) pDOP = -1.0;
|
||||
fprintf(stdout, "numSatsFix: %2d sAcc: %.1f pDOP: %.1f\n", numSV, sAcc, pDOP);
|
||||
|
||||
|
||||
fprintf(stdout, "CRC: ");
|
||||
fprintf(stdout, " %04X", pck_GPS1);
|
||||
if (check_CRC(gpx, pos_GPS1, pck_GPS1)==0) fprintf(stdout, "[OK]"); else fprintf(stdout, "[NO]");
|
||||
//fprintf(stdout, "[%+d]", check_CRC(gpx, pos_GPS1, pck_GPS1));
|
||||
fprintf(stdout, " %04X", pck_GPS2);
|
||||
if (check_CRC(gpx, pos_GPS2, pck_GPS2)==0) fprintf(stdout, "[OK]"); else fprintf(stdout, "[NO]");
|
||||
//fprintf(stdout, "[%+d]", check_CRC(gpx, pos_GPS2, pck_GPS2));
|
||||
fprintf(stdout, " %04X", pck_GPS3);
|
||||
if (check_CRC(gpx, pos_GPS3, pck_GPS3)==0) fprintf(stdout, "[OK]"); else fprintf(stdout, "[NO]");
|
||||
//fprintf(stdout, "[%+d]", check_CRC(gpx, pos_GPS3, pck_GPS3));
|
||||
|
||||
fprintf(stdout, "\n");
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int get_FrameNb(gpx_t *gpx) {
|
||||
int i;
|
||||
unsigned byte;
|
||||
|
|
@ -442,16 +376,20 @@ static int get_SondeID(gpx_t *gpx, int crc) {
|
|||
if ( strncmp(gpx->id, sondeid_bytes, 8) != 0 ) {
|
||||
//for (i = 0; i < 51; i++) gpx->calfrchk[i] = 0;
|
||||
memset(gpx->calfrchk, 0, 51);
|
||||
memcpy(gpx->id, sondeid_bytes, 8);
|
||||
gpx->id[8] = '\0';
|
||||
// conf data
|
||||
// reset conf data
|
||||
memset(gpx->rstyp, 0, 9);
|
||||
gpx->freq = 0;
|
||||
gpx->conf_fw = 0;
|
||||
gpx->conf_cd = -1;
|
||||
gpx->conf_kt = -1;
|
||||
gpx->conf_bt = 0;
|
||||
gpx->conf_bk = 0;
|
||||
gpx->freq = 0;
|
||||
memset(gpx->rstyp, 0, 9);
|
||||
gpx->conf_cd = -1;
|
||||
gpx->conf_kt = -1;
|
||||
// don't reset gpx->frame[] !
|
||||
// gpx->T = -273.15;
|
||||
// gpx->RH = -1.0;
|
||||
// new ID:
|
||||
memcpy(gpx->id, sondeid_bytes, 8);
|
||||
gpx->id[8] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -467,8 +405,8 @@ static int get_FrameConf(gpx_t *gpx) {
|
|||
if (crc) gpx->crc |= crc_FRAME;
|
||||
|
||||
err = crc;
|
||||
err |= get_FrameNb(gpx);
|
||||
err |= get_SondeID(gpx, crc);
|
||||
err |= get_FrameNb(gpx);
|
||||
|
||||
if (crc == 0) {
|
||||
calfr = gpx->frame[pos_CalData];
|
||||
|
|
@ -636,10 +574,10 @@ static int get_PTU(gpx_t *gpx) {
|
|||
printf(" Tc:%.2f ", Tc);
|
||||
printf(" RH:%.1f ", RH);
|
||||
printf(" TH:%.2f ", TH);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
if (gpx->alt > -400.0)
|
||||
//if (gpx->alt > -400.0)
|
||||
{
|
||||
printf(" %9.2f ; %6.1f ; %6.1f ", gpx->alt, gpx->ptu_Rf1, gpx->ptu_Rf2);
|
||||
printf("; %10.6f ; %10.6f ; %10.6f ", gpx->ptu_calT1[0], gpx->ptu_calT1[1], gpx->ptu_calT1[2]);
|
||||
|
|
@ -657,6 +595,82 @@ static int get_PTU(gpx_t *gpx) {
|
|||
return err;
|
||||
}
|
||||
|
||||
|
||||
const double c = 299.792458e6;
|
||||
const double L1 = 1575.42e6;
|
||||
|
||||
static int get_SatData(gpx_t *gpx) {
|
||||
int i, n;
|
||||
int sv;
|
||||
ui32_t minPR;
|
||||
int numSV;
|
||||
double pDOP, sAcc;
|
||||
int err = 0;
|
||||
|
||||
if ( ((gpx->frame[pos_GPS1]<<8) | gpx->frame[pos_GPS1+1]) != pck_GPS1 ) return -1;
|
||||
if ( ((gpx->frame[pos_GPS2]<<8) | gpx->frame[pos_GPS2+1]) != pck_GPS2 ) return -2;
|
||||
if ( ((gpx->frame[pos_GPS3]<<8) | gpx->frame[pos_GPS3+1]) != pck_GPS3 ) return -3;
|
||||
|
||||
err = get_FrameConf(gpx);
|
||||
|
||||
if (!err) {
|
||||
fprintf(stdout, "[%5d] ", gpx->frnr);
|
||||
fprintf(stdout, "(%s) ", gpx->id);
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
fprintf(stdout, "iTOW: 0x%08X", u4(gpx->frame+pos_GPSiTOW));
|
||||
fprintf(stdout, " week: 0x%04X", u2(gpx->frame+pos_GPSweek));
|
||||
fprintf(stdout, "\n");
|
||||
minPR = u4(gpx->frame+pos_minPR);
|
||||
fprintf(stdout, "minPR: %d", minPR);
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
for (i = 0; i < 12; i++) {
|
||||
n = i*7;
|
||||
sv = gpx->frame[pos_satsN+2*i];
|
||||
if (sv == 0xFF) break;
|
||||
fprintf(stdout, " SV: %2d ", sv);
|
||||
//fprintf(stdout, " (%02x) ", gpx->frame[pos_satsN+2*i+1]);
|
||||
fprintf(stdout, "# ");
|
||||
fprintf(stdout, "prMes: %.1f", u4(gpx->frame+pos_dataSats+n)/100.0 + minPR);
|
||||
fprintf(stdout, " ");
|
||||
fprintf(stdout, "doMes: %.1f", -i3(gpx->frame+pos_dataSats+n+4)/100.0*L1/c);
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
fprintf(stdout, "ECEF-POS: (%d,%d,%d)\n",
|
||||
(i32_t)u4(gpx->frame+pos_GPSecefX),
|
||||
(i32_t)u4(gpx->frame+pos_GPSecefY),
|
||||
(i32_t)u4(gpx->frame+pos_GPSecefZ));
|
||||
fprintf(stdout, "ECEF-VEL: (%d,%d,%d)\n",
|
||||
(i16_t)u2(gpx->frame+pos_GPSecefV+0),
|
||||
(i16_t)u2(gpx->frame+pos_GPSecefV+2),
|
||||
(i16_t)u2(gpx->frame+pos_GPSecefV+4));
|
||||
|
||||
numSV = gpx->frame[pos_numSats];
|
||||
sAcc = gpx->frame[pos_sAcc]/10.0; if (gpx->frame[pos_sAcc] == 0xFF) sAcc = -1.0;
|
||||
pDOP = gpx->frame[pos_pDOP]/10.0; if (gpx->frame[pos_pDOP] == 0xFF) pDOP = -1.0;
|
||||
fprintf(stdout, "numSatsFix: %2d sAcc: %.1f pDOP: %.1f\n", numSV, sAcc, pDOP);
|
||||
|
||||
|
||||
fprintf(stdout, "CRC: ");
|
||||
fprintf(stdout, " %04X", pck_GPS1);
|
||||
if (check_CRC(gpx, pos_GPS1, pck_GPS1)==0) fprintf(stdout, "[OK]"); else fprintf(stdout, "[NO]");
|
||||
//fprintf(stdout, "[%+d]", check_CRC(gpx, pos_GPS1, pck_GPS1));
|
||||
fprintf(stdout, " %04X", pck_GPS2);
|
||||
if (check_CRC(gpx, pos_GPS2, pck_GPS2)==0) fprintf(stdout, "[OK]"); else fprintf(stdout, "[NO]");
|
||||
//fprintf(stdout, "[%+d]", check_CRC(gpx, pos_GPS2, pck_GPS2));
|
||||
fprintf(stdout, " %04X", pck_GPS3);
|
||||
if (check_CRC(gpx, pos_GPS3, pck_GPS3)==0) fprintf(stdout, "[OK]"); else fprintf(stdout, "[NO]");
|
||||
//fprintf(stdout, "[%+d]", check_CRC(gpx, pos_GPS3, pck_GPS3));
|
||||
|
||||
fprintf(stdout, "\n");
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_GPSweek(gpx_t *gpx) {
|
||||
int i;
|
||||
unsigned byte;
|
||||
|
|
@ -714,15 +728,16 @@ static int get_GPStime(gpx_t *gpx) {
|
|||
static int get_GPS1(gpx_t *gpx) {
|
||||
int err=0;
|
||||
|
||||
// ((gpx->frame[pos_GPS1]<<8) | gpx->frame[pos_GPS1+1]) != pck_GPS1 ?
|
||||
if ( gpx->frame[pos_GPS1] != ((pck_GPS1>>8) & 0xFF) ) {
|
||||
// gpx->frame[pos_GPS1+1] != (pck_GPS1 & 0xFF) ?
|
||||
err = check_CRC(gpx, pos_GPS1, pck_GPS1);
|
||||
if (err) {
|
||||
gpx->crc |= crc_GPS1;
|
||||
// reset GPS1-data (json)
|
||||
gpx->jahr = 0; gpx->monat = 0; gpx->tag = 0;
|
||||
gpx->std = 0; gpx->min = 0; gpx->sek = 0.0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = check_CRC(gpx, pos_GPS1, pck_GPS1);
|
||||
if (err) gpx->crc |= crc_GPS1;
|
||||
|
||||
err |= get_GPSweek(gpx); // no plausibility-check
|
||||
err |= get_GPStime(gpx); // no plausibility-check
|
||||
|
||||
|
|
@ -732,6 +747,7 @@ static int get_GPS1(gpx_t *gpx) {
|
|||
static int get_GPS2(gpx_t *gpx) {
|
||||
int err=0;
|
||||
|
||||
// gpx->frame[pos_GPS2+1] != (pck_GPS2 & 0xFF) ?
|
||||
err = check_CRC(gpx, pos_GPS2, pck_GPS2);
|
||||
if (err) gpx->crc |= crc_GPS2;
|
||||
|
||||
|
|
@ -775,7 +791,9 @@ static int get_GPSkoord(gpx_t *gpx) {
|
|||
double X[3], lat, lon, alt;
|
||||
ui8_t gpsVel_bytes[2];
|
||||
short vel16; // 16bit
|
||||
double V[3], phi, lam, dir;
|
||||
double V[3];
|
||||
double phi, lam, dir;
|
||||
double vN; double vE; double vU;
|
||||
|
||||
|
||||
for (k = 0; k < 3; k++) {
|
||||
|
|
@ -809,12 +827,12 @@ static int get_GPSkoord(gpx_t *gpx) {
|
|||
// ECEF-Vel -> NorthEastUp
|
||||
phi = lat*M_PI/180.0;
|
||||
lam = lon*M_PI/180.0;
|
||||
gpx->vN = -V[0]*sin(phi)*cos(lam) - V[1]*sin(phi)*sin(lam) + V[2]*cos(phi);
|
||||
gpx->vE = -V[0]*sin(lam) + V[1]*cos(lam);
|
||||
gpx->vU = V[0]*cos(phi)*cos(lam) + V[1]*cos(phi)*sin(lam) + V[2]*sin(phi);
|
||||
vN = -V[0]*sin(phi)*cos(lam) - V[1]*sin(phi)*sin(lam) + V[2]*cos(phi);
|
||||
vE = -V[0]*sin(lam) + V[1]*cos(lam);
|
||||
vU = V[0]*cos(phi)*cos(lam) + V[1]*cos(phi)*sin(lam) + V[2]*sin(phi);
|
||||
|
||||
// NEU -> HorDirVer
|
||||
gpx->vH = sqrt(gpx->vN*gpx->vN+gpx->vE*gpx->vE);
|
||||
gpx->vH = sqrt(vN*vN+vE*vE);
|
||||
/*
|
||||
double alpha;
|
||||
alpha = atan2(gpx->vN, gpx->vE)*180/M_PI; // ComplexPlane (von x-Achse nach links) - GeoMeteo (von y-Achse nach rechts)
|
||||
|
|
@ -822,10 +840,12 @@ static int get_GPSkoord(gpx_t *gpx) {
|
|||
if (dir < 0) dir += 360; // atan2(y,x)=atan(y/x)=pi/2-atan(x/y) , atan(1/t) = pi/2 - atan(t)
|
||||
gpx->vD2 = dir;
|
||||
*/
|
||||
dir = atan2(gpx->vE, gpx->vN) * 180 / M_PI;
|
||||
dir = atan2(vE, vN) * 180 / M_PI;
|
||||
if (dir < 0) dir += 360;
|
||||
gpx->vD = dir;
|
||||
|
||||
gpx->vV = vU;
|
||||
|
||||
gpx->numSV = gpx->frame[pos_numSats];
|
||||
|
||||
return 0;
|
||||
|
|
@ -834,15 +854,17 @@ static int get_GPSkoord(gpx_t *gpx) {
|
|||
static int get_GPS3(gpx_t *gpx) {
|
||||
int err=0;
|
||||
|
||||
// ((gpx->frame[pos_GPS3]<<8) | gpx->frame[pos_GPS3+1]) != pck_GPS3 ?
|
||||
if ( gpx->frame[pos_GPS3] != ((pck_GPS3>>8) & 0xFF) ) {
|
||||
// gpx->frame[pos_GPS3+1] != (pck_GPS3 & 0xFF) ?
|
||||
err = check_CRC(gpx, pos_GPS3, pck_GPS3);
|
||||
if (err) {
|
||||
gpx->crc |= crc_GPS3;
|
||||
// reset GPS3-data (json)
|
||||
gpx->lat = 0.0; gpx->lon = 0.0; gpx->alt = 0.0;
|
||||
gpx->vH = 0.0; gpx->vD = 0.0; gpx->vV = 0.0;
|
||||
gpx->numSV = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = check_CRC(gpx, pos_GPS3, pck_GPS3);
|
||||
if (err) gpx->crc |= crc_GPS3;
|
||||
|
||||
err |= get_GPSkoord(gpx); // plausibility-check: altitude, if ecef=(0,0,0)
|
||||
|
||||
return err;
|
||||
|
|
@ -891,7 +913,7 @@ static int get_Aux(gpx_t *gpx) {
|
|||
}
|
||||
gpx->xdata[n] = '\0';
|
||||
|
||||
i = check_CRC(gpx, pos7E, 0x7600); // 0x76xx: 00-padding block
|
||||
i = check_CRC(gpx, pos7E, pck_ZERO); // 0x76xx: 00-padding block
|
||||
if (i) gpx->crc |= crc_ZERO;
|
||||
|
||||
return count7E;
|
||||
|
|
@ -1080,20 +1102,20 @@ static int print_position(gpx_t *gpx, int ec) {
|
|||
int i;
|
||||
int err, err0, err1, err2, err3;
|
||||
int output, out_mask;
|
||||
int encrypted;
|
||||
int encrypted = 0;
|
||||
|
||||
gpx->out = 0;
|
||||
gpx->aux = 0;
|
||||
|
||||
err = get_FrameConf(gpx);
|
||||
|
||||
// Quick check for an encrypted packet (RS41-SGM)
|
||||
// These sondes have a type 0x80 packet in place of the regular PTU packet.
|
||||
if (gpx->frame[pos_PTU] == pck_ENCRYPTED){
|
||||
encrypted = 1;
|
||||
// Continue with the rest of the extraction (which will result in null data)
|
||||
if (check_CRC(gpx, pos_PTU, pck_ENCRYPTED)==0) { // frame[pos_PTU] == pck_ENCRYPTED>>8
|
||||
encrypted = 1; // and CRC-OK
|
||||
// Continue with the rest of the extraction
|
||||
}
|
||||
|
||||
err = get_FrameConf(gpx);
|
||||
|
||||
err1 = get_GPS1(gpx);
|
||||
err2 = get_GPS2(gpx);
|
||||
err3 = get_GPS3(gpx);
|
||||
|
|
@ -1113,8 +1135,8 @@ static int print_position(gpx_t *gpx, int ec) {
|
|||
fprintf(stdout, "[%5d] ", gpx->frnr);
|
||||
fprintf(stdout, "(%s) ", gpx->id);
|
||||
}
|
||||
if (encrypted) {
|
||||
fprintf(stdout, " Encrypted payload (RS41-SGM) ");
|
||||
if (encrypted) { // e.g. 0x80A7-pck
|
||||
fprintf(stdout, " (RS41-SGM: %02X%02X) ", gpx->frame[pos_PTU], gpx->frame[pos_PTU+1]);
|
||||
}
|
||||
if (!err1) {
|
||||
Gps2Date(gpx);
|
||||
|
|
@ -1131,7 +1153,7 @@ static int print_position(gpx_t *gpx, int ec) {
|
|||
//if (gpx->option.vbs)
|
||||
{
|
||||
//fprintf(stdout, " (%.1f %.1f %.1f) ", gpx->vN, gpx->vE, gpx->vU);
|
||||
fprintf(stdout," vH: %4.1f D: %5.1f vV: %3.1f ", gpx->vH, gpx->vD, gpx->vU);
|
||||
fprintf(stdout," vH: %4.1f D: %5.1f vV: %3.1f ", gpx->vH, gpx->vD, gpx->vV);
|
||||
if (gpx->option.vbs == 3) fprintf(stdout," sats: %02d ", gpx->numSV);
|
||||
}
|
||||
}
|
||||
|
|
@ -1149,9 +1171,9 @@ static int print_position(gpx_t *gpx, int ec) {
|
|||
int flen = NDATA_LEN;
|
||||
if (frametype(gpx) < 0) flen += XDATA_LEN;
|
||||
pos = pos_FRAME;
|
||||
while (pos < flen-1) {
|
||||
blk = gpx->frame[pos]; // 0x80XX: encrypted block
|
||||
len = gpx->frame[pos+1]; // 0x76XX: 00-padding block
|
||||
while (pos < flen-1) { // e.g.
|
||||
blk = gpx->frame[pos]; // 0x80xx: encrypted block
|
||||
len = gpx->frame[pos+1]; // 0x76xx: 00-padding block
|
||||
crc = check_CRC(gpx, pos, blk<<8);
|
||||
fprintf(stdout, " %02X%02X", gpx->frame[pos], gpx->frame[pos+1]);
|
||||
fprintf(stdout, "[%d]", crc&1);
|
||||
|
|
@ -1188,7 +1210,7 @@ static int print_position(gpx_t *gpx, int ec) {
|
|||
if ((!err && !err1 && !err3) || (!err && encrypted)) { // frame-nb/id && gps-time && gps-position (crc-)ok; 3 CRCs, RS not needed
|
||||
// eigentlich GPS, d.h. UTC = GPS - 18sec (ab 1.1.2017)
|
||||
fprintf(stdout, "{ \"frame\": %d, \"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f, \"sats\": %d",
|
||||
gpx->frnr, gpx->id, gpx->jahr, gpx->monat, gpx->tag, gpx->std, gpx->min, gpx->sek, gpx->lat, gpx->lon, gpx->alt, gpx->vH, gpx->vD, gpx->vU, gpx->numSV);
|
||||
gpx->frnr, gpx->id, gpx->jahr, gpx->monat, gpx->tag, gpx->std, gpx->min, gpx->sek, gpx->lat, gpx->lon, gpx->alt, gpx->vH, gpx->vD, gpx->vV, gpx->numSV );
|
||||
if (gpx->option.ptu && !err0 && gpx->T > -273.0) {
|
||||
fprintf(stdout, ", \"temp\": %.1f", gpx->T );
|
||||
}
|
||||
|
|
@ -1199,7 +1221,7 @@ static int print_position(gpx_t *gpx, int ec) {
|
|||
fprintf(stdout, ", \"aux\": \"%s\"", gpx->xdata );
|
||||
}
|
||||
if (encrypted){
|
||||
printf(",\"encrypted\": true");
|
||||
printf(", \"encrypted\": true");
|
||||
}
|
||||
fprintf(stdout, " }\n");
|
||||
fprintf(stdout, "\n");
|
||||
|
|
|
|||
Ładowanie…
Reference in New Issue