incorrectly decoded gps coordinates from some packets in syslog #153

Closed
opened 2026-10-05 05:43:16 +02:00 by adam · 8 comments
Owner

Looks like there is a problem with decoding GPS coordinates (and as a result also wrong calculated distance and cropped comment) in some packets -- probably due to unfulfilled condition in gps_utils.cpp line 200.

example recaived packet:
SP9APV-4>APLOX1,SP9APV-4,WIDE1*:!L54-NSLn4# XLora Digi/iGate Nagoya NL550 P=5.47V

in syslog:
CA2RXU_LoRa_iGate_1.3 RX / GPS / SP9APV-4 / APLOX1,SP9APV-4,WIDE1* / - / -100dBm / 12.75dB / 983Hz / 0.06667N / 0.00000E / 5871.6km / igi/iGate Nagoya NL550 P=5.47V

decode_aprs tool from direwolf:

$ echo 'SP9APV-4>APLOX1,SP9APV-4,WIDE1*:!L54-NSLn4# XLora Digi/iGate Nagoya NL550 P=5.47V' | decode_aprs

SP9APV-4>APLOX1,NOCALL-10,WIDE1*:!L54-NSLn4# XLora Digi/iGate Nagoya NL550 P=5.47V
Position, WIDEn-N with path length trapping, LoRa KISS TNC/Tracker
N 50 01.1253, E 019 43.9525
ora Digi/iGate Nagoya NL550 P=5.47V
Looks like there is a problem with decoding GPS coordinates (and as a result also wrong calculated distance and cropped comment) in some packets -- probably due to unfulfilled condition in `gps_utils.cpp` line 200. example recaived packet: `SP9APV-4>APLOX1,SP9APV-4,WIDE1*:!L54-NSLn4# XLora Digi/iGate Nagoya NL550 P=5.47V` in syslog: `CA2RXU_LoRa_iGate_1.3 RX / GPS / SP9APV-4 / APLOX1,SP9APV-4,WIDE1* / - / -100dBm / 12.75dB / 983Hz / 0.06667N / 0.00000E / 5871.6km / igi/iGate Nagoya NL550 P=5.47V` decode_aprs tool from direwolf: ``` $ echo 'SP9APV-4>APLOX1,SP9APV-4,WIDE1*:!L54-NSLn4# XLora Digi/iGate Nagoya NL550 P=5.47V' | decode_aprs SP9APV-4>APLOX1,NOCALL-10,WIDE1*:!L54-NSLn4# XLora Digi/iGate Nagoya NL550 P=5.47V Position, WIDEn-N with path length trapping, LoRa KISS TNC/Tracker N 50 01.1253, E 019 43.9525 ora Digi/iGate Nagoya NL550 P=5.47V ``` <!-- github-sync-id:2729386289 -->
adam closed this issue 2026-10-05 05:43:17 +02:00
Author
Owner

I guess I know how to solve this

Can you flash with vscode the firmware only with a minor modification to test?

I guess I know how to solve this Can you flash with vscode the firmware only with a minor modification to test? <!-- github-comment-id:2531955510 -->
Author
Owner

Sure, just flashed with small modification:

-            if (String(packet[encodedBytePosition]) == "G" || String(packet[encodedBytePosition]) == "Q" || String(packet[encodedBytePosition]) == "[" || String(packet[encodedBytePosition]) == "H") {
+            if (String(packet[encodedBytePosition]) == "G" || String(packet[encodedBytePosition]) == "Q" || String(packet[encodedBytePosition]) == "[" || String(packet[encodedBytePosition]) == "H" || String(packet[encodedBytePosition]) == "X") {

and seems to works ok now for packet: SP9APV-4>APLOX1,SP9SVE-12,WIDE1*:!L54-NSLn4# XLora Digi/iGate Nagoya NL550 P=5.22V

lora32 module with modification as above:

Dec 10 18:38:55 NOCALL-13 CA2RXU_LoRa_iGate_1.3 RX / GPS / SP9APV-4 / APLOX1,SP9SVE-12,WIDE1* / - / -105dBm / -3.75dB / -790Hz / 50.01875N / 19.73254E / 14.3km / Lora Digi/iGate Nagoya NL550 P=5.22V

lora32 module with unmodified firmware:

Dec 10 18:38:55 NOCALL-12 CA2RXU_LoRa_iGate_1.3 RX / GPS / SP9APV-4 / APLOX1,SP9SVE-12,WIDE1* / - / -98dBm / 12.25dB / -274Hz / 0.06667N / 0.00000E / 5871.6km / igi/iGate Nagoya NL550 P=5.22V

or maybe you had some more sophisticated changes in mind? ;)

Sure, just flashed with small modification: ``` - if (String(packet[encodedBytePosition]) == "G" || String(packet[encodedBytePosition]) == "Q" || String(packet[encodedBytePosition]) == "[" || String(packet[encodedBytePosition]) == "H") { + if (String(packet[encodedBytePosition]) == "G" || String(packet[encodedBytePosition]) == "Q" || String(packet[encodedBytePosition]) == "[" || String(packet[encodedBytePosition]) == "H" || String(packet[encodedBytePosition]) == "X") { ``` and seems to works ok now for packet: `SP9APV-4>APLOX1,SP9SVE-12,WIDE1*:!L54-NSLn4# XLora Digi/iGate Nagoya NL550 P=5.22V` lora32 module with modification as above: ``` Dec 10 18:38:55 NOCALL-13 CA2RXU_LoRa_iGate_1.3 RX / GPS / SP9APV-4 / APLOX1,SP9SVE-12,WIDE1* / - / -105dBm / -3.75dB / -790Hz / 50.01875N / 19.73254E / 14.3km / Lora Digi/iGate Nagoya NL550 P=5.22V ``` lora32 module with unmodified firmware: ``` Dec 10 18:38:55 NOCALL-12 CA2RXU_LoRa_iGate_1.3 RX / GPS / SP9APV-4 / APLOX1,SP9SVE-12,WIDE1* / - / -98dBm / 12.25dB / -274Hz / 0.06667N / 0.00000E / 5871.6km / igi/iGate Nagoya NL550 P=5.22V ``` or maybe you had some more sophisticated changes in mind? ;) <!-- github-comment-id:2532432498 -->
Author
Owner

This was what I planned to recomend you to test

So I should add this to main ;)

This was what I planned to recomend you to test So I should add this to main ;) <!-- github-comment-id:2532472411 -->
Author
Owner

Yes, should fit as workaround.

I have reviewed APRS 1.0.1 (29 Aug 2000) documentation, and there should be an easy way for distinguish compressed and uncompressed position (APRS101.PDF doc page 32 vs doc page 37)

In all cases the compressed format is a fixed 13-character field:
 /YYYYXXXX$csT
where:
/ is the Symbol Table Identifier
[...]

*Symbol*
The presence of the leading Symbol Table Identifier instead of a digit
indicates that this is a compressed Position Report and not a normal lat/long
report

but it seems that all the received compressed packets are 12-bytes instead of 13-bytes long -- without this Sym Table ID byte.

What's even more interesting is that aprs-is decode these packets flawlessly, so there must be some newer documentation that I couldn't find...

Yes, should fit as workaround. I have reviewed APRS 1.0.1 (29 Aug 2000) documentation, and there should be an easy way for distinguish compressed and uncompressed position (APRS101.PDF doc page 32 vs doc page 37) ``` In all cases the compressed format is a fixed 13-character field: /YYYYXXXX$csT where: / is the Symbol Table Identifier [...] *Symbol* The presence of the leading Symbol Table Identifier instead of a digit indicates that this is a compressed Position Report and not a normal lat/long report ``` but it seems that all the received compressed packets are 12-bytes instead of 13-bytes long -- without this Sym Table ID byte. What's even more interesting is that aprs-is decode these packets flawlessly, so there must be some newer documentation that I couldn't find... <!-- github-comment-id:2533220192 -->
Author
Owner

APRS101.pdf is missing more than 20 years of corrections, clarifications, and new features.
This is what you want: APRS12c.pdf in https://github.com/wb2osz/aprsspec

73,
John WB2OSZ

APRS101.pdf is missing more than 20 years of corrections, clarifications, and new features. This is what you want: APRS12c.pdf in https://github.com/wb2osz/aprsspec 73, John WB2OSZ <!-- github-comment-id:2533328534 -->
Author
Owner

@wb2osz -- thx for fresh spec! I checked and the length of the encoded position is unchanged (13 bytes). The problem turned out to be the way double space is displayed in html - it caused me to lose one character.

So my mentioned packet should be:
SP9APV-4>APLOX1,SP9APV-4,WIDE1*:!L54-NSLn4# XLora Digi/iGate Nagoya NL550 P=5.47V
rather than:
SP9APV-4>APLOX1,SP9APV-4,WIDE1*:!L54-NSLn4# XLora Digi/iGate Nagoya NL550 P=5.47V

this also explains the fact that the comment in decode_aprs output was missing the first character, which I didn't notice before...

Can be avoided by small change in code:

             element.innerHTML = `
                         <td>${packet.rxTime}</td>
-                        <td>${packet.packet}</td>
+                        <td><pre>${packet.packet}</pre></td>
                         <td>${packet.RSSI}</td>
                         <td>${packet.SNR}</td>
                     `;

in my case <pre> seems to be working without escaping special characters (chrome/firefox)

also changed position decoding logic from:

        if (encodedBytePosition != 0) {
            if (String(packet[encodedBytePosition]) == "G" || String(packet[encodedBytePosition]) == "Q" || String(packet[encodedBytePosition]) == "[" || String(packet[encodedBytePosition]) == "H") {
                return decodeEncodedGPS(packet);
            } else {
                return getReceivedGPS(packet);
            }

to:

        if (encodedBytePosition != 0) {
            // if first byte of position is not a digit then we are dealing with a compressed position
            if (packet[encodedBytePosition-12] < '0' || packet[encodedBytePosition-12] > '9') {
                return decodeEncodedGPS(packet);
            } else {
                return getReceivedGPS(packet);
            }

it seems to be working as expected and makes the condition independent of other potential values ​​of Compression Type (T) byte -- @richonguzman what's yours opinion?

@wb2osz -- thx for fresh spec! I checked and the length of the encoded position is unchanged (13 bytes). The problem turned out to be the way double space is displayed in html - it caused me to lose one character. So my mentioned packet should be: `SP9APV-4>APLOX1,SP9APV-4,WIDE1*:!L54-NSLn4# XLora Digi/iGate Nagoya NL550 P=5.47V` rather than: `SP9APV-4>APLOX1,SP9APV-4,WIDE1*:!L54-NSLn4# XLora Digi/iGate Nagoya NL550 P=5.47V` this also explains the fact that the comment in decode_aprs output was missing the first character, which I didn't notice before... Can be avoided by small change in code: ``` element.innerHTML = ` <td>${packet.rxTime}</td> - <td>${packet.packet}</td> + <td><pre>${packet.packet}</pre></td> <td>${packet.RSSI}</td> <td>${packet.SNR}</td> `; ``` in my case `<pre>` seems to be working without escaping special characters (chrome/firefox) also changed position decoding logic from: ``` if (encodedBytePosition != 0) { if (String(packet[encodedBytePosition]) == "G" || String(packet[encodedBytePosition]) == "Q" || String(packet[encodedBytePosition]) == "[" || String(packet[encodedBytePosition]) == "H") { return decodeEncodedGPS(packet); } else { return getReceivedGPS(packet); } ``` to: ``` if (encodedBytePosition != 0) { // if first byte of position is not a digit then we are dealing with a compressed position if (packet[encodedBytePosition-12] < '0' || packet[encodedBytePosition-12] > '9') { return decodeEncodedGPS(packet); } else { return getReceivedGPS(packet); } ``` it seems to be working as expected and makes the condition independent of other potential values ​​of **Compression Type (T)** byte -- @richonguzman what's yours opinion? <!-- github-comment-id:2534925735 -->
Author
Owner

There is a strange special case for numeric overlays with the compressed position report.
This is mentioned in section 21, APRS Symbols.
I should add a note to the compressed position report section.

in a compressed Position Report, it is not permissible to use a
numeric Symbol Table Identifier (0-9) — compressed positions never start
with a digit. If a numeric overlay is required, the report must use a lower-case
letter instead (in the range a-j) as the Symbol Table Identifier. The lower-
case letter is then mapped to the digits 0-9 (i.e. a=0, b=1, c=2, d=3 etc).
Thus, in the compressed Position Report:
=d5L!!<*e7>7P[
the letter d maps to overlay character “3”.

There is a strange special case for numeric overlays with the compressed position report. This is mentioned in section 21, APRS Symbols. I should add a note to the compressed position report section. in a compressed Position Report, it is not permissible to use a numeric Symbol Table Identifier (0-9) — compressed positions never start with a digit. If a numeric overlay is required, the report must use a lower-case letter instead (in the range a-j) as the Symbol Table Identifier. The lower- case letter is then mapped to the digits 0-9 (i.e. a=0, b=1, c=2, d=3 etc). Thus, in the compressed Position Report: =d5L!!<*e7>7P[ the letter d maps to overlay character “3”. <!-- github-comment-id:2536685317 -->
Author
Owner

thanks for the info, all is added now for igate and tracker packet decoding ;)

thanks for the info, all is added now for igate and tracker packet decoding ;) <!-- github-comment-id:2565938690 -->
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: adam/LoRa_APRS_iGate#153