@@ -68,11 +67,10 @@ document.addEventListener("DOMContentLoaded", function () {
if (!resp.ok) throw new Error(`Failed to load data for ${name}`);
const data = await resp.json();
- // Reverse to go left-to-right
+ // Reverse for chronological order
data.timestamps.reverse();
data.series.forEach(s => s.data.reverse());
- // Format timestamps as MM-DD-YY
const formattedDates = data.timestamps.map(t => {
const d = new Date(t);
return `${(d.getMonth() + 1).toString().padStart(2, '0')}-${d.getDate().toString().padStart(2, '0')}-${d.getFullYear().toString().slice(-2)}`;
@@ -84,14 +82,45 @@ document.addEventListener("DOMContentLoaded", function () {
};
const chart = echarts.init(chartDiv);
+
+ const isDualAxis = name === 'power';
+
chart.setOption({
- tooltip: { trigger: 'axis' },
+ tooltip: {
+ trigger: 'axis',
+ formatter: function (params) {
+ return params.map(p => {
+ const label = p.seriesName.toLowerCase();
+ const unit = label.includes('volt') ? 'V' : label.includes('battery') ? '%' : '';
+ return `${p.marker} ${p.seriesName}: ${p.data}${unit}`;
+ }).join('
');
+ }
+ },
xAxis: {
type: 'category',
data: formattedDates,
axisLabel: { color: '#fff', rotate: 45 },
},
- yAxis: {
+ yAxis: isDualAxis ? [
+ {
+ type: 'value',
+ name: 'Battery (%)',
+ min: 0,
+ max: 120,
+ position: 'left',
+ axisLabel: { color: '#fff' },
+ nameTextStyle: { color: '#fff' }
+ },
+ {
+ type: 'value',
+ name: 'Voltage (V)',
+ min: 0,
+ max: 6,
+ position: 'right',
+ axisLabel: { color: '#fff' },
+ nameTextStyle: { color: '#fff' }
+ }
+ ] : {
type: 'value',
axisLabel: { color: '#fff' },
},
@@ -102,6 +131,7 @@ document.addEventListener("DOMContentLoaded", function () {
smooth: true,
connectNulls: true,
showSymbol: false,
+ yAxisIndex: isDualAxis && s.name.toLowerCase().includes('volt') ? 1 : 0,
})),
legend: { textStyle: { color: '#fff' } }
});
@@ -111,11 +141,12 @@ document.addEventListener("DOMContentLoaded", function () {
console.error(err);
currentChartData = null;
currentChartName = null;
+ chartDiv.innerHTML = `
Error loading ${name} data.
`;
return null;
}
}
- // Load the first chart
+ // Load first chart
const firstTabBtn = document.querySelector('.nav-tabs button.nav-link.active');
if (firstTabBtn) {
const name = firstTabBtn.textContent.toLowerCase();
@@ -123,7 +154,7 @@ document.addEventListener("DOMContentLoaded", function () {
loadChart(name, chartId).then(chart => currentChart = chart);
}
- // Tab change event
+ // On tab switch
document.querySelectorAll('.nav-tabs button.nav-link').forEach(button => {
button.addEventListener('shown.bs.tab', event => {
const name = event.target.textContent.toLowerCase();
@@ -132,7 +163,7 @@ document.addEventListener("DOMContentLoaded", function () {
});
});
- // Download CSV button
+ // CSV Download
document.getElementById('downloadCsvBtn').addEventListener('click', () => {
if (!currentChartData || !currentChartName) {
alert("Chart data not loaded yet.");
@@ -159,7 +190,7 @@ document.addEventListener("DOMContentLoaded", function () {
URL.revokeObjectURL(url);
});
- // Expand chart modal
+ // Fullscreen modal chart
document.getElementById('fullChartModal').addEventListener('shown.bs.modal', () => {
if (!currentChartData || !currentChartName) return;
@@ -167,15 +198,45 @@ document.addEventListener("DOMContentLoaded", function () {
fullChart = echarts.init(document.getElementById('fullChartContainer'));
}
+ const isDualAxis = currentChartName === 'power';
+
fullChart.setOption({
title: { text: currentChartName.charAt(0).toUpperCase() + currentChartName.slice(1), textStyle: { color: '#fff' } },
- tooltip: { trigger: 'axis' },
+ tooltip: {
+ trigger: 'axis',
+ formatter: function (params) {
+ return params.map(p => {
+ const label = p.seriesName.toLowerCase();
+ const unit = label.includes('volt') ? 'V' : label.includes('battery') ? '%' : '';
+ return `${p.marker} ${p.seriesName}: ${p.data}${unit}`;
+ }).join('
');
+ }
+ },
xAxis: {
type: 'category',
data: currentChartData.timestamps,
axisLabel: { color: '#fff', rotate: 45 },
},
- yAxis: {
+ yAxis: isDualAxis ? [
+ {
+ type: 'value',
+ name: 'Battery (%)',
+ min: 0,
+ max: 120,
+ position: 'left',
+ axisLabel: { color: '#fff' },
+ nameTextStyle: { color: '#fff' }
+ },
+ {
+ type: 'value',
+ name: 'Voltage (V)',
+ min: 0,
+ max: 6,
+ position: 'right',
+ axisLabel: { color: '#fff' },
+ nameTextStyle: { color: '#fff' }
+ }
+ ] : {
type: 'value',
axisLabel: { color: '#fff' },
},
@@ -186,6 +247,7 @@ document.addEventListener("DOMContentLoaded", function () {
smooth: true,
connectNulls: true,
showSymbol: false,
+ yAxisIndex: isDualAxis && s.name.toLowerCase().includes('volt') ? 1 : 0,
})),
legend: { textStyle: { color: '#fff' } }
});
@@ -198,4 +260,4 @@ document.addEventListener("DOMContentLoaded", function () {
if (currentChart) currentChart.resize();
});
});
-
\ No newline at end of file
+
diff --git a/meshview/web.py b/meshview/web.py
index e88d54b..e23edfb 100644
--- a/meshview/web.py
+++ b/meshview/web.py
@@ -568,9 +568,6 @@ async def graph_telemetry_json(node_id, payload_type, graph_config):
})
-
-
-
@routes.get("/graph/neighbors_json/{node_id}")
async def graph_neighbors_json(request):
import datetime