Showing posts with label Socket.IO. Show all posts
Showing posts with label Socket.IO. Show all posts

Wednesday, September 3, 2014

Node.js Chat Server on RPi, send msg to Arduino Uno, display on LCD Module

This example combine the last post of "Node.js Chat application using socket.io, run on Raspberry Pi", and "Node.js send string to Arduino Uno" in my another blog for Arduino. To create a Chat server, and send the received messages to USB connected Arduino Uno board, then display on the equipped 2x16 LCD Module on Arduino.


In order to use serialport in Node.js to send message to serial port, enter the command on Raspberry Pi command line to install serialport.
$ npm install serialport

Modify index.js in last post to add handles for serialport.
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

var SerialPort = require("serialport").SerialPort
var serialPort = new SerialPort('/dev/ttyACM0', 
    {   baudrate: 9600
    });
    
serialPort.on("open", function () {
    console.log('open');
});

app.get('/', function(req, res){
  res.sendfile('index.html');
});

io.on('connection', function(socket){
  socket.on('chat message', function(msg){
    io.emit('chat message', msg);
    
    serialPort.write(msg, function(err, results) {
            console.log('err ' + err);
            console.log('results ' + results);
        });
    
  });
});

http.listen(3000, function(){
  console.log('listening on *:3000');
});

For the sketch on Arduino Uno, refer to the post "Read from Arduino Serial port, and write to 2x16 LCD".

Node.js Chat application using socket.io, run on Raspberry Pi

The tutorial Get Started: Chat application describe how to create a basic chat application on Node.js using socket.io.

This video show how I following the tutorial to do the job on Raspberry Pi:

The next post show how to send the received messages to USB connected Arduino Uno using serialport, and display on LCD Module.


Thursday, March 20, 2014

Node.js+socket.io+serialport = web app to control Pi connected Arduino

This is a example to implement a web app with Node.js running on Raspberry Pi, to receive command from client, and control connected Arduino Esplora's LED. All clients share a common hardware: when a client toggle the LED, all clients will be updated accordingly.


This example should be run on any other Node.js supported platform, with changing SerialPort name. The tablet is used to log-in Raspberry Pi to start the app, for demonstrate only, not a part of the example.

You have to install socket.io and serialport modules for Node.js:
$ npm install socket.io
$ npm install serialport

app.js
var app = require('http').createServer(handler), 
    io = require('socket.io').listen(app), 
    fs = require('fs'),
    os = require('os'),
    sp = require("serialport");
  
//init for SerialPort connected to Arduino
var SerialPort = sp.SerialPort
var serialPort = new SerialPort('/dev/ttyACM0', 
    {   baudrate: 9600,
        dataBits: 8,
        parity: 'none',
        stopBits: 1,
        flowControl: false
    });
    
serialPort.on("open", function () {
    console.log('serialPort open');
    serialPort.write("LEDOFF\n");
});
    
//Display my IP
var networkInterfaces=os.networkInterfaces();

for (var interface in networkInterfaces) {
    
    networkInterfaces[interface].forEach(
        function(details){
            
            if (details.family=='IPv4' 
                && details.internal==false) {
                    console.log(interface, details.address);  
        }
    });
}

//All clients have a common status
var commonStatus = 'ON';

app.listen(8080);

function handler (req, res) {
  fs.readFile(__dirname + '/index.html',
  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) {
    
    //Send client with his socket id
    socket.emit('your id', 
        { id: socket.id});
    
    //Info all clients a new client caaonnected
    io.sockets.emit('on connection', 
        { client: socket.id,
          clientCount: io.sockets.clients().length,
        });
        
    //Set the current common status to the new client
    socket.emit('ack button status', { status: commonStatus });
    
    socket.on('button update event', function (data) {
        console.log(data.status);
        
        //acknowledge with inverted status, 
        //to toggle button text in client
        if(data.status == 'ON'){
            console.log("ON->OFF");
            commonStatus = 'OFF';
            serialPort.write("LEDON\n");
        }else{
            console.log("OFF->ON");
            commonStatus = 'ON';
            serialPort.write("LEDOFF\n");
        }
        io.sockets.emit('ack button status', 
            { status: commonStatus,
              by: socket.id
            });
    });
    
    //Info all clients if this client disconnect
    socket.on('disconnect', function () {
        io.sockets.emit('on disconnect', 
            { client: socket.id,
              clientCount: io.sockets.clients().length-1,
            });
    });
});

index.html
<html>
<meta name="viewport" content="width=device-width, user-scalable=no">
<head></head>
<body>
<hi>Test Node.js with socket.io</hi>
<form action="">
<input type="button" id="buttonToggle" value="ON" style="color:blue"
       onclick="toggle(this);">
</form>
<script src="/https/helloraspberrypi.blogspot.com/socket.io/socket.io.js"></script>
<script>
var socket = io.connect(document.location.href);
var myId;

socket.on('on connection', function (data) {
    console.log("on connection: " + data.client);
    console.log("Number of client connected: " + data.clientCount);
});

socket.on('on disconnect',function(data) {
    console.log("on disconnect: " + data.client);
    console.log("Number of client connected: " + data.clientCount);
});

socket.on('your id',function(data) {
    console.log("your id: " + data.id);
    myId = data.id;
});

socket.on('ack button status', function (data) {
    console.log("status: " + data.status);
    
    if(myId==data.by){
        console.log("by YOU");
    }else{
        console.log("by: " + data.by);
    }
    
    if(data.status =='ON'){
        document.getElementById("buttonToggle").value="ON";
    }else{
        document.getElementById("buttonToggle").value="OFF";
    }
});

function toggle(button)
{
 if(document.getElementById("buttonToggle").value=="OFF"){
  socket.emit('button update event', { status: 'OFF' });
 }
 else if(document.getElementById("buttonToggle").value=="ON"){
  socket.emit('button update event', { status: 'ON' });
 }
}
</script>

</body>
</html>

Arduino code
#include <Esplora.h>
#include <TFT.h>
#include <SPI.h>

int MAX_CMD_LENGTH = 10;
char cmd[10];
int cmdIndex;
char incomingByte;

void setup() {
  
    EsploraTFT.begin();  
    EsploraTFT.background(0,0,0);
    EsploraTFT.stroke(255,255,255);  //preset stroke color
     
    //Setup Serial Port with baud rate of 9600
    Serial.begin(9600);
    
    //indicate start
    Esplora.writeRGB(255, 255, 255);
    delay(250);
    Esplora.writeRGB(0, 0, 0);
    
    cmdIndex = 0;
    
}
 
void loop() {
    
    if (incomingByte=Serial.available()>0) {
      
      char byteIn = Serial.read();
      cmd[cmdIndex] = byteIn;
      
      if(byteIn=='\n'){
        //command finished
        cmd[cmdIndex] = '\0';
        Serial.println(cmd);
        cmdIndex = 0;
        
        if(strcmp(cmd, "LEDON")  == 0){
          Serial.println("Command received: LEDON");
          Esplora.writeRGB(255, 255, 255);
        }else if (strcmp(cmd, "LEDOFF")  == 0) {
          Serial.println("Command received: LEDOFF");
          Esplora.writeRGB(0, 0, 0);
        }else{
          Serial.println("Command received: unknown!");
        }
        
      }else{
        if(cmdIndex++ >= MAX_CMD_LENGTH){
          cmdIndex = 0;
        }
      }
    }
    
}

Cross post with Arduino-er

Next: Bi-directional control between Raspberry Pi + Node.js + Arduino

Sunday, March 16, 2014

Node.js + Socket.IO: share common status for all clients

Last post have individual status for each client. In this example, all client share one common status, that means client A click to change status, not only his button text will change, but also all other clients will change.


In this example:
  • All clients share a common status, commonStatus.
  • Will info new client his id, socket.id.
  • Server will broadcast all clients if any new client connected, io.sockets.emit(). Also info the number of client connected, io.sockets.clients().length.
  • Info the current common status to new connected client.
  • Info all clients if a client disconnected, socket.on('disconnect', function).
app.js
//$ npm install socket.io

var app = require('http').createServer(handler)
  , io = require('socket.io').listen(app)
  , fs = require('fs')

//All clients have a common status
var commonStatus = 'ON';

app.listen(8080);

function handler (req, res) {
  fs.readFile(__dirname + '/index.html',
  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) {
    
    //Send client with his socket id
    socket.emit('your id', 
        { id: socket.id});
    
    //Info all clients a new client caaonnected
    io.sockets.emit('on connection', 
        { client: socket.id,
          clientCount: io.sockets.clients().length,
        });
        
    //Set the current common status to the new client
    socket.emit('ack button status', { status: commonStatus });
    
    socket.on('button update event', function (data) {
        console.log(data.status);
        
        //acknowledge with inverted status, 
        //to toggle button text in client
        if(data.status == 'ON'){
            console.log("ON->OFF");
            commonStatus = 'OFF';
            
        }else{
            console.log("OFF->ON");
            commonStatus = 'ON';
        }
        io.sockets.emit('ack button status', 
            { status: commonStatus,
              by: socket.id
            });
    });
    
    //Info all clients if this client disconnect
    socket.on('disconnect', function () {
        io.sockets.emit('on disconnect', 
            { client: socket.id,
              clientCount: io.sockets.clients().length-1,
            });
    });
});

index.html
<html>
<head></head>
<body>
<hi>Test Node.js with socket.io</hi>
<form action="">
<input type="button" id="buttonToggle" value="ON" style="color:blue"
       onclick="toggle(this);">
</form>
<script src="/https/helloraspberrypi.blogspot.com/socket.io/socket.io.js"></script>
<script>
var socket = io.connect(document.location.href);
var myId;

socket.on('on connection', function (data) {
    console.log("on connection: " + data.client);
    console.log("Number of client connected: " + data.clientCount);
});

socket.on('on disconnect',function(data) {
    console.log("on disconnect: " + data.client);
    console.log("Number of client connected: " + data.clientCount);
});

socket.on('your id',function(data) {
    console.log("your id: " + data.id);
    myId = data.id;
});

socket.on('ack button status', function (data) {
    console.log("status: " + data.status);
    
    if(myId==data.by){
        console.log("by YOU");
    }else{
        console.log("by: " + data.by);
    }
    
    if(data.status =='ON'){
        document.getElementById("buttonToggle").value="ON";
    }else{
        document.getElementById("buttonToggle").value="OFF";
    }
});

function toggle(button)
{
 if(document.getElementById("buttonToggle").value=="OFF"){
  socket.emit('button update event', { status: 'OFF' });
 }
 else if(document.getElementById("buttonToggle").value=="ON"){
  socket.emit('button update event', { status: 'ON' });
 }
}
</script>

</body>
</html>

Node.js + Socket.IO: acknowledge from server

Last example send button status to server from client, and toggle button status in client side without acknowledge from server. It is modified to send back acknowledge from server with inverted status, and update button status in client once acknowledge received.


app.js
//$ npm install socket.io

var app = require('http').createServer(handler)
  , io = require('socket.io').listen(app)
  , fs = require('fs')

app.listen(8080);

function handler (req, res) {
  fs.readFile(__dirname + '/index.html',
  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) {
    socket.on('button update event', function (data) {
        console.log(data.status);
        
        //acknowledge with inverted status, 
        //to toggle button text in client
        if(data.status == 'ON'){
            console.log("ON->OFF");
            socket.emit('ack button status', { status: 'OFF' });
        }else{
            console.log("OFF->ON");
            socket.emit('ack button status', { status: 'ON' });
        }
                    
        
    });
});

index.html
<html>
<head></head>
<body>
<hi>Test Node.js with socket.io</hi>
<form action="">
<input type="button" id="buttonToggle" value="ON" style="color:blue"
       onclick="toggle(this);">
</form>
<script src="/https/helloraspberrypi.blogspot.com/socket.io/socket.io.js"></script>
<script>
var socket = io.connect(document.location.href);

socket.on('ack button status', function (data) {
    console.log(data.status);
    if(data.status =='ON'){
        document.getElementById("buttonToggle").value="ON";
    }else{
        document.getElementById("buttonToggle").value="OFF";
    }
});

function toggle(button)
{
 if(document.getElementById("buttonToggle").value=="OFF"){
  socket.emit('button update event', { status: 'OFF' });
 }
 else if(document.getElementById("buttonToggle").value=="ON"){
  socket.emit('button update event', { status: 'ON' });
 }
}
</script>

</body>
</html>

Next: Share common status for all clients

Node.js app using Socket.IO

Socket.IO aims to make realtime apps possible in every browser and mobile device, blurring the differences between the different transport mechanisms. It's care-free realtime 100% in JavaScript.

This example create a simple web app to receive the status of a toggle button from client.


Before using Socket.IO on your Node.js app, run the command to install:
$ npm install socket.io

app.js run in server side:
//$ npm install socket.io

var app = require('http').createServer(handler)
  , io = require('socket.io').listen(app)
  , fs = require('fs')

app.listen(8080);

function handler (req, res) {
  fs.readFile(__dirname + '/index.html',
  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) {
  socket.on('button update event', function (data) {
    console.log(data.status);
  });
});

index.html, it will be sent to and run on client side.
<html>
<head></head>
<body>
<hi>Test Node.js with socket.io</hi>
<form action="">
<input type="button" id="buttonToggle" value="ON" style="color:blue"
       onclick="toggle(this);">
</form>
<script src="/https/helloraspberrypi.blogspot.com/socket.io/socket.io.js"></script>
<script>
var socket = io.connect(document.location.href);

function toggle(button)
{
 if(document.getElementById("buttonToggle").value=="OFF"){
  document.getElementById("buttonToggle").value="ON";
  socket.emit('button update event', { status: 'OFF' });
 }
 else if(document.getElementById("buttonToggle").value=="ON"){
  document.getElementById("buttonToggle").value="OFF";
  socket.emit('button update event', { status: 'ON' });
 }
}
</script>

</body>
</html>

Run the app.js in server:
$ node app

Visit <server IP>:8080 with browser in client side.


Next: Acknowledge from server