Zum Hauptinhalt springen

Translator API

Referenz für den Translator Service der IoT-Plattform - das Objektschema, die translate-Funktionsvereinbarung und wie Übersetzer ausgewählt und ausgeführt werden. Dies ist eine Referenz; für eine Schritt-für-Schritt-Anleitung mit ausgearbeiteten Beispielen und einem lokalen Test-Harness siehe Übersetzer entwickeln.

Die API-Endpunkte sind in Swagger dokumentiert.

Laufzeitumgebung​

Übersetzer laufen in einer sandboxed JavaScript-Umgebung (isoliertes V8). Alle Standard-JavaScript-Built-ins sind verfügbar (Date, Math, JSON, …), außerdem lodash als _, Buffer als Buffer, und console.log. Die Sandbox stellt kein require/import, keine Timer und keinen Netzwerk-/Dateisystemzugriff bereit. Ein Übersetzer interagiert mit der Plattform nur über den Wert, den er aus translate zurückgibt.

Das Übersetzer-Objekt​

Ein Übersetzer ist ein JSON-Objekt mit diesen Feldern:

FeldErforderlichBeschreibung
namejaEindeutiger Name. Alphanumerische Kleinbuchstaben und Bindestriche, muss mit einem Buchstaben beginnen (/^[a-z][a-z0-9-]+$/).
versionjaSemver Major.Minor.Patch.
apiVersionjaDie API-Version des Translator-Service, auf die der Übersetzer ausgelegt ist (aktuell: 1.0).
descriptionjaBenutzerseitige Markdown-Beschreibung (wird in der IoT-Plattform angezeigt).
matchjaAuf welche Geräte er zutrifft - ein Objekt mit deviceModelName (Zeichenkette).
specjaDie Felder, die der Übersetzer ausgeben darf (siehe spec). Setzen Sie spec: false, um die Validierung zu deaktivieren.
parametersneinVom Nutzer bereitgestellte Eingaben (siehe parameters).
codejaEine Zeichenkette mit JavaScript, die eine translate-Funktion definiert (siehe code).

match kann statt eines exakten Namens einen regulären Ausdruck verwenden, indem regex: true gesetzt und deviceModelName zu einem Muster der Form <name>.* gemacht wird (Alternation ist nicht erlaubt).

spec​

spec deklariert jedes Feld, das translate ausgeben darf; die Sandbox lehnt jeden ausgegebenen Schlüssel ab, der nicht in spec vorhanden ist. Jeder Eintrag ist entweder:

  • Eine reine Typ-Zeichenkette - eine von 'string', 'number', 'boolean', 'date', 'object', 'array'. Für Kennungen, Booleans und intransparente Werte:
    spec: { serialNumber: 'string', tamperAlarm: 'boolean' }
  • Ein Messgrößen-Deskriptor - {type, unit, quantity}, wobei unit ein SI-Symbol ist (oder '' für dimensionslos) und quantity die semantische Gruppe:
    spec: { temperature: {type: 'number', unit: '°C', quantity: 'temperature'} }

Feldnamen, Einheiten und Größen sind durch den kanonischen Feldkatalog (das Datenmodell der IoT-Plattform) definiert - siehe Datenmodell für die gängigen Felder und die Namensregeln.

parameters​

parameters deklariert Werte, die der Nutzer bei der Auswahl des Übersetzers bereitstellt. Sie werden gegen das Schema validiert und als zweites Argument an translate übergeben.

parameters: {
// primitiv
someNumber: 'number',
someBoolean: 'boolean',
someString: 'string',

// eingeschränkt
constrainedNumber: {type: 'number', min: 10, max: 30},
choice: {type: 'enum', values: ['apple', 'pear']},

// optional / Standardwert (beides macht den Parameter für den Nutzer optional)
offset: {type: 'number', optional: true},
timeZone: {type: 'string', default: 'Europe/Stockholm'},
}

code​

code ist eine Zeichenkette mit JavaScript, die eine Funktion namens translate definiert (plus alle Hilfsfunktionen, die sie aufruft - Hilfsfunktionen müssen in derselben code-Zeichenkette stehen, da diese gesamte Zeichenkette in der Sandbox ausgeführt wird).

Datenmodell (Feldkatalog)​

Die IoT-Plattform legt jedes Gerät auf einem Node mithilfe eines gemeinsamen Vokabulars kanonischer Feldnamen ab - dem Feldkatalog. Die Bedeutung eines Feldes liegt vollständig in seinem Namen, seiner Einheit und seiner Größe, sodass Übersetzer für verschiedene Hersteller das gleiche Feld für dieselbe Messung ausgeben müssen. Bilden Sie die rohen Herstellernamen sowohl in spec als auch im zurückgegebenen result auf kanonische Felder ab.

Regeln:

  • lowerCamelCase, flache NGSI-LD-Namen - kein snake_case, kein Herstellerjargon (TempC_SHT, BatV) in der Ausgabe.
  • SI-Einheiten (°C, %, Pa, V, A, W, kWh, m, m/s); dimensionslose Werte verwenden die Einheit '' mit einer camelCase-quantity. Konvertieren Sie im Übersetzer (z. B. hPa → Pa ist × 100, mV → V ist / 1000).
  • Die Temperatur trägt ihr Medium im Namen: temperature = Luft/Umgebung; waterTemperature, soilTemperature, surfaceTemperature; externalTemperature/2/3 = Sonde mit nicht näher bestimmtem Medium; internalTemperature/cpuTemperature = Geräteelektronik.
  • Indizierte Kanäle: Der bloße Name ist der primäre, weitere beginnen bei 2 (temperature, temperature2; eine Form …1 ist ein Legacy-Alias).

Häufige Felder​

FeldEinheitGröße
temperature°Ctemperature
internalTemperature°Ctemperature
externalTemperature°Ctemperature
waterTemperature°Ctemperature
soilTemperature°Ctemperature
relativeHumidity%relativeHumidity
pressurePapressure
co2ppmco2
tvocppbtvoc
pm2_5ug/m^3pm2_5
pm10ug/m^3pm10
illuminancelxilluminance
windSpeedm/svelocity
precipitationmmprecipitation
distancemlength
waterLevelmlength
soilMoisture%soilMoisture
batteryLevel%fill
batteryVoltageVvoltage
current1Acurrent
voltageL1NVvoltage
activeEnergyImportkWhenergy
motion''count
lnglat- (Typ geoJsonPoint)GNSS-Position

Boolesche / Status-Felder verwenden einen reinen Typ: batteryLow, presence, digital, relayState ('boolean'); contact, occupied (kleines Enum 'number'). Alarmfelder sind subjekt-first Booleans mit einem *Alarm-Suffix (temperatureLowAlarm, tamperAlarm), quantity: 'alarm'.

Bevor Sie einen Namen erfinden, prüfen Sie die häufigen Felder oben (oder GET /api/translators) auf einen bereits existierenden.

Harmonisierungsbeispiele​

Die Aufgabe eines Übersetzers ist es, die rohe Ausgabe des Herstellers in kanonische Felder umzubenennen.

Wenn Sie einen Referenz-Decoder eines Herstellers einbetten, behalten Sie den Decoder unverändert bei und führen Sie die Harmonisierung als letzten Schritt durch - bilden Sie seine Rohausgabe auf kanonische Felder im zurückgegebenen result ab und skalieren Sie die Einheiten korrekt (z. B. hPa → Pa, mV → V, cm → m). Ändern Sie nicht die interne Logik des Herstellerdecoders.

Dragino LHT65

RohKanonisch
TempC_SHT (eingebaut)internalTemperature
TempC_DS (externe Sonde)temperature
Hum_SHTrelativeHumidity
BatVbatteryVoltage

Milesight AM319 (beachten Sie die Einheitenkorrektur)

RohKanonisch
temperaturetemperature
humidityrelativeHumidity
batterybatteryLevel
co2co2
pressure (hPa)pressure (Pa, × 100)

Da beide relativeHumidity (%, relativeHumidity) ausgeben, bedeutet derselbe Wert unabhängig vom Hersteller dasselbe - und dieselben nachgeschalteten Übersetzer und Ansichten funktionieren über alle Geräte hinweg.

Die translate-Funktion​

translate läuft jedes Mal, wenn neue Daten für den IoTNode des Geräts eintreffen. Signatur:

function translate (iotnode, parameters) { /* ... */ }
  • iotnode - der Node, der übersetzt wird. Ein Übersetzer kann jedes Feld darauf lesen. Rohe Uplink-Payloads für einen Hardware-Decoder liegen unter iotnode.encodedData ({hexEncoded, port}); der Empfangszeitpunkt der Payload ist iotnode.reportedAt. Bevorzugen Sie reportedAt gegenüber Date.now() für Beobachtungs-/Ereigniszeiten - Date.now()/new Date() funktionieren, aber die Systemzeit ist die Verarbeitungszeit und nicht deterministisch (das bricht die Reproduzierbarkeit, wenn eine Übersetzung wiederholt wird). Wenn Übersetzer verkettet sind, trägt iotnode auch die von den vorherigen Übersetzern erzeugten Felder.
  • parameters - das validierte parameters-Objekt (oder {}).

translate muss ein Objekt zurückgeben oder einen Error werfen. Das Objekt kann leer sein ({}), wenn nichts übersetzt werden konnte. Erkannte Rückgabefelder - geben Sie beliebige, alle oder keine zurück:

RückgabefeldBedeutung
resultAktualisierte Werte für den Iotnode. Nur in spec deklarierte Schlüssel sind erlaubt; undefined-/null-Werte werden entfernt.
timeseriesArray von {timestamp, value} - timestamp ein JS-Date, value folgt denselben Regeln wie result.
additionalDeviceUpdatesUpdates für andere Geräte (Gateways) - siehe unten.

Da die Plattform undefined und NaN aus result entfernt, kann ein Übersetzer ein Feld bedingt ausgeben und das einfache Objekt zurückgeben, ohne es selbst zu bereinigen.

Fehler und Protokollierung​

Wenn ein Übersetzer eine Ausnahme wirft, zeichnet die IoT-Plattform den Fehler in den Logs des Geräts auf und bewahrt ihn 6 Stunden lang auf - filtern Sie nach Type = Debug, Category = System, um ihn zu finden. Eine erfolgreiche Übersetzung protokolliert nichts, sodass ein leeres Log bedeutet, dass der Übersetzer entweder einwandfrei lief oder nie ausgelöst wurde (prüfen Sie die Zeit unter Last reported des Geräts, um festzustellen, welches der Fälle zutrifft).

Minimales Beispiel​

function translate (iotnode) {
return {result: {temperature: 21.4, batteryVoltage: 3.01}};
}

const translator = {
name: 'examplecorp-demodevice9000',
version: '1.0.0',
apiVersion: '1.0',
description: 'A translator for ExampleCorp DemoDevice 9000.',
match: {deviceModelName: 'examplecorp-demodevice9000'},
spec: {
temperature: {type: 'number', unit: '°C', quantity: 'temperature'},
batteryVoltage: {type: 'number', unit: 'V', quantity: 'voltage'},
},
code: translate.toString(),
};

Zeitreihen-Beispiel​

return {
timeseries: [
{timestamp: new Date('2021-11-12T14:30:00Z'), value: {temperature: 12}},
{timestamp: new Date('2021-11-12T14:15:00Z'), value: {temperature: 11}},
],
};

Übersetzer auswählen​

Welche Übersetzer für ein Gerät ausgeführt werden, wird durch die translatorPreferences des Geräts festgelegt (einstellbar bei der Erstellung oder Aktualisierung des Geräts):

translatorPreferences: [
{name: 'sensative-strips', userId: '…', version: '1.0.0', upgradePolicy: 'minor'},
{name: 'celsius-to-fahrenheit', userId: '…', version: '1.2.0', upgradePolicy: 'all'},
]

version + upgradePolicy bestimmen, welche Version ausgeführt wird:

upgradePolicyVerhalten (ausgewählt 1.0.0)
noneimmer die ausgewählte Version
patchdie neueste 1.0.x
minordie neueste 1.x
alldie neueste verfügbare

Verwenden Sie GET /api/translators (optional ?deviceModelName=…), um für ein Gerät geeignete Übersetzer aufzulisten und die translatorPreferences zu befüllen. Wenn ein Gerät mit einem deviceModelName erstellt wird, befüllt die IoT-Plattform automatisch einen geeigneten Standardübersetzer.

Wenn ein von Sensative erstellter Übersetzer passt, wird er anderen vorgezogen.

Verkettung (mehrere Übersetzer)​

Übersetzer laufen sequenziell; jeder erhält die vorherigen Ergebnisse zusammengeführt mit dem ursprünglichen Iotnode:

result = A(x) + B(x + A(x))

wobei A, B Übersetzer sind, x der ursprüngliche Iotnode ist und + eine Zusammenführung ist. Ein Übersetzer liest also die von früheren Übersetzern erzeugten Felder. Wenn ein Übersetzer eine Ausnahme wirft, stoppt die Kette und spätere Übersetzer laufen nicht mehr.

Gateways​

Ein Übersetzer auf einem Gateway (oder einem gatewayartigen Gerät) kann andere Geräte über additionalDeviceUpdates aktualisieren - ein Array von {identifier, result}:

  • identifier - ein Objekt, das das Zielgerät identifiziert, z. B. {devEui: '123456789012345'} oder {wMbusDeviceId: '12312312', manufacturer: 'BMT'}.
  • result - die Aktualisierungen für dieses Gerät (dieselben Regeln wie result).

Das Gerät kann sich in derselben Rückgabe auch selbst über result aktualisieren.

return {
result: {internalTemperature: 13},
additionalDeviceUpdates: [
{identifier: {devEui: '123456789012345'}, result: {temperature: 11}},
],
};

Versionierung​

Versionen sind semver Major.Minor.Patch. Bei einer Aktualisierung wird die durch die upgradePolicy jedes Geräts aufgelöste Version verwendet (wobei von Sensative erstellte Übersetzer bevorzugt werden). Sie müssen die Major-Version erhöhen, wann immer sich das Datenmodell ändert - ein Feld hinzugefügt, umbenannt oder entfernt wird, oder sich seine Wertsemantik (Einheit, Skalierung, Bedeutung) ändert. Rein Metadaten-Änderungen oder Bugfixes mit gleicher Ausgabe erfordern keine Major-Erhöhung.

Eigentum und Löschung​

Ein hochgeladener Übersetzer gehört permanent seinem Uploader (userId). Nutzer können Übersetzer nicht löschen - um andere Nutzer, die von ihnen abhängen, nicht zu beeinträchtigen. Ein Plattform-Administrator darf einen Übersetzer nur unter außergewöhnlichen Umständen löschen (z. B. bösartigen Code).

API-Versionen​

apiVersion 1.0 ist die aktuelle Translator-Service-API und die Grundlage für zukünftige Versionen.


Siehe Übersetzer entwickeln für die Regeln des Datenmodells und ausgearbeitete Vorlagen (Hardware, calculate, set-alarm, Analytics) sowie die Werkzeuge, um einen Übersetzer ohne jegliche Infrastruktur der IoT-Plattform zu testen und auszuliefern:

  • translator-harness.js - führt Ihre translate- Funktion lokal gegen Testpayloads aus (rekonstruiert die Sandbox mit Node's vm; benötigt nur npm install lodash).
  • translator-build.js - verpackt Ihre Funktion + Metadaten in die translator.json zum POST an die API.