Versions Compared

Key

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

...

  1. The KNOT will run a script on a schedule. 
  2. The script will "read/scan" the payloads that are shown in the IoT>Bluetooth>Advertising reports tab.
  3. If the stored/captured payload's 21st octet value equals the configured trigger value (which is set up in the script) to any "triggered" value → email notification is going to be sent.

In other words, when the KNOT scans through the payloads and finds one where the 21st octet equals indicates that the configured trigger value was activated → you will get an email notification that the trigger was detected.

...

You can find a manual on how to enable the triggers by following the iOS and/or Android guides ("Advertisement"/Beacon settings sections).

In our example, we would like to monitor "freefalling" state detection, so just enable the checkbox for the "Freefall trigger/detection". You can use other triggers instead but you will need to alter a couple of lines in the script that will be shown later.

To easier "activate" the trigger, we can also alter the trigger's To easier "activate" the trigger, we can also alter the trigger's settings as per the iOS and/or Android guides (Free Fall Threshold and Duration sections). For the purpose of the test and to, basically, just "trigger" the detection "easier"much faster, we can change the "Free Fall ThresholdDuration" to the maximally available value (this will result in any acceleration within this threshold on all axis to be considered a "trigger"). We can also change the "Free Fall Duration" parameter to "0" seconds, for the purpose of the test parameter to "0" seconds (this will make sure that any acceleration that is within the threshold on all axis will be instantly detected as a "freefalling" event).

...

Try sending a test email to make sure that it is set up correctly.

System>Scripts

...

Option (a

...

)

Navigate to System>Scripts menu and add a new script there.

You can copy the script below. Copy the script below into a "notepad" and copy it again into the script "Source:" field.

#User configuration:

#input the tag's mac address that you wish to monitor within the # Input MAC address of the tag within ""
:local addressRegex "2C:C8:1B:4BE2:BC15:4E29"

#enter trigger value, for example "04" for freefalling trigger and "02" for tilt trigger detectionthe subject for the email within the ""
:local triggervalue emailsubject "04RouterOS report!"

#enter the email address wthin the ""#name the trigger accordingly
:local triggername "freefalling"

#enter the message for the email body that you wish to receive within the ""
:local emailmessage "Our tag fell down!"

#enter the subject for the email within the ""
:local emailsubject "RouterOS report!"

#enter the email address wthin the ""
:local emailaddress "YOUR_EMAIL@gmail.com"

###Bluetooth scanner:

:local trigger
:put ("[*] Gathering Bluetooth info...")
:global btOldestAdvertisementTimestamp
:if ([:typeof $btOldestAdvertisementTimestamp] = "nothing") do={: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]
:local advCount 0
:local lastAdvTimestamp 0

:foreach adv in=$advertisements do={
       :local address ($adv->"address")
       :local ad ($adv->"data")
       :local ts ($adv->"epoch")
       :local trig [:pick ($adv->"data") 40 42]
       :set $advCount ($advCount + 1)
       :set $lastAdvTimestamp $ts
       :if ($trig="$triggervalue") do={:set trigger "$triggername"}
       :if ($advCount > 0) do={:set $btOldestAdvertisementTimestamp $lastAdvTimestamp}}

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

###Result
:if ($trigger="$triggername") do={/tool e-mail send to=$emailaddress subject="$emailsubject" body="$emailmessage"}

The following 6 lines need to be taken into account:

:local addressRegex "2C:C8:1B:4B:BC:4E"

line, where you need to input the MAC address of the tag that you wish to monitor.

:local triggervalue "04"

line, where you need to input the value of the 21st payload's octet that you wish to scan for. In this example, we want to scan for the "freefalling" trigger and that means scanning for the "04" value.

If we want to scan for a "tilt" trigger → we will need to change the trigger value to "02" instead.

If we want to scan for the "movement/wakeup" trigger → please note, that movement against different axis (x,y,z) will have its own different "value" triggered. So, for example, impact only on the x-axis will be "08", impact on the y-axis will be "10", impact on the z-axis will be "20", impact on the x-axis and y-axis will be "18" and impact on all axis at the same time will be "38".

The script example for scanning multiple triggers with 1 script will be shown later in the guide.

:local triggername "freefalling"

line, where you just need to name the trigger (however you like). So if you choose "04" in the previously mentioned → :local triggervalue "04" ← line, you can name it "freefalling".

If you want to monitor "tilting" and you've set up → :local triggervalue "02", name it "tilting" or something similar.

:local emailmessage "Our tag fell down!"

line, where you can alter the e-mail message/content within the quotation marks. Type in any message that you wish to send in case the trigger was detected.

:local emailsubject "RouterOS report!"

line, where can alter the subject for the email.

:local emailaddress "YOUR_EMAIL@gmail.com"

and, lastly, the email address line, where you need to input the email address. To where do you want to send the report?

The rest of the script does not need to be changed.

Name the script however you like, for example, triggernotification. Click on Apply and OK.

Info
titleAdditionally

In this example, we are specifically showcasing an e-mail notification scenario. But! in case you want to use other methods for sending a notification, you can just alter the line below:

:if ($trigger="$triggername") do={/tool e-mail send to=$emailaddress subject="$emailsubject" body="$emailmessage"}

You can change the "do={/tool e-mail..." part of the line to, for example, "do={/tool fetch..." or "do={/iot mqtt publish...". That way, you can send out an HTTP post or MQTT publish message instead.

If you would like to get a phone notification when the trigger is detected, you can also utilize IFTTT services (HTTP post to IFTTT webhook) as described in our other guide over here.

You can run the script manually via the command "/system script run triggernotification" or by clicking on the "Run Script" button under the Script List section.

You should make sure that the e-mail notification was received after manually initiating the script.

Monitoring multiple triggers

emailaddress "YOUR_EMAIL@gmail.com"

#Script:
################################## Bluetooth ##################################
:local flagStr do={
    :local str ""

    :if ($1 & 0x01) do={ :set $str " switch" }
    :if ($1 & 0x02) do={ :set $str "$str tilt" }
    :if ($1 & 0x04) do={ :set $str "$str free_fall" }
    :if ($1 & 0x08) do={ :set $str "$str impact_x" }
    :if ($1 & 0x10) do={ :set $str "$str impact_y" }
    :if ($1 & 0x20) do={ :set $str "$str impact_z" }

    :if ([:len $str] = 0) do={ :return "" }

    :return [:pick $str 1 [:len $str]]
}

:local triggernameF "free_fall"
:local triggernameT "tilt"
:local triggernameX "impact_x"
:local triggernameY "impact_y"
:local triggernameZ "impact_z"
:local triggernameS "switch"

# Find fresh Bluetooth advertisements
: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 advertisements [/iot bluetooth scanners advertisements print detail \
    as-value where \
        epoch > $btOldestAdvertisementTimestamp and \
        address ~ $addressRegex
]
:local advCount 0
:local lastAdvTimestamp 0
:local triggerlist ""

:local triggerF
:local triggerT
:local triggerX
:local triggerY
:local triggerZ
:local triggerS

:local messageF ""
:local messageT ""
:local messageX ""
:local messageY ""
:local messageZ ""
:local messageS ""

:local 21st ""

:foreach adv in=$advertisements do={
    :local address ($adv->"address")
    :local rssi ($adv->"rssi")
    :local epoch ($adv->"epoch")
    :local rtime ($adv->"time")
    :local ad ($adv->"data")
    :local flags [:tonum "0x$[:pick $ad 40 42]"]
    :local obj "$[$flagStr $flags]"

    :set $advCount ($advCount + 1)
    :set $lastAdvTimestamp $epoch
    :set $triggerlist "$triggerlist$obj"

:set triggerF [:pick $triggerlist ([find $triggerlist "free_fall"]-0) ([find $triggerlist "free_fall"]+9)]
:if ($triggerF=$triggernameF) do={:set messageF "$triggernameF";:set 21st "not00";}
:set triggerT [:pick $triggerlist ([find $triggerlist "tilt"]-0) ([find $triggerlist "tilt"]+4)]
:if ($triggerT=$triggernameT) do={:set messageT "$triggernameT";:set 21st "not00";}
:set triggerX [:pick $triggerlist ([find $triggerlist "impact_x"]-0) ([find $triggerlist "impact_x"]+8)]
:if ($triggerX=$triggernameX) do={:set messageX "$triggernameX";:set 21st "not00";}
:set triggerY [:pick $triggerlist ([find $triggerlist "impact_y"]-0) ([find $triggerlist "impact_y"]+8)]
:if ($triggerY=$triggernameY) do={:set messageY "$triggernameY";:set 21st "not00";}
:set triggerZ [:pick $triggerlist ([find $triggerlist "impact_z"]-0) ([find $triggerlist "impact_z"]+8)]
:if ($triggerZ=$triggernameZ) do={:set messageZ "$triggernameZ";:set 21st "not00";}
:set triggerS [:pick $triggerlist ([find $triggerlist "switch"]-0) ([find $triggerlist "switch"]+6)]
:if ($triggerS=$triggernameS) do={:set messageS "$triggernameS";:set 21st "not00";}

}
:if ($advCount > 0) do={
    :set $btOldestAdvertisementTimestamp $lastAdvTimestamp
}

#Message structure:
:local message "$messageF
$messageT
$messageX
$messageY
$messageZ
$messageS
--trigger(s) reported by the tag!"

:if ($21st="not00") do={/tool e-mail send to=$emailaddress subject="$emailsubject" body="$message"} else={:put "21st octet does not have triggers detected!"}

The following 3 lines need to be taken into account:

:local addressRegex "2C:C8:1B:E2:15:29"

line, where we input the MAC address of the tag that you wish to monitor;

:local emailsubject "RouterOS report!"

line, where you can alter the subject for the email;

:local emailaddress "YOUR_EMAIL@gmail.com"

the email address line, where you need to input the email address. To where do you want to send the report?

You can also change the structure of the e-mail message using the lines:

#Message structure:

:local message "$messageF

$messageT

$messageX

$messageY

$messageZ

$messageS

--trigger(s) reported by the tag!"

Name the script however you like, for example, triggernotification. Click on Apply and OK.


Info
titleAdditionally

In this example, we are specifically showcasing an e-mail notification scenario. But! in case you want to use other methods for sending a notification, you can just alter the line below:

:if ($21st="not00") do={/tool e-mail send to=$emailaddress subject="$emailsubject" body="$message"}

You can change the "do={/tool e-mail..." part of the line to, for example, "do={/tool fetch..." or "do={/iot mqtt publish...". That way, you can send out an HTTP post or MQTT publish message instead.

If you would like to get a phone notification when the trigger is detected, you can also utilize IFTTT services (HTTP post to IFTTT webhook) as described in our other guide over here.


You can run the script manually via the command "/system script run triggernotification" or by clicking on the "Run Script" button under the Script List section.

You should make sure that the e-mail notification was received after manually initiating the script.

When script (a) is initiated, RouterOS is going to check every received/stored Bluetooth payload, and if any trigger is found in the payload's list → an e-mail message is structured and sent. This e-mail message will simply indicate which triggers were detected in the list with no additional information.

Option (b) 

# Input MAC address of the tag within ""
:local addressRegex "2C:C8:1B:E2:15:29"

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

#enter the subject for the email within the ""
:local emailsubject "RouterOS report!"

#enter the email address wthin the ""
:local emailaddress "YOUR_GMAIL@gmail.com"

#Script:
################################## Bluetooth ##################################
:local flagStr do={
    :local str ""

    :if ($1 & 0x01) do={ :set $str " switch" }
    :if ($1 & 0x02) do={ :set $str "$str tilt" }
    :if ($1 & 0x04) do={ :set $str "$str free_fall" }
    :if ($1 & 0x08) do={ :set $str "$str impact_x" }
    :if ($1 & 0x10) do={ :set $str "$str impact_y" }
    :if ($1 & 0x20) do={ :set $str "$str impact_z" }

    :if ([:len $str] = 0) do={ :return "" }

    :return [:pick $str 1 [:len $str]]
}

:local triggernameF "free_fall"
:local triggernameT "tilt"
:local triggernameX "impact_x"
:local triggernameY "impact_y"
:local triggernameZ "impact_z"
:local triggernameS "switch"

# Find fresh Bluetooth advertisements
: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 advertisements [/iot bluetooth scanners advertisements print detail \
    as-value where \
        epoch > $btOldestAdvertisementTimestamp and \
        address ~ $addressRegex and \
        data ~ $advertisingDataRegex and \
        rssi > $rssiThreshold
]
:local advCount 0
:local lastAdvTimestamp 0
:local triggerlist ""

:local triggerF
:local triggerT
:local triggerX
:local triggerY
:local triggerZ
:local triggerS

:local messageF ""
:local messageT ""
:local messageX ""
:local messageY ""
:local messageZ ""
:local messageS ""

:local 21st ""

:foreach adv in=$advertisements do={
    :local address ($adv->"address")
    :local rssi ($adv->"rssi")
    :local epoch ($adv->"epoch")
    :local rtime ($adv->"time")
    :local ad ($adv->"data")
    :local flags [:tonum "0x$[:pick $ad 40 42]"]
    :local fflags "$[$flagStr $flags]"
    :if ($fflags="") do={:set $fflags "none - periodically broadcasted payload"}

    :local obj "# $advCount:
                             time: $rtime
                             trigger: $fflags

"
    :set $advCount ($advCount + 1)
    :set $lastAdvTimestamp $epoch
    :set $triggerlist "$triggerlist$obj"

:set triggerF [:pick $triggerlist ([find $triggerlist "free_fall"]-0) ([find $triggerlist "free_fall"]+9)]
:if ($triggerF=$triggernameF) do={:set messageF "$triggernameF";:set 21st "not00";}
:set triggerT [:pick $triggerlist ([find $triggerlist "tilt"]-0) ([find $triggerlist "tilt"]+4)]
:if ($triggerT=$triggernameT) do={:set messageT "$triggernameT";:set 21st "not00";}
:set triggerX [:pick $triggerlist ([find $triggerlist "impact_x"]-0) ([find $triggerlist "impact_x"]+8)]
:if ($triggerX=$triggernameX) do={:set messageX "$triggernameX";:set 21st "not00";}
:set triggerY [:pick $triggerlist ([find $triggerlist "impact_y"]-0) ([find $triggerlist "impact_y"]+8)]
:if ($triggerY=$triggernameY) do={:set messageY "$triggernameY";:set 21st "not00";}
:set triggerZ [:pick $triggerlist ([find $triggerlist "impact_z"]-0) ([find $triggerlist "impact_z"]+8)]
:if ($triggerZ=$triggernameZ) do={:set messageZ "$triggernameZ";:set 21st "not00";}
:set triggerS [:pick $triggerlist ([find $triggerlist "switch"]-0) ([find $triggerlist "switch"]+6)]
:if ($triggerS=$triggernameS) do={:set messageS "$triggernameS";:set 21st "not00";}

}
:if ($advCount > 0) do={
    :set $btOldestAdvertisementTimestamp $lastAdvTimestamp
}

:if ($21st="not00

#User configuration:

#input the tag's mac address that you wish to monitor within the ""

:local addressRegex "2C:C8:1B:4B:BC:4E"

#enter trigger value, for example "04" for freefalling trigger and "02" for tilt trigger detection
:local triggervalueA "04"
:local triggervalueB "02"

#name the trigger accordingly
:local triggernameA "freefalling"
:local triggernameB "tilt"

#enter the message for the email body that you wish to receive within the ""
:local emailmessageA "Our tag fell down!"
:local emailmessageB "Our tag tilted!"

#enter the subject for the email within the ""
:local emailsubject "RouterOS report!"

#enter the email address wthin the ""
:local emailaddress "YOUR_EMAIL@gmail.com"

###Bluetooth scanner
:local triggerA
:local triggerB
:put ("[*] Gathering Bluetooth info...")
:global btOldestAdvertisementTimestamp
:if ([:typeof $btOldestAdvertisementTimestamp] = "nothing") do={: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]
:local advCount 0
:local lastAdvTimestamp 0

:foreach adv in=$advertisements do={
       :local address ($adv->"address")
       :local ad ($adv->"data")
       :local ts ($adv->"epoch")
       :local trig [:pick ($adv->"data") 40 42]
       :set $advCount ($advCount + 1)
       :set $lastAdvTimestamp $ts
       :if ($trig="$triggervalueA") do={:set triggerA "$triggernameA"}
       :if ($trig="$triggervalueB") do={:set triggerB "$triggernameB"}
       :if ($advCount > 0) do={:set $btOldestAdvertisementTimestamp $lastAdvTimestamp}}

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

###Result
:if ($triggerA="$triggernameA") do={/tool e-mail send to=$emailaddress subject="$emailsubject" body="$emailmessageA$triggerlist"}
:if ($triggerB="$triggernameB") do={/tool e-mail send to=$emailaddress subject="$emailsubject" body="$emailmessageB"}else={:put "21st octet does not have triggers detected!"}

When script (b) is initiated, RouterOS is going to check every received/stored Bluetooth payload, and if any trigger is found in the payload's list → an e-mail message is structured and sent. This e-mail message will have a bit more detailed information, compared to script (a). The message, in this case, will indicate each payload's reception timeUse the script above as a reference. The script above scans for "tilt" and "freefall" triggers.

System>Scheduler

To automate the process add a new scheduler under the System>Scheduler tab:

...

Click on Apply and OK.

Result verification

a1) Confirm that the tag broadcasts advertising reports and that the tag's triggers get detected:

b2) Confirm that your email server is set up correctly and that you are able to send emails from the KNOT (RouterOS).

c3) After you manually run the script or apply a scheduler to the script, an email notification should go through, like so:

     Script (a):

Image Added

     Script (b):

Image AddedImage Removed