Datenmodell: ThingsBoard auf SensorThings abbilden

Zweck

Diese Seite beantwortet für jede SensorThings‑Entität, die der Adapter anlegt, woher jedes ihrer Felder kommt. Die Entitäten selbst und ihre Abfragesyntax beschreibt Schnittstellenbeschreibung SensorThings API; die Tabellen, aus denen die Zuordnungen stammen, Datenbankschema des Adapters.

Alles hier Beschriebene wird in den FROST‑Server eines Mandanten geschrieben — den, dessen Slug in der Ingest‑URL stand.

Überblick

  ThingsBoard                                    FROST (SensorThings)

  Gerät                          ───────────►    Thing
   └─ Relation "Contains"
       └─ Asset (Typ `building`) ───────────►    Location
   └─ Geräteprofil               ───────────►    Sensor
   └─ Telemetrie-Schlüssel       ───────────►    Datastream
       └─ Wert + Zeitstempel     ───────────►    Observation

  Adapter-Datenbank
   └─ observedproperty           ───────────►    ObservedProperty (Kopie je Mandant)
   └─ telemetrykey                    ⌐ Name des Datastreams
   └─ unitofmeasurement(key)          └ eingebettetes unitOfMeasurement

Zwei Quellen also: die Gerätedaten kommen aus ThingsBoard, die Bedeutung der Telemetrie aus den Stammdaten des Adapters.

Thing

Ein Thing entspricht genau einem Gerät in ThingsBoard.

Feld Quelle Anmerkung

name

Gerätename

Muss eindeutig sein und ist der Schlüssel, über den der Adapter das Thing wiederfindet.

description

additional_info.description des Geräts

Fällt auf den Gerätenamen zurück, wenn keine Beschreibung gepflegt ist.

properties

Alle Attribute des Geräts als Objekt

Hier landen auch die Attribute, die der Adapter selbst auswertet: device_definition und die <telemetry_key>_uom‑Einträge.

Locations

Das verknüpfte building‑Asset

Wird im selben POST mitgegeben und nicht nachträglich verknüpft — ein Thing, das für einen Moment ohne Standort existiert, ist ein Zustand, den ein gleichzeitiger Leser sehen könnte.

Location

Der Standort stammt aus dem Asset, das über eine Contains‑Relation mit dem Gerät verknüpft ist und den Typ building trägt. Findet der Adapter kein solches Asset, lehnt er mit 404 ab und schreibt nichts.

Feld Quelle Anmerkung

name

Name des Assets

Der Name identifiziert den Standort; mehrere Geräte im selben Gebäude teilen sich eine Location.

description

additional_info.description des Assets

Fällt auf den Asset‑Namen zurück.

location

Die Attribute lat und lon des Assets

Als GeoJSON Point in der Reihenfolge (lon, lat).

encodingType

fest

application/geo+json.

Sensor

Ein Sensor entspricht einem Geräteprofil in ThingsBoard — nicht einem einzelnen Gerät. Alle Geräte desselben Profils teilen sich einen Sensor.

Feld Quelle Anmerkung

name

Name des Geräteprofils

description

Beschreibung des Geräteprofils

metadata

Geräteattribut device_definition

Üblicherweise ein Link auf ein Datenblatt. Fehlt das Attribut, steht dort no device definition maintained.

encodingType

fest

application/pdf.

ObservedProperty

Die einzige Entität, die nicht aus ThingsBoard stammt. Ihre Wahrheit liegt in der Tabelle observedproperty des Adapters; jeder Mandant hält in seinem FROST eine abgeleitete Kopie mit name, definition und description aus der kanonischen Zeile.

Die Kopie wird ausschließlich über die in tenantobservedproperty hinterlegte frost_id aufgelöst, niemals über den Namen. Die Begründung steht in Geschäftsregeln.

Welche Observed Property zu einer Telemetrie gehört, entscheidet die Tabelle telemetrykey: Ein Schlüssel ohne Zuordnung erzeugt keinen Datastream und damit auch keine Observation — er wird still übergangen und protokolliert.

Datastream

Ein Datastream je Telemetrie‑Schlüssel und Gerät. Er verbindet Thing, Sensor und ObservedProperty.

Feld Quelle Anmerkung

name

Der Telemetrie‑Schlüssel

Der Name ist der Schlüssel. Ein Telemetry Key hat keine eigene Identität in FROST — er existiert nur als dieser Name, weshalb eine Umbenennung die Datastreams direkt umschreiben muss.

description

erzeugt

Datastream for <key> measurements of <Gerätename>.

observationType

fest

OM_Measurement.

unitOfMeasurement

siehe Wie die Maßeinheit bestimmt wird

Ein eingebettetes Objekt aus name, symbol und definition — keine verknüpfte Entität.

Thing, Sensor, ObservedProperty

die oben angelegten Entitäten

Wie die Maßeinheit bestimmt wird

Zwei Stufen, in dieser Reihenfolge:

  1. Gerätespezifisch. Der Adapter liest das Geräteattribut <telemetry_key>_uom aus den properties des Things und schlägt dessen Wert in der Tabelle unitofmeasurementkey nach. Ein Gerät, dessen Telemetrie temperature in Fahrenheit liefert, bekommt damit über ein Attribut temperature_uom eine andere Einheit als alle anderen.

  2. Standard. Findet sich darüber nichts, gilt telemetrykey.default_uom.

Die Maßeinheit wird nicht aus einem Suffix des Telemetrie‑Schlüssels abgeleitet. Sie kommt entweder aus dem Geräteattribut oder aus der Standardzuordnung des Schlüssels — beides gepflegt über die Verwaltungsoberfläche.

Observation

Für jeden Telemetrie‑Schlüssel einer eingehenden Nachricht, der einen Datastream hat, entsteht eine Observation.

Feld Quelle Anmerkung

result

Der Wert des Telemetrie‑Felds

phenomenonTime

ts aus den Metadaten der Nachricht

Millisekunden seit Epoch, umgerechnet nach Europe/Berlin und als ISO‑Zeitstempel geschrieben. FROST zeigt ihn ohnehin in UTC an. Fehlt ts, bleibt das Feld leer.

Datastream

Der Datastream dieses Schlüssels an diesem Thing

Fehlt er und ist der Schlüssel zugeordnet, wird er zuvor angelegt.

FeatureOfInterest

Wird nicht verwendet. Der Adapter legt keine FeaturesOfInterest an; FROST erzeugt sie bei Bedarf selbst aus der Location des Things.

Beispiele

Die folgenden Ausschnitte zeigen die Entitäten eines Luftqualitätssensors, wie der Adapter sie anlegt.

Thing
{
  "name": "KSPB-0507",
  "description": "Luftqualitätssensor an der Schule an der Wakenitz",
  "properties": {
    "areaServed": "Schule an der Wakenitz",
    "device_definition": "https://example.org/datasheets/kspb.pdf",
    "co2_uom": "ppm"
  }
}
Location
{
  "name": "Schule an der Wakenitz",
  "description": "Geo-Position des Geräts KSPB-0507",
  "encodingType": "application/geo+json",
  "location": {
    "type": "Point",
    "coordinates": [10.7383340505368, 53.855998806145]
  }
}
Sensor
{
  "name": "KSPB Umweltsensor",
  "description": "Geräteprofil der KSPB-Messstationen",
  "encodingType": "application/pdf",
  "metadata": "https://example.org/datasheets/kspb.pdf"
}
ObservedProperty
{
  "name": "CO2-Konzentration",
  "definition": "https://en.wikipedia.org/wiki/Carbon_dioxide#Concentration",
  "description": "Kohlenstoffdioxid-Konzentration in ppm"
}
Datastream
{
  "name": "co2",
  "description": "Datastream for co2 measurements of KSPB-0507",
  "observationType": "OM_Measurement",
  "unitOfMeasurement": {
    "name": "Parts per million",
    "symbol": "ppm",
    "definition": "https://unitsofmeasure.org"
  },
  "Thing": { "@iot.id": 1 },
  "Sensor": { "@iot.id": 1 },
  "ObservedProperty": { "@iot.id": 1 }
}
Observation
{
  "result": 487.2485,
  "phenomenonTime": "2024-06-20T06:58:06.594Z",
  "Datastream": { "@iot.id": 1 }
}