diff --git a/data_embed/index.html b/data_embed/index.html
index f169abc..8d61fbf 100644
--- a/data_embed/index.html
+++ b/data_embed/index.html
@@ -96,7 +96,6 @@ body{background:var(--msh-bg);color:var(--msh-text);font-family:"Inter",system-u
d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8m8-7a7 7 0 0 0-5.468 11.37C3.242 11.226 4.805 10 8 10s4.757 1.225 5.468 2.37A7 7 0 0 0 8 1"
/>
Station
-Maps
Beaconing
Administration
About / Info
+Map
Received Packets
Update OTA
@@ -218,7 +218,7 @@ body{background:var(--msh-bg);color:var(--msh-text);font-family:"Inter",system-u
Stations Map
-
Needs internet (OpenStreetMap tiles). Updates every 15 seconds.
+
Needs internet (OpenStreetMap tiles). Updates every 15 seconds. Stations heard in the last hour.
diff --git a/data_embed/script.js b/data_embed/script.js
index 51de1e8..ea64fdf 100644
--- a/data_embed/script.js
+++ b/data_embed/script.js
@@ -670,7 +670,13 @@ function loadMapStations(stations) {
+ ` RSSI ${s.RSSI} / SNR ${s.SNR}`
+ ` Packets: ${s.count}`;
- L.marker([s.lat, s.lon]).bindPopup(popup).addTo(mapMarkers);
+ L.circleMarker([s.lat, s.lon], {
+ radius: 6,
+ color: "#1d6fe0", // borde
+ weight: 2,
+ fillColor: "#3b8cff", // relleno
+ fillOpacity: 0.9
+ }).bindPopup(popup).addTo(mapMarkers);
});
}
diff --git a/include/map_utils.h b/include/map_utils.h
index 7aee54c..912a565 100644
--- a/include/map_utils.h
+++ b/include/map_utils.h
@@ -22,7 +22,6 @@
#include
#include
-#define MAX_MAP_STATIONS 50
struct MapStation {
char callsign[10]; // "XX9XXX-NN" + null -> clave para deduplicar
@@ -38,7 +37,7 @@ struct MapStation {
namespace MAP_Utils {
- void upsert(const String& callsign, float latitude, float longitude, const String& symbol, int16_t rssi, float snr);
+ void upsert(const String& callsign, float latitude, float longitude, const String& symbol, int rssi, float snr);
String getStationsJson();
}
diff --git a/src/lora_utils.cpp b/src/lora_utils.cpp
index 14f5b6e..60d5db1 100644
--- a/src/lora_utils.cpp
+++ b/src/lora_utils.cpp
@@ -16,6 +16,7 @@
* along with LoRa APRS iGate. If not, see .
*/
+#include
#include
#include "configuration.h"
#include "network_manager.h"
@@ -23,13 +24,12 @@
#include "station_utils.h"
#include "board_pinout.h"
#include "syslog_utils.h"
+#include "map_utils.h"
#include "ntp_utils.h"
#include "display.h"
#include "utils.h"
-
-
extern Configuration Config;
extern NetworkManager *networkManager;
extern bool packetIsBeacon;
@@ -280,6 +280,11 @@ namespace LoRa_Utils {
receivedPacket.RSSI = rssi;
receivedPacket.SNR = snr;
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 (Config.syslog.active && networkManager->isConnected()) {
diff --git a/src/map_utils.cpp b/src/map_utils.cpp
index 71b630b..69a3716 100644
--- a/src/map_utils.cpp
+++ b/src/map_utils.cpp
@@ -20,6 +20,9 @@
#include "map_utils.h"
#include "ntp_utils.h"
+#define MAX_MAP_STATIONS 50
+#define STATION_TTL_MS 3600000UL // 1 hora (en milisegundos)
+
std::vector mapStations;
@@ -39,7 +42,7 @@ 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, int16_t rssi, float snr) {
+ void upsert(const String& callsign, float latitude, float longitude, const String& symbol, int rssi, float snr) {
for (auto &s : mapStations) { // 1) ya existe -> actualizar
if (callsign.equals(s.callsign)) {
s.latitude = latitude;
@@ -77,7 +80,17 @@ namespace MAP_Utils {
mapStations.push_back(st);
}
+ void purgeOldStations() {
+ uint32_t now = millis();
+ for (int i = (int)mapStations.size() - 1; i >= 0; i--) {
+ if (now - mapStations[i].lastHeardMillis > STATION_TTL_MS) {
+ mapStations.erase(mapStations.begin() + i);
+ }
+ }
+ }
+
String getStationsJson() {
+ purgeOldStations();
JsonDocument data;
for (size_t i = 0; i < mapStations.size(); i++) {