PDA

Bekijk de volledige versie : Bluetooth proximity monitor



taylor729
12-07-2009, 15:30
Hello,
I haven't found anything similar on this site, so I hope it might be useful.

I wrote a few scripts to automatically monitor bluetooth devices in range of BT USB stick attached to Asus router (for example mobile phones of people coming and leaving home or office). Devices can be in hidden mode.

!!! Some modifications according your own environment will be needed, mainly paths and usernames !!!

Requirements (see other related topics in this forum how to get it working):
- kernel modules for USB bluetooth stick loaded
- bluez-libs, bluez-utils (or bluez2-libs, bluez2-utils) packages installed
- sqlite2 (or sqlite) package
- procps (for pgrep used in startup script)


Main script blueproximity.sh can be run directly from command line or using simple script S99local:


#!/bin/sh
#
# Startup script for local custom services
case $1 in
start)
echo "Starting blueproximity.sh"
su pavel -c "exec nice sh ~pavel/btproximity/blueproximity.sh" >/dev/null 2>&1 &
;;
stop)
pid=`pgrep -f blueproximity.sh`
if [ -n "$pid" ] ; then
echo "Stopping blueproximity.sh"
kill $pid
fi
;;
restart)
$0 stop
sleep 1
$0 start
;;
*)
echo "usage: $0 (start|stop|restart)"
exit 1
;;
esac

Script doesn't require to be run under root privileges - I used my own account 'pavel'. It uses sqlite (version 2) for data storage - database has to be created in advance:

sqlite btlog.db < db.sql
Then it is neccessary to add one or more MAC addresses and names into 'devices' table. Value of 'enabled' allows to selectively disable or enable scanning of devices.

There are some variables that can be changed in the beginning of the script (blueproximity.sh):


treshold=2 # no of successive unsuccessful tries to treat device as out of range
cycletime=120 # duration of one cycle

treshold means that device will be logged as 'away' after two succesive unsuccessful attempts to find it.
cycletime=120 means that every enabled device will be scanned every 2 minutes.

Every device also has it's own directory (automatically created) which contain temporary state file. If you create a script run-in and/or run-out inside, it will be run on corresponding event with device name as argument. Additionally, 'run-in' gets second argument with minutes since last 'OUT' event.

Finally, script btlog.php is a script to display records from the database (tables status and log). It is very simple - if you develop more sophisticated version, possibly including management of devices in database, you're welcome to post it here ;-).
Script was tested under lighttpd and php-fcgi with extensions pdo.so and sqlite.so enabled in php.ini.

I hope it will be useful for somebody.

Paul

Lesiuk
12-07-2009, 19:27
Great! :) Thank you.

taylor729
15-07-2009, 09:46
I have made some changes and improvements - and also I organized directory structure and added some comments.

upgraded DB support to sqlite3
rate of looking for a device decreases after specified time the device hasn't been seen
optimized for less number of disk writes
addes some comments ;-)
more minor improvements in all parts


Starting from this version, temporary files are created in /tmp/btproximity, but option for your own handler scripts remains. You only need to manually create directory with the same name as BT device located in the directory which contains blueproximity.sh script and put script named run-in and/or run-out into.

Script gets following arguments when it is run:
device_name mac_address minutes_away

minutes_away has meaning only for IN event.

I've learned how to handle sqlite3 via DSO class in PHP, so there is no need to use old sqlite2. Lines

extension=pdo.so
extension=pdo_sqlite.so
must be present in your /opt/etc/php.ini file

initializing database:

sqlite3 btlog.db < db.sql

or migrating database from sqlite v2 to sqlite v3:

sqlite btlog.db ".dump" > btlog_dump
ipkg remove sqlite2 ; ipkg install sqlite
rm btlog.db
sqlite3 btlog.db < btlog_dump


I've added optional decreasing of search rate because it takes about 20 second to look for device that's not present (at least in my case) and time to look for all devices is limited by length of cycle. So it saves some time on devicess that haven't been present for longer time (default setting is 24 hours).

There is still no web management of devices, maybe in next version or up to someone else ;-)

PS etc/init.d/S99local contains a small mistake - a quote char at line 9 is needed to remove. Newest version below is OK.

derrij
10-11-2009, 08:51
Then it is neccessary to add one or more MAC addresses and names into 'devices' table. Value of 'enabled' allows to selectively disable or enable scanning of devices.

how to add MAC addresses and names into 'devices' table?

taylor729
10-11-2009, 11:48
For example:


sqlite3 btlog.db 'insert into devices (mac, name, enabled) values ("11:22:33:44:55:66", "MyDeviceName", 1)'


Of course, database file btlog.db must already exist (the command for DB initialisation is in my first post).

taylor729
10-11-2009, 12:31
New version:

additionally to multiple probing ('treshold' times) of device before considering it as away, there is another (i think better) function - OUT events are written after 'writedelay' successive unsuccessful probes, but with time of first unsuccessful probe. Status is updated immediately
Reduced disk writes by storing absolute time when a device became unavailable instead of counting cycles of being away.


I have also added a simple script for sending OBEX notes to mobile phones (tested on several Nokias). It is used in example of script run on IN event to send welcome message to the incoming phone.

derrij
10-11-2009, 14:54
./S99local: line 30: syntax error: "(" unexpected (expecting "fi")

in btproximity_0.3

nice sh /opt/btproximity/blueproximity.sh" >/dev/null 2>&1 &
I think must be
nice sh /opt/btproximity/blueproximity.sh >/dev/null 2>&1 &

taylor729
10-11-2009, 15:12
Sorry, I'm using slightly different version of S99local init script and I forgot to remove one quote, when creating package for this forum. File in attachment in the post above is now correct.

taylor729
10-11-2009, 15:23
nice sh /opt/btproximity/blueproximity.sh" >/dev/null 2>&1 &
I think must be
nice sh /opt/btproximity/blueproximity.sh >/dev/null 2>&1 &

Yes, you're right.
Sorry

derrij
10-11-2009, 17:53
Thanks for the script.Works fine.

P.S. In btproximity_0.3.tgz attachment btlog.php incorrect path in $dbname.

taylor729
10-11-2009, 18:10
Thanks for the script.Works fine.

P.S. In btproximity_0.3.tgz attachment btlog.php incorrect path in $dbname.

Thanks for notice - also forgotten to change this from environment that I'm running the script in. Corrected in the attachement above.

I hope you find my work useful.

Pavel

derrij
12-11-2009, 07:54
Every device also has it's own directory (automatically created) which contain temporary state file. If you create a script run-in and/or run-out inside, it will be run on corresponding event with device name as argument. Additionally, 'run-in' gets second argument with minutes since last 'OUT' event.

is this working in btproximity_0.3? I can't get script to run on event?

taylor729
12-11-2009, 12:26
Yes, this has been working in all versions.
The only difference is that first version used this directory also for temporary file and created it itself. Since version 0.2, temporary files go to /tmp/btproximity and directory for scripts run-in and run-out has to be created manually. It is located at the same level as btproximity.sh script (try to rename dev-name-example directory to real name of one of your bluetooth device).

I have added this information to the post related to version 0.2 (post #3).

derrij
12-11-2009, 13:04
# call external script (if exists); $1 = device name, $2 = BT addr, $3 = minutes away
timeaway=${5:-0}
if [ -x "${mydir}/$1/run-$3" ] ; then
"${mydir}/$1/run-$3" $1 $2 $(($timeaway / 60))
fi
}

I was trying to rename dev-name-example, but nothing happens.
And I think btproximity.sh trying call run-1... , but not run-in.
(run-1, I was trying to)

taylor729
12-11-2009, 13:30
# call external script (if exists); $1 = device name, $2 = BT addr, $3 = minutes away
timeaway=${5:-0}
if [ -x "${mydir}/$1/run-$3" ] ; then
"${mydir}/$1/run-$3" $1 $2 $(($timeaway / 60))
fi
}

I was trying to rename dev-name-example, but nothing happens.
And I think btproximity.sh trying call run-1... , but not run-in.
(run-1, I was trying to)

Don't let to confuse yourself, $3 in the comment doesn't mean $3 in the code, but third argument passed to run-{in,out} script.
$3 that is passed to the function log () is name of the event (in, out). See lines 139 and 162. So, script names should really be run-in and run-out.
They have to have eXecute right set.

derrij
02-12-2009, 16:14
it is possible, to make external script executing, only if another device from DB is away(or not).

for example: run script "run-in" from folder "device1" if device2 is away
or maybe execute command from "device1/run-in" script if device2 is away.

taylor729
05-02-2010, 18:41
it is possible, to make external script executing, only if another device from DB is away(or not).

for example: run script "run-in" from folder "device1" if device2 is away
or maybe execute command from "device1/run-in" script if device2 is away.

I'm sorry for my late response - I didn't get mail notification of new post for some reason.
Unfortunately it is not possible natively, but you can put sqlite query to `status` table and check for status of any other device.

You may get inspiration from this function:
----------------------
# get state of device from DB (print it on stdout)
# $1 = device name
get_state () {
sqlite3 "$dbname" << /EOF/
SELECT status FROM status WHERE name = "$1" AND status IS NOT NULL;
/EOF/
}
-----------------------

and then, for example, execute this in run-in
if [ "$(get_state OtherDeviceName)" == "OUT" ] ; then
.........
fi

I hope this will help you.

Paul

derrij
21-02-2010, 14:09
I'm sorry for my late response - I didn't get mail notification of new post for some reason.
Unfortunately it is not possible natively, but you can put sqlite query to `status` table and check for status of any other device.

You may get inspiration from this function:
----------------------
# get state of device from DB (print it on stdout)
# $1 = device name
get_state () {
sqlite3 "$dbname" << /EOF/
SELECT status FROM status WHERE name = "$1" AND status IS NOT NULL;
/EOF/
}
-----------------------

and then, for example, execute this in run-in
if [ "$(get_state OtherDeviceName)" == "OUT" ] ; then
.........
fi

I hope this will help you.

Paul

Yes,thank you very much. It's works.

skylin3d
29-04-2010, 20:44
Could someone here explain how to load the kernel modules required for the bluetooth stick to work, and how to install bluez?

Here (http://wl500g.info/showthread.php?t=23668) I've tried to share my internet connection to my phone using bluetooth, but I can't even get the bluetooth stick to work. So what should I do to get bluetooth working on my WL-500gP?

taylor729
01-05-2010, 20:12
I'm using bluez2-libs and bluez2-utils packages (older version than bluez-* ones) and these modules:

-rwxr-xr-x 1 root root 58788 Jun 21 2009 bluez.o
-rwxr-xr-x 1 root root 17268 Jun 21 2009 bnep.o
-rwxr-xr-x 1 root root 4420 Jun 21 2009 crc32.o
-rwxr-xr-x 1 root root 15924 Jun 21 2009 hci_usb.o
-rwxr-xr-x 1 root root 30600 Jun 21 2009 l2cap.o
-rwxr-xr-x 1 root root 50592 Jun 21 2009 rfcomm.o
-rwxr-xr-x 1 root root 18612 Jun 21 2009 sco.o

I found the modules somewhere on this forum, but I can't locate it now. You could try files from the attachment if you were unable to get the correct version of modules.

Paul