Internet of Customers – Node.js, Socket.IO and nForce on Heroku

[easy-social-share counters=1 total_counter_pos="leftbig"]
Internet of Customers – Node.js, Socket.IO and nForce on Heroku

To complete the demonstration shown in Heroku, Arduino and Salesforce.com for Customer Service, we finally turn our attentions to the server side portion of the architecture. In this post we will share how Heroku was used to run a Node.js application that queried Salesforce.com via the nForce package to find an account matching the RFID code sent by the Arduino, finally sending any cases for the account over Socket.IO back to an application dashboard pictured below.

IOC-App
Thanks to the Start Bootstrap group for base UI template I modified.

Setting Up Your Application – OAuth
In order to communicate with Salesforce, you will need to setup an “app”. The steps are detailed at Creating a Custom Apps. Once you have gone through the steps, make note of your Consumer Key and Consumer Secret (blurred out in the example below). For the example, don’t worry about the callback URL (http://localhost:3001/oauth/_callback), as unlike standard OAuth patterns we are not going to directly interact with the Salesforce login – our Node.js application with nForce will do it for us. For full details take a look at the readme / setup information on the GitHub page for nForce.

Connected_App__IOCNode___salesforce_com_-_Developer_Edition

Using Heroku
If you have not used Heroku before, check out Using Web Sockets on Heroku to get a sense of what was involved getting a basic setup working with Heroku’s Toolbelt to get their sample running locally. This was used as the starting point for this proof.

It is especially important to become familiar with Node Package Manager, as it will act as the workhorse to ensure that you have all of the packages (think of them as “libraries” in more general development terms) required for the project. Thankfully, the package.json file within the project files will help to make getting the packages needed a single operation using the following command line.

npm install

It even ensures that it respects particular versions of packages. Take a look at the sample files for detail.

Key Node Files

  • app.js – this exact file name is not required, but in our example, app.js works as the heart of our application
  • package.json – contains references to the packages that are required for the application. Once the project is loaded into a directory, the “npm install” command can be run to download them.
  • .env – contains environment variables, making it easy to have various constants that are specific to an environment. This is where we place things like our OAuth codes in our proof.
  • views/dashboard.html – our sample dashboard that the Node application will communicate with using Web Sockets
  • procfile – what will be run by default when our application is loaded into a Heroku Dyno

Key Packages used in our Proof
Using the well documented nForce package from Kevin O’Hara, it was amazingly easy to communicate with Salesforce. The library acts as a REST API wrapper for force.com and allows easy interaction via SOQL with Salesforce objects.

We additionally use the express web application framework and the Socket.IO library to round out our proof, adding a dashboard UI and communication mechanism between clients and our Node application.

Working locally with the Node.js application was done via the Heroku Toolbelt, making running the sample as easy as typing the following foreman command once the application was setup.

foreman start

If all goes well, you will see the following output within your console. The best way to get started is to ensure that you can run the basic web sockets sample from the Heroku developer center.

IOC-Sockets

Socket.IO on the Server and Client
Our proof uses Socket.IO to send the matching results of Salesforce Cases to the client on the basis of a custom field for the account that holds the RFID tag value. The

Server

The following excerpt from app.js shows the key areas where we include socket.io, then use its emit method to send our servicedata to the client over web sockets.

var app = express()
  , http = require('http')
  , server = http.createServer(app)
  , io = require('socket.io').listen(server);

// the env.PORT values are stored in the .env file, as well as authentication information needed for nForce
var port = process.env.PORT || 3001; // use port 3001 if localhost (e.g. http://localhost:3001)
...
server.listen(port);

// dashboard.html will be sent to requesting user at root - http://localhost:3001
app.get('/', function (req, res) {
  res.sendfile(__dirname + '/views/dashboard.html');
});

...

app.put('/card', function(req, res) {
  ...
  var scannedid = req.body.carddata.cardid;
  console.log(scannedid);

  // SOQL query to get Account and related Cases based on custom field of RFID_Code__c
  org.query("SELECT Account.id, Account.name, (SELECT Case.Id, Case.CaseNumber, Case.IsClosed, Case.LastModifiedDate, Case.Subject, Case.Reason, Case.Description FROM Account.Cases ORDER BY Case.LastModifiedDate DESC) FROM Account WHERE Account.RFID_Code__c LIKE '"+scannedid+"'", oauth, function(err, resp){

    console.log(resp.records[0].Cases);

    // send all response data to client to view all attributes of object within the a browser console
    io.sockets.emit("servicedata", resp.records[0]);

    res.send({});
  });
});

Client

After we include the socket.io library, we have access to the servicedata event, from which we can get our results in the message object. The following is an excerpt of the key sections.

        
        ...
        

Node.js Application with Socket.IO and nForce
The following is our main code. Please keep in mind that this is a proof and was put together to showcase a general idea. It is not intended for production.

/*
  Node.js application running on Heroku that connects to Salesforce.com
  using the nForce package to query support information for a customer based
  on an RFID custom field for an account.  The application then uses Socket.IO
  to update any clients browing a dashboard at http://localhost:3001

  Resources used
  nForce package - https://github.com/kevinohara80/nforce nforce is a node.js salesforce REST API wrapper for force.com, database.com, and salesforce.com.  Thanks to https://twitter.com/kevino80
  Express web application framework - http://expressjs.com/
  Socket.IO web socket library - http://socket.io/

  more details at www.johnbrunswick.com
*/
var express=require('express');
var nforce = require('nforce');

var app = express()
  , http = require('http')
  , server = http.createServer(app)
  , io = require('socket.io').listen(server);

// the env.PORT values are stored in the .env file, as well as authentication information needed for nForce
var port = process.env.PORT || 3001; // use port 3001 if localhost (e.g. http://localhost:3001)
var oauth;

// configuration
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.static(__dirname + '/public'));

server.listen(port);

// dashboard.html will be sent to requesting user at root - http://localhost:3001
app.get('/', function (req, res) {
  res.sendfile(__dirname + '/views/dashboard.html');
});

// use the nforce package to create a connection to salesforce.com
var org = nforce.createConnection({
  clientId: process.env.CLIENT_ID,
  clientSecret: process.env.CLIENT_SECRET,
  redirectUri: 'http://localhost:' + port + '/oauth/_callback',
  apiVersion: 'v24.0',  // optional, defaults to v24.0
});

// authenticate using username-password oauth flow
org.authenticate({ username: process.env.USERNAME, password: process.env.PASSWORD }, function(err, resp){
  if(err) {
    console.log('Error: ' + err.message);
  } else {
    console.log('Access Token: ' + resp.access_token);
    oauth = resp;
  }
});

app.put('/card', function(req, res) {
  console.log('PUT CARD received');
  console.log(req);

  // Show incoming card ID from PUT
  console.log(req.body.carddata.cardid);

  var scannedid = req.body.carddata.cardid;
  console.log(scannedid);

  // SOQL query to get Account and related Cases based on custom field of RFID_Code__c
  org.query("SELECT Account.id, Account.name, (SELECT Case.Id, Case.CaseNumber, Case.IsClosed, Case.LastModifiedDate, Case.Subject, Case.Reason, Case.Description FROM Account.Cases ORDER BY Case.LastModifiedDate DESC) FROM Account WHERE Account.RFID_Code__c LIKE '"+scannedid+"'", oauth, function(err, resp){

    console.log(resp.records[0].Cases);

    // send all response data to client to view all attributes of object within the a browser console
    io.sockets.emit("servicedata", resp.records[0]);

    res.send({});
  });
});

// get feed for a given case to see latest updates noted by salesforce internal users
app.get('/casefeed/:id', function(req, res) {

  org.query("SELECT CaseFeed.Body, CaseFeed.ContentDescription, CaseFeed.CreatedDate, CaseFeed.ParentId FROM CaseFeed WHERE CaseFeed.ParentId = '"+req.params.id+"'", oauth, function(err, resp){

    console.log(resp);

    // send results as JSON to the client applicaiton at http://localhost:3001 (e.g. dashboard.html)
    res.writeHead(200, { 'Content-Type': 'application/json', "Access-Control-Allow-Origin":"*" });
    res.write(JSON.stringify(resp, 0, 4));
    res.end();
  });
});

Download Proof of Concept Code from GitHub

4 Comments

  1. sanjpradhan 5 years ago

    Great article John!!

  2. Author
    John Brunswick 5 years ago

    sanjpradhan Thanks for the kind words – much more to come in the IOT area.  Have been buried in circuit boards and parts lately 🙂

    Hope that all goes well on your end!

  3. calvin_nr 4 years ago

    Great tutorial John. I am just beginning to scratch the surface with Node.js and other JS frameworks. I am a Salesforce developer. It appears that sky is the limit which the magic that we can produce by working with so many cool and awesome technologies.

  4. John Brunswick 4 years ago

    calvin_nr thanks for the kind words!  yes – it is pretty amazing what can be done using Salesforce as the data & process part of a solution, then using libraries that JSForce and nForce to easily call into the automatic REST endpoints.  Highly recommend checking out some great blogs from some of the development gurus at Salesforce – Reid Carlberg http://reidcarlberg.com/ and Pat Patterson – http://blog.superpat.com/

Leave a reply

Your email address will not be published. Required fields are marked *

*