Skip to content
Obscenter

Docs Install

Connect an IoT device

Send sensor readings from an ESP32 or any microcontroller over HTTPS: the JSON contract, the served settings, a DS18B20 sketch and a curl test.

A microcontroller cannot run an agent. An ESP32 has a few hundred kilobytes of RAM and no operating system to install anything into. So the device is the agent. The whole integration is one JSON object posted over HTTP, and nothing is installed on the device.

Two addresses and a key

Address
ReadingsPOST https://your-install/collect/iot
The formatGET https://your-install/iot/settings?k=KEY

The key goes in the body as k, or in the X-Api-Key header. One key is enough for a whole fleet. The key says which install a report belongs to, and the device's own id says which device it is. You can make a device key of your own per place, named after it, and switch it off when you need to. See Device keys.

You do not register a device. It appears on its first report, under its own id, and you rename it on its page afterwards.

The second address is the point of the design. Firmware is the one thing nobody can redeploy from a dashboard, so the contract is served rather than documented. It lists every field, unit, kind and limit, with a worked example. The device fetches it on boot, so a board flashed two years ago picks up an interval changed this morning. The Install page renders the same document, which means the description and what the collector accepts cannot drift apart.

What to send

{
  "k":    "YOUR_KEY",
  "id":   "a4cf12ab34cd",
  "name": "Boiler room",
  "dev":  { "model": "esp32", "fw": "1.0.0", "mac": "A4:CF:12:AB:34:CD",
            "ip": "192.168.1.42", "rssi": -63, "up": 3600, "heap": 182000,
            "boot": 4, "interval": 60, "cfg": "" },
  "m":    [ { "s": "28FF641F2713A2C1", "n": "flow", "t": "temperature",
              "u": "C", "v": 42.31, "q": 1 } ]
}
  • id is derived from hardware: the WiFi MAC, lower case, without colons. A reflash keeps the same device.
  • s is the address the sensor itself carries, such as a DS18B20's ROM code. It is never the index on the bus, because two probes that swap places would swap their histories.
  • v may be negative. Send what the sensor gives you, in SI units, and say the unit.
  • q: 0 marks a reading the sensor itself distrusts. For a DS18B20 that is exactly 85.0, its power-on default, or -127, no answer. The collector counts those readings and refuses to chart them.
  • dev is reported on every post. Signal strength, free heap, uptime and boot count are what explain a device that goes quiet at night.
  • Optional: ts per report or per reading, log for lines that will never become a reading, and tr for the phases of the previous report cycle.

The same reading sent twice is stored once, keyed on sensor and time. That lets the firmware buffer readings and resend them with their real timestamps. The Install page lists every field under Every field, named.

The answer is the settings channel

{ "ok": true, "stored": 2, "dropped": 0,
  "interval_s": 60,
  "config": { "interval_s": 60 },
  "config_version": "db98a4fac51c" }

Nothing can reach a sensor, and nothing needs to. Settings ride back on the answer to a report the device itself made. There is no broker, no open port, and no inbound path into the network the sensor sits on. Apply interval_s, apply the parameters you recognise, and send the config_version back as dev.cfg. That acknowledgement is how the dashboard tells a device that obeyed from one that never listened. Re-fetch the settings document only when its settings_version changes. See Settings and actions.

Test it with curl

curl -sS https://your-install/collect/iot -H 'Content-Type: application/json' -d '{"k":"YOUR_KEY","id":"bench01","name":"Bench test","dev":{"model":"curl","fw":"0"},"m":[{"s":"28FF000000000001","n":"test","t":"temperature","u":"C","v":21.5}]}'

A device called bench01 appears within a second. You can forget it again from its own page.

ESP32 with DS18B20 probes

The Install page carries a complete Arduino sketch for an ESP32 with one-wire temperature probes. It needs only the OneWire and DallasTemperature libraries: no MQTT broker, no cloud account, and no library of ours.

  1. Wire the data line to GPIO 4, with a 4.7 kΩ pull-up to 3V3. Every probe goes on the same two wires, and the bus finds them.
  2. Put your WiFi details in and flash it.
  3. Watch the serial monitor. The first line names the device id and how many probes answered.

Three choices in it are worth reading twice. The device id is the MAC and nothing else. A probe is addressed by its ROM code. And the TLS connection is opened once and kept. Measured on an ESP32 against this collector, a handshake per report cost 6.3 seconds and the whole cycle 12.7 seconds. On a kept connection the same report took 54 milliseconds. The sketch pins the certificate authority, so do not replace that with setInsecure().

For a different board or sensor, The brief on the Install page states the contract as eleven rules you can hand to whoever writes the next firmware. They are the same rules the collector enforces.

Did it work

  • IoT devices: the board appears by its id within one interval, with its probes and their latest readings.
  • The serial monitor: a 200 with {"ok":true,"stored":…} means the report landed. dropped above zero comes with a reason saying what the collector could not read.
  • 404 unknown key: the device is not sending the key you think. Other 4xx answers mean the payload is wrong. Do not retry those. Retry 5xx answers and timeouts with a back-off.