Search code examples
pythonbuttonraspberry-pishutdownheadless

Button Press To Shutdown Raspberry Pi Python


I am writing a script for a surveillance camera. I have programmed it to take a picture when motion is detected (PIR sensor) then attach the photo to an email, to a chosen recipient. However because I am running this without a screen, mouse or keyboard attached I had no way to turn the device off without pulling the plug! so I created a script to turn off the computer on a button press(this works fine on its own) however, because the rest of the code is in a loop I don't know where to place it. Keeping in mind I need to be able to turn it off any where in the code. If you have any ideas they would be appreciated Thanks James

import os, re
import sys
import smtplib
import RPi.GPIO as GPIO
import time
import picamera
inport os
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import time
import RPi.GPIO as gpio
GPIO.setmode(GPIO.BCM)
GPIO_PIR = 4
print ("PIR Module Test (CTRL-C to exit)")
GPIO.setup(GPIO_PIR,GPIO.IN)     
Current_State  = 0
Previous_State = 0
try:
  print ("Waiting for PIR to settle ...")
  while GPIO.input(GPIO_PIR)==1:
    Current_State  = 0
  print ("  Ready")
  while True :
    Current_State = GPIO.input(GPIO_PIR)
    surv_pic = open('/home/pi/Eaglecam/surveillance.jpg', 'wb')
    if Current_State==1 and Previous_State==0:
      print("  Motion detected!")
      with picamera.PiCamera() as cam:
        cam.capture(surv_pic)
        surv_pic.close()
      print('  Picture Taken')
      SMTP_SERVER = 'smtp.gmail.com'
      SMTP_PORT = 587       
      sender = '**************'
      password = "**********"
      recipient = '**************'
      subject = 'INTRUDER DETECTER!!'
      message = 'INTRUDER ALLERT!! INTRUDER ALERT!! CHECK OUT THIS PICTURE OF THE INTRUDER! SAVE THIS PICTURE AS EVIDENCE!'
      directory = "/home/pi/Eaglecam/"
      def main():
          msg = MIMEMultipart()
          msg['Subject'] = 'INTRUDER ALERT'
          msg['To'] = recipient
          msg['From'] = sender
          files = os.listdir(directory)
          jpgsearch = re.compile(".jpg", re.IGNORECASE)
          files = filter(jpgsearch.search, files)
          for filename in files:
              path = os.path.join(directory, filename)
              if not os.path.isfile(path):
                  continue
              img = MIMEImage(open(path, 'rb').read(), _subtype="jpg")
              img.add_header('Content-Disposition', 'attachment', filename=filename)
              msg.attach(img)
          part = MIMEText('text', "plain")
          part.set_payload(message)
          msg.attach(part)
          session = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
          session.ehlo()
          session.starttls()
          session.ehlo
          session.login(sender, password)
          session.sendmail(sender, recipient, msg.as_string())
          session.quit()
      if __name__ == '__main__':   
        print('  Email Sent')
      Previous_State=1
    elif Current_State==0 and Previous_State==1:
      print("  Ready")
      Previous_State=0
      time.sleep(0.01)
    import time
    import RPi.GPIO as gpio
except KeyboardInterrupt:
  print('Quit')
  GPIO.cleanup()

Here is the shutdown section of the script. Where would I place this in the loop?

    gpio.setmode(gpio.BCM)
    gpio.setup(7, gpio.IN, pull_up_down=gpio.PUD_UP)
    buttonReleased = True
    while buttonReleased:
        gpio.wait_for_edge(7, gpio.FALLING)
        buttonReleased = False
        for i in range(1):
            time.sleep(0.1)
            if gpio.input(7):
                buttonReleased = True
                break

Solution

  • Two separate scripts would be unnecessary for this project.

    You can do this a couple ways.

    1. Create a global boolean variable called shutdownButton or whatever. Use a callback function for the GPIO pin, and set shutdownButton = True in the callback. And then change your main loop to be while not shutdownButton: instead of while True:.
    2. You could just change your main loop to while gpio.input(7): instead of while True: (assuming you are pulling the pin up and then grounding it down with your switch).

    And then finally just add a shutdown like os.system('sudo shutdown -h now') or call some other script you want to run to clean it up. The point is you just need a function to break out of your main loop when the button has been pressed and then shut down your pi at the end of the program.
    There are other ways to do this also (I personally like the kernel patches from Adafruit that allow a power switch configuration to be added to /etc/modprobe.d...) but I only listed methods that applied directly to your question.