From 95a3598dc40389863f1f8cba8383dc24ce5beadd Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sat, 4 Jan 2025 23:47:29 +0100 Subject: [PATCH 01/19] spacer: Integrate with newer sky library --- apps/spacer/spacer.app.js | 152 ++++++++++++++++++++++++++++++-------- 1 file changed, 121 insertions(+), 31 deletions(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index 13812b2a59..0015c1c767 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -124,13 +124,14 @@ let ui = { let fix = {}; /* Global for sky library */ -/* sky library v0.1.0 */ +/* sky library v0.2.2 */ let sky = { sats: [], snum: 0, sats_used: 0, sky_start: -1, this_usable: 0, + debug: 0, drawGrid: function() { g.setColor(0,0,0); @@ -140,7 +141,8 @@ let sky = { ui.radCircle(1.0); }, - snrLim: 28, + /* 18.. don't get reliable fix in 40s */ + snrLim: 22, drawSat: function(s) { let a = s.azi / 360; let e = ((90 - s.ele) / 90); @@ -172,7 +174,7 @@ let sky = { if (fix && fix.fix && fix.lat) { g.setColor(0, 0, 0) - .setFontAlign(-1, 1); + .setFontAlign(-1, 1); g.drawString(fix.satellites + "/" + fix.hdop, 5, ui.y2); } this.decorate(); @@ -197,13 +199,11 @@ let sky = { msg: {}, tof: function(v) { let i = (1*v); return i.toFixed(0); }, fmtSys: function(sys) { - if (sys && sys.sent !== undefined && sys.d23 !== undefined) - return sys.sent + "." + sys.d23 + "D "+ this.tof(sys.pdop) + " " + this.tof(sys.vdop) + "\n"; - else - return "(no data)\n"; + return sys.sent + "." + sys.d23 + "D "+ this.tof(sys.pdop) + " " + this.tof(sys.vdop) + "\n"; }, display: function() { - if (ui.display != 1) + /* unused on skyspy */ + if (ui.display == 1) return; let m = this.old_msg; let msg = "" + this.tof(m.time) + "\n" + @@ -218,37 +218,122 @@ let sky = { .setFontAlign(-1, -1) .drawString(msg, 0, 0); }, + snrSort: function() { + return this.sats.slice(0, this.snum).sort((a, b) => b.snr - a.snr); + }, + getSatSNR: function(n) { /* Get n-th strongest sat */ + if (n <= 0 || n > this.sats.length) + return -1; + + // Sort the satellites by snr in descending order + let sortedSats = this.snrSort(); + + // Return the SNR of the n-th strongest satellite + return sortedSats[n - 1].snr; + }, + qualest: function() { + // Sort the satellites by snr in descending order + let sortedSats = this.snrSort(); + if (sortedSats[4] && sortedSats[4].snr) { + return "" + sortedSats[4].snr + "dB"; + } + for (i=4; i>=0; i--) { + if (sortedSats[i] && sortedSats[i].snr) + return "S" + (i+1); + } + return "nil"; + }, + satVisibility: [], + trackSatelliteVisibility: function() { + const threshold = this.snrLim; // SNR threshold + const now = getTime(); + let newVisibility = []; + //this.satVisibility = []; + for (let i = 0; i < this.snum; i++) { + let sat = this.sats[i]; + let existingSat = this.satVisibility[sat.id]; + if (sat.snr >= threshold) { + if (!existingSat) { + // New satellite starts visibility + newVisibility[sat.id] = { start: now, visible: true }; + } else + newVisibility[sat.id] = this.satVisibility[sat.id]; + } + } + this.satVisibility = newVisibility; + }, + getnthLowestStartTimeSat: function(n) { + // Collect all satellites from visibility + let satellites = Object.values(this.satVisibility); + + // Ensure we have at least 5 satellites + if (satellites.length < n) + return -1; + + // Sort satellites by start time in ascending order + satellites.sort((a, b) => a.start - b.start); + + // Return the satellite with the 5th lowest start time + return satellites[n-1]; // 0-based index, so 5th is index 4 + }, + goodest: function () { + let s = this.getnthLowestStartTimeSat(5); + if (s==-1) + return "none"; + let t = getTime() - s.start; + return "" + t; + }, + onMessageEnd: function() { /* quality.updateGps(); /* FIXME -- for skyspy */}, + messageEnd: function() { + this.old_msg = this.msg; + this.msg = {}; + this.msg.gp = {}; + this.msg.bd = {}; + this.msg.gl = {}; + this.drawSats(this.sats); + let r = this.qualest(); + let r1 = this.goodest(); + print(r, r1, this.old_msg.hdop, this.old_msg.quality); + if (ui.display == 4) + ui.drawMsg(r + "\n" + r1 + "\n" + this.old_msg.hdop + "-" + this.old_msg.quality + "d\n" + (getTime() - this.sky_start)); + this.trackSatelliteVisibility(); + //print(this.sats); + if (this.sats_used < 5) + this.sky_start = getTime(); + this.snum = 0; + this.sats = []; + this.sats_used = 0; + this.onMessageEnd(); + }, parseRaw: function(msg, lost) { if (lost) print("## data lost"); let s = msg.split(","); + // print(getTime(), s[0]); + //return; let cmd = s[0].slice(3); //print("cmd", cmd); + if (cmd === "TXT") { + this.messageEnd(); + return; + } if (cmd === "GGA") { - this.old_msg = this.msg; - this.msg = {}; this.msg.time = s[1]; this.msg.quality = s[6]; this.msg.in_view = s[7]; this.msg.hdop = s[8]; - this.msg.gp = {}; - this.msg.bd = {}; - this.msg.gl = {}; - print("-----------------------------------------------"); - print("GGA Time", s[1], "fix quality", s[4], "sats in view ", s[5]); - this.drawSats(this.sats); - if (this.sats_used < 5) - this.sky_start = getTime(); - this.snum = 0; - this.sats = []; - this.sats_used = 0; + + if (this.debug > 0) { + print("-----------------------------------------------"); + print("GGA Time", s[1], "fix quality", s[4], "sats in view ", s[5]); + } return; } if (cmd === "GLL") return; /* Position lat/lon */ if (cmd === "GSA") { /* - $GNGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5,4*04 + $GNGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5,4*04 0 1 2 15 16 17 18 - */ + */ /* Satelites used, fix type! INTERESTING */ let sys = s[18]; let add = {}; @@ -256,29 +341,34 @@ let sky = { add.pdop = s[15]; add.hdop = s[16]; add.vdop = s[17]; + sys = sys[0]; /* FIXME -- should really add to the sentence */ if (sys == 1) { this.msg.gp = add; } else if (sys == 2) { this.msg.gl = add; } else if (sys == 4) { this.msg.bd = add; } - else print("GSA Unknown system\n"); - - print(msg); + else { + print("GSA Unknown system -- ", sys, "\n"); + print(msg); + } return; } if (s[0] === "$GPGSV") { - print("Have gps sentences", s[1], "/", s[2]); + if (this.debug > 0) + print("Have gps sentences", s[1], "/", s[2]); this.parseSats(s); this.msg.gp.sent = ""+s[2]; return; } if (s[0] === "$BDGSV") { - print("Have baidu sentences", s[1], "/", s[2]); + if (this.debug > 0) + print("Have baidu sentences", s[1], "/", s[2]); this.parseSats(s); this.msg.bd.sent = ""+s[2]; return; } if (s[0] === "$GLGSV") { - print("Have glonass sentences", s[1], "/", s[2]); + if (this.debug > 0) + print("Have glonass sentences", s[1], "/", s[2]); this.parseSats(s); this.msg.gl.sent = ""+s[2]; return; @@ -304,7 +394,7 @@ let sky = { this.sys += 1; if (this.sys == 4) this.sys = 0; - let val = 7; + val = 7; if (this.sys) val = 1 << (this.sys - 1); this.casic_cmd("$PCAS04,"+val); @@ -323,7 +413,7 @@ function start() { // CASIC_CMD("$PCAS06,0"); /* Query product information */ setTimeout(() => sky.casic_cmd("$PCAS04,7"), 1000); /* Enable gps + beidou + glonass */ -setTimeout(() => sky.casic_cmd("$PCAS03,1,1,1,1,1,1,1,1"), 1000); /* Enable gps + beidou + glonass */ +setTimeout(() => sky.casic_cmd("$PCAS03,1,1,1,1,1,1,1,1"), 1500); /* Enable all messages */ //setTimeout(() => sky.casic_cmd("$PCAS10,2"), 1200); /* 2: cold start, 1 warm start, 0: hot start */ From f693bbf80ca4df207323bcc29daf90184ec85d78 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sun, 5 Jan 2025 18:48:51 +0100 Subject: [PATCH 02/19] spacer: Make it easier to split modules, got it back to working order. --- apps/spacer/spacer.app.js | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index 0015c1c767..817b61ffc0 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -162,8 +162,6 @@ let sky = { // https://in-the-sky.org//satmap_radar.php?year=2023&month=10&day=24&skin=1 decorate: function() {}, drawSats: function(sats) { - if (ui.display != 0) - return; g.reset() .setColor(1, 1, 1) .fillRect(0, ui.wi, ui.w, ui.y2) @@ -201,10 +199,7 @@ let sky = { fmtSys: function(sys) { return sys.sent + "." + sys.d23 + "D "+ this.tof(sys.pdop) + " " + this.tof(sys.vdop) + "\n"; }, - display: function() { - /* unused on skyspy */ - if (ui.display == 1) - return; + drawRace: function() { let m = this.old_msg; let msg = "" + this.tof(m.time) + "\n" + "q" + m.quality + " " + m.in_view + " " + m.hdop + "\n" + @@ -283,19 +278,31 @@ let sky = { let t = getTime() - s.start; return "" + t; }, - onMessageEnd: function() { /* quality.updateGps(); /* FIXME -- for skyspy */}, + drawEstimates: function() { + let r = this.qualest(); + let r1 = this.goodest(); + print(r, r1, this.old_msg.hdop, this.old_msg.quality); + /* FIXME: -- for skyspy + if (ui.display == 4) + ui.drawMsg(r + "\n" + r1 + "\n" + this.old_msg.hdop + "-" + this.old_msg.quality + "d\n" + (getTime() - this.sky_start)); + */ + }, + onMessageEnd: function() { + /* quality.updateGps(); /* FIXME -- for skyspy */ + if (ui.display == 0) + this.drawSats(this.sats); + if (ui.display == 1) + this.drawRace(); + if (ui.display == 4) + this.drawEstimates(); + }, messageEnd: function() { this.old_msg = this.msg; this.msg = {}; this.msg.gp = {}; this.msg.bd = {}; this.msg.gl = {}; - this.drawSats(this.sats); - let r = this.qualest(); - let r1 = this.goodest(); - print(r, r1, this.old_msg.hdop, this.old_msg.quality); - if (ui.display == 4) - ui.drawMsg(r + "\n" + r1 + "\n" + this.old_msg.hdop + "-" + this.old_msg.quality + "d\n" + (getTime() - this.sky_start)); + this.onMessageEnd(); this.trackSatelliteVisibility(); //print(this.sats); if (this.sats_used < 5) @@ -303,7 +310,6 @@ let sky = { this.snum = 0; this.sats = []; this.sats_used = 0; - this.onMessageEnd(); }, parseRaw: function(msg, lost) { if (lost) print("## data lost"); @@ -312,7 +318,7 @@ let sky = { //return; let cmd = s[0].slice(3); //print("cmd", cmd); - if (cmd === "TXT") { + if (cmd === "TXT") { // FIXME: we want to end on some more common message */ this.messageEnd(); return; } @@ -408,7 +414,6 @@ function start() { setTimeout(function() { Bangle.removeAllListeners('GPS-raw'); }, 1000000); - setInterval(function() { sky.display(); }, 1000); } // CASIC_CMD("$PCAS06,0"); /* Query product information */ From 35a02cd44322c34b74c704324a873c43cbe2b35a Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sun, 5 Jan 2025 18:52:30 +0100 Subject: [PATCH 03/19] spacer: Cleanups. --- apps/spacer/spacer.app.js | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index 817b61ffc0..acfd06a871 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -1,20 +1,6 @@ /* Space race */ /* - -Performance Assessment of GNSS Signals in -terms of Time to First Fix for -Cold, Warm and Hot Start -Matteo Paonni, Marco Anghileri, Stefan Wallner, José-Ángel Ávila-Rodríguez, Bernd Eissfeller -Institute of Geodesy and Navigation, University FAF Munich, Germany - -=> 22 to 26 dB -- long time / no fix / ... -=> 26db + -- basically strength no longer matters - -apps/assistedgps/custom.html - -https://github.com/espruino/EspruinoDocs/blob/master/info/Bangle.js2%20Technical.md#gps - gsa mi rika 2d/3d fix, a taky pdop/vdop/hdop CFG-NAVX z CASIC_en -- umoznuje nastavit chodec / auto / letadlo @@ -279,13 +265,19 @@ let sky = { return "" + t; }, drawEstimates: function() { + /* + Performance Assessment of GNSS Signals in terms of Time to + First Fix for Cold, Warm and Hot Start Matteo Paonni, Marco Anghileri, + Stefan Wallner, José-Ángel Ávila-Rodríguez, Bernd Eissfeller Institute + of Geodesy and Navigation, University FAF Munich, Germany + + => 22 to 26 dB -- long time / no fix / ... + => 26db + -- basically strength no longer matters + */ let r = this.qualest(); let r1 = this.goodest(); print(r, r1, this.old_msg.hdop, this.old_msg.quality); - /* FIXME: -- for skyspy - if (ui.display == 4) - ui.drawMsg(r + "\n" + r1 + "\n" + this.old_msg.hdop + "-" + this.old_msg.quality + "d\n" + (getTime() - this.sky_start)); - */ + ui.drawMsg(r + "\n" + r1 + "\n" + this.old_msg.hdop + "-" + this.old_msg.quality + "d\n" + (getTime() - this.sky_start)); }, onMessageEnd: function() { /* quality.updateGps(); /* FIXME -- for skyspy */ From 80065fac88e8f2e8a4fa9076054ed4cf7674aa22 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sun, 5 Jan 2025 18:53:17 +0100 Subject: [PATCH 04/19] spacer: Fix whitespace. --- apps/spacer/spacer.app.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index acfd06a871..449a3ca7f4 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -1,6 +1,6 @@ /* Space race */ -/* +/* gsa mi rika 2d/3d fix, a taky pdop/vdop/hdop CFG-NAVX z CASIC_en -- umoznuje nastavit chodec / auto / letadlo @@ -54,12 +54,12 @@ let ui = { touchHandler: function(d) { let x = Math.floor(d.x); let y = Math.floor(d.y); - + if (d.b != 1 || this.last_b != 0) { this.last_b = d.b; return; } - + print("touch", x, y, this.h, this.w); if ((x this.sats.length) return -1; - + // Sort the satellites by snr in descending order let sortedSats = this.snrSort(); @@ -237,7 +237,7 @@ let sky = { if (!existingSat) { // New satellite starts visibility newVisibility[sat.id] = { start: now, visible: true }; - } else + } else newVisibility[sat.id] = this.satVisibility[sat.id]; } } @@ -265,7 +265,7 @@ let sky = { return "" + t; }, drawEstimates: function() { - /* + /* Performance Assessment of GNSS Signals in terms of Time to First Fix for Cold, Warm and Hot Start Matteo Paonni, Marco Anghileri, Stefan Wallner, José-Ángel Ávila-Rodríguez, Bernd Eissfeller Institute @@ -330,7 +330,7 @@ let sky = { if (cmd === "GSA") { /* $GNGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5,4*04 - 0 1 2 15 16 17 18 + 0 1 2 15 16 17 18 */ /* Satelites used, fix type! INTERESTING */ let sys = s[18]; @@ -376,7 +376,7 @@ let sky = { if (cmd === "ZDA") return; /* Time + timezone */ if (cmd === "TXT") { this.msg.finished = 1; - return; /* Misc text? antena open */ + return; /* Misc text? antena open */ } print(msg); From 6b42dbe1a6cc472ce8b41410b416e21ea38998b9 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sun, 5 Jan 2025 18:57:05 +0100 Subject: [PATCH 05/19] spacer: More cleanups. --- apps/spacer/spacer.app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index 449a3ca7f4..60e11d26ab 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -402,7 +402,7 @@ let sky = { function start() { Bangle.setGPSPower(1); - Bangle.on('GPS-raw', function(a, b) { sky.parseRaw(a, b); }); + Bangle.on('GPS-raw', (a, b) => sky.parseRaw(a, b)); setTimeout(function() { Bangle.removeAllListeners('GPS-raw'); }, 1000000); From 6965a2acfa3fca8da4a01673b3038f9bfc27ecc7 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sun, 5 Jan 2025 19:01:17 +0100 Subject: [PATCH 06/19] spacer: better split into modules --- apps/spacer/spacer.app.js | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index 60e11d26ab..631eb25db5 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -279,15 +279,7 @@ let sky = { print(r, r1, this.old_msg.hdop, this.old_msg.quality); ui.drawMsg(r + "\n" + r1 + "\n" + this.old_msg.hdop + "-" + this.old_msg.quality + "d\n" + (getTime() - this.sky_start)); }, - onMessageEnd: function() { - /* quality.updateGps(); /* FIXME -- for skyspy */ - if (ui.display == 0) - this.drawSats(this.sats); - if (ui.display == 1) - this.drawRace(); - if (ui.display == 4) - this.drawEstimates(); - }, + onMessageEnd: function() {}, messageEnd: function() { this.old_msg = this.msg; this.msg = {}; @@ -408,6 +400,17 @@ function start() { }, 1000000); } +function onMessage() { + /* quality.updateGps(); /* FIXME -- for skyspy + if (ui.display == 4) + sky.drawEstimates(); + */ + if (ui.display == 0) + sky.drawSats(sky.sats); + if (ui.display == 1) + sky.drawRace(); +} + // CASIC_CMD("$PCAS06,0"); /* Query product information */ setTimeout(() => sky.casic_cmd("$PCAS04,7"), 1000); /* Enable gps + beidou + glonass */ setTimeout(() => sky.casic_cmd("$PCAS03,1,1,1,1,1,1,1,1"), 1500); /* Enable all messages */ @@ -417,4 +420,5 @@ setTimeout(() => sky.casic_cmd("$PCAS03,1,1,1,1,1,1,1,1"), 1500); /* Enable all ui.init(); ui.topLeft = () => sky.selectSpace(); Bangle.on("drag", (b) => ui.touchHandler(b)); +sky.onMessageEnd = onMessage; start(); From 64c11e13099123c6121c3c8a12ebe9b93a8267fe Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sun, 5 Jan 2025 20:09:06 +0100 Subject: [PATCH 07/19] spacer: Move satelite set related functions to separate struct. --- apps/spacer/spacer.app.js | 183 ++++++++++++++++++++------------------ 1 file changed, 94 insertions(+), 89 deletions(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index 631eb25db5..9210eeea4d 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -108,62 +108,16 @@ let ui = { }, }; +/* sky library v0.2.3 + needs ui */ + let fix = {}; /* Global for sky library */ -/* sky library v0.2.2 */ -let sky = { +let skys = { sats: [], snum: 0, sats_used: 0, - sky_start: -1, - this_usable: 0, - debug: 0, - - drawGrid: function() { - g.setColor(0,0,0); - ui.radLine(0, 1, 0.5, 1); - ui.radLine(0.25, 1, 0.75, 1); - ui.radCircle(0.5); - ui.radCircle(1.0); - }, - - /* 18.. don't get reliable fix in 40s */ - snrLim: 22, - drawSat: function(s) { - let a = s.azi / 360; - let e = ((90 - s.ele) / 90); - let x = ui.radX(a, e); - let y = ui.radY(a, e); - - if (s.snr == 0) - g.setColor(1, 0.25, 0.25); - else if (s.snr < this.snrLim) - g.setColor(0.25, 0.5, 0.25); - else - g.setColor(0, 0, 0); - g.drawString(s.id, x, y); - }, - - // Should correspond to view from below. - // https://in-the-sky.org//satmap_radar.php?year=2023&month=10&day=24&skin=1 - decorate: function() {}, - drawSats: function(sats) { - g.reset() - .setColor(1, 1, 1) - .fillRect(0, ui.wi, ui.w, ui.y2) - .setFont("Vector", 20) - .setFontAlign(0, 0); - this.drawGrid(); - sats.forEach(s => this.drawSat(s)); - - if (fix && fix.fix && fix.lat) { - g.setColor(0, 0, 0) - .setFontAlign(-1, 1); - g.drawString(fix.satellites + "/" + fix.hdop, 5, ui.y2); - } - this.decorate(); - }, - + parseSats: function(s) { let view = 1 * s[3]; let k = Math.min(4, view - this.snum); @@ -179,26 +133,6 @@ let sky = { } }, - old_msg: {}, - msg: {}, - tof: function(v) { let i = (1*v); return i.toFixed(0); }, - fmtSys: function(sys) { - return sys.sent + "." + sys.d23 + "D "+ this.tof(sys.pdop) + " " + this.tof(sys.vdop) + "\n"; - }, - drawRace: function() { - let m = this.old_msg; - let msg = "" + this.tof(m.time) + "\n" + - "q" + m.quality + " " + m.in_view + " " + m.hdop + "\n" + - "gp"+ this.fmtSys(m.gp) + - "bd" + this.fmtSys(m.bd) + - "gl" + this.fmtSys(m.gl); - if (this.msg.finished != 1) - msg += "!"; - g.reset().clear().setFont("Vector", 30) - .setColor(0, 0, 0) - .setFontAlign(-1, -1) - .drawString(msg, 0, 0); - }, snrSort: function() { return this.sats.slice(0, this.snum).sort((a, b) => b.snr - a.snr); }, @@ -264,6 +198,79 @@ let sky = { let t = getTime() - s.start; return "" + t; }, +}; + +let sky = { + sky_start: -1, + this_usable: 0, + debug: 0, + all: skys, /* Sattelites from all systems */ + + drawGrid: function() { + g.setColor(0,0,0); + ui.radLine(0, 1, 0.5, 1); + ui.radLine(0.25, 1, 0.75, 1); + ui.radCircle(0.5); + ui.radCircle(1.0); + }, + + /* 18.. don't get reliable fix in 40s */ + snrLim: 22, + drawSat: function(s) { + let a = s.azi / 360; + let e = ((90 - s.ele) / 90); + let x = ui.radX(a, e); + let y = ui.radY(a, e); + + if (s.snr == 0) + g.setColor(1, 0.25, 0.25); + else if (s.snr < this.snrLim) + g.setColor(0.25, 0.5, 0.25); + else + g.setColor(0, 0, 0); + g.drawString(s.id, x, y); + }, + + // Should correspond to view from below. + // https://in-the-sky.org//satmap_radar.php?year=2023&month=10&day=24&skin=1 + decorate: function() {}, + drawSats: function(sats) { + g.reset() + .setColor(1, 1, 1) + .fillRect(0, ui.wi, ui.w, ui.y2) + .setFont("Vector", 20) + .setFontAlign(0, 0); + this.drawGrid(); + sats.forEach(s => this.drawSat(s)); + + if (fix && fix.fix && fix.lat) { + g.setColor(0, 0, 0) + .setFontAlign(-1, 1); + g.drawString(fix.satellites + "/" + fix.hdop, 5, ui.y2); + } + this.decorate(); + }, + + old_msg: {}, + msg: {}, + tof: function(v) { let i = (1*v); return i.toFixed(0); }, + fmtSys: function(sys) { + return sys.sent + "." + sys.d23 + "D "+ this.tof(sys.pdop) + " " + this.tof(sys.vdop) + "\n"; + }, + drawRace: function() { + let m = this.old_msg; + let msg = "gmt " + this.tof(m.time) + "\n" + + "q" + m.quality + " S" + m.in_view + " h" + (1*m.hdop).toFixed(1) + "m\n" + + "gp"+ this.fmtSys(m.gp) + + "bd" + this.fmtSys(m.bd) + + "gl" + this.fmtSys(m.gl); + if (this.msg.finished != 1) + msg += "!"; + g.reset().clear().setFont("Vector", 30) + .setColor(0, 0, 0) + .setFontAlign(-1, -1) + .drawString(msg, 0, 0); + }, drawEstimates: function() { /* Performance Assessment of GNSS Signals in terms of Time to @@ -274,8 +281,8 @@ let sky = { => 22 to 26 dB -- long time / no fix / ... => 26db + -- basically strength no longer matters */ - let r = this.qualest(); - let r1 = this.goodest(); + let r = this.all.qualest(); + let r1 = this.all.goodest(); print(r, r1, this.old_msg.hdop, this.old_msg.quality); ui.drawMsg(r + "\n" + r1 + "\n" + this.old_msg.hdop + "-" + this.old_msg.quality + "d\n" + (getTime() - this.sky_start)); }, @@ -287,22 +294,24 @@ let sky = { this.msg.bd = {}; this.msg.gl = {}; this.onMessageEnd(); - this.trackSatelliteVisibility(); + this.all.trackSatelliteVisibility(); //print(this.sats); - if (this.sats_used < 5) + if (this.all.sats_used < 5) this.sky_start = getTime(); - this.snum = 0; - this.sats = []; - this.sats_used = 0; + this.all.snum = 0; + this.all.sats = []; + this.all.sats_used = 0; }, parseRaw: function(msg, lost) { + //print(msg); if (lost) print("## data lost"); let s = msg.split(","); // print(getTime(), s[0]); //return; let cmd = s[0].slice(3); //print("cmd", cmd); - if (cmd === "TXT") { // FIXME: we want to end on some more common message */ + if (cmd === "RMC") { + /* Repeat of position/speed/course */ this.messageEnd(); return; } @@ -345,32 +354,28 @@ let sky = { if (s[0] === "$GPGSV") { if (this.debug > 0) print("Have gps sentences", s[1], "/", s[2]); - this.parseSats(s); + this.all.parseSats(s); this.msg.gp.sent = ""+s[2]; return; } if (s[0] === "$BDGSV") { if (this.debug > 0) print("Have baidu sentences", s[1], "/", s[2]); - this.parseSats(s); + this.all.parseSats(s); this.msg.bd.sent = ""+s[2]; return; } if (s[0] === "$GLGSV") { if (this.debug > 0) print("Have glonass sentences", s[1], "/", s[2]); - this.parseSats(s); + this.all.parseSats(s); this.msg.gl.sent = ""+s[2]; return; } - if (cmd === "RMC") return; /* Repeat of position/speed/course */ + if (cmd === "VTG") return; /* Speeds in knots/kph */ if (cmd === "ZDA") return; /* Time + timezone */ - if (cmd === "TXT") { - this.msg.finished = 1; - return; /* Misc text? antena open */ - } - + if (cmd === "TXT") return; /* Misc text? antena open */ print(msg); }, casic_cmd: function (cmd) { @@ -406,7 +411,7 @@ function onMessage() { sky.drawEstimates(); */ if (ui.display == 0) - sky.drawSats(sky.sats); + sky.drawSats(sky.all.sats); if (ui.display == 1) sky.drawRace(); } From d9d6e23d93a47644a0a6865f95d52713090211f2 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sun, 5 Jan 2025 20:17:41 +0100 Subject: [PATCH 08/19] spacer: More refactoring. --- apps/spacer/spacer.app.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index 9210eeea4d..cc9c019a86 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -117,7 +117,12 @@ let skys = { sats: [], snum: 0, sats_used: 0, - + + reset: function() { + this.snum = 0; + this.sats = []; + this.sats_used = 0; + }, parseSats: function(s) { let view = 1 * s[3]; let k = Math.min(4, view - this.snum); @@ -298,9 +303,7 @@ let sky = { //print(this.sats); if (this.all.sats_used < 5) this.sky_start = getTime(); - this.all.snum = 0; - this.all.sats = []; - this.all.sats_used = 0; + this.all.reset(); }, parseRaw: function(msg, lost) { //print(msg); From 641b43af60215766dc16dec53eb13f686e0dc8e8 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sun, 5 Jan 2025 20:26:58 +0100 Subject: [PATCH 09/19] spacer: prepare for printing vdop/pdop --- apps/spacer/spacer.app.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index cc9c019a86..43681264f3 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -258,14 +258,17 @@ let sky = { old_msg: {}, msg: {}, - tof: function(v) { let i = (1*v); return i.toFixed(0); }, + tof: function(v, n) { let i = (1*v); return i.toFixed(n); }, + tof0: function(v) { return this.tof(v, 0); }, + tof1: function(v) { return this.tof(v, 1); }, fmtSys: function(sys) { - return sys.sent + "." + sys.d23 + "D "+ this.tof(sys.pdop) + " " + this.tof(sys.vdop) + "\n"; + return sys.sent + "." + sys.d23 + "D "+ this.tof(sys.pdop) + " " + this.tof0(sys.vdop) + "\n"; }, drawRace: function() { let m = this.old_msg; - let msg = "gmt " + this.tof(m.time) + "\n" + - "q" + m.quality + " S" + m.in_view + " h" + (1*m.hdop).toFixed(1) + "m\n" + + let msg = "gmt" + this.tof0(m.time) + "\n" + + "q" + m.quality + " S" + m.in_view + " h" + this.tof0(m.hdop) + "m\n" + +/* "v" + this.tof0(m.vdop) + "m " + "p" + this.tof0(m.pdop) + "m\n" + */ "gp"+ this.fmtSys(m.gp) + "bd" + this.fmtSys(m.bd) + "gl" + this.fmtSys(m.gl); From ebb4cd7c27853d27a00fdf913a349db1b5d27b61 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Mon, 6 Jan 2025 14:22:32 +0100 Subject: [PATCH 10/19] spacer: refactor --- apps/spacer/spacer.app.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index 43681264f3..ede98eb6be 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -117,6 +117,7 @@ let skys = { sats: [], snum: 0, sats_used: 0, + sky_start: -1, reset: function() { this.snum = 0; @@ -203,10 +204,14 @@ let skys = { let t = getTime() - s.start; return "" + t; }, + onEnd: function () { + if (this.sats_used < 5) + this.sky_start = getTime(); + this.reset(); + }, }; let sky = { - sky_start: -1, this_usable: 0, debug: 0, all: skys, /* Sattelites from all systems */ @@ -292,7 +297,7 @@ let sky = { let r = this.all.qualest(); let r1 = this.all.goodest(); print(r, r1, this.old_msg.hdop, this.old_msg.quality); - ui.drawMsg(r + "\n" + r1 + "\n" + this.old_msg.hdop + "-" + this.old_msg.quality + "d\n" + (getTime() - this.sky_start)); + ui.drawMsg(r + "\n" + r1 + "\n" + this.old_msg.hdop + "-" + this.old_msg.quality + "d\n" + (getTime() - this.all.sky_start)); }, onMessageEnd: function() {}, messageEnd: function() { @@ -304,9 +309,7 @@ let sky = { this.onMessageEnd(); this.all.trackSatelliteVisibility(); //print(this.sats); - if (this.all.sats_used < 5) - this.sky_start = getTime(); - this.all.reset(); + this.all.onEnd(); }, parseRaw: function(msg, lost) { //print(msg); From ee90dcdfdb79399fad18a1e44a26c938f0629963 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Mon, 6 Jan 2025 14:28:04 +0100 Subject: [PATCH 11/19] spacer: display fix summary --- apps/spacer/spacer.app.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index ede98eb6be..1b31afb645 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -200,9 +200,15 @@ let skys = { goodest: function () { let s = this.getnthLowestStartTimeSat(5); if (s==-1) - return "none"; + return ""; let t = getTime() - s.start; - return "" + t; + return "" + t + "s"; + }, + summary: function () { + let s = this.goodest(); + if (s != "") + return s; + return this.qualest(); }, onEnd: function () { if (this.sats_used < 5) @@ -273,7 +279,8 @@ let sky = { let m = this.old_msg; let msg = "gmt" + this.tof0(m.time) + "\n" + "q" + m.quality + " S" + m.in_view + " h" + this.tof0(m.hdop) + "m\n" + -/* "v" + this.tof0(m.vdop) + "m " + "p" + this.tof0(m.pdop) + "m\n" + */ + /* "v" + this.tof0(m.vdop) + "m " + "p" + this.tof0(m.pdop) + "m\n" + */ + this.all.summary() + "\n" + "gp"+ this.fmtSys(m.gp) + "bd" + this.fmtSys(m.bd) + "gl" + this.fmtSys(m.gl); From 6db2d36193a30e6800596e2000969e194024bb3d Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Mon, 6 Jan 2025 17:43:46 +0100 Subject: [PATCH 12/19] spacer: update icon. --- apps/spacer/app-icon.js | 2 +- apps/spacer/app.png | Bin 14889 -> 1976 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/spacer/app-icon.js b/apps/spacer/app-icon.js index 903d14af51..53dbfa31ee 100644 --- a/apps/spacer/app-icon.js +++ b/apps/spacer/app-icon.js @@ -1,2 +1,2 @@ -require("heatshrink").decompress(atob("mEwgIQNgQFEj/gAof+jgECgeAAIIFBgwCBuACBhgCEjAOEAoQ6CmAhCDwItDoEB4AFCsEBFgUEkEDG4XEJYcL8gFCgUP+gxCAoP8DIIFBhfsiEIAoMJAogCBAoYlBiBMBAoUwrA0B////ALECI0QAocgAolgApVADolAHYnAAomAAoqdBAoKVBMoRvCOIQDCRIIFBYwKVBAoKqC4AFBVQVggTRDn0CYgQcBN4LpDV4T7IAooAJA=")) +require("heatshrink").decompress(atob("mEwhHXAH4A/AH4A/AGMAF34v/F34EBAAIvrFwQxnEoIsFGEyNHF9ZgNGrheMF4guJHDAvLEhCdbLyLLdL5ImFfRo6SLpjGOCgw5TdZRhKHwhEPFxjOJCwwOGF6zOJBxpjFAB4TKR6aEJDpgwKd5rzUYBrkVMxwtVF7CYHeBxGRF5LwMR9YvdPiJfjBhYv/F/4v/F/4v/F/4v/F/4v/F/4vfAH4Ad")) diff --git a/apps/spacer/app.png b/apps/spacer/app.png index ce7ac239fd0f72f3a1ab88ccfa91bcd21846caf4..6743d6e59284b3867f46119a9400afa32cecdefa 100644 GIT binary patch literal 1976 zcmd5-c~q0v5>Gxq;bS$C9T9;%8g`J#RyJ8eAZ&u{Vu-RTU;|;5uzVH*NGw{R3I-H# z#ggz?s!$u^Qb9m^(5C@`5+7icB}R4(m45V{_s9F={oi}eotb-Q<~Mido;g!~D1f9S zuPu*4p_F{QJ%bV6y1gM8gmUjqQxJxx2b0`UoFSbL$N{9g`-DKqVnA_aD3t7RA5XWC z9Lhr7aM-xF;?B2QuC<2KD8iNfyteCOEe)$S>1&yH#?`+{T>8BFWl~|wjcNpkgSu}V zju&DMQav^OQ84LVr37N_Xp+;DykEuY!fDh4Xi#^;ziEt=13ra^K}=4D z6sqLgTh*d~%2WH^Vl`#GR1OM<7jRC%6h8@ooVxRiNmQM`0cb?hU!oTZd9}rpm1KjT2F$`xqdV*j&=m}5?-^;tHxOYALHY!lmHySWS4% z+WN8#jJ3Z#NST2cFL&{r<_&LskK9CjiW}2L+)`&k&irv2Cd58o=p?mn{H$`8DM-fH zf6~artas;xh8tJ`;aweZdqHLSAKBexyq38tS!4sT_@W9%iNxDI(L&gTeC7nXS4tL{`#oIcQI0pMDR9UTAqDB<8-XP(&k zw~nm-ZJ0W0`!)aNsZ!1_xVgV?zx@to9mrsh2+J&RT*v6UGY5yNrNw#^J6 zB~1tnB$-+9;Rvnr-N`v!(z09l_39;!#Do(1G9^pP9Ap2ctMN3*L6`GwbROT;qiK#l zR+tA8DTySm`7K485hJwgsEUYB%1$i5I8Iy+v9JOlyXPBcZuv&9r zJ(F43);#5T?w#s4TgM`MDZ@6{hl*J0q7 zcTE0sg2aYc$diY!fa0XE-dZj6*NdKl`93a7-IP><^SXhjbztw#I)b#{eMtpiR+d#) zcq!_ccf)|=B93-@XL7~1>H?uKgWDwAki1DPUXOQuLfm%%{BAelU!*I?%T(Vys&VZW zykztH{nTco4yOt3wit_h+k);`M>ghXET!zxZ?vn2*qSude{=sqsY zPk^%>XV^eS()fiK2U^zLRImMt?rf_3bTfM|5E6g*^@qMn{uXW$9eIKi+)n=~bOUKk zwKeid)lsr7+2X}=dXMj~&@jQx@W|HE3^ceaEe6!N<=Och>9atb*8Ra4P@5TO?l5`IDeQj%^vzV^i*z8F8VV=pJqIi zi@%&MJ>^s7chyFm!sfI2Sl7U0?7C_YkFVr#b-kdZZt3UtG=L6Va*2VW&tB9TDO&ns zDFC-*D@PgI_K~HS`&HLkFH3Fkp7Pc6?8&-wDwkF4mnCd9oJ6bPjBB=sMcIR8o4wCI zCJZ2Pbv`Y1sKbHS8HMrlOXVBNj3?(2`}@lq>HCzCl%UPBBB>86fcN;Z!Tlp6% z9#@RUq?b23F4U70U>>~$}**EcIlv{;Dz~c7*AID8uL3(?XtQ`|TrZ38e7~siq Hr=Ix}GpBEV literal 14889 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

obkzBHHw)%!W~j@Fk!G)!@_9jb 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 oeUItr=y-W~? Date: Tue, 7 Jan 2025 11:44:39 +0100 Subject: [PATCH 13/19] spacer: better docs, compute statistics per-system --- apps/spacer/README.md | 14 +++++++++++- apps/spacer/spacer.app.js | 48 +++++++++++++++++++++++++++++++++++---- 2 files changed, 56 insertions(+), 6 deletions(-) diff --git a/apps/spacer/README.md b/apps/spacer/README.md index 5a8725a966..00d9de4a3b 100644 --- a/apps/spacer/README.md +++ b/apps/spacer/README.md @@ -4,5 +4,17 @@ Compare GPS with Baido and Glonass This turns GNSS receiver into mode with all three systems enabled, and displays debug info from all of them. Click into top left corner to -switch navigation systems. +switch navigation systems. Clicks in bottom half of screen switch info +pages. + +GNSS acquisition has few phases, and this software is assuming you are +not doing a cold start. GNSS fix needs 4 or 5 satellites with +reasonable signal strength, and then holding the same place for 40 or +so seconds. + +nil -- no satellites visible + +S1..S4 -- not enough satellites being decoded (5 needed) + +XXdB -- have enough satellites, but signal is not strong enough diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index 1b31afb645..7d4699a7b2 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -217,10 +217,37 @@ let skys = { }, }; +function deepCopy(obj) { + if (obj === null || typeof obj !== "object") { + return obj; // Return primitive values as-is + } + + if (Array.isArray(obj)) { + return obj.map(deepCopy); // Handle arrays recursively + } + + const copy = {}; + for (const key in obj) { + if (obj.hasOwnProperty(key)) { + copy[key] = deepCopy(obj[key]); // Recursively copy properties + } + } + return copy; +} + let sky = { this_usable: 0, debug: 0, all: skys, /* Sattelites from all systems */ + split: 1, + + init: function () { + if (this.split) { + this.s_gp = deepCopy(skys); + this.s_gl = deepCopy(skys); + this.s_bd = deepCopy(skys); + } + }, drawGrid: function() { g.setColor(0,0,0); @@ -272,8 +299,12 @@ let sky = { tof: function(v, n) { let i = (1*v); return i.toFixed(n); }, tof0: function(v) { return this.tof(v, 0); }, tof1: function(v) { return this.tof(v, 1); }, - fmtSys: function(sys) { - return sys.sent + "." + sys.d23 + "D "+ this.tof(sys.pdop) + " " + this.tof0(sys.vdop) + "\n"; + fmtSys: function(sys, sats) { + let r = sys.sent + " "; + // r+= sys.d23 + "D "; + if (sats) + r += sats.sats_used + "/" + sats.snum; + return r + "\n"; }, drawRace: function() { let m = this.old_msg; @@ -281,9 +312,9 @@ let sky = { "q" + m.quality + " S" + m.in_view + " h" + this.tof0(m.hdop) + "m\n" + /* "v" + this.tof0(m.vdop) + "m " + "p" + this.tof0(m.pdop) + "m\n" + */ this.all.summary() + "\n" + - "gp"+ this.fmtSys(m.gp) + - "bd" + this.fmtSys(m.bd) + - "gl" + this.fmtSys(m.gl); + "gp"+ this.fmtSys(m.gp, this.s_gp) + + "bd" + this.fmtSys(m.bd, this.s_bd) + + "gl" + this.fmtSys(m.gl, this.s_gl); if (this.msg.finished != 1) msg += "!"; g.reset().clear().setFont("Vector", 30) @@ -371,6 +402,8 @@ let sky = { if (this.debug > 0) print("Have gps sentences", s[1], "/", s[2]); this.all.parseSats(s); + if (this.split) + this.s_gp.parseSats(s); this.msg.gp.sent = ""+s[2]; return; } @@ -378,6 +411,8 @@ let sky = { if (this.debug > 0) print("Have baidu sentences", s[1], "/", s[2]); this.all.parseSats(s); + if (this.split) + this.s_bd.parseSats(s); this.msg.bd.sent = ""+s[2]; return; } @@ -385,6 +420,8 @@ let sky = { if (this.debug > 0) print("Have glonass sentences", s[1], "/", s[2]); this.all.parseSats(s); + if (this.split) + this.s_gl.parseSats(s); this.msg.gl.sent = ""+s[2]; return; } @@ -442,4 +479,5 @@ ui.init(); ui.topLeft = () => sky.selectSpace(); Bangle.on("drag", (b) => ui.touchHandler(b)); sky.onMessageEnd = onMessage; +sky.init(); start(); From 9605d0d2bbcb516ffc2f24403165e52b1b10b860 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Tue, 7 Jan 2025 12:34:08 +0100 Subject: [PATCH 14/19] spacer: report details for each system --- apps/spacer/spacer.app.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index 7d4699a7b2..d66defaf6d 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -162,7 +162,7 @@ let skys = { if (sortedSats[i] && sortedSats[i].snr) return "S" + (i+1); } - return "nil"; + return "U" + this.snum; }, satVisibility: [], trackSatelliteVisibility: function() { @@ -303,7 +303,8 @@ let sky = { let r = sys.sent + " "; // r+= sys.d23 + "D "; if (sats) - r += sats.sats_used + "/" + sats.snum; + // r += sats.sats_used + "/" + sats.snum; + r += sats.summary(); return r + "\n"; }, drawRace: function() { From 302e1009d6b41d9f41a426eeb0b9988c1130c55f Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Fri, 10 Jan 2025 11:17:14 +0100 Subject: [PATCH 15/19] spacer: Fix computations on multiple systems --- apps/spacer/spacer.app.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index d66defaf6d..95f2ab4264 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -211,6 +211,7 @@ let skys = { return this.qualest(); }, onEnd: function () { + this.trackSatelliteVisibility(); if (this.sats_used < 5) this.sky_start = getTime(); this.reset(); @@ -346,9 +347,13 @@ let sky = { this.msg.bd = {}; this.msg.gl = {}; this.onMessageEnd(); - this.all.trackSatelliteVisibility(); //print(this.sats); this.all.onEnd(); + if (this.split) { + this.s_gp.onEnd(); + this.s_gl.onEnd(); + this.s_bd.onEnd(); + } }, parseRaw: function(msg, lost) { //print(msg); From f870343b4254af8f2325f2b23d28d0f50d2b59b5 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Fri, 10 Jan 2025 11:22:49 +0100 Subject: [PATCH 16/19] spacer: Display systems with no data as "off" --- apps/spacer/spacer.app.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index 95f2ab4264..2a12d1f501 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -301,6 +301,8 @@ let sky = { tof0: function(v) { return this.tof(v, 0); }, tof1: function(v) { return this.tof(v, 1); }, fmtSys: function(sys, sats) { + if (!sys.sent) + return " off\n"; let r = sys.sent + " "; // r+= sys.d23 + "D "; if (sats) From d2276bee06867d690adc5fe6c5e41f75e231ae1c Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Fri, 10 Jan 2025 20:14:34 +0100 Subject: [PATCH 17/19] spacer: Document current behaviour --- apps/spacer/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/spacer/README.md b/apps/spacer/README.md index 00d9de4a3b..b3fc437ba7 100644 --- a/apps/spacer/README.md +++ b/apps/spacer/README.md @@ -12,9 +12,9 @@ not doing a cold start. GNSS fix needs 4 or 5 satellites with reasonable signal strength, and then holding the same place for 40 or so seconds. -nil -- no satellites visible +Uxx -- satellites are known but not being received S1..S4 -- not enough satellites being decoded (5 needed) -XXdB -- have enough satellites, but signal is not strong enough +XXdB -- this is strength of 5th strongest satellite From d38dec5e4c7d21654552af2909431ee5d845aed8 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Fri, 10 Jan 2025 20:14:47 +0100 Subject: [PATCH 18/19] spacer: version 0.10 --- apps/spacer/ChangeLog | 1 + apps/spacer/metadata.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/spacer/ChangeLog b/apps/spacer/ChangeLog index 263d4078d2..88e8a64fc0 100644 --- a/apps/spacer/ChangeLog +++ b/apps/spacer/ChangeLog @@ -1 +1,2 @@ 0.01: attempt to import +0.10: major updates, display satellites, display per-system satellite info diff --git a/apps/spacer/metadata.json b/apps/spacer/metadata.json index 55598f9535..e114d8dd12 100644 --- a/apps/spacer/metadata.json +++ b/apps/spacer/metadata.json @@ -1,6 +1,6 @@ { "id": "spacer", "name": "Space Race", - "version": "0.01", + "version": "0.10", "description": "Compare GPS with Baido and Glonass", "icon": "app.png", "readme": "README.md", From 473b9734107677d5d6461458ad4ec5f747a916d1 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Fri, 10 Jan 2025 21:21:21 +0100 Subject: [PATCH 19/19] spacer: fix some warnings --- apps/spacer/spacer.app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index 2a12d1f501..99453e79a8 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -158,7 +158,7 @@ let skys = { if (sortedSats[4] && sortedSats[4].snr) { return "" + sortedSats[4].snr + "dB"; } - for (i=4; i>=0; i--) { + for (let i=4; i>=0; i--) { if (sortedSats[i] && sortedSats[i].snr) return "S" + (i+1); } @@ -450,7 +450,7 @@ let sky = { this.sys += 1; if (this.sys == 4) this.sys = 0; - val = 7; + let val = 7; if (this.sys) val = 1 << (this.sys - 1); this.casic_cmd("$PCAS04,"+val);