你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
IoT Central 设备网桥是一种开源解决方案,用于将其他 IoT 云(如 Sigfox、 Particle Device Cloud 和 Things Network )连接到 IoT Central 应用程序。 设备网桥的工作原理是将数据从连接到其他 IoT 云的设备转发到 IoT Central 应用程序。 设备网桥仅将数据转发到 IoT Central,它不会将命令或属性更新从 IoT Central 发送回设备。
通过设备网桥,可将 IoT Central 的强大功能与以下设备相结合:
- 连接到 Sigfox 低功率广域网的资产跟踪设备。
- 粒子设备云上的空气质量监测设备。
- 事物网络上的土壤湿度监测设备。
可以使用 IoT Central 应用程序功能,例如对数据的规则和分析、在 Power Automate 和 Azure 逻辑应用中创建工作流,或导出数据。
设备网桥解决方案将多个 Azure 资源预配到 Azure 订阅中,这些资源协同工作,将设备消息转换和转发到 IoT Central。
先决条件
若要完成本作指南中的步骤,需要:
有效的 Azure 订阅。 如果没有 Azure 订阅,请在开始之前创建一个免费帐户。
从 自定义应用程序 模板创建的 IoT Central 应用程序。 若要了解详细信息,请参阅创建 IoT Central 应用程序以及如何获取有关应用程序的信息?
概述
IoT Central 设备网桥是 GitHub 中的开源解决方案。 它使用自定义 Azure 资源管理器模板将多个资源部署到 Azure 订阅,包括 Azure Functions 中的函数应用。
函数应用是设备网桥的核心部分。 它通过简单的 Webhook 从其他 IoT 平台接收 HTTP POST 请求。 Azure IoT Central Device Bridge 存储库包含演示如何连接 Sigfox、Particle 和 Things Network 云的示例。 如果平台可以将 HTTP POST 请求发送到函数应用,则可以扩展此解决方案以连接到自定义 IoT 云。
函数应用将数据转换为 IoT Central 接受的格式,并使用设备预配服务和设备客户端 API 转发数据:
如果 IoT Central 应用程序识别转发消息中的设备 ID,则来自设备的遥测数据会显示在 IoT Central 中。 如果 IoT Central 应用程序无法找到设备 ID,函数应用将尝试使用该设备 ID 注册新设备。 新设备在 IoT Central 应用程序中“设备”页上显示为“未分配”设备。 在 “设备” 页中,可以将新设备分配到设备模板,然后查看遥测数据。
部署设备网桥
要将设备网桥部署到您的订阅中:
在 IoT Central 应用程序中,导航到 “权限 > 设备连接组 ”页。
记下 ID 范围。 部署设备网桥时,请使用此值。
在同一页中,打开 SAS-IoT-Devices 注册组。 在 SAS-IoT-Devices 组页上,复制 主密钥。 部署设备网桥时,请使用此值。
使用以下 “部署到 Azure ”按钮打开将函数应用部署到订阅的自定义资源管理器模板。 使用上一步中的 ID 范围 和 主键 :
部署完成后,需要安装函数所需的 npm 包:
在 Azure 门户中,打开部署到您的订阅的函数应用。 然后,转到 开发工具>控制台。 在控制台中运行以下命令以安装包:
cd IoTCIntegration npm install这些命令可能需要几分钟才能运行。 可以安全地忽略任何警告消息。
包安装完成后,在函数应用的“概述”页上选择“重启”:
函数现已可供使用。 外部系统可以使用 HTTP POST 请求通过设备网桥将设备数据发送到 IoT Central 应用程序。 若要获取函数 URL,请导航到 Functions > IoTCIntegration > Code + Test > 获取函数 URL:
发送到设备网桥的消息正文必须采用以下格式:
"device": {
"deviceId": "my-cloud-device"
},
"measurements": {
"temp": 20.31,
"pressure": 50,
"humidity": 8.5,
"ledColor": "blue"
}
对象中的每个 measurements 密钥必须与 IoT Central 应用程序中设备模板中的遥测类型的名称匹配。 此解决方案不支持在消息正文中指定接口 ID。 因此,如果两个不同的接口具有具有相同名称的遥测类型,则度量值将显示在 IoT Central 应用程序中的两个遥测流中。
可以在正文中包含一个 timestamp 字段,以指定邮件的 UTC 日期和时间。 此字段必须采用 ISO 8601 格式。 例如,2020-06-08T20:16:54.602Z。 如果未包含时间戳,则使用当前日期和时间。
可以在正文中包含字段 modelId 。 使用此字段在预配期间将设备分配到设备模板。
deviceId 必须为字母数字、小写字母,并且可以包含连字符。
如果未包含 modelId 该字段,或者 IoT Central 无法识别模型 ID,则无法识别 deviceId 的消息会在 IoT Central 中创建新的 未分配设备 。 操作员可以手动将设备迁移到正确的设备模板。 若要了解详细信息,请参阅 在 Azure IoT Central 应用程序中 > 管理设备,将设备迁移到模板。
注释
在将设备分配给模板之前,对函数的所有 HTTP 调用都会返回 403 错误状态。
若要通过 Application Insights 开启函数应用的日志记录功能,请在 Azure 门户导航到函数应用中的“监视”>“日志”。 选择 “打开 Application Insights”。
预配的资源
资源管理器模板在 Azure 订阅中预配以下资源:
- 函数应用
- App Service 计划
- 存储帐户
- 密钥保管库
密钥保管库存储 IoT Central 应用程序的 SAS 组密钥。
函数应用在 消耗计划中运行。 虽然此选项不提供专用计算资源,但它使设备网桥可以处理每分钟数百条设备消息,适合较小的设备群或不太频繁发送消息的设备。 如果应用程序依赖于流式传输大量设备消息,请将消耗计划替换为专用 应用服务计划。 此计划提供专用计算资源,可加快服务器响应时间。 使用标准应用服务计划,此存储库中 Azure 中函数的最大观测性能约为每分钟 1,500 条设备消息。 若要了解详细信息,请参阅 Azure Functions 托管选项。
若要使用专用应用服务计划而不是消耗计划,请先编辑自定义模板,然后再部署。 选择“编辑模板”。
替换以下段:
{
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2015-04-01",
"name": "[variables('planName')]",
"location": "[resourceGroup().location]",
"properties": {
"name": "[variables('planName')]",
"computeMode": "Dynamic",
"sku": "Dynamic"
}
},
替换为:
{
"type": "Microsoft.Web/serverfarms",
"sku": {
"name": "S1",
"tier": "Standard",
"size": "S1",
"family": "S",
"capacity": 1
},
"kind": "app",
"name": "[variables('planName')]",
"apiVersion": "2016-09-01",
"location": "[resourceGroup().location]",
"tags": {
"iotCentral": "device-bridge",
"iotCentralDeviceBridge": "app-service-plan"
},
"properties": {
"name": "[variables('planName')]"
}
},
接下来,编辑模板,使 "alwaysOn": true 下的 functionapp 资源的配置中包含 "properties": {"SiteConfig": {...}}。alwaysOn 配置确保函数应用始终处于运行状态。
例子
以下示例概述了如何为各种 IoT 云配置设备网桥:
示例 1:通过设备桥连接粒子设备
若要通过设备桥将 Particle 设备连接到 IoT Central,请转到 Particle 控制台并创建新的 Webhook 集成。 将 请求格式 设置为 JSON。 在 “高级设置”下,使用以下自定义正文格式:
{
"device": {
"deviceId": "{{{PARTICLE_DEVICE_ID}}}"
},
"measurements": {
"{{{PARTICLE_EVENT_NAME}}}": "{{{PARTICLE_EVENT_VALUE}}}"
}
}
粘贴函数应用中的 函数 URL ,可以看到粒子设备在 IoT Central 中显示为未分配的设备。 若要了解详细信息,请参阅 下面介绍如何将粒子驱动的项目与 Azure IoT Central 博客文章集成。
示例 2:通过设备桥连接 Sigfox 设备
某些平台可能不允许指定通过 Webhook 发送的设备消息的格式。 对于此类系统,必须在设备桥处理消息之前将消息有效负载转换为预期的正文格式。 可以在运行设备桥的同一函数中执行转换。
本部分介绍如何将 Sigfox Webhook 集成的有效负载转换为设备网桥所需的正文格式。 Sigfox 云以十六进制字符串格式传输设备数据。 为方便起见,设备网桥包含一个此格式的转换函数,该函数接受 Sigfox 设备有效负载中可能的字段类型的子集:8、16、32 或 64 位的 int 和 uint,32 位或 64 位的 float,little-endian 和 big-endian。 若要处理来自 Sigfox webhook 集成的消息,请对函数应用中的 IoTCIntegration/index.js 文件进行以下更改。
若要转换消息有效负载,请在第 21 行调用 handleMessage 之前添加以下代码,并将 payloadDefinition 替换为你的 Sigfox 有效负载定义。
const payloadDefinition = 'gforce::uint:8 lat::uint:8 lon::uint:16'; // Replace this with your payload definition
req.body = {
device: {
deviceId: req.body.device
},
measurements: require('./converters/sigfox')(payloadDefinition, req.body.data)
};
Sigfox 设备需要 204 响应代码。 在调用 handleMessage 第 21 行后添加以下代码:
context.res = {
status: 204
};
示例 3:通过设备网桥连接设备
将物联网网络设备连接到 IoT Central:
- 将新的 HTTP 集成添加到 The Things Network 中的应用程序:“应用程序”>“集成”>“添加集成”>“HTTP 集成”。
- 请确保应用程序包含一个解码器函数,该函数在将设备消息的有效负载发送到函数之前自动将设备消息的有效负载转换为 JSON: 应用程序 > 有效负载函数 > 解码器。
以下示例演示了一个 JavaScript 解码器函数,可用于从二进制数据解码常见数值类型:
function Decoder(bytes, port) {
function bytesToFloat(bytes, decimalPlaces) {
var bits = (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | bytes[0];
var sign = (bits >>> 31 === 0) ? 1.0 : -1.0;
var e = bits >>> 23 & 0xff;
var m = (e === 0) ? (bits & 0x7fffff) << 1 : (bits & 0x7fffff) | 0x800000;
var f = Math.round((sign * m * Math.pow(2, e - 150)) * Math.pow(10, decimalPlaces)) / Math.pow(10, decimalPlaces);
return f;
}
function bytesToInt32(bytes, signed) {
var bits = bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
var sign = 1;
if (signed && bits >>> 31 === 1) {
sign = -1;
bits = bits & 0x7FFFFFFF;
}
return bits * sign;
}
function bytesToShort(bytes, signed) {
var bits = bytes[0] | (bytes[1] << 8);
var sign = 1;
if (signed && bits >>> 15 === 1) {
sign = -1;
bits = bits & 0x7FFF;
}
return bits * sign;
}
return {
temperature: bytesToFloat(bytes.slice(0, 4), 2),
presscounter: bytesToInt32(bytes.slice(4, 8), true),
blueLux: bytesToShort(bytes.slice(8, 10), false)
};
}
定义集成后,请在调用handleMessage函数应用的 IoTCIntegration/index.js 文件第 21 行之前添加以下代码。 此代码将 HTTP 集成的正文转换为预期格式。
req.body = {
device: {
deviceId: req.body.end_device_ids.device_id.toLowerCase()
},
measurements: req.body.uplink_message.decoded_payload
};
注释
前面的代码片段使用用户友好的设备 ID。 The Things Network 消息还包括一个技术 ID,你可以使用 req.body.dev_eui.toLowerCase() 进行访问。 若要了解详细信息,请参阅 “内容网络 - 数据格式”。
局限性
设备网桥仅将消息转发到 IoT Central,不会将消息发送回设备。 此限制是属性和命令不适用于通过此设备桥连接到 IoT Central 的设备的原因。 由于不支持设备孪生操作,因此无法通过设备桥更新设备属性。 若要使用这些功能,设备必须使用其中一个 Azure IoT 设备 SDK 直接连接到 IoT Central。