kopia lustrzana https://github.com/projecthorus/radiosonde_auto_rx
Merge pull request #986 from projecthorus/testing
v1.8.1 Release - RS41 Multi-GNSS Support, ka9q-radio updatesmaster v1.8.1
commit
8b6e2f25be
|
@ -41,6 +41,8 @@ jobs:
|
|||
|
||||
- name: Setup QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
with:
|
||||
image: tonistiigi/binfmt:qemu-v8.1.5
|
||||
|
||||
- name: Setup Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
|
|
@ -26,6 +26,7 @@ RUN apt-get update && \
|
|||
libbsd-dev \
|
||||
libfftw3-dev \
|
||||
libiniparser-dev \
|
||||
libogg-dev \
|
||||
libopus-dev && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
@ -61,11 +62,11 @@ RUN git clone https://github.com/miweber67/spyserver_client.git /root/spyserver_
|
|||
# Compile ka9q-radio from source
|
||||
RUN git clone https://github.com/ka9q/ka9q-radio.git /root/ka9q-radio && \
|
||||
cd /root/ka9q-radio && \
|
||||
git checkout ff7fe26a12909317b26bdb24a0576db87c15baf2 && \
|
||||
git checkout d0febaa033e1d53b9b53078cfe17457ac3676d20 && \
|
||||
make \
|
||||
-f Makefile.linux \
|
||||
"COPTS=-std=gnu11 -pthread -Wall -funsafe-math-optimizations -fno-math-errno -fcx-limited-range -D_GNU_SOURCE=1" \
|
||||
tune powers pcmcat
|
||||
ARCHOPTS= \
|
||||
tune powers pcmrecord
|
||||
|
||||
# Copy in radiosonde_auto_rx.
|
||||
COPY . /root/radiosonde_auto_rx
|
||||
|
@ -118,7 +119,7 @@ RUN ln -s ss_client /opt/auto_rx/ss_iq && \
|
|||
# Copy ka9q-radio utilities
|
||||
COPY --from=build /root/ka9q-radio/tune /usr/local/bin/
|
||||
COPY --from=build /root/ka9q-radio/powers /usr/local/bin/
|
||||
COPY --from=build /root/ka9q-radio/pcmcat /usr/local/bin/
|
||||
COPY --from=build /root/ka9q-radio/pcmrecord /usr/local/bin/
|
||||
|
||||
# Allow mDNS resolution for ka9q-radio utilities
|
||||
RUN sed -i -e 's/files dns/files mdns4_minimal [NOTFOUND=return] dns/g' /etc/nsswitch.conf
|
||||
|
|
|
@ -40,6 +40,8 @@ Improvements from the upstream RS codebase will be merged into this codebase whe
|
|||
Please consider joining the Google Group to receive updates on new software features:
|
||||
https://groups.google.com/forum/#!forum/radiosonde_auto_rx
|
||||
|
||||
We also have a channel in the SondeHub Discord server: https://sondehub.org/go/discord
|
||||
|
||||
## Presentations
|
||||
* Linux.conf.au 2019 - https://www.youtube.com/watch?v=YBy-bXEWZeM
|
||||
* UKHAS Conference 2019 - [Presented via Skype](https://youtu.be/azDJmMywBgw?t=643) which had some audio issues at the start. Slides [here](https://rfhead.net/sondes/auto_rx_presentation_UKHAS2019.pdf).
|
||||
|
|
|
@ -12,7 +12,7 @@ from queue import Queue
|
|||
# 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.8.0"
|
||||
__version__ = "1.8.1"
|
||||
|
||||
# Global Variables
|
||||
|
||||
|
|
|
@ -829,9 +829,10 @@ class SondeDecoder(object):
|
|||
_baud_rate = 4800
|
||||
_sample_rate = 48000 # 10x Oversampling
|
||||
|
||||
# Limit FSK estimator window to roughly +/- 10 kHz
|
||||
_lower = -10000
|
||||
_upper = 10000
|
||||
# Limit FSK estimator window to roughly +/- 5 kHz
|
||||
_lower = -5000
|
||||
_upper = 5000
|
||||
|
||||
|
||||
demod_cmd = get_sdr_iq_cmd(
|
||||
sdr_type = self.sdr_type,
|
||||
|
@ -844,14 +845,17 @@ class SondeDecoder(object):
|
|||
ppm = self.ppm,
|
||||
gain = self.gain,
|
||||
bias = self.bias,
|
||||
dc_block = True
|
||||
dc_block = True,
|
||||
channel_filter = 5000 # +/- 5 kHz channel filter.
|
||||
)
|
||||
|
||||
# Add in tee command to save IQ to disk if debugging is enabled.
|
||||
if self.save_decode_iq:
|
||||
demod_cmd += f" tee {self.save_decode_iq_path} |"
|
||||
|
||||
demod_cmd += "./fsk_demod --cs16 -b %d -u %d -s --stats=%d 2 %d %d - -" % (
|
||||
# Use a 4800 Hz mask estimator to better avoid adjacent sonde issues.
|
||||
# Also seems to give a small performance bump.
|
||||
demod_cmd += "./fsk_demod --cs16 -b %d -u %d -s --mask 4800 --stats=%d 2 %d %d - -" % (
|
||||
_lower,
|
||||
_upper,
|
||||
_stats_rate,
|
||||
|
@ -949,15 +953,9 @@ class SondeDecoder(object):
|
|||
_baud_rate = 2500
|
||||
_sample_rate = 50000 # 10x Oversampling
|
||||
|
||||
# Limit FSK estimator window to roughly +/- 10 kHz
|
||||
_lower = -10000
|
||||
_upper = 10000
|
||||
|
||||
if (abs(403200000 - self.sonde_freq) < 20000) and (self.sdr_type == "RTLSDR"):
|
||||
# Narrow up the frequency estimator window if we are close to
|
||||
# the 403.2 MHz RTLSDR Spur.
|
||||
_lower = -8000
|
||||
_upper = 8000
|
||||
# Limit FSK estimator window to roughly +/- 5 kHz
|
||||
_lower = -5000
|
||||
_upper = 5000
|
||||
|
||||
demod_cmd = get_sdr_iq_cmd(
|
||||
sdr_type = self.sdr_type,
|
||||
|
@ -970,7 +968,8 @@ class SondeDecoder(object):
|
|||
ppm = self.ppm,
|
||||
gain = self.gain,
|
||||
bias = self.bias,
|
||||
dc_block = True
|
||||
dc_block = True,
|
||||
channel_filter = 5000
|
||||
)
|
||||
|
||||
# Add in tee command to save IQ to disk if debugging is enabled.
|
||||
|
@ -978,6 +977,7 @@ class SondeDecoder(object):
|
|||
demod_cmd += f" tee {self.save_decode_iq_path} |"
|
||||
|
||||
# NOTE - Using inverted soft decision outputs, so DFM type detection works correctly.
|
||||
# No mask estimator - DFMs seem to decode better without it!
|
||||
demod_cmd += "./fsk_demod --cs16 -b %d -u %d -s -i --stats=%d 2 %d %d - -" % (
|
||||
_lower,
|
||||
_upper,
|
||||
|
|
|
@ -17,7 +17,8 @@ def ka9q_setup_channel(
|
|||
sdr_hostname,
|
||||
frequency,
|
||||
sample_rate,
|
||||
scan
|
||||
scan,
|
||||
channel_filter = None
|
||||
):
|
||||
if scan:
|
||||
ssrc="04"
|
||||
|
@ -25,12 +26,20 @@ def ka9q_setup_channel(
|
|||
ssrc="01"
|
||||
|
||||
# tune --samprate 48000 --frequency 404m09 --mode iq --ssrc 404090000 --radio sonde.local
|
||||
|
||||
if channel_filter:
|
||||
_low = int(channel_filter * -1.0)
|
||||
_high = int(channel_filter)
|
||||
else:
|
||||
_low = int(int(sample_rate) / (-2.4))
|
||||
_high = int(int(sample_rate) / 2.4)
|
||||
|
||||
_cmd = (
|
||||
f"{timeout_cmd()} 5 " # Add a timeout, because connections to non-existing servers block for ages
|
||||
f"tune "
|
||||
f"--samprate {int(sample_rate)} "
|
||||
f"--mode iq "
|
||||
f"--low {int(int(sample_rate) / (-2.4))} --high {int(int(sample_rate) / 2.4)} "
|
||||
f"--low {_low} --high {_high} "
|
||||
f"--frequency {int(frequency)} "
|
||||
f"--ssrc {round(frequency / 1000)}{ssrc} "
|
||||
f"--radio {sdr_hostname}"
|
||||
|
@ -120,7 +129,8 @@ def ka9q_get_iq_cmd(
|
|||
sdr_hostname,
|
||||
frequency,
|
||||
sample_rate,
|
||||
scan
|
||||
scan,
|
||||
channel_filter = None
|
||||
):
|
||||
if scan:
|
||||
ssrc="04"
|
||||
|
@ -128,7 +138,7 @@ def ka9q_get_iq_cmd(
|
|||
ssrc="01"
|
||||
|
||||
# We need to setup a channel before we can use it!
|
||||
_setup_success = ka9q_setup_channel(sdr_hostname, frequency, sample_rate, scan)
|
||||
_setup_success = ka9q_setup_channel(sdr_hostname, frequency, sample_rate, scan, channel_filter)
|
||||
|
||||
if not _setup_success:
|
||||
logging.critical(f"KA9Q ({sdr_hostname}) - Could not setup rx channel! Decoder will likely timeout.")
|
||||
|
@ -136,12 +146,13 @@ def ka9q_get_iq_cmd(
|
|||
# Get the 'PCM' version of the server name, where as assume -pcm is added to the first part of the hostname.
|
||||
_pcm_host = sdr_hostname.split('.')[0] + "-pcm." + ".".join(sdr_hostname.split(".")[1:])
|
||||
|
||||
# Example: pcmcat -s 404090000 sonde-pcm.local
|
||||
# Example: pcmrecord --ssrc 404090001 --catmode --raw sonde-pcm.local
|
||||
# -2 option was removed sometime in early 2024.
|
||||
_cmd = (
|
||||
f"pcmcat "
|
||||
f"-s {round(frequency / 1000)}{ssrc} "
|
||||
f"-b 1 "
|
||||
f"pcmrecord "
|
||||
f"--ssrc {round(frequency / 1000)}{ssrc} "
|
||||
f"--catmode "
|
||||
f"--raw "
|
||||
f"{_pcm_host} |"
|
||||
)
|
||||
|
||||
|
|
|
@ -288,13 +288,7 @@ def detect_sonde(
|
|||
_if_bw = 64
|
||||
else:
|
||||
_iq_bw = 48000
|
||||
_if_bw = 20
|
||||
|
||||
# Try and avoid the RTLSDR 403.2 MHz spur.
|
||||
# Note that this is only goign to work if we are detecting on 403.210 or 403.190 MHz.
|
||||
if (abs(403200000 - frequency) < 20000) and (sdr_type == "RTLSDR"):
|
||||
logging.debug("Scanner - Narrowing detection IF BW to avoid RTLSDR spur.")
|
||||
_if_bw = 15
|
||||
_if_bw = 15
|
||||
|
||||
else:
|
||||
# 1680 MHz sondes
|
||||
|
|
|
@ -24,7 +24,7 @@ def test_sdr(
|
|||
ss_iq_path = "./ss_iq",
|
||||
ss_power_path = "./ss_power",
|
||||
check_freq = 401500000,
|
||||
timeout = 5
|
||||
timeout = 20
|
||||
):
|
||||
"""
|
||||
Test the prescence / functionality of a SDR.
|
||||
|
@ -60,8 +60,8 @@ def test_sdr(
|
|||
# if not os.path.isfile('tune'):
|
||||
# logging.critical("Could not find KA9Q-Radio 'tune' binary! This may need to be compiled and installed.")
|
||||
# return False
|
||||
# if not os.path.isfile('pcmcat'):
|
||||
# logging.critical("Could not find KA9Q-Radio 'pcmcat' binary! This may need to be compiled and installed.")
|
||||
# if not os.path.isfile('pcmrecord'):
|
||||
# logging.critical("Could not find KA9Q-Radio 'pcmrecord' binary! This may need to be compiled and installed.")
|
||||
# return False
|
||||
# TBD - whatever we need for spectrum use.
|
||||
# if not os.path.isfile('TBD'):
|
||||
|
@ -281,7 +281,8 @@ def get_sdr_iq_cmd(
|
|||
sdr_hostname = "",
|
||||
sdr_port = 5555,
|
||||
ss_iq_path = "./ss_iq",
|
||||
scan = False
|
||||
scan = False,
|
||||
channel_filter = None
|
||||
):
|
||||
"""
|
||||
Get a command-line argument to get IQ (signed 16-bit) from a SDR
|
||||
|
@ -303,7 +304,8 @@ def get_sdr_iq_cmd(
|
|||
Arguments for KA9Q SDR Server / SpyServer:
|
||||
sdr_hostname (str): Hostname of KA9Q Server
|
||||
sdr_port (int): Port number of KA9Q Server
|
||||
scan (bool): Create unique SSRC for scan attempts
|
||||
scan (bool): Create unique SSRC for scan attempts (KA9Q Only)
|
||||
channel_filter (int/float): Set a high/lowpass frequency for a KA9Q channel.
|
||||
|
||||
Arguments for SpyServer Client:
|
||||
ss_iq_path (str): Path to spyserver IQ client utility.
|
||||
|
@ -361,9 +363,9 @@ def get_sdr_iq_cmd(
|
|||
return _cmd
|
||||
|
||||
if sdr_type == "KA9Q":
|
||||
_cmd = ka9q_get_iq_cmd(sdr_hostname, frequency, sample_rate, scan)
|
||||
_cmd = ka9q_get_iq_cmd(sdr_hostname, frequency, sample_rate, scan, channel_filter)
|
||||
|
||||
if dc_block:
|
||||
if dc_block and ("KA9Q" not in sdr_type):
|
||||
_cmd += _dc_remove
|
||||
|
||||
return _cmd
|
||||
|
@ -779,7 +781,6 @@ def get_power_spectrum(
|
|||
_ssrc = f"{round(_center_freq / 1000)}03"
|
||||
|
||||
_powers_cmd = (
|
||||
f"LANG=C " # temporary workaround for https://github.com/ka9q/ka9q-radio/pull/65#issuecomment-2480243690
|
||||
f"{_timeout_cmd} {ka9q_powers_path} "
|
||||
f"{sdr_hostname} "
|
||||
f"-f {_center_freq} "
|
||||
|
|
|
@ -213,7 +213,7 @@
|
|||
scan_chart_latest_timestamp = data.timestamp;
|
||||
|
||||
// Do not update the scan plot if the tab is hidden, or we have the scan plot hidden.
|
||||
if( (document.visibilityState == "hidden") || (document.getElementById("showscanbutton").checked == false) ){
|
||||
if( (document.visibilityState == "hidden") || (document.getElementById("scanid").hasAttribute("open") == false) ){
|
||||
return;
|
||||
} else {
|
||||
redraw_scan_chart(data);
|
||||
|
@ -224,7 +224,7 @@
|
|||
});
|
||||
|
||||
document.addEventListener("visibilitychange", () => {
|
||||
if (document.visibilityState === "visible" && document.getElementById("showscanbutton").checked) {
|
||||
if (document.visibilityState === "visible" && document.getElementById("scanid").hasAttribute("open")) {
|
||||
redraw_scan_chart();
|
||||
}
|
||||
});
|
||||
|
@ -312,18 +312,17 @@
|
|||
|
||||
// Check if user has preffered map visiblity.
|
||||
if (getCookie('map') == 'false') {
|
||||
document.getElementById("showmapbutton").checked = false;
|
||||
document.getElementById("mapid_details").removeAttribute("open") ;
|
||||
document.getElementById("mapid").style.display = "none";
|
||||
} else {
|
||||
document.getElementById("showmapbutton").checked = true;
|
||||
document.getElementById("mapid_details").setAttribute("open", true) ;
|
||||
}
|
||||
|
||||
// Check if user has preffered table visiblity.
|
||||
if (getCookie('table') == 'false') {
|
||||
document.getElementById("showtablebutton").checked = false;
|
||||
document.getElementById("tableid").style.display = "none";
|
||||
document.getElementById("tableid").removeAttribute("open") ;
|
||||
} else {
|
||||
document.getElementById("showtablebutton").checked = true;
|
||||
document.getElementById("tableid").setAttribute("open", true) ;
|
||||
}
|
||||
|
||||
// Check if user has preffered follow latest sonde selection.
|
||||
|
@ -360,11 +359,9 @@
|
|||
|
||||
// Check if user has preffered scan chart visiblity.
|
||||
if (getCookie('scan') == 'true') {
|
||||
document.getElementById("showscanbutton").checked = true;
|
||||
document.getElementById("scanid").style.display = "block";
|
||||
document.getElementById("scanid").setAttribute("open", true) ;
|
||||
} else {
|
||||
document.getElementById("showscanbutton").checked = false;
|
||||
document.getElementById("scanid").style.display = "none";
|
||||
document.getElementById("scanid").removeAttribute("open") ;
|
||||
}
|
||||
|
||||
// Check if user has dark mode set.
|
||||
|
@ -464,6 +461,31 @@
|
|||
mymap.invalidateSize();
|
||||
})
|
||||
|
||||
$("#tableid").on("toggle", function() {
|
||||
mymap.invalidateSize();
|
||||
setCookie("table", $("#tableid").prop("open"), 365);
|
||||
})
|
||||
|
||||
$("#scanid").on("toggle", function() {
|
||||
mymap.invalidateSize();
|
||||
setCookie("scan", $("#scanid").prop("open"), 365);
|
||||
if ($("#scanid").prop("open")) {
|
||||
redraw_scan_chart();
|
||||
scan_chart_obj.flush();
|
||||
}
|
||||
})
|
||||
|
||||
$("#mapid_details").on("toggle", function() {
|
||||
mymap.invalidateSize();
|
||||
setCookie("map", $("#mapid_details").prop("open"), 365);
|
||||
if ($("#mapid_details").prop("open")) {
|
||||
document.getElementById("mapid").style.display = "block";
|
||||
mymap.invalidateSize();
|
||||
} else {
|
||||
document.getElementById("mapid").style.display = "none";
|
||||
}
|
||||
})
|
||||
|
||||
// Create Tabulator table.
|
||||
table = new Tabulator("#telem_table", {
|
||||
index:"realid",
|
||||
|
@ -485,12 +507,12 @@
|
|||
_sondehub_id = _cell_data.id.replace(/^(DFM|M10|M20|IMET|IMET5|IMET54|MRZ|IMS100|RS11G|MTS01|WXR)-/,"");
|
||||
|
||||
// Add Sondehub Link
|
||||
_id += " <a href='http://sondehub.org/" + _sondehub_id + "' title='View on Sondehub' target='_blank'>" + "<img src='{{ url_for('static', filename='img/sondehub.png')}}'/>" + "</a>";
|
||||
_id += " <a href='http://sondehub.org/" + _sondehub_id + "' title='View on Sondehub' target='_blank'>" + "<img src='{{ url_for('static', filename='img/sondehub.png')}}' width='14' height='16'/>" + "</a>";
|
||||
|
||||
// Add Radiosondy Link
|
||||
if(_cell_data.aprsid != null){
|
||||
_aprs_id = _cell_data.aprsid.trim();
|
||||
_id += "<a href='https://radiosondy.info/sonde_archive.php?sondenumber=" + _aprs_id + "' title='View on Radiosondy.info' target='_blank'>" + "<img src='{{ url_for('static', filename='img/radiosondy.png')}}'/>" + "</a>";
|
||||
_id += "<a href='https://radiosondy.info/sonde_archive.php?sondenumber=" + _aprs_id + "' title='View on Radiosondy.info' target='_blank'>" + "<img src='{{ url_for('static', filename='img/radiosondy.png')}}' width='17' height='16'/>" + "</a>";
|
||||
|
||||
} else {
|
||||
_aprs_id = null;
|
||||
|
@ -1265,7 +1287,7 @@
|
|||
myDiv.scrollTop = 0;
|
||||
if ((window.innerWidth/window.innerHeight) > 1) { // 350px wide on desktop.
|
||||
x.style.display = "none";
|
||||
if (getCookie('map') == true || document.getElementById("showmapbutton").checked == true) {
|
||||
if (getCookie('map') == true || document.getElementById("mapid_details").hasAttribute("open")) {
|
||||
y.style.display = "block";
|
||||
}
|
||||
document.getElementById("mySidenav").style.width = "350px";
|
||||
|
@ -1282,7 +1304,7 @@
|
|||
}
|
||||
} else {
|
||||
x.style.display = "none";
|
||||
if (getCookie('map') == true || document.getElementById("showmapbutton").checked == true) {
|
||||
if (getCookie('map') == true || document.getElementById("mapid_details").hasAttribute("open")) {
|
||||
y.style.display = "block";
|
||||
}
|
||||
document.getElementById("mySidenav").style.width = 0;
|
||||
|
@ -1297,7 +1319,7 @@
|
|||
var y = document.getElementById('mapid');
|
||||
if (document.getElementById("mySettings").style.width == "0px" || document.getElementById("mySettings").style.width == 0) {
|
||||
if ((window.innerWidth/window.innerHeight) > 1) { // 350px wide on desktop.
|
||||
if (getCookie('map') == true || document.getElementById("showmapbutton").checked == true) {
|
||||
if (getCookie('map') == true || document.getElementById("mapid_details").hasAttribute("open")) {
|
||||
y.style.display = "block";
|
||||
}
|
||||
document.getElementById("mySettings").style.width = "350px";
|
||||
|
@ -1313,7 +1335,7 @@
|
|||
document.getElementById("mySettings").style.borderRadius = "0px";
|
||||
}
|
||||
} else {
|
||||
if (getCookie('map') == true || document.getElementById("showmapbutton").checked == true) {
|
||||
if (getCookie('map') == true || document.getElementById("mapid_details").hasAttribute("open")) {
|
||||
y.style.display = "block";
|
||||
}
|
||||
document.getElementById("mySettings").style.width = 0;
|
||||
|
@ -1332,33 +1354,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
// Show/hide map on button press and update cookies.
|
||||
function showMap(element) {
|
||||
if (element.checked == false) {
|
||||
document.getElementById("mapid").style.display = "none";
|
||||
setCookie("map", 'false', 365);
|
||||
} else {
|
||||
document.getElementById("mapid").style.display = "block";
|
||||
setCookie("map", 'true', 365);
|
||||
mymap.invalidateSize();
|
||||
}
|
||||
}
|
||||
|
||||
// Show/hide scan chart on button press and update cookies.
|
||||
function showScan(element) {
|
||||
if (element.checked == false) {
|
||||
document.getElementById("scanid").style.display = "none";
|
||||
setCookie("scan", 'false', 365);
|
||||
mymap.invalidateSize();
|
||||
} else {
|
||||
document.getElementById("scanid").style.display = "block";
|
||||
setCookie("scan", 'true', 365);
|
||||
mymap.invalidateSize();
|
||||
redraw_scan_chart();
|
||||
scan_chart_obj.flush();
|
||||
}
|
||||
}
|
||||
|
||||
// Enable/disable auto follow on button press and update cookies.
|
||||
function autoFollow(element) {
|
||||
if (element.checked == false) {
|
||||
|
@ -1368,17 +1363,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
// Show/hide table on button press and update cookies.
|
||||
function showTable(element) {
|
||||
if (element.checked == false) {
|
||||
document.getElementById("tableid").style.display = "none";
|
||||
setCookie("table", 'false', 365);
|
||||
} else {
|
||||
document.getElementById("tableid").style.display = "block";
|
||||
setCookie("table", 'true', 365);
|
||||
}
|
||||
}
|
||||
|
||||
// Set given cookie name and value.
|
||||
function setCookie(name,value) {
|
||||
localStorage.setItem(name, value);
|
||||
|
@ -1493,36 +1477,6 @@
|
|||
<label> Other</label><br><br>
|
||||
</form>
|
||||
<div style="margin-left:40px;">
|
||||
<h2 style="display:inline;vertical-align:middle;">Show Table</h2>
|
||||
|
||||
<div style="display:inline;vertical-align:middle;">
|
||||
<label class="switch">
|
||||
<input type="checkbox" onchange="showTable(this)" id="showtablebutton">
|
||||
<span class="slider round"></span>
|
||||
</label>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<h2 style="display:inline;vertical-align:middle;">Show Scan Plot</h2>
|
||||
|
||||
<div style="display:inline;vertical-align:middle;">
|
||||
<label class="switch">
|
||||
<input type="checkbox" onchange="showScan(this)" id="showscanbutton">
|
||||
<span class="slider round"></span>
|
||||
</label>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<h2 style="display:inline;vertical-align:middle;">Show Map</h2>
|
||||
|
||||
<div style="display:inline;vertical-align:middle;">
|
||||
<label class="switch">
|
||||
<input type="checkbox" onchange="showMap(this)" id="showmapbutton">
|
||||
<span class="slider round"></span>
|
||||
</label>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<h2 style="display:inline;vertical-align:middle;">Dark Mode</h2>
|
||||
|
||||
<div style="display:inline;vertical-align:middle;">
|
||||
|
@ -1638,14 +1592,19 @@
|
|||
<summary id="summary_element">Tasking: <span id="task_summary"></span></summary>
|
||||
<span id="task_details"></span>
|
||||
</details>
|
||||
<div id="tableid">
|
||||
<details id="tableid" style="font-size:2vh;font-size:calc(var(--vh, 1vh) * 2);">
|
||||
<summary id="summary_element_telem_table">Telemetry</summary>
|
||||
<div id="telem_table"></div>
|
||||
</div>
|
||||
<div id="scanid">
|
||||
</details>
|
||||
<details id="scanid" style="font-size:2vh;font-size:calc(var(--vh, 1vh) * 2);">
|
||||
<summary id="summary_element_scan_plot">Scan Plot</summary>
|
||||
<div id='scan_results'>No scan data yet...</div>
|
||||
<div id="scan_chart" style="width:100%;"></div>
|
||||
</div>
|
||||
</details>
|
||||
<br>
|
||||
<details id="mapid_details" style="font-size:2vh;font-size:calc(var(--vh, 1vh) * 2);">
|
||||
<summary id="summary_element_map">Map</summary>
|
||||
</details>
|
||||
<div id="mapid"></div>
|
||||
<i id="myBtn1" onclick="changeSettings()" class="icon-cog" style="font-size:4vh;font-size:calc(var(--vh, 1vh) * 4);"></i>
|
||||
<a href="historical.html" id="myBtn2"><i class="icon-history" style="font-size:4vh;font-size:calc(var(--vh, 1vh) * 4);"></i></a>
|
||||
|
|
|
@ -718,7 +718,7 @@ def lsusb():
|
|||
|
||||
depth = 1 + len(indent_match.group(1)) / 2
|
||||
if depth > len(depth_stack):
|
||||
logging.debug('lsusb parsing error: unexpected indentation: "%s"', line)
|
||||
#logging.debug('lsusb parsing error: unexpected indentation: "%s"', line)
|
||||
continue
|
||||
|
||||
while depth < len(depth_stack):
|
||||
|
@ -743,7 +743,7 @@ def lsusb():
|
|||
depth_stack.append(new_entry)
|
||||
continue
|
||||
|
||||
logging.debug('lsusb parsing error: unrecognized line: "%s"', line)
|
||||
#logging.debug('lsusb parsing error: unrecognized line: "%s"', line)
|
||||
|
||||
if device:
|
||||
devices.append(device)
|
||||
|
|
|
@ -19,10 +19,9 @@
|
|||
#
|
||||
# RTLSDR - Use one or more RTLSDRs
|
||||
#
|
||||
# EXPERIMENTAL / NOT IMPLEMENTED options:
|
||||
# Network SDR Server options:
|
||||
# SpyServer - Use an Airspy SpyServer
|
||||
# KA9Q - Use a KA9Q-Radio Server
|
||||
# WARNING: These are still under development and may not work correctly.
|
||||
#
|
||||
sdr_type = RTLSDR
|
||||
|
||||
|
@ -140,7 +139,7 @@ always_decode = []
|
|||
# STATION LOCATION #
|
||||
####################
|
||||
# Used by the Sondehub Uploader, APRS Uploader, and by Rotator Control
|
||||
# Lat/Lon in decimal degrees, altitude in metres.
|
||||
# Lat/Lon in decimal degrees, altitude in metres (AMSL).
|
||||
# Note: You do not need to specify your home station accurately if you don't want to!
|
||||
# Feel free to use a position somewhere near your general area, that doesn't identify your home location.
|
||||
#
|
||||
|
|
|
@ -20,12 +20,11 @@
|
|||
#
|
||||
# RTLSDR - Use one or more RTLSDRs
|
||||
#
|
||||
# EXPERIMENTAL / NOT IMPLEMENTED options:
|
||||
# Network SDR Server options:
|
||||
# SpyServer - Use an Airspy SpyServer
|
||||
# KA9Q - Use a KA9Q-Radio Server
|
||||
# WARNING: These are still under development and may not work correctly.
|
||||
#
|
||||
sdr_type = SpyServer
|
||||
sdr_type = KA9Q
|
||||
|
||||
|
||||
#
|
||||
|
@ -38,7 +37,7 @@ sdr_type = SpyServer
|
|||
# If SDR type is either KA9Q or SpyServer, this defines the maximum number of parallel
|
||||
# decoding/scan tasks. On a RPi 4, ~5 tasks are possible.
|
||||
#
|
||||
sdr_quantity = 5
|
||||
sdr_quantity = 10
|
||||
|
||||
|
||||
#
|
||||
|
@ -48,7 +47,7 @@ sdr_quantity = 5
|
|||
# Is using KA9Q-Radio, the hostname of the 'radio' server (e.g. sonde.local) needs to be
|
||||
# defined, and the port number is unused.
|
||||
#
|
||||
sdr_hostname = localhost
|
||||
sdr_hostname = sonde.local
|
||||
sdr_port = 5555
|
||||
|
||||
#
|
||||
|
@ -141,7 +140,7 @@ always_decode = []
|
|||
# STATION LOCATION #
|
||||
####################
|
||||
# Used by the Sondehub Uploader, APRS Uploader, and by Rotator Control
|
||||
# Lat/Lon in decimal degrees, altitude in metres.
|
||||
# Lat/Lon in decimal degrees, altitude in metres (AMSL).
|
||||
# Note: You do not need to specify your home station accurately if you don't want to!
|
||||
# Feel free to use a position somewhere near your general area, that doesn't identify your home location.
|
||||
#
|
||||
|
@ -550,8 +549,8 @@ scan_delay = 10
|
|||
quantization = 10000
|
||||
# Decoder Spacing Limit - Only start a new decoder if it is separated from an existing decoder by at least
|
||||
# this value (Hz). This helps avoid issues where a drifting radiosonde is detected on two adjacent channels.
|
||||
# If you regularly encounter radiosondes on adjacent (10kHz) channels, then set this value to 5000.
|
||||
decoder_spacing_limit = 15000
|
||||
# For Network SDR systems, we set this to a lower value than the usual default of 15 kHz, as we have better channel filtering.
|
||||
decoder_spacing_limit = 5000
|
||||
# Temporary Block Time (minutes) - How long to block encrypted or otherwise non-decodable sondes for.
|
||||
temporary_block_time = 120
|
||||
# Upload when (seconds_since_utc_epoch%upload_rate) == 0. Otherwise just delay upload_rate seconds between uploads.
|
||||
|
|
|
@ -209,7 +209,7 @@ processing_type = {
|
|||
},
|
||||
'rs41_fsk_demod_soft_centre': {
|
||||
# Keep signal centred.
|
||||
'demod' : "| csdr convert_f_s16 | ./tsrc - - 0.500 | ../fsk_demod --cs16 -b -10000 -u 10000 -s --stats=5 2 48000 4800 - - 2>stats.txt |",
|
||||
'demod' : "| csdr convert_f_s16 | ./tsrc - - 0.500 | ../fsk_demod --cs16 -b -10000 -u 10000 -s --mask 4800 --stats=5 2 48000 4800 - - 2>stats.txt |",
|
||||
|
||||
# Decode using rs41ecc
|
||||
'decode': "../rs41mod --ecc --ptu --crc --softin -i --json 2>/dev/null",
|
||||
|
@ -275,6 +275,32 @@ processing_type = {
|
|||
"post_process" : "| grep aprsid | wc -l",
|
||||
'files' : "./generated/m10*"
|
||||
},
|
||||
'm10_fsk_demod_soft_centre_48000': {
|
||||
# Shift up to ~24 khz, and then pass into fsk_demod.
|
||||
'demod' : "| csdr convert_f_s16 | ../tsrc - - 0.500 -c | ../fsk_demod --cs16 -b -10000 -p 5 -u 10000 -s --stats=5 2 48000 9600 - - 2>stats.txt |",
|
||||
'decode': "../m10mod --json --softin -i -vvv 2>/dev/null",
|
||||
# Count the number of telemetry lines.
|
||||
"post_process" : "| grep aprsid | wc -l",
|
||||
'files' : "./generated/m10*"
|
||||
},
|
||||
|
||||
'm10_fsk_demod_soft_centre_48000_2': {
|
||||
# Shift up to ~24 khz, and then pass into fsk_demod.
|
||||
'demod' : "| csdr convert_f_s16 | ../tsrc - - 0.500 -c | ../fsk_demod --cs16 -b -10000 -p 5 -u 10000 -s --stats=5 2 48080 9616 - - 2>stats.txt |",
|
||||
'decode': "../m10mod --json --softin -i -vvv 2>/dev/null",
|
||||
# Count the number of telemetry lines.
|
||||
"post_process" : "| grep aprsid | wc -l",
|
||||
'files' : "./generated/m10*"
|
||||
},
|
||||
|
||||
'm10_fsk_demod_soft_centre_96200': {
|
||||
# Shift up to ~24 khz, and then pass into fsk_demod.
|
||||
'demod' : "| csdr convert_f_s16 | ../tsrc - - 1.0020833333333334 -c | ../fsk_demod --cs16 -b -10000 -p 10 -u 10000 -s --stats=5 2 96200 9620 - - 2>stats.txt |",
|
||||
'decode': "../m10mod --json --softin -i -vvv 2>/dev/null",
|
||||
# Count the number of telemetry lines.
|
||||
"post_process" : "| grep aprsid | wc -l",
|
||||
'files' : "./generated/m10*"
|
||||
},
|
||||
'm20_fsk_demod_soft_centre': {
|
||||
# Shift up to ~24 khz, and then pass into fsk_demod.
|
||||
'demod' : "| csdr convert_f_s16 | ./tsrc - - 0.500 | ../fsk_demod --cs16 -p 5 -b -10000 -u 10000 -s --stats=5 2 48000 9600 - - 2>stats.txt |",
|
||||
|
|
|
@ -456,12 +456,10 @@ static int get_GPSvel(gpx_t *gpx) {
|
|||
|
||||
static int get_SN(gpx_t *gpx) {
|
||||
int i;
|
||||
ui8_t b0 = gpx->frame_bytes[pos_SN]; //0x12
|
||||
ui32_t s2 = (gpx->frame_bytes[pos_SN+2]<<8) | gpx->frame_bytes[pos_SN+1];
|
||||
ui8_t ym = b0 & 0x7F; // #{0x0,..,0x77}=120=10*12
|
||||
ui32_t sn24 = (gpx->frame_bytes[pos_SN+2]<<16) | (gpx->frame_bytes[pos_SN+1]<<8) | gpx->frame_bytes[pos_SN];
|
||||
ui8_t ym = sn24 & 0x7F; // #{0x0,..,0x77}=120=10*12
|
||||
ui8_t y = ym / 12;
|
||||
ui8_t m = (ym % 12)+1; // there is b0=0x69<0x80 from 2018-09-19 ...
|
||||
ui32_t sn_val = 0;
|
||||
|
||||
for (i = 0; i < 11; i++) gpx->SN[i] = ' '; gpx->SN[11] = '\0';
|
||||
for (i = 12; i < 15; i++) gpx->SN[i] = '\0'; gpx->SN[15] = '\0';
|
||||
|
@ -469,15 +467,14 @@ static int get_SN(gpx_t *gpx) {
|
|||
for (i = 0; i < 3; i++) {
|
||||
gpx->SNraw[i] = gpx->frame_bytes[pos_SN + i];
|
||||
}
|
||||
sn_val = (gpx->SNraw[0]<<16) | (gpx->SNraw[1]<<8) | gpx->SNraw[2];
|
||||
|
||||
sprintf(gpx->SN, "%u%02u", y, m); // more samples needed
|
||||
sprintf(gpx->SN+3, "-%u-", (s2&0x3)+2); // (b0>>7)+1? (s2&0x3)+2?
|
||||
sprintf(gpx->SN+6, "%u", (s2>>(2+13))&0x1); // ?(s2>>(2+13))&0x1 ?? (s2&0x3)?
|
||||
sprintf(gpx->SN+7, "%04u", (s2>>2)&0x1FFF);
|
||||
sprintf(gpx->SN, "%u%02u", y, m);
|
||||
sprintf(gpx->SN+3, "-%u-", ((sn24>> 7)&0x7)+1);
|
||||
sprintf(gpx->SN+6, "%u", (sn24>>23)&0x1);
|
||||
sprintf(gpx->SN+7, "%04u", (sn24>>10)&0x1FFF);
|
||||
|
||||
|
||||
if (sn_val == 0)
|
||||
if (sn24 == 0)
|
||||
{ // get_GPStime(gpx);
|
||||
// replace SN: 001-2-00000 -> 000-0-00000-[_diffcnt]
|
||||
sprintf(gpx->SN, "%s", "000-0-00000");
|
||||
|
|
|
@ -99,11 +99,20 @@ typedef struct {
|
|||
int sort_idx2[FRAME_LEN]; // ui8_t[] sort_cw2_idx
|
||||
} ecdat_t;
|
||||
|
||||
typedef struct {
|
||||
ui8_t id168;
|
||||
ui8_t status;
|
||||
} gnss_t;
|
||||
|
||||
typedef struct {
|
||||
int out;
|
||||
int frnr;
|
||||
char id[9];
|
||||
ui8_t numSV;
|
||||
ui8_t gnss_numSVb168;
|
||||
ui8_t gnss_nSVstatus;
|
||||
gnss_t gnss_sv[32];
|
||||
ui8_t isUTC;
|
||||
int week; int tow_ms; int gpssec;
|
||||
int jahr; int monat; int tag;
|
||||
int wday;
|
||||
|
@ -383,6 +392,12 @@ GPS chip: ublox UBX-G6010-ST
|
|||
#define pck_SGM_xTU 0x7F1B // temperature/humidity
|
||||
#define pck_SGM_CRYPT 0x80A7 // Packet type for an Encrypted payload
|
||||
|
||||
// fw 0x50dd
|
||||
#define pck_960A 0x960A //
|
||||
#define pck_8226_POSDATETIME 0x8226 // ECEF-POS/VEL , DATE/TIME
|
||||
#define pck_8329_SATS 0x8329 // GNSS sats
|
||||
|
||||
|
||||
/*
|
||||
frame[pos_FRAME-1] == 0x0F: len == NDATA_LEN(320)
|
||||
frame[pos_FRAME-1] == 0xF0: len == FRAME_LEN(518)
|
||||
|
@ -470,6 +485,10 @@ static int get_SondeID(gpx_t *gpx, int crc, int ofs) {
|
|||
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;
|
||||
gpx->gnss_numSVb168 = 0;
|
||||
gpx->gnss_nSVstatus = 0;
|
||||
memset(gpx->gnss_sv, 0, 32*sizeof(gnss_t)); // gpx->gnss_sv[i].id168 = 0; gpx->gnss_sv[i].status = 0;
|
||||
gpx->isUTC = 0;
|
||||
gpx->T = -273.15f;
|
||||
gpx->RH = -1.0f;
|
||||
gpx->P = -1.0f;
|
||||
|
@ -942,6 +961,7 @@ static int get_GPStime(gpx_t *gpx, int ofs) {
|
|||
gpx->std = gpstime / 3600;
|
||||
gpx->min = (gpstime % 3600) / 60;
|
||||
gpx->sek = gpstime % 60 + ms/1000.0;
|
||||
gpx->isUTC = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -956,6 +976,7 @@ static int get_GPS1(gpx_t *gpx, int ofs) {
|
|||
// reset GPS1-data (json)
|
||||
gpx->jahr = 0; gpx->monat = 0; gpx->tag = 0;
|
||||
gpx->std = 0; gpx->min = 0; gpx->sek = 0.0;
|
||||
gpx->isUTC = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1005,7 +1026,7 @@ static void ecef2elli(double X[], double *lat, double *lon, double *alt) {
|
|||
*lon = lam*180/M_PI;
|
||||
}
|
||||
|
||||
static int get_GPSkoord(gpx_t *gpx, int ofs) {
|
||||
static int get_ECEFkoord(gpx_t *gpx, int pos_ecef) {
|
||||
int i, k;
|
||||
unsigned byte;
|
||||
ui8_t XYZ_bytes[4];
|
||||
|
@ -1021,14 +1042,14 @@ static int get_GPSkoord(gpx_t *gpx, int ofs) {
|
|||
for (k = 0; k < 3; k++) {
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
byte = gpx->frame[pos_GPSecefX+ofs + 4*k + i];
|
||||
byte = gpx->frame[pos_ecef + 4*k + i];
|
||||
XYZ_bytes[i] = byte;
|
||||
}
|
||||
memcpy(&XYZ, XYZ_bytes, 4);
|
||||
X[k] = XYZ / 100.0;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
byte = gpx->frame[pos_GPSecefV+ofs + 2*k + i];
|
||||
byte = gpx->frame[pos_ecef+12 + 2*k + i];
|
||||
gpsVel_bytes[i] = byte;
|
||||
}
|
||||
vel16 = gpsVel_bytes[0] | gpsVel_bytes[1] << 8;
|
||||
|
@ -1068,8 +1089,6 @@ static int get_GPSkoord(gpx_t *gpx, int ofs) {
|
|||
|
||||
gpx->vV = vU;
|
||||
|
||||
gpx->numSV = gpx->frame[pos_numSats+ofs];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1086,12 +1105,157 @@ static int get_GPS3(gpx_t *gpx, int ofs) {
|
|||
gpx->numSV = 0;
|
||||
return -1;
|
||||
}
|
||||
// pos_GPS3+2 = pos_GPSecefX
|
||||
err |= get_ECEFkoord(gpx, pos_GPS3+ofs+2); // plausibility-check: altitude, if ecef=(0,0,0)
|
||||
|
||||
err |= get_GPSkoord(gpx, ofs); // plausibility-check: altitude, if ecef=(0,0,0)
|
||||
gpx->numSV = gpx->frame[pos_numSats+ofs];
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
// GNSS1=8226
|
||||
static int get_posdatetime(gpx_t *gpx, int pos_posdatetime) {
|
||||
int err=0;
|
||||
|
||||
err = check_CRC(gpx, pos_posdatetime, pck_8226_POSDATETIME);
|
||||
if (err) {
|
||||
///TODO: fw 0x50dd , ec < 0
|
||||
gpx->crc |= crc_GPS1 | crc_GPS3;
|
||||
// reset GPS1-data (json)
|
||||
gpx->jahr = 0; gpx->monat = 0; gpx->tag = 0;
|
||||
gpx->std = 0; gpx->min = 0; gpx->sek = 0.0;
|
||||
gpx->isUTC = 0;
|
||||
// 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;
|
||||
}
|
||||
|
||||
// ublox M10 UBX-NAV-POSECEF (0x01 0x01) ?
|
||||
err |= get_ECEFkoord(gpx, pos_posdatetime+2); // plausibility-check: altitude, if ecef=(0,0,0)
|
||||
|
||||
// ublox M10 UBX-NAV-PVT (0x01 0x07) ? (UTC)
|
||||
// date
|
||||
gpx->jahr = gpx->frame[pos_posdatetime+20] | gpx->frame[pos_posdatetime+21]<<8;
|
||||
gpx->monat = gpx->frame[pos_posdatetime+22];
|
||||
gpx->tag = gpx->frame[pos_posdatetime+23];
|
||||
// time
|
||||
gpx->std = gpx->frame[pos_posdatetime+24];
|
||||
gpx->min = gpx->frame[pos_posdatetime+25];
|
||||
gpx->sek = gpx->frame[pos_posdatetime+26];
|
||||
if (gpx->frame[pos_posdatetime+27] < 100) gpx->sek += gpx->frame[pos_posdatetime+27]/100.0;
|
||||
//
|
||||
gpx->isUTC = 1;
|
||||
|
||||
///TODO: numSV/fixOK
|
||||
//gpx->numSV = gpx->frame[pos_numSats+ofs];
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
// GNSS2=8329
|
||||
static int get_gnssSVs(gpx_t *gpx, int pos_gnss2) {
|
||||
int err=0;
|
||||
|
||||
memset(gpx->gnss_sv, 0, 32*sizeof(gnss_t));
|
||||
gpx->gnss_numSVb168 = 0;
|
||||
gpx->gnss_nSVstatus = 0;
|
||||
|
||||
err = check_CRC(gpx, pos_gnss2, pck_8329_SATS);
|
||||
|
||||
if (!err) {
|
||||
// ublox M10 UBX-NAV-SAT (0x01 0x35) ?
|
||||
// ublox M10 UBX-NAV-SIG (0x01 0x43) ?
|
||||
|
||||
// int pos_gnss1 = 161;
|
||||
// int pos_gnss2 = 203; == pos_posgnss
|
||||
// int pos_zero = 248;
|
||||
|
||||
int cntSV168 = 0; // 21*8 bits
|
||||
// 00..31: GPS, PRN+1
|
||||
// 32..67: GALILEO, GAL_E + 31
|
||||
for (int j = 0; j < 21; j++) {
|
||||
int b = gpx->frame[pos_gnss2+2+4+j];
|
||||
for (int n = 0; n < 8; n++) { //DBG fprintf(stdout, "%d", (b>>n)&1);
|
||||
int s = (b>>n)&1;
|
||||
if (s) {
|
||||
ui8_t svid = j*8+n + 1;
|
||||
if (cntSV168 < 32) {
|
||||
gpx->gnss_sv[cntSV168].id168 = svid;
|
||||
//DBG fprintf(stdout, " %3d", svid);
|
||||
}
|
||||
cntSV168 += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
gpx->gnss_numSVb168 = cntSV168;
|
||||
|
||||
int cntSVstatus = 0; // max 16*2
|
||||
for (int j = 0; j < 16; j++) {
|
||||
ui8_t b = gpx->frame[pos_gnss2+2+4+21+j];
|
||||
ui8_t b0 = b & 0xF; // b & 0x0F
|
||||
ui8_t b1 = (b>>4) & 0xF; // b & 0xF0
|
||||
gpx->gnss_sv[2*j ].status = b0; if (b0) cntSVstatus++;
|
||||
gpx->gnss_sv[2*j+1].status = b1; if (b1) cntSVstatus++;
|
||||
}
|
||||
gpx->gnss_nSVstatus = cntSVstatus;
|
||||
|
||||
//check: cntSV168 == cntSVstatus ?
|
||||
|
||||
///TODO: numSV/fixOK
|
||||
// used in solution / tracked / searched / visible ?
|
||||
gpx->numSV = gpx->gnss_nSVstatus; // == gpx->gnss_numSVb168 ?
|
||||
}
|
||||
else {
|
||||
///TODO: fw 0x50dd , ec < 0
|
||||
gpx->crc |= crc_GPS2;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int prn_gnss_sat2(gpx_t *gpx) {
|
||||
int n;
|
||||
|
||||
fprintf(stdout, "\n");
|
||||
fprintf(stdout, " numSV168 : %2d", gpx->gnss_numSVb168);
|
||||
fprintf(stdout, " nSVstatus: %2d", gpx->gnss_nSVstatus);
|
||||
// DBG fprintf(stdout, " # %d #", gpx->nss_numSV168 - gpx->gnss_nSVstatus);
|
||||
fprintf(stdout, "\n");
|
||||
fprintf(stdout, " SVids: ");
|
||||
for (n = 0; n < 32; n++) {
|
||||
if (n < gpx->gnss_numSVb168) fprintf(stdout, " %3d", gpx->gnss_sv[n].id168);
|
||||
if (n < gpx->gnss_nSVstatus) fprintf(stdout, ":%X", gpx->gnss_sv[n].status);
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
for (n = 0; n < 32; n++) {
|
||||
if (n < gpx->gnss_numSVb168 || n < gpx->gnss_nSVstatus) {
|
||||
if (gpx->gnss_sv[n].id168 < 33) { // 01..32 (GPS ?)
|
||||
ui8_t prnGPS = gpx->gnss_sv[n].id168;
|
||||
if (n == 0 && gpx->gnss_sv[n].id168 < 33) fprintf(stdout, " GPS: ");
|
||||
//fprintf(stdout, " GPS PRN%02d: %X\n", prnGPS, gpx->gnss_sv[n].status);
|
||||
//fprintf(stdout, " GPS PRN%02d", prnGPS);
|
||||
fprintf(stdout, " PRN%02d", prnGPS);
|
||||
}
|
||||
else if (gpx->gnss_sv[n].id168 < 33+36) { // 33..68 -> 01..36 (GALILEO ??)
|
||||
ui8_t prnGAL = gpx->gnss_sv[n].id168 - 32;
|
||||
if (n == 0 || n > 0 && gpx->gnss_sv[n-1].id168 < 33) {
|
||||
if (n > 0) fprintf(stdout, "\n");
|
||||
fprintf(stdout, " GAL: ");
|
||||
}
|
||||
//fprintf(stdout, " GAL E%02d: %X\n", prnGAL, gpx->gnss_sv[n].status);
|
||||
//fprintf(stdout, " GAL E%02d", prnGAL);
|
||||
fprintf(stdout, " E%02d", prnGAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int hex2uint(char *str, int nibs) {
|
||||
int i;
|
||||
|
@ -1859,6 +2023,25 @@ static int prn_gpspos(gpx_t *gpx) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int prn_posdatetime(gpx_t *gpx) {
|
||||
//Gps2Date(gpx);
|
||||
//fprintf(stdout, "%s ", weekday[gpx->wday]);
|
||||
fprintf(stdout, "%04d-%02d-%02d %02d:%02d:%05.2f",
|
||||
gpx->jahr, gpx->monat, gpx->tag, gpx->std, gpx->min, gpx->sek);
|
||||
//if (gpx->option.vbs == 3) fprintf(stdout, " (W %d)", gpx->week);
|
||||
fprintf(stdout, " ");
|
||||
|
||||
fprintf(stdout, " ");
|
||||
fprintf(stdout, " lat: %.5f ", gpx->lat);
|
||||
fprintf(stdout, " lon: %.5f ", gpx->lon);
|
||||
fprintf(stdout, " alt: %.2f ", gpx->alt);
|
||||
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); ///TODO: used/tracked/searched/visible ?
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int prn_sat1(gpx_t *gpx, int ofs) {
|
||||
|
||||
fprintf(stdout, "\n");
|
||||
|
@ -1935,7 +2118,8 @@ static int prn_sat3(gpx_t *gpx, int ofs) {
|
|||
|
||||
static int print_position(gpx_t *gpx, int ec) {
|
||||
int i;
|
||||
int err, err0, err1, err2, err3;
|
||||
int err = 1;
|
||||
int err0 = 1, err1 = 1, err2 = 1, err3 = 1, err13 = 1;
|
||||
//int output, out_mask;
|
||||
int encrypted = 0;
|
||||
int unexp = 0;
|
||||
|
@ -1943,6 +2127,7 @@ static int print_position(gpx_t *gpx, int ec) {
|
|||
int sat = 0;
|
||||
int pos_aux = 0, cnt_aux = 0;
|
||||
int ofs_ptu = 0, pck_ptu = 0;
|
||||
int isGNSS2 = 0;
|
||||
|
||||
//gpx->out = 0;
|
||||
gpx->aux = 0;
|
||||
|
@ -2044,6 +2229,23 @@ static int print_position(gpx_t *gpx, int ec) {
|
|||
if (out) fprintf(stdout, " [%04X] (RS41-SGM) ", pck_SGM_CRYPT);
|
||||
break;
|
||||
|
||||
case pck_960A: // 0x960A
|
||||
// ? 64 bit data integrity and authenticity ?
|
||||
break;
|
||||
|
||||
case pck_8226_POSDATETIME: // 0x8226
|
||||
err13 = get_posdatetime(gpx, pos);
|
||||
if ( !err13 ) {
|
||||
if (out) prn_posdatetime(gpx);
|
||||
}
|
||||
break;
|
||||
|
||||
case pck_8329_SATS: // 0x8329
|
||||
err2 = get_gnssSVs(gpx, pos);
|
||||
isGNSS2 = 1;
|
||||
////if ( !err2 ) { if (sat) prn_gnss_sat2(gpx); }
|
||||
break;
|
||||
|
||||
default:
|
||||
if (blk == 0x7E) {
|
||||
if (pos_aux == 0) pos_aux = pos; // pos == pos_AUX ?
|
||||
|
@ -2083,13 +2285,16 @@ static int print_position(gpx_t *gpx, int ec) {
|
|||
gpx->crc = 0;
|
||||
frm_end = FRAME_LEN-2;
|
||||
|
||||
if ( isGNSS2 ) {
|
||||
if (sat && !err2) prn_gnss_sat2(gpx);
|
||||
}
|
||||
|
||||
if (out || sat) fprintf(stdout, "\n");
|
||||
|
||||
|
||||
if (gpx->option.jsn) {
|
||||
// Print out telemetry data as JSON
|
||||
if ((!err && !err1 && !err3) || (!err && encrypted)) { // frame-nb/id && gps-time && gps-position (crc-)ok; 3 CRCs, RS not needed
|
||||
if ( !err && ((!err1 && !err3) || !err13 || 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)
|
||||
char *ver_jsn = NULL;
|
||||
fprintf(stdout, "{ \"type\": \"%s\"", "RS41");
|
||||
|
@ -2169,8 +2374,8 @@ static int print_position(gpx_t *gpx, int ec) {
|
|||
fprintf(stdout, ", \"tx_frequency\": %d", gpx->freq );
|
||||
}
|
||||
|
||||
// Reference time/position
|
||||
fprintf(stdout, ", \"ref_datetime\": \"%s\"", "GPS" ); // {"GPS", "UTC"} GPS-UTC=leap_sec
|
||||
// Reference time/position (fw 0x50dd: datetime UTC)
|
||||
fprintf(stdout, ", \"ref_datetime\": \"%s\"", gpx->isUTC ? "UTC" : "GPS" ); // {"GPS", "UTC"} GPS-UTC=leap_sec
|
||||
fprintf(stdout, ", \"ref_position\": \"%s\"", "GPS" ); // {"GPS", "MSL"} GPS=ellipsoid , MSL=geoid
|
||||
|
||||
#ifdef VER_JSN_STR
|
||||
|
@ -2204,6 +2409,7 @@ static int print_position(gpx_t *gpx, int ec) {
|
|||
|
||||
pck = (gpx->frame[pos_PTU]<<8) | gpx->frame[pos_PTU+1];
|
||||
ofs = 0;
|
||||
///TODO: fw 0x50dd
|
||||
|
||||
if (pck < 0x8000) {
|
||||
//err0 = get_PTU(gpx, 0, pck, 0);
|
||||
|
|
Ładowanie…
Reference in New Issue