From e0dc2f81ee270f89c709e9cbefc789155de425d1 Mon Sep 17 00:00:00 2001 From: Ricardo Guzman Date: Mon, 24 Aug 2026 23:18:25 -0400 Subject: [PATCH] ready for testing --- data_embed/aprs-symbols-24-0.png | Bin 0 -> 38591 bytes data_embed/aprs-symbols-24-1.png | Bin 0 -> 41892 bytes data_embed/script.js | 284 ++++++++++++++++++++++++++++++- include/map_utils.h | 3 +- platformio.ini | 2 + src/LoRa_APRS_iGate.cpp | 4 +- src/lora_utils.cpp | 4 +- src/map_utils.cpp | 17 +- src/web_utils.cpp | 34 ++++ tools/compress.py | 2 + 10 files changed, 327 insertions(+), 23 deletions(-) create mode 100644 data_embed/aprs-symbols-24-0.png create mode 100644 data_embed/aprs-symbols-24-1.png diff --git a/data_embed/aprs-symbols-24-0.png b/data_embed/aprs-symbols-24-0.png new file mode 100644 index 0000000000000000000000000000000000000000..92bf1147277d4bbb71ffd05fe4140773f28cbeda GIT binary patch literal 38591 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 LNkvXXu0mjfGLO)F literal 0 HcmV?d00001 diff --git a/data_embed/aprs-symbols-24-1.png b/data_embed/aprs-symbols-24-1.png new file mode 100644 index 0000000000000000000000000000000000000000..b83d4b14fe5440bab67ed15248d9c0452a517fc1 GIT binary patch literal 41892 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 AbN~PV literal 0 HcmV?d00001 diff --git a/data_embed/script.js b/data_embed/script.js index 90faeef..2f54d32 100644 --- a/data_embed/script.js +++ b/data_embed/script.js @@ -490,7 +490,6 @@ function toggleWiFiAutoAPFields() { if (autoAPConfig) autoAPConfig.style.display = isEnabled ? 'block' : 'none'; } - document.querySelector(".new button").addEventListener("click", function () { const networksContainer = document.querySelector(".list-networks"); @@ -659,10 +658,240 @@ function setMapMessage(text) { } } + +/* + * APRS symbol renderer for Stations Map + * + * s.symbol contains APRS table + symbol code, for example: + * "/>" Primary table + * "\\>" Alternate table + * "L&" Alternate table with overlay + * + * Sprite layout: + * aprs-symbols-24-0.png = Primary table + * aprs-symbols-24-1.png = Alternate table + */ + +function getAprsSymbolIcon(symbol, callsign = "") { + + if (!symbol || String(symbol).length < 2) { + return null; + } + + const value = String(symbol); + + let table = value.charAt(0); + let code = value.charAt(1); + let overlay = null; + + /* + * Standard APRS: + * "/" = Primary + * "\\" = Alternate + * + * A-Z / 0-9 / a-j in table position are overlays + * for the Alternate table. + */ + if ( + table !== "/" && + table !== "\\" + ) { + overlay = table; + table = "\\"; + } + + const ascii = code.charCodeAt(0); + + /* + * APRS printable symbol codes are ASCII 33..126. + */ + if ( + ascii < 33 || + ascii > 126 + ) { + return null; + } + + const index = ascii - 33; + + /* + * Sprite sheet contains 16 columns. + * Each cell is 24 x 24 px. + */ + const columns = 16; + + const col = index % columns; + const row = Math.floor(index / columns); + + const sprite = + table === "/" + ? "/aprs-symbols-24-0.png" + : "/aprs-symbols-24-1.png"; + + const x = -(col * 24); + const y = -(row * 24); + + let overlayHtml = ""; + + if (overlay) { + + let displayOverlay = overlay; + + /* + * APRS compressed numeric overlay: + * a-j -> 0-9 + */ + if ( + overlay >= "a" && + overlay <= "j" + ) { + displayOverlay = + String( + overlay.charCodeAt(0) - + "a".charCodeAt(0) + ); + } + + overlayHtml = ` + + ${displayOverlay} + + `; + } + + return L.divIcon({ + className: "", + html: ` +
+ ${overlayHtml} + + ${callsign} +
+ `, + iconSize: [24, 24], + iconAnchor: [12, 12], + popupAnchor: [0, -12] + }); +} + + +let mapStationsCache = []; +let mapRouteLayer = null; + +function getUsedDigipeaters(path) { + if (!path) return []; + + return path + .split(",") + .map((x) => x.trim()) + .filter((x) => x.endsWith("*")) + .map((x) => x.replace(/\*+$/, "")) + .filter((x) => + x && + !x.startsWith("WIDE") && + !x.startsWith("TRACE") && + !x.startsWith("TCPIP") && + !x.startsWith("TCPXX") && + !x.startsWith("qA") + ); +} + + +function describeMapPath(station) { + const digis = getUsedDigipeaters(station.path); + + if (!digis.length) { + return "Direct"; + } + + return "Via: " + digis.join(" → "); +} + + +function clearMapRoute() { + if (mapRouteLayer && mapInstance) { + mapInstance.removeLayer(mapRouteLayer); + } + mapRouteLayer = null; +} + + +function drawStationRoute(station) { + if (!mapInstance || !iGateLatLng) return; + + clearMapRoute(); + + const points = [ + L.latLng(station.lat, station.lon) + ]; + + const digis = getUsedDigipeaters(station.path); + + digis.forEach((digiCall) => { + const digi = mapStationsCache.find((s) => + String(s.callsign || "").toUpperCase() === digiCall.toUpperCase() + ); + + if (digi && !(digi.lat === 0 && digi.lon === 0)) { + points.push(L.latLng(digi.lat, digi.lon)); + } + }); + + points.push(iGateLatLng); + + mapRouteLayer = L.polyline(points, { + color: "#e53935", + weight: 3, + opacity: 0.9 + }).addTo(mapInstance); +} + + function loadMapStations(stations) { if (!mapMarkers) return; + mapStationsCache = stations || []; + mapMarkers.clearLayers(); + clearMapRoute(); let drawn = 0; (stations || []).forEach((s) => { @@ -671,15 +900,52 @@ function loadMapStations(stations) { const popup = `${s.callsign}` + (s.lastHeard ? `
Last: ${s.lastHeard}` : "") + `
RSSI ${s.RSSI} / SNR ${s.SNR}` - + `
Packets: ${s.count}`; + + `
Packets: ${s.count}` + + `
${describeMapPath(s)}` + + (s.path ? `
Path: ${s.path}` : ""); + + const aprsIcon = + getAprsSymbolIcon(s.symbol, s.callsign); + + if (aprsIcon) { + + const marker = L.marker( + [s.lat, s.lon], + { + icon: aprsIcon + } + ) + .bindPopup(popup) + .addTo(mapMarkers); + + marker.on("mouseover", function () { + drawStationRoute(s); + }); + + marker.on("mouseout", function () { + clearMapRoute(); + }); + + } else { // Fallback: station with missing or invalid APRS symbol + const marker = L.circleMarker([s.lat, s.lon], { + radius: 6, + color: "#1d6fe0", + weight: 2, + fillColor: "#3b8cff", + fillOpacity: 0.9 + }) + .bindPopup(popup) + .addTo(mapMarkers); + + marker.on("mouseover", function () { + drawStationRoute(s); + }); + + marker.on("mouseout", function () { + clearMapRoute(); + }); + } - L.circleMarker([s.lat, s.lon], { - radius: 6, - color: "#1d6fe0", // borde - weight: 2, - fillColor: "#3b8cff", // relleno - fillOpacity: 0.9 - }).bindPopup(popup).addTo(mapMarkers); drawn++; }); diff --git a/include/map_utils.h b/include/map_utils.h index 07d2f1c..027ab5b 100644 --- a/include/map_utils.h +++ b/include/map_utils.h @@ -32,12 +32,13 @@ struct MapStation { float snr; // ultimo SNR uint16_t count; // nro de paquetes oidos de esa estacion char lastHeard[10]; // "HH:MM:SS" si hay NTP valido, "" si no + char path[96]; // last path received uint32_t lastHeardMillis; // millis() -> ordenar / expirar (no se muestra) }; namespace MAP_Utils { - void upsert(const String& callsign, float latitude, float longitude, const String& symbol, int rssi, float snr); + void upsert(const String& callsign, float latitude, float longitude, const String& path, const String& symbol, int rssi, float snr); String getStationsJson(); } diff --git a/platformio.ini b/platformio.ini index 4499fa8..b4bf4b5 100644 --- a/platformio.ini +++ b/platformio.ini @@ -29,6 +29,8 @@ board_build.embed_files = data_embed/leaflet.css.gz data_embed/leaflet.js.gz data_embed/favicon.png.gz + data_embed/aprs-symbols-24-0.png.gz + data_embed/aprs-symbols-24-1.png.gz extra_scripts = pre:tools/compress.py debug_tool = esp-prog \ No newline at end of file diff --git a/src/LoRa_APRS_iGate.cpp b/src/LoRa_APRS_iGate.cpp index eb501f8..8a23b27 100644 --- a/src/LoRa_APRS_iGate.cpp +++ b/src/LoRa_APRS_iGate.cpp @@ -68,8 +68,8 @@ ___________________________________________________________________*/ #endif -String versionDate = "2026-08-16"; -String versionNumber = "4.0.0"; +String versionDate = "2026-08-24"; +String versionNumber = "4.0.1"; Configuration Config; WiFiClient aprsIsClient; WiFiClient mqttClient; diff --git a/src/lora_utils.cpp b/src/lora_utils.cpp index 1f603be..5ce7d91 100644 --- a/src/lora_utils.cpp +++ b/src/lora_utils.cpp @@ -291,8 +291,8 @@ namespace LoRa_Utils { receivedPackets.push_back(receivedPacket); APRSPacket aprsPacket = APRSPacketLib::processReceivedPacket(packet.substring(3), rssi, snr, freqError); - if (aprsPacket.type == 0 || aprsPacket.type == 4) { // 0 = GPS, 4 = Mic-E (los que traen posición) - MAP_Utils::upsert(aprsPacket.sender, aprsPacket.latitude, aprsPacket.longitude, aprsPacket.overlay + aprsPacket.symbol, aprsPacket.rssi, aprsPacket.snr); + if (aprsPacket.type == 0 || aprsPacket.type == 4) { // 0 = GPS, 4 = Mic-E (only ones with position) + MAP_Utils::upsert(aprsPacket.sender, aprsPacket.latitude, aprsPacket.longitude, aprsPacket.path, aprsPacket.overlay + aprsPacket.symbol, aprsPacket.rssi, aprsPacket.snr); } } diff --git a/src/map_utils.cpp b/src/map_utils.cpp index 762534f..fc27a89 100644 --- a/src/map_utils.cpp +++ b/src/map_utils.cpp @@ -29,9 +29,7 @@ std::vector mapStations; namespace MAP_Utils { - // Copia la hora NTP "HH:MM:SS" si es valida; si no hay red (NTP devuelve - // un texto de fallback) deja el campo vacio para no guardar hora falsa. - void writeFormatedTime(char* dst, size_t size) { + void writeFormatedTime(char* dst, size_t size) { // gets NTP time ("HH:MM:SS") and writes it to dst if valid String t = NTP_Utils::getFormatedTime(); if (t.length() == 8 && t.charAt(2) == ':') { t.toCharArray(dst, size); @@ -40,10 +38,8 @@ namespace MAP_Utils { } } - // Inserta una estacion nueva o actualiza la existente (dedup por callsign). - // Llamar solo cuando el parser ya decodifico una posicion valida. - void upsert(const String& callsign, float latitude, float longitude, const String& symbol, int rssi, float snr) { - for (auto &s : mapStations) { // 1) ya existe -> actualizar + void upsert(const String& callsign, float latitude, float longitude, const String& path, const String& symbol, int rssi, float snr) { // Upsert station only with valid position with callsign dedup. + for (auto &s : mapStations) { // 1) update if (callsign.equals(s.callsign)) { s.latitude = latitude; s.longitude = longitude; @@ -51,13 +47,14 @@ namespace MAP_Utils { s.snr = snr; s.count++; symbol.toCharArray(s.symbol, sizeof(s.symbol)); + path.toCharArray(s.path, sizeof(s.path)); writeFormatedTime(s.lastHeard, sizeof(s.lastHeard)); s.lastHeardMillis = millis(); return; } } - if (mapStations.size() >= MAX_MAP_STATIONS) { // 2) llena -> descartar la mas vieja + if (mapStations.size() >= MAX_MAP_STATIONS) { // 2) full? delete oldest one size_t oldest = 0; for (size_t i = 1; i < mapStations.size(); i++) { if (mapStations[i].lastHeardMillis < mapStations[oldest].lastHeardMillis) { @@ -67,9 +64,10 @@ namespace MAP_Utils { mapStations.erase(mapStations.begin() + oldest); } - MapStation st = {}; // 3) insertar nueva + MapStation st = {}; // 3) insert new callsign.toCharArray(st.callsign, sizeof(st.callsign)); symbol.toCharArray(st.symbol, sizeof(st.symbol)); + path.toCharArray(st.path, sizeof(st.path)); st.latitude = latitude; st.longitude = longitude; st.rssi = rssi; @@ -102,6 +100,7 @@ namespace MAP_Utils { data[i]["SNR"] = mapStations[i].snr; data[i]["count"] = mapStations[i].count; data[i]["lastHeard"] = mapStations[i].lastHeard; + data[i]["path"] = mapStations[i].path; } String buffer; diff --git a/src/web_utils.cpp b/src/web_utils.cpp index 5604038..ec81b87 100644 --- a/src/web_utils.cpp +++ b/src/web_utils.cpp @@ -62,6 +62,14 @@ extern const unsigned char favicon_data[] asm("_binary_data_embed_favicon_png_gz extern const unsigned char favicon_data_end[] asm("_binary_data_embed_favicon_png_gz_end"); extern const size_t favicon_data_len = favicon_data_end - favicon_data; +extern const unsigned char aprs_symbols_24_0_data[] asm("_binary_data_embed_aprs_symbols_24_0_png_gz_start"); +extern const unsigned char aprs_symbols_24_0_data_end[] asm("_binary_data_embed_aprs_symbols_24_0_png_gz_end"); +extern const size_t aprs_symbols_24_0_data_len = aprs_symbols_24_0_data_end - aprs_symbols_24_0_data; + +extern const unsigned char aprs_symbols_24_1_data[] asm("_binary_data_embed_aprs_symbols_24_1_png_gz_start"); +extern const unsigned char aprs_symbols_24_1_data_end[] asm("_binary_data_embed_aprs_symbols_24_1_png_gz_end"); +extern const size_t aprs_symbols_24_1_data_len = aprs_symbols_24_1_data_end - aprs_symbols_24_1_data; + namespace WEB_Utils { @@ -92,6 +100,30 @@ namespace WEB_Utils { request->send(response); } + void handleAprsSymbols24Primary(AsyncWebServerRequest *request) { + AsyncWebServerResponse *response = request->beginResponse( + 200, + "image/png", + (const uint8_t*)aprs_symbols_24_0_data, + aprs_symbols_24_0_data_len + ); + response->addHeader("Content-Encoding", "gzip"); + response->addHeader("Cache-Control", "max-age=3600"); + request->send(response); + } + + void handleAprsSymbols24Alternate(AsyncWebServerRequest *request) { + AsyncWebServerResponse *response = request->beginResponse( + 200, + "image/png", + (const uint8_t*)aprs_symbols_24_1_data, + aprs_symbols_24_1_data_len + ); + response->addHeader("Content-Encoding", "gzip"); + response->addHeader("Cache-Control", "max-age=3600"); + request->send(response); + } + void handleReadConfiguration(AsyncWebServerRequest *request) { if(Config.webadmin.active && !request->authenticate(Config.webadmin.username.c_str(), Config.webadmin.password.c_str())) return request->requestAuthentication(); @@ -401,6 +433,8 @@ namespace WEB_Utils { server.on("/leaflet.css", HTTP_GET, handleLeafletStyle); server.on("/leaflet.js", HTTP_GET, handleLeafletScript); server.on("/favicon.png", HTTP_GET, handleFavicon); + server.on("/aprs-symbols-24-0.png", HTTP_GET, handleAprsSymbols24Primary); + server.on("/aprs-symbols-24-1.png", HTTP_GET, handleAprsSymbols24Alternate); OTA_Utils::setup(&server); // Include OTA Updater for WebServer diff --git a/tools/compress.py b/tools/compress.py index 0d91d17..fe75697 100644 --- a/tools/compress.py +++ b/tools/compress.py @@ -29,6 +29,8 @@ files = [ 'data_embed/leaflet.js', 'data_embed/leaflet.css', 'data_embed/favicon.png', + 'data_embed/aprs-symbols-24-0.png', + 'data_embed/aprs-symbols-24-1.png', ] string_to_find_str = "String"