Skip to content
BoilerBuddy

API

Fetching the configuration

What GET /device/config returns, how to poll cheaply with ETag and 304, and how a device reads the controller.

With GET /device/config your device learns which sensor codes to report and how often to measure. With the ETag you only download it when something has changed.

What it contains

For circuit 201 (collector, tank bottom, tank top, pump), shortened to two sensors:

{
  "config_version": "9f2c1a0b7d3e4f56",
  "device": {"id": 42, "name": "Attic", "mode": "live"},
  "intervals": {"scan_seconds": 60},
  "controller": {
    "brand": "OEG", "model": "KSW-E, KSW, KS2W", "protocol": "modbus_ascii",
    "connection": {"slave_address": 128, "baudrate": 9600, "parity": "E",
                   "bytesize": 7, "stopbits": 1, "timeout_ms": 1000}
  },
  "sensors": [
    {"sensor": "T1", "name": "Temperatuur zonnepaneel", "type": "collector_temp",
     "category": "temperature", "unit": "°C", "position": null,
     "address": {"register": 38, "decimals": 1, "signed": true, "function_code": 3},
     "plausible_min": -50.0, "plausible_max": 250.0},
    {"sensor": "R2", "name": "Pomp", "type": "pump",
     "category": "relay", "unit": null, "position": null,
     "address": {"register": 58, "decimals": 1, "signed": true, "function_code": 3},
     "plausible_min": null, "plausible_max": null}
  ]
}
Field Meaning
config_version A hash of the content. Equal to the ETag, without the quotes
device Id, name and mode (live or simulated) of the device
intervals.scan_seconds How often the device measures, in seconds. 60 by default. Shown in the portal as Scan interval, but you cannot change it there
controller The controller of the circuit: brand, model, protocol (how to read it) and connection (that protocol's settings). null while the device has no circuit
sensors The sensors of the circuit

Per sensor:

Field Meaning
sensor The code you send with every reading, such as T1 or R2
name The name shown in the portal. Display only; the sensor names in the catalogue are in Dutch
type What the sensor measures, independent of brand: collector_temp, tank_bottom_temp, solar_pump, …
category temperature, relay (an output such as a pump or valve), energy or flow
unit Unit, such as °C, kWh or l/min. null for outputs
position Which tank or panel, for installations with more than one. Otherwise null
address Where the controller keeps the value, in the shape of the protocol. null if the controller does not have this sensor. See below
plausible_min, plausible_max The range in which a value can be right. null for outputs

Polling with ETag and 304

The answer has an ETag header:

ETag: "9f2c1a0b7d3e4f56"

Send it back unchanged next time:

If-None-Match: "9f2c1a0b7d3e4f56"

Nothing changed: 304 Not Modified without a body. Something changed: 200 with the new configuration and ETag.

  • A compressing proxy sometimes turns the ETag into W/"…" or "…-gzip". Send back what you received: the server recognises those forms too.
  • Every 15 minutes is enough; the BoilerBuddy Alpo does the same. Every request counts towards your 60 per minute.
  • It changes when the owner changes the circuit or the device name, or when BoilerBuddy changes the scan interval or the sensor catalogue.
  • Keep the last configuration on disk, so the device can measure after a restart even without internet.

Without a circuit

Right after it is created or paired, a device often has controller set to null and an empty sensors list. Don't send anything yet: every code would go into quarantine. Keep polling until the owner chooses a circuit; the ETag then changes.

Only codes from the configuration

Only send codes listed in sensors; any other code goes into quarantine (see Sending readings). If you briefly cannot read a sensor, send "quality": "no_response" with "value": null.

Reading the controller

controller.protocol says how to read the controller. controller.connection and each sensor's address have the shape of that protocol. Today that is always Modbus; more protocols may follow. If you don't know the protocol, read nothing and keep polling.

Modbus

For modbus_ascii and modbus_rtu, as on the Alpo:

  1. Open the serial port with the settings in connection: slave_address, baudrate, parity (E, O or N), bytesize and stopbits. timeout_ms is the time to wait per request.
  2. For each sensor, read one 16-bit register at address.register with address.function_code (3 is "read holding registers", 4 "read input registers"). signed: true means two's complement. Skip sensors without an address.
  3. Divide by 10 to the power of decimals: raw 614 with decimals: 1 is 61.4.
  4. 32767, -32768, 65535 or -9999 means "no sensor": send sensor_fault without a value.
  5. Outside plausible_min and plausible_max: send the value with out_of_range.
  6. No answer: send no_response without a value.

For the OEG KSW controllers (KSW-E, KSW and KS2W), T1 to T6 are at registers 38 to 43, R1 at 57, R2 at 58 and R3 at 31, all with one decimal, signed and function code 3.

If you read your sensors another way, ignore controller and address and only use sensor, type, category, unit and the plausible range. See Building your own BoilerBuddy.

Stuck?

Ask your question through the contact form. We'll help you out and make this page better.

Contact us