Only requirement is a working bluez stack/package and hcetool (included), pkill and curl.
Features of this script:
- It is passive, as in it only listens for LE beacons, it does not query them or ping them. This has some security benefits.
- Every initial run it will register the configured beacons as user variables. No need to manually add them, sync IDs etc.
- Beacon names are used as user variabel names
- Domoticz is not updates unless beacon is not seen in 3 scans or immediately when seen
- Retry settings are customizable
- Detailed debugging if required
Code: Select all
#!/bin/bash
# Backoff period when hcetool after which hcetool run
BACKOFF=5
# Nr of retries before updating Domoticz that device is $AWAY
RETRY=3
# BaseURL for Domoticz inc port
BASEURL="http://localhost:8888"
declare -A BEACONS=(
#[ MAC Address ]=Beaconname
[7C:2F:80:97:1A:72]="Huissleutel_Daan"
[7C:2F:80:97:1A:D3]="Hoofdsleutel_Hyundai"
[7C:2F:80:96:3C:FA]="Hoofdsleutel_Up"
[7C:2F:80:97:2E:5E]="Huissleutel_Naomi"
)
# How many seconds to wait before SIGINT hcitool, may need tweaking when more devices are visible/beacons are not that chatty
PKILLDELAY=5
# String value to register when beacon is visible
HOME="HOME"
# String value to register when beacon is not visible
AWAY="AWAY"
# If all else fails debug will assist
DEBUG=0
# Bluetooth interface to use
HCIINT="hci0"
# Path of hcitool
HCITOOL="/usr/bin/hcitool"
# Path to sleep
SLEEP="/bin/sleep"
# Path to pkill
PKILL="/usr/bin/pkill"
# Path to curl
CURL="/usr/bin/curl"
#####
### NO EDITS BELOW THIS LINE UNLESS YOU KNOW WHAT YOU ARE DOING###
#####
#URLs for saving/updating user variables
JSONSAVE="/json.htm?type=command¶m=saveuservariable&vtype=2"
JSONUPDATE="/json.htm?type=command¶m=updateuservariable&vtype=2"
# Array to store beacon status
declare -A CURRENTBCNSTS
# Array to store beacon retry count
declare -A BCNRETRY
# Linenumber when debugging
DBGCNTR=0
debug () {
# Simple debug function
if [[ $DEBUG -eq 1 ]]; then
((DBGCNTR++))
printf "%05d" $DBGCNTR
echo " DEBUG: $1"
fi
}
scan_beacons () {
# Using hcitool to listen for LE beacons
debug "listening on $HCIINT for devices"
SCAN=`$HCITOOL -i $HCIINT lescan --passive & $SLEEP $PKILLDELAY && $PKILL --signal SIGINT hcitool`
debug "scan results: $SCAN"
}
beacon_alive () {
# Regex function to determine if beacon MAC is part of scan results
if [[ $SCAN =~ "$1" ]]; then
SCANRESULT=$HOME
else
SCANRESULT=$AWAY
fi
}
# Initial beacon scan
scan_beacons
for i in "${!BEACONS[@]}"
# Initial round at startup
do
VNAME="&vname=${BEACONS[$i]}"
beacon_alive $i
VVALUE="&vvalue=$SCANRESULT"
CURRENTBCNSTS[$i]=$SCANRESULT
if [ "$SCANRESULT" = "$AWAY" ]; then
BCNRETRY[$i]=1
else
BCNRETRY[$i]=0
fi
debug "setting current status of $i to ${CURRENTBCNSTS[$i]}"
# Setting or updating user variables, Domoticz will ignore duplicate saves
$CURL -s --request GET $BASEURL$JSONSAVE$VNAME$VVALUE > /dev/null
$CURL -s --request GET $BASEURL$JSONUPDATE$VNAME$VVALUE > /dev/null
done
for (( ; ; ))
do
$SLEEP $BACKOFF
scan_beacons
for i in "${!BEACONS[@]}"
do
VNAME="&vname=${BEACONS[$i]}"
CURSTATUS=${CURRENTBCNSTS[$i]}
debug "CURSTATUS $i:$CURSTATUS"
beacon_alive $i
debug "SCANRESULT $i:$SCANRESULT"
if [ "$CURSTATUS" != "$SCANRESULT" ]; then
VVALUE="&vvalue=$SCANRESULT"
if [ "$SCANRESULT" = "$AWAY" ]; then
((BCNRETRY[$i]++))
debug "beacon $i not found ${BCNRETRY[$i]} times"
if [ ${BCNRETRY[$i]} -eq $RETRY ]; then
CURRENTBCNSTS[$i]=$SCANRESULT
debug "beacon $i status changed to $SCANRESULT after $RETRY retries updating Domoticz"
$CURL -s --request GET $BASEURL$JSONUPDATE$VNAME$VVALUE > /dev/null
fi
else
CURRENTBCNSTS[$i]=$SCANRESULT
debug "beacon $i status changed to $SCANRESULT - updating Domoticz"
$CURL -s --request GET $BASEURL$JSONUPDATE$VNAME$VVALUE > /dev/null
BCNRETRY[$i]=0
fi
else
if [ "$SCANRESULT" = "$HOME" ]; then
if [ ${BCNRETRY[$i]} -ne 0 ]; then
debug "beacon $i resetting retry count"
BCNRETRY[$i]=0
fi
fi
debug "Skipping Domoticz for beacon $i as status $CURSTATUS has not changed"
fi
done
debug "Next round..."
done
The script can be run as a service using this systemd script
Code: Select all
[Unit]
Description=Beaconing Service
After=domoticz.service
[Service]
User=root
Type=idle
ExecStart=/usr/local/bin/beaconing
ExecStop=/usr/bin/pkill --signal SIGINT hcitool
KillMode=process
[Install]
WantedBy=multi-user.target
- Delayed switch to AWAY something along the line of 3 times not seen in a scan really AWAY, but immediate HOME when showing in the scan.
- Reduce load on Domoticz API when BACKOFF period is lowered