Add data plot to sauna route

Signed-off-by: Thomas Klaehn <thomas.klaehn@perinet.io>
This commit is contained in:
Thomas Klaehn
2024-07-03 11:25:54 +02:00
parent 59cb6d1380
commit 5822328d9d
4 changed files with 648 additions and 393 deletions

113
webui/src/lib/Uplot.svelte Normal file
View File

@@ -0,0 +1,113 @@
<script lang="ts">
import 'uplot/dist/uPlot.min.css';
export let data_label = ""; // data label in legend
export let unit = ""; // unit in legend
export let last_for_seconds = 20; // Period of time [s] the data are shifted out on the left
let plotContainer;
let data = [];
data[0] = [Date.now()];
data[1] = [null];
const PRECISION = 1;
export async function create(legend_label, legend_unit, duration) {
console.log(legend_label);
console.log(legend_unit);
console.log(duration);
data_label = legend_label;
unit = legend_unit;
last_for_seconds = duration;
const uplotModule = await import('uplot');
const uPlot = uplotModule.default;
redraw(uPlot);
}
export async function add_data(new_data) {
data[0].push(Date.now());
data[1].push(new_data);
}
function redraw(uPlot) {
function getSize() {
let max_height = window.innerHeight;
let max_width = window.innerWidth;
let current_posY = plotContainer.getBoundingClientRect().top;
let height = Math.max(max_height - current_posY - 200, 250);
let width = Math.max(max_width - (2 * 50), 600);
return {
width: width,
height: height,
}
}
const opts = {
...getSize(),
ms: 1,
cursor: {drag: {setScale: false}},
points: {show: false},
pxSnap: false,
pxAlign: 0,
series: [
{
label: "time"
},
{
label: data_label,
stroke: "red",
paths: uPlot.paths.spline(),
value: (u, v, sidx, didx) => {
if (didx == null) {
let d = u.data[sidx];
v = d[d.length - 1];
}
let value = v;
if ( value != null) {
value = value.toFixed(PRECISION) + unit;
}
return value;
},
pxAlign: 0,
points: { show: false },
}
],
axes: [{grid: { show: false}}, {grid: { show: false}}],
// hooks are used here to filter out the time series from the legend
hooks: {
init: [
u => {
[...u.root.querySelectorAll('.u-legend .u-series')].forEach((el, i) => {
if (u.series[i].label ==="time") {
el.style.display = 'none';
}
});
}
]
}
};
let uplot = new uPlot(opts, data, plotContainer);
function update() {
const now = Date.now();
const scale = { min: now - (last_for_seconds * 1000), max: now };
// shift out data earlier than chart origin
let last = Date.now();
let first = last - (last_for_seconds * 1000);
while(data[0][0] < first) {
for(let i = 0; i < data.length; i++) {
data[i].shift();
}
}
uplot.setData(data, false);
uplot.setScale('x', scale);
uplot.setLegend({idx: data[0].length - 1}, false);
requestAnimationFrame(update);
}
requestAnimationFrame(update);
}
</script>
<div bind:this={plotContainer}></div>