About
This is part of a ThingBerry related blog post series.
ThingBerry is ThingWorx installed on a RaspBerry Pi, which can be used for portable demonstrations without the need of utilizing e.g. customer networks. Instead the ThingBerry provides its own custom WIFI hotspot and allows Things to connect and send / receive demo data on a small scale.
In this particual blog post we'll discuss on how to connect a ESP8266 module to the ThingBerry WIFI hotspot and send data from a DHT-11 sensor via the MQTT protocol.
As the ThingBerry is a highly unsupported environment for ThingWorx, please see this blog post for all related warnings.
Install MQTT broker on the ThingBerry
To install mosquitto as a MQTT broker, log in to the ThingBerry and run
sudo apt-get install mosquitto
This will provide a basic broker installation, which is good enough for this example.
MQTT clients (including ThingWorx) will connect to this broker to exchange messages.
There will be no added security like encrypted traffic shown in this example, it's however good practise to secure MQTT broker / client connections.
While the ESP8266 module is publishing information, ThingWorx will subscribe to the corresponding topics to update its internal property values with what is sent by the ESP8266 module.
For more information on MQTT, how to configure it for ThingWorx or more security relevant information also see
https://community.thingworx.com/message/5063#5063
https://community.thingworx.com/community/developers/blog/2016/08/08/securing-mqtt-connection-to-thingworx-platform?sr=tcontent
Configure the ESP8266
There are too many instructions on the web already on how to initially setup the ESP8266 and use it with the Arduino IDE. I'll therefore just refer to Google which covers the topic more extensively than I ever could.
All coding in this example is done in the Arduino IDE and is pushed to the ESP8266 (NodeMCU) via USB. For this you might need to install a CH340g USB driver for the NodeMCU.
In the Arduino IDE under Tools, I have set my environment to
Board: NodeMCU 1.0 (ESP-12E Module)
CPU Frequency: 80 MHz
Flash Size: 4M (3M SPIFFS)
Upload Speed: 115200
Port: COM3
Under Sketch > Include Library > Manage Libraries add / install the following libraries:
DHT sensor library by Adafruit
Adafruit Unified Sensor by Adafruit
PubSubClient by Nick O'Leary
These bring the libraries necessary to read data from the DHT-11 sensor and to configure the ESP8266 as MQTT client.
Wiring the DHT-11 sensor
The following image shows the PINs on the ESP8266
I'm using a DHT-11 sensor with cables included and already fixed to a board with 3 PINs.
In case you're using a different version, there might be additional components and wiring required, like a resistor etc.
Google might help here as well.
Ensure that neither board nor sensor are plugged in, and the ESP8266 is powered off.
To hook the sensor up to the ESP8266, join
( - ) to GND
( + ) to 3.3V
(out) to D3
After all the connections are made, connect the ESP8266 via USB to a computer / laptop with the Arudino IDE configured.
Coding
In the Arduino IDE use the following code - adjust the WIFI settings and the MQTT broker configuration.
Ensure to rename the ESP_xx name / topic to something more meaningful, e.g. a specific device name (or just leave it as is if in doubt).
Use the ssid and wpa_passphrase from the hostapd.conf used to configure the ThingBerry as WIFI hotspot.
Copy&paste the code below into the Arduino IDE, verify it and upload it to the ESP8266.
If searching for a WIFI connection, the device's blue LED will blink.
A successful connection to the broker and publishing the values will result in a static blue LED.
In case the LED is off, the connection to the broker is lost or messages cannot be published.
For troubleshooting, use the Serial Monitor function (at 115200 baud) in the Arduino IDE.
In case sensor data cannot be read but the wiring is correct and the code addressing the correct PIN verify the sensor is indeed working. It took me a long time to figure out that the first sensor I used was a defective device.
The current configuration sends updates every 10 seconds - longer intervals might make more sense, but can trigger a timeout for the MQTT broker. In this case the program will re-connect automatically and log corresponding messages in the Serial Monitor. This might seem like an error, but is indeed intended behavior by the code and the MQTT broker.
Configure MQTT Thing in ThingWorx
Create a new Thing in ThingWorx based on the MQTT Template.
Add two properties:
temperature
humidity
Both set to persistent and logged and Data Change Type to ALWAYS.
Also configure a Value Stream to log a history of values.
In the configuration, add two more subscriptions. Activate the "subscribe" checkbox and map name (local property) to topic (MQTT topic), e.g.
name = temperature; topic = ESP_xx/temp
name = humidity; topic = ESP_xx/hum
Ensure the correct servernames, ports etc. are configured (an empty servername will use the localhost).
Save the configuration.
Property values should now be updated from the MQTT broker, depending on what the device is sending.
Code
#include "DHT.h"
#include "PubSubClient.h"
#include "ESP8266WiFi.h"
/*
*
* Configure parameters for sensor and network / MQTT connections
*
*/
// setup DHT 11 pin and sensor
#define DHTPin D3
#define DHTTYPE DHT11
// setup WiFi credentials
#define WLAN_SSID "mySSID"
#define WLAN_PASS "WIFIpassword"
// setup MQTT
#define MQTTBROKER "mqttbrokerhostname"
#define MQTTPORT 1883
// setup built-in blue LED
#define LED 2
/*
* ============================================================
*
* DO NOT CHANGE ANYTHING BELOW
* (unless you know what you're doing)
*
*/
// initiate DHT
DHT dht(DHTPin, DHTTYPE);
// initiate MQTT client
WiFiClient wifiClient;
PubSubClient client(MQTTBROKER, MQTTPORT, wifiClient);
/*
* setup
*/
void setup() {
// switch off internal LED
pinMode(LED, OUTPUT);
digitalWrite(LED, HIGH);
// start serial monitor
Serial.begin(115200);
// start DHT
dht.begin();
// start WiFi
WiFi.begin(WLAN_SSID, WLAN_PASS);
}
/*
* the loop
*/
void loop() {
// while not connected to WiFi, print "."
// after connection exit the loop
// blink LED while having no WiFi signal
boolean wifiReconnect = false;
while (WiFi.status() != WL_CONNECTED) {
digitalWrite(LED, LOW);
delay(200);
Serial.print(".");
digitalWrite(LED, HIGH);
delay(300);
wifiReconnect = true;
}
// if WiFi has reconnected, print new connection information and turn on LED
if (wifiReconnect == true) {
// print connection information and local IP address, mac address
Serial.println();
Serial.println("WiFi connected");
Serial.println(WiFi.localIP());
Serial.println(WiFi.macAddress());
Serial.println();
// turn on built-in LED to indiciate successful WiFi connection
digitalWrite(LED, LOW);
}
// if MQTT client is not connected, connect again
// turn on built-in LED to indicate a successful connection
if (!client.connected()) {
Serial.println("Disconnected from MQTT server... trying to connect");
if (client.connect("ESP_xx")) {
Serial.println("Connected to MQTT server");
Serial.println("Topic = ESP_xx");
digitalWrite(LED, LOW);
} else {
Serial.println("MQTT connection failed");
digitalWrite(LED, HIGH);
}
Serial.println();
}
// read temperature and humidity from sensor
float t = dht.readTemperature();
float h = dht.readHumidity();
if (isnan(t) || isnan(h)) {
// if temperature or humidity is not a number, print error
Serial.println("Failed retrieving data from DHT sensor");
} else {
// print temperature and humidity
Serial.print(t);
Serial.print("° - ");
Serial.print(h);
Serial.print("%");
Serial.println();
// only send values to MQTT broker, if client is connected
if (client.connected()) {
// boolean to check for errors during payload transfer
bool isError = false;
// create payload and publish values via MQTT client
// use buffer to convert float to char*
char buffer[10];
dtostrf(t, 0, 0, buffer);
if (client.publish("ESP_xx/temp", buffer)) {
Serial.print(" published /temp ");
} else {
Serial.print(" failed /temp ");
isError = true;
}
dtostrf(h, 0, 0, buffer);
if (client.publish("ESP_xx/hum", buffer)) {
Serial.print(" published /hum ");
} else {
Serial.print(" failed /hum ");
isError = true;
}
Serial.println();
// on error, turn off LED
if (isError == true) {
digitalWrite(LED, HIGH);
} else {
digitalWrite(LED, LOW);
}
}
}
// sleep for 10 seconds
// if sleep > default mosquitto timeout : a reconnect is forced for each update-cycle
delay(10000);
}
View full tip