Skip to content

Instantly share code, notes, and snippets.

@DS256
Created March 6, 2022 22:48
Show Gist options
  • Save DS256/0b2f9afa65d056201464418629006a57 to your computer and use it in GitHub Desktop.
Save DS256/0b2f9afa65d056201464418629006a57 to your computer and use it in GitHub Desktop.
Scripted Reboot Button for Raspberry PI

Scripted Reboot Button for Raspberry PI

I based this project off of Shutdown Raspberry Pi with a Single Button. I used the scripted approach only so there is no reference here to using the Boot Overlay method.

This project consists of:

Approach

I built this for a Raspberry PI Application that would be running unattended 24x7. Since I was not always available, I wanted to be able to instuct someone else to reboot the PI if needed. I added the light to provide feedback. The user instructions are:

  1. Find the flashing light with the button next to it
  2. Push and hold the button. The button will stop flashing and stay on. If you hold it long enough the light will go out.
  3. Release the button
  4. Wait a minute until you see the light flashing again.
  5. If the light does not come back flashing, call me.

You can review the Python code to see how the program works.

Some notes:

  • This was developed on a Raspberry PI P400 running Raspbian GNU/Linux 11 (bullseye)
  • The blinking LED runs independantly once started.
  • The pins for the button and LED were chosen based on the requirements of the overall project.
  • You will see print statements in the Python script. These are written to a log file defined in the services definition. This is optional if you don't need them.
  • I set the output, error and working directory to an attached /media disk since I will be running the PI OS in read only mode. These can also be elminated if not needed.
  • I wasn't able to find anyway to comment the services definition file.

Breadboard Circuit

reboot_button_circuit

Loading the Service

You can find more details on using the SYSTEM service definition details here A good source for understanding PI Services is The ultimate guide on using systemd to autostart scripts on the Raspberry Pi

The following copies the files to their execution directories, reload the services, sets the reboot_button service to automatically run and starts it for the first time

sudo cp reboot_button.py /usr/bin
sudo cp reboot_button.service /lib/systemd/system
sudo systemctl daemon-reload
sudo systemctl enable reboot_button
sudo systemctl start reboot_button

You can check on the status of the service. Here is an example

sudo systemctl status reboot_button
● reboot_button.service - Reboot Button Service
     Loaded: loaded (/lib/systemd/system/reboot_button.service; enabled; vendor>
     Active: active (running) since Sun 2022-03-06 16:08:29 EST; 1h 25min ago
   Main PID: 2049 (python3)
      Tasks: 4 (limit: 4915)
        CPU: 6.888s
     CGroup: /system.slice/reboot_button.service
             └─2049 /usr/bin/python3 -u /usr/bin/reboot_button.py

Mar 06 16:08:29 paulsPI systemd[1]: Started Reboot Button Service.
#!/usr/bin/env python
# REBOOT_BUTTON.PY
# This is based on the project at https://gist.github.com/lbussy/9e81cbcc617952f1250e353bd42e7775
# I chose to implement the 'scripted method' since the project was
# going to run 24x7 and I only needed to provide some way for
# someone else to reboot the PI.
# There are print statements since the service definition I used
# included specs for capturing out/err to a log file.
# This program needs to be run with the -u Python3 option so as not
# to buffer output.
# Here is the meaning of the led
# BLINKING - Running, waiting for reboot button to be pushed
# ON has 2 meanings
# BUTTON HELD - Waiting x seconds to ensure reboot requested
# BUTTON RELEASED - An error has occurred. This is likely short
# lived since the service will restart and
# the light will start blinking again.
# OFF - PI is shutting down or starting up.
from gpiozero import LED, Button
from datetime import datetime
from subprocess import call
from os import getpid
from time import sleep
import sys, os, traceback
# Return the current date and time in nice string format
def dt(): return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# Mainline
def main():
print(dt(),"Reboot: Started as PID",getpid())
led = LED(19) # Chosen because of other pins in use
led.blink() # Indicates running and waiting for button push
button = Button(5) # Chosen because of other pins in use
# Loop checking every few seconds to see if the button has been
# pressed and held. When the button is first pressed, the led
# changes from blinking to on. This is visual feedback to the
# operator. If the button is held down, the led is turned off to
# indicate the PI is rebooting.
# If the led is left on, a problem has occurred.
reboot_req = False
while not reboot_req:
try:
if button.is_pressed:
print(dt(),"Reboot: Button pressed")
led.on() # Led user know the button pressed detected
sleep(5) # User has to hold the button down
if button.is_pressed:
led.off() # Let user know reboot in progress
print(dt(),"Reboot: Button held for 5 seconds.")
reboot_req = True
else:
led.blink() # Let user know reboot was not initiated
sleep(2) # Don't make too short or higher CPU is used.
# Since this runs as a service, there should be not exceptions
# If there is, make sure we log it nicely
except:
exc_type, exc_value, exc_traceback = sys.exc_info()
type=exc_type.__name__
summ = str(traceback.extract_tb(exc_traceback))
print (dt(),"Reboot: Exception '"+type+"="+str(exc_value)+"'. Traceback: "+summ)
break # Leave loop because we don't know what's wrong
if reboot_req:
print(dt(),"Reboot: Rebooting")
sleep(1)
call(["sudo","reboot"])
return 0 # Should never get here
else:
led.on() # Keep light on to say there is a problem.
print(dt(),"Reboot: Loop exited without button reboot request. Error exit")
return 1
# MAIN
if __name__ == "__main__":
rtn=main()
sys.exit(rtn)
[Unit]
Description=Reboot Button Service
After=multi-user.target
[Service]
Type=simple
ExecStart=/usr/bin/python3 -u /usr/bin/reboot_button.py
WorkingDirectory=/media/work
StandardOutput=append:/media/work/log/reboot_button.log
StandardError=append:/media/work/log/reboot_button.log
Restart=always
[Install]
WantedBy=multi-user.target
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment