changes to calculations

This commit is contained in:
pablorevilla-meshtastic
2026-05-14 07:40:04 -07:00
parent 98549e05b9
commit 82323a8783
+37 -13
View File
@@ -211,6 +211,17 @@
font-weight: 700;
}
.reliability-status-skipped {
color: #cbd5e1 !important;
font-weight: 700;
}
.reliability-row-skipped td {
text-decoration: line-through;
text-decoration-thickness: 1px;
color: rgba(255, 255, 255, 0.58) !important;
}
@media (max-width: 600px) {
.reach-gateway-panels {
grid-template-columns: 1fr;
@@ -226,7 +237,9 @@
Review how often each gateway hears packets from a selected node. The report uses the
latest selected packet sample and calculates reliability as heard packets divided by packets
reviewed. The range table groups gateways by reliability bands, while the gateway list
shows each gateway's heard count and percentage for the same sample.
shows each gateway's heard count and percentage for the same sample. Reliability is
calculated only from Text, Position, Node Info, and Telemetry packets; other packet types
are shown in packet details but skipped from the calculation.
</p>
</div>
@@ -248,7 +261,6 @@
<option value="3">Position</option>
<option value="4">Node Info</option>
<option value="67">Telemetry</option>
<option value="70">Traceroute</option>
</select>
<label class="reach-limit-label" for="reach-packet-limit">Packets to review</label>
<select class="form-select" id="reach-packet-limit" style="max-width:110px;">
@@ -367,6 +379,7 @@ const initialReachNodeId = Number(new URLSearchParams(window.location.search).ge
let reachNodeId = initialReachNodeId;
let reachNodes = [];
let reliabilityGatewayDetails = new Map();
const countedReliabilityPorts = new Set([1, 3, 4, 67]);
function escapeHtml(value) {
return String(value ?? "")
@@ -410,6 +423,10 @@ function packetTypeTag(portnum) {
`;
}
function isSkippedReliabilityPacket(packet) {
return !countedReliabilityPorts.has(Number(packet.portnum));
}
function openGatewayPacketModal(nodeId) {
const details = reliabilityGatewayDetails.get(Number(nodeId));
const titleEl = document.getElementById("gateway-packet-title");
@@ -419,16 +436,21 @@ function openGatewayPacketModal(nodeId) {
if (!details) return;
titleEl.textContent = `${details.label}: ${details.heardCount} (${details.total}) packets heard`;
bodyEl.innerHTML = details.packets.map(packet => `
<tr>
bodyEl.innerHTML = details.packets.map(packet => {
const statusClass = packet.skipped
? "reliability-status-skipped"
: packet.heard ? "reliability-status-heard" : "reliability-status-missed";
const statusText = packet.heard ? "Heard" : "Missed";
return `
<tr class="${packet.skipped ? "reliability-row-skipped" : ""}">
<td><a href="/packet/${packet.id}">${packet.id}</a></td>
<td>${escapeHtml(formatPacketTime(packet.import_time_us))}</td>
<td>${packetTypeTag(packet.portnum)}</td>
<td class="${packet.heard ? "reliability-status-heard" : "reliability-status-missed"}">
${packet.heard ? "Heard" : "Missed"}
</td>
<td class="${statusClass}">${statusText}</td>
</tr>
`).join("");
`;
}).join("");
modalEl.classList.add("open");
}
@@ -508,7 +530,7 @@ async function loadReachReport(nodeId = reachNodeId) {
fetchJson(packetUrl),
]);
const packets = (packetData.packets || []).filter(packet => packet.portnum !== 71);
const packets = packetData.packets || [];
const nodesById = new Map(reachNodes.map(node => [Number(node.node_id), node]));
packetCountEl.textContent = packets.length;
@@ -532,7 +554,8 @@ async function loadReachReport(nodeId = reachNodeId) {
);
const gatewayStats = new Map();
seenResults.forEach(result => {
const reportResults = seenResults.filter(result => !isSkippedReliabilityPacket(result.packet));
reportResults.forEach(result => {
const gatewaysForPacket = new Set(result.seen.map(row => Number(row.node_id)));
gatewaysForPacket.delete(reachNodeId);
gatewaysForPacket.forEach(nodeId => {
@@ -544,7 +567,7 @@ async function loadReachReport(nodeId = reachNodeId) {
.map(([nodeId, heardCount]) => ({
nodeId,
heardCount,
percent: packets.length ? (heardCount / packets.length) * 100 : 0,
percent: reportResults.length ? (heardCount / reportResults.length) * 100 : 0,
}))
.sort((a, b) => b.percent - a.percent || b.heardCount - a.heardCount || a.nodeId - b.nodeId);
@@ -586,7 +609,7 @@ async function loadReachReport(nodeId = reachNodeId) {
<button class="reach-heard-link" type="button" onclick="openGatewayPacketModal(${row.nodeId})">
${row.heardCount}
</button>
<span class="text-secondary">(${packets.length})</span>
<span class="text-secondary">(${reportResults.length})</span>
</td>
<td>${row.percent.toFixed(1)}%</td>
</tr>
@@ -597,11 +620,12 @@ async function loadReachReport(nodeId = reachNodeId) {
{
label: gatewayLabel(row.nodeId, nodesById),
heardCount: row.heardCount,
total: packets.length,
total: reportResults.length,
packets: seenResults.map(result => ({
id: result.packet.id,
import_time_us: result.packet.import_time_us,
portnum: result.packet.portnum,
skipped: isSkippedReliabilityPacket(result.packet),
heard: new Set(result.seen.map(seen => Number(seen.node_id))).has(Number(row.nodeId)),
})),
}