Translator API
Referens för IoT-plattformens Translator Service - objektschemat, kontraktet för
translate-funktionen, och hur översättare väljs ut och körs. Detta är en
referens; för en steg-för-steg-guide med genomarbetade exempel och en lokal test-
rigg, se Utveckla översättare.
API-ändpunkter finns dokumenterade i Swagger.
Körmiljö
Översättare körs i en sandlådad JavaScript-miljö (isolerad V8). Alla
standard-JavaScript-inbyggda funktioner är tillgängliga (Date, Math, JSON, …), plus
lodash som _,
Buffer som Buffer, och console.log. Sandlådan
tillhandahåller inte require/import, timers, eller nätverks-/filsystemsåtkomst. En
översättare interagerar med plattformen enbart genom värdet den
returnerar från translate.
Översättarobjektet
En översättare är ett JSON-objekt med följande fält:
| Fält | Obligatoriskt | Beskrivning |
|---|---|---|
name | ja | Unikt namn. Gemener, siffror och bindestreck, måste börja med en bokstav (/^[a-z][a-z0-9-]+$/). |
version | ja | Semver Major.Minor.Patch. |
apiVersion | ja | Den API-version av översättartjänsten som översättaren riktar sig mot (nuvarande: 1.0). |
description | ja | Användarvänd Markdown-beskrivning (visas i IoT-plattformen). |
match | ja | Vilka enheter den gäller för - ett objekt med deviceModelName (sträng). |
spec | ja | De fält översättaren får skicka ut (se spec). Sätt spec: false för att inaktivera validering. |
parameters | nej | Användarangivna indata (se parameters). |
code | ja | En sträng med JavaScript som definierar en translate-funktion (se code). |
regex tas emot och lagras, men enhetsmatchningen är i dagsläget en exakt jämförelse
av match.deviceModelName mot enhetens modellnamn. Sätt deviceModelName till det
exakta namnet i stället för ett mönster.
spec
spec deklarerar varje fält translate får skicka ut; sandlådan
avvisar varje utskickad nyckel som inte finns i spec. Varje post är en av:
- En ren typsträng - en av
'string','number','boolean','date','object','array'. Används för identifierare, booleaner och opaka värden:spec: { serialNumber: 'string', tamperAlarm: 'boolean' } - En mätvärdesbeskrivning -
{type, unit, quantity}, därunitär en SI- symbol (eller''för dimensionslös) ochquantityär den semantiska gruppen:spec: { temperature: {type: 'number', unit: '°C', quantity: 'temperature'} }
Fältnamn, enheter och kvantiteter definieras av den kanoniska fältkatalogen (IoT-plattformens datamodell) - se Datamodell för de vanliga fälten och namnreglerna.
parameters
parameters deklarerar värden som användaren anger när översättaren väljs.
De valideras mot schemat och skickas som andra argument till
translate.
parameters: {
// primitive
someNumber: 'number',
someBoolean: 'boolean',
someString: 'string',
// constrained
constrainedNumber: {type: 'number', min: 10, max: 30},
choice: {type: 'enum', values: ['apple', 'pear']},
// optional / default (both make the parameter optional to the user)
offset: {type: 'number', optional: true},
timeZone: {type: 'string', default: 'Europe/Stockholm'},
}
code
code är en sträng med JavaScript som definierar en funktion med namnet translate (plus
eventuella hjälpfunktioner den anropar - hjälpfunktioner måste finnas i samma code-sträng,
eftersom hela strängen är det som körs i sandlådan).
Datamodell (fältkatalog)
IoT-plattformen platttar ut varje enhet till en nod med hjälp av ett delat vokabulär av kanoniska
fältnamn - fältkatalogen. Ett fälts betydelse ligger helt i dess
namn, enhet och kvantitet, så översättare för olika tillverkare måste skicka ut
samma fält för samma mätning. Mappa tillverkarens råa namn till kanoniska
fält i både spec och det returnerade result.
Regler:
- lowerCamelCase, platta NGSI-LD-namn - ingen
snake_case, ingen tillverkarjargong (TempC_SHT,BatV) i utdatan. - SI-enheter (
°C,%,Pa,V,A,W,kWh,m,m/s); dimensionslösa värden använder enheten''med en camelCase-quantity. Konvertera i översättaren (t.ex.hPa → Paär× 100,mV → Vär/ 1000). - Temperatur bär sitt medium i namnet:
temperature= luft/omgivning;waterTemperature,soilTemperature,surfaceTemperature;externalTemperature/2/3= sond med ospecificerat medium;internalTemperature/cpuTemperature= enhetens elektronik. - Indexerade kanaler: det rena namnet är det primära, extra kanaler börjar på
2(temperature,temperature2; en…1-form är ett äldre alias).
Vanliga fält
| Fält | Enhet | Kvantitet |
|---|---|---|
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 |
Booleska fält / statusfält använder en ren typ: batteryLow, presence, digital,
relayState ('boolean'); contact, occupied (litet enum, 'number'). Larm-
fält är subjekt-först-booleaner med ett *Alarm-suffix
(temperatureLowAlarm, tamperAlarm), quantity: 'alarm'.
Innan du hittar på ett namn, kontrollera de vanliga fälten ovan (eller GET /api/translators)
efter ett befintligt.
Harmoniseringsexempel
En översättares uppgift är att döpa om tillverkarens råa utdata till kanoniska fält.
När du omsluter en tillverkares referensdekoder, behåll dekodern oförändrad och
utför harmoniseringen som det sista steget - mappa dess råa utdata till kanoniska
fält i det returnerade result, och skala enheter korrekt (t.ex. hPa → Pa,
mV → V, cm → m). Ändra inte tillverkardekoderns interna logik.
Dragino LHT65
| Rått | Kanoniskt |
|---|---|
TempC_SHT (inbyggd) | internalTemperature |
TempC_DS (extern sond) | temperature |
Hum_SHT | relativeHumidity |
BatV | batteryVoltage |
Milesight AM319 (observera enhetsfixet)
| Rått | Kanoniskt |
|---|---|
temperature | temperature |
humidity | relativeHumidity |
battery | batteryLevel |
co2 | co2 |
pressure (hPa) | pressure (Pa, × 100) |
Eftersom båda skickar ut relativeHumidity (%, relativeHumidity), betyder samma värde
samma sak oavsett tillverkare - och samma nedströms-översättare
och vyer fungerar för alla enheter.
translate-funktionen
translate körs varje gång ny data anländer för enhetens
IoTNode. Signatur:
function translate (iotnode, parameters) { /* ... */ }
iotnode- noden som översätts. En översättare kan läsa vilket fält som helst på den. Råa upplänkspayloads för en hårdvarudekoder finns underiotnode.encodedData({hexEncoded, port}); tidpunkten för mottagen payload äriotnode.reportedAt. FöredrareportedAtframförDate.now()för observations-/händelsetider -Date.now()/new Date()fungerar, men klockan visar bearbetningstiden och är icke-deterministisk (det bryter reproducerbarheten om en översättning körs igen). När översättare kedjas, bäriotnodeockså de fält som producerats av tidigare översättare.parameters- det valideradeparameters-objektet (eller{}).
translate måste returnera ett objekt eller throw ett Error. Objektet kan vara
tomt ({}) när ingenting kunde översättas. Kända returfält - returnera
valfritt antal, alla eller inga:
| Returfält | Betydelse |
|---|---|
result | Uppdaterade värden för iotnoden. Endast nycklar deklarerade i spec är tillåtna; undefined- och NaN-värden tas bort (null gör det inte - se nedan). |
timeseries | En array av {timestamp, value} - timestamp ett JS-Date-objekt, value följer samma regler som result. |
additionalDeviceUpdates | Uppdateringar för andra enheter (gateways) - se nedan. |
Eftersom plattformen tar bort undefined och NaN från result, kan en översättare
skicka ut ett fält villkorligt och returnera det vanliga objektet utan att själv
rensa bort det.
null är undantaget, och inget ofarligt sådant. Ett null behålls i stället för att
tas bort, och faller sedan på den deklarerade typen i spec, vilket avvisar hela
översättningen i stället för bara det fältet. En leverantörsdekoder som returnerar
null för en utebliven avläsning måste därför städas innan resultatet returneras -
utelämna nyckeln, eller sätt den till undefined.
Fel och loggning
När en översättare kastar ett fel registrerar IoT-plattformen felet i enhetens Loggar
och behåller det i 6 timmar - filtrera Type = Debug, Category =
System för att hitta det. En lyckad översättning loggar ingenting, så en tom logg
innebär att översättaren antingen kördes felfritt eller aldrig utlöstes (kontrollera enhetens
Last reported-tid för att avgöra vilket).
Obs: bara den första översättaren i en kedja rapporterar ett kastat fel på det här sättet. Om en senare översättare kastar ett fel behåller plattformen resultatet som producerats hittills och skriver ingen loggpost, så en tom logg bevisar inte i sig att en kedjad översättare lyckades.
Minimalt exempel
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(),
};
Tidsserieexempel
return {
timeseries: [
{timestamp: new Date('2021-11-12T14:30:00Z'), value: {temperature: 12}},
{timestamp: new Date('2021-11-12T14:15:00Z'), value: {temperature: 11}},
],
};
Välja översättare
Vilka översättare som körs för en enhet bestäms av enhetens
translatorPreferences (kan sättas vid enhetens skapande eller uppdatering):
translatorPreferences: [
{name: 'sensative-strips', userId: '…', version: '1.0.0', upgradePolicy: 'minor'},
{name: 'celsius-to-fahrenheit', userId: '…', version: '1.2.0', upgradePolicy: 'all'},
]
version + upgradePolicy avgör vilken version som körs:
upgradePolicy | Beteende (vald 1.0.0) |
|---|---|
none | alltid den valda versionen |
patch | senaste 1.0.x |
minor | senaste 1.x |
all | senaste tillgängliga |
Använd GET /api/translators (valfritt ?deviceModelName=…) för att lista översättare
som passar en enhet och fylla translatorPreferences. När en enhet
skapas med ett deviceModelName, fyller IoT-plattformen automatiskt i en lämplig standard-
översättare.
Om en översättare skapad av Sensative matchar, föredras den framför andra.
Kedjning (flera översättare)
Översättare körs sekventiellt; varje mottar de föregående resultaten sammanslagna med den ursprungliga iotnoden:
result = A(x) + B(x + A(x))
där A, B är översättare, x är den ursprungliga iotnoden, och + är en sammanslagning. En
översättare läser alltså fälten som producerats av tidigare översättare. Om en
översättare kastar ett fel stannar kedjan och senare översättare körs inte.
Gateways
En översättare på en gateway (eller gatewayliknande enhet) kan uppdatera andra enheter via
additionalDeviceUpdates - en array av {identifier, result}:
identifier- ett objekt som identifierar målenheten, t.ex.{devEui: '123456789012345'}eller{wMbusDeviceId: '12312312', manufacturer: 'BMT'}.result- uppdateringarna för den enheten (samma regler somresult).
Enheten kan också uppdatera sig själv i samma svar via result.
return {
result: {internalTemperature: 13},
additionalDeviceUpdates: [
{identifier: {devEui: '123456789012345'}, result: {temperature: 11}},
],
};
Versionshantering
Versioner är semver Major.Minor.Patch. Vid uppdatering används den version som
väljs av varje enhets upgradePolicy (med översättare skapade av Sensative föredragna).
Du måste höja huvudversionen (major) varje gång datamodellen ändras - ett fält
läggs till, byter namn eller tas bort, eller dess värdesemantik (enhet, skalning, betydelse)
ändras. Ändringar som bara rör metadata eller buggfixar med samma utdata behöver inte en huvudversionshöjning.
Ägarskap och radering
En uppladdad översättare ägs permanent av den som laddade upp den (userId). Användare
kan inte radera översättare - för att inte förstöra för andra användare som är beroende av dem. En
plattformsadministratör kan radera en endast under extraordinära omständigheter (t.ex.
skadlig kod).
API-versioner
apiVersion 1.0 är den nuvarande API:et för översättartjänsten och grunden för
framtida versioner.
Se Utveckla översättare för datamodellens
regler och genomarbetade mallar (hårdvara, calculate, set-alarm, analys), samt
verktygen för att testa och skicka en översättare utan någon av IoT-plattformens infrastruktur:
translator-harness.js- kör dintranslate- funktion lokalt mot testpayloads (återskapar sandlådan med Nodesvm; kräver baranpm install lodash).translator-build.js- paketera din funktion + metadata till dentranslator.jsonsom skaPOST-as till API:et.