node.jsraspberry-pi3mpu6050

Data not sending data over socket in loop


I'm trying to send sensor information from instance of NodeJs to another(eventually on another server). When the while loop in the client code below is enable no connection or data is sent to the server. However when the while loop is commented out I get a connection and data. It's only a single object of data but that's expected when not pulling the sensor data in a loop.

Server Code:

'use strict';
const net = require('net');
const PORT = 5000;
const ADDRESS = '127.0.0.1';

let server = net.createServer(onClientConnected);
server.listen(PORT, ADDRESS);

function onClientConnected(socket) {
    console.log(`New client: ${socket.remoteAddress}:${socket.remotePort}`);
    socket.destroy();
}

console.log(`Server started at: ${ADDRESS}:${PORT}`);

function onClientConnected(socket) {
    let clientName = `${socket.remoteAddress}:${socket.remotePort}`;
    console.log(`${clientName} connected.`);
    socket.on('data', (data) => {
    let m = data.toString().replace(/[\n\r]*$/, '');
    var d = {msg:{info:m}};
    console.log(`${clientName} said: ${data.toString()}`);
    socket.write(`We got your message (${m}). Thanks!\n`);
});

socket.on('end', () => {
    console.log(`${clientName} disconnected.`);
});

Client Code:

var n = require('net');
var s = n.Socket();
s.connect(5000, 'localhost');
var i2c = require('i2c-bus');
var MPU6050 = require('i2c-mpu6050');

var address = 0x68;
var i2cl = i2c.openSync(1);
var sensor = new MPU6050(i2cl, address);

//while (true) {
    var data = sensor.readSync();
    console.log(data);
    s.write(data.toString());
//}

Solution

  • Node's main event loop is single threaded so only a single thing is executing at any one time. A particular thread won't relinquish control back to the event loop to continue processing more events until it's finished. Socket.write doesn't actually write to the socket when it's called; instead it creates a task in the event loop queue. The while loop causes the current thread to never exit and effectively blocks the event loop, so the subsequent socket write events are never processed.

    Replacing your client code with this should work and achieve effectively what you're trying to do:

    var n = require('net');
    var s = n.Socket();
    s.connect(5000, 'localhost');
    var i2c = require('i2c-bus');
    var MPU6050 = require('i2c-mpu6050');
    
    var address = 0x68;
    var i2cl = i2c.openSync(1);
    var sensor = new MPU6050(i2cl, address);
    
    const readData = () => {
        var data = sensor.readSync();
        console.log(data);
        s.write(data.toString());
        setImmediate(readData);
    }
    
    readData();
    

    setImmediate says to execute the function AFTER any other events have processed, in this case it will be the event from Socket.write. The Socket.write function also provides a callback that is called once the data is done writing to the socket.