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:
| Feld | Erforderlich | Beschreibung |
|---|---|---|
name | ja | Eindeutiger Name. Alphanumerische Kleinbuchstaben und Bindestriche, muss mit einem Buchstaben beginnen (/^[a-z][a-z0-9-]+$/). |
version | ja | Semver Major.Minor.Patch. |
apiVersion | ja | Die API-Version des Translator-Service, auf die der Übersetzer ausgelegt ist (aktuell: 1.0). |
description | ja | Benutzerseitige Markdown-Beschreibung (wird in der IoT-Plattform angezeigt). |
match | ja | Auf welche Geräte er zutrifft - ein Objekt mit deviceModelName (Zeichenkette). |
spec | ja | Die Felder, die der Übersetzer ausgeben darf (siehe spec). Setzen Sie spec: false, um die Validierung zu deaktivieren. |
parameters | nein | Vom Nutzer bereitgestellte Eingaben (siehe parameters). |
code | ja | Eine 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}, wobeiunitein SI-Symbol ist (oder''für dimensionslos) undquantitydie 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 → Paist× 100,mV → Vist/ 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…1ist ein Legacy-Alias).
Häufige Felder
| Feld | Einheit | Größe |
|---|---|---|
temperature | °C | temperature |
internalTemperature | °C | temperature |
externalTemperature | °C | temperature |
waterTemperature | °C | temperature |
soilTemperature | °C | temperature |
relativeHumidity | % | relativeHumidity |
pressure | Pa | pressure |
co2 | ppm | co2 |
tvoc | ppb | tvoc |
pm2_5 | ug/m^3 | pm2_5 |
pm10 | ug/m^3 | pm10 |
illuminance | lx | illuminance |
windSpeed | m/s | velocity |
precipitation | mm | precipitation |
distance | m | length |
waterLevel | m | length |
soilMoisture | % | soilMoisture |
batteryLevel | % | fill |
batteryVoltage | V | voltage |
current1 | A | current |
voltageL1N | V | voltage |
activeEnergyImport | kWh | energy |
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
| Roh | Kanonisch |
|---|---|
TempC_SHT (eingebaut) | internalTemperature |
TempC_DS (externe Sonde) | temperature |
Hum_SHT | relativeHumidity |
BatV | batteryVoltage |
Milesight AM319 (beachten Sie die Einheitenkorrektur)
| Roh | Kanonisch |
|---|---|
temperature | temperature |
humidity | relativeHumidity |
battery | batteryLevel |
co2 | co2 |
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 unteriotnode.encodedData({hexEncoded, port}); der Empfangszeitpunkt der Payload istiotnode.reportedAt. Bevorzugen SiereportedAtgegenüberDate.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ägtiotnodeauch die von den vorherigen Übersetzern erzeugten Felder.parameters- das validierteparameters-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ückgabefeld | Bedeutung |
|---|---|
result | Aktualisierte Werte für den Iotnode. Nur in spec deklarierte Schlüssel sind erlaubt; undefined-/null-Werte werden entfernt. |
timeseries | Array von {timestamp, value} - timestamp ein JS-Date, value folgt denselben Regeln wie result. |
additionalDeviceUpdates | Updates 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:
upgradePolicy | Verhalten (ausgewählt 1.0.0) |
|---|---|
none | immer die ausgewählte Version |
patch | die neueste 1.0.x |
minor | die neueste 1.x |
all | die 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 wieresult).
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 Ihretranslate- Funktion lokal gegen Testpayloads aus (rekonstruiert die Sandbox mit Node'svm; benötigt nurnpm install lodash).translator-build.js- verpackt Ihre Funktion + Metadaten in dietranslator.jsonzumPOSTan die API.