1

I'm trying to send a packet from my server to ping a client every few seconds in an infinite loop at all times.

This is the code I am running:

const dgram = require('dgram');
const message = Buffer.from('Some bytes');
const clientPing = dgram.createSocket('udp4');

const pinging = true;

function ping() {
  clientPing.send("Hi Uno", 8888, 'XXX.XX.XX.XXX', (err) => {
    clientPing.close();
  });
}

function sleep(time, callback) {
    var stop = new Date().getTime();
    while(new Date().getTime() < stop + time) {
        ;
    }
    callback();
}

function loop() {
  while(pinging == true) {
    sleep(3000, function() {
      ping();
      console.log('ping');
    });
  }
}

loop();

What's weird is that the console logs the string ping just fine at the given interval but the packet is never sent and never reaches my client. But when I run just ping(); outside of the loop the packet hits the client.

Udp isn't supposed to wait for a response after it sends the packet and doesn't wait for a response. What am I missing here?

AustinFoss
  • 385
  • 5
  • 13
  • 2
    You're blocking the event queue completely. Don't sleep synchronously. – tkausl Nov 22 '18 at 02:47
  • I'm not sure what you mean. How would you loop this? I've tried it with `setTimeout(() => { ping(); }, 3000);` and the loop seems to run without waiting for the timeout to end. – AustinFoss Nov 22 '18 at 02:50
  • node.js runs your Javascript single threaded. So, while you're in `sleep()` NOTHING else can get processed by your Javascript. Nothing. Thus, the value of `pinging` can never change unless it happens directly inside the `while` loop. No other events will ever get processed. This type of question has been covered multiple times here. – jfriend00 Nov 22 '18 at 03:30

2 Answers2

1

As @tkausl says, you're blocking the event loop. Don't use that sleep() function. Try something like this instead:

function loop() {
  if (!pinging) {
    return;
  }
  ping();
  console.log('ping');
  setTimeout(loop, 3000);
}

loop();
Brad
  • 159,648
  • 54
  • 349
  • 530
  • I first had to comment out `clientPing.close();` in order to get your code looping properly. Forgot to get rid of that from just the standalone file. Even after doing so though I was only seeing the console log the the ping but not see the packet reach my client. Though I think I found another method I answer below. – AustinFoss Nov 22 '18 at 03:23
0

So I finally got it behave properly using this:

function loop() {

  setInterval(() => {
    clientPing.send("Hi Uno", 8888, 'XXX.XX.XX.XXX', (err) => {
    });
  }, 5000);

}

loop();

So now the Pi running this pings my arduino client successfully every 5s, the arduino then replies with temp and humidity data, the Pi server then catches it and pushes that to mongo.

AustinFoss
  • 385
  • 5
  • 13
  • There's no point in `loop` in this case. Just use `setInterval` directly. – Brad Nov 22 '18 at 03:31
  • I wanted to use it as an export from this module that my server file can import. So I did `const loop = funtcion() { setInterval(() => {}, 3000); }` in the end. – AustinFoss Nov 22 '18 at 03:39