我正在尝试用Python实现带闹钟的数字时钟。现在我想知道实现闹钟功能的最佳方法是什么。我能够找到几个类似的项目,主要集中在闹钟功能上。他们通常只计算下一次唤醒广告进入睡眠状态的时间,计算出的秒数。 请参阅here和here:
我的问题是,我还实现了一个普通时钟并显示时间。因此我必须每秒更新时钟。在此循环中,我检查是否不应该关闭警报。出于这个原因,我正在寻找简单有效的闹钟功能实现。
受到第一个例子的启发,我最终得到了这个:
#!/usr/bin/python
import time
import datetime
class Clock:
def __init__(self):
# set the initial time
self.hour = 0
self.minute = 0
self.second = 0
# the update interval in seconds
self.update_interval = 1
self.keep_running = True
# the instance of the alarm
self.alarm = AlarmClock()
def run(self):
while self.keep_running:
# update the clock time
now = datetime.datetime.now()
self.hour = now.hour
self.minute = now.minute
self.second = now.second
# now check if the alarm should not be started
if self.alarm.is_active():
if self.alarm.time_till_next_alarm() < 1:
# has to be done in separate thread
self.alarm.on_wake_up()
time.sleep(self.update_interval)
def get_alarm(self):
return self.alarm
class AlarmClock:
def __init__(self, hour=8, minute=0):
# We start with predefined alarm at 8:00 which is not active
self.hour = hour
self.minute = minute
self.active = False
# the alarm should be stopped after some time (1h 00min)
self.duration = datetime.timedelta(hours=1, minutes=0)
def time_till_next_alarm(self):
now = datetime.datetime.now() # get current date & time
# separate date and time from each other:
currdate = datetime.date(now.year, now.month, now.day)
currtime = datetime.time(now.hour, now.minute)
alarmtime = self.get_wake_up_time()
# add today's date onto the alarm time entered
alarmdatetime = datetime.datetime.combine(currdate, alarmtime)
if alarmtime <= currtime: # if the alarm time is less than the current time set clock for tomorrow
alarmdatetime += datetime.timedelta(hours=24)
return alarmdatetime - now
def set_time(self, hour, minute):
self.hour = hour
self.minute = minute
def activate(self):
self.active = True
def deactivate(self):
self.active = False
def is_active(self):
return self.active
def on_wake_up(self):
# start the wake up
print 'Wake up!'
#Execution starts here
if __name__ == '__main__':
clock = Clock()
clock.get_alarm().activate()
clock.get_alarm().set_time(8,0)
clock.run()
是否有更好或更少计算要求的实施?
编辑:
我想在7段LCD显示屏上显示时间,here are some details about the part.因此,我在 run()方法中每次更新时都会将数字写入LCD显示屏
# set the tens and ones of hours and minutes
self.display.set_digit(0, int(self.hour / 10)) # Tens
self.display.set_digit(1, self.hour % 10) # Ones
self.display.set_digit(2, int(self.minute / 10)) # Tens
self.display.set_digit(3, self.minute % 10) # Ones
EDIT2:
虽然Adafruit提供的python库允许你设置整个显示器的闪烁率,我想以1Hz的频率闪烁冒号 - 暗示秒的速率。
# Toggle colon at 1Hz
self.display.set_colon(self.second % 2)
答案 0 :(得分:1)
查看sched
模块。包含在Python标准库中!
答案 1 :(得分:1)
您可以完全消除AlarmClock类,只需使用threading.Timer
即可。大多数其他类似乎也是多余的 - 日期时间对象已经有小时,分钟,秒,所以不需要保留自己的版本。
import datetime
import threading
import sys
def ring_ring():
sys.stdout.write('ring ring\n')
sys.stdout.flush()
class Clock:
def __init__(self):
self.alarm_time = None
self._alarm_thread = None
self.update_interval = 1
self.event = threading.Event()
def run(self):
while True:
self.event.wait(self.update_interval)
if self.event.isSet():
break
now = datetime.datetime.now()
if self._alarm_thread and self._alarm_thread.is_alive():
alarm_symbol = '+'
else:
alarm_symbol = ' '
sys.stdout.write("\r%02d:%02d:%02d %s"
% (now.hour, now.minute, now.second, alarm_symbol))
sys.stdout.flush()
def set_alarm(self, hour, minute):
now = datetime.datetime.now()
alarm = now.replace(hour=int(hour), minute=int(minute))
delta = int((alarm - now).total_seconds())
if delta <= 0:
alarm = alarm.replace(day=alarm.day + 1)
delta = int((alarm - now).total_seconds())
if self._alarm_thread:
self._alarm_thread.cancel()
self._alarm_thread = threading.Timer(delta, ring_ring)
self._alarm_thread.daemon = True
self._alarm_thread.start()
clock = Clock()
clock.set_alarm(sys.argv[1], sys.argv[2])
clock.run()