IoT 隨插即用慣例
IoT 隨插即用 裝置在與IoT中樞交換訊息時,應該遵循一組慣例。 IoT 隨插即用 裝置會使用 MQTT 通訊協定與 IoT 中樞 通訊。 IoT 中樞 也支援某些 IoT 裝置 SDK 中提供的 AMQP 通訊協定。
裝置可以包含模組,或是在IoT Edge運行時間所裝載的IoT Edge模組中實作。
您描述 IoT 隨插即用 裝置使用數字對應項定義語言 (DTDL) 模型實作的遙測、屬性和命令。 本文所參考的模型類型有兩種:
- 無元件 - 沒有元件的模型。 模型會將遙測、屬性和命令宣告為主要介面內容區段中的最上層元素。 在 Azure IoT 總管工具中,此模型會顯示為單 一預設元件。
- 多個元件 - 由兩個或多個介面組成的模型。 主要介面,其會顯示為 預設元件,其中包含遙測、屬性和命令。 一或多個介面宣告為具有更多遙測、屬性和命令的元件。
如需詳細資訊,請參閱 IoT 隨插即用 模型化指南。
識別模型
若要宣告其實作的模型,IoT 隨插即用 裝置或模組會藉由將 新增model-id
至 USERNAME
欄位,在 MQTT 連線封包中包含模型識別碼。
若要識別裝置或模組所實作的模型,服務可以從下列專案取得模型標識碼:
- 裝置對應項
modelId
欄位。 - 數字對應項
$metadata.$model
欄位。 - 數字對應項變更通知。
遙測
- 從任何元件裝置傳送的遙測不需要任何額外的元數據。 系統會新增
dt-dataschema
屬性。 - 使用元件從裝置傳送的遙測必須將元件名稱新增至遙測訊息。
- 使用 MQTT 時,將具有元件名稱的屬性新增
$.sub
至遙測主題,系統會新增dt-subject
屬性。 - 使用AMQP時,將具有元件名稱的屬性新增
dt-subject
為訊息批注。
注意
來自元件的遙測需要每個元件一則訊息。
如需更多遙測範例,請參閱 承載 > 遙測
唯讀屬性
裝置會設定只讀屬性,然後向後端應用程式報告該屬性。
範例沒有元件唯讀屬性
裝置或模組可以傳送任何遵循 DTDL 規則的有效 JSON。
定義介面上屬性的 DTDL:
{
"@context": "dtmi:dtdl:context;2",
"@id": "dtmi:example: Thermostat;1",
"@type": "Interface",
"contents": [
{
"@type": "Property",
"name": "temperature",
"schema": "double"
}
]
}
範例報告屬性承載:
"reported" :
{
"temperature" : 21.3
}
範例多個元件唯讀屬性
裝置或模組必須新增 {"__t": "c"}
標記,以指出元素參考元件。
參考元件的 DTDL:
{
"@context": "dtmi:dtdl:context;2",
"@id": "dtmi:com:example:TemperatureController;1",
"@type": "Interface",
"displayName": "Temperature Controller",
"contents": [
{
"@type" : "Component",
"schema": "dtmi:com:example:Thermostat;1",
"name": "thermostat1"
}
]
}
定義元件的 DTDL:
{
"@context": "dtmi:dtdl:context;2",
"@id": "dtmi:com:example:Thermostat;1",
"@type": "Interface",
"contents": [
{
"@type": "Property",
"name": "temperature",
"schema": "double"
}
]
}
範例報告屬性承載:
"reported": {
"thermostat1": {
"__t": "c",
"temperature": 21.3
}
}
如需更多只讀屬性範例,請參閱 Payloads > 屬性。
可寫入的屬性
後端應用程式會設定可寫入的屬性,IoT 中樞 然後傳送至裝置。
裝置或模組應該藉由傳送報告屬性來確認其已接收屬性。 報告的屬性應該包括:
value
- 屬性的實際值 (通常接收的值,但裝置可能會決定報告不同的值)。ac
- 使用 HTTP 狀態碼的確認代碼。av
- 參考所需屬性$version
的確認版本。 您可以在所需的屬性 JSON 承載中找到此值。ad
- 選擇性確認描述。
通知回應
當報告可寫入的屬性時,裝置應該使用上一個清單中的四個字段來撰寫通知訊息,以指出實際的裝置狀態,如下表所述:
Status(ac) | Version(av) | Value(value) | 描述(av) |
---|---|---|---|
200 | 所需的版本 | 所需值 | 接受所需的屬性值 |
202 | 所需的版本 | 裝置接受的值 | 接受所需的屬性值,進行中更新 (應該完成 200) |
203 | 0 | 裝置所設定的值 | 從裝置設定的屬性,不會反映任何所需的屬性 |
400 | 所需的版本 | 裝置所使用的實際值 | 不接受所需的屬性值 |
500 | 所需的版本 | 裝置所使用的實際值 | 套用 屬性時的例外狀況 |
裝置啟動時,它應該要求裝置對應項,並檢查是否有任何可寫入的屬性更新。 如果裝置離線時可寫入屬性的版本增加,裝置應該傳送回報的屬性回應,以確認它已收到更新。
當裝置第一次啟動時,如果它未從IoT中樞收到初始所需的屬性,它可以傳送報告屬性的初始值。 在此情況下,裝置可以將的av
預設值傳送至 0
和 ac
。203
例如:
"reported": {
"targetTemperature": {
"value": 20.0,
"ac": 203,
"av": 0,
"ad": "initialize"
}
}
裝置可以使用報告屬性,將其他資訊提供給中樞。 例如,裝置可能會回應一系列進行中的訊息,例如:
"reported": {
"targetTemperature": {
"value": 35.0,
"ac": 202,
"av": 3,
"ad": "In-progress - reporting current temperature"
}
}
當裝置達到目標溫度時,它會傳送下列訊息:
"reported": {
"targetTemperature": {
"value": 20.0,
"ac": 200,
"av": 4,
"ad": "Reached target temperature"
}
}
裝置可能會回報錯誤,例如:
"reported": {
"targetTemperature": {
"value": 120.0,
"ac": 500,
"av": 3,
"ad": "Target temperature out of range. Valid range is 10 to 99."
}
}
Object type
如果可寫入的屬性定義為對象,服務必須將完整的物件傳送至裝置。 裝置應該認可更新,方法是將足夠的資訊傳回服務,讓服務了解裝置在更新上的運作方式。 此回應可能包括:
- 整個物件。
- 只是裝置更新的欄位。
- 欄位的子集。
對於大型物件,請考慮將認可中包含的物件大小降到最低。
下列範例顯示定義為 Object
具有四個字段的 可寫入屬性:
DTDL:
{
"@type": "Property",
"name": "samplingRange",
"schema": {
"@type": "Object",
"fields": [
{
"name": "startTime",
"schema": "dateTime"
},
{
"name": "lastTime",
"schema": "dateTime"
},
{
"name": "count",
"schema": "integer"
},
{
"name": "errorCount",
"schema": "integer"
}
]
},
"displayName": "Sampling range"
"writable": true
}
若要更新這個可寫入的屬性,請從看起來像下列範例的服務傳送完整的物件:
{
"samplingRange": {
"startTime": "2021-08-17T12:53:00.000Z",
"lastTime": "2021-08-17T14:54:00.000Z",
"count": 100,
"errorCount": 5
}
}
裝置會以類似下列範例的通知回應:
{
"samplingRange": {
"ac": 200,
"av": 5,
"ad": "Weighing status updated",
"value": {
"startTime": "2021-08-17T12:53:00.000Z",
"lastTime": "2021-08-17T14:54:00.000Z",
"count": 100,
"errorCount": 5
}
}
}
無元件可寫入屬性的範例
當裝置在單一承載中收到多個所需屬性時,它可以跨多個承載傳送報告的屬性回應,或將響應合併成單一承載。
裝置或模組可以傳送任何遵循 DTDL 規則的有效 JSON。
DTDL:
{
"@context": "dtmi:dtdl:context;2",
"@id": "dtmi:example: Thermostat;1",
"@type": "Interface",
"contents": [
{
"@type": "Property",
"name": "targetTemperature",
"schema": "double",
"writable": true
},
{
"@type": "Property",
"name": "targetHumidity",
"schema": "double",
"writable": true
}
]
}
範例所需的屬性承載:
"desired" :
{
"targetTemperature" : 21.3,
"targetHumidity" : 80,
"$version" : 3
}
範例報告屬性第一個承載:
"reported": {
"targetTemperature": {
"value": 21.3,
"ac": 200,
"av": 3,
"ad": "complete"
}
}
範例報告屬性第二個承載:
"reported": {
"targetHumidity": {
"value": 80,
"ac": 200,
"av": 3,
"ad": "complete"
}
}
注意
您可以選擇將這兩個報告的屬性承載合併成單一承載。
範例多個元件可寫入屬性
裝置或模組必須新增 {"__t": "c"}
標記,以指出元素參考元件。
標記只會針對元件中定義的屬性更新傳送。 更新 預設元件中定義的屬性不包含標記,請參閱範例中沒有元件可寫入的屬性。
當裝置在單一承載中收到多個報告屬性時,它可以跨多個承載傳送報告的屬性回應,或將響應合併成單一承載。
裝置或模組應該藉由傳送報告的屬性來確認它已接收屬性:
參考元件的 DTDL:
{
"@context": "dtmi:dtdl:context;2",
"@id": "dtmi:com:example:TemperatureController;1",
"@type": "Interface",
"displayName": "Temperature Controller",
"contents": [
{
"@type" : "Component",
"schema": "dtmi:com:example:Thermostat;1",
"name": "thermostat1"
}
]
}
定義元件的 DTDL:
{
"@context": "dtmi:dtdl:context;2",
"@id": "dtmi:com:example:Thermostat;1",
"@type": "Interface",
"contents": [
{
"@type": "Property",
"name": "targetTemperature",
"schema": "double",
"writable": true
}
]
}
範例所需的屬性承載:
"desired": {
"thermostat1": {
"__t": "c",
"targetTemperature": 21.3,
"targetHumidity": 80,
"$version" : 3
}
}
範例報告屬性第一個承載:
"reported": {
"thermostat1": {
"__t": "c",
"targetTemperature": {
"value": 23,
"ac": 200,
"av": 3,
"ad": "complete"
}
}
}
範例報告屬性第二個承載:
"reported": {
"thermostat1": {
"__t": "c",
"targetHumidity": {
"value": 80,
"ac": 200,
"av": 3,
"ad": "complete"
}
}
}
注意
您可以選擇將這兩個報告的屬性承載合併成單一承載。
如需更多可寫入的屬性範例,請參閱 Payloads > 屬性。
命令
沒有元件介面會使用不含前置詞的命令名稱。
在裝置或模組上,多個元件介面會使用具有下列格式的命令名稱: componentName*commandName
。
如需更多命令範例,請參閱 Payloads > 命令。
下一步
既然您已瞭解 IoT 隨插即用 慣例,以下是一些其他資源: