Repeat a sound/action every certain time - python

I'm trying to write a Python program that reproduces a sound every certain hour, but it doesn't really work. When I test the code and the specified time comes, it will keep repeating the sound forever.
Here is the code:
import os
from datetime import datetime
now = datetime.now()
currentHour = now.hour
currentMin = now.minute
#I also tested with if but it didn't work
while currentHour==15 and currentMin==33:
os.system("aplay /home/pi/sound.wav") #Plays the sound thru aplay

Your logic is wrong.
First of all, the while loop will most likely end in the first iteration and you want the program to continue till you tell it to.
In addition to that, you don't update the now variable inside the loop, which is basically a bad idea.
For example, this code will continue running and when it is 15:33, a sound will be played only once.
myHour = 15
myMin = 33
is_played = False
while True:
now = datetime.now()
currentHour = now.hour
currentMin = now.minute
if currentHour == myHour and currentMin == myMin and not is_played:
is_played = True
os.system("aplay /home/pi/sound.wav")
if currentHour != myHour or currentMin != myMin:
is_played = False
Xiaotian Pei suggested a great idea, to efficiently use your CPU resource, lets use the Timer module:
def to_play_sound(hour, min):
now = datetime.now()
currentHour = now.hour
currentMin = now.minute
if currentHour == hour and currentMin == min and not is_played:
is_played = True
os.system("aplay /home/pi/sound.wav")
if currentHour != myHour or currentMin != myMin:
is_played = False
while True:
t = Timer(30.0, to_play_sound, [15, 33])
t.start()
J.F. Sebastian has also suggested a great idea:
import datetime
import subprocess
while True:
now = datetime.now()
# compute `deadline`
while True:
deadline = now.replace(hour=hour, minute=min)
if deadline > now:
break
else:
deadline += datetime.timedelta(1)
sleep_until(deadline) # sleep
subprocess.check_call(['aplay', '/home/pi/sound.wav']) # play the sound!
Read how sleep_until was implemented here.

It's a complement to #bshuster13 's answer.
What you need is actually a timer. Using a busy loop and detect if it's the right time to do something is not a good idea. Take a look at Timer in python. I think you will come up with a better solution.

Related

How to make program sleep until next day

I need my code to stop and wait until the next day. The time does not matter, I just need it to continue when the date changes.
currentDate = datetime.datetime.now()
future = datetime.datetime(currentDate.year, currentDate.month,
(currentDate.day + 1))
time.sleep((future-currentDate).total_seconds())
The code pauses but does not continue after
Two options here with comments.
First do imports
import datetime
import time
one uses a while loop - probably not a good solution but highlights one way to wait for a condition to be met.
def loop_until_tomorrow():
""" Will use a while loop to iterate until tomorrow """
#get current date
currentDate = datetime.datetime.now().date()
# loop attempts
times = 0
# this will loop infiniatly if condition is never met
while True:
# increment by one each iteration
times += 1
#get date now
now = datetime.datetime.now().date()
if currentDate != now:
# return when condition met
print("\nDay has changed")
return
else:
# print attempts and sleep here to avoid program hanging
print(f"Attempt: {times}".ljust(13) + " - Not tomorrow yet!", end="\r")
time.sleep(5)
the other - sleeps for the amount of seconds from now till tomorrow
def sleep_until_tomorrow():
"""wait till tomorrow using time.sleep"""
#get date now
now = datetime.datetime.now()
#get tomorrows date
tomorrow_date = now.date() + datetime.timedelta(days=1)
#set to datetime
tomorrow_datetime = datetime.datetime(year=tomorrow_date.year, month=tomorrow_date.month, day=tomorrow_date.day, hour=0, minute=0, second=0)
#get seconds
seconds_til_tomorrow = (tomorrow_datetime-now).total_seconds()
#sleep
time.sleep(seconds_til_tomorrow)
You can use schedule for that purpose, which will give you the flexibility to refactore the code when needed without having to write a chunck of code.
from schedule import every, repeat, run_pending
import time
#just to give you the idea on how to implement the module.
#repeat(every().day.at("7:15"))
def remind_me_its_a_new_day():
print("Hey there it's a new day! ")
while True:
run_pending()
time.sleep(1)

I am trying to execute an alarm function in tkinter but it is not working properly

I am trying to Execute the function in tkinter as I want function to run in background I have done following code. Also I am trying to execute it inside a while loop but its not looping through.
t1 = dt.time(hour = 13, minute= 24)
t2 = dt.time(hour= 13, minute= 4)
timetable = [t1, t2]
root = Tk()
def Alarm():
current_time = now_time.strftime("%H:%M:%S")
print(current_time)
print(timetable[0])
while True:
if timetable[0] <= dt.datetime.now().time():
print("Its time")
break
Alarm()
root.mainloop()
print statements are only for testing. The logic I am using in alarm clock is also not executing properly as it tells ""Its time" even after time has passed. I have tried following methods before.
method 1:
for i in reversed(timetable):
i_time = i
#print (i_time)
#print(now_time.strftime("%H:%M"))
while True:
if dt.datetime.now().time() < i_time:
#if i_time <= dt.datetime.now().time():
print("Its Time")
break
method 2:
for i in timetable:
current_time = dt.datetime.now().time()
alarm_time = i
while True:
if current_time < alarm_time:
if current_time <= alarm_time:
print("its time", alarm_time)
Using for loop was my first goal but for loop isn't executing properly. It only gets 1st element and doesn't go to 2nd element even if first element has passed so I have decided to go with if,elif,else statement
You can use the after method to run a function after a certain amount of time has elapsed. You should use it rather than creating a loop.
You simply need to convert the alarm time to a number of milliseconds, then use that to ring the alarm at the given time. For example, to ring an alarm in one hour you would do this:
def ring_alarm():
print("Its time")
delay = 60 * 60 * 1000 # 60 min/hour, 60 secs/min, 1000ms/sec
root.after(delay, ring_alarm)
I am going with if..else response for executing alarm as
current_time = dt.datetime.now().time()
if timetable[0] == current_time:
print("Its time")
break
I was breaking While loop in wrong place as well an typo from my end.

I Need a More Precise Current-Time, Count down clock in Python

The countdown timer I have made counts down to a specified time of the day, not accounting for which day of what month in what year, I am just looking for it to countdown to the time of day.
The clock works to the second, but for my use, I need it to work to the 100th of a millisecond; Python has 6 digits accounting for the millisecond, yet my clock, no matter what, always ends on a second rather than if I specify a millisecond to land on.
I wanted the clock to end at 9:41, 55 seconds, and 500000 ms, but it instead just rounded my milliseconds to seconds for the desired time to break the loop
user_input = input("Enter time...example: 17:21:15:550000: ")
import datetime
stop = False
while stop == False:
rn = str(datetime.datetime.now().time())
print(rn)
if rn >= str(user_input):
stop = True
print("Ended at wanted time...")
You could try to do this:
from datetime import datetime, timedelta
user_input = input("Enter time...example: '17:21:15:550000' :")
now = datetime.now()
stop_time = datetime.strptime(user_input, "%H:%M:%S:%f")
stop_time = stop_time.replace(year=now.year, month=now.month, day=now.day)
if stop_time < now:
stop_time += timedelta(days=1)
while True:
now = datetime.now()
print(now)
if stop_time < now:
print("Ended at wanted time...")
break;
Let me know if everything works as expected

Trying to write a alarm clock in python

I'm trying to write a program to remind a user to take breaks. Here is the code:
import datetime
import os
from playsound import playsound
import time
# current_time = datetime.datetime.now()
# print(current_time)
running = True
while running:
current_time = datetime.datetime.now()
new_time = datetime.datetime.now()
# print(current_time)
breaktime = datetime.timedelta(
days=0,
hours=0,
minutes=1
)
times = datetime.timedelta(seconds=5)
time.sleep(6)
new = current_time + times
if new_time == new:
print("hello")
playsound('Take_Flight.mp3')
running = False
break
The program does not play the sound Take_Flight.mp3 and it does not print hello.
How can I make it work?
I think the reason your alarm does not ring is because of the break statement at the bottom line of your code. The while loop simply ends without looping over and over again as you intended. I believe if you remove that your code will work. As an alternative to what you wrote you can also make the program wait for 5 min and then ring without getting the current time:
while True
time.sleep(300000)
print("hello")
playsound('Take_Flight.mp3')

datetime module not matching int comparison to int

I'm currently making an Alarm Clock as a tool to further learn python3 and I have come across a problem.
def clockCheck():
#get the hour and time from setAlarm
splitTime = re.compile(r'(\d+?)(:)(\d+)')
timeRe = splitTime.search(setAlarm())
alarmHour = timeRe.group(1)
alarmMinute = timeRe.group(3)
#get the live time
now = datetime.datetime.now()
currentHour = now.hour
currentMinute = now.minute
currentSecond = now.second
print(currentHour)
print(alarmHour)
while True:
if currentHour != alarmHour:
print("check1")
time.sleep(60-currentSecond) #if this isn't done, the alarm could be off by a couple seconds. Line's up things
time.sleep((60*60) - (60*currentMinute)) #this sleeps the program until the next hour is hit and reruns a check
elif currentMinute != alarmMinute:
print("check2")
time.sleep(60-currentSecond) #sleep until the next minute and rerun the check
#play sound
#break out of program, it's done
In this code snippet, when currentHour is compared to alarmHour (the first if statement), even when those two variables are the same, the code executes the if statement in which they do not equal each other.
In other words, if currentHour = 1 and alarmHour = 1, the code will execute as if currentHour != alarmHour and will run that if statements code.
Obviously that doesn't make sense and I don't know why that is happening when clearly 1==1. I have posted the full code, feel free to play with it. All these modules are built into python3.6
Here is my full code
'''
alarmclock.
ask user for what time to blare off
compare current time to set alarm time
if they do not equal the same then sleep the program for x time and ` rerun the check where it checks if current time is equal alarm time yet. loop until currenttime equals alarm time. then play soun`d
'''
import time
import datetime
import re
def setAlarm():
print("Hello, what time would you like the alarm to sound? Please input in this format\ne.g. 7:45pm\n")
time = input("Time: ")
splitTime = re.compile(r'(\d+?)(:)(\d+?)(pm|am)') #split up time inputted for manipulation
timeRe = splitTime.search(time)
hour = int(timeRe.group(1))
minutes = int(timeRe.group(3))
dayOfTime = timeRe.group(4).lower() #set pm or am to lowercase for ease
#errorChecking for proper time format
if hour > 12 or hour < 1:
print("Please input your time properly, in 12 hour time")
setAlarm()
if minutes > 59 or minutes < 0:
print("Please input your time properly")
setAlarm()
#if time of day is pm, then reassign all values from 1pm - 11:59pm as 13, 14, 15, etc 24 hour bullshit.
if dayOfTime == "pm" and hour != 12:
convertedHour = hour + 12
else:
convertedHour = hour
if dayOfTime == "am" and hour == 12:
convertedHour = 24
finalTime = str(convertedHour) + ":" + str(minutes)
print(finalTime)
return finalTime
def clockCheck():
#get the hour and time from setAlarm
splitTime = re.compile(r'(\d+?)(:)(\d+)')
timeRe = splitTime.search(setAlarm())
alarmHour = timeRe.group(1)
alarmMinute = timeRe.group(3)
#get the live time
now = datetime.datetime.now()
currentHour = now.hour
currentMinute = now.minute
currentSecond = now.second
print(currentHour)
print(alarmHour)
while True:
if currentHour != alarmHour:
print("check1")
time.sleep(60-currentSecond) #if this isn't done, the alarm could be off by a couple seconds. Line's up things
time.sleep((60*60) - (60*currentMinute)) #this sleeps the program until the next hour is hit and reruns a check
elif currentMinute != alarmMinute:
print("check2")
time.sleep(60-currentSecond) #sleep until the next minute and rerun the check
#play sound
#break out of program, it's done
def main():
clockCheck()
main()

Categories

Resources