TIP_Bluetooth_Proximity_Monitor
Contents |
Bluetooth Proximity Monitor
| Terminals / Shells • Network • X Window System • Portage • System • Filesystems • Kernel • Other |
Introduction
Here's the idea: I have a bluetooth phone. When I walk away from my computer, I want the screen to lock. When I come back, I want the screen to unlock. Sound simple? Well, it is! First, you need to get bluetooth working and you need to be able to connect to your phone. If you haven't done that yet, see here.
Here's how it works. The following bash script will tell hcitool to connect to your phone and get the RSSI (Received Signal Strength Indicator). If your RSSI falls below the threshold, it calls the "FAR" command, when you come back, it calls the "NEAR" command. At the beginning of the script, there are several variables you'll want to change:
| DEVICE | the bluetooth address of your phone. |
| CHECK_INTERVAL | how often the script checks the RSSI of your phone. |
| THRESHOLD | the RSSI at which you want the script to know you are "away". -10 works best for me, but you may have to test this by setting your phone at the distance you want your screen to lock, and run 'hcitool rssi <addr>' to get the desired number. |
| FAR_CMD | the command to run to when the RSSI goes below the THRESHOLD |
| NEAR_CMD | the command to run when the RSSI comes back above the THRESHOLD. |
| DEBUG | set this to /dev/tty if you're testing, and set it to a file if you want a log. |
The script must be run as root so that hcitool can connect to the bluetooth device. The one problem I found was how to successfully unlock the screensaver from a script. Using xscreensaver -deactivate will only simulate what happens when you move the mouse or when a key is pressed. If your screen is locked, it will stay locked. If you want the screen to automatically unlock, you have to kill xscreensaver and restart it. The problem is that you can't restart xscreensaver as root (as far as I can know), so I the only way I could make the script run as a normal user was to setuid the hcitool program. to do this, simply:
chmod +s /usr/bin/hcitool
Please change the $DEBUG variable to something writeable by the user. Note: When using GNOME or KDE, both environments bring their own screensaver daemon which is fully controlable using D-BUS (GNOME) or DCOP (KDE). It can be called to lock AND to unlock the screen without a password.
If you don't need to kill and restart xscreensaver when you come back, you can just run the script as root and leave hcitool as is.
Tasty bit
I used have the RSSI signal drop when I am infront of my pc using a Nokia 6600. the new bluez 2.25 fixs this issue. I suggest upgrading to the current bluez version.
enough talk... here's the script!
| File: /usr/local/bin/btproximity |
#!/bin/sh
DEVICE="00:0E:07:17:ED:6C"
CHECK_INTERVAL=2
THRESHOLD=-10
PID=0
START_CMD='/usr/bin/xscreensaver -nosplash'
FAR_CMD='/usr/bin/xscreensaver-command -lock'
NEAR_CMD='/usr/bin/killall xscreensaver'
#You really shouldn't kill -9 xscreensaver.
#From help: (Note that one must *never* kill xscreensaver with -9!)
HCITOOL="/usr/bin/hcitool"
DEBUG="/var/log/btproximity.log"
connected=0
function msg {
echo "$1" >> $DEBUG
}
function check_connection {
connected=0;
found=0
for s in `$HCITOOL con`; do
if [[ "$s" == "$DEVICE" ]]; then
found=1;
fi
done
if [[ $found == 1 ]]; then
connected=1;
else
msg 'Attempting connection...'
if [ -z "`$HCITOOL cc $DEVICE 2>&1`" ]; then
msg 'Connected.'
connected=1;
else
msg "ERROR: Could not connect to device $DEVICE."
fi
fi
}
function check_xscreensaver {
PID=`ps -C xscreensaver --no-heading | awk '{ print $1 }'`
if [ "$PID" == "" ]; then
$START_CMD &
fi
}
check_connection
while [[ $connected -eq 0 ]]; do
check_connection
done
name=`$HCITOOL name $DEVICE`
msg "Monitoring proximity of \"$name\" [$DEVICE]";
state="near"
while /bin/true; do
check_xscreensaver
check_connection
if [[ $connected -eq 1 ]]; then
rssi=`$HCITOOL rssi $DEVICE | sed -e 's/RSSI return value: //g'`
if (( $rssi <= $THRESHOLD )); then
if [[ "$state" == "near" ]]; then
msg "*** Device \"$name\" [$DEVICE] has left proximity"
state="far"
$FAR_CMD > /dev/null 2>&1
fi
else
if [[ "$state" == "far" ]]; then
msg "*** Device \"$name\" [$DEVICE] is within proximity"
state="near"
$NEAR_CMD > /dev/null 2>&1
$START_CMD &
fi
fi
#msg "state = $state, RSSI = $rssi, PID = $PID"
fi
sleep $CHECK_INTERVAL
done
|
And, for KDE users, inspired by the above script. Tested with my Sony Ericsson K750i and works perfectly. Also tested with Samsung D600, works great.
| File: /usr/local/bin/btproximity |
#!/bin/bash
# BTProximity by Thomas Kear <qupada@initng.org>
# Inspired by scripts from www.gentoo-wiki.info, but designed for KDE users
# No warranty expressed or implied, if it breaks you get to keep both pieces.
# TODO: make the script disconnect on exit, rather than leaving open rfcomm channel.
DEVICE="00:12:EE:07:95:48" # Use 'hcitool scan' to find
INTERVAL="2" # Seconds
MIN_RSSI="-9" # Min = -10
HCITOOL="/usr/bin/hcitool"
DATE="date +%X" # Format to log times in, default = HH:MM:SS (24 hour), 'date --help' for info
log () {
# Log to console
echo $1
# Log to file
#echo $1 >> /var/log/BTProximity.log
}
# Script to run when device leaves proximity
device_out () {
log "`${DATE}`: Device left proximity"
proximity="out"
# Only change commands below this line
dcop kdesktop KScreensaverIface lock &> /dev/null # Start KDE Screensaver
amixer -c 0 cset numid=216 0 &> /dev/null & # Mutes speakers on an audigy 2zs, will need modifying for other cards.
}
#Script to run when device enters proximity
device_in () {
log "`${DATE}`: Device entered proximity"
proximity="in"
# only change commands below this line
killall -9 kdesktop_lock &> /dev/null & # Stop KDE Screensaver. -9 might seem a bit harsh, but works fine
amixer -c 0 cset numid=216 1 &> /dev/null & # Unmutes speakers, as above.
}
# This keeps trying to connect until it succeeds, may cause a few % CPU usage, but better than failing to unlock
connect () {
while `check_disconnected`
do
/usr/bin/hcitool cc ${DEVICE}
if `check_connected`
then
log "`${DATE}`: Connected to `${HCITOOL} name ${DEVICE}` (${DEVICE})"
sleep 3 # RSSI returns stupid values if measured immediately after connecting, wait a couple of seconds
fi
done
}
#Returns 0 if connected, 1 otherwise
check_connected () {
[[ -n `${HCITOOL} con | grep ${DEVICE}` ]] && return 0 || return 1
}
#Opposite of above, 1 if connected
check_disconnected () {
[[ -z `${HCITOOL} con | grep ${DEVICE}` ]] && return 0 || return 1
}
proximity="in"
while `/bin/true`
do
#Connect to bluetooth device
check_disconnected && connect
#Get RSSI from bluetooth device
rssi=`${HCITOOL} rssi ${DEVICE} | gawk -F\:\ '{print $2}'`
if (( ${rssi} <= ${MIN_RSSI} ))
then
# Exit proximity
[[ ${proximity} == "in" ]] && device_out
else
# Enter proximity
[[ ${proximity} == "out" ]] && device_in
fi
# Wait for interval set at the top, and cycle
sleep ${INTERVAL}
done
|
login guard
I hate calling to a mate of mine who seems online in ICQ, only to see he is not there. I decided to fix it from my side by using the previous script to log me in and out automatically. I had to modify the previous script and I use this to start that script automaticly.
| File: /etc/init.d/btproximity |
#!/sbin/runscript
# this will start the Bluetooth proximity script, that logs me in when my
# bluetooth phone is near the pc, and logs-out when I walk away
USER=<your user>
depend() {
need bluetooth
}
start() {
ebegin "Starting BT Proximity"
start-stop-daemon --start --quiet --background --chuid "$USER" --exec /usr/local/bin/btproximity.sh
sleep 1
eend $? "Failed to start BT proximity"
}
stop() {
ebegin "Stopping BT Proximity"
start-stop-daemon --stop --quiet
eend ${?} # "Failed to stop BT proximity"
}
|
Just put the user name instead of <your user>
Concerns or Compliments? Please use the Discussion section.
Created by NickStallman.net, Luxury Homes Australia
Real estate agents should list their apartments, townhouses and units in Australia.
