Zum Inhalt
BoilerBuddy

Beispiele

Beispiel: curl

Jeden Endpunkt der API für Geräte mit curl ausprobieren, mit echten Anfragen und Antworten, und die Konfiguration nur abrufen, wenn sie sich geändert hat.

Mit curl probierst du jeden Endpunkt aus, bevor du Code schreibst, und siehst genau, was der Server antwortet. Die Beispiele gehen von Regelkreis 201 aus: T1 Kollektor, T2 Speicher unten, T3 Speicher oben, R2 Pumpe.

Vorbereitung

API=https://boilerbuddy.eu/api/v1
TOKEN=bb_live_42_...   # der API-Schlüssel deines Geräts, aus dem Portal

Noch kein Schlüssel? Kopple unten oder erstelle einen im Portal: siehe Dein eigenes BoilerBuddy bauen. Mit read -rs TOKEN landet der Schlüssel nicht in deinem Shell-Verlauf.

Koppeln

Erzeuge einmalig eine UUID (Version 4) und frag nach einem 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\"}"

Solange niemand das Gerät gekoppelt hat:

{"claimed":false,"pairing_code":"BB-7KQ4-M2XD","expires_at":"2026-10-16T09:30:00+00:00"}

Gib den Code auf der Geräteseite bei Mit Code koppeln ein und schick dann denselben Befehl noch einmal:

{"claimed":true,"token":"bb_live_42_Xk3..."}

Speichere den Token und nutze ihn sofort, zum Beispiel unten. Danach gibt hello nur noch zurück:

{"claimed":true}

Warum: siehe Koppeln mit hello.

Die Konfiguration abrufen

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":"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":"\u00b0C","position":null,"address":{"register":38,"decimals":1,"signed":true,"function_code":3},"plausible_min":-50.0,"plausible_max":250.0}, ...]}

Nur die Sensorcodes, mit jq:

curl -s "$API/device/config" -H "Authorization: Bearer $TOKEN" | jq -r '.sensors[].sensor'
T1
T2
T3
R2

Nur abrufen, wenn sich etwas geändert hat

Schick das ETag in If-None-Match zurück. Hat sich nichts geändert? Dann bekommst du 304 ohne Body:

curl -s -i "$API/device/config" \
  -H "Authorization: Bearer $TOKEN" \
  -H 'If-None-Match: "9f2c1a0b7d3e4f56"'
HTTP/2 304
etag: "9f2c1a0b7d3e4f56"

Ersetze in einem Skript die Konfiguration und das ETag nur bei einer 200:

# Beim ersten Mal: Body und ETag aufbewahren
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')

# Später: nur herunterladen, wenn sich etwas geändert hat
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

Messwerte senden

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":[]}

Genau dasselbe noch einmal (gleiches $NOW) speichert nichts doppelt:

{"accepted":0,"duplicates":3,"unmapped":[],"rejected":[]}

Ein Batch mit Fehlern

Fehler in einzelnen Messwerten bekommen trotzdem 200. Die Antwort sagt pro Messwert, was nicht stimmt:

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 gehört nicht zu Regelkreis 201 und ist jetzt in Quarantäne. Alle Gründe stehen in Messwerte senden.

Ein Batch, der als Ganzes ungültig ist

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."]}}

Das ist eine 422: Noch einmal senden hilft nicht.

Einen Status senden

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

Die Geräteseite zeigt dann curl-test unter Firmware, und Zuletzt gesehen wird aktualisiert.

Fehler

Ein falscher oder ersetzter 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."}

Zu viele Uploads in einer Minute:

HTTP/2 429
retry-after: 37
content-type: application/json

{"message":"Too Many Attempts."}

Warte die Anzahl Sekunden aus retry-after ab und schick denselben Batch noch einmal. Mehr dazu in Limits und Fehlercodes.

Kommst du nicht weiter?

Stell deine Frage über das Kontaktformular. Wir helfen dir weiter und verbessern diese Seite.

Kontakt aufnehmen