Your first ESP32 sensor with the HydroNode Arduino library

From an empty sketch to live charts: install the library, send a whole reading in one signed request, and switch a relay with typed commands.

HydroNode Updated 8 min read
A HydroNode sensor chart with temperature readings sent from an ESP32A HydroNode sensor chart with temperature readings sent from an ESP32

An ESP32, a BME280 and twenty minutes. By the end of this post, temperature, humidity and pressure land in HydroNode every minute, and you switch a relay from the app. The library takes care of WiFi, time, TLS and signing every request.

What you need

An ESP32 or ESP8266Any ESP32 board works, here a classic DevKit. For the ESP8266, 4 MB of flash is recommended.
A BME280Or any other sensor you can read.
Arduino IDE or PlatformIOWith the ESP32 board package from Espressif installed.
A HydroNode sensorHow to create one is in the welcome tour.

Get the Sensor ID and secret

  1. Open the sensorClick your sensor under Sensors.
  2. Open its settingsPress Settings at the top right, then Connection on the left.
  3. Copy bothUnder Direct connection you find the Sensor ID and the Secret, each with a copy button. The secret belongs on your device only, never in a public repository.
Connection settings of a sensor with the Sensor ID and a hidden secretConnection settings of a sensor with the Sensor ID and a hidden secret
Settings, Connection: Sensor ID and secret for the direct connection. If the secret ever leaks, you replace it right here.

Install the library

  1. Open the library managerToolsManage Libraries
  2. Search and installSearch for HydroNode-Library and install it. The IDE offers to install ArduinoJson and ArduinoHttpClient along with it: say yes.
  3. Add the sensor libraryFor the BME280, also install Adafruit BME280 Library.

Wire the BME280

Four wires: VIN to 3.3 V, GND to GND, SDA to GPIO 21 and SCL to GPIO 22. Those are the default I²C pins of a classic ESP32. With SDO on GND the sensor answers at 0x76, with SDO on 3.3 V at 0x77.

The sketch

Fill in your four values at the top and upload. sendValues() sends all three values of a round in one signed request, stamped with the time they were measured. That saves one connection per value, which is several seconds on an ESP8266.

HydroNodeBME280.inoC++
#include <Wire.h>
#include <Adafruit_BME280.h>
#include <HydroNode.h>

const char* WIFI_SSID     = "YOUR_WIFI_SSID";
const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD";
const char* SENSOR_ID     = "your-sensor-id";   // Settings > Connection
const char* SECRET_KEY    = "your-secret-key";  // Settings > Connection

HydroNode hydro(SENSOR_ID, SECRET_KEY);
Adafruit_BME280 bme;

void setup() {
  Serial.begin(115200);
  hydro.setDebug(Serial);  // prints every request and answer

  if (!bme.begin(0x76)) {
    Serial.println("BME280 not found, check the wiring");
  }
  while (!hydro.connectWiFi(WIFI_SSID, WIFI_PASSWORD)) {
    Serial.println("WiFi failed, retrying");
  }
  hydro.begin();
}

void loop() {
  HydroNodeValue reading[] = {
    {"TEMPERATURE", bme.readTemperature()},
    {"HUMIDITY",    bme.readHumidity()},
    {"PRESSURE",    bme.readPressure() / 100.0f},
  };
  int codes[3];
  int status = hydro.sendValues(reading, 3, codes);
  Serial.printf("HydroNode answered %d\n", status);

  delay(60000);  // one round per minute
}
  1. ReadBME280 over I²C
  2. sendValues()One signed HTTPS request
  3. 202Values stored and charted
  4. CommandsArrive with the answer
What happens every round. The library fetches the time on its own and refreshes it every 30 minutes.

Check that the values arrive

Open the serial monitor at 115200 baud. HydroNode answered 202 means accepted. Then open the sensor page in HydroNode and press ` to open the console. Every request shows up the moment it arrives, with hmac ok and how far the device clock is off.

The Live tab of the console with accepted HTTP requestsThe Live tab of the console with accepted HTTP requests
One line per request: time, path, status, values, signature check and clock offset.
AnswerMeaningWhat to do
202AcceptedNothing, all good.
401Signature or time wrongCheck the Sensor ID and secret. The console tells you the exact reason.
429Too fastAt most one value per measurement type every 10 seconds.
-2No timeAllow UDP port 123 (NTP) on your network.
-4Invalid type nameUse upper case: TEMPERATURE, not temperature.

If it still gets stuck, Debugging with the device console walks you through it.

Switch a relay from the app

A HydroNode command has a name, a type and a value. Your device reports back for every command whether it took it or why not. One name can have several types: relay1 true switches on for good, relay1 1400 only for 1.4 seconds.

Commands.inoC++
const int RELAY_PIN = 5;  // most relay modules switch on at LOW

void setup() {
  // WiFi and hydro.begin() as in the sketch above
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, HIGH);  // off after power-up

  // relay1 true / relay1 false
  hydro.onBool("relay1", [](bool on) {
    digitalWrite(RELAY_PIN, on ? LOW : HIGH);
  });

  // relay1 1400: on for 1400 ms, then off again
  hydro.onUInt32("relay1", [](uint32_t ms) {
    ms = min(ms, (uint32_t)10000);  // local safety limit
    digitalWrite(RELAY_PIN, LOW);
    delay(ms);
    digitalWrite(RELAY_PIN, HIGH);
  });
}
  1. Send a commandOn the sensor page press Send command, name relay1, type BOOL, value true. Or type relay1:bool true in the Commands tab of the console.
  2. Wait for the next roundCommands travel with the answer to the next value the device sends. With one round per minute, that takes up to a minute.
  3. Read the statusAcknowledged means taken. Declined names the reason, for example NO_HANDLER when the device has no callback for that name and type.
Safety An acknowledgement means the device received the command, not that the pump actually ran. Pumps, heaters and dosing systems need time limits and interlocks on the device itself, like the 10 second cap in the example.

Where to go next