IoT - Kubus
/
Kubus
JNP3 16/17
frontend/kubus.js
- Committer:
- Micha? ?azowik
- Date:
- 2017-01-09
- Revision:
- 25:4fd33808f095
- Parent:
- 24:a929fcdb1208
- Child:
- 26:52e8eee05dc6
File content as of revision 25:4fd33808f095:
Chart.defaults.global.defaultFontFamily = "triplicate, Courier, 'Courier New', monospace"; Chart.defaults.global.defaultFontSize = 15; Chart.defaults.global.defaultFontColor = "#efefef"; const UPDATE_INTERVAL_SECONDS = 5; const KEEP_DATA_POINTS = 10; class Charts { constructor(containerId) { this.container = document.getElementById(containerId); this.charts = {}; } addSensorData(sensors) { for (let sensor of sensors) { if (!(sensor.name in this.charts)) { this._addChart(SensorChartFactory.create(sensor)); } this.charts[sensor.name].addDataPoint({ x: new Date(), y: sensor.value }); } } _addChart(chart) { this.charts[chart.getName()] = chart; this._addToContainer(chart); } _addToContainer(chart) { const chartContainer = this._createChartContainer(); const title = this._createChartTitle(chart.getName()); chartContainer.appendChild(title); chartContainer.appendChild(chart.getCanvas()); this.container.appendChild(chartContainer); chart.render(); } _createChartContainer() { const chartContainer = document.createElement("div"); chartContainer.classList.add('chart'); return chartContainer; } _createChartTitle(name) { const title = document.createElement("h2"); title.innerHTML = name; title.classList.add('chart__title'); return title; } } class SensorChart { constructor(name) { this.canvas = document.createElement("canvas"); this.canvas.height = "70"; this.name = name; this.dataSize = 0; } getCanvas() { return this.canvas; } getName() { return this.name; } render() { throw Error("Not implemented"); } addDataPoint(dataPoint) { this.chart.data.datasets[0].data.push(dataPoint); this.dataSize++; if (this.dataSize > KEEP_DATA_POINTS) { this.chart.data.datasets[0].data.shift(); this.dataSize--; } this.chart.update(); } _getConfig(data) { return { type: 'line', data: { datasets: [ { label: this.name, data: data, backgroundColor: "rgba(75, 192, 192, 0.1)", borderColor: "rgba(75, 192, 192, 1)" } ] }, options: { scales: { xAxes: [{ type: 'time', position: 'bottom', time: { unit: 'second', unitStepSize: UPDATE_INTERVAL_SECONDS } }], yAxes: [{ display: true, ticks: { max: 100, min: 0 }, scaleLabel: { display: false, labelString: "" } }] }, legend: { display: false } } } } } class NumberChart extends SensorChart { constructor(name, options) { super(name); this.range = options.range; this.unit = options.unit; } render() { this.chart = new Chart(this.canvas, this._getConfig([])); } _getConfig(data) { const config = super._getConfig(data); config.options.scales.yAxes[0].ticks.max = this.range[1]; config.options.scales.yAxes[0].ticks.min = this.range[0]; config.options.scales.yAxes[0].scaleLabel.display = true; config.options.scales.yAxes[0].scaleLabel.labelString = this.unit; return config; } } class BoolChart extends SensorChart { render() { this.chart = new Chart(this.canvas, this._getConfig([])); } _getConfig(data) { const config = super._getConfig(data); config.data.datasets[0].steppedLine = true; config.options.scales.yAxes[0].ticks.max = 1; config.options.scales.yAxes[0].ticks.min = 0; return config; } } class SensorChartFactory { static create(sensor) { switch (sensor.type) { case "number": return new NumberChart(sensor.name, { range: sensor.range, unit: sensor.unit }); break; case "bool": return new BoolChart(sensor.name); break; default: throw Error(`Sensor type ${sensor.type} not supported`); } } } const sensorCharts = new Charts("charts"); function fakeUpdate() { sensorCharts.addSensorData([ { name: "Distance at the entrance", type: "number", range: [0, 90], unit: "cm", value: Math.random() * 90, }, { name: "Motion at the stairway", type: "bool", value: Math.random() >= 0.5 } ]); setTimeout(fakeUpdate, UPDATE_INTERVAL_SECONDS * 1000); } function update() { fetch("/api/sensors") .then((response) => { return response.json(); }) .then((json) => { sensorCharts.addSensorData(json); }); setTimeout(update, UPDATE_INTERVAL_SECONDS * 1000); } const query = window.location.search.substring(1); if (query === "fake") { fakeUpdate(); } else { update(); }