{"id":2888,"date":"2014-10-03T17:59:33","date_gmt":"2014-10-03T21:59:33","guid":{"rendered":"https:\/\/itp.nyu.edu\/physcomp\/?page_id=2888"},"modified":"2021-07-26T15:44:46","modified_gmt":"2021-07-26T19:44:46","slug":"lab-serial-communication-with-node-js","status":"publish","type":"page","link":"https:\/\/itp.nyu.edu\/physcomp\/labs\/labs-serial-communication\/lab-serial-communication-with-node-js\/","title":{"rendered":"Lab: Serial Communication with Node.js"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Introduction\"><\/span>Introduction<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>You can write programs that handle serial communication in many different languages. This page introduces how to do it using node.js. Node is a JavaScript environment that allows user to write web server programs. Below, you&#8217;ll use it to connect a microcontroller to a web browser using the node.js programming environment, HTML, and JavaScript.<\/p>\n\n\n\n<p>To get the most out of this tutorial, you should know <a href=\"https:\/\/itp.nyu.edu\/physcomp\/lessons\/microcontrollers__trashed\/microcontrollers-the-basics\/\">what a microcontroller is <\/a>and <a href=\"https:\/\/itp.nyu.edu\/physcomp\/lessons\/programming__trashed\/programming-terms-and-programming-environments\/\">how to program a microcontroller<\/a>. You should also understand <a href=\"https:\/\/itp.nyu.edu\/physcomp\/lessons\/serial-communication__trashed\/serial-communication-the-basics\/\">asynchronous serial communication<\/a> between microcontrollers and personal computers. You should also understand the basics of <a rel=\"noopener\" href=\"http:\/\/itp.nyu.edu\/groups\/flyby\/unix-intro-1\/\">command line interfaces<\/a>.<\/p>\n\n\n\n<p>You will struggle with this tutorial if you aren&#8217;t familiar with JavaScript. &nbsp;For more on JavaScript, see Douglas Crockford&#8217;s <a rel=\"noopener\" href=\"http:\/\/shop.oreilly.com\/product\/9780596517748.do\">JavaScript: The Good Parts,<\/a>&nbsp;Manuel Kiessling&#8217;s &nbsp;the <a rel=\"noopener\" href=\"http:\/\/www.nodebeginner.org\/\">Node Beginner Book<\/a>, or Shelley Powers&#8217; <a rel=\"noopener\" href=\"http:\/\/shop.oreilly.com\/product\/0636920024606.do\">Learning Node<\/a>.<\/p>\n\n\n\n<p>The current version of this tutorial works with version 6.x.x of the node-serialport library.<\/p>\n\n\n\n<p>This <a href=\"https:\/\/vimeo.com\/380358087\">node.js introductory video<\/a> will help in understanding this lab. The code in the video is different than this lab, but the basic concepts are similar. This&nbsp;lab simplifies the process a bit.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Nodejs\"><\/span>Node.js<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>The JavaScript programming language is mainly used to add interactivity to web pages. All modern browsers include a JavaScript interpreter, which allows the browser to run JavaScript code that&#8217;s embedded in a web page. Google&#8217;s JavaScript engine is called <a rel=\"noopener\" href=\"https:\/\/code.google.com\/p\/v8\/\">v8<\/a>, and it&#8217;s available under an open source license. <a rel=\"noopener\" href=\"http:\/\/www.nodejs.org\">Node.js<\/a> wraps the v8 engine up in an application programming interface that can run on personal computers and servers. On your personal computer, you run it through the command line interface.<\/p>\n\n\n\n<p>Node was originally designed as a tool for writing server programs, but it can do much more. It has a library management system called <strong>node package manager<\/strong> or <a rel=\"noopener\" href=\"https:\/\/www.npmjs.org\/\"><strong>npm<\/strong><\/a> that allows you to extend its functionality in many directions. There is also an online registry of node libraries, <a rel=\"noopener\" href=\"https:\/\/www.npmjs.org\/\">npmjs.org<\/a>. You can download libraries from this registry directly using npm. Below you&#8217;ll see npm used to add both serial communication functionality and a simple server programming library to node.<\/p>\n\n\n\n<p>To get started, download the <a rel=\"noopener\" href=\"http:\/\/www.nodejs.org\">node.js installer<\/a> and install it on your computer. Then open your command line terminal. On OSX, open the Terminal app, which can be found in the Applications\/Utilities directory. On Windows, go to the start menu and type cmd then press enter to open a window to the command line.<\/p>\n\n\n\n<p>If you&#8217;ve never used a command line interface, check out this <a rel=\"noopener\" href=\"http:\/\/itp.nyu.edu\/groups\/flyby\/unix-intro-1\/\">tutorial on the Unix\/Linux command line interface<\/a>. &nbsp;From here on out, you&#8217;ll see the command prompt indicated like this:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">yourname@yourcomputer ~ $<\/pre>\n\n\n\n<p> Any commands you need to type will follow the $ symbol. The actual command prompt will vary depending on your operating system. On Windows, it&#8217;s typically this: <code>&gt;<\/code>. On most Unix and Linux systems, including OSX, it&#8217;s <code>$<\/code> or <code>%<\/code>.<\/p>\n\n\n\n<p>When you&#8217;ve installed node.js, type this command at the command prompt to get the version of node that you&#8217;re running:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ node -v<\/pre>\n\n\n\n<p> If you installed it correctly, you&#8217;ll get a version number like 12.18.0. The node installer should also install the node package manager (npm). You can check that in the same way:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ npm -v<\/pre>\n\n\n\n<p>Once node and npm are in place, you&#8217;re ready to create a new project. \n\n<a rel=\"noopener\" href=\"https:\/\/vimeo.com\/97949559#t=2m9s\"><\/a><\/p>\n\n\n\n<p><a rel=\"noopener\" href=\"https:\/\/vimeo.com\/380358087#t=2m9s\">Related video:&nbsp;Install the serialport Node module<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Hello_from_Nodejs\"><\/span>Hello from Node.js<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>There&#8217;s a library for node.js that allows you to communicate over your computer&#8217;s serial ports called serialport. If your computer&#8217;s connected to the internet, you can download install it automatically using npm. Create a new directory for your project:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ mkdir nodeSerialExample<\/pre>\n\n\n\n<p>Then change directories to that directory:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ cd nodeSerialExample<\/pre>\n\n\n\n<p><br>Now make a new text file in that directory with the name <code>index.js<\/code>.<\/p>\n\n\n\n<p>This will be your main program file. &nbsp;Add the following text to the file:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nconsole.log(\"Hello, and welcome to node.\");\n<\/pre><\/div>\n\n\n<p>Save the file, then run it by typing the following on the command line:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ node index.js<\/pre>\n\n\n\n<p>Your program should print out:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Hello, and welcome to node.<\/pre>\n\n\n\n<p>The program will finish and return to the command line when it&#8217;s done. Seeing that script running is indication that node.js is fully working on your machine.<\/p>\n\n\n\n<p>You can also pass information into your node program using the process arguments on the command line. &nbsp;Change your program like so:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nvar name = process.argv&#x5B;2];\nconsole.log(\"Hello, and welcome to node,\" + name);\n<\/pre><\/div>\n\n\n<p>Run this as you did before, but add your name after the name of your program when you invoke it, like so:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ node index.js Tom<\/pre>\n\n\n\n<p>You&#8217;ll get the following:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Hello, and welcome to node, Tom<\/pre>\n\n\n\n<p>The command line arguments are passed to your program as an array. The name was the third word you typed, or array element 2 (counting &#8220;node&#8221; as element 0 and &#8220;index.js&#8221; as element 1). &nbsp;This is a useful technique, and you&#8217;ll see it later to pass the program your serial port&#8217;s name.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_Node_Serialport_Library\"><\/span>The Node Serialport Library<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>You&#8217;ll also need the <a href=\"https:\/\/www.npmjs.org\/package\/serialport\">node serialport <\/a>library, which you can install from the npm registry like so:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ npm install serialport<\/pre>\n\n\n\n<p>This command will make a new subdirectory called node_modules, and in that directory it will install all the necessary assets for the serialport library. &nbsp;You&#8217;ll see a lot of text go by, and hopefully no errors. If you get errors, consult npmjs.org and the <a href=\"https:\/\/github.com\/voodootikigod\/node-serialport\/wiki\">github wiki&nbsp;for serialport<\/a>. Now you&#8217;re ready to use the serialport library.<\/p>\n\n\n\n<p>The first thing you&#8217;ll want is a list of the serial ports.&nbsp;Replace the text of your program file with the following:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nlet serialport = require(&#039;serialport&#039;);\n\n\/\/ list serial ports:\nserialport.list().then (\n  ports =&gt; ports.forEach(port =&gt;console.log(port.path)),\n  err =&gt; console.log(err)\n)\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Note_Whats_With_This_Crazy_Syntax\"><\/span>Note: What&#8217;s With This Crazy Syntax?<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>If you&#8217;re new to JavaScript, this syntax may be confusing. Node.js examples tend to use <strong>anonymous functions<\/strong> frequently. JavaScript can pass functions as variables (and vice versa). \u00a0This is also using the JavaScript ES6 <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Functions\/Arrow_functions\">arrow function notation<\/a>. That&#8217;s what&#8217;s going on here.<\/p>\n\n\n\n<p>Stoyan Stefanov&#8217;s <a href=\"http:\/\/shop.oreilly.com\/product\/9783897215986.do\">JavaScript Patterns<\/a> is useful for understanding the various patterns of JavaScript coding.<\/p>\n\n\n\n<p>When you run this script, you&#8217;ll get a list of your serial ports like so:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ node ListPorts.js\n\/dev\/cu.Bluetooth-Incoming-Port\n\/dev\/cu.Bluetooth-Modem\n\/dev\/cu.usbmodem1411<\/pre>\n\n\n\n<p>If you&#8217;ve got an Arduino plugged in via USB, you should see the name of your board&#8217;s port there as well. In the example above, which was run on OSX, the Arduino&#8217;s port is&nbsp;<code>\/dev\/cu.usbmodem1411<\/code>.<\/p>\n\n\n\n<p>The process of using the serialport library will be the same every time:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>initialize the serialport library<\/li><li>open the serial port<\/li><li>set up the callback functions and let them do the rest<\/li><\/ul>\n\n\n\n<p>Which are all explained below.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Opening_the_Serial_Port\"><\/span>Opening the Serial Port<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>To open a&nbsp;serial port in node, you include the library at the beginning of&nbsp;&nbsp;your script, and make a local&nbsp;instance of the library in a variable.&nbsp;Make a new script or replace index.js with the following:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nlet serialport = require('serialport');\/\/ include the library\n\/\/ get port name from the command line:\nlet portName = process.argv&#x5B;2];\n<\/pre><\/div>\n\n\n<p>Then you open the port using <code>new()<\/code> like so:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nlet myPort = new SerialPort(portName, 9600);\n<\/pre><\/div>\n\n\n<p>Note the serial parameters, which are passed to the new() function&nbsp;after the port name, as a list. The only one used here is the baud rate, set to 9600 bits per second.<\/p>\n\n\n\n<p>If you want to read serial data as ASCII-encoded text, line by line, you also need to create a parser to tell the serial library how to interpret data when it comes in. It should read all the incoming data as a line of text, and generate a new data event when it sees &nbsp;a newline (&#8220;\\n&#8221;). The parser is doing the same thing as Processing&#8217;s <a rel=\"noopener\" href=\"https:\/\/processing.org\/reference\/libraries\/serial\/Serial_bufferUntil_.html\">Serial.bufferUntil()<\/a> function does. You do it like so:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nlet Readline = SerialPort.parsers.Readline; \/\/ make instance of Readline parser\nlet parser = new Readline(); \/\/ make a new parser to read ASCII lines\nmyPort.pipe(parser); \/\/ pipe the serial stream to the parser\n<\/pre><\/div>\n\n\n<p>You can find the full program so far at <a href=\"https:\/\/github.com\/ITPNYU\/physcomp\/blob\/main\/Labs\/Node%20Serial%20Lab\/serial-in.js\">this link<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_Program_Wont_Stop\"><\/span>The Program Won&#8217;t Stop!<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>When you run this program now, it won&#8217;t automatically stop and return to the command line. To stop it, you&#8217;ll need to type control-C in the terminal window to stop it. \u00a0 The new instance of Serialport created a software object that listens for events from the serial port. Any node.js script that creates an event listener like this will run until you explicitly\u00a0stop it. \u00a0Both the serialport library and the http library, which you&#8217;ll use below, generate event listeners and will need to be explicitly stopped using control-C.<br><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Serialport_Library_Events\"><\/span>Serialport Library Events<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>The serialport library, like most node.js libraries, is <strong>event-based<\/strong>. This means that when the program is running, the operating system and the user&#8217;s actions will generate <strong>events<\/strong> and the program will provide functions to deal with those events called <strong>callback functions<\/strong>.<\/p>\n\n\n\n<p>The main events that the serial library will deal with are when a&nbsp;serial port opens, when it closes, when new data arrives, and when there&#8217;s an error.&nbsp;The data event in particular performs the same function as <a title=\"Labs: Serial Communication\" href=\"https:\/\/itp.nyu.edu\/physcomp\/labs\/labs-serial-communication\/\">Processing&#8217;s serialEvent()<\/a> function. &nbsp;Once you&#8217;ve made an instance of the serialport library using the new() function as shown above, you define what functions will get called when each event occurs by using <code>serialport.on()<\/code> like so:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nmyPort.on('open', showPortOpen);\nparser.on('data', readSerialData);\nmyPort.on('close', showPortClose);\nmyPort.on('error', showError);\n<\/pre><\/div>\n\n\n<p>The functions that are called by the event are the <strong>callback functions<\/strong>. In the example above, when the serial port is opened, the showPortOpen function will get called. When new data arrives, the sendSerialData&nbsp;function will get called, and so forth. If the event generates any parameters (for example a new data event will have the data as a parameter), those parameters will get passed to the callback function.<\/p>\n\n\n\n<p>In the example above, you&#8217;re listening for the open, close, and error events using functions from the serial port object (e.g. <code>myPort.on('open', showPortOpen);<\/code>), but you;&#8217;re listening for the data event using a function from the parser object (<code>parser.on('data',readSerialData);<\/code>). You can listen with the serial port object too (e.g.<code>myPort.on('data',readSerialData);<\/code>), but the port object listener function generates a data event once every byte, while the parser object lets you generate a data event once every newline instead.<\/p>\n\n\n\n<p>Write the callback functions for these events like so:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nfunction showPortOpen() {\n  console.log('port open. Data rate: ' + myPort.baudRate);\n}\n\nfunction readSerialData(data) {\n  console.log(data);\n}\n\nfunction showPortClose() {\n  console.log('port closed.');\n}\n\nfunction showError(error) {\n  console.log('Serial port error: ' + error);\n}\n<\/pre><\/div>\n\n\n<p>Now you&#8217;ve got enough of a program to see some results. Upload a simple serial output sketch to your Arduino such as the <a rel=\"noopener\" href=\"http:\/\/arduino.cc\/en\/Tutorial\/AnalogReadSerial\">AnalogReadSerial example <\/a>or the sketch shown in the <a title=\"Lab: Analog In with an Arduino\" rel=\"noopener\" href=\"https:\/\/itp.nyu.edu\/physcomp\/labs\/labs-arduino-digital-and-analog\/analog-in-with-an-arduino\/\">Analog Input Lab<\/a>, you&#8217;ll be able to see its output from this script. Save the script. Then invoke it as follows, replacing portname with the name of your serial port:<br><code>$ node index.js portname<\/code><\/p>\n\n\n\n<p>For example, on OSX, if you haven an Arduino attached to the serial port called\u00a0<code>\/dev\/cu.usbmodem1411<\/code>, then you&#8217;d type:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ node index.js \/dev\/cu.usbmodem1411<\/pre>\n\n\n\n<p>When the port opens, you&#8217;ll see the message from the <code>showPortOpen()<\/code> function, then the output from the Arduino. Here&#8217;s the output from the node script:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">port open. Data rate: 9600\n\n266\n276\n261<\/pre>\n\n\n\n<p>To send serial output from node.js to the Arduino, use the serialport <code>write()<\/code> function like so:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">myPort.write(\"Hello\");<\/pre>\n\n\n\n<p>That&#8217;s all it takes to read and write serial data from node.js to a microcontroller. Node.js is designed for writing web server applications, however, so in the following steps you&#8217;ll see how to connect a serial port to your web browser using more of node.js.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Connecting_from_the_Browser_to_the_Node_Program\"><\/span>Connecting from the Browser to the Node Program<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>In order to connect your node.js program&nbsp;to a web page, your program needs to listen for messages from the web browser, and the web pages need to connect to the program. To do this, you&#8217;ll use a connection called a <strong>webSocket<\/strong>. WebSockets are connections between web clients and servers that function a bit like serial ports. Both serial connections and webSocket connections are <strong>data streams<\/strong>, in which the first byte sent into the stream on one end is the first byte read out on the other end. Data streams are common programming structures and you&#8217;ll see them used in lots of places. They connect programs to files on your computer, or client programs to server programs, or desktop programs to serial or network ports. &nbsp;The diagram below(Figure 1) shows how the browser connects to your node.js program and how the node.js program connects to the serial port.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><a href=\"https:\/\/itp.nyu.edu\/physcomp\/wp-content\/uploads\/workflow.png\"><img loading=\"lazy\" decoding=\"async\" width=\"781\" height=\"196\" src=\"https:\/\/itp.nyu.edu\/physcomp\/wp-content\/uploads\/workflow.png\" alt=\"Diagram of the node.js serial workflow. The webpage on the left communicates with a node.js script running on a computer, shown in a box in the middle of the diagram. The node.js script communicates with an Arduino, shown on the right of the diagram, through a serial port.\" class=\"wp-image-3559\" srcset=\"https:\/\/itp.nyu.edu\/physcomp\/wp-content\/uploads\/workflow.png 781w, https:\/\/itp.nyu.edu\/physcomp\/wp-content\/uploads\/workflow-300x75.png 300w\" sizes=\"(max-width: 781px) 85vw, 781px\" \/><\/a><figcaption>Figure 1. Diagram of the node.js serial workflow. The webpage on the left communicates with a node.js script running on a computer, shown in a box in the middle of the diagram. The node.js script communicates with an Arduino, shown on the right of the diagram, through a serial port.<\/figcaption><\/figure><\/div>\n\n\n\n<p>There&#8217;s a node.js library your script will need to listen for webSocket connections that you should&nbsp;install using &nbsp;the node package manager like so:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ npm install ws<\/pre>\n\n\n\n<p>Once it&#8217;s successfully installed, include it with your previous script by adding the following at the beginning of &nbsp;the script, right after you included&nbsp;the serialport library:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nlet WebSocketServer = require('ws').Server;\n<\/pre><\/div>\n\n\n<p>Following that, you need to use new() to make a new instance of the webSocket servver, and then configure a few parameters, and finally start the server:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nconst SERVER_PORT = 8081;               \/\/ port number for the webSocket server\nlet wss = new WebSocketServer({port: SERVER_PORT}); \/\/ the webSocket server\nlet connections = new Array;          \/\/ list of connections to the server\n<\/pre><\/div>\n\n\n<p>The server will operate on port 8081, so when you write a client-side JavaScript program, you&#8217;ll connect to that port number. Your browser will be a client of the node.js script, and the script&nbsp;will be running as a server. Just as there are serialport event listener functions, there will be webSocket event listener functions too. You&#8217;ll need to listen for a webSocket connection event, and once connected, you&#8217;ll need to listen for incoming messages, and for the webSocket to close.<\/p>\n\n\n\n<p>There can be multiple webSocket clients at any one time, so the server maintains an array to keep track of all the clients. That array is called <code>connections<\/code>, and every time a new client connects, the client is added to the array using the <code>.push()<\/code> function. When a client closes, it&#8217;s removed from the array using the&nbsp;<code>.slice()<\/code> function.<\/p>\n\n\n\n<p>Here are the webSocket event listeners:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nwss.on('connection', handleConnection);\n\nfunction handleConnection(client) {\n  console.log(\"New Connection\"); \/\/ you have a new client\n  connections.push(client); \/\/ add this client to the connections array\n\n  client.on('message', sendToSerial); \/\/ when a client sends a message,\n\n  client.on('close', function() { \/\/ when a client closes its connection\n    console.log(\"connection closed\"); \/\/ print it out\n    let position = connections.indexOf(client); \/\/ get the client's position in the array\n    connections.splice(position, 1); \/\/ and delete it from the array\n  });\n}\n<\/pre><\/div>\n\n\n<p>You&#8217;ll also need to modify the serialport data event listener to send data to the webSocket, and vice versa. Here&#8217;s a function to send webSocket&nbsp;data to the serial port. Put this after the serial event listeners&nbsp;above:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nfunction sendToSerial(data) {\n  console.log(\"sending to serial: \" + data);\n  myPort.write(data);\n}\n<\/pre><\/div>\n\n\n<p>To parallel that, here&#8217;s a function to send serial data to the webSocket clients. Put this after the webSocket event listeners:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\n\/\/ This function broadcasts messages to all webSocket clients\nfunction broadcast(data) {\n  for (myConnection in connections) {   \/\/ iterate over the array of connections\n    connections&#x5B;myConnection].send(data); \/\/ send the data to each connection\n  }\n}\n<\/pre><\/div>\n\n\n<p>Finally, you need to add the highlighted lines below to the <code>readSerialData()<\/code> function. This will send the latest data to all available webSocket clients:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nfunction readSerialData(data) {\n  console.log(data);\n  \/\/ if there are webSocket connections, send the serial data\n  \/\/ to all of them:\n  if (connections.length &gt; 0) {\n    broadcast(data);\n  }\n}\n<\/pre><\/div>\n\n\n<p>Now you&#8217;ve got a complete script for connecting serial data to a webSocket server, and serving that to a client through a browser. Next you need a web page with its own embedded JavaScript to connect to his script.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Using_the_Data_in_HTML\"><\/span>Using the&nbsp;Data in HTML<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>The real value in connecting the serial port to a server is to generate dynamic HTML from the sensor data. You can do this by making an HTML page that includes some JavaScript to request data from the server, and serving that HTML page from a directory&nbsp;called <code>public<\/code> in your project directory. First, create the directory and change directory into it:<br>$ mkdir public<br>$ cd publicThen create a new document, index.html, in this directory. Don&#8217;t enter any elements, just the bare skeleton of a page:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;!DOCTYPE html&gt;\n&lt;html&gt;\n&lt;head&gt;\n  &lt;meta charset=&#039;utf-8&#039;&gt;\n  &lt;title&gt;Hello&lt;\/title&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n  \n&lt;\/body&gt;\n&lt;\/html&gt;\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Including_P5js\"><\/span>Including P5.js<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>If you&#8217;re used to Processing, then P5.js is a really good way to get started with JavaScript in the browser. It gives you the same structure as Processing, but in JavaScript. &nbsp;To use it, you&#8217;ll need to include P5.js using script tags in the head of your HTML.<\/p>\n\n\n\n<p>First, you need to include p5.js in the document head. You can either <a rel=\"noopener\" href=\"http:\/\/p5js.org\/download\/\">download P5.js and its libraries directly<\/a>, or you can include them from p5.js&#8217;s content delivery site, as shown in the HTML below.<\/p>\n\n\n\n<p>Create a file called sketch.js in the same directory as your HTML file. This is where you&#8217;ll write your JavaScript, using the p5.js library. <\/p>\n\n\n\n<p>p5.js uses <code>setup()<\/code> and <code>draw()<\/code> methods, just like Processing, and similar to Arduino. You&#8217;re going to use it to create an HTML text div element&nbsp;in the document, and when&nbsp;you receive serial data, you&#8217;ll use it to set the text and the position of the text element. &nbsp;Start with the <code>setup()<\/code> and <code>draw()<\/code> and global variables for the text element and a webSocket connection like so (from here on out, the rest of the HTML will be omitted&nbsp;for brevity. Everything you see below will be done in the <code>sketch.js<\/code> file. Here&#8217;s the final HTML:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;!DOCTYPE html&gt;\n&lt;html&gt;\n\n&lt;head&gt;\n  &lt;script type=&quot;text\/javascript&quot; src=&quot;https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/p5.js\/1.0.0\/p5.min.js&quot;&gt;&lt;\/script&gt;\n  &lt;script type=&quot;text\/javascript&quot; src=&quot;sketch.js&quot;&gt;&lt;\/script&gt;\n&lt;\/head&gt;\n\n&lt;body&gt;\n&lt;\/body&gt;\n\n&lt;\/html&gt;\n<\/pre><\/div>\n\n\n<p>Start the <code>sketch.js<\/code> file by making webSocket that will listen on port 8081. Then add the p5.js <code>setup()<\/code> and <code>draw()<\/code> functions:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nlet text;\t\t\/\/ variable for the text div you'll create\nlet socket = new WebSocket(\"ws:\/\/localhost:8081\");\n\nfunction setup() {\n}\n\nfunction draw() {\n}\n<\/pre><\/div>\n\n\n<p>In the <code>setup()<\/code> function, add listeners for the webSocket, and create the text div and position it. You&#8217;ll write the listener functions a bit later:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nfunction setup() {\n  \/\/ The socket connection needs two event listeners:\n  socket.onopen = openSocket;\n  socket.onmessage = showData;\n\n  \/\/ make a new div and position it at 10, 10:\n  text = createDiv(\"Sensor reading:\");\n  text.position(10,10);\n}\n\nfunction draw() {\n}\n<\/pre><\/div>\n\n\n<p>Next, write the <code>openSocket()<\/code> listener and showData functions which are the callback functions for the webSocket&#8217;s event listeners:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nfunction openSocket() {\n  text.html(\"Socket open\");\n  socket.send(\"Hello server\");\n}\n\nfunction showData(result) {\n  \/\/ result is a JSON string. Parse it:\n  let input = JSON.parse(result.data);\n  \/\/ when the server returns, show the result in the div:\n  text.html(\"Sensor reading:\" + input);\n  xPos = int(input);        \/\/ convert result to an integer\n  text.position(xPos, 10);        \/\/ position the text\n}\n<\/pre><\/div>\n\n\n<p>This last function&nbsp;changes the text inside the div. It also moves the div&#8217;s horizontal position. Whenever new data arrives from the server, this function will be called automatically, so there&#8217;s no need for a <code>draw()<\/code> function. Save this file in the <code>public<\/code> directory, then restart the server and open the file in your browser. &nbsp;You should see the text moving across the screen left to right, depending on the sensor, as in the video below. When the sensor value is high, its text representation will be to the right in the browser. When it&#8217;s low, it will be to the right in the browser: <\/p>\n\n\n\n<iframe loading=\"lazy\" src=\"https:\/\/player.vimeo.com\/video\/107957343\" width=\"640\" height=\"212\" frameborder=\"0\" allow=\"autoplay; fullscreen\" allowfullscreen=\"\"><\/iframe>\n<p><a href=\"https:\/\/vimeo.com\/107957343\">browser-animation<\/a> from <a href=\"https:\/\/vimeo.com\/itpred\">ITP_NYU<\/a> on <a href=\"https:\/\/vimeo.com\">Vimeo<\/a>.<\/p>\n\n\n\n<p>There is no soundtrack to this video. <\/p>\n\n\n\n<p>Once you&#8217;ve got a server program serving data from a serial device to a browser, you have potential to make&nbsp;all kinds dynamic interfaces that combine HTML and physical interfaces. Notice that the server program doesn&#8217;t actually parse the serial data; it just treats it as a string, and passes that string on to the client. The client does any parsing work; in this case, converting the numeric string to an integer. This means you can keep the server very simple, so you only need to make sure the two endpoints (the microcontroller and the web client) are speaking the same protocol. JavaScript has many functions&nbsp;for manipulating strings, particularly comma-separated values. So consider sending your data from Arduino as comma-separated values.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Note_Check_your_data_types\"><\/span>Note: Check your data types<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>When p5.js returns the result of a request, it returns the string as an array with one element.&nbsp;If you&#8217;re planning on manipulating that string with functions like parseInt(), <a rel=\"noopener\" href=\"http:\/\/p5js.org\/reference\/#\/p5\/split\">split()<\/a> and <a rel=\"noopener\" href=\"http:\/\/p5js.org\/reference\/#group-Data\">other string handling functions<\/a>, make sure to get&nbsp;the string out of the array first. For example, if you&#8217;ve sent over the string:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\n\"234, 124, 134\"\n<\/pre><\/div>\n\n\n<p>and you want to split it, here&#8217;s how you&#8217;d do it:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nfunction showData(result) {\n  var resultString = JSON.parse(result.data);\n  text.html(\"Sensor reading:\" + resultString);\n  \/\/ split it:\n  var numbers = split(resultString, \",\");\n  \/\/ use the numbers:\n  text.position(int(numbers&#x5B;0]), int(numbers&#x5B;1]));\n  text.style(\"font-size\", int(numbers&#x5B;2]) + \"%\");\n}\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Adding_Handshaking_aka_Call-and-Response\"><\/span>Adding Handshaking (aka Call-and-Response)<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Because the wsServer.js script passes through messages through without parsing, you can add handshaking to this application by modifying only the Arduino program and the P5.js script. When you add handshaking the Arduino will only send new data when it receives a byte of data in the serial port. It allows you to control the flow of data better.<\/p>\n\n\n\n<p>To implement handshaking, make the following change in the Arduino sketch. Wrap the contents of the <code>loop()<\/code> in the Arduino sketch in an if statement like so:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: arduino; highlight: [2,3,9]; title: ; notranslate\" title=\"\">\nvoid loop() {\n  if (Serial.available()) {\n    char input = Serial.read();\n    \/\/ read the input on analog pin 0:\n    int sensorValue = analogRead(A0);\n    \/\/ print out the value you read:\n    Serial.println(sensorValue);\n    delay(1); \/\/ delay in between reads for stability\n  }\n}\n<\/pre><\/div>\n\n\n<p>Then add the following line to the end of the <code>showData()<\/code> function in your p5.js sketch:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; highlight: [7]; title: ; notranslate\" title=\"\">\nfunction showData(result) {\n  \/\/ result is a JSON string. Parse it:\n  let input = JSON.parse(result.data);\n  \/\/ when the server returns, show the result in the div:\n  text.html(\"Sensor reading:\" + input);\n  xPos = int(input);        \/\/ convert result to an integer\n  text.position(xPos, 10);        \/\/ position the text\n  socket.send('a');        \/\/ send a byte to get the Arduino to send new data\n}\n<\/pre><\/div>\n\n\n<p>You won&#8217;t need to change the <code>wsServer.js <\/code>script at all. Just restart it after you upload to the Arduino, and reload the page in the browser. When the client connects to the server, it will send the &#8220;Hello&#8221; message, which will be sent from the server to the Arduino, and that will trigger the Arduino to start sending data.<\/p>\n\n\n\n<p>For more info:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a rel=\"noopener\" href=\"http:\/\/p5js.org\/\">P5.js<\/a><\/li><li><a rel=\"noopener\" href=\"http:\/\/nodejs.org\/\">node.js<\/a><\/li><li><a rel=\"noopener\" href=\"https:\/\/github.com\/voodootikigod\/node-serialport\">node serialport<\/a><\/li><\/ul>\n\n\n\n<p>A more complete set of code for this lab can be found on <a href=\"https:\/\/github.com\/ITPNYU\/physcomp\/tree\/master\/Labs\/Node%20Serial%20Lab\">gitHub<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this lab you\u2019ll connect a microcontroller to a web browser using the node.js programming environment, HTML, and JavaScript.<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":1979,"menu_order":231,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"categories":[11,15,16,26,9],"tags":[],"class_list":["post-2888","page","type-page","status-publish","hentry","category-code","category-lab","category-node-js","category-programming","category-serial-communication"],"_links":{"self":[{"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/pages\/2888"}],"collection":[{"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/comments?post=2888"}],"version-history":[{"count":99,"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/pages\/2888\/revisions"}],"predecessor-version":[{"id":8930,"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/pages\/2888\/revisions\/8930"}],"up":[{"embeddable":true,"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/pages\/1979"}],"wp:attachment":[{"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/media?parent=2888"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/categories?post=2888"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/tags?post=2888"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}