#!/usr/bin/python
#Based on Adafruit's Raspberry Pi Lesson 11 Temperature sensing tutorial by Simon Monk
#Modified by John Vigilante 1/13/2017
#two Acurite 986 temp sensors to monitor the freezer and fridge unit 
#sendtext messages and email when temperature is out of range 

#import os
import time
import StringIO
from decimal import Decimal
import smtplib
from email.mime.text import MIMEText
import datetime
from time import sleep
import threading
import json
import pickle

global textsent  # used to avoid sending too many texts
global base_dir

# modify if necessary to reflect where your project is staged
base_dir = '/home/pi/Documents/FreezerProjects/'

textsent = pickle.load( open( base_dir + "save.dat", "rb" ) )


# init the acceptable temperature ranges - these will be overridden by config file 
# Define Workhours & Offhours by how you set this script to execute in cron

workLowFridge = 30
workHiFridge = 45
workLowFreezer = 30
workHiFreezer = 45


# Timer thread will kick off every xx seconds and measure the temperature
class TimerClass(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.event = threading.Event()

    def run(self):
        while not self.event.is_set():
            print "Checking Temperature......"
            fridgeTemp = read_temp(1) # sensor 1 is the Fridge unit
            freezerTemp = read_temp(2) # sensor 2 is the Freezer unit
            checkTempRanges(fridgeTemp, freezerTemp)       
            time.sleep( 2)  # Sleep between temperature checks
            self.event.wait( 6)

    def stop(self):
        self.event.set()


# reads the actual files where the record_986.py script recorded them.
def read_temp_raw(sense):

    if sense == 1:
      print "----sensor 1:----"
      f = open(device_file, 'r')
    else:
      print "----sensor 2:----"
      f = open(device_file_two, 'r')
 
    lines = f.readlines()
    f.close()
    print lines
    return lines

# read the temperature and return the Farenheit value to caller
def read_temp(sense):
    lines = read_temp_raw(sense)	 
    equals_pos = lines[0].find('t=')
    if equals_pos != -1:
        temp_string = lines[0][equals_pos+2:]
        temp_f = temp_string
#        return temp_c, temp_f   # no need to return celcius
##        print temp_f
        return str(temp_f)[:5]

# check the fridge and freezer temps passed in vs the allowed ranges and error out if invalid
def checkTempRanges(fridgeTemp, freezerTemp):
    global textsent
    print ("Temps to check: " + fridgeTemp + " " + freezerTemp)
    print "textsent is: ", textsent
    #print Decimal(fridgeTemp), Decimal(freezerTemp)
    # TODO: if workhours could have a different range
    if ((Decimal(fridgeTemp) > Decimal(workHiFridge)) or (Decimal(freezerTemp) > Decimal(workHiFreezer))):
##       print ("Temp too warm! Fridge: " + str(fridgeTemp) + " Freezer: " + str(freezerTemp) ) 
##       print workHiFridge
##       print workHiFreezer
##       print ("Text to number: " + phonenumber)

       if textsent is 0: # don't sent too many texts   
         sendTextMessageGmail("Temp too warm: Fridge =" + str(fridgeTemp) + " Freezer =" + str(freezerTemp), phonenumber, emailadd)
    if ((Decimal(fridgeTemp) < Decimal(workLowFridge)) or (Decimal(freezerTemp) < Decimal(workLowFreezer))):
##       print ("temp too cold! " + str(fridgeTemp) + ' ' + str(freezerTemp))
##       print ("Text to number: " + phonenumber)
	
       if textsent is 0: # don't sent too many texts   
         sendTextMessageGmail("Temp too cold: Fridge =" + str(fridgeTemp) + " Freezer =" + str(freezerTemp), phonenumber, emailadd)


# send a text message through gmail service
# ----------------------------------------------------
def sendTextMessageGmail(message,number,emailadd):
    global textsent
    #TODO only text every xx mins
    to = emailadd
    gmail_user = 'xxxxxxxxx@gmail.com'
    gmail_password = 'fhsjakhfkjasdhfksdhf'
    smtpserver = smtplib.SMTP('smtp.gmail.com', 587)
    smtpserver.ehlo()
    smtpserver.starttls()
    smtpserver.ehlo()
    smtpserver.login(gmail_user, gmail_password)
    today = datetime.date.today()
    msg = MIMEText(message)
    msg['Subject'] = 'Freezer Alert on %s' % today.strftime('%b %d %Y')
    msg['From'] = gmail_user
    msg['To'] = ", ".join(to)
    smtpserver.sendmail(gmail_user, to, msg.as_string())
    smtpserver.quit()

    try: 
      # save textsent = 1 so we do not sent emails repeatly.
      textsent = 1
      pickle.dump( 1, open( base_dir + "save.dat", "wb" ) )
    except:
      print "could not send text, internet access?"

## Codebegins here:

try:
  #device_folder = glob.glob(base_dir + '28*')[0]
  #device_file = device_folder + '/w1_slave'
  device_file = base_dir + 'R1.dat'

##  print device_folder
  #device_folder_two = glob.glob(base_dir + '28*')[1]
  #device_file_two = device_folder_two + '/w1_slave'
  device_file_two = base_dir + 'F1.dat'
##  print device_folder_two
except:
  print "Error 23 reading temp sensor file, sensors connected?"
  exit(23)  

# Read config file to set defaults
# Config file contains a json construct for each of these(in Farenheit)
# Low Fridge Temp, High Fridge Temp
# Low Freezer Temp, High Freezer Temp
# Phone number to text 1xxxyyyzzzz
# Email address yourname.email.com

try:
    with open(base_dir + 't4sensorjson.cfg') as data_file:    
        data = json.load(data_file)
except:
    print "Error 22 on file Open t4sensorjson.cfg"
    exit(22)

workLowFridge = data["S1_Low"]
workHiFridge = data["S1_High"]
workLowFreezer= data["S2_Low"]
workHiFreezer= data["S2_High"]
phonenumber= data["TextID"]
emailadd = data["EmailID"]

#Debug print lines

# display acceptable temperature ranges from config file
print "Acceptable temperature range:\n"
print "Fridge:  %sF to %sF" % (workLowFridge,workHiFridge)
print "Freezer: %sF to %sF\n" % (workLowFreezer,workHiFreezer)

#time.sleep( 1 )
#print "setting up timer for tempcheck"

tmr = TimerClass()
tmr.start()  # start the timer thread which will wake up and measure temperature

time.sleep( 15 )
tmr.stop()
time.sleep( 1 )    # sleep so we can clear the screen

