Add distance calculation and display in neighbors table

This commit is contained in:
Lloyd
2025-10-27 18:26:56 +00:00
parent ad2ba7c023
commit 733bdc4847

View File

@@ -42,6 +42,7 @@
<th>Public Key</th>
<th>Contact Type</th>
<th>Location</th>
<th>Distance</th>
<th>RSSI</th>
<th>SNR</th>
<th>Last Seen</th>
@@ -51,7 +52,7 @@
</thead>
<tbody id="neighbors-table">
<tr>
<td colspan="9" class="empty-message">
<td colspan="10" class="empty-message">
No repeaters discovered yet - waiting for adverts...
</td>
</tr>
@@ -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 = `
<tr>
<td colspan="9" class="empty-message">
<td colspan="10" class="empty-message">
No repeaters discovered yet - waiting for adverts...
</td>
</tr>
@@ -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 @@
<td data-label="Public Key"><code class="pubkey">${pubkeyShort}</code></td>
<td data-label="Contact Type"><span class="contact-type-badge">${contactType}</span></td>
<td data-label="Location">${location}</td>
<td data-label="Distance"><strong class="distance">${distance}</strong></td>
<td data-label="RSSI"><span class="${rssiClass}">${rssi}</span></td>
<td data-label="SNR">${snr}</td>
<td data-label="Last Seen">${lastSeen}</td>
@@ -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;
}
</style>
</body>
</html>