diff --git a/repeater/templates/neighbors.html b/repeater/templates/neighbors.html
index 4858434..47654a5 100644
--- a/repeater/templates/neighbors.html
+++ b/repeater/templates/neighbors.html
@@ -42,6 +42,7 @@
Public Key |
Contact Type |
Location |
+ Distance |
RSSI |
SNR |
Last Seen |
@@ -51,7 +52,7 @@
- |
+ |
No repeaters discovered yet - waiting for adverts...
|
@@ -71,6 +72,29 @@
let configLat = null;
let configLng = null;
+ // Haversine formula to calculate distance between two lat/lng points in kilometers
+ function calculateDistance(lat1, lng1, lat2, lng2) {
+ const R = 6371; // Earth's radius in kilometers
+ const dLat = (lat2 - lat1) * Math.PI / 180;
+ const dLng = (lng2 - lng1) * Math.PI / 180;
+ const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
+ Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
+ Math.sin(dLng / 2) * Math.sin(dLng / 2);
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
+ return R * c;
+ }
+
+ // Format distance with appropriate units
+ function formatDistance(distanceKm) {
+ if (distanceKm < 1) {
+ return (distanceKm * 1000).toFixed(0) + ' m';
+ } else if (distanceKm < 10) {
+ return distanceKm.toFixed(2) + ' km';
+ } else {
+ return distanceKm.toFixed(1) + ' km';
+ }
+ }
+
// Initialize map
function initMap() {
if (map || !configLat || !configLng) return; // Already initialized or no coords yet
@@ -259,7 +283,7 @@
if (!neighbors || Object.keys(neighbors).length === 0) {
tbody.innerHTML = `
- |
+ |
No repeaters discovered yet - waiting for adverts...
|
@@ -282,6 +306,16 @@
const location = neighbor.latitude && neighbor.longitude && (neighbor.latitude !== 0.0 || neighbor.longitude !== 0.0)
? `${neighbor.latitude.toFixed(6)}, ${neighbor.longitude.toFixed(6)}`
: 'N/A';
+
+ // Calculate distance if both local and neighbor have valid coordinates
+ let distance = 'N/A';
+ if (configLat && configLng &&
+ neighbor.latitude && neighbor.longitude &&
+ (neighbor.latitude !== 0.0 || neighbor.longitude !== 0.0)) {
+ const distanceKm = calculateDistance(configLat, configLng, neighbor.latitude, neighbor.longitude);
+ distance = formatDistance(distanceKm);
+ }
+
const rssi = neighbor.rssi || 'N/A';
const snr = neighbor.snr !== undefined ? neighbor.snr.toFixed(1) + ' dB' : 'N/A';
const lastSeen = new Date(neighbor.last_seen * 1000).toLocaleString();
@@ -302,6 +336,7 @@
${pubkeyShort} |
${contactType} |
${location} |
+ ${distance} |
|
${snr} |
${lastSeen} |
@@ -654,16 +689,17 @@
.data-table td:nth-child(2)::before { content: "Public Key"; }
.data-table td:nth-child(3)::before { content: "Contact Type"; }
.data-table td:nth-child(4)::before { content: "Location"; }
- .data-table td:nth-child(5)::before { content: "RSSI"; }
- .data-table td:nth-child(6)::before { content: "SNR"; }
- .data-table td:nth-child(7)::before { content: "Last Seen"; }
- .data-table td:nth-child(8)::before { content: "First Seen"; }
- .data-table td:nth-child(9)::before { content: "Advert Count"; }
+ .data-table td:nth-child(5)::before { content: "Distance"; }
+ .data-table td:nth-child(6)::before { content: "RSSI"; }
+ .data-table td:nth-child(7)::before { content: "SNR"; }
+ .data-table td:nth-child(8)::before { content: "Last Seen"; }
+ .data-table td:nth-child(9)::before { content: "First Seen"; }
+ .data-table td:nth-child(10)::before { content: "Advert Count"; }
/* Location and timestamps wrap to next line */
.data-table td:nth-child(4),
- .data-table td:nth-child(7),
- .data-table td:nth-child(8) {
+ .data-table td:nth-child(8),
+ .data-table td:nth-child(9) {
display: block;
width: 100%;
margin-right: 0;
@@ -694,8 +730,8 @@
.data-table td:nth-child(1),
.data-table td:nth-child(2),
.data-table td:nth-child(4),
- .data-table td:nth-child(7),
- .data-table td:nth-child(8) {
+ .data-table td:nth-child(8),
+ .data-table td:nth-child(9) {
display: block;
width: 100%;
margin-right: 0;
@@ -731,8 +767,8 @@
.data-table td:nth-child(1),
.data-table td:nth-child(2),
.data-table td:nth-child(4),
- .data-table td:nth-child(7),
- .data-table td:nth-child(8) {
+ .data-table td:nth-child(8),
+ .data-table td:nth-child(9) {
display: block;
width: 100%;
margin-right: 0;
@@ -750,6 +786,11 @@
padding: 2px 4px;
}
}
+
+ .distance {
+ color: #dcdcaa;
+ font-weight: 600;
+ }