The Intel® XDK provides a cross-development environment for creating Node.js* IoT applications that run on headless embedded Linux* systems. The tools used to assemble this environment within the Intel® XDK are standard open-source tools. This article provides a starting point for assembling a similar set of tools for developing Node.js applications on headless IoT Linux devices.
Intel® XDK IoT Development Components
That part of the Intel® XDK that supports IoT application development includes the following key functional elements:
- An editor that is JavaScript* friendly.
- Tools to connect to headless IoT Linux devices.
- Samples that can be used to learn how to interact with I/O sensors.
- A means to remotely debug your Node.js application.
Useful alternatives to the first three components are described below. An alternative to the last component (remotely debugging your Node.js application) is described in a companion article titled Using Chrome DevTools to Debug your Remote IoT Node.js Application.
JavaScript* Friendly Editors
A variety of free JavaScript friendly editors can be used as alternatives to the Intel® XDK. In addition to the free open-source Brackets* editor from Adobe*, the editor built into the Intel® XDK, there is also the open-source Atom* editor from GitHub* and the free and open-source Visual Studio* Code editor from Microsoft*.
If you have been using the Intel® XDK it is not a requirement that you continue to use the Brackets editor. Ultimately, you should pick an editor that works for you, any of the free alternatives mentioned above will work, as well as many popular fee-based code editors such as Webstorm* by JetBrains* and Sublime Text* by Sublime HQ*.
Brackets
The editor built into the Intel® XDK is the Brackets open-source editor, which is sponsored by Adobe and was designed expressly for development of HTML5 (JavaScript, CSS and HTML) applications. In fact, the Brackets editor itself is an HTML5 app! The Brackets editor can be extended via many open-source extensions. Some extensions to consider adding to Brackets are:
Use this "javascript development with brackets" search link to find many other suggestions.
The Brackets editor runs on Microsoft Windows*, Apple macOS* and most distributions of the Linux* OS.
Atom
GitHub has created an open-source editor called Atom that, like Brackets, is also built on HTML5 technologies. It has many free packages which can be used to extend the editor. Some extensions to consider adding to Atom are:
NOTE: Of particular interest is the Nuclide package for Atom. This "add-on" provides built-in support for Chrome DevTools and remote development of Node.js applications, akin to that which is provided by the Intel® XDK.
Use this "javascript development with atom" search link to find many other suggestions.
The Atom editor runs on Microsoft Windows, Apple macOS and most distributions of the Linux OS.
Visual Studio* Code
The Visual Studio* Code editor is a general-purpose open-source programming editor from Microsoft that includes many features that are specific to developing JavaScript applications, as well as extensions for JavaScript and Node.js application development. Despite this editor's name, a Microsoft Visual Studio* license is not required to use the editor, nor does its use depend on having Visual Studio installed on your system. It is a standalone editor. Some extensions to consider adding to Visual Studio Code are:
- git support is built into this editor
- ESLint
- npm IntelliSense
- Debugger for Chrome*
Use this "javascript development with visual studio code" search link to find many other suggestions.
The Visual Studio Code editor runs on Microsoft Windows, Apple macOS and most distributions of the Linux OS.
Connecting to Headless IoT Devices
On the Intel® XDK IoT Develop tab there are several features to help you locate a headless Linux IoT device on your network, login to your IoT device and transfer project files to your device. You can use the following tools and techniques to perform similar tasks if you are working outside of the Intel® XDK:
- ssh to remotely login to an IoT device.
- MDNS (aka Boujour or Avahi) to locate IoT devices by name.
- SSHFS to share project files with your IoT device.
Enabling Remote Login using SSH
Remote login into your Linux IoT target device is most easily accomplished by using SSH. This allows you to get a shell prompt over the network, from your host development system to your IoT target device. Using this feature requires an SSH client on your development machine (aka PuTTY on many Windows machines) and an SSH server on your IoT target.
NOTE: Some IoT targets include a serial TTY port that can be used to obtain access to a login shell. Technically, this is not a "remote login" because you must physically connect your host development machine to your IoT target, usually via a serial over USB connection or a conventional RS-232 or "TTL" serial port. You will need to use this serial TTY port to install and configure an SSH server if your IoT device does not support the use of a keyboard and monitor.
Depending on the Linux distribution that is installed on your IoT target device, there may already be an SSH server installed. If you are using an IoT device that you previously used with the Intel® XDK, it should already have an SSH server running on it. If not, you may have to install an SSH server on your IoT device to enable remote login using SSH.
If there is no sshd
(or equivalent ssh server) running on your Linux IoT device, type the following command at a bash command-line prompt on your IoT device (these instructions assume an Ubuntu* distribution, other Linux distributions may require different instructions):
$ sudo apt install openssh-server
NOTE: The Intel® XDK requires that you enable the ability to remote into your IoT device as root, because the xdk-daemon
assumes, and the mraa
library requires, that your IoT applications run with root privileges. This is an overly restrictive limitation that is not otherwise required. If you want to enable remote login as root, search for "enabling root login via ssh" for details.
If you do not want to add a root user to your remote IoT device, a convenient way to "become root" temporarily is to use the "sudo -E bash" command. This will allow you to act like a root user and will retain your regular user's environment and home directory. When you no longer need to "be root" simply type "exit" to return to your regular user shell session.
Once the SSH service has been enabled on your IoT target device, you can use your favorite SSH client to login to your IoT device over the network. Depending on your network configuration, you may have to identify your IoT device by its numerical IP address to establish a remote SSH connection. See the next section for a solution to that problem.
From an Apple macOS* machine, a Linux* desktop or a Microsoft Windows® 10 machine that has "Bash on Windows" enabled, the simplest way to remotely login to your IoT device is by using the "ssh" command (substitute the username and IP address for your IoT device):
$ ssh my-iot-username@192.168.2.15
The IP address 192.168.2.15 shown above is a placeholder and will probably not work! You must use the IP address of your IoT device to establish a remote ssh connection!!
If you do not have "Bash on Windows" enabled (or you have an older version of Windows) you can install the MinGW MSYS utilities for a copy of the ssh command that will run directly from a Windows command prompt or from within the MSYS bash prompt (remember to add the MSYS utilities to your PATH). Otherwise, a free and popular alternative to ssh for Windows development hosts is the PuTTY ssh and telnet client.
Adding MDNS Services to Your IoT Device
If you are working on a small or unmanaged network (such as the typical home network), you likely do not have a name server to help locate your IoT device by name. Unless you have specifically configured your router's DHCP services to provide a fixed IP address to your IoT device, the IP address associated with your IoT device is subject to change.
To address this problem add MDNS (Avahi) services to your Linux IoT device. This technique is used by the Intel® XDK to identify and locate IoT devices. The use of MDNS is limited to those situations where your development system (e.g., your laptop) and your IoT device reside on the same subnet (which is typical of most home networks).
NOTE: The precise instructions to install MDNS on your target IoT device will vary as a function of the specific Linux distribution that is installed on your IoT device. The instructions below assume your IoT device is running Ubuntu.
If your IoT target device is running Ubuntu, type the following commands on your remote IoT device shell (i.e., you are logged into your IoT device via a remote shell using ssh/PuTTY or the IoT device's open TTY serial port, if it has one):
$ sudo -E apt install avahi-daemon avahi-autoipd avahi-utils
Then test the MDNS service by typing the following commands via the same remote shell on your IoT device:
$ sudo systemctl is-active avahi-daemon.service active $ ping $HOSTNAME.local PING my-iot-ubuntu.local (10.7.188.149) 56(84) bytes of data. 64 bytes from my-iot-ubuntu.intel.com (10.7.188.149): icmp_seq=1 ttl=64 time=0.051 ms 64 bytes from my-iot-ubuntu.intel.com (10.7.188.149): icmp_seq=2 ttl=64 time=0.090 ms
If you see results similar to those above, your MDNS service is running on your IoT device.
With the MDNS service installed and running on your IoT device, you can quickly identify your IoT device using the special local
domain that is employed by MDNS/Avahi/Bonjour (assuming, of course, that you know the hostname of your IoT device and your IoT device and development system are on the same local subnet).
On a typical Ubuntu Desktop or Apple macOS machine the MDNS/Bonjour/Avahi services and utilities are already installed. In that case, type the following command at a terminal shell on your Apple or Ubuntu Linux development machine:
$ ping my-iot-hostname.local
Where "my-iot-hostname" is the base hostname of your IoT device. For example, using the results of the earlier on-device"ping $HOSTNAME.local
" test, the following command typed on your development system would locate and identify that IoT device:
$ ping my-iot-ubuntu.local
A Windows machine needs the Apple Bonjour Service installed to perform this ping test. The Bonjour service is typically included with iTunes or any one of a variety of other applications that employ MDNS (typically software designed to support networked printers, media servers and NAS drives on unmanaged networks). To determine if the Bonjour service is already running on your Windows system, type the following at a Windows command prompt:
> net start | find "Bonjour" Bonjour Service
If you see the output "Bonjour Service" it means MDNS/Avahi/Bonjour is installed and running on your Windows system. In that case, the ping test described above will also work from a Windows command line.
If the Bonjour service is not running on your Windows system, it may have been disabled or you may need to install it. To install the Bonjour service, install iTunes or use the "Bonjour Print Services for Windows" installer available at support.apple.com/bonjour.
For more information about installing and configuring MDNS/Avahi/Bonjour, see the following:
- wiki.archlinux.org/index.php/avahi
- en.wikipedia.org/wiki/Avahi_(software)
- blog.uguu.waw.pl/2015/05/21/mdns-netbsd-linux-osx
Using SSHFS to Share Files
When developing applications for a headless IoT target, it is generally easier to run your development tools (editor, package manager, debugger, etc.) on your development host (your laptop or desktop machine) and then copy the application you are developing to your IoT device, where you can then run it. You may be able to run your development tools directly on your IoT device, but if your IoT target is headless, has limited RAM and storage space, or is physically inaccessible, using your IoT device as your development host is not practical.
Developing Node.js JavaScript applications for your IoT device is more difficult when you separate the development host system from the target runtime system. Because Node.js applications are not compiled into a single executable, like a typical C/C++ application, you need a way to efficiently and accurately copy all the Node.js application files to your IoT device for testing and debugging.
With the Intel® XDK, development is performed locally on your host dev machine and your project is copied to your IoT target device to run and debug. In essence, the Intel® XDK would TAR the local project folder on your host, copy it to your target device and unTAR it on the target device (into a folder named "/node_app_slot"). To duplicate this process manually, you could do something like the following (assuming a folder named "node_app_slot" already exists on the target device).
First, on the host development machine:
$ cd my-project-folder $ tar cvjhf my-project.tgz * $ scp my-project.tgz user@iot-hostname.local: $ ssh iot-username@iot-hostname.local
Then, on the remote IoT device (using the remote ssh channel that was opened in the prior step):
$ cd node_app_slot $ rm -rf * $ tar xvf ../my-project.tgz
After your application files have been copied to your IoT device you can commence with package installation (if required) and running and debugging the application.
Obviously, the above process is very tedious if you are making many small changes to your code and/or need to install NPM packages as part of the installation of the application onto your IoT device.
NOTE: It is important that installation of node packages, especially those that include installation of binary components, be done on the target device, not on the host. This is done to insure that the binary components of the node package match the architecture and OS of the system that will be using them (i.e., your IoT target device).
If the architecture and the OS on your target IoT device match your host development machine, you can perform the installation of NPM packages on your host, before copying your project to the IoT target.
There are many optimizations that can be made to this process, such as copying across only those files that have been added or changed. Another optimization is to use the "scp -r" option and skip the tar/untar step. Even faster would be to use the "rsync" tool to keep your host and target project folders mirrored and in sync (keep in mind the issues regarding NPM package installation). Trying to manage this process by hand is clumsy and error prone.
Using a Network File system, Instead
Rather than using the copy method described above, you can manage a single set of sources and project by using a shared network file system. There are essentially two ways to approach this:
- Export an application project folder on the target and mount it on the host
- Export an application project folder on the host and mount it on the target
Option #2 has the advantage of insuring your project source code "lives" on your host development system. This makes it easy to manage and backup your application source code files.
Option #1 has the advantage of being easier to setup and implement on a variety of IoT devices. This option also insures that the application code to be run resides on the device that is running the code, which is important if you experience network file system delays and/or disconnects while running and testing your application. These network interruptions are a significant problem for scripted languages that are interpreted at runtime, like Node.js applications.
NOTE: The simplest way to implement option #1 is to use SSHFS. Since you already have an SSH server on your IoT target, there is no additional software to install on your target IoT device (such as a Samba server or similar network file system). This is especially helpful for working with resource limited IoT devices.
To understand how to use SSHFS for this task, read the first page of this article. There may be additional software required to install on your host development system to make SSHFS work. For a review of how to install this additional software on your host development system, see this excellent installation article.
In essence, once you have the SSHFS software installed on your host development system, you will issue a command that looks something like the following (on your host development machine):
$ sshfs user@my-iot-device.local: my-host-mount-folder
This will result in mounting your IoT device's remote file system and making it visible at <my-host-mount-folder> on your host development system.
Once mounted, you can use your favorite editor and other tools to work on the application. You will also need to initiate a parallel SSH connection to your remote IoT device to deal with installing NPM packages and running the application (on your IoT device). Be sure to make backups of the sources located on this remote IoT project folder, either onto another location on your host system or into a cloud repository, to insure that you do not lose your source code in the event something happens to your IoT device!
For help using remote Chrome DevTools session to debug your remote Node.js IoT application see this companion article.
NOTE: The Nuclide package for Atom "add-on" also provides built-in support for Chrome DevTools and remote development of Node.js applications, similar to the SSHFS method described above, but within a complete development environment.
JavaScript* Samples Written for Node.js* IoT Devices
The IoT Node.js samples included with the Intel® XDK are published in the Intel managed IoT DevKit GitHub* account and GoMobile GitHub* account, specifically, in these repos:
The majority of these samples rely on the open-source MRAA and UPM libraries for access to local device I/O (a few samples require only the MRAA library to function). The MRAA and UPM Linux libraries provide access to low speed sensors, serial communication ports and actuator outputs. They are written in C/C++ and include API bindings for the Python, JavaScript (Node.js) and Java* languages.
A special service called imraa
is included with MRAA to utilize an Arduino 101* (branded Genuino 101* outside the U.S.) board attached to your IoT target device via USB as an "I/O extender" for easy prototyping of IoT "edge device" applications, by way of the firmata
sketch software.
For additional details regarding the MRAA and UPM libraries, see the following pages:
- MRAA doc pages and the UPM doc pages for API details
- MRAA readme page for a complete list of supported IoT hardware platforms
- Installing MRAA on your IoT device
- Installing UPM on your IoT device
Installing MRAA and UPM
Before you can use these samples you need to confirm that you have the MRAA library and (optionally) appropriate UPM libraries installed on your IoT target device. To determine if mraa
is installed as a global node module, and that it can be included in a Node.js application, type the following at your IoT device prompt:
$ npm -g list --depth=0 /usr/lib ├── mraa@1.6.1 └── npm@2.15.11 $ node > var x = require('mraa') undefined> x.getVersion()'v1.6.1'> .exit
The specific versions reported by your system may vary from those shown above.
NOTE: Installing the MRAA and UPM libraries globally is not a requirement, it is done only as a convenience, especially if you are developing many applications that depend on these libraries. If you prefer, you can install the necessary MRAA and UPM libraries as local node modules within your application project workspace.
The following commands assume the use of an Ubuntu IoT device. For other Linux distributions, see the MRAA installation instructions.
At the time this article was written the MRAA library did not support Node.js 7.x or higher. Please check the MRAA library README for the latest information regarding which versions of Node.js are supported by MRAA.
$ sudo add-apt-repository ppa:mraa/mraa $ sudo apt update $ sudo apt install libmraa1 libmraa-dev mraa-tools mraa-imraa python-mraa python3-mraa
The update command (middle line above) may take some time to complete, be patient!
To confirm that the imraa service was successfully installed, type the following on your IoT target device command-line:
$ which imraa /usr/bin/imraa
Now install the mraa node module (the version number you see reported may vary from below):
$ sudo npm -g install mraa> mraa@1.6.1 install /usr/lib/node_modules/mraa> node-gyp rebuild ...many compile messages, with many warnings... SOLINK_MODULE(target) Release/obj.target/mraa.node COPY Release/mraa.node make: Leaving directory '/usr/lib/node_modules/mraa/build' mraa@1.6.1 /usr/lib/node_modules/mraa
Do not be alarmed by the many warning messages during the compilation phase of the installation. This is normal.
NOTE: Install only those UPM modules you need for the samples that interest you. It is not necessary to install every UPM library module available in the UPM repo.