user2870492 user2870492 - 1 year ago 66
Node.js Question

Repeated calling a function embedded in an init function

Noobish here.

I am building a raspberry pi project to measure the depth of a water tank every 5mins. I have placed an ultrasonic distance measure in the tank and have got everything running using node and the r-pi-usonic library. I can make an initial call to the ultrasonic device to create an average of 10 individual measures (because of the variability in individual measures) and log that to the console.

But what I want to do is repeat this every 5mins. I initially tried to do this by setting a setInterval(), and have tried using cron. But as the query loop is tied up in the init function, it throws the following error...

callback.apply(this, args);
TypeError: Cannot read property 'apply' of undefined
at wrapper [as _onTimeout] (timers.js:274:13)
at Timer.listOnTimeout (timers.js:119:15)

So my question is really what is the best way to get this to run the query every 5mins? The answer will no doubt help my understanding of callbacks etc.. Sorry for being such a dunce!

My code is here, apologies for its crapness!

//Import required modules

var usonic = require('r-pi-usonic');
console.log('starting water tank monitor');
var min_tank = 30
var max_tank = 90
var tank_percent = 0

usonic.init(function (error) {
if (error) {
} else {
var sensor = usonic.createSensor(13, 21, 1000);
var i = 0
var values = 0
function myLoop (){
setTimeout(function () {
var v = sensor().toFixed(2) ;
values = values+parseFloat(v);
if (i < 10) {
} else {
value = (values/10).toFixed(2)
tank_percent = 100 -((value - min_tank )/ (max_tank - min_tank) * 100)
i = 0;
values = 0;
}, 500)
setInterval (myLoop(), 30000);

Answer Source

My eyes bleed when I see (a joke):

setInterval (myLoop(), 30000);

Notice how you're calling myLoop in setInterval. With that current way, you call myLoop() instantly and just once. You should instead be giving the reference to your myLoop function.

setInterval (myLoop, 30000);

Once you've used setInterval correctly, you won't have to use your setTimeout within your myLoop since setInterval is asynchronous..