mirror of
https://github.com/rightup/pyMC_Repeater.git
synced 2026-03-28 17:43:06 +01:00
Add distance calculation and display in neighbors table
This commit is contained in:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user