diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index e2ff43fe..0136a254 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -398,6 +398,8 @@ jobs: CHROMIUM_REQUIRE=1 BASE_URL=http://localhost:13581 node test-issue-1510-live-nav-pin-e2e.js 2>&1 | tee -a e2e-output.txt CHROMIUM_REQUIRE=1 BASE_URL=http://localhost:13581 node test-live-fullscreen-1572-e2e.js 2>&1 | tee -a e2e-output.txt CHROMIUM_REQUIRE=1 BASE_URL=http://localhost:13581 node test-issue-1599-replay-freeze-e2e.js 2>&1 | tee -a e2e-output.txt + CHROMIUM_REQUIRE=1 BASE_URL=http://localhost:13581 node test-issue-1648-m1-icons-e2e.js 2>&1 | tee -a e2e-output.txt + CHROMIUM_REQUIRE=1 BASE_URL=http://localhost:13581 node test-issue-1648-m2-icons-e2e.js 2>&1 | tee -a e2e-output.txt BASE_URL=http://localhost:13581 node test-issue-1224-channels-mobile-ux-e2e.js 2>&1 | tee -a e2e-output.txt BASE_URL=http://localhost:13581 node test-issue-1367-channels-chat-app-e2e.js 2>&1 | tee -a e2e-output.txt BASE_URL=http://localhost:13581 node test-issue-1236-map-mobile-e2e.js 2>&1 | tee -a e2e-output.txt diff --git a/public/analytics.js b/public/analytics.js index 3e2bae36..d9cab35b 100644 --- a/public/analytics.js +++ b/public/analytics.js @@ -98,7 +98,7 @@ app.innerHTML = `
Deep dive into your mesh network data
Score = payload bytes Γ distinct repeaters that forwarded the packet. Counts relay re-transmissions; originator TX excluded. Not comparable across meshes.
${renderRelayAirtimeDumbbell(d.airtimeData)}Signal-to-Noise Ratio (higher = cleaner signal)
${snrHist.svg}Received Signal Strength (closer to 0 = stronger)
${rssiHist.svg}Each dot = one packet. Cluster position reveals link quality.
${renderScatter(rf.scatterData)}Raw packet length in bytes
${histogram(rf.packetSizes, 25, '#8b5cf6').svg}Number of repeater hops per packet
${barChart(topo.hopDistribution.map(h=>h.count), topo.hopDistribution.map(h=>h.hops), ['#3b82f6'])}Nodes appearing most in packet paths
${renderRepeaterTable(topo.topRepeaters)}Which repeaters frequently appear together in paths
${renderPairTable(topo.topPairs)}Does more hops = worse signal?
${renderHopsSNR(topo.hopsVsSnr)}Shortest hop distance seen across all observers
${renderBestPath(topo.bestPathList)}Nodes at each hop distance, from each observer's perspective
${topo.observers.length > 1 ? `Nodes seen by multiple observers β hop distance varies by vantage point
${renderCrossObserver(topo.multiObsNodes)}' + ch.activeChannels + ' active channels, ' + ch.decryptable + ' decryptable
' + '| ' + esc(r.name) + ' | ' + '' + esc(r.role || 'unknown') + ' | ' + '' + - (statusIcon[r.status] || 'β') + ' ' + (statusLabel[r.status] || 'Unknown') + ' | ' + + (statusIcon[r.status] || '') + ' ' + (statusLabel[r.status] || 'Unknown') + '' + '' + r.hashSize + '-byte | ' + '' + r.packets + ' | ' + '' + (r.lastSeen ? timeAgo(r.lastSeen) : 'β') + ' | ' + @@ -1370,9 +1370,9 @@ '' + '
| ${i + 1} | -${routeDisplay}${hasSelfLoop ? ' π' : ''} ${esc(prefixDisplay)} |
+ ${routeDisplay}${hasSelfLoop ? ' ' : ''} ${esc(prefixDisplay)} |
${s.count.toLocaleString()} | ${s.pct}% | @@ -1979,7 +1979,7 @@ el.innerHTML = ` |
| # | Node | Role | Total Packets | Packets Today | Analytics | ${n.role} | ${n.health.stats.totalTransmissions || n.health.stats.totalPackets || 0} | ${n.health.stats.packetsToday || 0} | -π | +`).join('')} |
|---|
| # | Node | Role | Avg SNR | Observers | Analytics | ${n.role} | ${n.health.stats.avgSnr.toFixed(1)} dB | ${n.health.observers?.length || 0} | -π | +`).join('')} |
|---|
| # | Node | Role | Observers | Avg SNR | Analytics | ${n.role} | ${n.health.observers?.length || 0} | ${n.health.stats.avgSnr != null ? n.health.stats.avgSnr.toFixed(1) + ' dB' : 'β'} | -π | +`).join('')} |
|---|
| # | From | To | Distance (${distUnitLabel}) | Type | Obs | Best SNR | Median SNR | Packet |
|---|
| # | From | To | Distance (${distUnitLabel}) | Type | Obs | Best SNR | Median SNR | Packet | |
|---|---|---|---|---|---|---|---|---|---|
| ${i+1} | ${fromLink} | ${toLink} | ${formatDistance(h.dist)} | ${esc(h.type)} | ${obs} | ${bestSnr} | ${medianSnr} | ${pktLink} | ${mapBtn} |
| # | Total Distance (${distUnitLabel}) | Hops | Route | Packet |
|---|
| # | Total Distance (${distUnitLabel}) | Hops | Route | Packet | |
|---|---|---|---|---|---|
| ${i+1} | ${formatDistance(p.totalDist)} | ${p.hopCount} | ${route} | ${pktLink} | ${mapBtn} |
β = high confidence (score β₯ 0.5), β = low confidence, β = ambiguous/unresolved
'; + html += '' + '' + ' = high confidence (score β₯ 0.5), ' + '' + ' = low confidence, ' + '' + ' = ambiguous/unresolved
'; listEl.innerHTML = html; } @@ -3052,8 +3052,8 @@ function destroy() { _stopRolesRefresh(); _stopScopesRefresh(); _analyticsData = // distinguish theoretical/would-collide-if-used from packet- // traffic-observed collisions shown on the Hash Issues tab. const opLine = opC === 0 - ? `β No address conflicts among configured repeaters` - : `β οΈ ${opC} address conflict${opC !== 1 ? 's' : ''} among configured repeaters (would-collide-if-used)`; + ? ` No address conflicts among configured repeaters` + : ` ${opC} address conflict${opC !== 1 ? 's' : ''} among configured repeaters (would-collide-if-used)`; // #1306: expandable WHICH-collides toggles (op + theoretical) const opEntries = collEntries.operational[b]; const theoEntries = collEntries.theoretical[b]; @@ -3130,7 +3130,7 @@ function destroy() { _stopRolesRefresh(); _stopScopesRefresh(); _analyticsData =Find a prefix with zero current collisions.
-
+
0x00 and 0xFF excluded as a first byte β the MeshCore firmware keygen routine re-rolls identities whose pub_key[0] is 00 or FF, so by convention you should not see those prefixes on real nodes (see
simple_repeater/main.cpp:83).
@@ -3150,7 +3150,7 @@ function destroy() { _stopRolesRefresh(); _stopScopesRefresh(); _analyticsData =