Você está na página 1de 17

node.js, socket.

io, and real-time web HMI example | Chris Larson

http://chrislarson.me/blog/nodejs-socketio-and-real-time-web-h...

between the cloud and the machine node.js, socket.io, and real-time web HMI example
Submitted by Chris Larson on Mon, 01/14/2013 - 11:18

(http://d3ttanjlcux1mo.cloudfront.net/sites/chrislarson.me/files/screenshot_0.png)

Using node.js, socket.io, and express I created a simple real-time HMI for controlling valves. This method can be used to control any device including a network connected arduino or raspberry pi, local USB connected IO boards, or any other device that can communicate with web sockets. In this simple web based HMI clients connect and enter their name. Clients are then allowed to send and receive chat messages or press the open and close buttons associated with each

1 of 17

12/24/13, 12:55 PM

node.js, socket.io, and real-time web HMI example | Chris Larson

http://chrislarson.me/blog/nodejs-socketio-and-real-time-web-h...

valve. Security and access restrictions were not used here, but could be added later. Before running the example install the latest version of node.js, socket.io and express. (/content/chris-larson/beginners-guide-nodejs-socketio-and-express-framework-installation) The node.js app is similar to the chat example (http://chrislarson.me/content/chris-larson
/beginners-guide-nodejs-socketio-and-express-framework-first-application)

, with the addition of

two functions that listen for close and open commands.

node.js application
var app = require('express')() , server = require('http').createServer(app) , io = require('socket.io').listen(server); server.listen(8080); // routing app.get('/', function (req, res) { res.sendfile(__dirname + '/index.html'); }); app.get('/app.css', function (req, res) { res.sendfile(__dirname + '/app.css'); }); // usernames which are currently connected to the chat var usernames = {}; io.sockets.on('connection', function (socket) { // when the client emits 'sendchat', this listens and executes

2 of 17

12/24/13, 12:55 PM

node.js, socket.io, and real-time web HMI example | Chris Larson

http://chrislarson.me/blog/nodejs-socketio-and-real-time-web-h...

socket.on('sendchat', function (data) { // we tell the client to execute 'updatechat' with 2 parameters io.sockets.emit('updatechat', socket.username, data); }); // when the client emits 'opencmd', this listens and executes socket.on('opencmd', function (data) { // Add calls to IO here io.sockets.emit('opencmd', socket.username, data); setTimeout(function () { io.sockets.emit('openvalve', socket.username, data); }, 1000) }); // when the client emits 'closecmd', this listens and executes socket.on('closecmd', function (data) { // Add calls to IO here io.sockets.emit('closecmd', socket.username, data); setTimeout(function () { io.sockets.emit('closevalve', socket.username, data); }, 1000) }); // when the client emits 'adduser', this listens and executes socket.on('adduser', function(username){ // we store the username in the socket session for this client socket.username = username; // add the client's username to the global list usernames[username] = username; // echo to client they've connected socket.emit('updatechat', 'SERVER', 'you have connected'); // echo globally (all clients) that a person has connected

3 of 17

12/24/13, 12:55 PM

node.js, socket.io, and real-time web HMI example | Chris Larson

http://chrislarson.me/blog/nodejs-socketio-and-real-time-web-h...

socket.broadcast.emit('updatechat', 'SERVER', username + ' has connected'); // update the list of users in chat, client-side io.sockets.emit('updateusers', usernames); }); // when the user disconnects.. perform this socket.on('disconnect', function(){ // remove the username from global usernames list delete usernames[socket.username]; // update list of users in chat, client-side io.sockets.emit('updateusers', usernames); // echo globally that this client has left socket.broadcast.emit('updatechat', 'SERVER', socket.username + ' has disconnected'); }); }); The client side web page and css file are also similar to the chat example and include the face plates for the valve control.

index.html
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" dir="ltr"> <meta http-equiv="X-UA-Compatible" content="IE=9" /> <head><title>SCADA Valve Control Example</title> <meta name="viewport" content="initial-scale = 1.0,maximum-scale = 1.0" /> <link type="text/css" rel="stylesheet" href="/app.css" media="all"> </head>

4 of 17

12/24/13, 12:55 PM

node.js, socket.io, and real-time web HMI example | Chris Larson

http://chrislarson.me/blog/nodejs-socketio-and-real-time-web-h...

<script src="/socket.io/socket.io.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4 /jquery.min.js"></script> <script> var socket = io.connect('127.0.0.1:8080'); //set this to the ip address of your node.js server // on connection to server, ask for user's name with an anonymous callback socket.on('connect', function(){ // call the server-side function 'adduser' and send one parameter (value of prompt) socket.emit('adduser', prompt("What's your name?")); }); // listener, whenever the server emits 'updatechat', this updates the chat body socket.on('updatechat', function (username, data) { $('#conversation').append('<b>'+username + ':</b> ' + data + '<br>'); }); // listener, whenever the server emits 'updateusers', this updates the username list socket.on('updateusers', function(data) { $('#users').empty(); $.each(data, function(key, value) { $('#users').append('<div>' + key + '</div>'); }); }); // listener, whenever the server emits 'updateusers', this updates

5 of 17

12/24/13, 12:55 PM

node.js, socket.io, and real-time web HMI example | Chris Larson

http://chrislarson.me/blog/nodejs-socketio-and-real-time-web-h...

the username list socket.on('updatevalve', function(data) { $('#users').empty(); $.each(data, function(key, value) { $('#users').append('<div>' + key + '</div>'); }); }); // listener, whenever the server emits 'openvalve', this updates the username list socket.on('openvalve', function(username, data) { $('#' + data + ' > div.feedback > div.circle.status').removeClass('red').addClass('green'); }); socket.on('opencmd', function(username, data) { $('#' + data + ' > div.feedback > div.circle.status > div.circle.command').removeClass('red').addClass('green'); }); // listener, whenever the server emits 'openvalve', this updates the username list socket.on('closevalve', function(username, data) { $('#' + data + ' > div.feedback > div.circle.status').removeClass('green').addClass('red'); }); socket.on('closecmd', function(username, data) { $('#' + data + ' > div.feedback > div.circle.status > div.circle.command').removeClass('green').addClass('red'); }); // on load of page $(function(){ // when the client clicks SEND

6 of 17

12/24/13, 12:55 PM

node.js, socket.io, and real-time web HMI example | Chris Larson

http://chrislarson.me/blog/nodejs-socketio-and-real-time-web-h...

$('#datasend').click( function() { var message = $('#data').val(); $('#data').val(''); // tell server to execute 'sendchat' and send along one parameter socket.emit('sendchat', message); }); // when the client hits ENTER on their keyboard $('#data').keypress(function(e) { if(e.which == 13) { $(this).blur(); $('#datasend').focus().click(); } }); // when the client clicks OPEN $('.open').click( function() { var id = $(this).parent().attr("id");; //console.log(id); socket.emit('opencmd', id); }); // when the client clicks CLOSE $('.close').click( function() { var id = $(this).parent().attr("id");; //console.log(id); socket.emit('closecmd', id); }); }); </script>

7 of 17

12/24/13, 12:55 PM

node.js, socket.io, and real-time web HMI example | Chris Larson

http://chrislarson.me/blog/nodejs-socketio-and-real-time-web-h...

<body> <p> <div id="userlist"> <b>USERS</b> <div id="users"></div> </div> <div id="messages"> <input id="data"/> <input type="button" id="datasend" class="send" value="send" /> <div id="conversation"></div> </div> <div class="clear"></div> <div id="valve1001" class="valve"> <h3>VALVE 1001</h3> <div class="open">OPEN</div> <div class="close">CLOSE</div> <div class="clear"></div> <div class="feedback"> <div class="circle status green"> <div class="circle command red"></div> </div> </div> <div class="clear"></div> </div> <div id="valve1002" class="valve"> <h3>VALVE 1002</h3> <div class="open">OPEN</div> <div class="close">CLOSE</div> <div class="clear"></div> <div class="feedback"> <div class="circle status green"> <div class="circle command red"></div>

8 of 17

12/24/13, 12:55 PM

node.js, socket.io, and real-time web HMI example | Chris Larson

http://chrislarson.me/blog/nodejs-socketio-and-real-time-web-h...

</div> </div> <div class="clear"></div> </div> <div id="valve1003" class="valve"> <h3>VALVE 1003</h3> <div class="open">OPEN</div> <div class="close">CLOSE</div> <div class="clear"></div> <div class="feedback"> <div class="circle status green"> <div class="circle command red"></div> </div> </div> <div class="clear"></div> </div> <div id="valve1004" class="valve"> <h3>VALVE 1004</h3> <div class="open">OPEN</div> <div class="close">CLOSE</div> <div class="clear"></div> <div class="feedback"> <div class="circle status green"> <div class="circle command red"></div> </div> </div> <div class="clear"></div> </div> </body>

app.css

9 of 17

12/24/13, 12:55 PM

node.js, socket.io, and real-time web HMI example | Chris Larson

http://chrislarson.me/blog/nodejs-socketio-and-real-time-web-h...

body { font-family: Verdana,Tahoma,"DejaVu Sans",sans-serif; } p { width:100%; } .clear { clear:both; } #userlist { float:left; width:290px; border-right:1px solid black; height:100px; padding:10px; overflow:scroll-y; } #messages { float:left; width:290px; padding:10px; } #data { width:65%; } #conversation {

10 of 17

12/24/13, 12:55 PM

node.js, socket.io, and real-time web HMI example | Chris Larson

http://chrislarson.me/blog/nodejs-socketio-and-real-time-web-h...

overflow:scroll; width:96%; height:150px; } .valve { float:left; overflow:scroll-y; padding:20px; border:1px solid black; } .feedback { width:103px; height:103px; margin-left:auto; margin-right:auto; margin-top:20px; } .open { -moz-box-shadow:inset 0px 1px 0px 0px #c1ed9c; -webkit-box-shadow:inset 0px 1px 0px 0px #c1ed9c; box-shadow:inset 0px 1px 0px 0px #c1ed9c; background:-webkit-gradient( linear, left top, left bottom, colorstop(0.05, #9dce2c), color-stop(1, #8cb82b) ); background:-moz-linear-gradient( center top, #9dce2c 5%, #8cb82b 100% ); filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#9d ce2c', endColorstr='#8cb82b'); background-color:#9dce2c; -moz-border-radius:6px;

11 of 17

12/24/13, 12:55 PM

node.js, socket.io, and real-time web HMI example | Chris Larson

http://chrislarson.me/blog/nodejs-socketio-and-real-time-web-h...

-webkit-border-radius:6px; border-radius:6px; border:1px solid #83c41a; display:inline-block; color:#ffffff; font-family:arial; font-size:15px; font-weight:bold; padding:6px 24px; text-decoration:none; text-shadow:1px 1px 0px #689324; }.open:hover { background:-webkit-gradient( linear, left top, left bottom, colorstop(0.05, #8cb82b), color-stop(1, #9dce2c) ); background:-moz-linear-gradient( center top, #8cb82b 5%, #9dce2c 100% ); filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#8c b82b', endColorstr='#9dce2c'); background-color:#8cb82b; }.open:active { position:relative; top:1px; } .close { -moz-box-shadow:inset 0px 1px 0px 0px #f5978e; -webkit-box-shadow:inset 0px 1px 0px 0px #f5978e; box-shadow:inset 0px 1px 0px 0px #f5978e; background:-webkit-gradient( linear, left top, left bottom, colorstop(0.05, #f24537), color-stop(1, #c62d1f) ); backgrouclear:both;nd:-moz-linear-gradient( center top, #f24537 5%, #c62d1f 100% );

12 of 17

12/24/13, 12:55 PM

node.js, socket.io, and real-time web HMI example | Chris Larson

http://chrislarson.me/blog/nodejs-socketio-and-real-time-web-h...

filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f2 4537', endColorstr='#c62d1f'); background-color:#f24537; -moz-border-radius:6px; -webkit-border-radius:6px; border-radius:6px; border:1px solid #d02718; display:inline-block; color:#ffffff; font-family:arial; font-size:15px; font-weight:bold; padding:6px 24px; text-decoration:none; text-shadow:1px 1px 0px #810e05; }.close:hover { background:-webkit-gradient( linear, left top, left bottom, colorstop(0.05, #c62d1f), color-stop(1, #f24537) ); background:-moz-linear-gradient( center top, #c62d1f 5%, #f24537 100% ); filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#c6 2d1f', endColorstr='#f24537'); background-color:#c62d1f; }.close:active { position:relative; top:1px; } .send { -moz-box-shadow:inset 0px 1px 0px 0px #ffffff; -webkit-box-shadow:inset 0px 1px 0px 0px #ffffff; box-shadow:inset 0px 1px 0px 0px #ffffff;

13 of 17

12/24/13, 12:55 PM

node.js, socket.io, and real-time web HMI example | Chris Larson

http://chrislarson.me/blog/nodejs-socketio-and-real-time-web-h...

background:-webkit-gradient( linear, left top, left bottom, colorstop(0.05, #ededed), color-stop(1, #dfdfdf) ); background:-moz-linear-gradient( center top, #ededed 5%, #dfdfdf 100% ); filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ed eded', endColorstr='#dfdfdf'); background-color:#ededed; -moz-border-radius:6px; -webkit-border-radius:6px; border-radius:6px; border:1px solid #dcdcdc; display:inline-block; color:#777777; font-family:arial; font-size:15px; font-weight:bold; padding:6px 24px; text-decoration:none; text-shadow:1px 1px 0px #ffffff; }.send:hover { background:-webkit-gradient( linear, left top, left bottom, colorstop(0.05, #dfdfdf), color-stop(1, #ededed) ); background:-moz-linear-gradient( center top, #dfdfdf 5%, #ededed 100% ); filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#df dfdf', endColorstr='#ededed'); background-color:#dfdfdf; }.send:active { position:relative; top:1px; }

14 of 17

12/24/13, 12:55 PM

node.js, socket.io, and real-time web HMI example | Chris Larson

http://chrislarson.me/blog/nodejs-socketio-and-real-time-web-h...

.green { background:-webkit-gradient( linear, left top, left bottom, colorstop(0.05, #9dce2c), color-stop(1, #8cb82b) ); background:-moz-linear-gradient( center top, #9dce2c 5%, #8cb82b 100% ); filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#9d ce2c', endColorstr='#8cb82b'); background-color:#9dce2c; } .red { background:-webkit-gradient( linear, left top, left bottom, colorstop(0.05, #f24537), color-stop(1, #c62d1f) ); backgrouclear:both;nd:-moz-linear-gradient( center top, #f24537 5%, #c62d1f 100% ); filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f2 4537', endColorstr='#c62d1f'); background-color:#f24537; } .circle { -moz-border-radius: 50%; border-radius: 50%; display: inline-block; margin-right: 20px; } .status { width: 103px; height: 103px; position: relative; }

15 of 17

12/24/13, 12:55 PM

node.js, socket.io, and real-time web HMI example | Chris Larson

http://chrislarson.me/blog/nodejs-socketio-and-real-time-web-h...

.command { width: 50px; height: 50px; position: absolute; top: 23%; left: 23%; display: block; border: 3px solid white; overflow:hidden; }

If you enjoyed this article, get email updates


JOIN!

16 of 17

12/24/13, 12:55 PM

node.js, socket.io, and real-time web HMI example | Chris Larson

http://chrislarson.me/blog/nodejs-socketio-and-real-time-web-h...

2 comments Join the discussion


Best Community Charls Agente
11 months ago

Share
!

Login

can you update the code pls, i found this very interesting but i cant understand the code right here in plain text
! Reply ! Share

Chris Larson

Mod >

Charls Agente

11 months ago

I added the code to github https://github.com/chrylarson/... you can download the project form there.
! Reply ! Share

Subscribe

Add Disqus to your site

17 of 17

12/24/13, 12:55 PM

Você também pode gostar