Voorbeelden
Voorbeeld: curl
Elk endpoint van de apparaat-API uitproberen met curl, met echte verzoeken en antwoorden, en de configuratie alleen ophalen als hij veranderd is.
Met curl probeer je elk endpoint uit voordat je code schrijft, en zie je precies wat de server antwoordt. De voorbeelden gaan uit van regelkring 201: T1 collector, T2 onderzijde vat, T3 bovenzijde vat, R2 pomp.
Voorbereiding
API=https://boilerbuddy.eu/api/v1
TOKEN=bb_live_42_... # the API key of your device, from the portal
Nog geen sleutel? Koppel hieronder, of maak er een in het portaal: zie Je eigen BoilerBuddy bouwen. Met read -rs TOKEN blijft de sleutel uit je shell-history.
Koppelen
Maak één keer een uuid (versie 4) en vraag een code:
UUID=$(python3 -c 'import uuid; print(uuid.uuid4())')
curl -s -X POST "$API/device/hello" \
-H "Content-Type: application/json" \
-d "{\"device_uuid\": \"$UUID\", \"firmware_version\": \"curl-test\"}"
Zolang niemand het apparaat heeft gekoppeld:
{"claimed":false,"pairing_code":"BB-7KQ4-M2XD","expires_at":"2026-10-16T09:30:00+00:00"}
Vul de code in bij Koppelen met code op de pagina van het apparaat, en stuur hetzelfde commando opnieuw:
{"claimed":true,"token":"bb_live_42_Xk3..."}
Bewaar het token en gebruik het meteen, bijvoorbeeld hieronder. Daarna geeft hello alleen nog:
{"claimed":true}
Waarom: zie Koppelen via hello.
Configuratie ophalen
curl -s -i "$API/device/config" -H "Authorization: Bearer $TOKEN"
HTTP/2 200
content-type: application/json
etag: "9f2c1a0b7d3e4f56"
{"config_version":"9f2c1a0b7d3e4f56","device":{"id":42,"name":"Zolder","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":"\u00b0C","position":null,"address":{"register":38,"decimals":1,"signed":true,"function_code":3},"plausible_min":-50.0,"plausible_max":250.0}, ...]}
Alleen de sensorcodes, met jq:
curl -s "$API/device/config" -H "Authorization: Bearer $TOKEN" | jq -r '.sensors[].sensor'
T1
T2
T3
R2
Alleen ophalen als er iets veranderd is
Stuur de ETag terug in If-None-Match. Niets veranderd? Dan krijg je 304 zonder body:
curl -s -i "$API/device/config" \
-H "Authorization: Bearer $TOKEN" \
-H 'If-None-Match: "9f2c1a0b7d3e4f56"'
HTTP/2 304
etag: "9f2c1a0b7d3e4f56"
In een script vervang je configuratie en ETag alleen bij een 200:
# First time: keep the body and the ETag
curl -s -D headers.txt -o config.json "$API/device/config" -H "Authorization: Bearer $TOKEN"
ETAG=$(grep -i '^etag:' headers.txt | cut -d' ' -f2 | tr -d '\r')
# Later: only download when something changed
STATUS=$(curl -s -D headers.txt -o new.json -w '%{http_code}' "$API/device/config" \
-H "Authorization: Bearer $TOKEN" -H "If-None-Match: $ETAG")
if [ "$STATUS" = 200 ]; then
mv new.json config.json
ETAG=$(grep -i '^etag:' headers.txt | cut -d' ' -f2 | tr -d '\r')
fi
Metingen insturen
NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)
BATCH=$(python3 -c 'import uuid; print(uuid.uuid4())')
curl -s -X POST "$API/device/readings" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
--data @- <<EOF
{
"batch_uuid": "$BATCH",
"readings": [
{"sensor": "T1", "value": 61.4, "measured_at": "$NOW"},
{"sensor": "T2", "value": 38.0, "measured_at": "$NOW"},
{"sensor": "R2", "value": 10, "measured_at": "$NOW"}
]
}
EOF
{"accepted":3,"duplicates":0,"unmapped":[],"rejected":[]}
Nog een keer precies hetzelfde (zelfde $NOW) slaat niets dubbel op:
{"accepted":0,"duplicates":3,"unmapped":[],"rejected":[]}
Een batch met fouten
Fouten in losse metingen geven toch 200. Het antwoord zegt per meting wat er mis is:
NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)
curl -s -X POST "$API/device/readings" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
--data @- <<EOF
{
"readings": [
{"sensor": "T1", "value": 61.5, "measured_at": "$NOW"},
{"sensor": "T9", "value": 30.0, "measured_at": "$NOW"},
{"sensor": "T2", "value": "warm", "measured_at": "$NOW"},
{"sensor": "T3", "value": 55.0, "measured_at": "2030-01-01T00:00:00Z"}
]
}
EOF
{"accepted":1,"duplicates":0,"unmapped":["T9"],"rejected":[{"index":2,"reason":"invalid_value","retry":false},{"index":3,"reason":"measured_at_in_future","retry":false}]}
T9 hoort niet bij regelkring 201 en staat nu in quarantaine. Alle redenen staan bij Metingen insturen.
Een batch die als geheel niet klopt
curl -s -X POST "$API/device/readings" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"readings": []}'
{"message":"The readings field is required.","errors":{"readings":["The readings field is required."]}}
Dat is een 422: opnieuw sturen helpt niet.
Status sturen
curl -s -i -X POST "$API/device/status" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"firmware_version": "curl-test", "uptime_s": 3600, "buffered": 0}'
HTTP/2 204
Op de pagina van het apparaat staat dan curl-test bij Firmware, en Laatst gezien is bijgewerkt.
Fouten
Een verkeerd of vervangen token:
curl -s -i "$API/device/config" -H "Authorization: Bearer bb_live_42_wrong"
HTTP/2 401
www-authenticate: Bearer
content-type: application/json
{"message":"Unauthenticated."}
Te veel uploads in een minuut:
HTTP/2 429
retry-after: 37
content-type: application/json
{"message":"Too Many Attempts."}
Wacht het aantal seconden uit retry-after en stuur dezelfde batch opnieuw. Meer bij Limieten en foutcodes.