#!/usr/bin/python # This code was written in August of 2017 by Alligator. # It was written to watch over Pelle, a goldfish. # Pelle has been alive a LONG time, and we want to keep him that way. # To anyone who sees this notice, you can use anything in this code # provided you do something you enjoy with it. Please pass it on. # If you meet me some day, perhaps you can tell me what you did with it. import RPi.GPIO as GPIO import time import Adafruit_CharLCD as LCD import pytz import datetime import smtplib # The following libraries are used to send email. from email.MIMEMultipart import MIMEMultipart from email.MIMEText import MIMEText # Raspberry Pi pin configuration: lcd_rs = 27 lcd_en = 22 lcd_d4 = 25 lcd_d5 = 24 lcd_d6 = 23 lcd_d7 = 18 lcd_red = 4 lcd_green = 17 lcd_blue = 7 # Pin 7 is CE1 # This sets the status of whether the fish was fed on a given day FedStatus = False # Define LCD column and row size for 20x4 LCD. lcd_columns = 20 lcd_rows = 4 # Set the timezone tz = pytz.timezone('America/Chicago') # Initialize the LCD using the pins above. lcd = LCD.Adafruit_RGBCharLCD(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, lcd_d7, lcd_columns, lcd_rows, lcd_red, lcd_green, lcd_blue) GPIO.setmode(GPIO.BCM) GPIO.setup(12, GPIO.IN, pull_up_down=GPIO.PUD_UP) # This is for a normally open switch on pin 12 GPIO.setup(26, GPIO.OUT) # This is for the blue switch LED GPIO.setup(13, GPIO.OUT) # This is for the green switch LED GPIO.setup(19, GPIO.OUT) # This is for the red switch LED # This function turns off the switch LED def led_off(): GPIO.output(26, GPIO.HIGH) # This sets pin GPIO pin 26 to high and the blue LED is off GPIO.output(13, GPIO.HIGH) # This sets pin GPIO pin 13 to high and the green LED is off GPIO.output(19, GPIO.HIGH) # This sets pin GPIO pin 19 to high and the red LED is off # Reset the fed status to not fed and set the LCD to red def reset_status(): global FedStatus FedStatus = False led_off() GPIO.output(19, 0) # This turns on the red switch LED. lcd.clear() lcd.set_color(1.0, 0.0, 0.0) lcd.set_cursor(2, 0) lcd.message("Pelle is hungry!") lcd.set_cursor(2, 2) lcd.message("Press the button") lcd.set_cursor(1, 3) lcd.message("when you feed him.") # Once the fish has been fed, log the time in a UTC file and a local time file for later graphing. def pelle_fed(): timestr = time.strftime("%Y-%m-%d %H:%M:%S") utc_time = datetime.datetime.utcnow() local_time = (pytz.utc.localize(utc_time, is_dst=None).astimezone(tz)) led_off() GPIO.output(13, 0) # Turn on the green switch LED. lcd.set_color(0.0, 1.0, 0.0) #Set LCD background color to green lcd.clear() lcd.set_cursor(3, 0) lcd.message("Pelle is full.") lcd.set_cursor(3, 2) lcd.message("He was fed at: ") lcd.set_cursor(6, 3) lcd.message(local_time.strftime("%I:%M %P")) with open('UTC-FedTime.txt', 'a') as file: file.write(timestr + "\n") with open('Local-FedTime.txt', 'a') as file: file.write((local_time.strftime("%Y-%m-%d %H:%M:%S")) + "\n") send_mail('user@mydomain.com', 'From Pelle', 'Somebody just fed me. Thanks!') time.sleep(5) # Set this sufficiently long to prevent multiple button presses # Check if it is the next day and if it is, reset the fish fed status to not fed. def check_date(): global FedStatus utc_time = datetime.datetime.utcnow() local_time = (pytz.utc.localize(utc_time, is_dst=None).astimezone(tz)) if (local_time.strftime('%H:%M:%S') == '00:00:00'): # This resets the fed status at midnight. time.sleep(1) # Added this delay to prevent it from refreshing the display during the first second of the day. reset_status() FedStatus = False # This checks to see if the fish was fed by 6:30, 7:00, and 7:30 pm, and if not, it sends a notification text message. def check_time(): global FedStatus utc_time = datetime.datetime.utcnow() local_time = (pytz.utc.localize(utc_time, is_dst=None).astimezone(tz)) if (local_time.strftime('%H:%M:%S') == '18:30:00') and (FedStatus == False): # This is the first check for feeding. time.sleep(1) send_mail('user@mydomain.com', 'From Pelle', "Hey! Nobody fed me today and I'm hungry. Please feed me!") if (local_time.strftime('%H:%M:%S') == '19:00:00') and (FedStatus == False): # This is the second check for feeding. time.sleep(1) send_mail('user@mydomain.com', 'From Pelle', "You forgot about me! Feed me please!") if (local_time.strftime('%H:%M:%S') == '19:30:00') and (FedStatus == False): # This is the third check for feeding time.sleep(1) send_mail('user@mydomain.com', 'From Pelle', "I'm going to die if nobody feeds me. Help!") if (local_time.strftime('%H:%M:%S') == '21:30:00') or (local_time.strftime('%H:%M:%S') == '21:30:01'): # This turns off all lights at night. time.sleep(3) led_off() # Turn off the switch LED. lcd.set_color(0.0, 0.0, 0.0) # Turn off the LCD backlight. if (local_time.strftime('%H:%M:%S') == '07:30:00') or (local_time.strftime('%H:%M:%S') == '07:30:01'): # This turns on all lights in the morning. time.sleep(3) # Added this delay to prevent it from refreshing the display during the first second of the day. if FedStatus == False: GPIO.output(19, GPIO.LOW) # This turns on the red switch LED. lcd.set_color(1.0, 0.0, 0.0) # Turn the LCD background color to red. if FedStatus == True: GPIO.output(13, GPIO.HIGH) # This turns on the green switch LED. lcd.set_color(0.0, 1.0, 0.0) #Set LCD background color to green # This is the function that sends an email message to the address indicated. def send_mail(recipient, subject, message): global error username = "insert your email username here" password = "abc123456" msg = MIMEMultipart() msg['From'] = username msg['To'] = recipient msg['Subject'] = subject msg.attach(MIMEText(message)) try: #print('sending mail to ' + recipient + ' on ' + subject) mailServer = smtplib.SMTP('smtp-mail.outlook.com', 587) mailServer.ehlo() mailServer.starttls() mailServer.ehlo() mailServer.login(username, password) mailServer.sendmail(username, recipient, msg.as_string()) mailServer.close() except error as e: print(str(e)) # ----------- The code that does stuff goes below this line ----------- # Set LCD to blue and switch to blue lcd.set_color(0.0, 0.0, 1.0) led_off() GPIO.output(26, GPIO.LOW) # This turns on the blue switch LED. # Print a two line welcome message lcd.clear() lcd.set_cursor(2, 0) lcd.message("Pelle's Fish Food") lcd.set_cursor(6, 1) lcd.message("Tracker") lcd.set_cursor(0, 2) lcd.message("Made in August 2017") lcd.set_cursor(2, 3) lcd.message("By Alligator") # Wait 5 seconds to read the welcome message time.sleep(5) reset_status() # This is needed to initialize the display to not fed status after the welcome message. while True: while (FedStatus == False): input_state = GPIO.input(12) check_time() if input_state == False: pelle_fed() FedStatus = True check_time() check_date()