10-12-2019, 07:38 AM
Hi all
After playing with a few different options for shutting down my Pi safely, I kind of gave up until a discussion on Facebook. A very clever guy called Ronald who is doing stuff using the can-bus suggested using Bluetooth detection. I'd done a load of stuff on this in the house a while ago to detect presence and adjust the heating so I can't believe I was so close to a solution and didn't think of it.
So, this is my Python script *so far*. I've called it inoutboard.py because that's where I got the initial code from and it's in a directory under my home directory called presence:
You just need to get your Bluetooth MAC address from your phone and put that in instead of the xx bit in 2 places.
I know this isn't the most elegant code but it works and I'll carry on improving it over time.
So this looks for the Bluetooth address of my phone. If it's found then it just waits 30 seconds and looks again. If it's not found, it waits 90 seconds and checks again. If it's still not found then it shuts down the Pi. I might change this later. I was thinking that I would set it to 15 minutes. That should be long enough to do something like fill up with fuel and pay without the Pi shutting down so you don't have to wait for it to come up again.
I'm running this as a service on the Pi so it start on boot and should restart if it crashes or anything. The only thing you need to ensure is that "Wait for network at boot" is enabled in raspi-config > Boot options. Otherwise the service fails to start.
To run this as a service, create a file called detect.service and copy it to /etc/systemd/system. The file should look like this:
Then run this to start the service:
sudo systemctl start detect.service
The next command will tell you if the service is active or not. Hopefully it's active.
sudo systemctl is-active detect.service
And finally, this will enable the service when you boot
sudo systemctl enable detect.service
Now when you boot your Pi, the service should start. If Bluetooth is on then the Pi will just keep running. If you turn Bluetooth off or your phone disconnects because you got home then the Pi should shut down.
This, of course, assumes that you car is parked far enough away from your house that the Bluetooth will disconnect. I turn my phone onto airplane mode at night so it's unlikely to kill the car battery if, by chance, it stays connected for a few hours but needs to be considered.
There are a few improvements I'm going to make.
1. If I change the timeout to 15 minutes then I want to add something that will turn the screen off sooner.
2. I want to add a score so that instead of just relying on 2 failed detects, it will detect multiple times over the timeout period and only shut down if they all fail. That should take care of any temporary glitches. Checking at the start and end is probably good enough but you may get an instance where just by sheer coincidence it can't see your phone for those 2 times.
3. I have a "Tile" which uses BLE. I might try with this instead. I tried this for presence at home but it was a bit flaky because the Tile only sends out a beacon message every now and then. So you have to be sure that your detection period coincides with when the Tile is active. My Tile is on my keyring so it's not then dependant on having the phone in the car and would then work for multiple phones - if my other half borrows my car and uses her phone, for example.
If anyone has any other improvements, spots any problems or can't get it working I'd be happy to hear and help if I can. Otherwise, feel free to use this yourself. I've been messing with it this morning and it seems to work fine.
Cheers
Andy
After playing with a few different options for shutting down my Pi safely, I kind of gave up until a discussion on Facebook. A very clever guy called Ronald who is doing stuff using the can-bus suggested using Bluetooth detection. I'd done a load of stuff on this in the house a while ago to detect presence and adjust the heating so I can't believe I was so close to a solution and didn't think of it.
So, this is my Python script *so far*. I've called it inoutboard.py because that's where I got the initial code from and it's in a directory under my home directory called presence:
import bluetooth
import time
from subprocess import call
while True:
result = bluetooth.lookup_name('xx:xx:xx:xx:xx:xx', timeout=10)
if (result != None):
score = 1
#print "Detected"
else:
#print "Not detected"
time.sleep(90)
result = bluetooth.lookup_name('xx:xx:xx:xx:xx:xx', timeout=10)
if (result == None):
call("sudo shutdown -h now", shell=True)
time.sleep(30)
You just need to get your Bluetooth MAC address from your phone and put that in instead of the xx bit in 2 places.
I know this isn't the most elegant code but it works and I'll carry on improving it over time.
So this looks for the Bluetooth address of my phone. If it's found then it just waits 30 seconds and looks again. If it's not found, it waits 90 seconds and checks again. If it's still not found then it shuts down the Pi. I might change this later. I was thinking that I would set it to 15 minutes. That should be long enough to do something like fill up with fuel and pay without the Pi shutting down so you don't have to wait for it to come up again.
I'm running this as a service on the Pi so it start on boot and should restart if it crashes or anything. The only thing you need to ensure is that "Wait for network at boot" is enabled in raspi-config > Boot options. Otherwise the service fails to start.
To run this as a service, create a file called detect.service and copy it to /etc/systemd/system. The file should look like this:
[Unit]
Description=My service
After=network.target
[Service]
ExecStart=/usr/bin/python -u inoutboard.py
WorkingDirectory=/home/pi/presence
StandardOutput=inherit
StandardError=inherit
Restart=always
User=pi
[Install]
WantedBy=multi-user.target
Then run this to start the service:
sudo systemctl start detect.service
The next command will tell you if the service is active or not. Hopefully it's active.
sudo systemctl is-active detect.service
And finally, this will enable the service when you boot
sudo systemctl enable detect.service
Now when you boot your Pi, the service should start. If Bluetooth is on then the Pi will just keep running. If you turn Bluetooth off or your phone disconnects because you got home then the Pi should shut down.
This, of course, assumes that you car is parked far enough away from your house that the Bluetooth will disconnect. I turn my phone onto airplane mode at night so it's unlikely to kill the car battery if, by chance, it stays connected for a few hours but needs to be considered.
There are a few improvements I'm going to make.
1. If I change the timeout to 15 minutes then I want to add something that will turn the screen off sooner.
2. I want to add a score so that instead of just relying on 2 failed detects, it will detect multiple times over the timeout period and only shut down if they all fail. That should take care of any temporary glitches. Checking at the start and end is probably good enough but you may get an instance where just by sheer coincidence it can't see your phone for those 2 times.
3. I have a "Tile" which uses BLE. I might try with this instead. I tried this for presence at home but it was a bit flaky because the Tile only sends out a beacon message every now and then. So you have to be sure that your detection period coincides with when the Tile is active. My Tile is on my keyring so it's not then dependant on having the phone in the car and would then work for multiple phones - if my other half borrows my car and uses her phone, for example.
If anyone has any other improvements, spots any problems or can't get it working I'd be happy to hear and help if I can. Otherwise, feel free to use this yourself. I've been messing with it this morning and it seems to work fine.
Cheers
Andy