Connect an ESP8266 WiFi module using the Arduino programming environment and the ThingWorx REST API.
This information was created for a previous version of ThingWorx and may not be fully accurate. Report any issues with this article here.
Guide Concept
This project will introduce the utilities ThingWorx provides for connections to an Adafruit Feather.
Following the steps in this guide, you will have a fully configured setup between your Adafruit Feather and the ThingWorx platform to begin your IoT development.
We will teach you how to utilize the ThingWorx REST API and the Arduino programming language to connect your Adafruit Feather for IoT application development.
You'll learn how to
Connect an ESP8266 WiFi module to a ThingWorx server
Use the Arduino programming environment with the ThingWorx REST API
NOTE: The estimated time to complete this guide is 30 minutes.
Step 1: Install Software
Arduino
There are three pieces of software to install before getting started with the ThingWorx-specfic code:
Install FTDI USB driver.
If you have connected development boards to your PC in the past you probably already have this installed. The latest Arduino IDE full install will also install the driver.
NOTE: SparkFun has an excellent FTDI Driver Installation guide.
3. Arduino IDE - version 1.6.4 or later recommended.
4. Install ESP8266 addon into Arduino IDE.
5. The SparkFun Setting Up the Arduino IDE Tutorial is a great guide to getting started with their board.
6. Adafruit also has a great with their board Testing a Wifi Connection Tutorial.
When everything is set-up correctly and you are able to upload and see the Blink demo flashing the LED on the board you are ready to move to the next step.
ThingWorx Foundation Server
Start, and Launch your ThingWorx Foundation server.
Log into Composer. You will need a ThingWorx appKey to authorize the board. Follow these instructions in Create an Application Key to create an appKey that you will copy into the source code in the next step.
Step 2: Set up Arduino IDE, Developer Board, and ThingWorx Server
Once you are able to run the blink test sketch, your IDE and board are set-up correctly. To learn how to run the blink test, read the SparkFun Board Instructions and the Adafruit board instructions.
Arduino IDE
Before you will be able to run the code below that connects a developement board to a ThingWorx Foundation server, you will need to modify the code with four pieces of information specific to your environment. You will need:
A WiFi access point SSID
The correct password for the WiFi access point
The IP address or URL of a ThingWorx Foundation Server
A valid appKey created by your ThingWorx Foundation Server. To create an appKey, follow these instructions to Create An Application Key
Create a new sketch in the Arduino IDE then copy and paste the code below into the IDE.
Modify the WiFi Definitions and the ThingWorx server definitions shown in the code with your specficic information then save the sketch with a new name. The next step will describe what you should see when you upload and run the code on your developer board.
/**
*
* ESP8266_ThingWorx_REST_Demo.ino
*
*
* (c) PTC, Inc. 2016-2020
*
*/
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureBearSSL.h>
//////////////////////
// WiFi Definitions //
//////////////////////
const char WiFiSSID[] = "Liberty454"; // WiFi access point SSID
const char WiFiPSK[] = "Flutie22"; // WiFi password - empty string for open access points
//////////////////////////////////////////////
// ThingWorx server definitions //
// modify for a specific platform instance //
//////////////////////////////////////////////
const char TWPlatformBaseURL[] = "https://pp-2007011431nt.devportal.ptc.io";
const char appKey[] = "2d4e9440-3e51-452f-a057-b55d45289264";
////////////////////////////////////////////////////////
// Pin Definitions - board specific for Adafruit board//
////////////////////////////////////////////////////////
const int RED_LED = 0; // Thing's onboard, red LED -
const int BLUE_LED = 2; // Thing's onboard, blue LED
const int ANALOG_PIN = A0; // The only analog pin on the Thing
const int OFF = HIGH;
const int ON = LOW;
// this will set as the Accept header for all the HTTP requests to the ThingWorx server
// valid values are: application/json, text/xml, text/csv, text/html (default)
#define ACCEPT_TYPE "text/csv"
/////////////////////
//Attempt to make a WiFi connection. Checks if connection has been made once per second until timeout is reached
//returns TRUE if successful or FALSE if timed out
/////////////////////
boolean connectToWiFi(int timeout){
Serial.println("Connecting to: " + String(WiFiSSID));
WiFi.begin(WiFiSSID, WiFiPSK);
// loop while WiFi is not connected waiting one second between checks
uint8_t tries = 0; // counter for how many times we have checked
while ((WiFi.status() != WL_CONNECTED) && (tries < timeout) ){ // stop checking if connection has been made OR we have timed out
tries++;
Serial.printf(".");// print . for progress bar
Serial.println(WiFi.status());
delay(2000);
}
Serial.println("*"); //visual indication that board is connected or timeout
if (WiFi.status() == WL_CONNECTED){ //check that WiFi is connected, print status and device IP address before returning
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
return true;
} else { //if WiFi is not connected we must have exceeded WiFi connection timeout
return false;
}
}
//////////////////////////
//create a name for the board that is probably unique by appending last two bytes of MAC address
//return name as a String
///////////////////////////////
String getUniqueDeviceName(){
String uniqueName;
uint8_t mac[WL_MAC_ADDR_LENGTH];
WiFi.macAddress(mac); // WiFi does NOT need to be connected for this call
String macID = String(mac[WL_MAC_ADDR_LENGTH - 2], HEX) +
String(mac[WL_MAC_ADDR_LENGTH - 1], HEX);
macID.toUpperCase();
uniqueName = "ESP8266Board-" + macID;
Serial.println("DeviceID>" + uniqueName);
return uniqueName;
}
///////////////////////////////
// make HTTP GET to a specific Thing and Propertry on a ThingWorx server
// thingName - Name of Thing on server to make GET from
// property - Property of thingName to make GET from
// returns HTTP response code from server and prints full response
///////////////////////////////
int httpGetPropertry(String thingName, String property){
std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);
client->setInsecure();
HTTPClient https;
int httpCode = -1;
String response = "";
Serial.print("[httpsGetPropertry] begin...");
String fullRequestURL = String(TWPlatformBaseURL) + "/Thingworx/Things/"+ thingName +"/Properties/"+ property +"?appKey=" + String(appKey);
https.begin(*client,fullRequestURL);
https.addHeader("Accept",ACCEPT_TYPE,false,false);
Serial.println("GET URL>" + fullRequestURL +"<");
// start connection and send HTTP header
httpCode = https.GET();
// httpCode will be negative on error
if(httpCode > 0) {
response = https.getString();
Serial.printf("[httpGetPropertry] response code:%d body>",httpCode);
Serial.println(response + "<\n");
} else {
Serial.printf("[httpGetPropertry] failed, error: %s\n\n", https.errorToString(httpCode).c_str());
}
https.end();
return httpCode;
}
///////////////////////////////
// makes HTTP POST to platform to CreateThing service using input string as the new Things's name.
// Returns server response code
///////////////////////////////
int createThing(String nameOfThing){
std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);
client->setInsecure();
HTTPClient https;
int httpCode = -1;
String response = "";
Serial.print("[createThing] begin...");
String fullRequestURL = String(TWPlatformBaseURL) + "/Thingworx/Resources/EntityServices/Services/CreateThing?appKey=" + String(appKey);
https.begin(*client,fullRequestURL);
https.addHeader("Accept",ACCEPT_TYPE,false,false);
https.addHeader("Content-Type","application/json",false,false);
Serial.println("POST URL>" + fullRequestURL + "<");
// start connection and send HTTP header
httpCode = https.POST("{\"name\": \""+ nameOfThing +"\",\"thingTemplateName\": \"GenericThing\"}");
// httpCode will be negative on error
if(httpCode > 0) {
response = https.getString();
Serial.printf("[createThing] response code:%d body>",httpCode);
Serial.println(response + "<\n");
} else {
Serial.printf("[createThing] POST... failed, error: %s\n\n", https.errorToString(httpCode).c_str());
}
https.end();
return httpCode;
}
///////////////////////////////
// make HTTP POST to ThingWorx server Thing service
// nameOfThing - Name of Thing to POST to
// endPoint - Services URL to invoke
// postBody - Body of POST to send to ThingWorx platform
// returns HTTP response code from server
///////////////////////////////
int postToThing(String nameOfThing, String endPoint, String postBody){
std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);
client->setInsecure();
HTTPClient https;
int httpCode = -1;
String response = "";
Serial.print("[postToThing] begin...");
String fullRequestURL = String(TWPlatformBaseURL) + "/Thingworx/Things/"+ nameOfThing +"/Services/"+ endPoint +"?appKey=" + String(appKey);
Serial.println("URL>" + fullRequestURL + "<");
https.begin(*client,fullRequestURL);
https.addHeader("Accept",ACCEPT_TYPE,false,false);
https.addHeader("Content-Type","application/json",false,false);
Serial.println("[postToThing] POST body>" + postBody + "<");
// start connection and send HTTP header
httpCode = https.POST(postBody);
// httpCode will be negative on error
if(httpCode > 0) {
response = https.getString();
Serial.printf("[postToThing] response code:%d body>",httpCode);
Serial.println(response + "<\n");
} else {
Serial.printf("[postToThing] POST... failed, error: %s\n\n", https.errorToString(httpCode).c_str());
}
https.end();
return httpCode;
}
void setup() {
pinMode(RED_LED, OUTPUT);
pinMode(BLUE_LED, OUTPUT);
Serial.begin(115200);
Serial.setDebugOutput(true);
Serial.println();
Serial.println();
Serial.println();
Serial.printf("Starting...\n");
for(uint8_t t = 4; t > 0; t--) {
Serial.printf(" WAIT %d...\n", t);
Serial.flush();
delay(1000);
}
connectToWiFi(10);
}
void loop() {
String thingName = getUniqueDeviceName(); //unique name for this Thing so many work on one ThingWorx server
while (WiFi.status() == WL_CONNECTED) { //confirm WiFi is connected before looping as long as WiFi is connected
int getResponseCode = httpGetPropertry(thingName, "SomeNumber");
if (getResponseCode == 404){ // a 404 means connected, but either no Thing or no property
// first we will try to create a new Thing on the platform
int postResp = createThing(thingName); // saving the response code for retry logic in the future
// the newly crated Thing has to be enabled
postResp = postToThing(thingName,"EnableThing",""); //POST to EnableThing endpoint with no body
// after the new Thing is enabled it must be restarted
postResp = postToThing(thingName,"RestartThing",""); //POST to RestartThing endpoint with no body
// add a property to the Thing 3rd parameter is ugly because required quotes are escaped with backslashes
postResp = postToThing(thingName,"AddPropertyDefinition", "{\"name\":\"SomeNumber\",\"type\":\"NUMBER\"}");
//POST body contains JSON object with property name and property type
// after changes to a Thing's structure it must be restarted
postResp = postToThing(thingName,"RestartThing",""); //POST to RestartThing endpoint with no body
}
delay(2000);
}// end WiFi connected while loop
Serial.printf("****Wifi connection dropped****\n");
WiFi.disconnect(true);
delay(10000);
connectToWiFi(10); }
Step 3: Run Arduino Demo
Click on the right arrow in the Arduino IDE toolbar to upload and start the sketch.
Note:The compile and upload process will take almost a minute and will show [ 100% ] when it is completed successfully.
2. After the upload is complete, click on Tools > Serial Monitor and select 115200 baud from the drop down in the lower right.
Check Connection on ThingWorx Server
Open the Composer window of your ThingWorx Foundation server and click on the browse folder icon, then Things.
You will see a Thing named "ESP8266Board-XXXX" with XXXX replaced by the last 4 digits of your boards WiFi MAC address.
Click on the Thing then click the Properties and Alerts tab in the left column.
Click the pencil "Set value" icon in the value column and enter a number in the text box.
Click the "Check" button to set the value.
Open the Arduino Serial monitor window, and you will see the value you just entered on the platform shown in the serial output.
Step 4: Next Steps
Congratulations! You've successfully completed the Connect an Arduino Developer Board Quickstart.
This guide has given you the basic tools to:
Set up Arduino IDE
Run Arduino demo
Check connection on ThingWorx Server
Learn More
We recommend the following resources to continue your learning experience:
Capability
Guide
Connect
Use REST API to Access ThingWorx
Build
Data Model Introduction
Additional Resources
If you have questions, issues, or need additional information, refer to:
Resource
Link
Community
Developer Community Forum
Support
REST API Help Center
View full tip