Finally I am releasing my multi-node Bluetooth and WiFi presence detection system, a significantly more advanced version of the original work here: viewtopic.php?t=12570
This system is capable of detecting a single device either via WiFi or Bluetooth using an unlimited number of nodes (eg Raspberry Pi's placed around a house for extended Bluetooth coverage).
The Master Node pings the target via both WiFi and Bluetooth logging the last time that the target device was seen using unix time to a MySQL database. Slave nodes read the database and if it's been more than 8 seconds since the Master Node last saw the target device then they also start searching at maximum speed until a node (Master or Slave) detects the target device.
To save the devices battery the slave nodes sit on Standby not pinging the target unless the master cannot see it.
The system is recommended only for advanced Linux users with mild to moderate PHP knowledge.
Simulated output from the bluegrid engine screen session (I've deliberately enabled / disabled WiFi and Bluetooth my phone to show the different terminal output:
Bens Mobile: Online via WiFi on Master
Bens Mobile: Online via Bluetooth on Master
Device Offline
Bens Mobile: Online via Bluetooth on Kitchen
Bens Mobile: Online via WiFi on Master
Bens Mobile: Online via WiFi on Master
Instructions for Master Node:
1) apt-get install jq screen php5-curl php-mysql php-cli bluez fping
2) mkdir ~/scripts/bluegrid
3) Create the below scripts as per their names with the contents filled out
config.php
Code: Select all
<?php // Configuration
$mysqlserver = "192.168.0.31";
$mysqlusername = "USERNAME";
$mysqlpassword = "PASSWORD";
$mysqldb = "BlueGrid";
$mysqlconn = mysqli_connect("p:".$mysqlserver, $mysqlusername, $mysqlpassword, $mysqldb);
$mysqlconnsetup = mysqli_connect("p:".$mysqlserver, $mysqlusername, $mysqlpassword);
$domoticzserver = "192.168.0.5";
$domoticzusername = "USERNAME";
$domoticzpassword = "PASSWORD";
?>
Code: Select all
<?php
// Include system config and other variables
include 'config.php';
// Start work loop
while ( true ){
// Time
$systemutc = shell_exec ("date -u +%s");
// Get data from the MySQL database
$result = mysqli_query($mysqlconn,"SELECT ref,device,node,technology,lastseen FROM devices WHERE ref = '1'");
$row = mysqli_fetch_row($result);
// Check existing state of Domoticz switch
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_URL => "https://$domoticzusername:$domoticzpassword@$domoticzserver/json.htm?type=devices&rid=1137",
));
$resp = curl_exec($curl);
curl_close($curl);
$json = json_decode($resp);
$state = ($json->result[0]->Data);
// Check time since last update
$timedifference = ($systemutc - $row[4]);
// If out of sync with Domoticz switch state, update it
if($timedifference <=5 ) {
echo "$row[1]: Online via $row[3] on $row[2]\n";
if (stripos($state, 'Off') !== false) {
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_URL => "https://$domoticzusername:$domoticzpassword@$domoticzserver/json.htm?type=command¶m=switchlight&idx=1137&switchcmd=On",
));
curl_exec($curl);
curl_close($curl);
echo "on";
};
};
// If out of sync with Domoticz switch state, update it
if($timedifference >=20 ) {
echo "Device Offline\n";
if (stripos($state, 'On') !== false) {
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_URL => "https://$domoticzusername:$domoticzpassword@$domoticzserver/json.htm?type=command¶m=switchlight&idx=1137&switchcmd=Off",
));
curl_exec($curl);
curl_close($curl);
echo "off";
};
};
// Sleep
usleep(1000000);
}
?>
Code: Select all
<?php
// Target device
$targetbluetoothmac = "xx:xx:xx:xx:xx:xx";
$targetwifiip = "192.168.0.80";
$targetname = "Bens Mobile";
$targetref = "1";
$nodename = "Master";
// Include system config and other variables
include 'config.php';
// Create tables in the database if needed
$createmysqldatabase = ("CREATE TABLE devices (
ref BIGINT(19) UNSIGNED PRIMARY KEY NOT NULL,
device CHAR(255),
node CHAR(255),
technology CHAR(255),
lastseen BIGINT(19)
)ENGINE = MEMORY;");
mysqli_query($mysqlconn, $createmysqldatabase);
//Disable PHP error reporting
error_reporting(0);
// Start work loop
while ( true ){
// Query WiFi Target
$wifi = shell_exec ("fping -c1 -b 32 -t1000 $targetwifiip 2>/dev/null 1>/dev/null && echo On || echo Off");
if (stripos($wifi, 'On') !== false) {
echo "$targetname: Online via Wifi\n";
$technology = "WiFi";
$sleep = "1000000";
};
// Query Bluetooth Target - if target was not reachable via WiFi
if (stripos($wifi, 'Off') !== false) {
$l2ping = shell_exec ("l2ping -c1 -s32 -t1 $targetbluetoothmac 2>/dev/null 1>/dev/null && echo On || echo Off");
if (stripos($l2ping, 'On') !== false) {
echo "$targetname: Online via Bluetooth\n";
$technology = "Bluetooth";
$sleep = "2500000";
};
};
// Display in terminal if device was not reachable
if ((stripos($wifi, 'Off') !== false) && (stripos($l2ping, 'Off') !== false)) { echo "$targetname: Offline\n"; };
// Send result to MySQL database
if ((stripos($wifi, 'On') !== false) OR (stripos($l2ping, 'On') !== false)) {
$systemutc = shell_exec ("date -u +%s");
$mysqldatainsert = "REPLACE INTO devices(ref, device, node, technology, lastseen)VALUES('$targetref','$targetname','$nodename','$technology','$systemutc')";
mysqli_query($mysqlconn, $mysqldatainsert);
};
// Sleep
usleep("$sleep");
}
?>
Code: Select all
<?php
// Include system config and other variables
include 'config.php';
// Check if MySQL server is running at server IP
if (mysqli_ping($mysqlconnsetup)){
echo "";}
else {
echo "Unable to connect to MySQL server at $mysqlserver is it running?";}
// Create MySQL Database if nessesary
if ($mysqlconnsetup->connect_error) {
die("Connection failed: " . $mysqlconn->connect_error);}
$mysqlcreatedb = "CREATE DATABASE IF NOT EXISTS $mysqldb";
if ($mysqlconnsetup->query($mysqlcreatedb) === TRUE) {
echo "MySQL database setup was successful!";
} else {
echo "MySQL setup error..." . $mysqlconnsetup->error;}
?>
Code: Select all
#!/bin/bash
# Path to BlueGrid folder
cd /root/scripts/bluegrid
# BlueGrid Master
/usr/bin/screen -S bluegridmaster -d -m nice -17 ionice -c2 -n6 php -f master.php
# BlueGrid Engine
/usr/bin/screen -S bluegridengine -d -m nice -17 ionice -c2 -n6 php -f engine.php
5) Run startup.sh to start the master.php and engine.php processes and remember to set the Domoticz device IDX number in the engine.php curl commands. If everything is filled out correctly and you can see your database created in phpmyadmin you should be able to type screen -x and see the screen sessions running and enter them to see the inside operations.
Instructions for Slave Node:
1) apt-get install jq screen php5-curl php-mysql php-cli bluez
2) mkdir ~/scripts/bluegrid
3) Create the below scripts as per their names with the contents filled out
config.php
Code: Select all
<?php // Configuration
$mysqlserver = "192.168.0.31";
$mysqlusername = "USERNAME";
$mysqlpassword = "PASSWORD";
$mysqldb = "BlueGrid";
$mysqlconn = mysqli_connect("p:".$mysqlserver, $mysqlusername, $mysqlpassword, $mysqldb);
$mysqlconnsetup = mysqli_connect("p:".$mysqlserver, $mysqlusername, $mysqlpassword);
?>
Code: Select all
<?php
// Target device
$targetbluetoothmac = "xx:xx:xx:xx:xx:xx";
$targetname = "Bens Mobile";
$targetref = "1";
$nodename = "Kitchen";
// Include system config and other variables
include 'config.php';
//Disable PHP error reporting
error_reporting(0);
// Start work loop
while ( true ){
// Time
$systemutc = shell_exec ("date -u +%s");
// Get data from the MySQL database
$result = mysqli_query($mysqlconn,"SELECT ref,device,node,technology,lastseen FROM devices WHERE ref = '1'");
$row = mysqli_fetch_row($result);
// Check time since last update
$timedifference = ($systemutc - $row[4]);
// Query Bluetooth Target
if($timedifference >=8 ) {
$l2ping = shell_exec ("l2ping -c1 -s32 -t1 $targetbluetoothmac 2>/dev/null 1>/dev/null && echo On || echo Off");
if (stripos($l2ping, 'On') !== false) {
echo "$targetname: Online via Bluetooth\n";
$technology = "Bluetooth";
$sleep = "2500000";
};
if ((stripos($l2ping, 'On') !== false)) {
$systemutc = shell_exec ("date -u +%s");
$mysqldatainsert = "REPLACE INTO devices(ref, device, node, technology, lastseen)VALUES('$targetref','$targetname','$nodename','$technology','$systemutc')";
mysqli_query($mysqlconn, $mysqldatainsert);
};
};
if($timedifference <=5 ) {
echo "Standing by...\n";
};
// Sleep
usleep(2500000);
}
?>
Code: Select all
#!/bin/sh
### BEGIN INIT INFO
# Provides: bluegrid
# Required-Start: $network
# Required-Stop: $network
# Default-Start: 2 3 5
# Default-Stop:
# Description:
### END INIT INFO
case "$1" in
'start')
sudo /usr/bin/screen -S bluegridslave -d -m sudo php -f /home/pi/scripts/bluegrid/slave.php
;;
'stop')
;;
*)
echo "Usage: $0 { start | stop }"
;;
esac
exit 0
1) You need to understand and edit as needed the above script to work in your own environment.
2) The PHP curl command is set to allow unsigned SSL certificates which depending on your environment may be a security risk.
3) Raspberry Pi Zero W's make really good slave nodes (they are very small with low power consumption and have built in Bluetooth).
