This repository was archived by the owner on Dec 23, 2025. It is now read-only.
forked from nebhead/garage-zero
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcontrol.py
More file actions
executable file
·275 lines (227 loc) · 9.83 KB
/
control.py
File metadata and controls
executable file
·275 lines (227 loc) · 9.83 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
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
#!/usr/bin/env python
# *****************************************
# 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
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
import urllib2
import urllib
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 = 2 # GPIO 2, Pin 03 (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_UP) # Setup Magnetic Switch on GPIO (set pull up)
# Global variables
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
exit_loop = False
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)
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":
return # don't send Pushover notifications for these
else:
notifymessage = "Whoops! GarageZero had the following unhandled notify event: " + notifyevent + " at " + now
subjectmessage = "GarageZero: Unknown Notification at " + str(now)
for user in settings['pushover']['UserKeys'].split(','):
data = {
"token": settings['pushover']['APIKey'],
"user": user.strip(),
"message": notifymessage,
"title": subjectmessage,
"url": settings['misc']['PublicURL'],
}
url = 'https://api.pushover.net/1/messages.json'
try:
request = urllib2.Request(url, json.dumps(data), {'Content-Type': 'application/json'})
response = urllib2.urlopen(request)
WriteLog(subjectmessage + ". Pushover notification sent to: " + user.strip())
except urllib2.HTTPError as e:
WriteLog("Pushover Notification to %s failed: %s" % (user, e))
except urllib2.URLError as e:
WriteLog("Pushover Notification to %s failed: %s" % (user, e))
except Exception as e:
WriteLog("Pushover Notification to %s failed: %s" % (user, e))
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:
postdata = urllib.urlencode(query_args)
request = urllib2.Request(url,postdata)
response = urllib2.urlopen(request)
WriteLog("IFTTT Notification Success: " + notifyevent)
except urllib2.HTTPError:
WriteLog("IFTTT Notification Failed: " + notifyevent)
except urllib2.URLError:
WriteLog("IFTTT Notification Failed: " + notifyevent)
except:
WriteLog("IFTTT Notification Failed: " + notifyevent)
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['ifttt']['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
def MainLoop():
global timer_start
global reminder_timer_start
global notify_on_close
global opened_at
WriteLog("System started.")
while not exit_loop:
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)
if __name__ == "__main__":
MainLoop()