IoT 隨插即用模型化指南

IoT 隨插即用的核心是一種裝置型號,描述已啟用IoT 隨插即用應用程式之裝置的功能。 此模型的結構是一組定義下列專案的介面:

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

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

若要定義模型,您可以使用 DIGITAL Twins 定義語言 (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"
            }
          ]
        }
      }
    }
  ]
}

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

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

若要深入瞭解,請參閱 Digital Twins Definition Language v2 規格。

模型結構

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

模型識別碼

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

DTMI 應遵循IoT 隨插即用模型存放庫所需的命名慣例:

  • 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 Explorer 和 IoT Central 裝置範本設計工具等工具會標示獨立介面,例如控溫器作為預設元件

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

Default component in Azure IoT explorer

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

Screenshot showing Thermostat model in IoT Central designer

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

Model ID in digital twin property

不含元件的 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."
    }
  ]
}

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

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

Screenshot showing the temperature controller device template in IoT Central.

Screenshot showing the thermostat components in the temperature controller device template in IoT Central.

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

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

繼承

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

Example of inheritance in a device model showing a Thermostat and a Flow Controller that share capabilities from a base interface.

下列程式碼片段顯示 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 裝置範本環境中的此模型:

Screenshot showing interface inheritance in IoT Central

當您撰寫裝置或服務端程式碼時,您的程式碼不需要執行任何特殊動作來處理繼承的介面。 在本節所示的範例中,您的裝置程式碼會報告序號,就像是控溫器介面的一部分一樣。

提示

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

Diagram showing a model that uses both components and inheritance.

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

[
  {
    "@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 節中所定義的完整時間

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

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

複雜資料類型

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

陣列

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

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

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

列舉

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

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

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

地圖服務

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

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

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

物件

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

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

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

地理空間類型

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

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

{
  "@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和 Visual Studio 2019 都有 DTDL 撰寫延伸模組。

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

安裝擴充功能後,請使用它來協助您在 VS 程式碼中撰寫 DTDL 模型檔案:

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

    Model validation in VS Code

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

    Use intellisense for DTDL models in VS Code

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

若要安裝 Visual Studio 2019 的 DTDL 擴充功能,請移至VS 2019 的 DTDL 語言支援。 您也可以在 Visual Studio 中的管理延伸模組中搜尋DTDL

安裝擴充功能後,請使用它來協助您在 Visual Studio 中撰寫 DTDL 模型檔案:

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

    Model validation in Visual Studio

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

    Use intellisense for DTDL models in Visual Studio

發佈

若要讓您的 DTML 模型可共用且可供探索,請在裝置模型存放庫中發佈它們。

在公用存放庫中發佈模型之前,您可以使用 dmr-client 工具來驗證模型。

若要深入瞭解,請參閱 裝置型號存放庫

使用

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

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

版本

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

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

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

限制和條件約束

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

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

後續步驟

現在您已瞭解裝置模型,以下是一些額外的資源: