Add data plot to sauna route
Signed-off-by: Thomas Klaehn <thomas.klaehn@perinet.io>
This commit is contained in:
113
webui/src/lib/Uplot.svelte
Normal file
113
webui/src/lib/Uplot.svelte
Normal 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>
|
Reference in New Issue
Block a user