Skip to content

Instantly share code, notes, and snippets.

@miaucl
Last active December 18, 2020 12:52
Show Gist options
  • Save miaucl/1625a6e2aec92b2a725a1b3a0310f53a to your computer and use it in GitHub Desktop.
Save miaucl/1625a6e2aec92b2a725a1b3a0310f53a to your computer and use it in GitHub Desktop.
Raspberry Pi Power Button Script

Install Raspberry Pi Power Button Script

Make sure you have a raspberry pi. (This script is tested with the raspbian dist on a series 3 model B+)

DISCLAIMER: Look at the script for the PINS and PORTS used. You can change it in the section Configuration if you like.

  1. Download the raspberry-pi-power-button-script.py script, name something like shutdown.py and put it somewhere publicly available.

  2. Make script executable with chmod +x <absolute_path_to>/shutdown.py.

  3. Create a service with sudo nano /lib/systemd/system/shutdown.service as root and with content:

[Unit]
Description=Raspberry Pi Power Button Script
After=multi-user.target

[Service]
Type=idle
ExecStart=<absolute_path_to>/shutdown.py &

[Install]
WantedBy=multi-user.target
  1. Make service executable sudo chmod 644 /lib/systemd/system/shutdown.service, register it and activate it:
sudo systemctl daemon-reload
sudo systemctl enable shutdown.service
sudo systemctl start shutdown.service
  1. After restart:
sudo systemctl status shutdown.service
  1. Use disable and stop to turn it off.

  2. Use journalctl -u shutdown.service -f to follow logs

How to use it

The script listens to a short press for shutdown and a long press for reboot. Look at the script to see the default value used for the long press and change it as you wish. (default: 3s)

Additionally, there is a timeout after which the press is cancelled to prevent accidental shutdowns and a possibility to cancel the action if required.

The script has also a rebound timeout integrated to smoothen the behaviour for cheap buttons ;)

Have fun!

Author: miaucl

#!/usr/bin/python
"""
Raspberry Pi Power Button Script.
Author: miaucl (https://gist.github.com/miaucl)
Description: This script listens to a power button connected on PIN XXX and enables shutdown and reboot functionality for a raspbian dist using python 2/3.
Setup: The PIN XXX is configured with a pull up resistor and should be connected to the GND PIN by a simple interuptor.
(PIN: XXX) (PIN: GND)
___ ___
| ___ |
|_______/ _______|
BTN
Standard:
PIN=29/PORT=5
GND=30
"""
import RPi.GPIO as GPIO
import subprocess, time, sys, syslog, os
#####################
### Configuration ###
#####################
# GPIO-Port of the PIN
# GPIO 5, PIN 29 (GND just aside on PIN 30)
PORT = 5
# Max limit for shutdown (in secs), should the button be pressed longer, a reboot takes place
T_REBOOT = 3
# Timeout for the button to disable the action
T_TIMEOUT = 6
# Debounce time for the button (in secs)
T_PRELL = 0.05
###############
### Globals ###
###############
# Timestamp of the button press
timestamp = None
######################
### Initialization ###
######################
# Get the uid to check the permissions
uid = os.getuid()
# Needs root permission to shutdown/reboot
if uid > 0:
print ("Scripts needs root permission!")
sys.exit(0)
# GPIO initializing, BMC-Pin number, Pullup-Resistor
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(PORT, GPIO.IN, pull_up_down=GPIO.PUD_UP)
##########################
### Interrupt Routines ###
##########################
# Interrupt-Routine fuer die Taste
def buttonISR(pin):
"""Interrupt routing listening to button."""
global timestamp
# Button is pressed down
if not (GPIO.input(pin)):
syslog.syslog("Button down")
# Start the press
if timestamp is None:
syslog.syslog("Start press")
timestamp = time.time()
# Restart the press
elif time.time() - timestamp > T_PRELL:
syslog.syslog("Restart press")
timestamp = time.time()
# Skip as it is probably a rebound
else:
syslog.syslog("\t--> Skip: Already a press in process and probably a rebound")
# Button is released up
else:
syslog.syslog("Button up")
# If a press is active
if timestamp:
# A press is completed
if time.time() - timestamp > T_PRELL:
syslog.syslog("Stop press after: {:.3f}s".format(time.time() - timestamp))
# Reboot for long press
if time.time() - timestamp >= T_REBOOT:
syslog.syslog('==> Shutdown: System rebooted');
subprocess.call(['shutdown', '-r', 'now'], shell=False)
# Shutdown for short press
else:
syslog.syslog('==> Shutdown: System halted');
subprocess.call(['shutdown', '-h', 'now'], shell=False)
# Reset the timestamp
timestamp = None
# Skip as it is probably a rebound
else:
syslog.syslog("\t--> Skip: Probably a rebound after: {:.3f}s".format(time.time() - timestamp))
# Interrupt for the button PIN
GPIO.add_event_detect(PORT, GPIO.BOTH, callback=buttonISR)
############
### Main ###
############
syslog.syslog('Shutdown.py started');
while True:
try:
# Sleep
time.sleep(1)
# Reset the timestamp after timeout when active
if timestamp and time.time() - timestamp > T_TIMEOUT:
syslog.syslog("Timeout press...")
timestamp = None
except KeyboardInterrupt:
syslog.syslog('Shutdown terminated (Keyboard CTRL+C)');
print("Bye")
sys.exit(0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment