Node.js based Web Application for mbed Device Connector specific to GR-PEACH_mbed-os-client-ZXingSample

Getting Started

Installing Node.js and npm

You need to have Node.js and npm installed.

To check if you have them installed, open a terminal or command prompt and run the following commands:

node --version
npm --version

If you see an number output similar to x.x.x for each command, then they are both installed and you can continue to the next section.

To install on Windows or mac, you can download the installer from https://nodejs.org/en/download.

To install on Linux, you can use a package manager. Instructions for installing Node.js on your distribution can be found in the following link:
https://nodejs.org/en/download/package-manager

Pre-requisite

This example assumes that you have the following example that can connect to mbed Device Connector:

Import programGR-PEACH_mbed-os-client-ZXingSample

This is a mbed Client sample where ZXing is incorporated, and works on GR-PEACH and GR-LYCHEE.

Configuring the App

Before running this app, you need to set some config options. This is done through environment variables or .env file stored in the root of the project.

The following variables are available to be configured:

  • ACCESS_KEY
    Set this to your Access Key you created in mbed Device Connector. If you don't have an Access Key, please create it by the following procedure:
    1. Access https://connector.mbed.com/#accesskeys.
    2. Click Create New Access Key.
    /media/uploads/HinoNaka/screenshot7.png
    When prompted, enter a name for the access key (ex. "demo") and click ADD.
    /media/uploads/HinoNaka/screenshot8.png
    3. Copy the access key you just created and use it in .env file.

  • PORT:
    Set this to override the default port for this example. The default port is 8080.

The .env file format is as follows:

ACCESS_KEY=Your ACCESS KEY
PORT=Port to be overridden (This is optional and can be omitted.)

Configuring the App

Once you've configured the example, you need to install its dependencies. Open a terminal or command prompt and run the following command:

npm install

If all the dependencies successfully installed, you can now run the app by using the following command:

node app.js

You should receive the following output:

mbed Device Connector Quickstart listening at http://localhost:8080

Copy and paste the printed URL into your browser and you should see the following screen: /media/uploads/HinoNaka/screenshot9-1.png

Deploying this example on HEROKU

HEROKU ( https://id.heroku.com ) is PaaS (Platform as a Service) on which Node.js application can deploy free-of charge. By utilizing it, user can confirm the decode result and control LED blink from your mobile terminal.

Here is the procedure to deploy this application on HEROKU:

  1. Create your HEROKU account at https://signup.heroku.com/login if you haven't created it yet.
  2. Open a terminal or command prompt and invoke the command heroku login. If Email and password is required, please type those registered at the step 1.
  3. Invoke git init to create a local git repository.
  4. Invoke git add . to add all the files to the local repository.
  5. Invoke git commit -m "[commit message]" to commit the files.
  6. Invoke heroku create at the root of the project. When successfully terminated, the remote repository heroku should be created and associated with the local repository.
  7. Invoke git push heroku master. When successfully terminated, this example application should be deployed on HEROKU.
  8. Invoke heroku open. If the example is successfully deployed, Webapp Quickstart shown above should be displayed on your browser. Also, by accessing the URL shown in the browser from your mobile terminal (e.g. iPhone), you can confirm the decode result and control LED blink from there.

    /media/uploads/HinoNaka/screenshot10.png
Committer:
Osamu Nakamura
Date:
Fri Mar 10 15:45:44 2017 +0900
Revision:
4:a682455428ae
Parent:
0:ee84b944af4c
Added .env file to the root of project

Who changed what in which revision?

UserRevisionLine numberNew contents of line
HinoNaka 0:ee84b944af4c 1 // Load .env config (silently fail if no .env present)
HinoNaka 0:ee84b944af4c 2 require('dotenv').config({ silent: true });
HinoNaka 0:ee84b944af4c 3
HinoNaka 0:ee84b944af4c 4 // Require necessary libraries
HinoNaka 0:ee84b944af4c 5 var async = require('async');
HinoNaka 0:ee84b944af4c 6 var ioLib = require('socket.io');
HinoNaka 0:ee84b944af4c 7 var http = require('http');
HinoNaka 0:ee84b944af4c 8 var path = require('path');
HinoNaka 0:ee84b944af4c 9 var express = require('express');
HinoNaka 0:ee84b944af4c 10 var MbedConnectorApi = require('mbed-connector-api');
HinoNaka 0:ee84b944af4c 11
HinoNaka 0:ee84b944af4c 12 // CONFIG (change these)
HinoNaka 0:ee84b944af4c 13 var accessKey = process.env.ACCESS_KEY || "ChangeMe";
HinoNaka 0:ee84b944af4c 14 var port = process.env.PORT || 8080;
HinoNaka 0:ee84b944af4c 15
HinoNaka 0:ee84b944af4c 16 // Paths to resources on the endpoints
HinoNaka 0:ee84b944af4c 17 var blinkResourceURI = '/3201/0/5850';
HinoNaka 0:ee84b944af4c 18 var blinkPatternResourceURI = '/3201/0/5853';
HinoNaka 0:ee84b944af4c 19 var colorResourceURI = '/3201/0/5855';
HinoNaka 0:ee84b944af4c 20 var ZXingURI = '/3202/0/5700';
HinoNaka 0:ee84b944af4c 21
HinoNaka 0:ee84b944af4c 22 // Instantiate an mbed Device Connector object
HinoNaka 0:ee84b944af4c 23 var mbedConnectorApi = new MbedConnectorApi({
HinoNaka 0:ee84b944af4c 24 accessKey: accessKey
HinoNaka 0:ee84b944af4c 25 });
HinoNaka 0:ee84b944af4c 26
HinoNaka 0:ee84b944af4c 27 // Create the express app
HinoNaka 0:ee84b944af4c 28 var app = express();
HinoNaka 0:ee84b944af4c 29 app.set('views', path.join(__dirname, 'views'));
HinoNaka 0:ee84b944af4c 30 app.set('view engine', 'hbs');
HinoNaka 0:ee84b944af4c 31 app.use(express.static(path.join(__dirname, 'public')));
HinoNaka 0:ee84b944af4c 32
HinoNaka 0:ee84b944af4c 33 app.get('/', function (req, res) {
HinoNaka 0:ee84b944af4c 34 // Get all of the endpoints and necessary info to render the page
HinoNaka 0:ee84b944af4c 35 mbedConnectorApi.getEndpoints(function(error, endpoints) {
HinoNaka 0:ee84b944af4c 36 if (error) {
HinoNaka 0:ee84b944af4c 37 throw error;
HinoNaka 0:ee84b944af4c 38 } else {
HinoNaka 0:ee84b944af4c 39 // Setup the function array
HinoNaka 0:ee84b944af4c 40 var functionArray = endpoints.map(function(endpoint) {
HinoNaka 0:ee84b944af4c 41 return function(mapCallback) {
HinoNaka 0:ee84b944af4c 42 mbedConnectorApi.getResourceValue(endpoint.name, blinkPatternResourceURI, function(error, value) {
HinoNaka 0:ee84b944af4c 43 endpoint.blinkPattern = value;
HinoNaka 0:ee84b944af4c 44 mbedConnectorApi.getResourceValue(endpoint.name, colorResourceURI, function(error, value) {
HinoNaka 0:ee84b944af4c 45 endpoint.color = value;
HinoNaka 0:ee84b944af4c 46 mapCallback(error);
HinoNaka 0:ee84b944af4c 47 });
HinoNaka 0:ee84b944af4c 48 });
HinoNaka 0:ee84b944af4c 49 };
HinoNaka 0:ee84b944af4c 50 });
HinoNaka 0:ee84b944af4c 51
HinoNaka 0:ee84b944af4c 52 // Fetch all blink patterns in parallel, finish when all HTTP
HinoNaka 0:ee84b944af4c 53 // requests are complete (uses Async.js library)
HinoNaka 0:ee84b944af4c 54 async.parallel(functionArray, function(error) {
HinoNaka 0:ee84b944af4c 55 if (error) {
HinoNaka 0:ee84b944af4c 56 res.send(String(error));
HinoNaka 0:ee84b944af4c 57 } else {
HinoNaka 0:ee84b944af4c 58 res.render('index', {
HinoNaka 0:ee84b944af4c 59 endpoints: endpoints
HinoNaka 0:ee84b944af4c 60 });
HinoNaka 0:ee84b944af4c 61 }
HinoNaka 0:ee84b944af4c 62 });
HinoNaka 0:ee84b944af4c 63 }
HinoNaka 0:ee84b944af4c 64 });
HinoNaka 0:ee84b944af4c 65 });
HinoNaka 0:ee84b944af4c 66
HinoNaka 0:ee84b944af4c 67 // Handle unexpected server errors
HinoNaka 0:ee84b944af4c 68 app.use(function(err, req, res, next) {
HinoNaka 0:ee84b944af4c 69 console.log(err.stack);
HinoNaka 0:ee84b944af4c 70 res.status(err.status || 500);
HinoNaka 0:ee84b944af4c 71 res.render('error', {
HinoNaka 0:ee84b944af4c 72 message: err.message,
HinoNaka 0:ee84b944af4c 73 error: err
HinoNaka 0:ee84b944af4c 74 });
HinoNaka 0:ee84b944af4c 75 });
HinoNaka 0:ee84b944af4c 76
HinoNaka 0:ee84b944af4c 77 var sockets = [];
HinoNaka 0:ee84b944af4c 78 var server = http.Server(app);
HinoNaka 0:ee84b944af4c 79 var io = ioLib(server);
HinoNaka 0:ee84b944af4c 80
HinoNaka 0:ee84b944af4c 81 // Setup sockets for updating web UI
HinoNaka 0:ee84b944af4c 82 io.on('connection', function (socket) {
HinoNaka 0:ee84b944af4c 83 // Add new client to array of client upon connection
HinoNaka 0:ee84b944af4c 84 sockets.push(socket);
HinoNaka 0:ee84b944af4c 85
HinoNaka 0:ee84b944af4c 86 socket.on('subscribe-to-decode', function (data) {
HinoNaka 0:ee84b944af4c 87 // Subscribe to all changes of resource /3202/0/5700 (Barcode decoded Data)
HinoNaka 0:ee84b944af4c 88 mbedConnectorApi.putResourceSubscription(data.endpointName, ZXingURI, function(error) {
HinoNaka 0:ee84b944af4c 89 if (error) throw error;
HinoNaka 0:ee84b944af4c 90 socket.emit('subscribed-to-decode', {
HinoNaka 0:ee84b944af4c 91 endpointName: data.endpointName
HinoNaka 0:ee84b944af4c 92 });
HinoNaka 0:ee84b944af4c 93 });
HinoNaka 0:ee84b944af4c 94 });
HinoNaka 0:ee84b944af4c 95
HinoNaka 0:ee84b944af4c 96 socket.on('unsubscribe-to-decode', function(data) {
HinoNaka 0:ee84b944af4c 97 // Unsubscribe from the resource /3202/0/5700 (Barcode decoded Data)
HinoNaka 0:ee84b944af4c 98 mbedConnectorApi.deleteResourceSubscription(data.endpointName, ZXingURI, function(error) {
HinoNaka 0:ee84b944af4c 99 if (error) throw error;
HinoNaka 0:ee84b944af4c 100 socket.emit('unsubscribed-to-decode', {
HinoNaka 0:ee84b944af4c 101 endpointName: data.endpointName
HinoNaka 0:ee84b944af4c 102 });
HinoNaka 0:ee84b944af4c 103 });
HinoNaka 0:ee84b944af4c 104 });
HinoNaka 0:ee84b944af4c 105
HinoNaka 0:ee84b944af4c 106 socket.on('get-decode', function(data) {
HinoNaka 0:ee84b944af4c 107 // Read data from GET resource /3202/0/5700 (Barcode decoded Data)
HinoNaka 0:ee84b944af4c 108 mbedConnectorApi.getResourceValue(data.endpointName, ZXingURI, function(error, value) {
HinoNaka 0:ee84b944af4c 109 if (error) throw error;
HinoNaka 0:ee84b944af4c 110 socket.emit('decode', {
HinoNaka 0:ee84b944af4c 111 endpointName: data.endpointName,
HinoNaka 0:ee84b944af4c 112 value: value
HinoNaka 0:ee84b944af4c 113 });
HinoNaka 0:ee84b944af4c 114 });
HinoNaka 0:ee84b944af4c 115 });
HinoNaka 0:ee84b944af4c 116
HinoNaka 0:ee84b944af4c 117 socket.on('update-blink-pattern', function(data) {
HinoNaka 0:ee84b944af4c 118 // Set data on PUT resource /3201/0/5853 (pattern of LED blink)
HinoNaka 0:ee84b944af4c 119 mbedConnectorApi.putResourceValue(data.endpointName, blinkPatternResourceURI, data.blinkPattern, function(error) {
HinoNaka 0:ee84b944af4c 120 if (error) throw error;
HinoNaka 0:ee84b944af4c 121 });
HinoNaka 0:ee84b944af4c 122 });
HinoNaka 0:ee84b944af4c 123
HinoNaka 0:ee84b944af4c 124 socket.on('update-color', function(data) {
HinoNaka 0:ee84b944af4c 125 // Set data on PUT resource /3201/0/5855 (LED color)
HinoNaka 0:ee84b944af4c 126 mbedConnectorApi.putResourceValue(data.endpointName, colorResourceURI, data.color, function(error) {
HinoNaka 0:ee84b944af4c 127 if (error) throw error;
HinoNaka 0:ee84b944af4c 128 });
HinoNaka 0:ee84b944af4c 129 });
HinoNaka 0:ee84b944af4c 130
HinoNaka 0:ee84b944af4c 131 socket.on('blink', function(data) {
HinoNaka 0:ee84b944af4c 132 // POST to resource /3201/0/5850 (start blinking LED)
HinoNaka 0:ee84b944af4c 133 mbedConnectorApi.postResource(data.endpointName, blinkResourceURI, null, function(error) {
HinoNaka 0:ee84b944af4c 134 if (error) throw error;
HinoNaka 0:ee84b944af4c 135 });
HinoNaka 0:ee84b944af4c 136 });
HinoNaka 0:ee84b944af4c 137
HinoNaka 0:ee84b944af4c 138 socket.on('disconnect', function() {
HinoNaka 0:ee84b944af4c 139 // Remove this socket from the array when a user closes their browser
HinoNaka 0:ee84b944af4c 140 var index = sockets.indexOf(socket);
HinoNaka 0:ee84b944af4c 141 if (index >= 0) {
HinoNaka 0:ee84b944af4c 142 sockets.splice(index, 1);
HinoNaka 0:ee84b944af4c 143 }
HinoNaka 0:ee84b944af4c 144 })
HinoNaka 0:ee84b944af4c 145 });
HinoNaka 0:ee84b944af4c 146
HinoNaka 0:ee84b944af4c 147 // When notifications are received through the notification channel, pass the
HinoNaka 0:ee84b944af4c 148 // button presses data to all connected browser windows
HinoNaka 0:ee84b944af4c 149 mbedConnectorApi.on('notification', function(notification) {
HinoNaka 0:ee84b944af4c 150 if (notification.path === ZXingURI) {
HinoNaka 0:ee84b944af4c 151 sockets.forEach(function(socket) {
HinoNaka 0:ee84b944af4c 152 socket.emit('decode', {
HinoNaka 0:ee84b944af4c 153 endpointName: notification.ep,
HinoNaka 0:ee84b944af4c 154 value: notification.payload
HinoNaka 0:ee84b944af4c 155 });
HinoNaka 0:ee84b944af4c 156 });
HinoNaka 0:ee84b944af4c 157 }
HinoNaka 0:ee84b944af4c 158 });
HinoNaka 0:ee84b944af4c 159
HinoNaka 0:ee84b944af4c 160 // Start the app
HinoNaka 0:ee84b944af4c 161 server.listen(port, function() {
HinoNaka 0:ee84b944af4c 162 // Set up the notification channel (pull notifications)
HinoNaka 0:ee84b944af4c 163 mbedConnectorApi.startLongPolling(function(error) {
HinoNaka 0:ee84b944af4c 164 if (error) throw error;
HinoNaka 0:ee84b944af4c 165 console.log('mbed Device Connector Quickstart listening at http://localhost:%s', port);
HinoNaka 0:ee84b944af4c 166 })
HinoNaka 0:ee84b944af4c 167 });