Integrating sensor data into our charts

The goal of this section is to have our sensor data reflect in our charts. We know that readings are measured every two seconds. This means that we will also have to update our charts every two seconds. This is a slightly different situation when compared to the sample chart we created earlier because there are some assumptions that we didn't consider:

  • The constant readings from the sensor require that our chart be dynamic. The values plotted have to change every time a new reading comes.
  • We must choose a sensible scale. Our sample chart had values from 12 to 23. In the real world, temperature and humidity readings rarely change that often or that drastically, especially when we are measuring on a per-second timescale.

Fortunately, the Chart.js library has features to take care of both of these new findings. Let's modify our code to have a more sensible range for our temperature and humidity values and to dynamically inject readings as and when they are received.

First, we create a generic function, which accepts an array, a value, and a maximum length. Its job is to make sure we have a set of readings with a fixed length. If a new reading comes in, the oldest reading in this set is pushed out, such as a fixed length queue:

    const pushData = (arr, value, maxLen) => {
/*
Push the new value into the array
*/

arr.push(value)

/*
If the length of the array is greater than the maximum
length allowed, push the first element out (through the
Array#shift method)
*/

if (arr.length > maxLen) {
arr.shift()
}
}
Remember, arrays and objects in JavaScript are passed by reference. So, any time we call this function with an array, that array is being directly modified by it.

Next, we change the chart configuration to take care of the range:

    /*
Here, we take the configuration out and declare it as a
variable first.
*/

const temperatureChartConfig = {
type: 'line',
data: {
/*
For our actual data, we will not have any readings
initially
*/

labels: [],
datasets: [{
data: [],
backgroundColor: 'rgba(255, 205, 210, 0.5)'
}]
},
options: {
legend: {
display: false
},
responsive: true,
maintainAspectRatio: false,
/*
Add in the range for the Y-axis. Where I live, the
temperature varies from 15-35 °C
With a 5 °C buffer range, that gives us a minimum
value of 10 and maximum of 40
*/

scales: {
yAxes: [{
ticks: {
suggestedMin: 10,
suggestedMax: 40
}
}]
}
}
}

We are using the suggestedMin and suggestedMax properties in our Chart.js configuration. Like the naming suggests, these maximum and minimum values are only suggested and not hard fixed. What this means is that Chart.js will maintain this range, but if by some miracle the temperature goes above or below the suggested limits, the chart will change its minimum or maximum range values to fit the extreme values of our readings. This will happen rarely, if ever, but it's good to prepare for the outlier cases as well.

The callback code from the API call is now modified to inject every new sensor reading into the chart dataset:

    const fetchTemperature = () => {
fetch('/temperature')
.then(results => {
return results.json()
})
.then(data => {
/*
Note the time when the reading is obtained,
and convert it to hh:mm:ss format
*/

const now = new Date()
const timeNow = now.getHours() + ':' +
now.getMinutes() + ':' + now.getSeconds()

/*
Add the data to the chart dataset

The x-axis here is time, with the time of
measurement added as its value. Since it is measure in
regular intervals,
we do not need to scale it, and can assume a
uniform regular interval
The y-axis is temperature, which is stored in
`data.value`

The data is being pushed directly into the
configuration we described above.
A maximum length of 10 is maintained. Which means
that after 10 readings are filled in the dataset, the
older readings will start being pushed out.
*/

pushData(temperatureChartConfig.data.labels,
timeNow, 10)
pushData(temperatureChartConfig.data.datasets[0]
.data, data.value, 10)

/*
`temperatureChart` is our ChartJs instance. The
`update` method looks for changes in the dataset and
axes, and animates and updates the chart accordingly.
*/

temperatureChart.update()
const temperatureDisplay =
document.getElementById('temperature-display')
temperatureDisplay.innerHTML = '<strong>' +
data.value + '</strong>'
})
}

The same logic is repeated for our humidity API.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.104.214