diff --git a/clocky.py b/clocky.py index e17b700..c3ffa9b 100755 --- a/clocky.py +++ b/clocky.py @@ -12,27 +12,28 @@ from time import sleep,strftime import RPi.GPIO as GPIO import button import signal +import clockyconfig import clockytracklist -VERBOSE=False +VERBOSE=True settings= {} looptype=0 quit=0 -print("\n +----------+\n | Clocky |\n | v0.2.5 |\n +----------+\n") +print("\n +----------+\n | Clocky |\n | v0.3.0 |\n +----------+\n") o_configfilename = "clocky.conf" -o_defaultalarmtime = 60*14+10 # hh*60+mm -o_showalarmtime=3 # time that the alarmtime shows after short press -o_showtracktime=2 # note that this is per track, so total time is 10 times longer -o_editdelaytime=3 # time it takes to qualify as longpress -o_showtimeout=6 # timeout to exit edit modus -o_snoozetime = 9 # time to snooze -o_timetomaxvol = 150# seconds it takes to go from 0% to 100% volume -o_maxplaytime = 900 # seconds it to play -o_soundpreviewtime=5 -o_defaultbrightness=0 +#o_defaultalarmtime = 60*14+10 # hh*60+mm +#config.settings['showalarmtime']=3 # time that the alarmtime shows after short press +#config.settings['showtracktime']=2 # note that this is per track, so total time is 10 times longer +#config.settings['editdelaytime']=3 # time it takes to qualify as longpress +#config.settings['edittimeout']=6 # timeout to exit edit modus +#config.settings['snoozetime'] = 9 # time to snooze +#config.settings['timetomaxvolume'] = 150# seconds it takes to go from 0% to 100% volume +#config.settings['maxalarmtime'] = 900 # seconds it to play +#config.settings['soundpreviewtime']=5 +#config.settings['defaultbrightness']=0 o_loopdelay=0.25 track=0 @@ -61,14 +62,13 @@ def receive_signal(signum, stack): stopprogram=1 -def stamp(): - sys.stdout.write(strftime("[%Y%m%d %H%M%S] ")) +def stamp(str): + sys.stdout.write(strftime("[%Y%m%d %H%M%S] ")+str+"\n") + sys.stdout.flush() -def writesettings(): - "write settings to conf file" - with open(o_configfilename, 'wb') as handle: - pickle.dump(settings, handle) - handle.close() + +def timetoval(str): + return (str.split(":")[0]*60)+str.split(":")[1] # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # @@ -95,6 +95,9 @@ but1=button.Button(21,verbose=VERBOSE) but2=button.Button(20,verbose=VERBOSE) but3=button.Button(26,verbose=VERBOSE) +config=clockyconfig.ClockyConfig(verbose=VERBOSE) +tracks=clockytracklist.ClockyTracklist("mp3",recursive=True,verbose=VERBOSE) + #------------------------------------------------------------------ #------------------------------------------------------------------ @@ -107,32 +110,29 @@ while not stopprogram: # display=max7219.MAX7219(brightness=1) display.Clear() - display.SetBrightnessRaw(o_defaultbrightness) + display.SetBrightnessRaw(config.settings['defaultbrightness']) if VERBOSE: print("Reading mp3s from directory:") - tracks=clockytracklist.ClockyTracklist("mp3",recursive=True,verbose=VERBOSE) allmp3s=tracks.tracklist c=0 - if VERBOSE: + if True: # VERBOSE: print("\nTracks:") for m in allmp3s: print("%2d : %s"%(c+1,m)) c+=1 - stamp() - print("Started") - sys.stdout.flush() + stamp("Started") # ................................................................. + if not os.path.isfile(o_configfilename): print("Createconf: \""+o_configfilename+"\":") settings = {'track0':1, 'track1':2, 'track2':3, 'track3':4, 'track4':5, 'track5':6, 'track6':7, 'track7':8, 'track8':9, 'track9':10 } - settings['alarmtime']=o_defaultalarmtime; - settings['starttrack']=0; - settings['alarmdisabled']=0; + config.starttrack=0; + config.settings['alarmdisabled']=0; with open(o_configfilename, 'wb') as handle: pickle.dump(settings, handle) @@ -146,15 +146,15 @@ while not stopprogram: settings = pickle.load(handle) handle.close() - a_mins=int(settings['alarmtime']%60) - a_hour=int((settings['alarmtime']-a_mins)/60) + a_hour=int(config.settings['alarmtime'].split(":")[0]) + a_mins=int(config.settings['alarmtime'].split(":")[1]) if VERBOSE: print("Alarmtime : %02d:%02d"%(a_hour,a_mins)) - print("Alarmdisable: %d"%(settings['alarmdisabled'])) - print("Starttrack : %d"%(settings['starttrack'])) + print("Alarmdisable: %d"%(config.settings['alarmdisabled'])) + print("Starttrack : %d"%(config.starttrack)) for i in range(0,10): - if i==settings['starttrack']: + if i==config.starttrack: if VERBOSE: print("=>",end='') else: @@ -169,12 +169,10 @@ while not stopprogram: if VERBOSE: print("") settings["track%d"%i]=0 - writesettings() - - # ................................................................. - +# Main loop without reload and stuff +# while not reload and not stopprogram: count+=1; sleep(o_loopdelay) @@ -182,8 +180,8 @@ while not stopprogram: mytime=time.localtime(time.time()) currenttime=mytime[3]*60 + mytime[4]; - if not settings["alarmdisabled"]: - if currenttime == settings['alarmtime']: + if not config.settings["alarmdisabled"]: + if currenttime == timetoval(config.settings['alarmtime']): if looptype==0 and not silencedalarm: looptype=5 else: @@ -198,16 +196,12 @@ while not stopprogram: if but1.WasLong(): if but2.WasPressed(): if but2.WasLong(): - if settings["alarmdisabled"]==0: - settings["alarmdisabled"]=1 - stamp() - print("Alarm disabled") - writesettings() + if config.settings["alarmdisabled"]==0: + config.settings["alarmdisabled"]=1 + stamp("Alarm disabled") else: - settings["alarmdisabled"]=0 - stamp() - print("Alarm enabled") - writesettings() + config.settings["alarmdisabled"]=0 + stamp("Alarm enabled") looptype=1 else: looptype=2 @@ -220,16 +214,12 @@ while not stopprogram: if but3.WasPressed(): if but3.WasLong(): - if settings["alarmdisabled"]==0: - settings["alarmdisabled"]=1 - stamp() - print("Alarm disabled") - writesettings() + if config.settings["alarmdisabled"]==0: + config.settings["alarmdisabled"]=1 + stamp("Alarm disabled") else: - settings["alarmdisabled"]=0 - stamp() - print("Alarm enabled") - writesettings() + config.settings["alarmdisabled"]=0 + stamp("Alarm enabled") looptype=1 @@ -244,9 +234,9 @@ while not stopprogram: # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if looptype==1: # show alarmtime - if not settings["alarmdisabled"]==1: - a_mins=int(settings['alarmtime']%60) - a_hour=int((settings['alarmtime']-a_mins)/60) + if not config.settings["alarmdisabled"]==1: + a_hour=int(config.settings['alarmtime'].split(":")[1]) + a_mins=int(config.settings['alarmtime'].split(":")[1]) if colon: tim="%02d:%02d" % (a_hour, a_mins) @@ -257,7 +247,7 @@ while not stopprogram: else: display.showclock(" O FF") - if showtime > o_showalarmtime: + if showtime > config.settings['showalarmtime']: if but1.WasPressed(): # drop intermediate presses {} if but2.WasPressed(): @@ -275,10 +265,10 @@ while not stopprogram: delta=0 - sm=int(settings['alarmtime']%10) - dm=int(((settings['alarmtime']-sm)/10)%6) - sh=int((settings['alarmtime']-dm)/60%10) - dh=int((settings['alarmtime']-sh)/600) + dh=int(config.settings['alarmtime'][0]) + sh=int(config.settings['alarmtime'][1]) + dm=int(config.settings['alarmtime'][3]) + sm=int(config.settings['alarmtime'][4]) if colon: tim="%0d%0d:%0d%0d" % (dh,sh,dm,sm) @@ -330,27 +320,24 @@ while not stopprogram: colon=1-colon - if showtime > o_showtimeout: + if showtime > config.settings['edittimeout']: showtime=0 if dh==2 and sh>3: sh=3 looptype=1 else: looptype=0 - if settings["alarmdisabled"]==1: - settings["alarmdisabled"]=0 - stamp() - print("Alarm enabled") - settings['alarmtime']=dh*600+sh*60+dm*10+sm - writesettings() - stamp() - print("Set alarmtime = %d%d:%d%d"%(dh,sh,dm,sm)) + if config.settings["alarmdisabled"]==1: + config.settings["alarmdisabled"]=0 + stamp("Alarm enabled") + config.settings['alarmtime']=("%d%d:%d%d" %(dh,sh,dm,sm)) + stamp("Set alarmtime = %d%d:%d%d"%(dh,sh,dm,sm)) sys.stdout.flush() digit=1 else: showtime+=o_loopdelay - settings['alarmtime']=dh*600+sh*60+dm*10+sm + config.settings['alarmtime']=("%d%d:%d%d" %(dh,sh,dm,sm)) if but1.WasPressed(): showtime=0 @@ -401,7 +388,7 @@ while not stopprogram: colon=1-colon if soundpreview: - if pygame.mixer.music.get_pos() >o_soundpreviewtime*1000: + if pygame.mixer.music.get_pos() >config.settings['soundpreviewtime']*1000: if pygame.mixer.get_init(): pygame.mixer.music.set_volume(0) pygame.mixer.music.stop() @@ -413,7 +400,7 @@ while not stopprogram: looptype=0 else: - if showtime > o_showtracktime: + if showtime > config.settings['showtracktime']: showtime=0 track+=1; if track>9: @@ -472,10 +459,9 @@ while not stopprogram: settings["track%d"%tr]=th*10+tl track=tr - if showtime > o_showtimeout: + if showtime > config.settings['edittimeout']: showtime=0 looptype=0 - writesettings() else: showtime+=o_loopdelay @@ -490,7 +476,7 @@ while not stopprogram: # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if looptype==5: # Alarm loop! -#o_timetomaxvol = 60 # seconds it takes to go from 0% to 100% volume +#config.settings['timetomaxvolume'] = 60 # seconds it takes to go from 0% to 100% volume if colon: display.SetBrightnessRaw(0) @@ -503,9 +489,8 @@ while not stopprogram: colon=1-colon if not alarmstarted: - track=settings['starttrack']; - stamp() - print("[T%02dM%02d] \"%s\""%(track,settings["track%d"%track],(allmp3s[settings["track%d"%track]-1]))) + track=config.starttrack; + stamp("[T%02dM%02d] \"%s\""%(track,settings["track%d"%track],(allmp3s[settings["track%d"%track]-1]))) sys.stdout.flush() if not pygame.mixer.get_init(): pygame.mixer.init() @@ -518,15 +503,14 @@ while not stopprogram: track=0 if settings["track%d"%track]==0: track=0 - settings['starttrack']=track; - writesettings() + config.starttrack=track; playtime=0 alarmstarted=1 else: # alarmstarted - if playtime < o_timetomaxvol: - brightness=int((playtime / o_timetomaxvol)*255) - volume = float(int((playtime*100) / o_timetomaxvol))/100 -# print("------> %d / %d => %f - %f [%d]"%(playtime,o_timetomaxvol,tvol,volume,brightness)) + if playtime < config.settings['timetomaxvolume']: + brightness=int((playtime / config.settings['timetomaxvolume'])*255) + volume = float(int((playtime*100) / config.settings['timetomaxvolume']))/100 +# print("------> %d / %d => %f - %f [%d]"%(playtime,config.settings['timetomaxvolume'],tvol,volume,brightness)) else: volume=1 @@ -537,9 +521,8 @@ while not stopprogram: if pygame.mixer.get_init(): if not pygame.mixer.music.get_busy(): - track=settings['starttrack'] - stamp() - print("[T%02dM%02d] \"%s\""%(track,settings["track%d"%track],(allmp3s[settings["track%d"%track]-1]))) + track=config.starttrack + stamp("[T%02dM%02d] \"%s\""%(track,settings["track%d"%track],(allmp3s[settings["track%d"%track]-1]))) sys.stdout.flush() pygame.mixer.music.load(allmp3s[settings["track%d"%track]-1]) pygame.mixer.music.play() @@ -548,20 +531,18 @@ while not stopprogram: track=0 if settings["track%d"%track]==0: track=0 - settings['starttrack']=track; - writesettings() + config.starttrack=track; - if playtime > o_maxplaytime: + if playtime > config.settings['maxalarmtime']: looptype=0 playtime=0 if pygame.mixer.get_init(): pygame.mixer.music.set_volume(0) pygame.mixer.music.stop() pygame.mixer.quit() - display.SetBrightnessRaw(o_defaultbrightness) + display.SetBrightnessRaw(config.settings['defaultbrightness']) alarmstarted=0 - stamp() - print("Alarmtime expired") + stamp("Alarmtime expired") if but1.WasPressed(): if but1.WasLong(): # Finished @@ -569,7 +550,7 @@ while not stopprogram: pygame.mixer.music.set_volume(0) pygame.mixer.music.stop() pygame.mixer.quit() - display.SetBrightnessRaw(o_defaultbrightness) + display.SetBrightnessRaw(config.settings['defaultbrightness']) playtime=0 if but1.WasPressed(): # flush intermediate presses {} @@ -580,8 +561,7 @@ while not stopprogram: looptype=0 alarmstarted=0 silencedalarm=1 - stamp() - print("Silenced alarm") + stamp("Silenced alarm") if but2.WasPressed(): @@ -590,9 +570,8 @@ while not stopprogram: if pygame.mixer.music.get_busy(): pygame.mixer.music.stop() - track=settings['starttrack'] - stamp() - print("[T%02dM%02d] \"%s\""%(track,settings["track%d"%track],(allmp3s[settings["track%d"%track]-1]))) + track=config.starttrack + stamp("[T%02dM%02d] \"%s\""%(track,settings["track%d"%track],(allmp3s[settings["track%d"%track]-1]))) sys.stdout.flush() if pygame.mixer.get_init(): pygame.mixer.music.load(allmp3s[settings["track%d"%track]-1]) @@ -602,13 +581,12 @@ while not stopprogram: track=0 if settings["track%d"%track]==0: track=0 - settings['starttrack']=track; - writesettings() + config.starttrack=track; # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if count % 40 == 0: # every 10 seconds - if tracks.CheckTrackList(): + if tracks.CheckTrackList() or config.CheckConfig(): reload = True; #------------------------------------------------------------------ @@ -618,5 +596,4 @@ if pygame.mixer.get_init(): pygame.mixer.quit() display.cleanup() sys.stdout.flush() -stamp() -print("Shutdown!") +stamp("Shutdown!") diff --git a/clockyconfig.py b/clockyconfig.py index 98f51a5..7d8d8c5 100644 --- a/clockyconfig.py +++ b/clockyconfig.py @@ -1,16 +1,16 @@ -#!/usr/bin/python +#!/usr/bin/python3 import json import os import time import copy -CONFIGFILEVERSION="1.0" +CONFIGFILEVERSION="1.1" class ClockyConfig: """Read/write clocky config files.""" - def __init__(self,filename,verbose=0): + def __init__(self,filename="clocky.json",verbose=0): """Open existing Clocky config file and read config data. If no file can be found create a new one with default values.""" self.filename=filename self.__verbose=verbose @@ -20,13 +20,22 @@ class ClockyConfig: else: self.__data={} self.__data["clocky"]={} - self.__data["clocky"]["CONFIGFILEVERSION"]=CONFIGFILEVERSION + self.__data["clocky"]["version"]=CONFIGFILEVERSION self.__data["clocky"]["settings"]={} - self.__data["clocky"]["settings"]["alarmtime"]="9:00" + self.__data["clocky"]["settings"]["alarmtime"]="09:00" self.__data["clocky"]["settings"]["alarmdisabled"]=0 self.__data["clocky"]["settings"]["maxalarmtime"]=30 self.__data["clocky"]["settings"]["snoozetime"]=9 + + self.__data["clocky"]["settings"]["showalarmtime"]=3 + self.__data["clocky"]["settings"]["showtracktime"]=2 + self.__data["clocky"]["settings"]["editdelaytime"]=3 + self.__data["clocky"]["settings"]["edittimeout"]=5 + self.__data["clocky"]["settings"]["timetomaxvolume"]=150 + self.__data["clocky"]["settings"]["soundpreviewtime"]=5 + self.__data["clocky"]["settings"]["defaultbrightness"]=0 + self.__data["clocky"]["settings"]["playmode"]="random" self.__data["clocky"]["tracks"]={} @@ -45,8 +54,12 @@ class ClockyConfig: with open(self.filename) as json_data_file: self.__data = json.load(json_data_file) if(self.__data["clocky"]["version"] != CONFIGFILEVERSION): - print ("ERROR: configfile \""+self.filename+"\" CONFIGFILEVERSION ("+self.__data["clocky"]["version"]+") does not match program CONFIGFILEVERSION ("+CONFIGFILEVERSION+")!") + print ("ERROR: configfile \""+self.filename+"\" version ("+self.__data["clocky"]["version"]+") does not match program version ("+CONFIGFILEVERSION+")!") exit(); + + if(self.__data["clocky"]["settings"]["alarmtime"][1]==':'): # make sure time data is like "09:00", not "9:00" + self.__data["clocky"]["settings"]["alarmtime"]="0"+self.__data["clocky"]["settings"]["alarmtime"] + self.__readdata=copy.deepcopy(self.__data) self.__timestamp=os.stat(self.filename).st_mtime @@ -54,9 +67,13 @@ class ClockyConfig: self.starttrack=self.__data["clocky"]["starttrack"] self.tracklist=self.__data["clocky"]["tracklist"] self.sequence=self.__data["clocky"]["tracksequence"] - + def __Write(self): """Internal function to do the actual writing of data into file""" + + if(self.__data["clocky"]["settings"]["alarmtime"][1]==':'): # make sure time data is like "09:00", not "9:00" + self.__data["clocky"]["settings"]["alarmtime"]="0"+self.__data["clocky"]["settings"]["alarmtime"] + with open(self.filename,"w") as json_data_file: json.dump(self.__data,json_data_file) self.__readdata=copy.deepcopy(self.__data) @@ -72,7 +89,7 @@ class ClockyConfig: """Print current config data in human readable format""" print("--ClockyConfig-------------") print("filename =",self.filename) - print("CONFIGFILEVERSION =",self.__data["clocky"]["version"]) + print("version =",self.__data["clocky"]["version"]) for x in self.__data["clocky"]["settings"].keys(): print("%-14s= %s" %(x,self.__data["clocky"]["settings"][x])) print("...........................") @@ -94,23 +111,28 @@ class ClockyConfig: print(self.__data) def CheckConfig(self): - """Check if config file has changed or removed since reading, or if the settings have changed. - Re-write or Re-read when necessary""" - if not os.access(self.filename,os.R_OK): - self.__Write() - if(self.__verbose): - print("Re-write settings because of file removal!") - self.Print() + """Check if config file has changed or removed since reading, or if the settings have changed. + Re-write or Re-read when necessary""" + if not os.access(self.filename,os.R_OK): + self.__Write() + if(self.__verbose): + print("Re-write settings because of config file removal!") + self.Print() + return True - elif(os.stat(self.filename).st_mtime != self.__timestamp): - self.__Read() - if(self.__verbose): - print("Re-read settings because of config file change!") - self.Print() + elif(os.stat(self.filename).st_mtime != self.__timestamp): + self.__Read() + if(self.__verbose): + print("Re-read settings because of config file change!") + self.Print() + return True - if(self.__data != self.__readdata): - self.__Write() - if(self.__verbose): - print("Re-write settings because of settings change!") - self.Print() + if(self.__data != self.__readdata): + self.__Write() + if(self.__verbose): + print("Re-write settings because of settings change!") + self.Print() + return True + + return False diff --git a/conftest.py b/conftest.py old mode 100644 new mode 100755 index 8b35b17..d4883cd --- a/conftest.py +++ b/conftest.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 import json import os @@ -18,7 +18,7 @@ class Tracklist: print("ERROR: \""+self.path+"\" is not an existing directory") exit(); os.chdir(self.path) - for ent in os.listdir(): + for ent in os.listdir("."): if ent.lower().endswith(".mp3") and os.access(ent,os.R_OK): self.tracklist.append(ent) self.count+=1 @@ -35,10 +35,10 @@ class Tracklist: -config=clockyconfig.ClockyConfig("clocky.jso") +config=clockyconfig.ClockyConfig() config.Print() -tl=Tracklist("m") +tl=Tracklist("mp3") tl.Show() if (tl.tracklist == config.tracklist):