Alarm

Building a custom home alarm system.

CONSIDERATIONS

It all started in the summer of 2011 where my basement was flooded during a heavy rain storm. No great damage was done that time, but what about next time? It initiated the idea of building an alarm system that could monitor events in the house and send notifications of manual incidents as well a timed updates. But living in an old house presents a lot challenges in terms of wiring and modifications if you want to install a surveillance system.

The scope for me was to create a system that could give some kind of feed-back from unusual events happening when the family was away. This could be water leaks, smoke and human activity etc. For a start a simple e-mail reminder could be useful so neighbours could be contacted in case something unusual is happening while travelling. Later on an SMS service was added.

Standard alarm systems are easy to operate and install but they often miss features that can combine motion activity with other useful inputs and outputs from a private house. The choice could therefore be to install some of the expensive home automation systems with a lot of standard interface boxes and a nice programming user interface.

Instead I decided to try out the Raspberry Pi (RPi). It is a cheap device which has a nice and rare combination of programming features and pins that can be connected to different sensors/buttons. The device operates in an open source environment and there are some standard programs that can be used for surveillance purposes. But if you want a true custom installation you have to build everything yourself.

Using the RPi presents a lot of technical challenges so some tech knowledge is necessary in order to succeed.  But being systematic and dividing the project up in to smaller chunks helps a lot for understanding, designing, installing and operating a system based on the RPi. A custom and wired installation also benefits from a central control with one power source for all devices saving you from maintenance and battery changes around the installation.

The Raspberry forum has a lot of many nice examples that can be picked up for inspiration so benefitting from this shared environment also encouraged me to make this documentation in order to share my experiences with other newcomers.

DESIGN

Designing the connection of peripherals to the RPi is the best way to start. During this process a lot of considerations and decisions are made in terms of functionality and which components to use. And its easy to add new features when they pop up (and they will do).

Once made the design is a great help when wiring the house  and purchasing electronics and components for building the interface board for the RPi. All devices that were previously installed in the house were also connected to the system (door bell, PIR etc.)

The design can be seen here

Colored cables are used in the installation and electronics for easy testing and error checking.

INTERFACING

There are several options for interfacing the RPi to peripherals such as the Slice of Pi and Humble Pi boards on which you can solder your electronic components. These are an excellent solution if you want a compact installation as they can be fitted on top of the RPi in one of the standard RPi cases.

Another option is to buy a bread board which is good for prototyping and the use this in the installation. But it takes up some space.

For this project a prototype interface board was built on a print test board with copper strips. It is easy to cut the strips eg if you mount a resistor on top of them. This also gives the ability of making “bus-lines” eg for Ground or Power distribution.

Next consideration is connectors to the board. If you go for a compact installation there is no space for eg the Molex 2,54mm connectors on the interface board if you need to keep everything  inside the standard casing. You can decide to build a break-out box and connect the two with a standard 26p flat cable. This enables you to use large connectors to your different peripherals and protect the RPi via resistors. The advantage is that the space gives a good freedom during testing (and reconstruction).

In my home installation I have an ethernet patch box equipped with RJ-45 connectors which lead to the different outlets in the house. Using some of the spare connectors in this box enables me to tie the RPi  to the box via CAT5 cables soldered directly to the interface board which is mounted on top of the RPi. Cutting some slices in the hood of the RPi case makes it possible to close and secure the unit after testing has been made making it a truly compact device in my installation.

The final unit with cables, modified hood and buzzer mounted on top of the print board. Ready for power supply before it is up and running.

From the patch box CAT5 cables go to the different peripherals and terminals.

SENSORS

The basement has two 220V PIR motion-sensors installed – one at each end of the staircase. Activating one of the sensors turns on the light so it stays on for five minutes. Using PIR instead of a standard power switch was a choice made during a renovation project as it is easy to forget to switch off the light when you leave the rooms downstairs as using a standard 220V switch the light can potentially stay on for a long time before the next person enters. The alarm system should thus connect to the PIR’s in a simple way. Dealing with 220 volts is not easy and it is not recommendable to connect the RPi directly to the power installation. Instead a simple spare power supply was connected to an extra 220V outlet for producing a 9 V DC voltage each time the light is switched on. By using a resistor and an opto coupler at the RPi interface board a safe power bridge is made between the two installations.

An extra low voltage PIR was installed in the entrance hall. This unit also has a “Tamper” switch in case someone tries to break the unit.

As smoke sensor the old fire alarm was used. It has two terminals inside which are used for connecting a series of alarms together, so if one alarm smells smoke then all alarms will sound. The terminal outputs around 5-6V when active and this is used for triggering the RPi via another opto coupler. Mounting the smoke alarm next to the PIR made it easy to take the 9V power supply and loop it from the PIR to the fire alarm so batteries are avoided.

A water leak sensor was a high priority as the basement was flooded during a rain storm in 2011. After the renovation the probability of a new event is much reduced but it will be an extra security to add this feature. The idea was to construct a primitive sensor based on some wires and a piece of kitchen roll. Adding some resistors together with a transistor at the RPi board then picks up the small current that would walk between the wires when the paper gets wet. Simple and cheap – but efficient!

ELECTRONICS

The opto coupler used for interfacing with the 220V PIR is the IL74 but there are a lot of other alternatives on the market if you can’t get this one.

Two transistors are used for driving the water leak input and the buzzer output respectively. Using transistors gives a good protection of the RPi and it also loops current away from the GPIO pins. The transistors used here are the BC 546C

Resistors are all standard carbon 5-10% resistors.

Piezo buzzers were selected for sound signalling as they are a very efficient when it comes to sound versus current consumption. Two buzzers are mounted in parallel – one at the board in the basement and one in the hall above the front door.

This board is too small if all GPIO ports needs to be used but for the initial use it worked fine. After six months it was decided to build an expansion board and connect the two boards with a 8-wire Molex connector. This open up for extended weather logging and triggers.

FUNCTIONALITY

The system had to be simple to operate and a high WAF is a prerequisite for daily use. So external keypads was quickly abandoned in favour of a simple on/off switch mounted inside beside the front door. The switch should turn on  alarm function for the movement sensors (PIR) in the entrance hall and in the basement. All other sensors should be armed all times.

When leaving the house, the switch is set to “on” position which starts a series of short beeps. After 30 seconds the beeps get longer and finally after 40 seconds a long beep is heard in order to show that the alarm is now armed eg if you wait outside the door. The system is now armed and a service message will be sent by mail.

Entering the house through the main door will almost immediately trigger the PIR sensor which invokes a loop of 30 seconds with a series of short beeps that should remind the incoming person to switch off the system. Doing so stops the loop immediately.

If an intruder enters the house through the basement the system will switch to alarm mode when the light turns on through the PIR sensors. If entering directly in to the ground floor the intruder will be caught by the PIR in the hall which starts the warning loop. Assuming that he/she will not find the Off switch as it looks like a normal light switch the system will switch to alarm mode after 30 seconds. If the house is entered from the first floor there is no PIR up there to catch the intruder. Obviously he will descend some time and then be caught by the PIR in the Hall.

In Alarm mode a series of “SOS” beeps will be sound at the buzzers installed and a “Alarm” warning message will be sent by mail with information about which sensor that was activated. Same thing will happen if one of the other sensors (smoke, water etc) are triggered while system is disarmed (and armed).

A function sends a mail every day in order to show that the system is alive. This feature is nice to have when leaving the house for longer vacations.

All mails can also be converted to SMS if you want a direct and quick information about an event.

PROGRAMMING

Python was selected as the programming language as it is recommended for RPi usage. I had no previous experience with Python and was only familiar with Basic and Visual Basic. It seemed to be a good back-ground as there are a lot of similarities. However Python is not so helpful with debugging as VB and especially the sensivity to correct casing causes some extra debugging in comparison to what I am used to.

There are some general differences you have to observe when walking from VB to Python:
<ul>
<li>Be aware of casing. Sometimes you have to start with a capital letter (“True”, “False” etc.) and sometimes not (“if”, “while”, “def” etc.).</li>
<li>def is the same function as a SUB routine</li>
<li>Using variables in the different modules (def’s) is fine as long as they are declared Global in the def.</li>
<li>Use threads if you want a def to run independently of the rest of your program</li>
</ul>
In general two resistors are used for the IN functions as I doubted that the internal resistors could provide full protection if I did something wrong. The input circuitry pulls the level down to ground by default and up to 3,3 volts of an event happens. The two PIR outputs from the hall are both closed by default so the programming has to be opposite for those.

Assuming that PIN 3 and 5 could be set-up for this kind of inputs was wrong. They can only be triggered if the input level is taken down as the internal pull up resistor can’t be disabled (at least I couldn’t find a way). This is also the reason for using BCM mode instead of BOARD mode as I saw someone recommending this for solving the PIN 3+5 problems. It didn’t help but I let the programming stay in BCM mode (for now). I will recommend BOARD mode for other projects as BCM doesn’t make sense to me as it is a source of unnecessary distraction to change pin numbers to something that isn’t logical even though that BCM should be compatible to other types of hardware. Instead of changing wiring so PINs 3+5 could be ground connected I decided to leave them free as they can be used if you want to expand GPIO’s at a later time (see links at bottom of the document).

All programming should be made directly at the RPi for quick testing of the GPIO functionality. Your old TFT with analog input can get a revival if you buy a HDMI-&gt;VGA <a href=”http://www.newegg.com/Product/Product.aspx?Item=N82E16812400359″ target=”_blank”>adapter</a>. It works in contradiction to what is (was?) posted somewhere at the RPi site.

It is also possible to install Python at your PC and do the coding there but then there is no way of testing the GPIO’s unless the code is transferred to the RPi. This can be done via FTP if you know the unit’s IP-address but it is not advisable to follow this procedure before you know that the electronics is working and you have gained some knowledge about Python. The RPi makes it possible to overwrite the program while it is running in contradiction to Windows. So you can do some adjustments on your PC’s Python program and the transfer this to the RPi that just has to be rebooted for the changes to take effect. With the remote terminal program PuTTy you can also test your new version on top of the old version.

There’s no GUI or displays for this installation. The only feed-back I get is the audible beeps when the system boots and alarm is armed together with a blinking LED outside the front door. If a monitor is connected to the RPi there will however be some “print events” displayed but no interactivity.

When the program is ready it is logical to start the alarm program every time the unit boots. This is done by editing the  /etc/rc.local file. You have to do this in command mode, that is starting the terminal where you type “sudo leafpad”. Then insert this line: (sleep 5; sudo python  /home/pi/projects/alarm.py) and make sure the last line is “exit 0″.

The code is <a title=”Code” href=”http://jesperbonde.dk/rpi/alarm/code/”>here</a>

I’ve made a page <a title=”SMS” href=”http://jesperbonde.dk/rpi/alarm/sms/”>here </a>which describes how an SMS function was added to the project.

TESTING

For testing the electronics and programming (and learning) I decided to build a “dummy” of the house interfaces so I could sit down next to my work station in order to use it for research and debugging. As the installation is made with CAT5 and RJ-45 connectors, three cables were made with some spare components that can be quickly connected when the RPi is removed from the basement installation.

INSTALLATION

It was decided to use CAT5 cables for wiring as they were “on stock” already. Two new cables were drawn from hall to the RJ45 patch bay in the basement and extra cable trays mounted in the hall. A standard 220V switch was mounted next to the front door for easy Alarm control. And finally the new PIR sensor was mounted in the hall.

In the basement three new RJ-45 connectors were mounted in the patch bay. One of them leading to a terminal where inputs from power supplies and water leak resistor could be connected. The other two connects to the cables to the hall.

So this is how it looks like now: The basic network installation with the RPi added top right and the terminal break-out bottom left. Other components are ADSL router, switchers and landline-to-wireless phone.

 

CONCLUSION

This project has taken app 60-70 hours from the first idea to final use. The installation is easy to operate and is therefore used when leaving the house which is the most important prerequisite for functionality.

There are a lot of cheap and easy standard solutions out on the market but they don’t give as much fun, versatility and knowledge as with this technology. It is great to see that the functionality is exactly what our family need for daily use and to know that new features can easily be added in the future. The experience gained is highly useful for other projects at home and professional use as the RPi is highly adaptable to all purposes.

RAIN SENSOR

A digital/optical rain sensor has now been included in the set-up. More details <a title=”Rain sensor” href=”http://jesperbonde.dk/rpi/alarm/rain-sensor/”>here</a>

TEMPERATURE

Temperature sensors are now added to the system. A specification can be seen here (soon)

THE FUTURE

Plans for extra functionality and features are
<ul>
<li>Extending the “Tamper” circuit to include windows and outside doors</li>
<li>Connecting more water sensors in parallel</li>
<li>Temperature sensors</li>
<li>External light sensor for conditional programming (daylight sensor)</li>
<li>Heating control – lower temperature in house when alarm is armed.</li>
<li>Camera functionality</li>
<li>Perhaps some GUI stuff or touch display but at this time I don’t see that it is useful.</li>
</ul>
<span style=”line-height: 1.714285714; font-size: 1rem;”>LINKS</span>

<a style=”line-height: 1.714285714; font-size: 1rem;” href=”http://www.raspberrypi.org/” target=”_blank”>The Raspberry Site</a>

<a href=”https://docs.python.org/2/” target=”_blank”>Python programming</a>

<a href=”http://elinux.org/RPi_Low-level_peripherals” target=”_blank”>Details about the GPIO</a>

The TI expander chip <a href=”http://www.ti.com.cn/cn/lit/ds/symlink/pcf8574a.pdf” target=”_blank”>PCF8574A</a> can be used if you need extra GPIO’s via pins 3+5

DISCLAIMER

Please respect that all the above information, guidelines, pictures and diagrams are published as a courtesy without warranty and responsibility and should be used at own risk.

&nbsp;

CODE

#alarm version without gdata
import RPi.GPIO as gpio
import string
import smtplib
from time import sleep
from datetime import datetime
import threading
import time
import os
import subprocess
import glob, sys
#import gdata.spreadsheet.service
import commands
from urllib import urlopen
import re
from ftplib import FTP
import ftplib

#GOOGLE:
#account details
gmail = 'you@gmail.com'
gpass = 'yourpass'
ghost = 'smtp.gmail.com:587'

#FTP information
FTPhost = 'ftpserver.zz'
FTPdomain = 'ftpdomain.zz'
FTPpass = 'yourpass'

# ID's of the different Google spreadsheets used for storing data
spr_key_event = '1QNmkzUWZKyZ6BYDu0B7UBJCcdiC9bLrg_vxXxBZIhtk' #Event log
spr_key_rainy_day = '1sidW4BTGui7frjRxehZlySCPe4oo_lSshNmGQDP0v3k' # Rain last 24H in 10 min intervals
spr_key_rainy_week = '1EFfRVuUIYqD9QObG0M_AgSmYjHYMd3kv2yvmHUrNSZM' # Rain last 2 weeks in 1H intervals
spr_key_rainy_year = '16R1nxxtNsrQNKULwiFXLzkvZUYaRc_N2XbgqcoVFnKE' #Rain last year with once daily updates
spr_key_temp_out = '1EflJUkzfxBI5vPTSAMh5Ds8Y01O63RGd5hCg2IFM50w' #Outside temperature the last 24h (Temp out)
spr_key_temp_now = '1iyAU5eHBeYHG3XHisUlPSWFEFM4dnc8_RkOR7AU108g' #Outside temperature right now (Temp now)
spr_key_temp_all = '1srQPRg9ZUfFLY_5z8m6DLgbz-Cz833S2HRz2alsWrRo' #All temperature sensors (Temp all) for internal use
spr_key_temp_extremes = '1Oe3DlM4uobJMgSfJw8Fucyd4qgDt7WgXn0BVFZRuFRw' #Outside temperature extremes

worksheet_id = 'od6' # worksheet #1 by default always has a value of 'od6' if necessary

# Mail default data
TO = "zz@zz.zz"
FROM = "zz@gmail.com"
TEXT = "Alarm event registered "
subject = "Default subject"
SUBJECT_before = "Before subject to send only one mail or SMS each time"
event_value = "something"
url = 'http://checkip.dyndns.org' # Check current IP address
iplookup = 'this has to be exchanged with the full ip information'
myip = '123.456.789.000'

#Declare rain variables
RAIN_10MIN = 0.0 #Accumulated rain mm in 10 minutes steps
RAIN_30MIN = 0.0 #Accumulated rain mm in 30 minutes steps
RAIN_HOUR = 0.0 #Accumulated rain the last whole hour
RAIN_DAY = 0.0 #"Accumulated rain for the day - reset every midnight"
RAIN_LO = 2.0 #Value for Heavy Rain mm/30 min
RAIN_MID = 2.0 #Value for Heavy Rain mm/30 min
RAIN_HI = 10.0 #Value for Skyfall mm/30 min (definition is 15mm/30min)
RAIN10A = 0.0 #Newest rain data for 10min interval
RAIN10B = 0.0 #Last rain data for 10min interval - before A
RAIN10C = 0.0 #Last rain data for 10min interval - before B

#Check if rain updates has been sent:
RAINDAY_UPDATE = True 
RAINWEEK_UPDATE = True 
RAINYEAR_UPDATE = True 

#temperature settings, load the kernel modules needed so directories are created for each sensor
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')

#Declare temperature variables and states
TEMP_OUT_READ = True
TEMP_OUT_UPDATE = True
TEMP_NOW_UPDATE = True
TEMP_ALL_UPDATE = True
TEMP_OUT = 0.0
TEMP_MAX = -20.0 #Max outdoor temperatue the last 24 hours (supposed to be higher than this)
TEMP_MIN = 60.0 #Min outdoor temperatue the last 24 hours (supposed to be lower than this)
temperature = 100
t_check = -100
t_last = 99 #store measurement from 10 mins ago for comparison

#Array with information about all tested sensors incl. color code, sensor ID, dict name, function, cell number and cable marker in tank
TempIDs = ["BLACK", "28-000005b16567", "out", "Outside temperature", "16", "X"],\
          ["BROWN", "28-000005b226ae", "water", "Water tank temp", "17", "A"], \
          ["RED", "28-000005b217e2", "radf", "Radiators forward temp", "18", "B"],\
          ["ORANGE", "28-000005b23020", "radr", "Radiators return temp", "19", "C"],\
          ["YELLOW", "28-000005b21d0d", "heatf", "Received power heating temp", "20", "D"], \
          ["GREEN", "28-000005b1b646", "heatr", "Returned power heating temp", "21", "E" ],\
          ["BLUE", "28-000005b1d70e", "floorf", "Floor heating forward temp", "22", "F"], \
          ["PURPLE", "28-000005b217eb", "floorr", "Floor heating return temp", "23", "G"],\
          ["BLACK - LOST BROWN", "28-000005b1a9e9", "xx", "xx", "24", "X"],\
          ["BROWN", "28-000005bxxxxx", "XX", "xx", "25", "Y"],\
          ["RED", "28-000005b22544", "dining", "Dining Room", "26", "Z"],\
          ["ORANGE", "28-000005b1725b", "living", "Living Room", "27", "Q"],\
          
#Event notices
SEND_SMS = False #Used for disabling too many SMS messages for some of the events
SEND_MAIL = True #Used for disabling too many mails for some of the events
SEND_EVENT = True #Used for disabling too many event updates

#Set the inputs and outputs
#gpio no. 4 is used for the DS18B20 temperature sensors with a 4K7 pull up resistor
gpio.setmode(gpio.BCM)
gpio.setup(3, gpio.OUT, pull_up_down=gpio.PUD_OFF) #Bell LED
# gpio no. 7 is reserved as an external trigger trigger pin OUT
gpio.setup(8, gpio.IN)  #External event trigger and test button switch IN
gpio.setup(9, gpio.IN)  #PIR Basement sensor
gpio.setup(10, gpio.IN) #PIR Hall alarm
gpio.setup(11, gpio.IN) #Floating sewer switch
gpio.setup(14, gpio.IN) #Power failure relay
gpio.setup(17, gpio.OUT) #Piezo buzzer
gpio.setup(18, gpio.IN) #Bell push button in the entrance hall
gpio.setup(22, gpio.IN) #PIR Hall tamper
gpio.setup(23, gpio.IN) #Main switch arming the alarm in the entrance hall
gpio.setup(24, gpio.IN) #Rain input from Hydreon sensor (50 ms bursts)
gpio.setup(25, gpio.IN) #Water Leak Basement sensor
gpio.setup(27, gpio.IN) #Smoke alarm

AlarmBellRunning = False #Only start one bell if someone sits at the button
AlarmBlinkRunning = False #Tells if the blink/buzz warning should be used
AlarmBuzzRunning = False #Tells if the buzzer is sounding SOS
AlarmDelayRunning = False #Tells if the Arm-timer is running
AlarmEvents = False #If events under the Alarm-Arm-Switch should run

#"before" values are used to compare current status to past in order to avoid mail loops
Update_before = gpio.input(8)
PIR_basement_before = gpio.input(9)
PIR_hall_before = gpio.input(10)
Float_before = gpio.input(11)
Bell_before = gpio.input(18)
Tamper_before = gpio.input(22)
Armed_before = gpio.input(23)
Rain_before = gpio.input(24)
Water_before = gpio.input(25)
Smoke_before = gpio.input(27)

#Miscellaneous
SpeedCount = 0 # Checking CPU performance
SpeedSample = 0 #Sample rate in Hz
SpeedTime = 0 #Mean time of one 'While Cycle'
PowerFailure = gpio.input(14) #Relay from UPS goes on when the PowerBank is looped through
SPR_FAIL = False # Set to True if anything went wrong uploading data to Google sheet

################################   FUNCTION DEFINITIONS   ##################################

def AlarmBell ():
        global AlarmBellRunning
        global SEND_SMS

        if Bell == True:
                AlarmBellRunning = True
                SEND_SMS = True
                EventNotice ("Bell: Someone at the door ")
                #print "Bell"
                gpio.output(17, True)
                gpio.output(3, True)
                sleep (2)
                gpio.output(17, False)
                gpio.output(3, False)
                AlarmBellRunning = False

def AlarmBlink ():
        global AlarmBlinkRunning

        AlarmBlinkRunning = True
        gpio.output(3, True)
        sleep(2)
        gpio.output(3, False)
        sleep(1)
        AlarmBlinkRunning = False

def AlarmBuzz (): #ALARM sound signal!
        global AlarmBuzzRunning

        AlarmBuzzRunning = True        
        for i in range (10): #SOS
                for n in range (3): 
                        gpio.output(17, True)
                        sleep (0.1)
                        gpio.output(17, False)
                        sleep (0.1)
                for n in range (3): 
                        gpio.output(17, True)
                        sleep (0.3)
                        gpio.output(17, False)
                        sleep (0.3)
                for n in range (3): 
                        gpio.output(17, True)
                        sleep (0.1)
                        gpio.output(17, False)
                        sleep (0.1)
                sleep (1)
        AlarmBuzzRunning = False        

def AlarmDelay (): #Function to delay the alarm sensors in order to get out out the house. Beeps are warning meanwhile.
        global SEND_SMS
        global AlarmEvents #passes value of this variable along to other modules
        global AlarmDelayRunning
        AlarmDelayRunning = True
        try:
                for i in range (100):
                        if Armed == True: #Checks that the Arm switch is still on for each loop
                                gpio.output(17, True)
                                sleep (0.1)
                                gpio.output(17, False)
                                sleep (2)
                for i in range (100): #Faster beeps
                        if Armed == True:
                                gpio.output(17, True)
                                sleep (0.2)
                                gpio.output(17, False)
                                sleep (0.1)
                if Armed == True: #Checks that the Arm switch is still on (no regrets)
                        sleep (0.2)
                        gpio.output(17, True)
                        sleep (5) #Long beep to indicate that the alarm is now armed if you are listening outside the front door
                        gpio.output(17, False)
                        SEND_SMS = False
                        EventNotice ("Alarm: Armed ")
                        #print "Alarm armed after delay"
                        AlarmEvents = True
                        AlarmDelayRunning = False
        except:
                LogFile (" AlarmDelay " )
                AlarmDelayRunning = False
        AlarmDelayRunning = False

def AlarmPIRhall (): #Runs if PIR hall is activated while Armed
        global SEND_SMS
        if Armed == True:
                for n in range (15): #Delay so you can get in and disarm before alarm goes on                                      
                        if Armed == True:
                                gpio.output(17, True)
                                sleep (0.3)
                                gpio.output(17, False)
                                sleep (1.5)
                if Armed == True: #Next block runs if alarm hasn't been disarmed after entrance
                        SEND_SMS = True
                        EventNotice ("Alarm: PIR hall ")  
                        #print "PIR hall alarm"
                        if AlarmBuzzRunning == False :
                                s=threading.Thread(target=AlarmBuzz)
                                s.start()

def AlarmSmoke ():
        global SEND_SMS
        sleep (0.3) #prevent false alarms
        if Smoke == True: # Fire alarm
                if  Smoke_before != Smoke: # Ensures that only one event is triggered
                        SEND_SMS = True
                        EventNotice ("Alarm: FIRE! ")
                        #print "FIRE!"
                        if AlarmBuzzRunning == False :
                                s=threading.Thread(target=AlarmBuzz)
                                s.start()                       

def AlarmTamper ():
        global SEND_SMS
        sleep (0.3) #Double check to avoid false alarms
        if Tamper == False:
                if  Tamper_before != Tamper: # Ensures that only one event is triggered
                        SEND_SMS = True
                        EventNotice ("Alarm: Tampering PIR in the hall ")
                        #print "Tamper" 
                        if AlarmBuzzRunning == False :
                                s=threading.Thread(target=AlarmBuzz)
                                s.start()

def EventNotice (subject): #Function to distribute info about each registered event
        global SUBJECT
        global SUBJECT_before
        global SEND_SMS
        global SEND_MAIL
        global SEND_EVENT
        global RAIN_10MIN, RAIN_30MIN, RAIN_HOUR, RAIN_DAY
        global TEMP_OUT, TEMP_MAX, TEMP_MIN
        global SpeedCount, SpeedSample, SpeedTime #Meantime of While cycles
        global PowerFailure
        global myip

        # Prepare the dictionary to write
        dict = {}
        dict['text'] = subject
        dict['date'] = time.strftime('%d/%m/%Y')
        dict['time'] = time.strftime('%H:%M:%S')
        dict['mm10'] = str(RAIN_10MIN)
        dict['mm30'] = str(RAIN_30MIN)
        dict['mmhour'] = str(RAIN_HOUR)
        dict['mmday'] = str(RAIN_DAY)
        dict['tamper'] = str(gpio.input(22))
        dict['armed'] = str(gpio.input(23))
        dict['water'] = str(gpio.input(25))
        dict['smoke'] = str(gpio.input(27))
        dict['hall'] = str(gpio.input(10))
        dict['base'] = str(gpio.input(9))
        dict['tout'] = str(TEMP_OUT)
        dict['tmax'] = str(TEMP_MAX)
        dict['tmin'] = str(TEMP_MIN)
        dict['sample'] = str(SpeedSample)
        dict['powerfail'] = str(PowerFailure)
        dict['myip'] = str(myip)
        d = open('/home/pi/Desktop/txt/dict.txt', 'w')
        d.write (str(dict))
        d.close()
        Upload('dict', 'txt')

        if SUBJECT_before != subject: #Ensures that only one update  will be made per event
                try:
                        if SEND_SMS == True:
                                SMS = "echo " + chr(34) + str(subject) + " " + chr(34)+ " | /usr/bin/gnokii --sendsms +1234567890 --smsc +1234567890"
                                os.popen(SMS)
                        if SEND_MAIL == True:
                                BODY = string.join((
                                "From: %s" % FROM,
                                "To: %s" % TO,
                                "Subject: %s" % subject,
                                "",
                                TEXT + time.strftime("%c"), str(dict)), "\r\n")
                                server = smtplib.SMTP(ghost)
                                server.ehlo()
                                server.starttls()
                                server.ehlo()
                                server.login(gmail, gpass)
                                server.sendmail(FROM, TO, BODY)
                                server.quit()
                        if SEND_EVENT == True:          
                                SprUpdate (dict, spr_key_event)
                
                except:
                        LogFile (" EventNotice " )
                SUBJECT_before = subject
                SEND_SMS = False
                SEND_MAIL = True
                SEND_EVENT = True

def LogFile (func): #Write to logfile if spreadsheet updates fail
        
        f = open('/home/pi/Desktop/alarm.txt', 'a')
        f.write(" Event registered for " + func + " at " + str(time.strftime('%d/%m/%Y %H:%M:%S')))
        f.close()

def RainAlerts (): #Calculate and warn for severe rain incidents
        global RAIN10A
        global RAIN10B
        global RAIN10C
        global RAIN_10MIN
        global RAIN_30MIN
        global RAIN_LO
        global RAIN_MID
        global RAIN_HI

        RAIN10C = RAIN10B
        RAIN10B = RAIN10A
        RAIN10A = RAIN_10MIN
        RAIN_30MIN = RAIN10A + RAIN10B + RAIN10C
        if RAIN_30MIN >= RAIN_LO:
                if RAIN_30MIN < RAIN_MID:
                        SEND_SMS = False
                        EventNotice ("Heavy Rain ")
        if RAIN_30MIN >= RAIN_MID:
                if RAIN_30MIN < RAIN_HI:
                        SEND_SMS = True
                        EventNotice ("Severe Rain ")
                        SEND_SMS = False
        if RAIN_30MIN >= RAIN_HI:
                SEND_SMS = True
                EventNotice ("Skyfall ")
                SEND_SMS = False 

def RainAppend (spr_key, rain_value): # Function to update any of the 3 Rain sheets
        global SPR_FAIL
        # Prepare the dictionary to write
        dict = {}
        dict['date'] = time.strftime('%d/%m/%Y %H:%M')
        dict['mm'] = str(rain_value)
        r=threading.Thread(target=SprUpdate (dict, spr_key))
        r.start()
        sleep (2)
        if SPR_FAIL == True: #Check if update was unsuccessful
                sleep (10)
                r=threading.Thread(target=SprUpdate (dict, spr_key)) 
                r.start() #Try again
                SPR_FAIL = False

def SprUpdate (dict, spr_key): #Generic function for updating all spreadsheets with 'dict'
        #DISABLED DUE TO GOOGLE PARANOIA AND THEIR OAUTH SYSTEM
        global SprDelete
        global SPR_FAIL
#       try:
#               entry = spr_client.InsertRow(dict, spr_key)
#               if SprDelete == True:
#                       sleep (0.2) #wait for the update before deleting the first line
#                       delfeed = spr_client.GetListFeed(spr_key)
#                       spr_client.DeleteRow(delfeed.entry[0])
#       except:
#               SPR_FAIL = True
#               LogFile (" SprUpdate ")

        SprDelete = True

def SprUpdateCell (value, cellno, spr_key): #Function to update single cells (temp, cell number and spreadsheet)
        sleep(1)#has to be something here instead .....
        
#       try:            
#               query = gdata.spreadsheet.service.CellQuery()
#               query.return_empty = "true" 
#               cells = spr_client.GetCellsFeed(spr_key, query=query)
#               batchRequest = gdata.spreadsheet.SpreadsheetsCellsFeed()  
#               cells.entry[int(str(cellno))].cell.inputValue = str(value)
#               batchRequest.AddUpdate(cells.entry[int(str(cellno))])  
#               updated = spr_client.ExecuteBatch(batchRequest, cells.GetBatchLink().href)
                
#       except:
#               LogFile (" SprUpdateCell had a problem. Temperature: " + str(value) + " Cell: " + str(cellno) + " Key: " + str(spr_key) + " ")

def TempAll(spr_key): #Compare the list of sensors with online sensors in order to know which ones to use
        global TEMP_MAX, TEMP_MIN, spr_key_temp_all, temperature, TempIDs
        OnlineIDs = commands.getoutput(' ls /sys/bus/w1/devices/ | grep -e "28-"').splitlines()  # Ids for sensors online

        dict = {} #Prepare data for spreadsheet
        
        #Open the CSV and write the header instead of old content
        r = open('/home/pi/Desktop/csv/temp.csv', 'w')
        r.write (time.strftime('Date %d-%m-%Y Time %H:%M:%S') + "," + "Degrees (C)" + '\r\n')
        r.close()

        try:
                i=0
                t=0
                u=0
                for i in range(len(OnlineIDs)):
                        a=OnlineIDs[i]
                        for t in range(len(TempIDs)): 
                                b=TempIDs[t][1]
                                if a==b:
                                        TempRead (str(TempIDs[t][1]))
                                        if temperature ==-0.062: #Check for error readings
                                                TempRead (str(TempIDs[t][1]))                           
                                        #u=int((TempIDs[t][2])-16
                                        #print str(TempIDs[t][0]) + " is " + str(temperature) + " deg C"
                                        dict[str(TempIDs[t][2])] = str(temperature) #Build the list for each run
                                        r = open('/home/pi/Desktop/csv/temp.csv', 'a') #Append the readings to the CSV
                                        r.write (str(TempIDs[t][3]) + "," + str(temperature) + '\r\n')
                                        r.close()
                                        #SprUpdateCell (str(TempIDs[t][2]), str(u), spr_key)
                                        SprUpdateCell (temperature, str(TempIDs[t][4]), spr_key)

        except:
                LogFile (" TempAll ")
        Upload ('temp','csv')

def TempAppend (spr_key, tempmax, tempmin): # Update the max and min temp sheet
        global SprDelete
        global SPR_FAIL
        
        SprDelete = False
        #Prepare the dictionary to write
        dict = {}
        dict['date'] = time.strftime('%d/%m/%Y')
        dict['tmax'] = str(tempmax)
        dict['tmin'] = str(tempmin)
        SprUpdate (dict, spr_key)
        sleep (2)
#       if SPR_FAIL == True: #Check if temp update was unsuccessful
#               sleep (10)
#               SprUpdate (dict, spr_key)
#               SPR_FAIL = False
        

def TempNow (): #Update the 'Temp now' Gauge spreadsheet every 10 mins
        global TEMP_OUT, TEMP_MAX, TEMP_MIN, spr_key_temp_now, i, t
        TempNowVal = [TEMP_OUT, TEMP_MAX, TEMP_MIN] #Array with the 3 outside temperatures
        i=0
        t=0     
        try:    #Update the 3 outside temperatures in the Temp Now spreadsheet by cells
                
                for t in range(len(TempNowVal)):
                        i=t+len(TempNowVal) #First cell number is 0 so second row starts with length
                        SprUpdateCell (str(TempNowVal[t]), i, spr_key_temp_now)
        except:
                LogFile (" TempNow ")
                
def TempOut (): #Update the 'Temp out' spreadsheet every 10 mins 
        global TEMP_OUT
        global TEMP_MAX
        global TEMP_MIN
        global spr_key_temp_out
        global temperature

        try:
                TempRead("28-000005b16567") #ID of outside sensor
                if temperature ==-0.062: #Check for errors
                        TempRead ("28-000005b16567")                            
                TEMP_OUT = temperature
                TEMP_MAX = var_read("TEMP_MAX")
                sleep(0.2)
                TEMP_MIN = var_read("TEMP_MIN")

                if TEMP_OUT > TEMP_MAX:
                        TEMP_MAX = TEMP_OUT
                        var_write("TEMP_MAX", TEMP_MAX) #saves new value
                        
                if TEMP_OUT < TEMP_MIN:
                        TEMP_MIN = TEMP_OUT
                        var_write("TEMP_MIN", TEMP_MIN) #saves new value
                        
                #Write the 3 values to a CSV file that can be uploaded and used for online charts
                t = open('/home/pi/Desktop/csv/tout.csv', 'w')
                t.write (time.strftime('Date %d-%m-%Y Time %H:%M:%S') + "," + "Degrees (C)" + '\r\n') # The '\r\n' is needed for correct linefeed
                t.write("Temp max," + str(TEMP_MAX) + '\r\n')
                t.write("Temp now," + str(TEMP_OUT) + '\r\n')
                t.write("Temp min," + str(TEMP_MIN) + '\r\n')
                t.close()
                Upload('tout','csv')

                #Append the current outside temperature to the daily temp CSV file that can be uploaded and used for online charts
                t = open('/home/pi/Desktop/csv/TEMP_DAY.csv', 'a')
                t.write (time.strftime('%H:%M:%S') + "," + str(TEMP_OUT) + '\r\n') # The '\r\n' is needed for correct linefeed
                t.close()
                Upload('TEMP_DAY','csv')

#               # Prepare the dictionary to write
#               dict = {}
#               dict['date'] = time.strftime('%d/%m/%Y %H:%M')
#               dict['tout'] = str(TEMP_OUT)
#               SprUpdate (dict, spr_key_temp_out)

        except:
                LogFile (" TempOut ")
                
def TempRead (tID): #Read the temperature of a specific sensor by ID and return as 'temperature'
        global temperature, t_check

        try:
                file = open("/sys/bus/w1/devices/" + tID + "/w1_slave") # Path of the sensor
                # Read all of the text in the file. 
                text = file.read() 
                # Close the file now that the text has been read. 
                file.close() 
                # Split the text with new lines (\n) and select the second line. 
                secondline = text.split("\n")[1] 
                # Split the line into words, referring to the spaces, and select the 10th word (counting from 0). 
                temperaturedata = secondline.split(" ")[9] 
                # The first two characters are "t=", so get rid of those and convert the temperature from a string to a number. 
                temperature = float(temperaturedata[2:]) 
                # Put the decimal point in the right place and display it. 
                temperature = temperature / 1000
                sleep (0.5)
                
                #Run the above one more time in order to compare for errors
                t_check = temperature
                file = open("/sys/bus/w1/devices/" + tID + "/w1_slave") # Path of the sensor
                text = file.read() 
                file.close() 
                secondline = text.split("\n")[1] 
                temperaturedata = secondline.split(" ")[9] 
                temperature = float(temperaturedata[2:]) 
                temperature = temperature / 1000

                if temperature != t_check: #make another measure if the first two were different
                        file = open("/sys/bus/w1/devices/" + tID + "/w1_slave") # Path of the sensor
                        text = file.read() 
                        file.close() 
                        secondline = text.split("\n")[1] 
                        temperaturedata = secondline.split(" ")[9] 
                        temperature = float(temperaturedata[2:]) 
                        temperature = temperature / 1000
                        
                if t_last != 99: #Don't do this at first run after reboot
                        if temperature-t_last>10: #skip if unrealistic high difference in measurement since last one
                                temperature=t_last     
                t_last = temperature

        except:
                LogFile (" Temp Read failure ")
                
def Upload (filename, ext): #Uploads the specified CSV file to the domain
        global FTPhost, FTPdomain, FTPpass
        fileup = '/home/pi/Desktop/' + str(ext) + '/' + str(filename) + '.' + str(ext)

        try:
                session = ftplib.FTP(str(FTPhost), str(FTPdomain), str(FTPpass))
                file = open(str(fileup),'rb')  # file to send
                session.cwd('/wp-content/uploads/') #change directory
                session.storbinary('STOR ' + str(filename) + "." + str(ext), file) # send the file
                file.close()                            # close file and FTP
                session.quit()
                
        except:
                print "FTP upload failed "

#Two functions to read and write variables to disk in order to save values and re-use after reboot.
def var_read(var):
        try:
                t = open('/home/pi/Desktop/var/' + str(var) + '.txt', 'r')
                return float(t.read())
                t.close()
        except:
                LogFile (" File read problem " )


def var_write(var, value):
        try:
                t = open('/home/pi/Desktop/var/' + str(var) + '.txt', 'w')
                t.write (str(value))
                t.close()
        except:
                LogFile (" File write problem " )

def checkmyip():
        global url, iplookup, myip

        try:
                iplookup = urlopen(url).read().decode('utf-8') # Open up the url, then read the contents, and take away to IP address
                myip = re.findall("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", iplookup) # Extract the IP address
                myip = str(myip)
        except:
                LogFile (" my ip problem " )


################################   BOOT PROCESS  ##################################

print "*************  Booting Alarm system  **************"

if PowerFailure == True: #Send an SMS if the power failure pin is high
        SMS = "echo " + chr(34) + "Power failure " + chr(34)+ " | /usr/bin/gnokii --sendsms +4521214544 --smsc +4571781877"
        os.popen(SMS)
        sleep(40) #Take a nap - the rest might not work as the network is also down.

#Read stored variables
RAIN_DAY = var_read("RAIN_DAY")
TEMP_MAX = var_read("TEMP_MAX")
TEMP_MIN = var_read("TEMP_MIN")

m=threading.Thread(target=checkmyip)
m.start()
sleep (5) #wait for the IP to be retrieved

if PowerFailure == False:
        SEND_SMS = True
        #Initializing spreadsheet service
#       spr_client = gdata.spreadsheet.service.SpreadsheetsService()
#       spr_client.email = gmail
#       spr_client.password = gpass
#       spr_client.source = 'Example Spreadsheet Writing Application'
#       spr_client.ProgrammaticLogin()
#       SprDelete = True #If false then first line is not deleted after appending a new line
        EventNotice ("Alarm was booted ")
                
if Armed_before == True: #Check if reboot is made while house is left - eg after power failure
        Armed_before = False

#Read sensors that are online 
OnlineIDs = commands.getoutput(' ls /sys/bus/w1/devices/ | grep -e "28-"').splitlines()  # Get IDs for sensors online
TempAll (spr_key_temp_all) #Update the Temp All spreadsheet
sleep (2)

#print "TempAll updated"
print "Total amount of installed temp sensors: " + str(len(TempIDs))
print "Amount of online temp sensors: " + str(len(OnlineIDs))
print "ID of online sensors: " + str(OnlineIDs)

TempNow () #Update the Temp Now spreadsheet
print "TempNow updated"

LogFile (" Booooted ")
print "LogFile updated"

print "The current IP address is: " + str(myip)

for i in range (2): #Two beeps/blink to tell that the boot process has ended
        gpio.output(17, True)
        gpio.output(3, True)
        sleep (0.2)
        gpio.output(17, False)
        gpio.output(3, False)
        sleep (0.2)

print "*************  Boot process finished  **************"

####################### END OF BOOT PROCESS ############################

while True:
             
        Update = gpio.input(8)
        PIR_basement = gpio.input(9)
        PIR_hall = gpio.input(10)
        Float = gpio.input(11)
        Bell = gpio.input(18)
        Tamper = gpio.input(22)
        Armed = gpio.input(23)
        Rain = gpio.input(24)
        Water = gpio.input(25)
        Smoke = gpio.input(27)
        minw = str(time.strftime ("%M"))# Watching minutes
        

################################   MANUAL EVENTS   ##################################

        #Section for events that should always run when system is powered
        
        if Bell == True:
                if  Bell_before != Bell: # Ensures that only one event is triggered
                        if AlarmBellRunning == False:
                                b=threading.Thread(target=AlarmBell)
                                b.start()
                                
        if Update == True: #Request  for status update via SSH on pin 8
                if Update != Update_before:
                        SEND_SMS = True
                        EventNotice ("Status requested ")                
                
        if Update == False: #prepare for another update request if required
                if Update != Update_before:
                        SUBJECT_before = "Status pin is low again "

        if Rain == True: #Rain detected (0,2 mm)
                if  Rain_before != Rain: # Ensures that only one event is triggered
                        RAIN_10MIN = RAIN_10MIN + 0.2
                        RAIN_DAY = var_read("RAIN_DAY")
                        sleep(0.2)
                        RAIN_DAY = RAIN_DAY + 0.2 #summarizing rain for all day
                        var_write("RAIN_DAY", RAIN_DAY) #saves values after reboot
                        RAIN_HOUR = RAIN_HOUR + 0.2 #accumulated rain for current hour
                        SUBJECT_before ="Is it still raining? " #subsequently send mails with rain info if nothing else happened since last mm count 
                        
 
        if Smoke == True: # Fire alarm
                if  Smoke_before != Smoke: # Ensures that only one event is triggered            
                        SEND_SMS = True
                        s=threading.Thread(target=AlarmSmoke)
                        s.start()

        if Float == True: # Sewer flooded
                if  Float_before != Float: # Ensures that only one event is triggered            
                        SEND_SMS = True
                        EventNotice ("Alarm: FLOAT ")

        if Tamper == False: 
                if  Tamper_before != Tamper: # Ensures that only one event is triggered            
                        t=threading.Thread(target=AlarmTamper)
                        t.start()

        #if Water == True: #Water leak
               #if  Water_before != Water: # Ensures that only one event is triggered
                       #SEND_SMS = False
                       #EventNotice ("Alarm: WATER! ")  
#                       print "Water"
#                       if AlarmBuzzRunning == False :
#                               s=threading.Thread(target=AlarmBuzz)
#                               s.start()


################################   TIMED EVENTS   ##################################

        #Section for events that are activated around the clock 24-7(mainly Google updates)


        if minw[-1:] == "2": #Update the outside thermometer every 10 min and make new Max and Min's
                if TEMP_OUT_UPDATE == True:
                        t=threading.Thread(target=TempOut())
                        t.start()
                        TEMP_OUT_UPDATE = False

        if minw[-1:] == "3": #Update the thermometer gauge spreadsheet every 10 min
                if TEMP_NOW_UPDATE == True:
                        n=threading.Thread(target=TempNow())
                        n.start()
                        TEMP_NOW_UPDATE = False

        if minw[-1:] == "4": #Update the sensor spreadsheet every 10 min
                if TEMP_ALL_UPDATE == True:
                        a=threading.Thread(target=TempAll(spr_key_temp_all))
                        a.start()
                        TEMP_ALL_UPDATE = False

        if minw[-1:] == "5": #Update the  Rainy DAY sheet every 10 min
                if RAINDAY_UPDATE == True:
                        r=threading.Thread(target=RainAppend(spr_key_rainy_day, RAIN_10MIN))
                        r.start()
                        #print "Starting next 10 min loop"
                        r = open('/home/pi/Desktop/csv/RAIN_DAY.csv', 'a') #add values
                        r.write (time.strftime ("%H:%M") + ":00," + str(RAIN_10MIN) + '\r\n')
                        r.close()
                        Upload('RAIN_DAY','csv')
                        a = open('/home/pi/Desktop/csv/RAIN_ACC.csv', 'a') #add values
                        a.write (time.strftime ("%H:%M:%S")+ "," + str(RAIN_DAY) + '\r\n')
                        a.close()
                        Upload('RAIN_ACC','csv')
                        RAINDAY_UPDATE = False
                        RAIN_10MIN = 0
                                                                                                                                                                                                
        if minw[-1:] == "6": 
                #Prepare for next Update of the rain- and temp sheets (10 min)
                RAINDAY_UPDATE = True
                TEMP_OUT_READ = True
                TEMP_OUT_UPDATE = True
                TEMP_NOW_UPDATE = True
                TEMP_ALL_UPDATE = True
                #print "Ready for next 10 min loop"

                if RAINDAY_UPDATE == False: #Check for heavy rain
                        h=threading.Thread(target=RainAlerts())
                        h.start()
                        RAINDAY_UPDATE = True

#       if minw[-1:] == "7": 

        if time.strftime ("%M") == "57": #Prepare for next Update of the WEEK sheet
                if RAINWEEK_UPDATE == False:                   
                        RAINWEEK_UPDATE = True

        if time.strftime ("%M") == "00": #Update the Rainy WEEK sheet every hour
                if RAINWEEK_UPDATE == True:
                        w=threading.Thread(target=RainAppend(spr_key_rainy_week, RAIN_HOUR))
                        w.start()
                        RAIN_HOUR=0
                        RAINWEEK_UPDATE = False
                        #print "starting next 1 hour loop"

        if time.strftime ("%H:%M:%S") == "23:57:10": #Prepare speed counting 
                SpeedCount=0

        if time.strftime ("%H:%M:%S") == "23:57:20": #Speed count test through 1 second
                SpeedCount = SpeedCount+1

        if time.strftime ("%H:%M:%S") == "23:57:30": #Prepare daily update of the Rainy YEAR sheet
                SpeedSample = SpeedCount
                SpeedTime = 1000/SpeedSample
                if RAINYEAR_UPDATE == False:
                        RAINYEAR_UPDATE = True
                        
        if time.strftime ("%H:%M:%S") == "23:57:40": #Daily update of the Rainy YEAR and TEMP sheets
                if RAINYEAR_UPDATE == True:
                        SprDelete = False
                        r=threading.Thread(target=RainAppend(spr_key_rainy_year, RAIN_DAY))
                        r.start()
                        SEND_SMS = False
                        SEND_MAIL = False
                        r = open('/home/pi/Desktop/csv/RAIN_YEAR.csv', 'a')
                        r.write (time.strftime('%d/%m/%Y') + "," + str(RAIN_DAY) + '\r\n')
                        r.close()
                        sleep(5)
                        Upload ('RAIN_YEAR','csv')
                        EventNotice ("Resetting rain counters. ")
                        sleep(5)
                        RAIN_DAY = 0.0
                        var_write("RAIN_DAY", RAIN_DAY) #reset file as well
                        sleep(5)
                        #Store and reset outside temp
                        t=threading.Thread(target=TempAppend(spr_key_temp_extremes, TEMP_MAX, TEMP_MIN))
                        t.start()
                        sleep(2)
                        r = open('/home/pi/Desktop/csv/TEMP_YEAR.csv', 'a')
                        r.write (time.strftime('%d/%m/%Y') + "," + str(TEMP_MIN) + "," + str(TEMP_MAX) + '\r\n')
                        r.close()
                        sleep(2)
                        Upload ('TEMP_YEAR','csv')
                        sleep(2)
                        TEMP_MAX = -20.0
                        var_write("TEMP_MAX", TEMP_MAX) #reset max temperature
                        sleep(2)
                        TEMP_MIN = 60.0
                        var_write("TEMP_MIN", TEMP_MIN) #reset min temperature
                        RAINYEAR_UPDATE = False
                        #"starting next 24 hour loop"
                        r = open('/home/pi/Desktop/csv/RAIN_DAY.csv', 'w') #prepare a new daily rain file
                        r.write ("time,mm" + '\r\n')
                        r.close()
                        t = open('/home/pi/Desktop/csv/TEMP_DAY.csv', 'w') #prepare a new daily temperature file
                        t.write ("time,deg" + '\r\n')
                        t.close()
                        a = open('/home/pi/Desktop/csv/RAIN_ACC.csv', 'w') #prepare a new daily accumulated rain file
                        a.write ("time,mm" + '\r\n')
                        a.close()

################################   ARMED ALARM EVENTS   ##################################
                    
        #Section for events that should run only when house is left
                        
        if Armed == True:
                try:
                        if  Armed_before != Armed: # Ensures that only one delay is executed
                                if AlarmDelayRunning == False: #Activates Arm delay for house exit
                                        t=threading.Thread(target=AlarmDelay)
                                        t.start()

                        if AlarmBlinkRunning == False: #Blink sequence
                                sleep (0.01)
                                if AlarmBlinkRunning == False: #Avoid double loops
                                        b=threading.Thread(target=AlarmBlink)
                                        b.start()
                                        
                        if time.strftime ("%H:%M:%S") == "12:00:00": #Once daily notification without SMS
                                #print "Still Alive!"
                                SEND_SMS = False
                                SEND_MAIL = True
                                n=threading.Thread(target=EventNotice ("Alarm is still alive 12.00 "))
                                n.start()
                
                        if time.strftime ("%H:%M:%S") == "17:00:00": #Once daily notification with SMS during vacations etc
                                #print "Still Alive!"
                                SEND_SMS = True
                                SEND_MAIL = True
                                s=threading.Thread(target=EventNotice ("Alarm is still alive 17.00 "))
                                s.start()

                        if AlarmEvents == True: #Events that will run only after the Armed delay is over
                                
                        # Ensure that only one mail is sent and that it doesn't fire if active when alarm is armed
                                if  PIR_hall_before != PIR_hall: 
                                        if PIR_hall == False:
                                                a=threading.Thread(target=AlarmPIRhall)
                                                a.start()
                  
                                if  PIR_basement_before != PIR_basement:
                                        if PIR_basement == True:
                                                SEND_SMS = True
                                                EventNotice ("Alarm: PIR basement ")  
                                                #print "PIR basement alarm"
                                                if AlarmBuzzRunning == False :
                                                        s=threading.Thread(target=AlarmBuzz)
                                                        s.start()
                except:
                        LogFile (" Arming failed ")
                        

        if Armed == False:
                if AlarmEvents == True:
                        if  Armed_before != Armed: # Ensures that only one mail is sent
                                #print "Alarm disarmed"
                                SEND_SMS = True
                                EventNotice ("Alarm: Disarmed ")
                        AlarmEvents = False                
                
################################   RESET   ##################################

        #Reset all variables once every cycle

        PIR_basement_before = PIR_basement
        PIR_hall_before = PIR_hall       
        Armed_before = Armed
        Water_before = Water
        Rain_before = Rain
        Smoke_before = Smoke
        Tamper_before = Tamper
        Bell_before = Bell
        Update_before = Update
        
gpio.cleanup()

#THIS IS THE END