I require help with my alarm system code that I am building with GPIOZero library (my boss really likes the library). The system is meant for a laptop cart so people do not forget to close the door as there is a buzzer that rings if people leave it open for too long. So what I want it to do is really simple but it always waits for the function to finish before going to the next:
If door opens: Log time, Time Delay ,Buzzer turns on
If door is closed/closes: Buzzer is off, Log Time
Is there a way to not wait for the function to finish in the GPIOZero library. Please let me know!
from gpiozero import Button
from signal import pause
from gpiozero import Buzzer
from gpiozero import LED
from time import sleep
##### VARIABLES DEF #######
button = Button(21, pull_up=True)
buzzer = Buzzer(4)
def door_opened():
f = open("log" + '.txt', 'a')
f.write("Opened " + time.strftime("%m-%d-%Y %X"))
f.close()
print("Door Open")
sleep(100)
print("door held, alarm on")
buzzer.on
def door_closed():
f = open("log" + '.txt', 'a')
f.write(" " + time.strftime("%X"))
f.write('\n')
f.close()
print("Door Closed")
buzzer.off()
print("Buzzer off")
button.when_pressed = door_closed
button.when_released = door_opened
pause()
You will have to restructure things a little to get this done.
The idea here is that you have a pair of global variables that are updated by the GPIOZero event handlers:
door_is_open
– true when the door is opendoor_open_counter
– counts the seconds the door has been opened (this is actually only reset to zero by the event handlers).There's also an infinite main loop that ticks once per second which reads the door_is_open
variable and increments the open counter... and finally, if the open counter reaches the threshold desired (5 seconds here because we're impatient people), it turns the buzzer
on.
The door_closed
handler takes care of resetting the buzzer
, but that could also be done in the main loop.
I also took the liberty of refactoring the logging into a function of its own that handily also prints the same thing to the console. (As an aside, I'd suggest using ISO 8601 date formatting, but I didn't want to impose that here.)
A further refactoring might wrap this all in a neat class to avoid global variables.
(This all is dry-coded, so your mileage may vary, but the idea should work. :) )
import time
from gpiozero import Button, Buzzer
button = Button(21, pull_up=True)
buzzer = Buzzer(4)
door_is_open = False
door_open_counter = 0
def log_event(text):
print(log_line)
with open("log.txt", "a") as log_file:
log_line = "%s | %s" % (time.strftime("%m-%d-%Y %X"), text)
log_file.write(log_line + "\n")
def door_opened():
global door_is_open
global door_open_counter
log_event("Opened")
door_is_open = True
door_open_counter = 0
def door_closed():
global door_is_open
global door_open_counter
log_event("Closed")
buzzer.off()
door_is_open = False
door_open_counter = 0
button.when_pressed = door_closed
button.when_released = door_opened
while True:
time.sleep(1)
if door_is_open:
door_open_counter += 1
if door_open_counter >= 5:
buzzer.on()