node-red-contrib-socketio Example flow
#Example flow for node-red-contrib-socketio
##Prerequisites
To use this flow you need to install node-red-contrib-socketio.
To install node-red-contrib-socketio use npm i node-red-contrib-socketio
##How to use
Connect to your <Node-RED istance>/sio
and the example chat app will start in your browser.
[{"id":"2d750ed.93b04f2","type":"tab","label":"SocketIO test"},{"id":"10304712.9b83e9","type":"debug","z":"2d750ed.93b04f2","name":"","active":true,"console":"false","complete":"true","x":235,"y":59,"wires":[]},{"id":"4232bc5c.6a5224","type":"http in","z":"2d750ed.93b04f2","name":"","url":"/sio","method":"get","swaggerDoc":"","x":104,"y":317,"wires":[["342e8024.c985d"]]},{"id":"6e8b3289.67d42c","type":"http response","z":"2d750ed.93b04f2","name":"","x":402,"y":317,"wires":[]},{"id":"f8fc0121.575f1","type":"socketio-in","z":"2d750ed.93b04f2","name":"","server":"47235b74.69f984","rules":[{"v":"add user"},{"v":"new message"},{"v":"typing"},{"v":"stop typing"}],"x":75,"y":178,"wires":[["10304712.9b83e9","5b63bcd4.846c34"]]},{"id":"e9e3f889.0fbf78","type":"socketio-out","z":"2d750ed.93b04f2","name":"","server":"47235b74.69f984","x":696,"y":235,"wires":[]},{"id":"5b63bcd4.846c34","type":"switch","z":"2d750ed.93b04f2","name":"checkEvent","property":"socketIOEvent","propertyType":"msg","rules":[{"t":"eq","v":"new message","vt":"str"},{"t":"eq","v":"add user","vt":"str"},{"t":"eq","v":"typing","vt":"str"},{"t":"eq","v":"stop typing","vt":"str"},{"t":"eq","v":"disconnect","vt":"str"}],"checkall":"false","outputs":5,"x":258,"y":178,"wires":[["40fa7ff3.6d09b"],["d851e0c9.0c289","fa3603ed.c9c0c"],["ffe0004d.b5508"],["ffe0004d.b5508"],["48a2dbb4.e0cd24"]]},{"id":"de96689f.114d38","type":"comment","z":"2d750ed.93b04f2","name":"Switch output","info":"1 new message\n2 add user\n3 typing\n4 stop typing\n5 disconnect","x":259,"y":233,"wires":[]},{"id":"d851e0c9.0c289","type":"function","z":"2d750ed.93b04f2","name":"add user","func":"var numUsers = flow.get ('numUsers') || 0;\n++numUsers;\nflow.set ('numUsers', numUsers);\nmsg.socketIOEvent = 'login';\nmsg.payload = {\n numUsers: numUsers\n };\nRED.util.setMessageProperty(msg, \"socketIOEmit\", \"emit\", true);\nreturn msg;","outputs":1,"noerr":0,"x":462,"y":135,"wires":[["e9e3f889.0fbf78","8ac6f5a.9cfae08"]]},{"id":"8ac6f5a.9cfae08","type":"debug","z":"2d750ed.93b04f2","name":"Accept/Disconnect user","active":true,"console":"false","complete":"true","x":727,"y":134,"wires":[]},{"id":"fc70dba0.8d9c38","type":"debug","z":"2d750ed.93b04f2","name":"say to other","active":true,"console":"false","complete":"true","x":686,"y":168,"wires":[]},{"id":"fa3603ed.c9c0c","type":"function","z":"2d750ed.93b04f2","name":"add user","func":"var numUsers = flow.get ('numUsers') || 0;\nmsg.socketIOEvent = 'user joined';\nRED.util.setMessageProperty(msg, \"socketIOAddStaticProperties\", {username: msg.payload}, true);\nmsg.payload = {\n username: msg.payload,\n numUsers: numUsers\n };\nRED.util.setMessageProperty(msg, \"socketIOEmit\", \"broadcast.emit\", true);\nreturn msg;","outputs":1,"noerr":0,"x":462,"y":168,"wires":[["e9e3f889.0fbf78","fc70dba0.8d9c38"]]},{"id":"dee7da46.6473a8","type":"debug","z":"2d750ed.93b04f2","name":"tayping","active":true,"console":"false","complete":"true","x":676,"y":201,"wires":[]},{"id":"ffe0004d.b5508","type":"function","z":"2d750ed.93b04f2","name":"typing","func":"msg.payload = {username: msg.socketIOStaticProperties.username};\nRED.util.setMessageProperty(msg, \"socketIOEmit\", \"broadcast.emit\", true);\nreturn msg;","outputs":1,"noerr":0,"x":452,"y":199,"wires":[["dee7da46.6473a8","e9e3f889.0fbf78"]]},{"id":"48a2dbb4.e0cd24","type":"function","z":"2d750ed.93b04f2","name":"disconnect","func":"var numUsers = flow.get ('numUsers') || 0;\n--numUsers;\nflow.set ('numUsers', numUsers);\nmsg.socketIOEvent = 'user left';\nmsg.payload = {\n username: msg.socketIOStaticProperties.username,\n numUsers: numUsers\n };\n//RED.util.setMessageProperty(msg, \"socketIOEmit\", \"broadcast.emit\", true);\nreturn msg;","outputs":1,"noerr":0,"x":472,"y":231,"wires":[["8ac6f5a.9cfae08","e9e3f889.0fbf78"]]},{"id":"40fa7ff3.6d09b","type":"function","z":"2d750ed.93b04f2","name":"new message","func":"msg.payload = {username: msg.socketIOStaticProperties.username,\n message: msg.payload\n};\nRED.util.setMessageProperty(msg, \"socketIOEmit\", \"broadcast.emit\", true);\nreturn msg;","outputs":1,"noerr":0,"x":482,"y":102,"wires":[["e9e3f889.0fbf78","a4ea03b1.7fd0b"]]},{"id":"a4ea03b1.7fd0b","type":"debug","z":"2d750ed.93b04f2","name":"Message","active":true,"console":"false","complete":"true","x":678,"y":101,"wires":[]},{"id":"342e8024.c985d","type":"template","z":"2d750ed.93b04f2","name":"Chat page","field":"payload","fieldType":"msg","format":"html","syntax":"plain","template":"<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <title>Socket.IO Chat Example</title>\n <style>\n\t/* Fix user-agent */\n\n* {\n box-sizing: border-box;\n}\n\nhtml {\n font-weight: 300;\n -webkit-font-smoothing: antialiased;\n}\n\nhtml, input {\n font-family:\n \"HelveticaNeue-Light\",\n \"Helvetica Neue Light\",\n \"Helvetica Neue\",\n Helvetica,\n Arial,\n \"Lucida Grande\",\n sans-serif;\n}\n\nhtml, body {\n height: 100%;\n margin: 0;\n padding: 0;\n}\n\nul {\n list-style: none;\n word-wrap: break-word;\n}\n\n/* Pages */\n\n.pages {\n height: 100%;\n margin: 0;\n padding: 0;\n width: 100%;\n}\n\n.page {\n height: 100%;\n position: absolute;\n width: 100%;\n}\n\n/* Login Page */\n\n.login.page {\n background-color: #000;\n}\n\n.login.page .form {\n height: 100px;\n margin-top: -100px;\n position: absolute;\n\n text-align: center;\n top: 50%;\n width: 100%;\n}\n\n.login.page .form .usernameInput {\n background-color: transparent;\n border: none;\n border-bottom: 2px solid #fff;\n outline: none;\n padding-bottom: 15px;\n text-align: center;\n width: 400px;\n}\n\n.login.page .title {\n font-size: 200%;\n}\n\n.login.page .usernameInput {\n font-size: 200%;\n letter-spacing: 3px;\n}\n\n.login.page .title, .login.page .usernameInput {\n color: #fff;\n font-weight: 100;\n}\n\n/* Chat page */\n\n.chat.page {\n display: none;\n}\n\n/* Font */\n\n.messages {\n font-size: 150%;\n}\n\n.inputMessage {\n font-size: 100%;\n}\n\n.log {\n color: gray;\n font-size: 70%;\n margin: 5px;\n text-align: center;\n}\n\n/* Messages */\n\n.chatArea {\n height: 100%;\n padding-bottom: 60px;\n}\n\n.messages {\n height: 100%;\n margin: 0;\n overflow-y: scroll;\n padding: 10px 20px 10px 20px;\n}\n\n.message.typing .messageBody {\n color: gray;\n}\n\n.username {\n font-weight: 700;\n overflow: hidden;\n padding-right: 15px;\n text-align: right;\n}\n\n/* Input */\n\n.inputMessage {\n border: 10px solid #000;\n bottom: 0;\n height: 60px;\n left: 0;\n outline: none;\n padding-left: 10px;\n position: absolute;\n right: 0;\n width: 100%;\n} </style>\n</head>\n<body>\n <ul class=\"pages\">\n <li class=\"chat page\">\n <div class=\"chatArea\">\n <ul class=\"messages\"></ul>\n </div>\n <input class=\"inputMessage\" placeholder=\"Type here...\"/>\n </li>\n <li class=\"login page\">\n <div class=\"form\">\n <h3 class=\"title\">What's your nickname?</h3>\n <input class=\"usernameInput\" type=\"text\" maxlength=\"14\" />\n </div>\n </li>\n </ul>\n\n <script src=\"https://code.jquery.com/jquery-1.10.2.min.js\"></script>\n <script src=\"/socket.io/socket.io.js\"></script>\n <script >$(function() {\n var FADE_TIME = 150; // ms\n var TYPING_TIMER_LENGTH = 400; // ms\n var COLORS = [\n '#e21400', '#91580f', '#f8a700', '#f78b00',\n '#58dc00', '#287b00', '#a8f07a', '#4ae8c4',\n '#3b88eb', '#3824aa', '#a700ff', '#d300e7'\n ];\n\n // Initialize variables\n var $window = $(window);\n var $usernameInput = $('.usernameInput'); // Input for username\n var $messages = $('.messages'); // Messages area\n var $inputMessage = $('.inputMessage'); // Input message input box\n\n var $loginPage = $('.login.page'); // The login page\n var $chatPage = $('.chat.page'); // The chatroom page\n\n // Prompt for setting a username\n var username;\n var connected = false;\n var typing = false;\n var lastTypingTime;\n var $currentInput = $usernameInput.focus();\n\n var socket = io();\n\n function addParticipantsMessage (data) {\n var message = '';\n if (data.numUsers === 1) {\n message += \"there's 1 participant\";\n } else {\n message += \"there are \" + data.numUsers + \" participants\";\n }\n log(message);\n }\n\n // Sets the client's username\n function setUsername () {\n username = cleanInput($usernameInput.val().trim());\n\n // If the username is valid\n if (username) {\n $loginPage.fadeOut();\n $chatPage.show();\n $loginPage.off('click');\n $currentInput = $inputMessage.focus();\n\n // Tell the server your username\n socket.emit('add user', username);\n }\n }\n\n // Sends a chat message\n function sendMessage () {\n var message = $inputMessage.val();\n // Prevent markup from being injected into the message\n message = cleanInput(message);\n // if there is a non-empty message and a socket connection\n if (message && connected) {\n $inputMessage.val('');\n addChatMessage({\n username: username,\n message: message\n });\n // tell server to execute 'new message' and send along one parameter\n socket.emit('new message', message);\n }\n }\n\n // Log a message\n function log (message, options) {\n var $el = $('<li>').addClass('log').text(message);\n addMessageElement($el, options);\n }\n\n // Adds the visual chat message to the message list\n function addChatMessage (data, options) {\n // Don't fade the message in if there is an 'X was typing'\n var $typingMessages = getTypingMessages(data);\n options = options || {};\n if ($typingMessages.length !== 0) {\n options.fade = false;\n $typingMessages.remove();\n }\n\n var $usernameDiv = $('<span class=\"username\"/>')\n .text(data.username)\n .css('color', getUsernameColor(data.username));\n var $messageBodyDiv = $('<span class=\"messageBody\">')\n .text(data.message);\n\n var typingClass = data.typing ? 'typing' : '';\n var $messageDiv = $('<li class=\"message\"/>')\n .data('username', data.username)\n .addClass(typingClass)\n .append($usernameDiv, $messageBodyDiv);\n\n addMessageElement($messageDiv, options);\n }\n\n // Adds the visual chat typing message\n function addChatTyping (data) {\n data.typing = true;\n data.message = 'is typing';\n addChatMessage(data);\n }\n\n // Removes the visual chat typing message\n function removeChatTyping (data) {\n getTypingMessages(data).fadeOut(function () {\n $(this).remove();\n });\n }\n\n // Adds a message element to the messages and scrolls to the bottom\n // el - The element to add as a message\n // options.fade - If the element should fade-in (default = true)\n // options.prepend - If the element should prepend\n // all other messages (default = false)\n function addMessageElement (el, options) {\n var $el = $(el);\n\n // Setup default options\n if (!options) {\n options = {};\n }\n if (typeof options.fade === 'undefined') {\n options.fade = true;\n }\n if (typeof options.prepend === 'undefined') {\n options.prepend = false;\n }\n\n // Apply options\n if (options.fade) {\n $el.hide().fadeIn(FADE_TIME);\n }\n if (options.prepend) {\n $messages.prepend($el);\n } else {\n $messages.append($el);\n }\n $messages[0].scrollTop = $messages[0].scrollHeight;\n }\n\n // Prevents input from having injected markup\n function cleanInput (input) {\n return $('<div/>').text(input).text();\n }\n\n // Updates the typing event\n function updateTyping () {\n if (connected) {\n if (!typing) {\n typing = true;\n socket.emit('typing');\n }\n lastTypingTime = (new Date()).getTime();\n\n setTimeout(function () {\n var typingTimer = (new Date()).getTime();\n var timeDiff = typingTimer - lastTypingTime;\n if (timeDiff >= TYPING_TIMER_LENGTH && typing) {\n socket.emit('stop typing');\n typing = false;\n }\n }, TYPING_TIMER_LENGTH);\n }\n }\n\n // Gets the 'X is typing' messages of a user\n function getTypingMessages (data) {\n return $('.typing.message').filter(function (i) {\n return $(this).data('username') === data.username;\n });\n }\n\n // Gets the color of a username through our hash function\n function getUsernameColor (username) {\n // Compute hash code\n var hash = 7;\n for (var i = 0; i < username.length; i++) {\n hash = username.charCodeAt(i) + (hash << 5) - hash;\n }\n // Calculate color\n var index = Math.abs(hash % COLORS.length);\n return COLORS[index];\n }\n\n // Keyboard events\n\n $window.keydown(function (event) {\n // Auto-focus the current input when a key is typed\n if (!(event.ctrlKey || event.metaKey || event.altKey)) {\n $currentInput.focus();\n }\n // When the client hits ENTER on their keyboard\n if (event.which === 13) {\n if (username) {\n sendMessage();\n socket.emit('stop typing');\n typing = false;\n } else {\n setUsername();\n }\n }\n });\n\n $inputMessage.on('input', function() {\n updateTyping();\n });\n\n // Click events\n\n // Focus input when clicking anywhere on login page\n $loginPage.click(function () {\n $currentInput.focus();\n });\n\n // Focus input when clicking on the message input's border\n $inputMessage.click(function () {\n $inputMessage.focus();\n });\n\n // Socket events\n\n // Whenever the server emits 'login', log the login message\n socket.on('login', function (data) {\n connected = true;\n // Display the welcome message\n var message = \"Welcome to Socket.IO Chat � \";\n log(message, {\n prepend: true\n });\n addParticipantsMessage(data);\n });\n\n // Whenever the server emits 'new message', update the chat body\n socket.on('new message', function (data) {\n addChatMessage(data);\n });\n\n // Whenever the server emits 'user joined', log it in the chat body\n socket.on('user joined', function (data) {\n log(data.username + ' joined');\n addParticipantsMessage(data);\n });\n\n // Whenever the server emits 'user left', log it in the chat body\n socket.on('user left', function (data) {\n log(data.username + ' left');\n addParticipantsMessage(data);\n removeChatTyping(data);\n });\n\n // Whenever the server emits 'typing', show the typing message\n socket.on('typing', function (data) {\n addChatTyping(data);\n });\n\n // Whenever the server emits 'stop typing', kill the typing message\n socket.on('stop typing', function (data) {\n removeChatTyping(data);\n });\n\n socket.on('disconnect', function () {\n log('you have been disconnected');\n });\n\n socket.on('reconnect', function () {\n log('you have been reconnected');\n if (username) {\n socket.emit('add user', username);\n }\n });\n\n socket.on('reconnect_error', function () {\n log('attempt to reconnect has failed');\n });\n\n});\n</script>\n</body>\n</html>\n","x":258,"y":317,"wires":[["6e8b3289.67d42c"]]},{"id":"47235b74.69f984","type":"socketio-config","z":"","port":"1881","sendClient":"true","path":"/socket.io","bindToNode":true}]