Modelleringsguide för IoT Plug and Play

Kärnan i IoT Plug and Play är en enhetsmodell som beskriver en enhets funktioner för ett IoT Plug and Play-aktiverat program. Den här modellen är strukturerad som en uppsättning gränssnitt som definierar:

  • Egenskaper som representerar skrivskyddat eller skrivbart tillstånd för en enhet eller annan entitet. Ett enhetsserienummer kan till exempel vara en skrivskyddad egenskap och en måltemperatur på en termostat kan vara en skrivbar egenskap.
  • Telemetrifält som definierar de data som genereras av en enhet, oavsett om data är en vanlig ström av sensoravläsningar, ett tillfälligt fel eller ett informationsmeddelande.
  • Kommandon som beskriver en funktion eller åtgärd som kan utföras på en enhet. Ett kommando kan till exempel starta om en gateway eller ta en bild med hjälp av en fjärrkamera.

Mer information om hur IoT Plug and Play använder enhetsmodeller finns i utvecklarhandboken för IoT Plug and Play-enheten och utvecklarguiden för IoT Plug and Play-tjänsten.

Om du vill definiera en modell använder du DTDL (Digital Twins Definition Language). DTDL använder en JSON-variant med namnet JSON-LD. Följande kodfragment visar modellen för en termostatenhet som:

  • Har ett unikt modell-ID: dtmi:com:example:Thermostat;1.
  • Skickar temperaturtelemetri.
  • Har en skrivbar egenskap för att ange måltemperaturen.
  • Har en skrivskyddad egenskap som rapporterar maximal temperatur sedan den senaste omstarten.
  • Svarar på ett kommando som begär högsta, lägsta och genomsnittliga temperaturer under en tidsperiod.
{
  "@context": "dtmi:dtdl:context;2",
  "@id": "dtmi:com:example:Thermostat;1",
  "@type": "Interface",
  "displayName": "Thermostat",
  "description": "Reports current temperature and provides desired temperature control.",
  "contents": [
    {
      "@type": [
        "Telemetry",
        "Temperature"
      ],
      "name": "temperature",
      "displayName": "Temperature",
      "description": "Temperature in degrees Celsius.",
      "schema": "double",
      "unit": "degreeCelsius"
    },
    {
      "@type": [
        "Property",
        "Temperature"
      ],
      "name": "targetTemperature",
      "schema": "double",
      "displayName": "Target Temperature",
      "description": "Allows to remotely specify the desired target temperature.",
      "unit": "degreeCelsius",
      "writable": true
    },
    {
      "@type": [
        "Property",
        "Temperature"
      ],
      "name": "maxTempSinceLastReboot",
      "schema": "double",
      "unit": "degreeCelsius",
      "displayName": "Max temperature since last reboot.",
      "description": "Returns the max temperature since last device reboot."
    },
    {
      "@type": "Command",
      "name": "getMaxMinReport",
      "displayName": "Get Max-Min report.",
      "description": "This command returns the max, min and average temperature from the specified time to the current time.",
      "request": {
        "name": "since",
        "displayName": "Since",
        "description": "Period to return the max-min report.",
        "schema": "dateTime"
      },
      "response": {
        "name": "tempReport",
        "displayName": "Temperature Report",
        "schema": {
          "@type": "Object",
          "fields": [
            {
              "name": "maxTemp",
              "displayName": "Max temperature",
              "schema": "double"
            },
            {
              "name": "minTemp",
              "displayName": "Min temperature",
              "schema": "double"
            },
            {
              "name": "avgTemp",
              "displayName": "Average Temperature",
              "schema": "double"
            },
            {
              "name": "startTime",
              "displayName": "Start Time",
              "schema": "dateTime"
            },
            {
              "name": "endTime",
              "displayName": "End Time",
              "schema": "dateTime"
            }
          ]
        }
      }
    }
  ]
}

Termostatmodellen har ett enda gränssnitt. Senare exempel i den här artikeln visar mer komplexa modeller som använder komponenter och arv.

Den här artikeln beskriver hur du utformar och skapar egna modeller och beskriver ämnen som datatyper, modellstruktur och verktyg.

Mer information finns i specifikationen för Digital Twins Definition Language .

Kommentar

IoT Central stöder för närvarande DTDL v2 med ett IoT Central-tillägg.

Modellstruktur

Egenskaper, telemetri och kommandon grupperas i gränssnitt. I det här avsnittet beskrivs hur du kan använda gränssnitt för att beskriva enkla och komplexa modeller med hjälp av komponenter och arv.

Modell-ID:t

Varje gränssnitt har en unik DTMI-modellidentifierare (Digital Twin Model Identifier). Komplexa modeller använder DTMIs för att identifiera komponenter. Program kan använda de DTMIs som enheter skickar för att hitta modelldefinitioner på en lagringsplats.

DTMIs bör använda följande namngivningskonvention:

  • DTMI-prefixet är dtmi:.
  • DTMI-suffixet är versionsnummer för modellen, ;2till exempel .
  • Brödtexten i DTMI mappar till mappen och filen i modelllagringsplatsen där modellen lagras. Versionsnumret är en del av filnamnet.

Modellen som identifieras av DTMI dtmi:com:Example:Thermostat;2 lagras till exempel i filen dtmi/com/example/thermostat-2.json .

Följande kodfragment visar dispositionen för en gränssnittsdefinition med dess unika DTMI:

{
  "@context": "dtmi:dtdl:context;2",
  "@id": "dtmi:com:example:Thermostat;2",
  "@type": "Interface",
  "displayName": "Thermostat",
  "description": "Reports current temperature and provides desired temperature control.",
  "contents": [
    ...
  ]
}

Inga komponenter

En enkel modell, till exempel termostaten som visades tidigare, använder inte inbäddade eller överlappande komponenter. Telemetri, egenskaper och kommandon definieras i noden i contents gränssnittet.

I följande exempel visas en del av en enkel modell som inte använder komponenter:

{
  "@context": "dtmi:dtdl:context;2",
  "@id": "dtmi:com:example:Thermostat;1",
  "@type": "Interface",
  "displayName": "Thermostat",
  "description": "Reports current temperature and provides desired temperature control.",
  "contents": [
    {
      "@type": [
        "Telemetry",
        "Temperature"
      ],
      "name": "temperature",
      "displayName": "Temperature",
      "description": "Temperature in degrees Celsius.",
      "schema": "double",
      "unit": "degreeCelsius"
    },
    {
      "@type": [
        "Property",
...

Verktyg som Azure IoT Explorer och IoT Central-enhetsmalldesignern etiketterar ett fristående gränssnitt som termostaten som en standardkomponent.

Följande skärmbild visar hur modellen visas i Azure IoT Explorer-verktyget:

Skärmbild som visar standardkomponenten i Azure IoT Explorer-verktyget.

Följande skärmbild visar hur modellen visas som standardkomponent i IoT Central-enhetsmalldesignern. Välj Visa identitet för att se modellens DTMI:

Skärmbild som visar termostatmodellen i designerverktyget för IoT Central-enhetsmallar.

Modell-ID:t lagras i en enhetstvillingeegenskap som följande skärmbild visar:

Skärmbild av verktyget Azure IoT Explorer som visar modell-ID:t i en digital tvillingegenskap.

En DTDL-modell utan komponenter är en användbar förenkling för en enhet eller en IoT Edge-modul med en enda uppsättning telemetri, egenskaper och kommandon. En modell som inte använder komponenter gör det enkelt att migrera en befintlig enhet eller modul till en IoT Plug and Play-enhet eller -modul – du skapar en DTDL-modell som beskriver din faktiska enhet eller modul utan att behöva definiera några komponenter.

Dricks

En modul kan vara en enhetsmoduleller en IoT Edge-modul.

Återanvänd

Det finns två sätt att återanvända gränssnittsdefinitioner.

  • Använd flera komponenter i en modell för att referera till andra gränssnittsdefinitioner.
  • Använd arv för att utöka befintliga gränssnittsdefinitioner.

Flera komponenter

Med komponenter kan du skapa ett modellgränssnitt som en sammansättning av andra gränssnitt.

Termostatgränssnittet definieras till exempel som en modell. Du kan använda det här gränssnittet som en eller flera komponenter när du definierar temperaturstyrenhetsmodellen. I följande exempel anropas thermostat1 dessa komponenter och thermostat2.

För en DTDL-modell med flera komponenter finns det två eller flera komponentavsnitt. Varje avsnitt har @type angetts till Component och refererar uttryckligen till ett schema enligt följande kodfragment:

{
  "@context": "dtmi:dtdl:context;2",
  "@id": "dtmi:com:example:TemperatureController;1",
  "@type": "Interface",
  "displayName": "Temperature Controller",
  "description": "Device with two thermostats and remote reboot.",
  "contents": [
    {
      "@type": [
        "Telemetry",
        "DataSize"
      ],
      "name": "workingSet",
      "displayName": "Working Set",
      "description": "Current working set of the device memory in KiB.",
      "schema": "double",
      "unit": "kibibyte"
    },
    {
      "@type": "Property",
      "name": "serialNumber",
      "displayName": "Serial Number",
      "description": "Serial number of the device.",
      "schema": "string"
    },
    {
      "@type": "Command",
      "name": "reboot",
      "displayName": "Reboot",
      "description": "Reboots the device after waiting the number of seconds specified.",
      "request": {
        "name": "delay",
        "displayName": "Delay",
        "description": "Number of seconds to wait before rebooting the device.",
        "schema": "integer"
      }
    },
    {
      "@type" : "Component",
      "schema": "dtmi:com:example:Thermostat;1",
      "name": "thermostat1",
      "displayName": "Thermostat One",
      "description": "Thermostat One of Two."
    },
    {
      "@type" : "Component",
      "schema": "dtmi:com:example:Thermostat;1",
      "name": "thermostat2",
      "displayName": "Thermostat Two",
      "description": "Thermostat Two of Two."
    },
    {
      "@type": "Component",
      "schema": "dtmi:azure:DeviceManagement:DeviceInformation;1",
      "name": "deviceInformation",
      "displayName": "Device Information interface",
      "description": "Optional interface with basic device hardware information."
    }
  ]
}

Den här modellen har tre komponenter som definierats i innehållsavsnittet – två Thermostat komponenter och en DeviceInformation komponent. Innehållsavsnittet innehåller även egenskaps-, telemetri- och kommandodefinitioner.

Följande skärmbilder visar hur den här modellen visas i IoT Central. Egenskaps-, telemetri- och kommandodefinitionerna i temperaturkontrollanten visas i standardkomponenten på den översta nivån. Egenskaps-, telemetri- och kommandodefinitionerna för varje termostat visas i komponentdefinitionerna:

Skärmbild som visar enhetsmallen för temperaturkontrollanten i IoT Central.

Skärmbild som visar termostatkomponenterna i enhetsmallen för temperaturstyrenhet i IoT Central.

Information om hur du skriver enhetskod som interagerar med komponenter finns i utvecklarhandboken för IoT Plug and Play-enheter.

Information om hur du skriver tjänstkod som interagerar med komponenter på en enhet finns i utvecklarhandboken för IoT Plug and Play-tjänsten.

Arv

Med arv kan du återanvända funktioner i ett basgränssnitt för att utöka funktionerna i ett gränssnitt. Flera enhetsmodeller kan till exempel dela gemensamma funktioner, till exempel ett serienummer:

Diagram som visar ett exempel på arv i en enhetsmodell. Ett termostatgränssnitt och ett Flow Controller-gränssnitt delar båda funktionerna från ett basgränssnitt.

Följande kodfragment visar en DTML-modell som använder nyckelordet extends för att definiera arvsrelationen som visas i föregående diagram:

[
  {
    "@context": "dtmi:dtdl:context;2",
    "@id": "dtmi:com:example:Thermostat;1",
    "@type": "Interface",
    "contents": [
      {
        "@type": "Telemetry",
        "name": "temperature",
        "schema": "double",
        "unit": "degreeCelsius"
      },
      {
        "@type": "Property",
        "name": "targetTemperature",
        "schema": "double",
        "unit": "degreeCelsius",
        "writable": true
      }
    ],
    "extends": [
      "dtmi:com:example:baseDevice;1"
    ]
  },
  {
    "@context": "dtmi:dtdl:context;2",
    "@id": "dtmi:com:example:baseDevice;1",
    "@type": "Interface",
    "contents": [
      {
        "@type": "Property",
        "name": "SerialNumber",
        "schema": "double",
        "writable": false
      }
    ]
  }
]

Följande skärmbild visar den här modellen i IoT Central-enhetsmallsmiljön:

Skärmbild som visar gränssnittsarv i IoT Central.

När du skriver kod på enhets- eller tjänstsidan behöver koden inte göra något speciellt för att hantera ärvda gränssnitt. I exemplet som visas i det här avsnittet rapporterar enhetskoden serienumret som om det vore en del av termostatgränssnittet.

Tips

Du kan kombinera komponenter och arv när du skapar en modell. Följande diagram visar en thermostat modell som ärver från ett baseDevice gränssnitt. Gränssnittet baseDevice har en komponent som i sig ärver från ett annat gränssnitt:

Diagram som visar en modell som använder både komponenter och arv.

Följande kodfragment visar en DTML-modell som använder nyckelorden extends och component för att definiera arvsrelationen och komponentanvändningen som visas i föregående diagram:

[
  {
    "@context": "dtmi:dtdl:context;2",
    "@id": "dtmi:com:example:Thermostat;1",
    "@type": "Interface",
    "contents": [
      {
        "@type": "Telemetry",
        "name": "temperature",
        "schema": "double",
        "unit": "degreeCelsius"
      },
      {
        "@type": "Property",
        "name": "targetTemperature",
        "schema": "double",
        "unit": "degreeCelsius",
        "writable": true
      }
    ],
    "extends": [
      "dtmi:com:example:baseDevice;1"
    ]
  },
  {
    "@context": "dtmi:dtdl:context;2",
    "@id": "dtmi:com:example:baseDevice;1",
    "@type": "Interface",
    "contents": [
      {
        "@type": "Property",
        "name": "SerialNumber",
        "schema": "double",
        "writable": false
      },
      {
        "@type" : "Component",
        "schema": "dtmi:com:example:baseComponent;1",
        "name": "baseComponent"
      }
    ]
  }
]

Datatyper

Använd datatyper för att definiera telemetri, egenskaper och kommandoparametrar. Datatyper kan vara primitiva eller komplexa. Komplexa datatyper använder primitiver eller andra komplexa typer. Det maximala djupet för komplexa typer är fem nivåer.

Primitiva typer

I följande tabell visas den uppsättning primitiva typer som du kan använda:

Primitiv typ beskrivning
boolean Ett booleskt värde
date Ett fullständigt datum enligt definitionen i avsnitt 5.6 i RFC 3339
dateTime En datum-tid enligt definitionen i RFC 3339
double En IEEE-flyttal på 8 byte
duration En varaktighet i ISO 8601-format
float En IEEE 4-bytes flyttal
integer Ett signerat heltal på 4 byte
long Ett signerat heltal på 8 byte
string En UTF8-sträng
time En heltid enligt definitionen i avsnitt 5.6 i RFC 3339

Följande kodfragment visar ett exempel på telemetridefinition som använder double typen i fältet schema :

{
  "@type": "Telemetry",
  "name": "temperature",
  "displayName": "Temperature",
  "schema": "double"
}

Komplexa datatyper

Komplexa datatyper är en av matriser, uppräkning, karta, objekt eller någon av geospatiala typerna.

Matriser

En matris är en indexerbar datatyp där alla element är av samma typ. Elementtypen kan vara en primitiv eller komplex typ.

Följande kodfragment visar ett exempel på telemetridefinition som använder Array typen i fältet schema . Elementen i matrisen är booleska:

{
  "@type": "Telemetry",
  "name": "ledState",
  "schema": {
    "@type": "Array",
    "elementSchema": "boolean"
  }
}

Uppräkningar

En uppräkning beskriver en typ med en uppsättning namngivna etiketter som mappar till värden. Värdena kan vara heltal eller strängar, men etiketterna är alltid strängar.

Följande kodfragment visar ett exempel på telemetridefinition som använder Enum typen i fältet schema . Värdena i uppräkningen är heltal:

{
  "@type": "Telemetry",
  "name": "state",
  "schema": {
    "@type": "Enum",
    "valueSchema": "integer",
    "enumValues": [
      {
        "name": "offline",
        "displayName": "Offline",
        "enumValue": 1
      },
      {
        "name": "online",
        "displayName": "Online",
        "enumValue": 2
      }
    ]
  }
}

Maps

En karta är en typ med nyckel/värde-par där alla värden har samma typ. Nyckeln i en karta måste vara en sträng. Värdena i en karta kan vara valfri typ, inklusive en annan komplex typ.

Följande kodfragment visar en exempelegenskapsdefinition som använder Map typen i fältet schema . Värdena på kartan är strängar:

{
  "@type": "Property",
  "name": "modules",
  "writable": true,
  "schema": {
    "@type": "Map",
    "mapKey": {
      "name": "moduleName",
      "schema": "string"
    },
    "mapValue": {
      "name": "moduleState",
      "schema": "string"
    }
  }
}

Objekt

En objekttyp består av namngivna fält. Fälttyperna i en objektkarta kan vara primitiva eller komplexa typer.

Följande kodfragment visar ett exempel på telemetridefinition som använder Object typen i fältet schema . Fälten i objektet är dateTime, durationoch string typer:

{
  "@type": "Telemetry",
  "name": "monitor",
  "schema": {
    "@type": "Object",
    "fields": [
      {
        "name": "start",
        "schema": "dateTime"
      },
      {
        "name": "interval",
        "schema": "duration"
      },
      {
        "name": "status",
        "schema": "string"
      }
    ]
  }
}

Geospatiala typer

DTDL tillhandahåller en uppsättning geospatiala typer, baserade på GeoJSON, för modellering av geografiska datastrukturer: point, multiPoint, lineString, multiLineString, polygonoch multiPolygon. Dessa typer är fördefinierade kapslade strukturer för matriser, objekt och uppräkningar.

Följande kodfragment visar ett exempel på telemetridefinition som använder point typen i fältet schema :

{
  "@type": "Telemetry",
  "name": "location",
  "schema": "point"
}

Eftersom geospatiala typer är matrisbaserade kan de för närvarande inte användas i egenskapsdefinitioner.

Semantiska typer

Datatypen för en egenskap eller telemetridefinition anger formatet på de data som en enhet utbyter med en tjänst. Den semantiska typen innehåller information om telemetri och egenskaper som ett program kan använda för att avgöra hur ett värde ska bearbetas eller visas. Varje semantisk typ har en eller flera associerade enheter. Celsius och fahrenheit är till exempel enheter för temperatursemantisk typ. IoT Central-instrumentpaneler och analyser kan använda semantisk typinformation för att fastställa hur telemetri- eller egenskapsvärden och visningsenheter ska ritas. Information om hur du kan använda modellparsern för att läsa semantiska typer finns i Förstå modellparsern för digitala tvillingar.

Följande kodfragment visar ett exempel på telemetridefinition som innehåller information av semantisk typ. Den semantiska typen Temperature läggs till i matrisen @typeunit och värdet degreeCelsius är en av de giltiga enheterna för den semantiska typen:

{
  "@type": [
    "Telemetry",
    "Temperature"
  ],
  "name": "temperature",
  "schema": "double",
  "unit": "degreeCelsius"
}

Lokalisering

Program, till exempel IoT Central, använder information i modellen för att dynamiskt skapa ett användargränssnitt kring de data som utbyts med en IoT Plug and Play-enhet. Paneler på en instrumentpanel kan till exempel visa namn och beskrivningar för telemetri, egenskaper och kommandon.

De valfria description fälten och displayName fälten i modellen innehåller strängar som är avsedda att användas i ett användargränssnitt. De här fälten kan innehålla lokaliserade strängar som ett program kan använda för att återge ett lokaliserat användargränssnitt.

Följande kodfragment visar ett exempel på en telemetridefinition för temperatur som innehåller lokaliserade strängar:

{
  "@type": [
    "Telemetry",
    "Temperature"
  ],
  "description": {
    "en": "Temperature in degrees Celsius.",
    "it": "Temperatura in gradi Celsius."
  },
  "displayName": {
    "en": "Temperature",
    "it": "Temperatura"
  },
  "name": "temperature",
  "schema": "double",
  "unit": "degreeCelsius"
}

Det är valfritt att lägga till lokaliserade strängar. I följande exempel finns bara ett enda standardspråk:

{
  "@type": [
    "Telemetry",
    "Temperature"
  ],
  "description": "Temperature in degrees Celsius.",
  "displayName": "Temperature",
  "name": "temperature",
  "schema": "double",
  "unit": "degreeCelsius"
}

Livscykel och verktyg

De fyra livscykelstegen för en enhetsmodell är författare, publicering, användning och version:

Författare

DTML-enhetsmodeller är JSON-dokument som du kan skapa i en textredigerare. I IoT Central kan du dock använda enhetsmallens GUI-miljö för att skapa en DTML-modell. I IoT Central kan du:

  • Skapa gränssnitt som definierar egenskaper, telemetri och kommandon.
  • Använd komponenter för att montera flera gränssnitt tillsammans.
  • Definiera arvsrelationer mellan gränssnitt.
  • Importera och exportera DTML-modellfiler.

Mer information finns i Definiera en ny IoT-enhetstyp i ditt Azure IoT Central-program.

Det finns ett DTDL-redigeringstillägg för VS Code.

Om du vill installera DTDL-tillägget för VS Code går du till DTDL-redigeraren för Visual Studio Code. Du kan också söka efter DTDL i tilläggsvyni VS Code.

När du har installerat tillägget använder du det för att skapa DTDL-modellfiler i VS Code:

  • Tillägget tillhandahåller syntaxverifiering i DTDL-modellfiler, vilket visar fel som visas på följande skärmbild:

    Skärmbild som visar DTDL-modellverifiering i VS Code.

  • Använd intellisense och komplettera automatiskt när du redigerar DTDL-modeller:

    Skärmbild som visar intellisense för DTDL-modeller i VS Code.

  • Skapa ett nytt DTDL-gränssnitt. Kommandot DTDL: Create Interface skapar en JSON-fil med ett nytt gränssnitt. Gränssnittet innehåller exempel på telemetri, egenskap och kommandodefinitioner.

Använd

Program, till exempel IoT Central, använder enhetsmodeller. I IoT Central ingår en modell i enhetsmallen som beskriver enhetens funktioner. IoT Central använder enhetsmallen för att dynamiskt skapa ett användargränssnitt för enheten, inklusive instrumentpaneler och analys.

Kommentar

IoT Central definierar vissa tillägg till DTDL-språket. Mer information finns i IoT Central-tillägget.

En anpassad lösning kan använda modellparsern digital twins för att förstå funktionerna i en enhet som implementerar modellen. Mer information finns i Använda IoT Plug and Play-modeller i en IoT-lösning.

Version

För att säkerställa att enheter och lösningar på serversidan som använder modeller fortsätter att fungera är publicerade modeller oföränderliga.

DTMI innehåller ett versionsnummer som du kan använda för att skapa flera versioner av en modell. Enheter och lösningar på serversidan kan använda den specifika version som de har utformats för att använda.

IoT Central implementerar fler versionsregler för enhetsmodeller. Om du har en enhetsmall och dess modell i IoT Central kan du migrera enheter från tidigare versioner till senare versioner. Migrerade enheter kan dock inte använda nya funktioner utan uppgradering av inbyggd programvara. Mer information finns i Redigera en enhetsmall.

Publicera

Från och med februari 2024 har Azure Certified Device-programmet dragits tillbaka. Därför accepterar Microsoft inte längre inlämningar av DTDL-modeller tillazure IoT-lagringsplatsen för plug and play-modeller .

Om du vill konfigurera en egen modelllagringsplats kan du använda azure IoT plug and play-modelllagringsplatsen . Den här lagringsplatsen innehåller koden för dmr-client CLI-verktyget som kan verifiera, importera och expandera DTDL-modeller. Med det här verktyget kan du även indexera modelllagringsplatser som följer lagringsplatsen för enhetsmodellen.

Begränsningar och krav

I följande lista sammanfattas några viktiga begränsningar och begränsningar för modeller:

  • För närvarande är det maximala djupet för matriser, kartor och objekt fem nivåer.
  • Du kan inte använda matriser i egenskapsdefinitioner.
  • Du kan utöka gränssnitten till ett djup på 10 nivåer.
  • Ett gränssnitt kan utöka högst två andra gränssnitt.
  • En komponent får inte innehålla någon annan komponent.

Nästa steg

Nu när du har lärt dig om enhetsmodellering finns här några fler resurser: