Email notification on the MikroTik BLE tag's accelerometer triggers
在本指南中,我们将快速分步展示如何设置您的 KNOT,使其在检测到 TG-BT5-IN 或 TG-BT5-OUT 标签报告的"已触发"条件时发送电子邮件通知。
简介
在本指南中,我们将快速分步展示如何设置您的 KNOT,使其在检测到 TG-BT5-IN 或 TG-BT5-OUT 标签报告的"已触发"条件时发送电子邮件通知。
这两个标签都有一个内置加速度计,能够检测自由落体、唤醒/移动和倾斜状态。当标签设置为广播 MikroTik 格式的载荷,并且加速度计触发器已启用(使用 MikroTik Beacon Manager 应用)→ 每当将要检测到触发器时,标签将立即广播一个广播载荷/报告。
对于 iOS,触发器设置如下所示(处于禁用状态/默认设置):

对于 Android,触发器设置如下所示(处于禁用状态/默认设置):

要激活触发器检测,只需勾选相应的"复选框"。
标签广播 Bluetooth 载荷后 → 载荷的第 21 个八位字节将指示检测到的确切触发器。您可以在 IoT>Bluetooth>Advertisng reports 选项卡下查看载荷:

如上图所示,第 21 个八位字节为 "04",这表明该载荷是在标签检测到自由落体条件时发送的(这些载荷是在我们"意外"掉落或抛出标签时广播的)。
一切配置完成后,将发生以下情况:
- KNOT 将按计划运行一个脚本。
- 脚本将"读取/扫描"显示在 IoT>Bluetooth>Advertising reports 选项卡中的载荷。
- 如果存储/捕获的载荷的第 21 个八位字节值等于任何"已触发"值 → 将发送电子邮件通知。
换言之,当 KNOT 扫描载荷并发现其中一个载荷的第 21 个八位字节指示触发器已激活时 → 您将收到一封检测到触发器的电子邮件通知。
TG-BT5 标签配置
在此特定示例中,我们需要将标签设置为以 MikroTik 格式工作。在 MikroTik 格式中,每个载荷的第 21 个八位字节将指示其被触发的原因。
您可以按照 iOS 和/或 Android 指南("Advertisement"/Beacon 设置部分)找到如何启用触发器的说明。
为了更容易地"激活"触发器,我们还可以按照 iOS 和/或 Android 指南(Free Fall Threshold 和 Duration 部分)更改触发器的设置。为了测试目的,基本上为了更快地"触发"检测,我们可以将 "Free Fall Duration" 参数更改为 "0" 秒(这将确保所有轴上处于阈值内的任何加速度都会被立即检测为"自由落体"事件)。
RouterOS 配置
信息
需要 iot 软件包。您可以从我们的下载页面——在 "Extra packages" 下获取它。 配置可以在 4 个步骤内完成:
- 启用 scanner(并且最好确认标签在检测到触发器时正在广播载荷);
- 设置电子邮件服务器;
- 导入脚本(并根据需求修改几行脚本);
- 设置调度器。
Bluetooth Scanner
转到 IoT>Bluetooth>Scanners 选项卡并确保它已启用:

转到 Advertising reports 选项卡,并使用 MAC 地址过滤选项过滤列表(您可以在标签本身上印制的标签上找到 MikroTik 标签的 MAC 地址)。
尝试"触发"已配置的检测,并通过检查第 21 个八位字节的值来确认它。
在我们的示例中,我们为标签配置了"自由落体"检测,并将其掉落。我们收到来自标签的报告,指示"下落"状态(第 21 个八位字节 = 04):

我们已经确认标签正确报告了触发器。
电子邮件
导航到 Tools>Email 部分并设置您选择的电子邮件服务器。
在本指南中,我们将使用所示的 GMAIL 示例。

尝试发送一封测试电子邮件以确保设置正确。
脚本
选项 (a)
导航到 System>Scripts 菜单并在其中添加一个新脚本。
您可以复制下面的脚本。将下面的脚本复制到"记事本"中,然后再次将其复制到脚本的 "Source:" 字段中。
## Input MAC address of the tag within ""
:local addressRegex "2C:C8:1B:E2:15:29"
#enter the subject for the email within the ""
:local emailsubject "RouterOS report!"
#enter the email address wthin the ""
:local 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!"}
需要考虑以下 3 行:
:local addressRegex "2C:C8:1B:E2:15:29"
行,我们在其中输入您希望监控的标签的 MAC 地址;
:local emailsubject "RouterOS report!"
行,您可以在其中更改电子邮件的主题;
:local emailaddress "YOUR_EMAIL@gmail.com"
电子邮件地址行,您需要在其中输入电子邮件地址。即您希望将报告发送到何处。
您还可以使用以下行更改电子邮件消息的结构:
#Message structure:
:local message "$messageF
$messageT
$messageX
$messageY
$messageZ
$messageS
--trigger(s) reported by the tag!"
随意为脚本命名,例如 triggernotification。点击 Apply 和 OK。
信息
此外,在此示例中,我们专门展示了电子邮件通知场景。但是! 如果您想使用其他方法发送通知,只需修改下面这一行:
:if ($21st="not00") do={/tool e-mail send to=$emailaddress subject="$emailsubject" body="$message"}您可以将该行中的
do={/tool e-mail...部分更改为例如do={/tool fetch...或do={/iot mqtt publish...。这样,您就可以改为发送 HTTP post 或 MQTT 发布消息。如果您希望在检测到触发器时收到手机通知,您还可以利用 IFTTT 服务(向 IFTTT webhook 发送 HTTP post),如我们在此处的另一份指南中所述。 您可以通过命令 "/system script run triggernotification" 手动运行脚本,或点击 Script List 部分下的 "Run Script" 按钮。
您应确保在手动启动脚本后收到了电子邮件通知。
当脚本 (a) 被启动时,RouterOS 将检查每一个接收/存储的 Bluetooth 载荷,如果载荷列表中发现任何触发器 → 将构造并发送一封电子邮件。此电子邮件将仅指出列表中检测到了哪些触发器,没有附加信息。
选项 (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") do={/tool e-mail send to=$emailaddress subject="$emailsubject" body="$triggerlist"} else={:put "21st octet does not have triggers detected!"}
当脚本 (b) 被启动时,RouterOS 将检查每一个接收/存储的 Bluetooth 载荷,如果载荷列表中发现任何触发器 → 将构造并发送一封电子邮件。与脚本 (a) 相比,此电子邮件将包含稍微更详细的信息。在这种情况下,消息将指示每个载荷的接收时间。
调度器
要自动化此过程,请在 System>Scheduler 选项卡下添加一个新的调度器:

在 "On Event:" 字段下输入 "/system script run triggernotification",并设置您希望运行脚本以检查/扫描广播报告的 interval(例如 10 秒)。
点击 Apply 和 OK。
结果验证
- 确认标签广播广告报告并且标签的触发器被检测到:

-
确认您的电子邮件服务器设置正确,并且您能够从 KNOT (RouterOS) 发送电子邮件。
-
在您手动运行脚本或将调度器应用于脚本后,电子邮件通知应能成功发送,如下所示:
Script (a):

Script (b):
