-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathcontrol.py
More file actions
257 lines (211 loc) · 9.37 KB
/
control.py
File metadata and controls
257 lines (211 loc) · 9.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
#!/usr/bin/env python3
# *****************************************
# Garage Door Control Python script
# *****************************************
#
# Description: This script will read the states.txt file and set relays/LEDs
# upon any changes to that file. This script also accepts input from the IR
# sensor and will write the states.txt file and set the relays appropriately.
#
# This script runs as a separate process from the Flask / Gunicorn
# implementation which handles the web interface.
#
# *****************************************
# Imports
import time
import datetime
import os
import json
import smtplib
import requests
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import urllib.request, urllib.parse, urllib.error
import RPi.GPIO as GPIO
from common import *
# GPIO Definitions
relay_pin = 15 # GPIO 15, Pin 10 (RasPi Header)
relay_gate_pin = 14 # GPIO 14, Pin 08 (RasPi Header)
switch_pin = 18 # GPIO 18, Pin 12 (RasPi Header)
# Init GPIO's to default values / behavior
GPIO.setmode(GPIO.BCM)
GPIO.setup(relay_pin, GPIO.OUT, initial=0) # Setup Relay IN1 on GPIO
GPIO.setup(relay_gate_pin, GPIO.OUT, initial=0) # Setup Relay IN2 on GPIO
GPIO.setup(switch_pin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # Setup Magnetic Switch on GPIO18 (set pull down)
timer_start = 0 # Initialize timer_start variable, set to 0
reminder_timer_start = 0 # Initialize reminder_timer_start, set to 0
notify_on_close = False # Initialize the flag for notifying that the door has closed
opened_at = 0 # Time the door was opened
def SendEmail(settings, notifyevent):
# WriteLog("[DEBUG]: SndEmail Function. " + notifyevent)
now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M')
if notifyevent == "GarageEvent_Open_Alarm" or notifyevent == "GarageEvent_StillOpen_Alarm":
open_minutes = int((time.time() - opened_at) / 60)
notifymessage = "GarageZero wants you to know that your garage door has been open for %d minutes at %s" % (open_minutes, now)
subjectmessage = "GarageZero: Door Open for %d Minutes" % open_minutes
elif notifyevent == "GarageEvent_Closed":
notifymessage = "GarageZero wants you to know that your garage door was closed at " + now
subjectmessage = "GarageZero: Closed at " + str(now)
elif notifyevent == "GarageEvent_Notify_on_Open":
return # don't send emails for these
else:
notifymessage = "Whoops! GarageZero had the following unhandled notify event: " + notifyevent + " at " + now
subjectmessage = "GarageZero: Unknown Notification at " + str(now)
notifymessage += "\n\nCheck: " + settings['misc']['PublicURL']
try:
fromaddr = settings['email']['FromEmail']
toaddr = settings['email']['ToEmail']
toaddrlist = [addr.strip() for addr in toaddr.split(',')] # split on commas and strip out any spaces
msg = MIMEMultipart()
msg['From'] = fromaddr
msg['To'] = ', '.join(toaddrlist)
msg['Subject'] = subjectmessage
body = notifymessage
msg.attach(MIMEText(body, 'plain'))
server = smtplib.SMTP(settings['email']['SMTPServer'], settings['email']['SMTPPort'])
if settings['email']['UseTLS']:
server.starttls()
if settings['email']['Username']:
server.login(settings['email']['Username'], settings['email']['Password'])
text = msg.as_string()
server.sendmail(fromaddr, toaddrlist, text)
server.quit()
for addr in toaddrlist:
event = subjectmessage + ". E-mail notification sent to: " + addr
WriteLog(event)
except smtplib.SMTPException as e:
event = "E-mail notification failed. SMTPLib general exception: %s" % e
WriteLog(event)
except Exception as e:
event = "E-mail notification failed, with exception: %s" % e
WriteLog(event)
return()
def SendPushoverNotification(settings,notifyevent):
now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M')
if notifyevent == "GarageEvent_Open_Alarm" or notifyevent == "GarageEvent_StillOpen_Alarm":
open_minutes = int((time.time() - opened_at) / 60)
notifymessage = "GarageZero wants you to know that your garage door has been open for %d minutes at %s" % (open_minutes, now)
subjectmessage = "GarageZero: Door Open for %d Minutes" % open_minutes
elif notifyevent == "GarageEvent_Closed":
notifymessage = "GarageZero wants you to know that your garage door was closed at " + now
subjectmessage = "GarageZero: Closed at " + str(now)
elif notifyevent == "GarageEvent_Notify_on_Open":
notifymessage = "GarageZero wants you to know that your garage door was just opened at " + now
subjectmessage = "GarageZero: Opened at " + str(now)
else:
notifymessage = "Whoops! GarageZero had the following unhandled notify event: " + notifyevent + " at " + now
subjectmessage = "GarageZero: Unknown Notification at " + str(now)
url = 'https://api.pushover.net/1/messages.json'
for user in settings['pushover']['UserKeys'].split(','):
try:
r = requests.post(url, data={
"token": settings['pushover']['APIKey'],
"user": user.strip(),
"message": notifymessage,
"title": subjectmessage,
"url": settings['misc']['PublicURL']
})
WriteLog('Pushover Response: ' + r.text)
WriteLog(subjectmessage + ". Pushover notification sent to: " + user.strip())
except Exception as e:
WriteLog("Pushover Notification to %s failed: %s" % (user, e))
except:
WriteLog("Pushover Notification to %s failed for unknown reason." % (user))
def SendIFTTTNotification(settings,notifyevent):
# WriteLog("[DEBUG]: SendIFTTTNotification Function. " + notifyevent)
key = settings['ifttt']['APIKey']
url = 'https://maker.ifttt.com/trigger/' + notifyevent + '/with/key/' + key
if notifyevent == "GarageEvent_Open_Alarm":
query_args = { "value1" : str(settings['notification']['minutes']) }
elif notifyevent == "GarageEvent_StillOpen_Alarm":
open_minutes = int((time.time() - opened_at) / 60)
query_args = { "value1" : open_minutes }
else:
query_args = {}
try:
r = requests.post(url, data=query_args)
WriteLog("IFTTT Notification Success: " + r.text)
except:
WriteLog("IFTTT Notification Failed: " + r.text)
def SendNotification(settings,notifyevent):
if settings['email']['FromEmail'] != "":
SendEmail(settings, notifyevent)
if settings['pushover']['APIKey']:
SendPushoverNotification(settings, notifyevent)
if settings['ifttt']['APIKey'] != "0":
SendIFTTTNotification(settings, notifyevent)
def ToggleRelay():
# *****************************************
# Function to Toggle Relay (and open/close the garage door)
# *****************************************
# Insert code to push button here
GPIO.output(relay_pin, 1) #Turn on Relay
time.sleep(0.5) #Wait for 0.5s
GPIO.output(relay_pin, 0) #Turn off Relay
def CheckDoorState(states, settings):
# *****************************************
# Check switch state Open / Closed
# Function run from Readstates()
# *****************************************
global timer_start
global reminder_timer_start
global opened_at
if (GPIO.input(switch_pin) == True and states['inputs']['switch'] != True):
states['inputs']['switch'] = True
WriteStates(states)
event = "Door Opened."
WriteLog(event)
if(settings['notification']['minutes'] > 0):
timer_start = time.time() # Set start time for timer
opened_at = timer_start # Note time the door was actually opened
if(settings['notification']['notify_on_open'] == "on"):
notifyevent = "GarageEvent_Notify_on_Open"
SendNotification(settings,notifyevent)
time.sleep(1)
if (GPIO.input(switch_pin) == False and states['inputs']['switch'] != False):
states['inputs']['switch'] = False
WriteStates(states)
event = "Door Closed."
WriteLog(event)
timer_start = 0
reminder_timer_start = 0
time.sleep(1)
return(states)
# *****************************************
# Main Program Loop
# *****************************************
# First Init List Switch States
while True:
settings = ReadSettings()
states = CheckDoorState(ReadStates(),settings)
if (states['inputs']['switch'] == False) and (notify_on_close == True):
# WriteLog("[DEBUG]: Garage Door Closed. Calling SendNotification Function")
notify_on_close = False
notifyevent = "GarageEvent_Closed"
SendNotification(settings,notifyevent)
if (timer_start > 0):
if(time.time() > (timer_start + (settings['notification']['minutes']*60))):
# WriteLog("[DEBUG]: Garage open for 10 mins. Calling SendNotification Function")
notifyevent = "GarageEvent_Open_Alarm"
SendNotification(settings,notifyevent)
timer_start = 0 # Stop the timer, stop from sending another notification
notify_on_close = True
if (settings['notification']['reminder'] > 0):
reminder_timer_start = time.time()
if (reminder_timer_start > 0):
if(time.time() > (reminder_timer_start + (settings['notification']['reminder']*60))):
# WriteLog("[DEBUG]: Garage still open for 10 mins. Calling SendNotification Function")
notifyevent = "GarageEvent_StillOpen_Alarm"
SendNotification(settings,notifyevent)
if settings['notification']['reminder'] > 0: # check that the setting hasn't changed
reminder_timer_start = time.time() # Restart the timer
else:
reminder_timer_start = 0
if (states['outputs']['button'] == True):
event = "Button Pressed."
WriteLog(event)
ToggleRelay()
states['outputs']['button'] = False
WriteStates(states)
time.sleep(0.25)
exit()