Hoppa till huvudinnehåll

Översättar-API

Från och med Yggio version 3.4 är den nya Översättartjänsten nu aktiverad. Den gör det möjligt för utvecklare att lägga till sina egna översättare till Yggio. API-detaljer finns på Swagger. Detta dokument beskriver utförligt hur Översättartjänsten fungerar.

Alla översättare körs i en avgränsad NodeJS v16-miljö. Översättarna är begränsade i det avseendet att de endast kan använda ren JS-funktioner och kan inte komma åt Node-specifika funktioner via import och require(). Vi tillhandahåller även definitioner av lodash (som "_") och Buffer.

Användning av översättare

Vilka översättare som körs för en enhet väljs utifrån enhetens translatorPreferences.

Exempel:

translatorPreferences: [
{
name: 'sensative-strips',
userId: '91698973-01ac-4879-a9f6-927611463f2e',
version: '1.0.0',
upgradePolicy: 'minor',
},
{
name: 'celsius-to-fahrenheit',
userId: '91698973-01ac-4879-a9f6-927611463f3a',
version: '1.2.0',
upgradePolicy: 'all',
},
]

Egenskaperna för en translatorPreference används för att identifiera en översättare. version tillsammans med upgradePolicy används för att välja versionen. upgradePolicy används för att automatiskt välja en nyare version av en översättare utan att användaren behöver uppdatera manuellt till den nya versionen.

upgradePolicy kan vara en av följande fyra:

  • none Den valda versionen kommer alltid att användas
  • patch Om du har valt version 1.0.0 kommer det att resultera i 1.^
  • minor Om du har valt version 1.0.0 kommer det att resultera i 1.0.^
  • all: Den absolut nyaste tillgängliga versionen kommer att användas

Val av translatorPreferences

translatorPreferences är en attribut av en enhet och kan ställas in vid skapandet eller när en enhet uppdateras.

En API-användare kan använda rutten GET /translators för att få de tillgängliga översättarna och använda dem för att fylla i en enhets translatorPreferences. Du kan tillhandahålla deviceModelName som en frågeparameter för att endast få översättare som är lämpliga för den deviceModelName.

Det finns också ett enklare sätt att lägga till translatorPreferences när du skapar en enhet. Om du tillhandahåller en deviceModelName, kommer Yggio automatiskt att fylla i translatorPreferences med en lämplig standardöversättare (som matchar med deviceModelName).

Körning av flera översättare

Det är möjligt att köra flera översättare. Detta kan användas för att utföra kraftfulla operationer. Till exempel, om en översättare ger temperaturen i Celsius kan en andra översättare användas för att översätta temperaturen till Fahrenheit.

Översättarna körs sedan i en sekventiell eller "kedjad" ordning. Inmatningen av en översättare är resultatet av de tidigare översättarna, sammanslagna med den ursprungliga iotnoden.

Detta kan beskrivas med följande formel:

resultat = A(x) + B(x + A(x))

där A och B är översättare, x är ursprungsdata för iotnoden och + betecknar sammanfogning.

Observera att om en översättare misslyckas med att köra avbryts loopen och de efterföljande översättarna kommer inte att köras.

Skapa en Översättare

Översättartjänsten kan köra vilken giltig JavaScript-kod som helst i en avgränsad miljö. En översättare kan endast interagera med sin miljö genom att returnera data från funktionen translate. Översättaren körs varje gång ny data för en iotnod tas emot.

Översättarspecifikation

Översättare är JSON-objekt och har ett par obligatoriska metadatafält som definierar var, när och hur de ska tillämpas.

name är namnet på översättaren. Får endast innehålla gemener, alfanumeriska tecken och bindestreck, måste börja med en bokstav. Regex: /[a-z][a-z0-9-]+/

version måste vara ett korrekt semver-versionsnummer.

apiVersion versionen av Yggio-översättarapiet som denna översättare är utformad att fungera med.

description en användarvänlig beskrivning av översättaren.

match ett objekt som specifierar vilka enheter översättaren är tillämplig för. Kan (för närvarande) endast innehålla fältet deviceModelName med en sträng som värde.

spec definierar vilken typ av data översättaren kommer att returnera. Varje fält inuti detta objekt måste innehålla en sträng med en giltig typ, någon av array, date, boolean, number, object, string. Objektet kan specificera många fält.

code är ett fält som måste innehålla en sträng med giltig JavaScript-kod (långa strängar tillåtna). Översättarens kod måste uppfylla följande krav.

Översättarkod

Översättarkoden är skriven i JavaScript och måste innehålla en funktion som heter translate. Den körs varje gång en ny nyttolast tas emot för den relaterade IoTNode. Översättningsfunktionen (function translate(iotnode) { ... }) kan komma åt vilket fält som helst på iotnoden som ska översättas. Om du behöver datumet då nyttolasten togs emot är det tillgängligt som iotnode.reportedAt.

Översättaren måste returnera ett objekt eller kasta ett fel. Detta objekt kan vara tomt om översättaren inte kunde översätta några värden. Om ett fel uppstår ska översättaren throw ett lämpligt fel.

Objektet (från och med nu kallat translated) som returneras av översättaren kommer att hålla fält med semantiskt värde. Alla fält som inte specificeras här behandlas som ett fel. För närvarande finns det två möjliga fält för översättaren att returnera. Översättaren kan välja att returnera inget, något eller båda dessa fält.

Om översättaren returnerar ett objekt med ett fält translated.result, måste detta fält innehålla uppdaterade värden för iotnoden. Endast fält i översättarens spec får uppdateras. Returnerade fält som är undefined eller null kommer att tas bort.

Tidsserie-data kan returneras via fältet translated.timeseries. Detta fält måste innehålla en array av objekt {timestamp, value} där timestamp måste vara ett giltigt JavaScript Date-objekt och value följer samma regler som det tidigare nämnda fältet result.

När en översättare laddas upp tillhör den uppladdaren för alltid. Detta lagras i översättarens userId-fält.

Exempel

// This is an example translator
function translate(iotnode) { // you can access the full iotnode object for the device

/* translator code here */

return {
result: {
someValue: 13,
anotherValue: 37,
},
timeseries: [{
timestamp: new Date("2021-11-12T14:30:00Z"),
value: {
someValue: 12,
},
}, {
timestamp: new Date("2021-11-12T14:15:00Z"),
value: {
someValue: 11,
},
}],
};
}

const translator = {
name: 'my-translator',
version: '0.2.1',
apiVersion: '1.0',
description: 'A translator for ExampleCorp DemoDevice™ 9000',
match: {
deviceModelName: 'examplecorp-demodevice9000',
},
spec: {
someValue: 'number',
anotherValue: 'number',
},
code: translate.toString(),
}

/* the translator object can now be POSTed to the API */

Översättare för gateway-enheter eller enheter som agerar som gateways

En översättare kan returnera fältet translated.additionalDeviceUpdates, som är en array med uppdateringar för andra enheter. Objekten translated.additionalDeviceUpdates måste ha två nycklar, translated.additionalDeviceUpdates.identifier och translated.additionalDeviceUpdates.result. translated.additionalDeviceUpdates.[i].identifier måste vara ett objekt med nycklar och värden som kan identifiera en specifik enhet. Ett exempel för LoRa skulle vara {devEui: '123456789012345'} och för trådlös M-Bus skulle det vara {wMbusDeviceId: '12312312', manufacturer: 'BMT'}. translated.additionalDeviceUpdates.[i].result innehåller uppdateringarna för enheten. Enheten eller gatewayen kan också skicka uppdateringar för sig själv i samma payload.

Exempel

// This is an example translator
function translate(iotnode) { // you can access the full iotnode object for the device

/* translator code here */

return {
result: {
internalTemperature: 13,
anotherValue: 37,
},
additionalDeviceUpdates: [{
identifier: {
wMbusDeviceId: '12312312',
manufacturer: 'BMT'
},
result: {
someValue: 12,
},
}, {
identifier: {
devEui: '123456789012345'
},
result: {
someValue: 11,
},
}],
};
}

const translator = {
name: 'my-gateway',
version: '0.0.1',
apiVersion: '0.1',
description: 'A translator for ExampleCorp DemoGateway™ 9001',
match: {
deviceModelName: 'examplecorp-demogateway9001',
},
spec: {
someValue: 'number',
anotherValue: 'number',
},
code: translate.toString(),
}

Översättarversioner

Översättare måste ha korrekta semver-kompatibla versionsnummer: Major.Minor.Patch. När en Iotnod uppdateras väljs automatiskt den översättare med högsta versionsnumret för att utföra översättningen.

Om det redan finns en översättare skapad av Sensative kommer den översättaren att väljas innan andra översättare övervägs.

Radera översättare

Översättare kan för närvarande inte raderas av en användare. Detta är för att undvika fall där en översättare används av en annan användare än den ursprungliga skaparen.

En översättare kan endast raderas av en Yggio-administratör under extraordinära omständigheter, som en översättare som innehåller skadlig kod.

Yggio translator-service API-versioner

Yggio 3.6 använder version 1.0 av översättartjänstens API, detta ska betraktas som grunden för alla framtida versioner.