Series y gráficas
This content is not available in your language yet.
Una serie es una lista de valores con marcas de tiempo. Desde un
artefacto se alimenta con pushData y se grafica con plotSerie.
pushData: agregar un dato
Sección titulada «pushData: agregar un dato»pushData("temperaturas", 23.5);pushData agrega el valor y su marca de tiempo (el reloj del navegador en ese
instante), manteniendo alineadas temperaturas y temperaturas_time. Es el único
camino correcto para alimentar una serie desde un artefacto.
El caso típico es registrar algo que hace el usuario:
document.querySelector("#btn").addEventListener("click", () => pushData("eventos", 1));Reiniciar una serie
Sección titulada «Reiniciar una serie»gVar.temperaturas = []; // borra valores y tiemposEs la única asignación de arreglo permitida sobre una serie. Asignar un arreglo con
valores lanza TypeError.
El rol de escritura
Sección titulada «El rol de escritura»Varias pestañas del mismo artefacto pueden estar abiertas a la vez, y dos flujos de
pushData sobre la misma serie la desordenarían. Por eso las operaciones de serie
(pushData y el reinicio) necesitan un rol de escritura por variable:
- El runtime lo pide solo, la primera vez que tu código toca esa serie.
- Si otra pestaña lo tiene, tu
pushDataavisa porconsole.warny no escribe. - Puedes tomarlo a la fuerza:
await requestWriter("temperaturas", { force: true }). - Puedes soltarlo:
await releaseWriter("temperaturas").
Ambas funciones devuelven una promesa con true o false. El estado vive en
gVarStatus.writer:
gVarStatus.writer.keys; // series que controlo yogVarStatus.writer.forced; // ...tomadas a la fuerzagVarStatus.writer.claimed; // todas las series con dueño ahora mismoLos escalares no usan rol: la última escritura gana.
plotSerie: puntos listos para graficar
Sección titulada «plotSerie: puntos listos para graficar»const proj = plotSerie("temperaturas", { maxPoints: 100, // cuántos puntos recientes incluir (def. 100) timeMode: "clock", // cómo construir el eje X});
// proj.points = [{ x: 0, label: "12:30:01", y: 23.5 }, { x: 1, label: "12:30:02", y: 23.6 }, ...]plotSerie es síncrona y devuelve null si la serie no tiene datos: comprueba eso
antes de dibujar. Además de points, devuelve values, timestamps,
originTimestamp, totalLength, hasTimestamps y timeMode.
Cada punto tiene tres campos:
x— índice dentro de la ventana proyectada (0, 1, 2…): posición equiespaciada.label— string para el eje X (segúntimeMode:"12:30:01","1.5","0"…).y— valor numérico, onullsi el valor no es numérico.
Modos de tiempo (timeMode)
Sección titulada «Modos de tiempo (timeMode)»| Modo | Eje X |
|---|---|
clock | Hora del reloj ("12:30:01"). |
relative-ms | Milisegundos desde el inicio de la serie. |
relative-seconds | Segundos desde el inicio. |
relative-minutes | Minutos desde el inicio. |
Una gráfica en vivo
Sección titulada «Una gráfica en vivo»No hay callbacks de actualización: se proyecta y se dibuja en el mismo intervalo con el que la plataforma sincroniza.
function dibujar(labels, data) { // entrega labels (eje X) y data (valores) a tu librería o canvas}
setInterval(() => { const proj = plotSerie("temperaturas", { maxPoints: 100, timeMode: "clock" }); if (!proj) return; const labels = proj.points.map((p) => p.label); // "12:30:01", "12:30:02"... const data = proj.points.map((p) => p.y); // 23.5, 23.6... dibujar(labels, data);}, 500);Con Chart.js, actualiza sin animación para que no parpadee:
setInterval(() => { const proj = plotSerie("temperaturas", { maxPoints: 100, timeMode: "clock" }); if (!proj) return; miChart.data.labels = proj.points.map((p) => p.label); miChart.data.datasets[0].data = proj.points.map((p) => p.y); miChart.update("none");}, 500);