iodriven.techLog in

platform

Your sensors report.Your rules decide.Your actuators move.

iodriven ingests sensor telemetry over MQTT, evaluates every threshold and rule in memory, the moment a message arrives, and drives the response — an actuator command, a notification, or a webhook — in under two seconds.

demo/sensor01/temperature28.1 °Cthreshold 30.0re-arm 28.0
thresholdre-arm
watching — condition must hold 1.5s before firing
breach → command
fan1 OFF

what it does

A rules engine wired straight to your hardware.

acquire

ESP32-class devices publish readings over MQTT/TLS. Everything lands in TimescaleDB and streams to the browser over WebSocket for live dashboards.

decide

A rule watches one metric — a threshold, or a rolling window — on the reading itself, the instant it arrives. No polling, no cron.

act

A firing rule sends an actuator command, raises a notification, or calls a webhook. One rule, one of three outcomes.

the other end

Real relays are on the other end of the command.

Duration, hysteresis, and cooldown are part of every rule — not an advanced tab you forget to open. A rule holds its condition before it fires, waits for the reading to fall back past a margin before it re-arms, and rate-limits itself. A noisy sensor will never chatter your relay to death.

for_duration

The condition must hold this long before the rule fires — brief spikes are ignored.

hysteresis

The reading must fall back past a margin before the rule can fire again.

cooldown

A hard floor on the time between two firings of the same rule.

hot-path

The decision never waits on a disk.

Hot path

Rules run in the worker’s memory with no database read. A breach goes straight to the command service, out through EMQX, and onto the device.

reading → evaluate → command → EMQX → actuator

Storage path

Telemetry is pushed to a Redis stream and drained by a writer that batches inserts into TimescaleDB. Built for throughput, not latency.

reading → Redis stream → batched writer → TimescaleDB

A batch flush is never between a reading and a decision. That’s the rule that keeps the two-second budget honest.

onboarding

From sign-up to live data in ten minutes.

  1. Create a workspace. The tenant is provisioned in the same step — there’s no separate setup.

  2. Define a device template. The metrics a device reports, the actuators it drives, the units and ranges.

  3. Copy the generated Arduino sketch. Topics, TLS, and the per-device credential are already filled in.

  4. Flash it. Readings appear on the live chart, and any rule you armed is already watching.

No SDK to vendor, no sales call. A device speaks four MQTT topics and it’s done.

device contract

The contract a device speaks is small and fixed.

{tenant}/{device}/{metric}            telemetry        device → platform
{tenant}/{device}/cmd/{actuator}      command          platform → device, QoS 1
{tenant}/{device}/state/{actuator}    desired state    retained
{tenant}/{device}/ack/{actuator}      acknowledgement  device → platform

MQTT over TLS. Per-device tokens, stored hashed with argon2id — never in plaintext. One firmware build works against the multi-tenant platform or a single-tenant deployment, because the contract is the same on both.

one host

Runs on one box. Isolated by the database.

Sized for 500 to 1,000 devices on one Linux VPS — Docker Compose, daily backups with a restore runbook that has actually been run, no cluster to keep alive at 3am. Every table carries a tenant id with a Postgres row-level-security policy behind it, so a forgotten WHERE clause is a bug, not a data breach. Anomaly detection is next, and it arrives as another evaluator on the same in-memory hot path — not another service to operate.

Ready when your devices are.

No workspace yet? Create one — it takes under a minute.