Sensor readings as JSON API using an ESP8266 NodeMCU dev kit
I've had some ESP8266 modules & dev kits laying around for quite a while now and a few months ago I started prototyping with them. Thought I'd make a basic example on how to present some sensor readings as a simple json api with only a few lines of code to get you started!
Goal
The goal is simple: a basic http endpoint that returns some json back with sensor readings, like below.
{
"illuminance": {
"visible": 905.0,
"full": 1255.0,
"ir": 347.0
},
"temperature": 24.51,
"humidity": 37.49,
"pressure": 1027.82
}
Hardware
First things first, getting the hardware needed! I've gotten everything of eBay for only a couple of bucks. I assume you have a breadboard and some jump wires but I'll link them too, just to be sure.
ESP8266 NodeMCU dev kit - $3.77
TMP102 sensor - $2.25
TSL2561 sensor - $1.48
BME280 sensor - $3.78
400 points solderless breadboard - $1.85
40 jump wires - $1.50
Wiring everything up
I don't have a schematic or anything, but the wiring is quite simple. Connect the 3.3V
of the ESP8266 NodeMCU with the VCC
, GND
with GND
, D1
with SCL
and D2
with SDA
pins of the sensors.
+---------------------------------------------+
| ESP8266 NodeMCU | TSL2561 | BME280 | TMP102 |
|-----------------|---------|--------|--------|
| 3.3V | VCC | VCC | VCC |
| GND | GND | GND | GND |
| D1 | SCL | SCL | SCL |
| D2 | SDA | SDA | SDA |
+---------------------------------------------+
Software
I'm not going to go step by step through the code as it is quite straightforward but basically the only thing you really need to do is download the required libraries and extract them here ~/Documents/Arduino/libraries
(or wherever it might be on Windows 🤷♂️).
Libraries
Program
This is the program, should work pretty much out of the box if everything is wired correctly. Just don't forget to substitute your WiFi credentials in WIFI_SSID
and WIFI_PASS
. Also my BME280 its address is 0x76
, but sometimes it lives on 0x77
as well. You can double-check this using the I2C scanner.
#include <Wire.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <Adafruit_Sensor.h>
#include <TSL2561.h>
#include <Adafruit_BME280.h>
#include <SparkFunTMP102.h>
// Configuration
#define WIFI_SSID ""
#define WIFI_PASS ""
#define WEB_SERVER_PORT 80
#define I2C_ADDR_TSL2561 0x39
#define I2C_ADDR_BME280 0x76
#define I2C_ADDR_TMP102 0x48
// Web server
ESP8266WebServer webServer(WEB_SERVER_PORT);
// Sensors
TSL2561 tsl2561(I2C_ADDR_TSL2561);
Adafruit_BME280 bme280;
TMP102 tmp102(I2C_ADDR_TMP102);
void setup()
{
// Setup I2C
Wire.begin(D2, D1);
// Setup Serial
Serial.begin(9600);
Serial.println();
setupWiFi();
setupWebServer();
setupSensors();
}
void loop()
{
webServer.handleClient();
}
void handleRoot()
{
Serial.println("[WebServer] Request: /");
// Read illuminance (lx)
float visible = tsl2561.getLuminosity(TSL2561_VISIBLE);
float full = tsl2561.getLuminosity(TSL2561_FULLSPECTRUM);
float ir = tsl2561.getLuminosity(TSL2561_INFRARED);
// Read temperature (°C)
float temperature = readTemperature();
// Read humidity (%)
float humidity = bme280.readHumidity();
// Read pressure (hPa)
float pressure = bme280.readPressure() / 100;
// Build response
String response = "";
response += "{";
response += "\"illuminance\":{";
response += "\"visible\":";
response += visible;
response += ",\"full\":";
response += full;
response += ",\"ir\":";
response += ir;
response += "}";
response += ",\"temperature\":";
response += temperature;
response += ",\"humidity\":";
response += humidity;
response += ",\"pressure\":";
response += pressure;
response += "}";
// Send response
webServer.send(200, "application/json", response);
}
float readTemperature() {
float bme280Temperature = bme280.readTemperature();
float tmp102Temperature = tmp102.readTempC();
return (tmp102Temperature + tmp102Temperature + bme280Temperature) / 3;
}
void setupWiFi()
{
Serial.println("[WiFi] Setup");
Serial.print("[WiFi] Connecting to: ");
Serial.println(WIFI_SSID);
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED)
{
delay(200);
Serial.print(".");
}
Serial.println();
Serial.println("[WiFi] Connected!");
Serial.print("[WiFi] IP: ");
Serial.println(WiFi.localIP());
}
void setupWebServer()
{
Serial.println("[WebServer] Setup");
webServer.on("/", handleRoot);
Serial.println("[WebServer] Starting..");
webServer.begin();
Serial.println("[WebServer] Running!");
}
void setupSensors()
{
setupSensorTSL2561();
setupSensorBME280();
setupSensorTMP102();
}
void setupSensorTSL2561()
{
Serial.println("[TSL2561] Setup");
Serial.print("[TSL2561] Connecting..");
while (!tsl2561.begin())
{
delay(200);
Serial.print(".");
}
Serial.println();
Serial.println("[TSL2561] Connected!");
}
void setupSensorBME280()
{
Serial.println("[BME280] Setup");
Serial.print("[BME280] Connecting..");
while (!bme280.begin(I2C_ADDR_BME280))
{
delay(200);
Serial.print(".");
}
Serial.println();
Serial.println("[BME280] Connected!");
}
void setupSensorTMP102()
{
Serial.println("[TMP102] Setup");
Serial.println("[TMP102] Connecting..");
tmp102.begin();
Serial.println("[TMP102] Assuming connected!");
}
Normally if you now compile & upload the above code to your ESP8266 module it should print out the IP address somewhere on the serial console.
[WiFi] Setup
[WiFi] Connecting to: Wouter's Place
..................................................................
[WiFi] Connected!
[WiFi] IP: 10.10.10.77
[WebServer] Setup
[WebServer] Starting..
[WebServer] Running!
[TSL2561] Setup
[TSL2561] Connecting..
[TSL2561] Connected!
[BME280] Setup
[BME280] Connecting..
[BME280] Connected!
[TMP102] Setup
[TMP102] Connecting..
[TMP102] Assuming connected!
And when making an http request to this ip you should get the sensor readings as json back 😄!
TLDR
You can find the entire project on Github.