Hello,
I'm looking for a script that notifies me by email when I move TG-BT5-IN by X or Y axis. is that possible?
E.g. if someone opens the server room door, we would like to be notified.
# 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 "00:CC:66:88:11:BB"
# 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 ""
################################## Bluetooth ##################################
:global invertU16 do={
:local inverted 0
:for idx from=0 to=15 step=1 do={
:local mask (1 << $idx)
:if ($1 & $mask = 0) do={
:set $inverted ($inverted | $mask)
}
}
return $inverted
}
:global le16ToHost do={
:local lsb [:pick $1 0 2]
:local msb [:pick $1 2 4]
:return [:tonum "0x$msb$lsb"]
}
:local le32ToHost do={
:local lsb [:pick $1 0 2]
:local midL [:pick $1 2 4]
:local midH [:pick $1 4 6]
:local msb [:pick $1 6 8]
:return [:tonum "0x$msb$midH$midL$lsb"]
}
:local from88 do={
:global invertU16
:global le16ToHost
:local num [$le16ToHost $1]
# Handle negative numbers
:if ($num & 0x8000) do={
:set num (-1 * ([$invertU16 $num] + 1))
}
# Convert from 8.8. Scale by 1000 since floating point is not supported
:return (($num * 125) / 32)
}
: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]]
}
# 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 advJson ""
:local advSeparator ""
# 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 rssi ($adv->"rssi")
:local epoch ($adv->"epoch")
:local ad ($adv->"data")
:local version [:tonum "0x$[:pick $ad 8 10]"]
:local encrypted [:tonum "0x$[:pick $ad 10 12]"]
:local salt [$le16ToHost [:pick $ad 12 16]]
:local accelX [$from88 [:pick $ad 16 20]]
:local accelY [$from88 [:pick $ad 20 24]]
:local accelZ [$from88 [:pick $ad 24 28]]
:local temp [$from88 [:pick $ad 28 32]]
:local uptime [$le32ToHost [:pick $ad 32 40]]
:local flags [:tonum "0x$[:pick $ad 40 42]"]
:local bat [:tonum "0x$[:pick $ad 42 44]"]
:put ("$advCount: \
address=$address \
ts=$epoch \
rssi=$rssi \
version=$version \
encrypted=$encrypted \
salt=$salt \
accelX=$accelX \
accelY=$accelY \
accelZ=$accelZ \
temp=$temp \
uptime=$uptime \
flags=\"$[$flagStr $flags]\" \
bat=$bat" \
)
:set $advCount ($advCount + 1)
:set $lastAdvTimestamp $epoch
}
:if ($advCount > 0) do={
:set $btOldestAdvertisementTimestamp $lastAdvTimestamp
:log info $advCount
}
[admin@Knot] > /system/script/export
# dec/12/2022 06:01:20 by RouterOS 7.4
# software id = LMW4-2MB9
#
# model = RB924i-2nD-BT5&BG77
# serial number = F5750ECE0D59
/system script
add dont-require-permissions=no name=script4 owner=admin policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="# Input MAC address of the tag within \"\"\r\
\n:local addressRegex \"DC:2C:6E:13:15:7E\"\r\
\n\r\
\n# POSIX regex for filtering Bluetooth advertisements based on their data. Same\r\
\n# usage as with 'addressRegex'.\r\
\n:local advertisingDataRegex \"\"\r\
\n\r\
\n# Signal strength filter. E.g. -40 would only include Bluetooth advertisements\r\
\n# whose signal strength is stronger than -40dBm.\r\
\n# To disable this filter, set it to \"\"\r\
\n:local rssiThreshold \"\"\r\
\n\r\
\n#enter the subject for the email within the \"\"\r\
\n:local emailsubject \"RouterOS report!\"\r\
\n\r\
\n#enter the email address wthin the \"\"\r\
\n:local emailaddress \"mail@domain.com\"\r\
\n\r\
\n#Script:\r\
\n################################## Bluetooth ##################################\r\
\n:local flagStr do={\r\
\n :local str \"\"\r\
\n\r\
\n :if (\$1 & 0x01) do={ :set \$str \" switch\" }\r\
\n :if (\$1 & 0x02) do={ :set \$str \"\$str tilt\" }\r\
\n :if (\$1 & 0x04) do={ :set \$str \"\$str free_fall\" }\r\
\n :if (\$1 & 0x08) do={ :set \$str \"\$str impact_x\" }\r\
\n :if (\$1 & 0x10) do={ :set \$str \"\$str impact_y\" }\r\
\n :if (\$1 & 0x20) do={ :set \$str \"\$str impact_z\" }\r\
\n\r\
\n :if ([:len \$str] = 0) do={ :return \"\" }\r\
\n\r\
\n :return [:pick \$str 1 [:len \$str]]\r\
\n}\r\
\n\r\
\n:local triggernameF \"free_fall\"\r\
\n:local triggernameT \"tilt\"\r\
\n:local triggernameX \"impact_x\"\r\
\n:local triggernameY \"impact_y\"\r\
\n:local triggernameZ \"impact_z\"\r\
\n:local triggernameS \"switch\"\r\
\n\r\
\n# Find fresh Bluetooth advertisements\r\
\n:global btOldestAdvertisementTimestamp\r\
\n:if ([:typeof \$btOldestAdvertisementTimestamp] = \"nothing\") do={\r\
\n # First time this script has been run since booting, need to initialize\r\
\n # persistent variables\r\
\n :set \$btOldestAdvertisementTimestamp 0\r\
\n}\r\
\n:local advertisements [/iot bluetooth scanners advertisements print detail \\\r\
\n as-value where \\\r\
\n epoch > \$btOldestAdvertisementTimestamp and \\\r\
\n address ~ \$addressRegex and \\\r\
\n data ~ \$advertisingDataRegex and \\\r\
\n rssi > \$rssiThreshold\r\
\n]\r\
\n:local advCount 0\r\
\n:local lastAdvTimestamp 0\r\
\n:local triggerlist \"\"\r\
\n\r\
\n:local triggerF\r\
\n:local triggerT\r\
\n:local triggerX\r\
\n:local triggerY\r\
\n:local triggerZ\r\
\n:local triggerS\r\
\n\r\
\n:local messageF \"\"\r\
\n:local messageT \"\"\r\
\n:local messageX \"\"\r\
\n:local messageY \"\"\r\
\n:local messageZ \"\"\r\
\n:local messageS \"\"\r\
\n\r\
\n:local 21st \"\"\r\
\n\r\
\n:foreach adv in=\$advertisements do={\r\
\n :local address (\$adv->\"address\")\r\
\n :local rssi (\$adv->\"rssi\")\r\
\n :local epoch (\$adv->\"epoch\")\r\
\n :local rtime (\$adv->\"time\")\r\
\n :local ad (\$adv->\"data\")\r\
\n :local flags [:tonum \"0x\$[:pick \$ad 40 42]\"]\r\
\n :local fflags \"\$[\$flagStr \$flags]\"\r\
\n :if (\$fflags=\"\") do={:set \$fflags \"none - periodically broadcasted payload\"}\r\
\n\r\
\n :local obj \"# \$advCount:\r\
\n time: \$rtime\r\
\n trigger: \$fflags\r\
\n\r\
\n\"\r\
\n :set \$advCount (\$advCount + 1)\r\
\n :set \$lastAdvTimestamp \$epoch\r\
\n :set \$triggerlist \"\$triggerlist\$obj\"\r\
\n\r\
\n:set triggerF [:pick \$triggerlist ([find \$triggerlist \"free_fall\"]-0) ([find \$triggerlist \"free_fall\"]+9)]\r\
\n:if (\$triggerF=\$triggernameF) do={:set messageF \"\$triggernameF\";:set 21st \"not00\";}\r\
\n:set triggerT [:pick \$triggerlist ([find \$triggerlist \"tilt\"]-0) ([find \$triggerlist \"tilt\"]+4)]\r\
\n:if (\$triggerT=\$triggernameT) do={:set messageT \"\$triggernameT\";:set 21st \"not00\";}\r\
\n:set triggerX [:pick \$triggerlist ([find \$triggerlist \"impact_x\"]-0) ([find \$triggerlist \"impact_x\"]+8)]\r\
\n:if (\$triggerX=\$triggernameX) do={:set messageX \"\$triggernameX\";:set 21st \"not00\";}\r\
\n:set triggerY [:pick \$triggerlist ([find \$triggerlist \"impact_y\"]-0) ([find \$triggerlist \"impact_y\"]+8)]\r\
\n:if (\$triggerY=\$triggernameY) do={:set messageY \"\$triggernameY\";:set 21st \"not00\";}\r\
\n:set triggerZ [:pick \$triggerlist ([find \$triggerlist \"impact_z\"]-0) ([find \$triggerlist \"impact_z\"]+8)]\r\
\n:if (\$triggerZ=\$triggernameZ) do={:set messageZ \"\$triggernameZ\";:set 21st \"not00\";}\r\
\n:set triggerS [:pick \$triggerlist ([find \$triggerlist \"switch\"]-0) ([find \$triggerlist \"switch\"]+6)]\r\
\n:if (\$triggerS=\$triggernameS) do={:set messageS \"\$triggernameS\";:set 21st \"not00\";}\r\
\n\r\
\n}\r\
\n:if (\$advCount > 0) do={\r\
\n :set \$btOldestAdvertisementTimestamp \$lastAdvTimestamp\r\
\n}\r\
\n\r\
\n:if (\$21st=\"not00\") do={/tool e-mail send to=\$emailaddress subject=\"\$emailsubject\" body=\"\$triggerlist\"} else={:put \"21st octet does not have triggers detected!\"}"
[admin@Knot] > /system/scheduler/export
# dec/12/2022 06:01:25 by RouterOS 7.4
# software id = LMW4-2MB9
#
# model = RB924i-2nD-BT5&BG77
# serial number = F5750ECE0D59
/system scheduler
add interval=10s name=schedule1 on-event="/system script run script4\r\
\n/system script run test" policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon start-date=nov/12/2022 start-time=19:33:27
[admin@Knot] >
# Input MAC address of the tag within ""
:local addressRegex "AC:2C:6E:13:05:9E"
# 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 "Move"
#enter the email address wthin the ""
:local emailaddress "mail@domain.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"]+1)]
:if ($triggerT=$triggernameT) do={:set messageT "$triggernameT";:set 21st "not00";}
:set triggerX [:pick $triggerlist ([find $triggerlist "impact_x"]-0) ([find $triggerlist "impact_x"]+1)]
:if ($triggerX=$triggernameX) do={:set messageX "$triggernameX";:set 21st "not00";}
:set triggerY [:pick $triggerlist ([find $triggerlist "impact_y"]-0) ([find $triggerlist "impact_y"]+1)]
: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="TAG MOVED!"} else={:put "21st octet does not have triggers detected!"}