Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Once you have a subscription setup (Azure Portal>All Services>Subscriptions), you will need to configure a resource group, an IoT hub, a device and generate a deviceSAS token.

Resource Group

Go to All Services>Resource groups and create one.

...

Chose Authentication type=Symmetric Keyand save the setting.

With this, the Azure part of the configuration is complete.

RouterOS configuration

note: In order to configure MQTT, make sure that iot package is installed beforehand.

SAS Token

In In our example, we are using KNOT as a gateway and a script (created specifically for the KNOT) to publish the data. In your specific application scenario, you can use any RouterOS device (with iot package installed) to post any data that you need.

Certificates

Since we are using an SSL connection, we will require the previously generated device certificate and its private key. We will also be using Baltimore CyberTrust Root certificate.

Go to the "Files" menu and add there the following certificates - Baltimore CyberTrust Root certificate, previously generated device certificate, and its private key.

Image Removed

Go to System>Certificates and import all 3 files (via the "Import" button - one by one):

Image Removed

note: Double-check that the "Common Name" matches the Device ID that was configured for the device on the Azure portal. In our case, the Device ID is "testor" and it matches the "Common Name" field.

Make sure that both certificates are trusted (T) and that the private key (K) was added to the device certificate.

MQTT Broker

Navigate to IoT>MQTT and add a new broker ("+" button):

Image Removed

  • Name the broker in the "Name" field (for example, Azure).
  • Type in/paste Azure hostname address into the "Address" field (you can find the hostname in the IoT Hub>Overview menu):

Image Removed

  • Configure the port used by the broker in the "Port" field and enable SSL via SSL checkbox (Azure, in this case, uses 8883 and, since we use certificates, it requires to enable SSL).
  • The "Username" field should be configured the following way - {iothubhostname}/{device_id}/?api-version=2018-06-30, where {iothubhostname} is the hostname for your IoT hub and {device_id} is the Device ID that was set up on the Azure portal (same as the "Common Name" for the certificate and in our example, it is "testor").
  • "Password" field is not required in this scenario (this configuration depends on the broker's settings - skip this field).
  • "Client Id" should be the same as the Device's ID (in our example, testor).
  • Since SSL is used, the certificate must be selected in the "Certificate" field (select the device certificate).

You can find more information about the required settings over here.

Click on "Apply" and "OK" to finish setting up the broker.

MQTT Publish with a script

will be using the Visual Studio Code program to generate the SAS token.

Simply, download the program and connect it to your IoT Hub.

When it is done and the previously configured device name shows up in your IoT HUB - right-click on the device name and generate the token as shown in the screenshot below:

Image Added

You will be asked to enter the expiration time (in hours) for the token and to press "enter" to confirm the setting.

After this step, the token should be generated in the "OUTPUT" field:

Image Added

Copy the token, as it is going to be used later in our HTTPS post script.


With this, the Azure part of the configuration is complete.

RouterOS configuration

In this guide, we are using KNOT as a gateway and a script (created specifically for the KNOT) to publish the data. In your specific application scenario, you can use any RouterOS device to post any data that you need.

HTTPS post with a script

HTTPS post can be achieved using the fetch tool. In order to post the In order to publish data from the Bluetooth tag (in our example, TG-BT5-INXX) to Azure, we will be using the script. Script example is shown below and can be downloaded using this link.

Every line that begins with the a symbol "#" is instructional and it describes the parameter that is going to be configured below the line. Change the parameters within quotation marks "" that would apply to your specific case.

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

:if ($advCount > 0) do={

    :set $btOldestAdvertisementTimestamp $lastAdvTimestamp

}

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

#################################### MQTT message #####################################
: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/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")

2 1 script lines line should be taken into account.

:local broker "Azure"

line, where you should specify the broker's name within the quotation marks "" (in our example, Azure).

:local topic "devices/testor/messages/events/"

:

/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"

Change the "{sas_token}" in the HTTP header to the token that was generated in the SAS Token section.

Change the {iot_hub_name} and {device_id} in the URL to the actual IoT Hub name and Device ID that were configured on the line, where you should specify the correct topic within the quotation marks "". The topic "devices/{device_id}/messages/events/" is used for publishing by Azure by default (as described in the manual here). Do not forget to change the {device_id} part to the "Device ID" that was configured on your Azure portal.

The rest of the script configuration depends on the overall requirements. The script explains which exact parameters are configured to be published.

...

There are many different ways to view the received/published message on the Azure portal. Please check Azure tutorials on the options you have.

In our example, we will verify the results We will be using the Visual Studio Code program to verify the results.Download the program and

connect it to Open your IoT Hub .Once the IoT Hub is added, you can and start monitoring the endpoint (the device):

Image RemovedImage Added

And you You can view published messages in the "OUTPUT" section as shown in the screenshot below. Just run the script and check the received message:

Image RemovedImage Added