HTTPS post and Azure configuration

本文将演示如何配置 Azure 和 RouterOS 以使用 HTTPS 协议发布数据。在此场景中,RouterOS 将充当网关,并将 BLEtag 广播的数据发布到云(Azure)。

简介

本文将演示如何配置 Azure 和 RouterOS 以使用 HTTPS 协议发布数据。在此场景中,RouterOS 将充当网关,并将 BLEtag 广播的数据发布到云(Azure)。

在继续设置之前,你需要在 Azure 系统中创建一个账户。你可以通过此链接找到有关如何操作的更多信息。

Azure 提供许多不同的选项和服务,其中许多选项/服务都有价目表。你可以通过此链接找到有关定价的更多信息。

Azure 配置

一旦你设置好订阅(Azure Portal>All Services>Subscriptions),你将需要配置一个资源组、一个 IoT hub、一个设备并生成一个 SAS token。

资源组

转到 All Services>Resource groups 并创建一个。

你可以通过此链接找到更详细的指南。

成功配置资源组后,你将需要创建一个 IoT hub。

IoT Hub

导航到 All services>IoT Hub 并创建一个。

将你的 IoT Hub 链接到之前创建的资源组。不要忘记勾选/设置 "Networking"(Network connectivity)和 Management(订阅层级)选项卡。

你可以通过此处找到更多信息。

设备

导航到你的 IoT Hub>IoT Devices 并添加一个新设备:

选择 Authentication type=Symmetric Key 并保存设置。

SAS Token

在我们的示例中,我们将使用 Visual Studio Code 程序来生成 SAS token。

只需下载该程序并将其连接到你的 IoT Hub。

完成后,之前配置的设备名称会出现在你的 IoT HUB 中 - 右键点击设备名称并生成 token,如下方截图所示:

系统将要求你输入 token 的过期时间(以小时为单位),然后按 "enter" 确认设置。

此步骤之后,token 应在 "OUTPUT" 字段中生成:

复制该 token,因为它稍后将在我们的 HTTPS post 脚本中使用。

至此,配置的 Azure 部分就完成了。

RouterOS 配置

在本指南中,我们使用 KNOT 作为网关,并使用一个脚本(专为 KNOT 创建)来发布数据。在你的特定应用场景中,你可以使用任何 RouterOS 设备来发布你需要的任何数据。

使用脚本进行 HTTPS post

可以使用 fetch 工具实现 HTTPS post。为了将 Bluetooth 标签(在我们的示例中为 TG-BT5-XX)的数据发布到 Azure,我们将使用脚本。脚本示例如下所示。

每一行以符号 # 开头的都是说明,它描述了将在该行下方配置的参数。将引号 "" 内的参数更改为适用于你特定情况的参数。

################################ Configuration ################################
## 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 ","
    }
}

:if ($advCount > 0) do={

    :set $btOldestAdvertisementTimestamp $lastAdvTimestamp

}

:put ("[*] Found $advCount new advertisements \
    (processing time: $[([/system clock get time] - $btProcessingStart)])")

#################################### message #####################################
:local message \
    "{\
        \"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")
/tool fetch http-method=post output=user http-header-field="authorization:{sas_token}" http-data=$message url="https://{iot_hub_name}.azure-devices.net/devices/{device_id}/messages/events\?api-version=2020-03-13"

:put ("[*] Done")

应考虑 1 行脚本:

/tool fetch http-method=post output=user http-header-field="authorization:{sas_token}" http-data=$message url="https://{iot_hub_name}.azure-devices.net/devices/{device_id}/messages/events\?api-version=2020-03-13"

将 HTTP 头中的 {sas_token} 更改为在 SAS Token 部分生成的 token。

将 URL 中的 {iot_hub_name} 和 {device_id} 更改为在 Azure 门户上配置的实际 IoT Hub 名称和 Device ID。

脚本配置的其余部分取决于整体需求。脚本解释了哪些确切参数被配置为发布。

导航到 System>Scripts,在那里添加一个新脚本,并粘贴上方显示的脚本(例如,将其命名为 script1)。

要运行脚本,你可以使用命令行:

/system script run script1

验证

在 Azure 门户上查看收到/发布的消息有许多不同的方法。请查看 Azure 教程了解你可用的选项。

我们将使用 Visual Studio Code 程序来验证结果。

打开你的 IoT Hub 并开始监控端点(设备):

你可以在 "OUTPUT" 部分查看已发布的消息,如下方截图所示。只需运行脚本并检查收到的消息: