Add Bluetooth selected device details panel

- New panel shows full device details when clicked
- Displays name, type, RSSI with signal bars, MAC, manufacturer
- Shows tracker/FindMy badges for detected trackers
- Buttons to enumerate services and copy MAC address
- Reorganized BT visualization layout

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Smittix
2026-01-08 12:37:03 +00:00
parent a87f66cc0c
commit 0c310ab068
+95 -8
View File
@@ -1337,25 +1337,31 @@
<canvas id="btRadarCanvas" width="150" height="150"></canvas>
</div>
</div>
<div class="wifi-visual-panel" style="grid-column: span 2;">
<h5>📋 Selected Device</h5>
<div id="btSelectedDevice" style="font-size: 11px; min-height: 120px;">
<div style="color: var(--text-dim); padding: 20px; text-align: center;">Click a device to view details</div>
</div>
</div>
<div class="wifi-visual-panel" style="grid-column: span 2;">
<h5>🔵 Discovered Devices (<span id="btListCount">0</span>)</h5>
<div id="btDeviceList" style="max-height: 200px; overflow-y: auto; font-size: 11px;">
<div id="btDeviceList" style="max-height: 180px; overflow-y: auto; font-size: 11px;">
<div style="color: var(--text-dim); padding: 10px; text-align: center;">Start scanning to discover devices...</div>
</div>
</div>
<div class="wifi-visual-panel signal-graph-panel" style="grid-column: span 2;">
<div class="wifi-visual-panel" style="grid-column: span 2;">
<h5>📍 Tracker Detection</h5>
<div id="btTrackerList" style="max-height: 120px; overflow-y: auto; font-size: 11px;">
<div style="color: var(--text-dim); padding: 10px; text-align: center;">Monitoring for AirTags, Tiles, and other trackers...</div>
</div>
</div>
<div class="wifi-visual-panel signal-graph-panel" style="grid-column: span 4;">
<div class="signal-graph-header">
<h4>📈 BT Signal History</h4>
<span class="signal-graph-device" id="btSignalGraphDevice">Select a device from the list</span>
</div>
<canvas id="btSignalGraph"></canvas>
</div>
<div class="wifi-visual-panel" style="grid-column: span 2;">
<h5>📍 Tracker Detection</h5>
<div id="btTrackerList" style="max-height: 150px; overflow-y: auto; font-size: 11px;">
<div style="color: var(--text-dim); padding: 10px; text-align: center;">Monitoring for AirTags, Tiles, and other trackers...</div>
</div>
</div>
</div>
<!-- Aircraft Visualizations - Leaflet Map -->
@@ -6054,10 +6060,91 @@
if (device) {
document.getElementById('btSignalGraphDevice').textContent = device.name || mac;
document.getElementById('btTargetMac').value = mac;
updateBtSelectedDevice(device);
}
updateBtDeviceList(); // Refresh to show selection
}
// Update the selected device details panel
function updateBtSelectedDevice(device) {
const panel = document.getElementById('btSelectedDevice');
if (!panel || !device) return;
const typeIcon = {
'phone': '📱', 'audio': '🎧', 'wearable': '⌚', 'tracker': '📍',
'computer': '💻', 'input': '⌨️', 'other': '📶'
}[device.device_type || device.type] || '📶';
const rssiColor = device.rssi > -50 ? 'var(--accent-green)' :
device.rssi > -70 ? 'var(--accent-cyan)' :
device.rssi > -85 ? 'var(--accent-orange)' : 'var(--accent-red)';
const signalBars = Math.max(1, Math.min(5, Math.floor((device.rssi + 100) / 10)));
const barsHtml = Array(5).fill(0).map((_, i) =>
`<div style="width:4px;height:${8 + i * 4}px;background:${i < signalBars ? rssiColor : 'rgba(255,255,255,0.1)'};border-radius:1px;"></div>`
).join('');
let trackerInfo = '';
if (device.findmy) {
trackerInfo = `
<div style="background:rgba(0,122,255,0.15);border:1px solid #007aff;border-radius:6px;padding:8px;margin-top:8px;">
<div style="color:#007aff;font-weight:bold;">🍎 ${escapeHtml(device.findmy.type)}</div>
<div style="color:var(--text-dim);font-size:10px;margin-top:2px;">${escapeHtml(device.findmy.network)} Network Device</div>
</div>`;
} else if (device.tracker) {
trackerInfo = `
<div style="background:rgba(255,100,100,0.15);border:1px solid var(--accent-red);border-radius:6px;padding:8px;margin-top:8px;">
<div style="color:var(--accent-red);font-weight:bold;">📍 ${escapeHtml(device.tracker.name)}</div>
<div style="color:var(--text-dim);font-size:10px;margin-top:2px;">Tracking Device Detected</div>
</div>`;
}
panel.innerHTML = `
<div style="display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:10px;">
<div>
<div style="font-size:16px;font-weight:bold;color:var(--accent-cyan);">${typeIcon} ${escapeHtml(device.name || 'Unknown Device')}</div>
<div style="color:var(--text-dim);font-size:10px;margin-top:2px;">${escapeHtml((device.device_type || device.type || 'unknown').toUpperCase())}</div>
</div>
<div style="text-align:right;">
<div style="font-size:18px;font-weight:bold;color:${rssiColor};">${device.rssi || '--'} dBm</div>
<div style="display:flex;gap:2px;justify-content:flex-end;align-items:flex-end;height:24px;margin-top:4px;">${barsHtml}</div>
</div>
</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:6px;">
<div style="background:rgba(0,0,0,0.3);padding:6px;border-radius:4px;">
<div style="color:var(--text-dim);font-size:9px;">MAC ADDRESS</div>
<div style="font-family:monospace;font-size:11px;">${escapeHtml(device.mac)}</div>
</div>
<div style="background:rgba(0,0,0,0.3);padding:6px;border-radius:4px;">
<div style="color:var(--text-dim);font-size:9px;">MANUFACTURER</div>
<div style="font-size:11px;">${escapeHtml(device.manufacturer || 'Unknown')}</div>
</div>
<div style="background:rgba(0,0,0,0.3);padding:6px;border-radius:4px;">
<div style="color:var(--text-dim);font-size:9px;">ADDRESS TYPE</div>
<div style="font-size:11px;">${escapeHtml(device.address_type || 'Unknown')}</div>
</div>
<div style="background:rgba(0,0,0,0.3);padding:6px;border-radius:4px;">
<div style="color:var(--text-dim);font-size:9px;">LAST SEEN</div>
<div style="font-size:11px;">${device.last_seen ? new Date(device.last_seen * 1000).toLocaleTimeString() : 'Now'}</div>
</div>
</div>
${trackerInfo}
<div style="display:flex;gap:6px;margin-top:10px;">
<button class="preset-btn" onclick="btEnumServicesFor('${escapeAttr(device.mac)}')" style="flex:1;font-size:10px;padding:6px;">Enumerate Services</button>
<button class="preset-btn" onclick="copyToClipboard('${escapeAttr(device.mac)}')" style="flex:1;font-size:10px;padding:6px;">Copy MAC</button>
</div>
`;
}
// Copy text to clipboard helper
function copyToClipboard(text) {
navigator.clipboard.writeText(text).then(() => {
showNotification('Copied', text);
}).catch(() => {
showInfo('Failed to copy to clipboard');
});
}
// Update tracker list panel
function updateBtTrackerList() {
const listEl = document.getElementById('btTrackerList');