Neu: Die KI-Firewall überwacht jedes Modul und erklärt jeden Vorfall in einfachen Worten. So funktioniert es

Firmware- und Geräteeinstellungen-API

Signierte Firmware hochladen, zuweisen, Rollouts in Wellen ausführen und steuern sowie die Einstellungen lizenzierter Geräte über REST lesen und ändern – Routen, Anfragekörper und Fehler.

Diese Seite behandelt zwei Gruppen von Routen: Firmware-Updates (OTA) und Remote-Geräteeinstellungen. Wie beide für Anwender funktionieren, steht unter Firmware-Updates (OTA), Firmware-Rollout-Wellen und Remote-Geräteeinstellungen. Pfade beginnen mit https://<your host>/tenant/<tenantId>.

Firmware-Routen

MethodePfadBerechtigungFunktion
GET/api/iot/ota/packagesiot_ota.readPakete auflisten (status, title)
POST/api/iot/ota/packagesiot_ota.packages.managePaket hochladen (multipart)
GET/api/iot/ota/packages/{packageId}iot_ota.readEin Paket mit seinen Update-Zählern
PATCH/api/iot/ota/packages/{packageId}iot_ota.packages.manageVersionshinweise oder Status DEPRECATED, erneut READY, REVOKED
DELETE/api/iot/ota/packages/{packageId}iot_ota.packages.manageEin nicht verwendetes Paket löschen
GET, POST/api/iot/ota/assignmentsLesen: iot_ota.read; zuweisen: iot_ota.assignZuweisungen auflisten oder anlegen
DELETE/api/iot/ota/assignments/{assignmentId}iot_ota.assignEine Zuweisung entfernen
GET/api/iot/ota/rolloutsiot_ota.readRollouts in Wellen (packageId, status)
GET, POST/api/iot/ota/rollouts/{rolloutId}Lesen; iot_ota.assignLesen; { "action": "pause" \| "resume" \| "abort" }
GET/api/iot/ota/statesiot_ota.readUpdate-Versuche (packageId, state, limit bis 500)
GET, POST/api/iot/ota/devices/{deviceId}Lesen; iot_ota.assignDas Update eines Geräts; { "action": "retry" }
GET, PUT/api/iot/ota/settings/{profile\|device}/{id}Lesen; iot_ota.assignOTA-Einstellungen eines Profils oder die Ausnahme für getaktete Verbindungen eines Geräts
GET, POST/api/iot/ota/signing-keysLesen; iot_ota.keys.manageSignatur-Public-Keys auflisten oder hinzufügen
DELETE/api/iot/ota/signing-keys/{keyId}iot_ota.keys.manageEinen Schlüssel widerrufen

Signaturschlüssel hinzufügen und widerrufen ist eine Owner-Berechtigung, daher kann ein API-Schlüssel das nicht.

Ein Paket hochladen

POST /api/iot/ota/packages erwartet multipart/form-data mit zwei Teilen: file (das Image) und meta (JSON-Text). Die Prüfsumme wird geprüft, bevor etwas gespeichert wird, und die Signatur wird gegen Ihre registrierten Schlüssel verifiziert.

curl -s -X POST "https://$HOST/tenant/$TENANT/api/iot/ota/packages" \
  -H "Authorization: Bearer $HERMETRY_KEY" \
  -F "file=@router-fw-2.5.0.bin" \
  -F 'meta={"title":"router-fw","version":"2.5.0","checksum":"<sha256 of the file>","signatureScheme":"usign-ed25519","signature":"<text of the .sig file>","profileId":"a1b2…","releaseNotes":"Fixes LTE reconnect."}'
Feld metaRegeln
title1 bis 128; Buchstaben, Ziffern, ., _, +, -
version1 bis 64; Buchstaben, Ziffern, ., _, +, ~, -
checksumSHA-256 der Datei, 64 hexadezimale Zeichen
signatureSchemeusign-ed25519 (eine losgelöste Signatur in signature), das Secure-Boot-Schema der Gerätefamilie, für die das Paket bestimmt ist, oder none (nur wenn das Profil unsignierte Images erlaubt)
typeFIRMWARE oder SOFTWARE
profileId, hardwareModels (bis 50), minFromVersionFür welche Geräte es passt
releaseNotesbis 4.000 Zeichen

Die maximale Standardgröße beträgt 64 MiB. Die Antwort ist 201 { "package": {...} }.

AblehnungMeldung
400 file_missingFügen Sie die Firmware-Datei an.
413 too_largeDas Paket ist größer als erlaubt.
413 quotaFür dieses Paket ist nicht genug Speicher frei.
422 checksum_mismatchDie SHA-256 der hochgeladenen Datei stimmt nicht mit der angegebenen überein.
422Die Signatur des Images lässt sich mit keinem registrierten Schlüssel verifizieren.
409 package_existsEin Paket mit diesem Titel und dieser Version existiert bereits.

Zuweisen und ausrollen

POST/tenant/{tenantId}/api/iot/ota/assignments

Weist ein READY-Paket einem PROFILE oder einem DEVICE (in targetId) oder einer GROUP zu (deviceIds, bis 5.000, oder selector.profileId, beides wird jetzt eingefroren). dryRun: true liefert die Anzahlen und schreibt nichts. waves (1 bis 20) rollt ein Profil oder eine Gruppe in Wellen aus; ein einzelnes Gerät wird nie in Wellen ausgerollt.

Anfragetext application/json

{
    "packageId": "f00d…",
    "targetType": "PROFILE",
    "targetId": "a1b2…",
    "waves": [
        {
            "size": {
                "percent": 5
            },
            "soakMin": 60,
            "minSuccessPct": 95,
            "maxFailurePct": 2,
            "maxDurationMin": 1440
        },
        {
            "size": {
                "percent": 100
            },
            "soakMin": 0,
            "minSuccessPct": 95,
            "maxFailurePct": 2,
            "maxDurationMin": 2880
        }
    ]
}

Beispiel curl

curl -X POST 'https://<your-host>/tenant/{tenantId}/api/iot/ota/assignments' \
  -H 'Content-Type: application/json' \
  -d '{"packageId":"f00d…","targetType":"PROFILE","targetId":"a1b2…","waves":[{"size":{"percent":5},"soakMin":60,"minSuccessPct":95,"maxFailurePct":2,"maxDurationMin":1440},{"size":{"percent":100},"soakMin":0,"minSuccessPct":95,"maxFailurePct":2,"maxDurationMin":2880}]}'

Antworten

201Erstellt
{
    "assignment": {
        "…": "…"
    },
    "preview": {
        "…": "…"
    },
    "result": {
        "…": "…"
    }
}
200OK
{
    "assignment": null,
    "preview": {
        "…": "…"
    }
}
409Konflikt
{
    "message": "Only a ready package can be assigned.",
    "code": "CONFLICT"
}

Die size einer Welle ist { "percent": 0–100 } oder { "count": 1–100000 }; die letzte Welle nimmt den Rest. soakMin 0 bis 10.080, minSuccessPct und maxFailurePct 0 bis 100, optional maxFailures, maxDurationMin 5 bis 43.200.

Rollout-Status: RUNNING, PAUSED, COMPLETED, ABORTED. Ein fehlgeschlagenes Gate pausiert den Rollout; resume setzt ihn fort, abort beendet ihn.

Update-Status

Das Update eines Geräts durchläuft QUEUED, INITIATED, WAITING, DOWNLOADING, DOWNLOADED, VERIFIED, UPDATING und endet mit UPDATED, FAILED, TIMEOUT, ROLLED_BACK, SKIPPED oder CANCELLED. Nur FAILED, TIMEOUT und ROLLED_BACK können wiederholt werden ({ "action": "retry" }), bis zum Versuchslimit.

OTA-Einstellungen

PUT /api/iot/ota/settings/profile/{profileId} erwartet otaEnabled, allowMetered, allowUnsigned, downloadTimeoutMin (5 bis 1.440), updateTimeoutMin (2 bis 240), maxAttempts (1 bis 10); null setzt auf den Standard zurück. Für ein Gerät (/settings/device/{deviceId}) wird nur allowMetered übernommen: „Ein Gerät übernimmt nur die Einstellung für getaktete Verbindungen.“

Webhook-Ereignisse: ota.update.* und ota.rollout.*, siehe die Webhook-Ereignisreferenz.

Routen für Geräteeinstellungen

Remote-Einstellungen gelten für lizenzierte Geräte, deren Modell ein Einstellungsmanifest veröffentlicht.

MethodePfadBerechtigungFunktion
GET/api/iot/devices/{deviceId}/settingsiot_device_settings.readJeder Abschnitt: Soll- und Istwerte, Status, Drift
GET/api/iot/devices/{deviceId}/settings/schema.readDas Manifest des Modells und der Firmware des Geräts
GET/api/iot/devices/{deviceId}/settings/history.readFrühere Änderungen (section, page ab 0, sort=at:desc)
GET/api/iot/devices/{deviceId}/settings/{section}.readEin Abschnitt; ETag ist seine Revision
PUT/api/iot/devices/{deviceId}/settings/{section}.operate und die geänderten KlassenEinen Abschnitt ersetzen: { values, confirm? }
PATCH/api/iot/devices/{deviceId}/settings/{section}.operate und die geänderten KlassenMerge-Patch: { patch, confirm? }
POST/api/iot/devices/{deviceId}/settings/{section}/reapply.operateDen Soll-Abschnitt erneut senden
GET/api/iot/device-settings/models, /model-schema?model=.readIhre Modelle und die Abschnitte eines Modells
GET, POST/api/iot/device-settings/baselines.read; .baselines.manageBaselines auflisten oder anlegen
GET, PUT, DELETE/api/iot/device-settings/baselines/{baselineId}.read; .baselines.manageLesen, ersetzen, löschen
GET, POST/api/iot/device-settings/jobs.read; .jobs.manageMassenjobs auflisten oder starten
GET/api/iot/device-settings/jobs/{jobId}, .../targets.readEin Job, seine Wellen und seine Geräte
POST/api/iot/device-settings/jobs/{jobId}/pause, /resume, /cancel.jobs.manageEinen Job steuern

Was ein Schreibvorgang ändern darf, hängt von der Klasse jeder geänderten Einstellung ab: Betriebseinstellungen benötigen iot_device_settings.operate, Konfigurationseinstellungen iot_device_settings.write, gefährliche Einstellungen iot_device_settings.dangerous.write (nur Owner, daher nie ein API-Schlüssel) und "confirm": true.

Einen Abschnitt ändern

GET  /api/iot/devices/{deviceId}/settings/network        → ETag: "7"
PATCH /api/iot/devices/{deviceId}/settings/network
If-Match: "7"
{ "patch": { "lte": { "apn": "iot.example" } } }
  • If-Match ist erforderlich: Ohne diesen Header antwortet die API mit 428 „If-Match is required: send the rev you read.“
  • Wurde ein Abschnitt seit dem Lesen geändert, antwortet die API mit 412 „The section changed since it was read; read it again.“ (rev_mismatch).
  • ?dryRun=true prüft und listet auf, was sich ändern würde, und speichert nichts.
  • Ein Merge-Patch führt Objekte zusammen, löscht mit null und ersetzt Listen vollständig.
  • Schreibvorgänge sind auf 600 pro Organisation und Minute begrenzt.
  • Geheimnisse werden nie zurückgegeben: Eine geheime Einstellung wird als { "set": true } gelesen.

Ein Gerät, das keine Einstellungen nach Abschnitt annimmt, antwortet mit 409 „This device does not take settings by section.“; eines, dessen Manifest noch nicht im Katalog ist, mit „The settings manifest of this device’s model and firmware is not in the catalog yet.“

Massenjobs

POST /api/iot/device-settings/jobs mit dem Header Idempotency-Key: name (bis zu 80), baselineId oder sections, selector (deviceIds, profileId oder models), optional waves ({ "percent": [1, 10, 100] } oder { "count": [...] }, bis zu 10), gates (minApplied, maxReverted als Anteile von 0 bis 1), onConflict (queue oder skip), offlineExpiryDays (1 bis 90), waveTimeoutMin (1 bis 1.440), confirm. Ein wiederholter Idempotency-Key liefert den ersten Job (200). ?dryRun=true liefert den Plan. Ablehnungen: 409 too_many_jobs; 422 confirm_required, invalid_sections, no_devices, too_many_devices; 403 class_forbidden.