Python Forum

Full Version: Running an action only between certain times
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I'm running a basic python program on a raspberry pi with an input connected to a pair of outdoor infrared beams. When the beams are crossed, a notification is sent via Pushbullet. This component of the code is working well, but am looking to expand the code to switch on some lights, between certain hours overnight. I am trying to only execute the post request if the current time is between 2am and 7am. The device time is correct. I'm sure this is something simple, but I don't have a lot of experience and would appreciate any assistance. I thought I had it working before, but it is executing now regardless of the current time. I've included the function below:

from pushbullet import Pushbullet
import RPi.GPIO as GPIO
import requests
from time import sleep
from gpiozero import Button
from datetime import datetime

def lights():
    now = datetime.now()
    current_time = now.strftime("%H:%M:%S")
    start = '2:00:00'
    end = '7:00:00'
    if current_time > start and current_time < end:
	    requests.post('https://maker.ifttt.com/trigger/lights/json/with/key/keyid')
	    
You could do
if (2, 0, 0) <= (now.hour, now.minute, now.second) < (7, 0, 0): ...
Time is essentially a number, but you treat it as a string. 2am is '02:00:00' and 7am is '07:00:00'. Both of these are less than '2:00:00', so your test will never be True. Treat time like a datetime object, as Griboulilis recommends, and this should work. Kind of.

If you want to turn lights on at 2am and off at 7am, why not schedule an event to turn the lights on at 2am and off at 7am? Have you looked at the sched library?

https://docs.python.org/3/library/sched.html
Thank you Gribouillis and deanhystad, I will take a look when I'm back at the computer. What I'm doing with the lights, is only switching them on when someone walks into the garden at night, so I only want that to happen between those times.
I've tried using the suggested syntax, thank you, but I'm still seeing the function run outside of the hours 2am-7am. I did check the system time is correct. Would anyone have an idea what might need adjusting?

def lights():
	now = datetime.now()
	if (2, 0, 0) <= (now.hour, now.minute, now.second) < (7, 0, 0):
		requests.post('https://maker.ifttt.com/trigger/flights/json/with/key/key')
		print("LightsActivated")
        
(Mar-15-2023, 06:04 AM)alexbca Wrote: [ -> ]I'm still seeing the function run outside of the hours 2am-7am.
Could you replace
print("LightsActivated")
by
print("LightsActivated", now.hour, now.minute, now.second, now)
and post the output here to see it fail. I find it hard to believe.
(Mar-15-2023, 07:13 AM)Gribouillis Wrote: [ -> ]
(Mar-15-2023, 06:04 AM)alexbca Wrote: [ -> ]I'm still seeing the function run outside of the hours 2am-7am.
Could you replace
print("LightsActivated")
by
print("LightsActivated", now.hour, now.minute, now.second, now)
and post the output here to see it fail. I find it hard to believe.

TY, will try this
OK, I feel stupid, I added the line to print the time readout, the function is running, however I am not seeing the print of LightsActivated, but the code proceeds to action the post requests.

from pushbullet import Pushbullet
import RPi.GPIO as GPIO
import requests
from time import sleep
from gpiozero import Button
from datetime import datetime

def lights():
	now = datetime.now()
	if (2, 0, 0) <= (now.hour, now.minute, now.second) < (6, 0, 0):
		print("LightsActivated", now.hour, now.minute, now.second, now)
		requests.post('http://10.0.0.36/light/0?turn=on&brightness=100')
		requests.post('https://maker.ifttt.com/trigger/lights/json/with/key/key')
		sleep(3)
		requests.post('https://maker.ifttt.com/trigger/lights2/json/with/key/key')
		sleep(2)
		requests.post('https://maker.ifttt.com/trigger/lights3/json/with/key/key')
		sleep(3)

button = Button(2)
pb = Pushbullet("key")
pbv = Pushbullet("key")
print(pb.devices)
print(pbv.devices)

while True:
    if button.is_pressed:
        print("Trigger")
        push = pb.push_note("IR Detect", "Beams Detect")
        push = pbv.push_note("IR Detect", "Beams Detect")
        lights()
        
        sleep(21)

else:
    print("NoTrigger")
I also never get to the else when there isn't an activation. Appreciate the help for this noob!!

[Image: 2023-03-15-23-49-48-Termius-Pi.png]
The else part goes with the if, not the while. You need to indent the else part here.
(Mar-15-2023, 01:32 PM)Gribouillis Wrote: [ -> ]The else part goes with the if, not the while. You need to indent the else part here.

Done, it's late here in AU, think might be good to go, will test property tomorrow, thank you 😊
As Gribouillis says, because of your indentation you are doing while..else, not if..else.

while..else is hardly ever used. I see occasionally see for..else used in a program, but I cannot remember the ever seeing while..else. When using "else" in conjunction with a loop, the else code runs only if the loop terminated normally, based on the condition. If the look was terminated by a break, the else block does not run.
i = 1
while i < 5:
    i += 1
else:
    print("while terminated normally")

i = 1
while True:
    i += 1
    if i > 4:
        print("break out of while loop")
        break
else:
    print("while terminated normally")
Output:
while terminated normally break out of while loop
Your code never prints "No Trigger" because the loop never ends.