Salesforce NodeMCU IoT Temperature Service

Author : Dinesh Kumar Wickramasinghe

Introduction

Hello friends, this project is about sending real time sensor data to the world’s number 1 CRM platform, Salesforce. In profession, I am a Salesforce developer and I did a simple experiment of sending real time temperature data that coming from DS18B20 digital temperature sensor to Salesforce using NodeMCU IoT Platform. I implemented a public REST API on my Salesforce developer org and the NoceMCU consumes this web service to send real time data. So this tutorial will explain all the steps I’ve followed to accomplish this project.

What is Salesforce?
Salesforce Logo

If you are new to Salesforce CRM, this information is for you. Salesforce is the world's number one CRM (Customer Relationship Management) company. Salesforce provides a cloud based platform to develop business applications to improve customer relations. It has their own programming language called APEX for advanced business application development and a database query language called SOQL for querying. The platform also has a front end framework called Visualforce to create dynamic web pages. Salesforce also provides several declarative (Point and click) features to build business application faster even without writing single line of code. Salesforce recently introduced their stunning front end framework called Lightning to build mobile enabled and responsive applications with rich UI Components.

If you are willing to learn more about salesforce, please reach their interactive learning platform called Salesforce Trailhead.

To start investigating more about Salesforce and to complete this tutorial, you can create a free developer account by following the below link :

Sign up for new Salesforce account

High Level Architecture

Below diagram shows the high level data flow of our project.


NodeMCU Salesforce Temperature Service Architecture
Salesforce Configurations

Now I will step by step explain you what are the configurations we need to do on Salesforce.

1. Custom object to Store Data

Salesforce custom object is like a Database table. So we are going to create a custom object to save temperature data coming from the web service.

Custom object name : Temperature Data (API Name : Temperature_Data__c)

Also create below custom fields on your Custom object.

Field Name Data Type Comments
Celsius__c Number(10, 2) Temperature data in celsius format
Fahrenheit__c Formula (Number) Celsius__c * 9.0 / 5.0 + 32.0
Is_Critical__c Checkbox Indicates whether the temperature value is critical or not

Please see the below screenshot of my custom object for more details. Also create a custom tab for this custom object. Then we can easily monitor the values of this object.

1. Apex Trigger

In this step, we are going to write a simple Apex trigger for the above custom object. This trigger will execute after you insert a new temperature record. If you carefully go through this simple trigger code, you can see that, if the temperature value (Celsius value) is above 50, then it creates a new Case record.

Also it calls a simple email sending method to send an email alert (Please replace the 'youremail@youremail.com' with your email address). Please note that you can modify this code in many ways. I wrote just a simple code to understand easily.



trigger TemperatureAlertTrigger on Temperature_Data__c(after insert) {
 //Get the Trigger's new data list
 Temperature_Data__c[] newTempDataList = Trigger.new;
 //Get the first data point
 Temperature_Data__c temperatureDataPoint = newTempDataList[0];
 //Get the temperature value
 Double celsiusValue = temperatureDataPoint.Celsius__c;
 //Check if the temperature is above the critical value
 if (celsiusValue > 50) {
  //Create a new case and set required data
  Case crtTemCase = new Case();
  crtTemCase.Status = 'New';
  crtTemCase.Origin = 'Device';
  crtTemCase.Subject = 'Temperature Alert from Device';
  crtTemCase.Description = 'The device temperature is increasing above the critical point. \n\n Temperature : ' + celsiusValue;
  crtTemCase.Reason = 'Other';
  crtTemCase.Type = 'Mechanical';
  crtTemCase.Priority = 'High';
  //Insert the case
  insert crtTemCase;
  //Send alert mail
  try {
   sendMail(celsiusValue);
  } catch (Exception ex) {
   System.debug('MAIL ERR ' + ex);
  }
 }

 /*
  * This method will send email alerts when the temperature is 
  * above the critical point
  */
 public void sendMail(Double temperature) {

  Messaging.reserveSingleEmailCapacity(2);
  Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
  String[] toAddresses = new String[] {
   'youremail@youremail.com'
  };
  mail.setToAddresses(toAddresses);
  mail.setSenderDisplayName('Critical Temperature Alert');
  mail.setSubject('Temperature Alert');
  //mail.setPlainTextBody('Temperature : ' + temperature);
  mail.setHtmlBody('<h1>Temperature: ' + temperature + ' C </h1> <p>' + 'Please take the necessary actions.</p>');

  Messaging.sendEmail(new Messaging.SingleEmailMessage[] {
   mail
  });
 }
}
                    

Please proceed the below link to learn more about Apex triggers.

Salesforce Apex Triggers

1. REST Web Service

In this step, we are going to write a simple salesforce REST web service and expose this as a publically accessible service. So, later we can invoke this web service using NodeMCU and send temperature data.

Create a new Apex class and paste the below code.

@RestResource(urlMapping = '/iotservice')
global class RealTimeDataService {
 @HttpGet
 global static void doGet() {

  //Set the response as plaintext
  RestContext.response.addHeader('Content-Type', 'text/plain');

  //Get the temperature value from the parameter
  String tempReading = RestContext.request.params.get('temperature');

  //Convert the string value to Double
  Double tempDoubleReading = Double.valueOf(tempReading);

  //Create a new custob object record to store the value
  Temperature_Data__c temperatureRecord = new Temperature_Data__c();
  temperatureRecord.Celsius__c = tempDoubleReading;

  //Set the critical checkbox to true
  if (tempDoubleReading > 50) {
   temperatureRecord.Is_Critical__c = true;
  }

  try {
   //Insert the temperature value, if success, send success response
   insert temperatureRecord;
   RestContext.response.responseBody = Blob.valueOf('sucess');
  } catch (Exception ex) {
   //If the insertion fails, send error response
   RestContext.response.responseBody = Blob.valueOf('error');
  }
 }
}
                    

We use the HTTP GET method to receive data. You can see that this trigger receives the celsius value as a parameter and creates a new record of the type of custom object we created in an earlier step (Temperature_Data__c).

If the celsius value is greater than 50, the logic set the Is_Critical__c field of our custom object to true. Please note that the Fahrenheit value will be automatically calculated since it is a formula field.

We need one last step to do on Salesforce before we move to NodeMCU configurations.

1. Make the REST service public

The web service we created in the previous step is not publicly accessible. So we are going to create a Salesforce site and expose this REST service via this public site. So that the NodeMCU can easily invoke this service without worrying about authentication.

Go to "Sites" on Salesforce setup and create a new site. Use the site name "TemperatureService"

Go to "Public Access Settings" of the site and click on "Enabled Apex Class Access"

Click the Edit button.

Move the web service class "RealTimeDataService" from the "Available Apex Classes" group to "Enabled Apex Classes" group.

Save your configurations.

Now we’ve done with all our configurations on Salesforce side. Now let’s move to our hardware setup. See the below blog post for more details about public RESTful web services.

Quick Tip – Public RESTful Web Services on Force.com Sites

Follow this link to learn more about Salesforce sites :

More about Salesforce sites

Configuring Node MCU

As I mentioned in the beginning of this tutorial, we use the NodeMCU IoT platform to send real time sensor data to Salesforce.

NodeMCU IoT Board

I’ve written two blog posts about NodeMCU. I recommend you to go through them before continue. They will give you an introduction knowledge about NodeMCU device and Configuring the Arduino IDE for NodeMCU programming.

  1. Introduction to Node MCU
  2. LED Blink with Node MCU
Schematic (Circuit Diagram)

Please use the below circuit diagram to setup your devices. You need below things to setup your devices.

  • ESP8266 Based NodeMCU IoT Platform
  • A Solderless development board
  • Some hook up wires
  • DS18B20 Digital temperature sensor
  • 4.7K Resistor
NodeMCU Salesforce Data Service Schematic
Setting Up Arduino IDE

If you referred my introduction tutorials for NodeMCU, you can learn how to setup the Arduino IDE for NodeMCU and how to upload a simple code. So, I am not going to explain those steps again here.

In this demo, we need to install two additional libraries to Arduino IDE. Those libraries will help us to read the DS18B20 Digital Temperature Sensor.

  • One Wire
  • Dallas Temperature

Go to Arduino IDE Menu : Sketch > Include Library > Manage Libraries

On Library manager window, first search for "onewire" and install the onewire library as on below screenshot.

Install onewire Library Arduino IDE

Then search for "dallas" and install the dallasTemperature library as on below screenshot.

Install dallasTemperature Library Arduino IDE

OK, Now your Arduino IDE is ready to write and upload the software for NodeMCU.

NodeMCU Code

Here is the source code for NodeMCU.


#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define USE_SERIAL Serial
#define ONE_WIRE_BUS 2

ESP8266WiFiMulti WiFiMulti;

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature DS18B20(&oneWire);
char temperatureString[6];

void setup() {

    USE_SERIAL.begin(115200);
    //USE_SERIAL.setDebugOutput(true);

    USE_SERIAL.println();
    USE_SERIAL.println();
    USE_SERIAL.println();

    for(uint8_t t = 4; t > 0; t--) {
        USE_SERIAL.printf("[SETUP] WAIT %d...\n", t);
        USE_SERIAL.flush();
        delay(1000);
    }

    WiFiMulti.addAP("MORPHEUS", "rvd@#ell12");

    DS18B20.begin();
}

float getTemperature() {
  float temp;
  do {
    DS18B20.requestTemperatures(); 
    temp = DS18B20.getTempCByIndex(0);
    delay(100);
  } while (temp == 85.0 || temp == (-127.0));
  return temp;
}

void loop() {

    float temperature = getTemperature();
    dtostrf(temperature, 2, 2, temperatureString);

    USE_SERIAL.println("Reading");
    USE_SERIAL.println(temperatureString);
    
    if((WiFiMulti.run() == WL_CONNECTED)) {

        HTTPClient http;

        USE_SERIAL.print("[HTTP] begin...\n");
        // configure traged server and url
        http.begin("https://iotservice-developer-edition.ap5.force.com/sensordata/services/apexrest/iotservice?temperature=" + String(temperatureString), "B0 9B F8 CD F9 7A FD DD 0F 86 3B E3 87 FA 7F FE 88 4C 61 02");
        //http.begin("http://192.168.1.12/test.html"); //HTTP

        USE_SERIAL.print("[HTTP] GET...\n");
        // start connection and send HTTP header
        int httpCode = http.GET();

        // httpCode will be negative on error
        if(httpCode > 0) {
            // HTTP header has been send and Server response header has been handled
            USE_SERIAL.printf("[HTTP] GET... code: %d\n", httpCode);

            // file found at server
            if(httpCode == HTTP_CODE_OK) {
                String payload = http.getString();
                USE_SERIAL.println(payload);
            }
        } else {
            USE_SERIAL.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
        }
        http.end();
    }
    delay(5000);
}
                    

There are few places you need to change on the above code.

Add your WiFi network SSID and password here.

WiFiMulti.addAP("AndroidHotspot4984", "dinesh1234");

You also need to change the below line with your Salesforce org details (Service URL and SHA1 Fingerprint). Let's see how.

http.begin("https://iotservice-developer-edition.ap5.force.com/sensordata/services/apexrest/iotservice?temperature=" + String(temperatureString), "B0 9B F8 CD F9 7A FD DD 0F 86 3B E3 87 FA 7F FE 88 4C 61 02");

REST API URL format.

You need to replace the API URL with your web service URL. Now let’s see how to populate the correct URL. For an example, here is my web service URL.

https://iotservice-developer-edition.ap5.force.com/sensordata/services/apexrest/iotservice?temperature=

Now let’s see how this URL is populated. Here are the components of this URL you need to change according to your Salesforce organization.

https://iotservice-developer-edition.ap5.force.com : Domain name of your custom URL

/sensordata : Path

/services/apexrest : This part is common for REST service

/Iotservice : URL Mapping you’ve given in your REST web service class

temperature : Parameter name you’ve given in your web service class

So, based on your Salesforce organization settings, build the correct URL. You can test this URL by sending a sample temperature value via the web browser. Make sure to add a temperature value at the end of this URL. See the below screenshot.

NodeMCU Salesforce Temperature Service Browser Request

If the service call was success, you will see a success response. When you get the success response, you can check from Salesforce backend if the record is correctly inserted to the custom object using a SOQL query or using a custom tab for your custom object.

Getting the SHA1 Fingerprint

Since we are accessing a HTTPS URL via NoceMCU, we need to get the SHA1 fingerprint of your salesforce url. Here is a simple hack to get it.

Node : I am not sure that this is the best way to get the SHA1 Fingerprint. If you know a better way than this, please comment ;)

Go to the service URL (you populated above) using Mozilla Firefox Browser

Click on the green color pad lock Icon.

Get SHA1 Fingerprint

Then click on 'Show Connection Details' button.

Get SHA1 Fingerprint Show Connection Details

Then click on more information.

Get SHA1 Fingerprint More Information

On the Page Info window, Click view certificate

Get SHA1 Fingerprint View Certificate

Bottom of the certificate viewer window, you will see your SHA1 Fingerprint as below.

Get SHA1 Fingerprint

Copy it and replace all the colon signs with spaces. Now it should look like this

B0 9B F8 CD F9 7A FD DD 0F 86 3B E3 87 FA 7F FE 88 4C 61 02

In the nodeMCU code, replace my fingerprint with your one. Now you've done all the changes to your NodeMCU code.

Once you done all the necessary changes on the code, plug your NodeMCU module to your PC and upload the code.

Running the Project

If everything went well, it is time to launch the project. You can power up the NodeMCU via your PC or Laptop USB port or by using an external power supply. I recommend you to power up via the USB port since it is safe.

Make sure your WiFi network is up and running and your internet connection is active on WiFi. Because once we power up the device setup, NodeMCU will connect to your WiFi network and after that it will start reading the temperature and finally invoke the web service URL.

The device setup will invoke the web service every 10 seconds and send a temperature value to Salesforce.

You can open the serial monitor of your Arduino IDE and see what is happening in the back end. Click on the below icon of your arduino IDE to open the serial monitor window.

Arduino IDE Serial Monitor Button

If everything going well, you will see an output similar to below screenshot.

Arduino IDE Serial Monitor Output

Login to your Salesforce org (if you are not already logged in) and open the custom tab you created for the custom object. Time to time refresh the data and you will see new data coming from the sensor.

If the temperature is increased above 50 celsius degrees, a case will be opened and an email alert will be sent. To test this, you can increase the temperature of the sensor by putting it inside a hot water glass ;) (No worries, it is a waterproof sensor)

If you open the Cases tab, you will see cases open if the temperature is increased above 50 celsius degrees. I have one case as below.

Click on the case name to see the case details.

You can also check your email account to see the critical temperature alert mail.

Salesforce critical temperature email

Here is a video clip I took while doing this project.

Conclusion

So, this is the end of this tutorial. Hope you enjoyed it. Please note that if you are new to Salesforce, you will have some questions while doing this project. So, please refer the links I’ve given you in the beginning of this tutorial to update your Salesforce knowledge.

Salesforce recently introduced a new cloud (service) calls Salesforce IoT Cloud. This has more features specially for IoT projects. I will post a new article soon related to the IoT cloud.

If you have any questions, suggestions or if you found any mistakes made by me while writing this blog post, please mention them as a comment. I will response my best. Thank you!

Comments Area
Add your questions and comments here. Comments will be published after the admin approval
Published By : Aritra M
Added Date :1/6/2021 7:20:24 PM
Hi, this is an excellent tutorial that actually works :) The SHA1 FP addition made the magic. Thanks for taking time to write it up and make it work. Great job!
Published By : surendranath M
Added Date :11/10/2020 6:02:46 PM
In the above code I need your help in url : /sensordata : Path How to set the path in the url. Please help me on this.
Published By : Parjanya Roy
Added Date :8/22/2018 11:21:12 AM
Hi, First of all thanks a lot for this helpful tutorial . If a IOT device has to be marketed , is it a good option to hardcode the SHA1 fingerprint into them ? Isn't there the risk of the fingerprint getting changed over time .

 

Similar Projects

Go Top