Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
自定义分配策略让你能够更好地控制将设备分配到 IoT 中心的方式。 当设备预配服务 (DPS) 提供的内置策略不能满足你的方案要求时,你可以使用自定义分配策略来定义自己的分配策略。
例如,你可能想要检查设备在预配过程中使用的证书,并根据证书属性将设备分配到IoT hub。 或者,您可能在用于设备的数据库中存储了信息,需要查询数据库以确定应分配到哪个IoT中心,或者设备的初始孪生对象应如何设置。
在 Azure Functions 托管的 Webhook 中实现自定义分配策略。 然后,可以在一个或多个单独注册和注册组中配置 Webhook。 当设备通过配置的注册条目注册时,DPS 会调用 Webhook,这会返回IoT hub以向设备注册设备,并且可以选择将设备的初始孪生设置以及要直接返回到设备的任何信息。
概述
以下步骤说明了自定义分配策略的工作原理:
自定义资源分配的开发人员创建一个实现预期分配策略的Webhook,并将其作为HTTP触发器函数部署到 Azure Functions。 Webhook 获取有关 DPS 注册条目和设备的信息,并返回设备应被注册到的 IoT Hub,以及(可选)设备的初始状态信息。
IoT运营商为自定义分配配置一个或多个单独的注册和/或注册组,并提供Azure Functions中自定义分配Webhook的调用信息。
当设备通过为自定义分配 Webhook 配置的注册条目注册时,DPS 会向 Webhook 发送一个 POST 请求,其请求正文设置为 AllocationRequest 请求对象。 AllocationRequest 对象包含有关尝试预配的设备以及该设备在预配时所用的单独注册或注册组的信息。 设备信息可能包括设备在其注册请求中发送的可选自定义有效负载。 有关详细信息,请参阅自定义分配策略请求。
Azure函数在成功时执行并返回 AllocationResponse 对象。 AllocationResponse 对象包含设备应被预配到的 IoT hub、初始孪生状态,以及用于返回设备的可选自定义有效负载。 有关详细信息,请参阅自定义分配策略响应。
DPS 将设备分配给响应中指定的 IoT Hub,如果返回初始孪生体,则相应地设置设备的初始孪生体。 如果 Webhook 返回自定义有效负载,则会将该负载与在 DPS 中分配的 IoT 中心和身份验证详细信息一起传递给设备的 注册响应 。
设备连接到分配的IoT hub并下载其初始孪生状态。 如果在注册响应中返回了自定义有效负载,设备将根据自身的客户端逻辑使用该有效负载。
以下部分提供有关自定义分配请求和响应、自定义有效负载和策略实现的更多详细信息。 有关自定义分配策略的完整端到端示例的详细信息,请参阅 教程:将自定义分配策略与设备预配服务(DPS)配合使用。
管理函数密钥
自定义分配策略使用函数密钥对授权级别设置为 Function 的Azure Functions调用进行身份验证。 密钥管理的行为因是通过Azure portal还是以编程方式配置自定义分配策略而有所不同。
门户中的函数密钥
在Azure portal中创建注册并指定自定义分配策略时,门户会自动处理检索和嵌入函数密钥。
为自定义分配策略选择函数后,门户将检索函数密钥。 此步骤不对用户通过门户界面可见。 然后,函数密钥作为 DPS 用来调用函数的加密 Webhook URL 的一部分存储。 密钥不会显示在门户中。
可以通过运行 GET 命令来检索注册详细信息,以验证密钥是否嵌入 Webhook URL 中。 在注册配置中,函数密钥包含在 webhookUrl 字段中。
使用 API 的函数密钥
使用 DPS API 以编程方式创建注册时,需要在创建注册期间手动提供密钥。 如果未提供密钥,Azure Functions调用将失败身份验证。
在创建个体或组注册之前,请从您的函数中检索函数密钥。 有关详细信息,请参阅获取函数的访问密钥。 然后,在 CustomAllocationDefinition 的 webhookUrl 字段中包含函数密钥。
有关详细信息,请参阅 Access 密钥授权。
自定义分配策略请求
DPS 在以下端点向 Webhook 发送 POST 请求:https://{your-function-app-name}.chinacloudsites.cn/api/{your-http-trigger}
请求正文是一个 AllocationRequest 对象:
| 属性名称 | 说明 |
|---|---|
| 个人注册 | 一条单独注册记录,其中包含与分配请求源自的单独注册关联的属性。 如果设备正在通过个人注册,则该记录是有效的。 |
| 注册组 | 一条注册组记录,其中包含与分配请求源自的注册组关联的属性。 如果设备通过注册组进行注册,则会显示。 |
| 设备运行时上下文 | 包含与正在注册的设备关联的属性的对象。 始终存在 |
| linkedHubs | 一个包含与分配请求源自的注册条目相关联的 IoT 中心主机名的数组。 设备可能分配到其中任一 IoT 中心。 始终存在 |
DeviceRuntimeContext 对象具有以下属性:
| 属性 | 类型 | 说明 |
|---|---|---|
| 注册ID | 字符串 | 设备在运行时提供的注册 ID。 始终存在 |
| currentIotHubHostName | 字符串 | 之前分配给设备的IoT hub的主机名(如果有)。 如果这是初始分配,则不存在。 可以使用此属性来确定这是设备的初始指派,还是设备是否已被之前指派。 |
| 当前设备ID | 字符串 | 设备以前分配中的设备 ID(如果有的话)。 如果这是初始分配,则不存在。 |
| x509 | X509DeviceAttestation | X.509认证包含证书详细信息。 |
| 对称密钥 | 对称密钥证明 | 对于对称密钥证明,其中包含主密钥和辅助密钥详细信息。 |
| tpm | TpmAttestation | 对于 TPM 证明,包含认可密钥和存储根密钥详细信息。 |
| 有效负载 | 对象 | 包含注册期间设备在有效负载属性中指定的属性。 如果设备在 DPS 注册请求中发送了自定义有效负载,则会出现。 |
以下 JSON 显示了 DPS 为通过基于对称密钥的注册组注册的设备发送的 AllocationRequest 对象。
{
"enrollmentGroup":{
"enrollmentGroupId":"contoso-custom-allocated-devices",
"attestation":{
"type":"symmetricKey"
},
"capabilities":{
"iotEdge":false
},
"etag":"\"13003fea-0000-0300-0000-62d1d5e50000\"",
"provisioningStatus":"enabled",
"reprovisionPolicy":{
"updateHubAssignment":true,
"migrateDeviceData":true
},
"createdDateTimeUtc":"2022-07-05T21:27:16.8123235Z",
"lastUpdatedDateTimeUtc":"2022-07-15T21:02:29.5922255Z",
"allocationPolicy":"custom",
"iotHubs":[
"custom-allocation-toasters-hub.azure-devices.cn",
"custom-allocation-heatpumps-hub.azure-devices.cn"
],
"customAllocationDefinition":{
"webhookUrl":"https://custom-allocation-function-app-3.chinacloudsites.cn/api/HttpTrigger1?****",
"apiVersion":"2021-10-01"
}
},
"deviceRuntimeContext":{
"registrationId":"breakroom499-contoso-tstrsd-007",
"symmetricKey":{
}
},
"linkedHubs":[
"custom-allocation-toasters-hub.azure-devices.cn",
"custom-allocation-heatpumps-hub.azure-devices.cn"
]
}
由于这是设备的初始注册,因此 deviceRuntimeContext 属性仅包含设备的注册 ID 和身份验证详细信息。 以下 JSON 显示了在后续调用中用于注册同一台设备的 deviceRuntimeContext。 请注意,请求中包含当前IoT hub主机名和设备 ID。
{
"deviceRuntimeContext":{
"registrationId":"breakroom499-contoso-tstrsd-007",
"currentIotHubHostName":"custom-allocation-toasters-hub.azure-devices.cn",
"currentDeviceId":"breakroom499-contoso-tstrsd-007",
"symmetricKey":{
}
},
}
自定义分配策略响应
成功的请求会返回 AllocationResponse 对象。
| 属性 | 说明 |
|---|---|
| initialTwin | 可选。 一个包含在分配的 IoT 中心的初始孪生体中设置所需属性和标记的对象。 DPS 使用 initialTwin 属性在首次分配时或重新预配时,在分配的 IoT Hub 上设置初始孪生,前提是注册条目的迁移策略设置为重新预配并重置为初始配置。在这两种情况下,如果 initialTwin 没有被返回或被设置为 null,DPS 将在分配的 IoT Hub 上设置注册条目中的初始孪生设置。 DPS 会忽略注册条目中所有其他重新预配设置的 initialTwin。 有关详细信息,请参阅实现详细信息。 |
| iotHubHostName | 必填 分配设备的 IoT hub 主机名。 此 IoT 中心必须是在请求的 linkedHubs 属性中传递的其中之一。 |
| 有效负载 | 可选。 一个对象,其中包含要在注册响应中传回设备的数据。 确切数据取决于开发人员在设备与自定义分配函数之间定义的隐式协定。 |
以下 JSON 显示自定义分配函数为 DPS 返回的 AllocationResponse 对象,以便在上一示例中注册。
{
"iotHubHostName":"custom-allocation-toasters-hub.azure-devices.cn",
"initialTwin":{
"properties":{
"desired":{
"state":"ready",
"darknessSetting":"medium"
}
},
"tags":{
"deviceType":"toaster"
}
}
}
在自定义资源分配中应用设备负载
设备可将 DPS 传递的自定义有效负载发送到自定义分配 Webhook,后者随后可以在其逻辑中使用该有效负载。 Webhook 可能以多种方式使用此数据,或许可以确定将设备分配到哪些IoT hub,或者查找外部数据库中可能用于在初始孪生体上设置属性的信息。 相反,Webhook 可以通过 DPS 将数据返回回设备,这可能用于设备的客户端逻辑。
例如,你可能希望基于设备模型分配设备。 在这种情况下,可将设备配置为在向 DPS 注册时在请求有效负载中报告其型号信息。 DPS 将此有效负载传递给自定义分配 Webhook,该 Webhook 根据设备模型信息确定设备预配到哪个 IoT hub。 如果需要,Webhook 可以在 Webhook 响应中将数据作为 JSON 对象返回给 DPS,而 DPS 会在注册响应中将此数据返回到您的设备。
设备将数据负载发送到 DPS
设备调用 DPS 注册 API 以向 DPS 注册。 可以使用可选的 payload 属性来增强请求。 此属性可以包含任何有效 JSON 对象。 具体内容取决于解决方案的要求。
若要使用 TPM 进行证明,请求正文如以下示例所示:
{
"registrationId": "mydevice",
"tpm": {
"endorsementKey": "xxxx-device-endorsement-key-xxxxx",
"storageRootKey": "xxxx-device-storage-root-key-xxxxx"
},
"payload": { "property1": "value1", "property2": {"propertyA":"valueA", "property2-2":1234}, .. }
}
DPS 将数据负载发送到自定义分配 Webhook
如果设备在其注册请求中包含有效负载,则 DPS 在调用自定义分配 Webhook 时会在 AllocationRequest.deviceRuntimeContext.payload 属性中传递该有效负载。
对于上一部分中的 TPM 注册请求,设备运行时上下文如以下示例所示:
{
"registrationId": "mydevice",
"tpm": {
"endorsementKey": "xxxx-device-endorsement-key-xxxxx",
"storageRootKey": "xxxx-device-storage-root-key-xxxxx"
},
"payload": { "property1": "value1", "property2": {"propertyA":"valueA", "property2-2":1234}, .. }
}
如果这不是设备的初始注册,则运行时上下文还包括 currentIoTHubHostname 和 currentDeviceId 属性。
自定义分配 Webhook 将数据返回给 DPS
自定义分配策略 Webhook 可以使用 Webhook 响应中的 AllocationResponse.payload 属性,在 JSON 对象中将预期发往设备的数据返回给 DPS。
以下 JSON 显示了包含有效负载的 Webhook 响应:
{
"iotHubHostName":"custom-allocation-toasters-hub.azure-devices.cn",
"initialTwin":{
"properties":{
"desired":{
"state":"ready",
"darknessSetting":"medium"
}
},
"tags":{
"deviceType":"toaster"
}
},
"payload": { "property1": "value1" }
}
DPS 发送数据包到设备
如果 DPS 在 Webhook 响应中收到有效负载,则在成功注册后,它会在响应中的 RegistrationOperationStatus.registrationState.payload 属性内将此数据传回给设备。 registrationState 属性的类型为 DeviceRegistrationResult。
以下 JSON 显示了 TPM 设备的成功注册响应,其中包含 payload 属性:
{
"operationId":"5.316aac5bdc130deb.b1e02da8-xxxx-xxxx-xxxx-7ea7a6b7f550",
"status":"assigned",
"registrationState":{
"assignedHub":"myIotHub",
"createdDateTimeUtc" : "2022-08-01T22:57:47Z",
"deviceId" : "myDeviceId",
"etag" : "xxxx-etag-value-xxxxx",
"lastUpdatedDateTimeUtc" : "2022-08-01T22:57:47Z",
"payload": { "property1": "value1" },
"registrationId": "mydevice",
"status": assigned,
"substatus": initialAssignment,
"tpm": {"authenticationKey": "xxxx-encrypted-authentication-key-xxxxx"}
}
}
实施细节信息
可以为以前未通过 DPS 注册的设备(初始分配)或以前通过 DPS 注册的设备(重新预配)调用自定义分配 Webhook。 DPS 支持以下重新预配策略:“重新预配并迁移数据”、“重新预配并重置为初始配置”和“永不重新预配”。 每当将以前预配的设备分配到新的IoT hub时,都应用这些策略。 有关详细信息,请参阅 IoT Hub 设备重新预配概念。
以下要点描述了自定义分配 Webhook 必须遵守的要求,以及在设计 Webhook 时应注意的行为:
应将设备分配到 AllocationRequest.linkedHubs 属性中的 IoT 中心之一。 此属性包含设备可分配到的 IoT 中心的列表,该列表按主机名列出。 此列表通常由为注册入口选择的 IoT 中心组成。 如果在注册条目中未选择 IoT 中心,则它包含链接到 DPS 实例的所有 IoT 中心。 最后,如果设备正在重新预配,并且注册条目上设置了永远重新预配策略,则仅包含当前分配给设备的IoT hub。
初始分配时,如果 webhook 返回 initialTwin 属性,DPS 会相应地在分配的IoT hub上设置设备的初始孪生体。 如果 initialTwin 属性被省略或为 null,则 DPS 会将设备的初始孪生设置为注册条目中指定的初始孪生设置。
重新预配时,DPS会遵循注册记录中设置的重新预配策略。 如果当前的 IoT hub 改变了,并且注册条目的重新配置策略设置为“重新配置并重置为初始配置”,那么 DPS 仅在响应中使用 initialTwin 属性。在这种情况下,DPS 在新的 IoT hub 上为设备设置初始孪生体,与上一个项目符号中初始分配时完全一样。 在所有其他情况下,DPS 都会忽略 initialTwin 属性。
如果在响应中设置了 有效负载 属性,则无论请求是用于初始分配还是重新预配,DPS 始终会将其返回到设备。
如果设备以前预配到 IoT hub,则 AllocationRequest.deviceRuntimeContext 包含 currentIotHubHostName 属性,该属性设置为设备当前分配的IoT hub的主机名。
通过检查请求中 AllocationRequest.individualEnrollment 属性或 AllocationRequest.enrollmentGroup 属性的 reprovisionPolicy 属性,可以确定当前注册项上设置了哪个重新预配策略。 以下 JSON 显示了“重新预配并迁移数据”策略的设置:
"reprovisionPolicy":{ "updateHubAssignment":true, "migrateDeviceData":true }
SDK 支持
DPS 设备 SDK 在 C、C#、Java 和 Node.js 中提供了 API,以帮助你将设备注册到 DPS。 IoT Hub SDK 和 DPS SDK 都提供了表示设备和服务工件的类,如设备孪生和注册项,这些类在开发自定义分配 Webhook 时可能会有所帮助。 若要详细了解可用于IoT Hub和IoT Hub设备预配服务的 Azure IoT SDK,请参阅 Azure IoT Hub SDK 和 Microsoft sdk for IoT Hub Device Provisioning Service。
后续步骤
有关使用自定义分配策略的端到端示例,请参阅 教程:将自定义分配策略用于设备预配服务(DPS)
若要了解有关Azure Functions的详细信息,请参阅 Azure Functions 文档