1

I am trying to use socket.io to transfer data from a node.js script to an HTML webpage. The node.js script is executing a function (that uses a BeagleBone Black sensor) and returning a certain value. I want to transfer this value via a socket to the HTML page. I then want the HTML page to display this value. I have been able to get the webpage to log everything on Chrome's Javascript console. I don't understand though why the data is not being printed on the actual page.

// Install socket.io: terminal, goto /var/lib/cloud9 and enter: npm install socket.io

var app = require('http').createServer(handler);

var io = require('socket.io').listen(app);

var fs = require('fs');

var b = require('bonescript');

var fulldata = 0;
// count how many pulses
var pulses = 0;
// track the state of the pulse pin
var lastflowpinstate;
//time between pulses
var lastflowratetimer = 0;
// used to calculate a flow rate
var flowrate;
// Interrupt is called once a millisecond, looks for any pulses 
var value = 0;

var liters = 0;


app.listen(8090);

/* socket.io options go here

io.set('log level', 2);   // reduce logging - set 1 for warn, 2 for info, 3 for debug

io.set('browser client minification', true);  // send minified client

io.set('browser client etag', true);  // apply etag caching logic based on version number
*/

console.log('Server running on: http://' + getIPAddress() + ':8090');

var Sensor = "P8_19";
b.pinMode('P8_19', b.INPUT);
console.log(b.digitalRead('P8_19'));

function handler (req, res) {

  if (req.url == "/favicon.ico"){   // handle requests for favico.ico

  res.writeHead(200, {'Content-Type': 'image/x-icon'} );

  res.end();

  //console.log('favicon requested');

  return;

  }

  fs.readFile('SensorHTML.html',    // load html file

  function (err, data) {

    if (err) {

      res.writeHead(500);

      return res.end('Error loading index.html');

    }

    res.writeHead(200);

    res.end(data);

  });

}



io.sockets.on('connection', function(socket) {

    setInterval(function() {

            //doSomething();
            b.pinMode('P8_19', b.INPUT);
            value = b.digitalRead('P8_19');

            if (value == lastflowpinstate) 
            {
            lastflowratetimer++;
            //return; // nothing changed!
            }

            if (value == '1') 
            {
               //low to high transition!
               pulses++;
            }

            lastflowpinstate = value;
            flowrate = 1000.0;
            flowrate /= lastflowratetimer;  // in hertz
            lastflowratetimer = 0;

            liters = pulses / (450);
            fulldata += liters;
            JSON.stringify(fulldata);
            //send temperature reading out to connected clients
            socket.emit('water', {'water': fulldata});

    }, 500);

    //function doSomething() {

 });

  // Get server IP address on LAN
  function getIPAddress() {

  var interfaces = require('os').networkInterfaces();

  for (var devName in interfaces) {

    var iface = interfaces[devName];

    for (var i = 0; i < iface.length; i++) {

      var alias = iface[i];

      if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal)

        return alias.address;

    }

  }

  return '0.0.0.0';
}

And the HTML file:

<html>
<head>
 <!-- include bootstrap, jquery for easy div manipulation -->
 <script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
 <link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
 <script src="node_modules/socket.io-client/dist/socket.io.min.js"></script>
 <script src="/socket.io/socket.io.js"></script>
 </head>
 <body>
 <h1>SmartWater</h1>
 <th>Flow (liters)</th>
 <script>

 var socket = io.connect('http://192.168.7.2:8090/');  //enter the IP of your beaglebone and port you are using in app.js

 socket.on('water', function(data) {
 //$('#').html(data.full_data);
    $('#water').html(data.fulldata);
    console.log(data.fulldata);
 });

</script>
<div id="water"></div>
</body>
</html>

Any help or insight would be appreciated.

7
  • 1
    What version of socket.io are you running? The latest socket.io doc shows io.on('connection', function() {...}), not io.sockets.on('connection', function () {...}); Commented May 18, 2015 at 0:00
  • FYI, you also need to listen for the disconnect event because otherwise your setInterval() goes forever even on closed sockets. You will need to stop the interval timer when the socket is closed. Commented May 18, 2015 at 0:02
  • Thanks for the tip, I must have overlooked it. I fixed that though, but I still get no output on the webpage, although the console does get data. Commented May 18, 2015 at 0:06
  • What do you mean the "console does get data"? What shows in the server console? On the client console? Commented May 18, 2015 at 0:09
  • Also, FYI you should not be calling JSON.stringify(fulldata). Remove that line. Commented May 18, 2015 at 0:11

2 Answers 2

2

In the client, change:

$('#water').html(data.fulldata);
console.log(data.fulldata);

to this:

$('#water').html(data.water);
console.log(data.water);

The property name you're setting on the server is water, not fulldata.


Also, on the server, remove this line:

JSON.stringify(fulldata)

There is no need to stringify a single number that is just being passed as a property on an object. In fact, it will probably cause a problem for you.


On the server, you will also need to save the timer from the call to setInterval() so you can clearInterval() when the socket is disconnected. I would suggest storing the interval timer handle as a custom property on the socket object itself as that will make it easier to access in the 'disconnect' event.

Here's an example of how to do that:

io.on('connection', function(socket) {

    var tm = setInterval(function() {

            //doSomething();
            b.pinMode('P8_19', b.INPUT);
            value = b.digitalRead('P8_19');

            if (value == lastflowpinstate) 
            {
            lastflowratetimer++;
            //return; // nothing changed!
            }

            if (value == '1') 
            {
               //low to high transition!
               pulses++;
            }

            lastflowpinstate = value;
            flowrate = 1000.0;
            flowrate /= lastflowratetimer;  // in hertz
            lastflowratetimer = 0;

            liters = pulses / (450);
            fulldata += liters;
            //send temperature reading out to connected clients
            socket.emit('water', {'water': fulldata});

    }, 500);

    socket.on('disconnect', function() {
        clearInterval(tm);
    });

    //function doSomething() {

 });
Sign up to request clarification or add additional context in comments.

3 Comments

@LockX - see the comments I added about the disconnect event too.
Thank you very much for the tip. I modified my server code, and I wanted to know if there was any way to test if it actually turns off the timer.
@LockX - Put a console.log("running interval timer") inside the timer callback and see if it keeps outputting or not.
0

Thanks for the tip (about turning off the timer). I made some edits in the server code, but I'm not sure if they're correct.

    io.on('connection', function(socket) {

            function to_start()
            {
                tm=window.setInterval('timer()', 500);
            }

            to_start();

            function timer()
            {
               ....
            }

            socket.on('disconnect', function () {
                window.clearInterval(tm);
            });

 });

1 Comment

See my answer for a way to do this. You have to make sure the tm variable has the right scope so it ONLY applies to this particular socket and so each separate socket has it's own tm variable. Also, this should not be posted as an answer to your question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.