Internet of Customers – Custom Visualforce Page with Web Sockets, Arduino & Temperature

In our Building Management Automation with Salesforce and Arduino proof of concept, we needed to do a number of things to setup our systems to communicate with each other, displaying real time data. In this post we review all the source code and steps used for the proof.

At a high level, the following needed to be performed to get us started.

  • Custom Visualforce page that includes JQuery Easy Pie Chart & static files (, jquery, etc)
  • Node.js application to accept PUTs from Arduino application
  • Web socket communication between Node.js application and Visualforce page to update charts
  • Task rules in Salesforce that created Task when the temperature goes over defined limit

Custom Visualforce Page with Web Sockets & Static Files
The following screens showcase using Eclipse’s Kelper Release with the plugin to incorporate static content within a custom Visualforce page.

For the Controller attribute for the apex:page tag, I leveraged my custom Object’s API name – Building__c.

As I was just focused on creating the proof vs a production deployment, I ran a local Node.js application that used You will notice in the source code for download at the bottom of this post, that the reference is not made using the static files. Instead the client files needed for are sent to the client via the server side process automatically. Also note that the JS code inline in the example would generally be externalized.

The following Apex code highlights the static resource inclusion, as well as a loop containing each unit within a given building.

Visualforce Static Resources & Loop with Child Objects


Web Sockets in Visualforce Code

Based on the Apex code above, the following will then ensure that the chart can reflect the latest sensor data on the basis of web sockets communication from the Node.js application.


Setting up the Arduino
The following physical configuration was used in the proof. Note that in the actual video I wanted to keep the main Arduino board and WiFi Shield away from the heat, so I set the temp sensor apart via a long wire.

Arduino Application

The following code borrows a lot from our prior proof – using Arduino & Heroku with Salesforce for Customer Service, but has been adapted to gather and send our temperature information.

void sendData() {

   //getting the voltage reading from the temperature sensor
   int reading = analogRead(sensorPin);

   // converting that reading to voltage, for 3.3v arduino use 3.3
   float voltage = reading * 5.0;
   voltage /= 1024.0;

   float temperatureC = (voltage - 0.5) * 100 ;  //converting from 10 mv per degree wit 500 mV offset
                                                 //to degrees ((voltage - 500mV) times 100)

   // now convert to Fahrenheit
   float temperatureF = (temperatureC * 9.0 / 5.0) + 32.0;

  Serial.println("Trying to send card data to server...");

  // if you get a connection, report back via serial:
  // change port info as needed, this was used with a local instance via Heroku command line
  if (client.connect(server, 3001)) {

    Serial.println("Connected to server...");

    static char dtostrfbuffer[15];
    dtostrf(temperatureF, 8, 2, dtostrfbuffer);

    String feedData = "n{"tempdata" : {"value" : "" + String(dtostrfbuffer) + ""}}";
    Serial.println("Sending: " + feedData);

    client.println("PUT /environment/ HTTP/1.0");

    client.println("Content-Type: application/json");
    client.println("Content-Length: " + String(feedData.length()));
    client.print("Connection: close");

Node.js Application & Web Sockets

As with our above Arduino code, the following is similar to our prior example. However, we not only update Salesforce is the temperature reading is different enough than the prior read, but we also get any Tasks that are created on the basis of Salesforce Task rules that have been configured in the Salesforce application.

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

  var tempreading = req.body.tempdata.value;

  // Hard coded - would come from sensor unit
  var unitnumber = 'Unit 309';

  // Send temp reading to dashboard on client
  io.sockets.emit("envread", tempreading);

  console.log('Temperature reading from sensors: ' + tempreading);

  // Don't send every sensor reading to Salesforce - unless it is 2 degrees different than prior reading
  if (Math.abs(tempbase - tempreading) > 2) {

    // Get Units and any open tickets for them
    var q = "SELECT Building__c, Name, Recent_Temp__c, (SELECT Description,Id,OwnerId,Status,Subject,WhatId FROM Unit__c.Tasks WHERE Status = 'Not Started') FROM Unit__c WHERE Name = '" + unitnumber + "' LIMIT 1";

    console.log("Updating SFDC record: " + unitnumber);

    org.query(q, oauth, function(err, resp){
      if(!err && resp.records) {
        var acc = resp.records[0];
        acc.Recent_Temp__c = tempreading;
        org.update(acc, oauth, function(err, resp){
          if(!err)  {
            // Use the following if needed to understand the various values returned
            // console.log("Description: " + acc.Tasks.records[0].Subject);
            if (acc.Tasks != null) {
              io.sockets.emit("task", acc.Tasks.records[0]);
    console.log("Skipping SFDC record update - data too similar in " + unitnumber + "...");
  tempbase = tempreading;

Salesforce Task Rules
Setting up the Task workflow is pretty straightforward and will provide alerts for maintenance if a temperate limit is exceeded from a reading. Additionally, we are able to get email notification, as well as access to the Task via the Salesforce1 mobile application.

Resources Used in the Proof
The following is a short list of some of the key resources used in the proof. Many thanks to their creators!

The source code on GitHub has been updated to now include all static files, along with an export of the custom objects (Building and Unit) used in the example. The screens below show the object relations, as well as the listing of the static assets.

Source Code Download
Download Source * Updated

  • DutchVonWichard
    February 14, 2014

    I’m very impressed by your demo and I’m trying to set it up on a dev org.
    Could you please tell me which files to include in the static ressources ?
    Also the visualforce page controlleur references customs objects “Building” and “Units” but the source files don’t contain the structure of thoses objects.

    Also in the source files, what are “node_modules” folder and “app.js”, “package.json”, “Procfile” files made for ?

    Thanks for reading me !

  • John Brunswick
    February 14, 2014

    DutchVonWichard  Thanks for the kind words – will update this post with those additional details.

    A few quick answers

    1. Since I was just testing I ran a local Node.js application and that contained the app.js, package.json and Procfile files.  Grab Heroku’s Toolbelt to easily get an environment setup that can run this portion of the application.  A great overview can be found at

    2. Will get information about the Building and the Units here and their source in an update later today.

    3. Will update this with the static resource specifics as well.

    For the VF pages – I was able to use the standard controller, so just the Page portion was needed.

    Stay tuned – give me about 24 hours and will have the update!


  • DutchVonWichard
    February 18, 2014

    Thanks for your answer, I look forward for your updates and in the meantime I will have a close look to Noje.js with the resources you provided.

  • John Brunswick
    February 18, 2014

    DutchVonWichard  Thanks!  I updated the bottom of the post and the source with the new items.  Let me know if these help and how it goes.

  • DutchVonWichard
    February 20, 2014

    Thanks a lot for additionnal ressources. I’ve followed the heroku and node.js tutorial, when I try to start the application with “foreman start” I get the following message :
    12:51:42 web.1  | started with pid 3824
    12:51:43 web.1  | info: started
    12:51:43 web.1  | exited with code 8
    12:51:43 system | sending SIGKILL to all processes
    12:51:43        | connect.multipart() will be removed in connect 3.0

    Another question : there are 2 ips in the files, one in visualforce page and another one in the arduino sketch, are they the ip of the arduino on the network or the ip of the computer running nodejs ?

    Thanks for your help.

  • talbrown
    March 2, 2014

    Hi John, Awesome article.
    Did you manage to consume the visualforce page on Salesforce1 with enabled?

  • John Brunswick
    March 3, 2014

    talbrown  Thanks for the kind words.  I initially tried to use some JS files as static resources for the client libraries for sockets, but ended up serving them from the same server that Node.js was running on.

    In the code above, I actually just used a local server (, but it could just as easily have been served from an application instance hosted on Heroku.

    I did a bit of digging and it turns out that the library is generally server in a dynamic way vs a static file, as with CSS and JS in normal circumstances.

    Hope that helps!

    I have a few upcoming examples using the Streaming API, but it more geared toward reacting to data changes in SFDC vs general realtime connectivity.


Leave a comment