SDK, protocol and examples on GitHubgithub.com / TexhFexLabs / hydronode-sdk

Copy one file

Copy the file for your language from the repository above. No package manager, no dependencies. The SDK signs every request with your sensor's Sensor ID and Secret:

Sensor and credentialsCreate a sensor, copy Sensor ID and Secret, keep them safe
LanguageFileRuns on
Pythonpython/hydronode.pyRaspberry Pi, Linux, macOS, Windows (Python 3.8+)
MicroPythonpython/hydronode.pyESP32, ESP8266, Raspberry Pi Pico W
JavaScriptnode/hydronode.mjsNode.js 18+, Deno, Bun
Gogithub.com/TexhFexLabs/hydronode-sdk/goGo 1.21+
Shellshell/hydronode.shbash with curl and openssl

Send a round

All values of one reading go out in one request. 202 means stored. Then open the sensor in HydroNode and press `: the device console shows the request, the signature check and how far your clock is off.

python / micropython
from hydronode import HydroNode

hydro = HydroNode("YOUR_SENSOR_ID", "YOUR_SECRET")
hydro.send_values({"TEMPERATURE": 21.5, "HUMIDITY": 48})
javascript
import { HydroNode } from './hydronode.mjs';

const hydro = new HydroNode({ sensorId: 'YOUR_SENSOR_ID', secret: 'YOUR_SECRET' });
await hydro.sendValues({ TEMPERATURE: 21.5, HUMIDITY: 48 });
go
client := hydronode.New("YOUR_SENSOR_ID", "YOUR_SECRET")
client.SendValues(ctx, hydronode.Values{{"TEMPERATURE", 21.5}, {"HUMIDITY", 48}})
shell
SENSOR_ID=... SECRET=... ./hydronode.sh send TEMPERATURE=21.5 HUMIDITY=48
On MicroPython, set the clock first (ntptime.settime()), because every request carries the time. Copy hydronode_roots.py along and pass ca=ROOTS, then the board checks the server certificate. Without it the connection is encrypted but not verified. CPython, Node and Go use the system certificates on their own.

Store now, send later

record() keeps a reading with the time it was measured, flush() sends what is stored in one request, up to 100 rounds and 7 days back. Use it so a reading is never lost while the network is down, or to send once an hour from a battery device. A round sent twice is stored once.

python
hydro.load_buffer("buffer.json")       # what waited before a restart

hydro.record({"TEMPERATURE": 12.3})    # no network needed
hydro.save_buffer("buffer.json")

try:
    hydro.flush()                      # every stored round, each with its own time
except OSError:
    pass                               # offline: the rounds stay for the next try

Take commands from HydroNode

A command has a name, a type and a value, for example pump, UINT32, 4000. It arrives with the answer to the next reading. The SDK confirms it to HydroNode before your handler runs, and declines what has no handler or the wrong type, so the app shows Confirmed or the reason.

python
def run_pump(ms):
    ms = min(ms, 10000)                # never trust a network value
    pump_on(ms)

hydro.on("pump", run_pump, "UINT32")
hydro.on("lamp", lambda on: relay(on), "BOOL")
hydro.send_values({"WATER_LEVEL": 72})  # commands arrive with this answer

Complete programs to start from

Each example runs as it is once Sensor ID and Secret are filled in, and explains every step in its comments.

ExampleWhat it shows
python/examples/send_once.pyThe smallest complete program
python/examples/raspberry_pi_offline_safe.pyRaspberry Pi loop that never loses a reading (buffer file)
python/examples/commands.pyPump, lamp and text commands from HydroNode
python/examples/micropython_esp32.pyMicroPython on ESP32 or Pico W: WiFi, NTP, verified TLS
python/examples/micropython_collect_hourly.pyBattery: measure every 6 min, send 10 readings once an hour, deep sleep
node/examples/send.mjsOne reading from Node.js
node/examples/gateway.mjsForward readings from anywhere, buffered to a file, with commands
go/examples/send/main.goOne reading and a command handler in Go
shell/hydronode.shdry-run shows what would be signed, to find the cause of a 401

Any other language

If it can do HTTPS and HMAC-SHA256, it can talk to HydroNode. The full protocol is in PROTOCOL.md: every endpoint, answer and limit. In short:

signature
X-Sensor-Id:  <sensor id>
X-Timestamp:  <Unix seconds, within 2 minutes of the server>
X-Signature:  Base64(HMAC-SHA256(secret, canonical + X-Timestamp))

canonical: {"sensorId":"<id>","timestamp":<ts>,"values":[{"type":"TEMPERATURE","value":21.50}]}
POST https://hydronode.tech/api/webhook/sensor-values  (the body is the canonical text)
Values need exactly two decimals, rounded half up on the 32-bit float: 21.125 becomes 21.13, not the 21.12 that printf gives. Check your client against the shared test vectors (vectors/signature-vectors.json): HydroNode itself, the Arduino library and every SDK pass the same file.

A walk through all of it, with a Raspberry Pi that never loses a reading and a Pico W on batteries: Send sensor data from Python, MicroPython, Node.js and Go. On an ESP32 with Arduino, the Arduino library does the same over WiFi, Ethernet and LTE-M.