You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 28 Next »

Introduction

Our TG-BT5-OUT Bluetooth tag model has a temperature sensor built in. This means that it can be used to measure the surrounding temperature.

The temperature's value is "written" into the advertising payload that the tag is going to broadcast over Bluetooth advertising channels. Based on how you configure the tag, the tag can broadcast the payload periodically or/and when a trigger is detected. You can find more information about the tag's configuration options in iOS and Android Beacon Manager guides.

You can see/display the payloads using our KNOT model under IoT>Bluetooth>Advertising reports tab:

The payloads will be shown in the "Advertisement (hex)" field and they will be in the hexadecimal format.

When the tag is configured in the MikroTik format, the payload's 14th and 15th octets indicate the temperature (ambient temperature in Celsius in signed 8.8 fixed point format) that was "sensed" at the moment of the broadcast.

An example of the payload in MikroTik's format is shown below:

15ff4f09010032a500000000ffff 5019 bd5954000061

Please note that all multi-byte values in the payload are in little-endian. So, if #14 and #15 octets indicate the temperature as "50 19" → the decimal temperature value is going to be (0x1950)/256 = 25.31 C.

With this knowledge, we can then utilize RouterOS scripting to structure a message out of the received payloads and send it to the MQTT/HTTP server. The server will be responsible for the data conversion from hexadecimal format to decimal format. In this guide, we will achieve the results using MQTT post to ThingsBoard.

ThingsBoard server and MQTT configuration

You will require to have a ThingsBoard server up and running. You can find useful information on how to set up your server by following the link. You can install the server locally onto a machine or use their cloud solution.

After you have the server ready, you will need to configure it to be able to receive MQTT messages. Please follow the "ThingsBoard configuration" link to set up your "device".

RouterOS configuration

Please check the link over here on how you can set up your MQTT broker depending on the device credential used by the ThingsBoard server.

After setting up your broker, confirm that the Bluetooth tag is broadcasting information as shown in the picture above under the IoT>Bluetooth>Advertising reports tab.

Paste in the script below (under System>Scripts>Add):

# Required packages: iot

################################ Configuration ################################
# Name of an existing MQTT broker that should be used for publishing
 :local broker "tb"

# MQTT topic where the message should be published
 :local topic "v1/devices/me/telemetry"

 # 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 "2C:C8:1B:4B:BB:0A"

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

#################################### 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 tempf [:pick ($adv->"data") 28 32]
    :local temp ("0x".[:pick $tempf 2 4].[:pick $tempf 0 2])
    :local obj "{\
        \
           \"ts\":$ts,\
           \"values\":{\
            \"id\":\"$[$minimizeMac address=$address]\",\
            \"rssi\":\"$rssi\",\
            \"temp\":\"$temp\",\
            \"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 #####################################
:local message \
    "[$advJson]"
: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")

Change the broker's name that you have chosen for the MQTT broker within the quotation marks (in our example, we called it tb):

 :local broker "tb"

The default topic used by the ThingsBoard is (you do not have to change it):

 :local topic "v1/devices/me/telemetry"

Change the MAC address of the tag that you wish to monitor (in our example, we have the MAC address 2C:C8:1B:4B:BB:0A):

:local addressRegex "2C:C8:1B:4B:BB:0A"

The lines below will take the payload's 14th and 15th octets and "re-structure" the values from "ABCD" to "0xCDAB" (per our example from the Introduction section, from "5019" to "0x1950"):

    :local tempf [:pick ($adv->"data") 28 32]

    :local temp ("0x".[:pick $tempf 2 4].[:pick $tempf 0 2])

The MQTT message that we are posting is structured in the following section (you do not have to change it):

    :local obj "{\

        \

           \"ts\":$ts,\

           \"values\":{\

            \"id\":\"$[$minimizeMac address=$address]\",\

            \"rssi\":\"$rssi\",\

            \"temp\":\"$temp\",\

            \"ad\":\"$ad\"\

            }\

        }"

The message that is structured per the example above will be displayed in JSON as (the only real value that we are going to be using are "timestamp"→ "ts" and "temperature"→ "temp" in hexadecimal format, so feel free to remove additional parameters):

[

  {

    "ts": 1661333913375,

    "values": {

      "id": "2CC81B4BBB0A",

      "rssi": "-43",

      "temp": "0x1939",

      "ad": "15ff4f0901002de0ffff010000003919877c54000061"

    }

  }

]

Save the script and run it:

[admin@MikroTik] > system script run name_of_the_script
[*] Gathering system info...
[*] Gathering Bluetooth info...
[*] Found 1 new advertisements (processing time: 00:00:00)
[*] Total message size: 134 bytes
[*] Sending message to MQTT broker...

[*] Done
[admin@MikroTik] > 

You will be able to verify the results under the Latest telemetry section under the device you have created for ThingsBoard (in our example, we called the "device" KNOT):

The result is a successful MQTT post!

But! we would like to display the temperature (temp parameter) in decimal format and we would also like to display the data easier to perceive. This is where "Widgets" come into play.

ThingsBoard widgets

  • No labels