MQTT and Azure configuration
将 MikroTik MQTT 数据发布到 Microsoft Azure IoT,涵盖 Azure 账户设置、设备凭据和 MQTT broker 配置。
简介
可用于监控 MQTT 发布者发送的信息的众多云服务之一是 Microsoft Azure。本文将演示如何配置 Azure 和 RouterOS 以使用 MQTT 协议发布数据。在此场景中,RouterOS 将充当网关,并将 BLEtag 广播的数据发布到云(Azure)。在此场景中,Azure 将充当 MQTT broker 和 MQTT 订阅者(数据将被发布/显示的服务器)。
在继续设置之前,你需要在 Azure 系统中创建一个账户。你可以通过此链接找到有关如何操作的更多信息。
Azure 提供许多不同的选项和服务,其中许多选项/服务都有价目表。你可以通过此链接找到有关定价的更多信息。
Azure 配置
一旦你设置好订阅(Azure Portal>All Services>Subscriptions),你将需要配置一个资源组、一个 IoT hub、一个证书和一个设备。
资源组
转到 All Services>Resource groups 并创建一个。

将你的 IoT Hub 链接到之前创建的资源组。不要忘记勾选/设置 "Networking"(Network connectivity)和 Management(订阅层级)选项卡。
你可以通过此处找到更多信息。
IoT Hub
导航到 All services>IoT Hub 并创建一个。

将你的 IoT Hub 链接到之前创建的资源组。不要忘记勾选/设置 "Networking"(Network connectivity)和 Management(订阅层级)选项卡。
你可以在此处找到更多信息。
证书
在此示例中,我们将重点介绍 X.509 CA-signed 身份验证。
你可以使用 Microsoft 提供的脚本)或 open SSL 来生成测试证书。
生成 RootCA 后,转到 IoT Hub>Certificates 并在那里添加证书:

成功添加 RootCA 后,你将需要证明所有权(验证它)。
如果你使用的是脚本,教程(步骤 3)中有很好的描述和展示;如果你使用的是 open ssl,则参见教程(步骤 7)。
一旦证书成功验证,你将需要创建设备证书(或者如果你使用的是 open ssl,请遵循此链接)。
设备
导航到你的 IoT Hub>IoT Devices 并添加一个新设备:

注意 "Device ID" 字段。Device ID 应与设备证书的 "Common name" 匹配。
选择 Authentication type=X.509 CA Signed 并保存设置。
现在你可以生成最后一个所需的证书 - 设备证书(或者如果你使用的是 open ssl,请遵循此链接)。
至此,配置的 Azure 部分就完成了。
RouterOS 配置
信息
为了配置 MQTT,请确保事先安装了 iot 软件包。 在我们的示例中,我们使用 KNOT 作为网关,并使用一个脚本(专为 KNOT 创建)来发布数据。在你的特定应用场景中,你可以使用任何 RouterOS 设备(已安装 iot 软件包)来发布你需要的任何数据。
证书
由于我们使用 SSL 连接,我们将需要之前生成的设备证书及其私钥。我们还将使用 Baltimore CyberTrust Root 证书。
转到 "Files" 菜单并在那里添加以下证书 - Baltimore CyberTrust Root 证书、之前生成的设备证书及其私钥。

转到 System>Certificates 并导入全部 3 个文件(通过 "Import" 按钮 - 逐个导入):

信息
再次确认 "Common Name" 与在 Azure 门户上为该设备配置的 Device ID 匹配。在我们的例子中,Device ID 是 "testor",它与 "Common Name" 字段匹配。 确保两个证书都是受信任的(T),并且私钥(K)已添加到设备证书中。
MQTT Broker
导航到 IoT>MQTT 并添加一个新 broker("+" 按钮):

- 在 "Name" 字段中为 broker 命名(例如,Azure)。
- 在 "Address" 字段中输入/粘贴 Azure 主机名地址(你可以在 IoT Hub>Overview 菜单中找到主机名):

- 在 "Port" 字段中配置 broker 使用的端口,并通过 SSL 复选框启用 SSL(在这种情况下,Azure 使用 8883,并且由于我们使用证书,它要求启用 SSL)。
- "Username" 字段应按以下方式配置 -
{iothubhostname}/{device_id}/?api-version=2018-06-30,其中{iothubhostname}是你 IoT hub 的主机名,{device_id}是在 Azure 门户上设置的 Device ID(与证书的 "Common Name" 相同,在我们的示例中为 "testor")。 - 在此场景中不需要 "Password" 字段(此配置取决于 broker 的设置 - 跳过此字段)。
- "Client Id" 应与设备的 ID 相同(在我们的示例中为 testor)。
- 由于使用了 SSL,必须在 "Certificate" 字段中选择证书(选择设备证书)。
你可以通过此处找到有关所需设置的更多信息。
点击 "Apply" 和 "OK" 完成 broker 的设置。
使用脚本进行 MQTT Publish
为了将 Bluetooth 标签(在我们的示例中为 TG-BT5-IN)的数据发布到 Azure,我们将使用脚本。脚本示例如下所示。
每一行以符号 # 开头的都是说明,它描述了将在该行下方配置的参数。将引号 "" 内的参数更改为适用于你特定情况的参数。
## Required packages: iot
################################ Configuration ################################
## Name of an existing MQTT broker that should be used for publishing
:local broker "Azure"
## MQTT topic where the message should be published
:local topic "devices/testor/messages/events/"
## Interface whose MAC should be used as 'Locator ID'
:local locatorIface "ether1"
## POSIX regex for filtering advertisement Bluetooth addresses. E.g. "^BC:33:AC"
## would only include addresses which start with those 3 octets.
## To disable this filter, set it to ""
:local addressRegex ""
## POSIX regex for filtering Bluetooth advertisements based on their data. Same
## usage as with 'addressRegex'.
:local advertisingDataRegex ""
## Signal strength filter. E.g. -40 would only include Bluetooth advertisements
## whose signal strength is stronger than -40dBm.
## To disable this filter, set it to ""
:local rssiThreshold "-40"
#################################### System ###################################
:put ("[*] Gathering system info...")
:local ifaceMac [/interface get [/interface find name=$locatorIface] mac-address]
:local cpuLoad [/system resource get cpu-load]
:local freeMemory [/system resource get free-memory]
:local usedMemory ([/system resource get total-memory] - $freeMemory)
:local rosVersion [/system package get value-name=version \
[/system package find where name ~ "^routeros"]]
:local model [/system routerboard get value-name=model]
:local serialNumber [/system routerboard get value-name=serial-number]
## Health is a bit iffy since '/system health' does not have 'find' in ROS6
:local health [/system health print as-value]
:local supplyVoltage 0
:local boardTemp 0
:foreach entry in=$health do={
:if ($entry->"name" = "voltage") do={:set $supplyVoltage ($entry->"value")}
:if ($entry->"name" = "board-temperature1") do={:set $boardTemp ($entry->"value")}
}
################################## Bluetooth ##################################
:put ("[*] Gathering Bluetooth info...")
:global btOldestAdvertisementTimestamp
:if ([:typeof $btOldestAdvertisementTimestamp] = "nothing") do={
# First time this script has been run since booting, need to initialize
# persistent variables
:set $btOldestAdvertisementTimestamp 0
}
:local btProcessingStart [/system clock get time]
:local advertisements [/iot bluetooth scanners advertisements print detail \
as-value where \
epoch > $btOldestAdvertisementTimestamp and \
address ~ $addressRegex and \
data ~ $advertisingDataRegex and \
rssi > $rssiThreshold
]
:local advJson ""
:local advCount 0
:local advSeparator ""
:local lastAdvTimestamp 0
## Remove semicolons from MAC/Bluetooth addresses
:local minimizeMac do={
:local minimized
:local lastIdx ([:len $address] - 1)
:for idx from=0 to=$lastIdx step=1 do={
:local char [:pick $address $idx]
:if ($char != ":") do={
:set $minimized "$minimized$char"
}
}
:return $minimized
}
:foreach adv in=$advertisements do={
:local address ($adv->"address")
:local ts ($adv->"epoch")
:local rssi ($adv->"rssi")
:local ad ($adv->"data")
:local obj "\
{\
\"id\":\"$[$minimizeMac address=$address]\",\
\"ts\":$ts,\
\"rssi\":$rssi,\
\"ed\":{\
\"ad\":\"$ad\"\
}\
}"
:set $advCount ($advCount + 1)
:set $lastAdvTimestamp $ts
# Ensure that the last object is not terminated by a comma
:set $advJson "$advJson$advSeparator$obj"
:if ($advSeparator = "") do={
:set $advSeparator ","
}
}
:set $btOldestAdvertisementTimestamp $lastAdvTimestamp
:put ("[*] Found $advCount new advertisements \
(processing time: $[([/system clock get time] - $btProcessingStart)])")
#################################### MQTT #####################################
:local message \
"{\
\"clientId\":\"$[/iot mqtt brokers get value-name=client-id \
[/iot mqtt brokers find name=$broker]]\",\
\"t\":0,\
\"v\":1,\
\"OldestAdvertisementTimestamp\":$btOldestAdvertisementTimestamp,\
\"locs\":[{\
\"id\":\"$[$minimizeMac address=$ifaceMac]\",\
\"tags\":[$advJson],\
\"ed\":{\
\"model\":\"$model\",\
\"sn\":\"$serialNumber\",\
\"ros\":\"$rosVersion\",\
\"cpu\":$cpuLoad,\
\"umem\":$usedMemory,\
\"fmem\":$freeMemory,\
\"psu\":$supplyVoltage,\
\"temp\":$boardTemp\
}\
}]\
}"
:log info "$message";
:put ("[*] Total message size: $[:len $message] bytes")
:put ("[*] Sending message to MQTT broker...")
/iot mqtt publish broker=$broker topic=$topic message=$message
:put ("[*] Done")
应考虑 2 行脚本:
:local broker "Azure"
该行,你应该在引号 "" 内指定 broker 的名称(在我们的示例中为 Azure)。
:local topic "devices/testor/messages/events/"
该行,你应该在引号 "" 内指定正确的 topic。Azure 默认使用 topic devices/{device_id}/messages/events/ 进行发布(如此处手册所述)。不要忘记将 {device_id} 部分更改为在 Azure 门户上配置的 "Device ID"。
脚本配置的其余部分取决于整体需求。脚本解释了哪些确切参数被配置为发布。
导航到 System>Scripts,在那里添加一个新脚本,并粘贴上方显示的脚本(例如,将其命名为 script1)。
要运行脚本,你可以使用命令行:
/system script run script1
验证
在 Azure 门户上查看收到/发布的消息有许多不同的方法。请查看 Azure 教程了解你可用的选项。
在我们的示例中,我们将使用 Visual Studio Code 程序验证结果。
下载该程序并将其连接到你的 IoT Hub。
一旦添加了 IoT Hub,你就可以开始监控端点:

你可以在 "OUTPUT" 部分查看已发布的消息,如下方截图所示:
