View examples on GitHubgithub.com / TexhFexLabs / HydroNode-Library

Install via Arduino Library Manager

The library is available in the official Arduino Library Manager: Arduino IDE → Tools → Manage Libraries, search for HydroNode-Library and install it. The IDE offers to install all dependencies automatically. For reference, these are:

WiFiManager
Captive-portal based WiFi provisioning
WiFiManager
ArduinoJson
JSON serialization / deserialization
ArduinoJson
ArduinoHttpClient
HTTP client for Arduino
ArduinoHttpClient
NTPClient
Network time protocol client
NTPClient
base64
Base64 encoding (densaugeo)
base64_arduino
Crypto
HMAC-SHA256 (Rhys Weatherley)
Crypto

Alternatively, clone the repository from GitHub into your libraries/ folder and install the dependencies above manually:

shell
git clone https://github.com/TexhFexLabs/HydroNode-Library.git ~/Arduino/libraries/HydroNode

Full .ino sketch

Replace YOUR_WIFI_SSID, YOUR_WIFI_PASSWORD, YOUR_SENSOR_ID, and YOUR_SECRET_KEY with your values. Sensor ID and secret key are shown when you create a sensor and can later be revealed by the owner under Sensor Settings → Credentials in the web app or iOS app. WiFi credentials are passed directly. No captive portal required.

The Secret Key authenticates every HMAC request. Keep it in the device configuration, never publish it, and never commit it to source control.
arduino / C++
#include <HydroNode.h>

// WiFi credentials
const char* WIFI_SSID     = "YOUR_WIFI_SSID";
const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD";

// Available to the owner under Sensor Settings -> Credentials
const char* SENSOR_ID  = "YOUR_SENSOR_ID";
const char* SECRET_KEY = "YOUR_SECRET_KEY";

HydroNode hydro(SENSOR_ID, SECRET_KEY);

// Handle remote commands queued in the HydroNode app
void pumpCallback(int ms) {
  Serial.println("Pump command received: " + String(ms));
  // run pump for ms milliseconds
}

void setup() {
  Serial.begin(115200);
  hydro.setDebug(Serial);  // optional: log WiFi/NTP/HTTP activity

  while (!hydro.connectWiFi(WIFI_SSID, WIFI_PASSWORD)) {
    Serial.println("WiFi failed, retrying...");
  }
  hydro.begin();  // starts NTP time sync (required for signatures)

  hydro.on("pump", HydroNode::bindCallback<int>(pumpCallback));
}

void loop() {
  // Replace with real sensor readings from your hardware
  float temperature = 22.4;  // °C
  float humidity    = 65.2;  // %RH

  // The backend accepts one submission per sensor every 9 s,
  // so alternate types with at least 10 s between sends.
  hydro.sendValue("TEMPERATURE", temperature);
  delay(10000);
  hydro.sendValue("HUMIDITY", humidity);
  delay(10000);
}

Captive portal setup via WiFiManager

A second sketch variant uses WiFiManager instead of hardcoded credentials. On first boot, the device opens a WiFi access point named HydroNode-Setup-XXXX (the last four characters of your sensor ID, via hydro.getApName()). Connect to it from any phone or laptop; a captive portal opens where you enter your network credentials. The device saves them to flash and reboots into normal operation. No password is ever compiled into the firmware.

The WiFiManager example sketch is available in the library's examples/ folder on GitHub.

Make an outdoor HMAC sensor a station

If this ESP32 is part of your own outdoor weather or environmental installation, you can add a Station Interface without changing the sketch or switching to LoRaWAN. This is useful when the measurements could also help other HydroNode users.

  1. 1
    Save the sensor as Outdoor
    Open the sensor's General settings, select Outdoor, and save. Indoor sensors cannot have a Station Interface.
  2. 2
    Create the Station Interface
    Under Sensor Settings → Station Interface, select Create Station Interface. The existing HMAC credentials and incoming data remain unchanged.
  3. 3
    Set location and optional public visibility
    Open Station Settings, enter GPS coordinates, and enable public visibility only if you want the station to appear on the map.
The Station Interface can be removed again in Station Settings without deleting this sensor or any measurements. Removing GPS alone makes the station private.
The first argument to sendValue() is the sensor type identifier and is case-sensitive: always use the exact uppercase key (e.g. TEMPERATURE, not temperature), otherwise the backend creates a separate measurement type. See the full list of supported types on the Sensor Types reference page.