分享方式:


IoT 隨插即用模型化指南

IoT 隨插即用的核心是裝置模型,該模型說明裝置針對 IoT 隨插即用的應用程式功能。 此模型是結構化的一組介面,可定義:

  • 代表裝置或其他實體的唯讀或可寫入狀態的屬性。 例如,裝置序號可能是唯讀屬性,而控溫器上的目標溫度可能是可寫入屬性。
  • 用於定義屬於裝置所發出資料的遙測欄位,無論這項資料是感應器讀數的一般串流、偶爾發生的錯誤,還是資訊訊息。
  • 說明可在裝置上完成之函式或作業的命令。 例如,命令可以重新啟動閘道或使用遠端相機拍照。

若要深入了解 IoT 隨插即用如何使用裝置模型,請參閱 IoT 隨插即用裝置開發人員指南IoT 隨插即用服務開發人員指南

若要定義模型,您可以使用數位分身定義語言 (DTDL)。 DTDL 使用稱為 JSON-LD 的 JSON變體。 下列程式碼片段顯示控溫器裝置的裝置模型:

  • 具有唯一的模型識別碼:dtmi:com:example:Thermostat;1
  • 傳送溫度遙測資料。
  • 具有可寫入的屬性,可設定目標溫度。
  • 具有唯讀屬性,可報告自上次重新開機後的最高溫度。
  • 回應一段時間內要求最大值、最小值和平均溫度的命令。
{
  "@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"
            }
          ]
        }
      }
    }
  ]
}

控溫器模型具有單一介面。 本文稍後的範例示範使用元件和繼承的更複雜模型。

本文說明如何設計和撰寫您自己的模型,並說明資料類型、模型結構和工具等主題。

若要深入了解,請參閱數位對應項定義語言規格。

注意

IoT Central 目前支援具有 IoT Central 延伸模組DTDL v2

模型結構

屬性、遙測和命令會分組為介面。 本節描述如何使用介面,以及使用元件和繼承來描述簡單和複雜的模型。

模型識別碼

每個介面都有唯一的數位對應項模型識別碼 (DTMI)。 複雜的模型會使用 DTMI 來識別元件。 應用程式可以使用裝置傳送的 DTMI,在存放庫中尋找模型定義。

DTMI 應使用下列命名慣例:

  • DTMI 首碼為 dtmi:
  • DTMI 尾碼是模型的版本號碼,例如 ;2
  • DTMI 的主體會對應至儲存模型的模型存放庫中資料夾和檔案。 版本號碼屬於檔案名稱的一部分。

例如,DTMI dtmi:com:Example:Thermostat;2 所識別的模型會儲存在 dtmi/com/example/thermostat-2.json 檔案中。

下列程式碼片段顯示介面定義的大綱及其唯一 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": [
    ...
  ]
}

沒有元件

簡單的模型,例如先前顯示的控溫器,不會使用內嵌或串聯的元件。 遙測、屬性和命令會在介面的 contents 節點進行定義。

下列範例顯示未使用元件簡單模型的一部分:

{
  "@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",
...

Azure IoT 總管和 IoT Central 裝置範本設計工具等工具會標示獨立介面,例如控溫器作為預設元件

下列螢幕擷取畫面顯示模型在 Azure IoT 總管工具中的顯示方式:

顯示 Azure IoT 總管工具中預設元件的螢幕擷取畫面。

下列螢幕擷取畫面顯示模型如何在 IoT Central 裝置範本設計工具中顯示為預設元件。 選取 [檢視身分識別] 以查看模型的 DTMI:

顯示 IoT Central 裝置範本設計工具中控溫器模型的螢幕擷取畫面。

模型識別碼會儲存在裝置對應項屬性中,如下列螢幕擷取畫面所示:

Azure IoT 總管工具的螢幕擷取畫面,其中顯示數位對應項屬性中的模型識別碼。

不含元件的 DTDL 模型是一組具有單一遙測、屬性和命令的裝置或 IoT Edge 模組的實用簡化方式。 不使用元件的模型可讓您輕鬆地將現有的裝置或模組移轉至 IoT 隨插即用裝置或模組,您即可建立 DTDL 模型來描述實際裝置或模組,而不需要定義任何元件。

提示

模組可以是裝置模組IoT Edge 模組

重複使用

有兩種方式可以重複使用介面定義。

  • 在模型中使用多個元件來參考其他介面定義。
  • 使用繼承來擴充現有介面的定義。

多個元件

元件可讓您建立模型介面作為其他介面的組件。

例如,控溫器介面會定義為模型。 當您定義溫度控制器模型時,您可以將此介面以一或多個元件的方式納入。 在下列範例中,這些元件稱為 thermostat1thermostat2

對於具有多個元件的 DTDL 模型,有兩個或多個元件區段。 每個區段已將 @type 設定為 Component,並明確參考架構,如下列程式碼片段所示:

{
  "@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."
    }
  ]
}

此模型在內容區段中定義三個元件,兩個 Thermostat 元件和一個 DeviceInformation 元件。 內容區段也包含屬性、遙測和命令定義。

下列螢幕擷取畫面顯示此模型在 IoT Central 中的顯示方式。 溫度控制器中的屬性、遙測和命令定義會出現在最上層的預設元件中。 每個控溫器的屬性、遙測和命令定義都會顯示在元件定義中:

顯示 IoT Central 中溫度控制器裝置範本的螢幕擷取畫面。

顯示 IoT Central 溫度控制器裝置範本中控溫器元件的螢幕擷取畫面。

若要了解如何撰寫與元件互動的裝置程式碼,請參閱 IoT 隨插即用裝置開發人員指南

若要了解如何撰寫與裝置上元件互動的服務程式碼,請參閱 IoT 隨插即用服務開發人員指南

繼承

繼承可讓您重複使用基底介面中的功能,以擴充介面的功能。 例如,數個裝置型號可以共用一般功能,例如序號:

顯示裝置模型中繼承範例的圖表。控溫器介面和流程控制器介面都會共用基底介面的功能。

下列程式碼片段顯示 DTML 模型,此模型會使用 extends 關鍵字來定義上圖所示的繼承關聯性:

[
  {
    "@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
      }
    ]
  }
]

下列螢幕擷取畫面顯示 IoT Central 裝置範本環境中的此模型:

顯示 IoT Central 中介面繼承的螢幕擷取畫面。

當您撰寫裝置或服務端程式碼時,您的程式碼不需要執行任何特殊動作即可處理繼承的介面。 在本區段所示的範例中,若您的裝置程式碼屬於控溫器介面,則會報告序號。

提示

您可以在建立模型時結合元件和繼承。 下圖顯示繼承自 baseDevice 介面的 thermostat 模型。 baseDevice 介面具有元件,其本身繼承自另一個介面:

顯示同時使用元件和繼承的模型的圖表。

下列程式碼片段顯示 DTML 模型,此模型會使用 extendscomponent 關鍵字來定義上圖所示的繼承關聯性和元件使用方式:

[
  {
    "@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"
      }
    ]
  }
]

資料類型

使用資料類型來定義遙測、屬性和命令參數。 資料類型可以是基本或複雜型。 複雜資料類型會使用基本類型或其他複雜類型。 複雜類型的深度上限為五個層級。

基本類型

下表顯示您可以使用的基本類型集:

基本型別 描述
boolean 布林值
date RFC 3339 的第 5.6 章節所定義的完整日期
dateTime RFC 3339中所定義的日期時間
double IEEE 8 位元組浮點數
duration ISO 8601 格式的持續時間
float IEEE 4 位元組浮點數
integer 帶正負號的 4 位元組整數
long 帶正負號的 8 位元組整數
string UTF8 字串
time RFC 3339 的第 5.6 章節所定義的完整時間

下列程式碼片段顯示使用 schema 欄位中 double 類型的範例遙測定義:

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

複雜的資料類型

複雜資料類型是陣列列舉對應物件或其中一種地理空間類型。

陣列

陣列是可編制索引的資料類型,其中所有元素均為相同的類型。 元素類型可以是基本類型或複雜類型。

下列程式碼片段顯示使用 schema 欄位中 Array 類型的範例遙測定義。 陣列的元素是布林值:

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

列舉

列舉描述類型,其中包含一組對應至值的具名標籤。 這些值可以是整數或字串,但標籤一律為字串。

下列程式碼片段顯示使用 schema 欄位中 Enum 類型的範例遙測定義。 列舉中的值為整數:

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

地圖

對應是索引鍵值組的類型,其中值均為相同的類型。 對應中的索引鍵必須為字串。 對應中的值可以是任何類型,包括另一個複雜類型。

下列程式碼片段顯示使用 schema 欄位中 Map 類型的範例屬性定義。 對應中的值為字串:

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

物件

物件類型是由具名欄位所組成。 物件對應中的欄位類型可以是基本類型或複雜類型。

下列程式碼片段顯示使用 schema 欄位中 Object 類型的範例遙測定義。 物件中的欄位為 dateTimedurationstring 類型:

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

地理空間類型

DTDL 會根據 GeoJSON 提供一組地理空間類型,以模型化地理資料結構:pointmultiPointlineStringmultiLineStringpolygonmultiPolygon。 這些類型是陣列、物件和列舉的預先定義巢狀結構。

下列程式碼片段顯示使用 schema 欄位中 point 類型的範例遙測定義:

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

由於地理空間類型是以陣列為基礎,因此目前無法用於屬性定義中。

語義類型

屬性或遙測定義的資料類型會指定裝置與服務交換的資料格式。 語意類型提供應用程式可用來判斷如何處理或顯示值的遙測和屬性相關資訊。 每個語意類型都有一或多個相關聯單位。 例如,攝氏和華氏是溫度語意類型的單位。 IoT Central 儀表板和分析可以使用語意類型資訊來決定如何繪製遙測或屬性值並顯示單位。 若要了解如何使用模型剖析器讀取語意類型,請參閱了解數位對應項模型剖析器

下列程式碼片段顯示包含語意類型資訊的範例遙測定義。 語意類型 Temperature 會新增至 @type 陣列,而 unitdegreeCelsius 是語意類型的其中一個有效單位:

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

當地語系化

IoT Central 之類的應用程式會使用模型中的資訊,在與 IoT 隨插即用裝置交換的資料周圍動態組建 UI。 例如,儀表板上的圖格可以顯示遙測、屬性和命令的名稱和描述。

模型中的選擇性 descriptiondisplayName 欄位會保存要在 UI 中使用的字串。 這些欄位可以保存應用程式可用來呈現當地語系化 UI 的當地語系化字串。

下列程式碼片段顯示包含當地語系化字串的範例溫度遙測定義:

{
  "@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"
}

新增當地語系化字串是選擇性選項。 下列範例只有單一的預設語言:

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

生命週期和工具

裝置模型的四個生命週期階段是撰寫發佈使用建立版本

作者

DTML 裝置模型是可在文字編輯器中建立的 JSON 文件。 不過,在 IoT Central 中,您可以使用裝置範本 GUI 環境來建立 DTML 模型。 在 IoT Central 中您可以:

  • 建立可定義屬性、遙測和命令的介面。
  • 使用元件將多個介面組合在一起。
  • 定義介面之間的繼承關聯性。
  • 匯入和匯出 DTML 模型檔案。

若要深入了解,請參閱在 Azure IoT Central 應用程式中定義新的 IoT 裝置類型

VS Code 有支援 DTDL v2 和 DTDL v3 的 DTDL 撰寫延伸模組。

若要安裝 VS Code 的 DTDL 擴充功能,請移至適用於 Visual Studio Code 的 DTDL 編輯器。 您也可以在 VS Code 的 [擴充功能] 檢視中搜尋 [DTDL]

在安裝延伸模組後,請使用延伸模組來協助您在 VS Code 中撰寫 DTDL 模型檔案:

  • 此擴充功能會在 DTDL 模型檔案中提供語法驗證,並醒目提示錯誤,如下列螢幕擷取畫面所示:

    顯示 VS Code 中 DTDL 模型驗證的螢幕擷取畫面。

  • 當您編輯 DTDL 模型時,請使用 IntelliSense 和自動完成:

    顯示 VS Code 中 DTDL 模型 IntelliSense 的螢幕擷取畫面。

  • 建立新的 DTDL 介面。 DTDL:建立介面命令會透過新的介面建立 JSON 檔案。 介面包含範例遙測、屬性和命令定義。

使用

IoT Central 之類的應用程式會使用裝置模型。 在 IoT Central 中,模型是描述裝置功能的裝置範本一部分。 IoT Central 會使用裝置範本來動態建置裝置的 UI,包括儀表板和分析。

注意

IoT Central 定義了 DTDL 語言的一些延伸模組。 若要深入了解,請參閱 IoT Central 延伸模組

自訂解決方案可以使用數位對應項模型剖析器來了解實作模型的裝置功能。 若要深入了解,請參閱在 IoT 解決方案中使用 IoT 隨插即用模型

版本

為了確保使用模型的裝置和伺服器端解決方案能繼續運作,已發佈的模型不可變。

DTMI 包含可用來建立模型多個版本的版本號碼。 裝置和伺服器端解決方案可以使用其設計用途的特定版本。

IoT Central 會針對裝置模型實作更多版本設定規則。 如果您在 IoT Central 中設定裝置範本及其模型的版本,您可以將裝置從舊版移轉至更新版本。 不過,移轉的裝置無法在韌體未升級的情況下使用新功能。 若要深入了解,請參閱<編輯裝置範本>。

發佈

自 2024 年 2 月起,Azure 認證裝置計劃已淘汰。 因此,Microsoft 不再接受將 DTDL 模型提交至 Azure IoT 隨插即用模型存放庫。

如果您想要設定自己的模型存放庫,則可以使用 Azure IoT 隨插即用模型工具存放庫。 此存放庫包含可驗證、匯入和展開 DTDL 模型之 dmr-client CLI 工具的程式碼。 此工具也可讓您為遵循裝置模型存放庫慣例的模型存放庫編製索引。

限制和條件約束

下列清單摘要說明模型的一些主要條件約束和限制:

  • 目前,陣列、對應和物件的深度上限為五個層級。
  • 您無法在屬性定義中使用陣列。
  • 您可以將介面擴充為 10 個層級的深度。
  • 介面最多可以擴充兩個其他介面。
  • 元件不能包含另一個元件。

了解數位對應項模型剖析器

DTDL 規格詳述數位對應項定義語言 (DTDL)。 使用者可使用「數位對應項模型剖析器」NuGet 套件來驗證及查詢 DTDL v2 或 v3 模型。 DTDL 模型可以在多個檔案中定義。

安裝 DTDL 模型剖析器

剖析器可在識別碼為 DTDLParser 的 NuGet.org 中使用。 若要安裝剖析器,請使用任何相容的 NuGet 套件管理員,例如 Visual Studio 或 dotnet CLI 中的 NuGet 套件管理員。

dotnet add package DTDLParser

注意

在撰寫本文時,剖析版本為 1.0.52

使用剖析器來驗證和檢查模型

DTDLParser 是一個程式庫,可用來:

  • 根據語言 v2 或 v3 規格,判斷一或多個模型是否有效。
  • 識別特定的模型化錯誤。
  • 檢查模型內容。

模型可以由 JSON 檔案中所述的一或多個介面組成。 您可使用剖析器來載入可定義模型的所有檔案,然後整體驗證所有檔案,包括檔案之間的任何參考。

適用於 .NET 的 DTDLParser 存放庫包含下列範例,以說明如何使用剖析器:

  • DTDLParserResolveSample 示範如何使用外部參考剖析介面,使用 Azure.IoT.ModelsRepository 用戶端解析相依性。
  • DTDLParserJSInteropSample 示範如何使用 .NET JSInterop,從在瀏覽器中執行的 JavaScript 使用 DTDL 剖析器。

適用於 .NET 的 DTDLParser 存放庫也包含教學課程集合,以示範如何使用剖析器來驗證和檢查模型。

模型剖析器 API 可讓許多案例自動執行或驗證相依於 DTDL 模型的工作。 例如,您可以透過模型中的資訊來以動態方式組建 UI。

下一步

現在您已了解裝置模型,以下有一些更多的資源可供參考: