Skip to content

Status und Requests

Diese Seite beschreibt, wie die App Requests aufbaut, ausführt und Antworten verarbeitet.

WidgetStatusConfig

Feld Typ Default Bedeutung
request EndpointRequestConfig? null direkter Status-Request
sharedRequestId String? null Referenz auf globalen Sammelrequest
responseKind ResponseKind auto erwartete Antwortart

Wichtige Regel:

  • genau eines von request oder sharedRequestId muss gesetzt sein
  • wenn ein Widget gar keinen Status braucht, darf status nur bei mode = "icon_text" oder mode = "shutter" komplett fehlen

EndpointRequestConfig

Feld Typ Default Bedeutung
url String kein Default Zieladresse
method EndpointRequestMethod? null optionale HTTP-Methode
headers Map<String, String> {} Request-Header
jsonBody JsonElement? null optionaler JSON-Body
timeoutMs Long? null überschreibt globales Timeout

Request-Aufbau

Zur Laufzeit erzeugt das Repository aus RequestDefaultsConfig und EndpointRequestConfig einen ResolvedRequest.

Merge-Regeln:

  • URL kommt immer aus dem konkreten Request
  • Header werden aus Defaults und Request zusammengeführt
  • widget-spezifische Header überschreiben Default-Header mit gleichem Key
  • timeoutMs des Requests überschreibt das Default-Timeout
  • wenn kein Accept gesetzt ist, setzt die App application/json, image/png, image/jpeg

HTTP-Methode

Unterstützte Werte für method:

  • get
  • post
  • put
  • patch
  • delete

Wenn method nicht gesetzt ist, verwendet die App automatisch:

  • GET, wenn jsonBody = null
  • POST, wenn jsonBody gesetzt ist

Wichtige Regel:

  • GET wird ohne JSON-Body ausgeführt
  • für Requests mit jsonBody solltest du POST, PUT, PATCH oder DELETE verwenden

ResponseKind

Wert Bedeutung
auto Antwort wird automatisch erkannt
json es wird JSON erwartet
text es wird ein einzelner Text-, Zahl- oder Boolean-Wert erwartet
jpg es wird ein JPG/JPEG erwartet
png es wird ein PNG erwartet

Automatische Erkennung:

  • image/png im Content-Type reicht aus
  • image/jpeg oder image/jpg im Content-Type reichen ebenfalls aus
  • alternativ prüft die App auch die PNG-Signatur der ersten Bytes
  • für JPG prüft die App zusätzlich die JPEG-Signatur
  • alles andere wird als JSON oder roher Text interpretiert

Hinweis zu text:

  • sinnvoll für Endpoints, die nur on, off, 23.5 oder true liefern
  • der Wert steht als primitiver Root-Wert zur Verfügung
  • für title.value oder value.value kannst du deshalb bei mode = "path" den Pfad $ verwenden

Beispiel für einen Text-Endpoint:

{
  "content": {
    "mode": "icon_text",
    "title": {
      "mode": "static",
      "value": "API-Status"
    },
    "value": {
      "mode": "path",
      "value": "$",
      "fallback": "unbekannt"
    }
  },
  "status": {
    "request": {
      "url": "https://example.org/api/healthz"
    },
    "responseKind": "text"
  }
}

Ergebnisobjekt EndpointExecutionResult

Zur Laufzeit liefert das Netzwerkmodul:

Feld Typ Bedeutung
statusCode Int HTTP-Statuscode
contentType String? Server-Content-Type
jsonPayload JsonElement? JSON- oder Textnutzlast
imageBytes ByteArray? Bilddaten, z. B. PNG oder JPG

Shared-Status-Requests

defaults.sharedStatusRequests erlaubt es, mehrere Widgets an dieselbe Statusantwort zu hängen.

Beispiel:

{
  "defaults": {
    "sharedStatusRequests": [
      {
        "id": "living-room-light-state",
        "request": {
          "url": "http://192.168.1.20/api/lights/living-room"
        }
      }
    ]
  },
  "widgets": [
    {
      "id": "light",
      "status": {
        "sharedRequestId": "living-room-light-state"
      }
    },
    {
      "id": "dimmer",
      "status": {
        "sharedRequestId": "living-room-light-state"
      }
    }
  ]
}

Laufzeitverhalten:

  • pro Refresh werden nur benötigte Shared-Requests ausgeführt
  • jeder benötigte Shared-Request läuft exakt einmal
  • alle Widgets lesen danach unterschiedliche Werte aus derselben JSON-Antwort

Fehlerverhalten

Wenn ein Widget nicht aktualisiert werden kann:

  • das Widget bleibt sichtbar
  • hasError = true
  • die Karte wird visuell ausgegraut
  • der bisherige Snapshot bleibt erhalten

URL-Regeln

Zulässig:

  • https://example.org/api/state
  • http://192.168.1.20/api/state

Nicht zulässig:

  • http://example.org/api/state
  • http://10.0.0.5/api/state
  • http://localhost/api/state
  • ftp://...

Die Logik sitzt in UrlPolicy.isAllowed(...).

Beispiel für einen Request mit Headern und Body

{
  "request": {
    "url": "https://example.org/api/energy/current",
    "method": "post",
    "headers": {
      "X-Api-Key": "demo"
    },
    "jsonBody": {
      "scope": "today"
    },
    "timeoutMs": 8000
  }
}

Empfehlung für Response-Design

Wenn du die API selbst kontrollierst, sind diese Muster besonders gut nutzbar:

  • flache JSONs für kleine Widgets
  • konsistente Namensgebung für gemeinsam genutzte Statuspayloads
  • Arrays aus Objekten für Select-Optionen
  • separate PNG-Endpunkte für Kamerabilder

Siehe auch