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  height: 100%;\n  position: absolute;\n  width: 100%;\n}\n\n/* Login Page */\n\ {\n  background-color: #000;\n}\n\ .form {\n  height: 100px;\n  margin-top: -100px;\n  position: absolute;\n\n  text-align: center;\n  top: 50%;\n  width: 100%;\n}\n\ .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\ .title {\n  font-size: 200%;\n}\n\ .usernameInput {\n  font-size: 200%;\n  letter-spacing: 3px;\n}\n\ .title, .usernameInput {\n  color: #fff;\n  font-weight: 100;\n}\n\n/* Chat page */\n\ {\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=\"\"></script>\n  <script src=\"/\"></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 = $(''); // The login page\n  var $chatPage = $(''); // 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      $;\n      $'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  $ () {\n    $currentInput.focus();\n  });\n\n  // Focus input when clicking on the message input's border\n  $ () {\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":"/","bindToNode":true}]

Flow Info

Created 5 years, 2 months ago
Rating: not yet rated




Node Types

  • comment (x1)
  • debug (x5)
  • function (x5)
  • http in (x1)
  • http response (x1)
  • switch (x1)
  • tab (x1)
  • template (x1)
  • socketio-config (x1)
  • socketio-in (x1)
  • socketio-out (x1)


  • socketio
  • node-red-contrib-socketio
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option