如何在 Azure 数字孪生中创建用户定义函数
用户定义函数使用户能够针对传入的遥测消息和空间图形元数据配置执行的自定义逻辑。 用户还可将事件发送到预定义的终结点。
本指南通过一个示例演示如何检测和警告任何超过特定温度的读数,这些读数来自接收到的温度事件。
在以下示例中,YOUR_MANAGEMENT_API_URL
代表数字孪生 API 的 URI:
https://YOUR_INSTANCE_NAME.YOUR_LOCATION.azuresmartspaces.net/management/api/v1.0
名称 | 替换为 |
---|---|
YOUR_INSTANCE_NAME | Azure 数字孪生实例的名称 |
YOUR_LOCATION | 托管实例的区域 |
客户端库参考
如需了解用户定义函数运行时中可用作帮助程序方法的函数,请参阅客户端库参考一文。
创建匹配程序
匹配程序是图形对象,可决定要对给定遥测消息运行哪些用户定义的函数。
有效匹配程序条件的比较:
Equals
NotEquals
Contains
有效匹配程序条件的目标:
Sensor
SensorDevice
SensorSpace
对于数据类型值为 "Temperature"
的所有传感器遥测事件,以下示例匹配程序的计算结果都为 true。 可通过向以下对象发出经过身份验证的 HTTP POST 请求,在用户定义函数中创建多个匹配程序:
YOUR_MANAGEMENT_API_URL/matchers
使用 JSON 体:
{
"id": "3626464-f39b-46c0-d9b0c-436aysj55",
"name": "Temperature Matcher",
"spaceId": "YOUR_SPACE_IDENTIFIER",
"conditions": [
{
"id": "ag7gq35cfu3-e15a-4e9c-6437-sj6w68sy44s",
"target": "Sensor",
"path": "$.dataType",
"value": "\"Temperature\"",
"comparison": "Equals"
}
]
}
值 | 替换为 |
---|---|
YOUR_SPACE_IDENTIFIER | 托管实例的服务器区域 |
创建用户定义的函数
创建用户定义的函数涉及向 Azure 数字孪生管理 API 发出多部分 HTTP 请求。
注意
多部分请求通常需要三个信息片段:
-
Content-Type 标头:
application/json; charset=utf-8
multipart/form-data; boundary="USER_DEFINED_BOUNDARY"
-
内容处置:
form-data; name="metadata"
- 要上传的文件内容
Content-Type 和 Content-Disposition 将因使用方案而异。
可以通过 REST 客户端或诸如 Postman 的工具以编程方式(通过 C#)进行多部分请求。 各种 REST 客户端工具对复杂的多部分请求可能具有不同的支持级别。 不同工具的配置设置也可能略有不同。 请验证哪个工具最适合你的需求。
重要
向 Azure 数字孪生管理 API 发出的多部分请求通常包含两个部分:
- 由 Content-Type 和/或 Content-Disposition 声明的 Blob 元数据(例如关联的 MIME 类型)
- 包括要上传的文件的非结构化内容的 Blob 内容
对于 PATCH 请求,上述两个部分都不是必需的。 对于 POST 请求或 create 操作,两者都是必需的。
采用快速入门源代码包含完整的 C# 示例,其中展示了如何针对 Azure 数字孪生管理 API 进行多部分请求。
创建匹配程序后,使用以下经过身份验证的多部分 HTTP POST 请求来上传函数代码片段:
YOUR_MANAGEMENT_API_URL/userdefinedfunctions
使用以下正文:
--USER_DEFINED_BOUNDARY
Content-Type: application/json; charset=utf-8
Content-Disposition: form-data; name="metadata"
{
"spaceId": "YOUR_SPACE_IDENTIFIER",
"name": "User Defined Function",
"description": "The contents of this udf will be executed when matched against incoming telemetry.",
"matchers": ["YOUR_MATCHER_IDENTIFIER"]
}
--USER_DEFINED_BOUNDARY
Content-Disposition: form-data; name="contents"; filename="userDefinedFunction.js"
Content-Type: text/javascript
function process(telemetry, executionContext) {
// Code goes here.
}
--USER_DEFINED_BOUNDARY--
值 | 替换为 |
---|---|
USER_DEFINED_BOUNDARY | 多部分内容边界名称 |
YOUR_SPACE_IDENTIFIER | 空间标识符 |
YOUR_MATCHER_IDENTIFIER | 要使用的匹配程序的 ID |
验证标头是否包括:
Content-Type: multipart/form-data; boundary="USER_DEFINED_BOUNDARY"
。验证正文由多个部分组成:
- 第一部分包含所需的用户定义的函数元数据。
- 第二部分包含 JavaScript 计算逻辑。
在 “USER_DEFINED_BOUNDARY ”部分中,替换 spaceId ()
YOUR_SPACE_IDENTIFIER
和 匹配器 (YOUR_MATCHER_IDENTIFIER
) 值。验证 JavaScript 用户定义的函数是否作为
Content-Type: text/javascript
提供。
示例函数
直接针对数据类型为 Temperature(也就是 sensor.DataType
)的传感器设置传感器遥测读数:
function process(telemetry, executionContext) {
// Get sensor metadata
var sensor = getSensorMetadata(telemetry.SensorId);
// Retrieve the sensor value
var parseReading = JSON.parse(telemetry.Message);
// Set the sensor reading as the current value for the sensor.
setSensorValue(telemetry.SensorId, sensor.DataType, parseReading.SensorValue);
}
telemetry 参数公开了 SensorId 和 Message 属性(对应于传感器发送的消息)。 ExecutionContext 参数公开了以下属性:
var executionContext = new UdfExecutionContext
{
EnqueuedTime = request.HubEnqueuedTime,
ProcessorReceivedTime = request.ProcessorReceivedTime,
UserDefinedFunctionId = request.UserDefinedFunctionId,
CorrelationId = correlationId.ToString(),
};
在下一示例中,如果传感器遥测读数超过预定义的阈值,则记录消息。 如果 Azure 数字孪生实例上启用了诊断设置,则还会转发用户定义函数中的日志:
function process(telemetry, executionContext) {
// Retrieve the sensor value
var parseReading = JSON.parse(telemetry.Message);
// Example sensor telemetry reading range is greater than 0.5
if(parseFloat(parseReading.SensorValue) > 0.5) {
log(`Alert: Sensor with ID: ${telemetry.SensorId} detected an anomaly!`);
}
}
如果温度高于预定义常量,以下代码会触发通知:
function process(telemetry, executionContext) {
// Retrieve the sensor value
var parseReading = JSON.parse(telemetry.Message);
// Define threshold
var threshold = 70;
// Trigger notification
if(parseInt(parseReading) > threshold) {
var alert = {
message: 'Temperature reading has surpassed threshold',
sensorId: telemetry.SensorId,
reading: parseReading
};
sendNotification(telemetry.SensorId, "Sensor", JSON.stringify(alert));
}
}
有关更复杂的用户定义函数代码示例,请阅读 “占用”快速入门。
创建角色分配
创建角色分配,以便用户定义函数依据其运行。 如果用户定义的函数不存在角色分配,则它将没有与管理 API 交互的适当权限,也没有对图形对象执行操作的权限。 用户定义的函数可以执行的操作是通过 Azure 数字孪生管理 API 中基于角色的访问控制来指定和定义的。 例如,用户定义函数可通过指定特定角色或特定访问控制路径来限制这些操作的范围。 有关详细信息,请阅读 基于角色的访问控制 文档。
查询所有角色的系统 API 以获取要分配给用户定义函数的角色 ID。 可通过发出经过身份验证的 HTTP GET 请求执行此操作,以便:
YOUR_MANAGEMENT_API_URL/system/roles
保留所需的角色 ID。 它将作为 JSON 正文属性 roleId ()
YOUR_DESIRED_ROLE_IDENTIFIER
传递给下面。objectId (
YOUR_USER_DEFINED_FUNCTION_ID
) 将是之前创建的用户定义的函数 ID。通过查询空格
fullpath
来查找路径 (YOUR_ACCESS_CONTROL_PATH
) 的值。复制返回的
spacePaths
值。 稍后你将使用该值。 向以下对象发出经过身份验证的 HTTP GET 请求:YOUR_MANAGEMENT_API_URL/spaces?name=YOUR_SPACE_NAME&includes=fullpath
值 替换为 YOUR_SPACE_NAME 要使用的空间名称 将返回的
spacePaths
值粘贴到“路径”,以通过向以下对象发出经过身份验证的 HTTP POST 请求来创建用户定义的函数角色分配:YOUR_MANAGEMENT_API_URL/roleassignments
使用 JSON 体:
{ "roleId": "YOUR_DESIRED_ROLE_IDENTIFIER", "objectId": "YOUR_USER_DEFINED_FUNCTION_ID", "objectIdType": "YOUR_USER_DEFINED_FUNCTION_TYPE_ID", "path": "YOUR_ACCESS_CONTROL_PATH" }
值 替换为 YOUR_DESIRED_ROLE_IDENTIFIER 所需角色的标识符 YOUR_USER_DEFINED_FUNCTION_ID 要使用的用户定义的函数 ID YOUR_USER_DEFINED_FUNCTION_TYPE_ID 指定用户定义的函数类型的 ID ( UserDefinedFunctionId
)YOUR_ACCESS_CONTROL_PATH 访问控制路径
提示
有关用户定义的函数管理 API 操作和终结点的详细信息,请参阅文章如何创建和管理角色分配。
发送要处理的遥测数据
空间智能图中定义的传感器发送遥测。 反过来,遥测会触发已上传的用户定义函数的执行。 数据处理器将选取遥测数据。 然后,为调用用户定义的函数创建执行计划。
- 为生成读数的传感器检索匹配程序。
- 根据成功进行计算的匹配程序,检索相关联的用户定义函数。
- 执行每个用户定义函数。
后续步骤
了解如何创建 Azure 数字孪生终结点以向其发送事件。
若要了解 Azure 数字孪生中的路由的详细信息,请阅读路由事件和消息。
请查看客户端库参考文档。