mirror of
https://github.com/pablorevilla-meshtastic/meshview.git
synced 2026-03-04 23:27:46 +01:00
Fix chart on node.html.
This commit is contained in:
@@ -41,7 +41,7 @@
|
||||
/* --- Charts --- */
|
||||
.chart-container {
|
||||
width: 100%;
|
||||
height: 320px;
|
||||
height: 380px;
|
||||
margin-bottom: 25px;
|
||||
border: 1px solid #3a3f44;
|
||||
border-radius: 8px;
|
||||
@@ -170,7 +170,7 @@
|
||||
<button onclick="exportCSV('battery_voltage')" data-translate-lang="export_csv">Export CSV</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="chart_battery_voltage" style="height:260px;"></div>
|
||||
<div id="chart_battery_voltage" style="height:380px;"></div>
|
||||
</div>
|
||||
|
||||
<!-- Air/Channel -->
|
||||
@@ -182,7 +182,7 @@
|
||||
<button onclick="exportCSV('air_channel')" data-translate-lang="export_csv">Export CSV</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="chart_air_channel" style="height:260px;"></div>
|
||||
<div id="chart_air_channel" style="height:380px;"></div>
|
||||
</div>
|
||||
|
||||
<!-- Env Metrics -->
|
||||
@@ -194,7 +194,7 @@
|
||||
<button onclick="exportCSV('environment')" data-translate-lang="export_csv">Export CSV</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="chart_environment" style="height:260px;"></div>
|
||||
<div id="chart_environment" style="height:380px;"></div>
|
||||
</div>
|
||||
|
||||
<!-- Neighbor chart -->
|
||||
@@ -207,7 +207,7 @@
|
||||
<button onclick="exportCSV('neighbors')" data-translate-lang="export_csv">Export CSV</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="chart_neighbors" style="height:260px;"></div>
|
||||
<div id="chart_neighbors" style="height:380px;"></div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -921,20 +921,22 @@ async function loadNeighborTimeSeries() {
|
||||
}
|
||||
|
||||
const data = await res.json();
|
||||
const packets = data.packets || [];
|
||||
let packets = data.packets || [];
|
||||
|
||||
if (!packets.length) {
|
||||
document.getElementById("neighbor_chart_container").style.display = "none";
|
||||
return;
|
||||
}
|
||||
|
||||
// --- FIX: sort packets chronologically (oldest → newest) ---
|
||||
packets.sort((a, b) => (b.import_time_us || 0) - (a.import_time_us || 0));
|
||||
|
||||
// --- FIX #1: enforce chronological order (oldest → newest) ---
|
||||
packets.sort((a, b) => (a.import_time_us || 0) - (b.import_time_us || 0));
|
||||
|
||||
// neighborHistory = { node_id: { name, snr:[...], times:[...] } }
|
||||
const neighborHistory = {};
|
||||
|
||||
for (const pkt of packets.reverse()) {
|
||||
for (const pkt of packets) {
|
||||
if (!pkt.import_time_us || !pkt.payload) continue;
|
||||
|
||||
const ts = new Date(pkt.import_time_us / 1000).toLocaleString([], {
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
@@ -942,14 +944,12 @@ async function loadNeighborTimeSeries() {
|
||||
minute: "2-digit"
|
||||
});
|
||||
|
||||
const payload = pkt.payload || "";
|
||||
|
||||
// Parse neighbor blocks
|
||||
const re = /neighbors\s*\{\s*([^}]+)\}/g;
|
||||
// Extract neighbor blocks
|
||||
const blockRe = /neighbors\s*\{([^}]+)\}/g;
|
||||
let m;
|
||||
|
||||
while ((m = re.exec(payload)) !== null) {
|
||||
while ((m = blockRe.exec(pkt.payload)) !== null) {
|
||||
const block = m[1];
|
||||
|
||||
const idMatch = block.match(/node_id:\s*(\d+)/);
|
||||
const snrMatch = block.match(/snr:\s*(-?\d+(?:\.\d+)?)/);
|
||||
|
||||
@@ -958,78 +958,62 @@ async function loadNeighborTimeSeries() {
|
||||
const nid = parseInt(idMatch[1], 10);
|
||||
const snr = parseFloat(snrMatch[1]);
|
||||
|
||||
// Fetch name if needed
|
||||
if (!nodeMap[nid]) {
|
||||
await fetchNodeFromApi(nid);
|
||||
}
|
||||
|
||||
const label = nodeMap[nid] || nid;
|
||||
|
||||
if (!neighborHistory[nid]) {
|
||||
neighborHistory[nid] = {
|
||||
name: label,
|
||||
snr: [],
|
||||
times: []
|
||||
name: nodeMap[nid] || `Node ${nid}`,
|
||||
times: [],
|
||||
snr: []
|
||||
};
|
||||
}
|
||||
|
||||
neighborHistory[nid].snr.push(snr);
|
||||
neighborHistory[nid].times.push(ts);
|
||||
neighborHistory[nid].snr.push(snr);
|
||||
}
|
||||
}
|
||||
|
||||
const neighborIds = Object.keys(neighborHistory);
|
||||
if (!neighborIds.length) {
|
||||
document.getElementById("neighbor_chart_container").style.display = "none";
|
||||
return;
|
||||
const chart = echarts.init(document.getElementById("chart_neighbors"));
|
||||
|
||||
const legend = [];
|
||||
const series = [];
|
||||
|
||||
for (const [nid, entry] of Object.entries(neighborHistory)) {
|
||||
legend.push(entry.name);
|
||||
|
||||
series.push({
|
||||
name: entry.name,
|
||||
type: "line",
|
||||
smooth: true,
|
||||
connectNulls: true, // --- FIX #2: connect dots even if missing ---
|
||||
showSymbol: false,
|
||||
data: entry.snr,
|
||||
});
|
||||
}
|
||||
|
||||
const container = document.getElementById("neighbor_chart_container");
|
||||
container.style.display = "block";
|
||||
// Build merged x-axis from first neighbor’s timestamps
|
||||
// (Your original code already behaved this way)
|
||||
const sampleTimes = Object.values(neighborHistory)[0]?.times || [];
|
||||
|
||||
const chartEl = document.getElementById("chart_neighbors");
|
||||
const neighborChart = echarts.init(chartEl);
|
||||
|
||||
const series = neighborIds.map(nid => ({
|
||||
name: neighborHistory[nid].name,
|
||||
type: "line",
|
||||
smooth: true,
|
||||
connectNulls: true,
|
||||
showSymbol: false,
|
||||
data: neighborHistory[nid].snr,
|
||||
}));
|
||||
|
||||
// All times should be aligned → use union of all timestamps
|
||||
const allTimes = [];
|
||||
for (const nid of neighborIds) {
|
||||
for (const t of neighborHistory[nid].times) {
|
||||
if (!allTimes.includes(t)) allTimes.push(t);
|
||||
}
|
||||
}
|
||||
|
||||
neighborChart.setOption({
|
||||
chart.setOption({
|
||||
tooltip: { trigger: "axis" },
|
||||
legend: {
|
||||
data: neighborIds.map(nid => neighborHistory[nid].name),
|
||||
textStyle: { color: "#ccc" }
|
||||
},
|
||||
legend: { data: legend, textStyle: { color: "#ccc" } },
|
||||
xAxis: {
|
||||
type: "category",
|
||||
data: allTimes,
|
||||
axisLabel: { color: "#ccc", rotate: allTimes.length > 6 ? 45 : 0 }
|
||||
data: sampleTimes,
|
||||
axisLabel: { color: "#ccc" }
|
||||
},
|
||||
yAxis: {
|
||||
type: "value",
|
||||
name: "SNR (dB)",
|
||||
name: "SNR",
|
||||
axisLabel: { color: "#ccc" }
|
||||
},
|
||||
series
|
||||
});
|
||||
|
||||
window.addEventListener("resize", () => neighborChart.resize());
|
||||
window.addEventListener("resize", () => chart.resize());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ======================================================
|
||||
EXPAND / EXPORT BUTTONS
|
||||
====================================================== */
|
||||
|
||||
Reference in New Issue
Block a user