def update(self): """Returns updated weather display""" # Catch errors from python 2 try: FileNotFoundError except NameError: FileNotFoundError = IOError try: with open(saved_weather_data_path, "r") as save_data: # Get elapsed time since update and check against update delay: last_check = self.nextupdatetime - float(save_data.readline()) if last_check > weather_update_delay: # Raises to trigger data update in except clause: raise FileNotFoundError("Old file") else: self.weatherdata = str(save_data.read()) # Exception if weather_data can't be opened: except FileNotFoundError: self.ioerror() return self.update() except ValueError: remove(saved_weather_data_path) self.ioerror() return self.update() string, result = "", [] index = self.weatherdata.find(weather_city.title()) while True: string += self.weatherdata[index] index += 1 if self.weatherdata[index] == "#": result.append(string[1:]) string = "" if self.weatherdata[index] == "\n": break desc = result[-1].lower() condition = [item for item in conditions if desc.find(item) != -1] if len(condition) > 0: condition = conditions[condition[-1]] else: condition = conditions[unknown] temp = result[-2] desc = result[-1].title() item = (self.font[1].render(weather_city, 1, self.colour), self.font[5].render(condition[0], 1, self.colour), self.font[3].render(desc, 1, self.colour), self.font[2].render("{}\xb0c".format(temp), 1, self.colour)) heights = (item[0].get_rect(left=0, top=0)[3] * condition[1][0], item[1].get_rect(left=0, top=0)[3] * condition[1][1], item[2].get_rect(left=0, top=0)[3], item[3].get_rect(left=0, top=0)[3]) itempos = (item[0].get_rect(left=self.width / 100, top=0), item[1].get_rect(left=self.width / 100, top=heights[0]), item[2].get_rect(left=self.width / 100, top=sum(heights[0:2])), item[3].get_rect(left=self.width / 100, top=sum(heights[0:3]))) timestamp("Completed updating BOM module...") return ((item[0], itempos[0]), (item[1], itempos[1]), (item[2], itempos[2]), (item[3], itempos[3]))
def __init__(self): timestamp("Initialising reddit module...") super(RedditModule, self).__init__() self.stories = self.fetch_news() self.count = 0 self.updatedelay = reddit_text_display_time self.nextrefreshtime = 0
def update(self): """called when update is triggered, and should return an array of arrays, each sub-array should contain one pygame object, and one pygame rect """ # Add a timestamp to stdout on each update call, priority # 0 ensures that it won't pop up constantly, priority=1 # ensures output will be seen no matter what debug settings # are enabled, and should be used sparingly: timestamp("Updating Quotes...", priority=0) timestamp("Updating Agenda...", priority=0) #gets the local day and time today = strftime("%A", localtime()) num = days[today] q = self.font.render("\"" + self.quote[num] + "\"", 1, self.colour) s = self.font.render("-" + self.speaker[num], 1, self.colour) # Places quote in the bottom middle of the screen: q_pos = q.get_rect() # Places speaker above the quote: s_pos = s.get_rect() s_pos.center = (800, 800) q_pos.center = (800, 850) return [[q, q_pos], [s, s_pos]]
def update(self): """called when update is triggered, and should return an array of arrays, each sub-array should contain one pygame object, and one pygame rect """ # Add a timestamp to stdout on each update call, priority # 0 ensures that it won't pop up constantly, priority=1 # ensures output will be seen no matter what debug settings # are enabled, and should be used sparingly: timestamp("Updating HelloWorldModule...", priority=0) # Defines text objects hello and world, # any pygame object can be used: hello = self.font.render("Hello", 1, self.colour) world = self.font.render("World", 1, self.colour) # Places "hello" in the top left of the screen: hello_pos = hello.get_rect(left=0, top=0) # Places "world" in the bottom right of the screen: world_pos = world.get_rect(right=self.width, bottom=self.height) # Returns "hello" with position of hello, # and "world" with the position of the text: return [[hello, hello_pos], [world, world_pos]]
def fetch_news(self): """Gets new stories when called""" stories = [] for subreddit in reddit_subreddits: timestamp("Fetching subreddit - {}...".format(subreddit)) useragent = ("{}:MagicMirror/Jackson-S/com.github:{} " + "(by /u/plainchips)" ) useragent = useragent.format(system(), version) prawagent = praw.Reddit(user_agent=useragent) sub = prawagent.get_subreddit(subreddit) sub = sub.get_top_from_day(limit=reddit_item_count) for item in sub: body = self.font[7].render( self.truncate(item.title), 1, self.colour) body_pos = body.get_rect( left=self.width / 100, bottom=self.height * 0.99 ) title = self.font[6].render( subreddit.title(), 1, self.colour ) title_pos = title.get_rect( left=self.width / 100, bottom=self.height * 0.99 - body_pos[3] ) stories.append([[body, body_pos], [title, title_pos]]) return stories
def __init__(self): timestamp("Initialising BOMWeatherModule module...") super(BOMWeatherModule, self).__init__() self.url = "ftp://ftp2.bom.gov.au/anon/gen/fwo/IDA00100.dat" self.savepath = saved_weather_data_path self.updatedelay = weather_update_delay self.weatherdata = None self.connectionattempts = 0
def cleanquit(): """Quits pygame correctly""" try: AutoOnModule().exit() except: pass timestamp("Quitting.") pygame.quit() quit()
def update(self): """called when update is triggered. return next item""" timestamp("Updating Reddit module...") if self.nextrefreshtime < time.time(): self.nextrefreshtime = time.time() + reddit_refresh_delay self.stories = self.fetch_news() self.fetch_news() self.count = 0 self.count += 1 result = self.stories[self.count % len(self.stories)] timestamp("Completed updating Reddit module...") return result
def main(screen): """UI of the program, loads and draws all modules.""" timestamp("Initialising main program...") loadingscreen(SCREEN) # Initialises the display # Enables clock, used for frame rate limiter: game_clock = pygame.time.Clock() pygame.mouse.set_visible(mouse_visible) ########################################################################### # '''To add a new module first add it to the import list at the top # # and then add it to this list using this format: # # SampleModule([required pass-ins]) # # # # if your module requires from the main loop in order to display # # correctly it can be added in here # ########################################################################### timestamp("Loading modules...") modules = [ PictureModule(), BOMWeatherModule(), RedditModule(), TimeModule() ] try: # Check if vcgencmd is installed, to see if it is running on a # raspberry pi with the requires software installed call("vcgencmd") modules.append(AutoOnModule()) except: pass timestamp("Completed loading modules.") module_display = [None] * len(modules) requires_update = False while True: game_clock.tick() while True: while requires_update is False: for module_no, module in enumerate(modules): if module.need_update() is True: module_display[module_no] = module.update() requires_update = True check_events() pygame.time.wait(200) timestamp("Commencing screen update...") screen.fill(colour[0]) for module in module_display: for item, item_pos in module: screen.blit(item, item_pos) pygame.display.flip() requires_update = False timestamp("Completed screen update...\n")
def main(screen): """UI of the program, loads and draws all modules.""" timestamp("Initialising main program...") loadingscreen(SCREEN) # Initialises the display # Enables clock, used for frame rate limiter: game_clock = pygame.time.Clock() pygame.mouse.set_visible(mouse_visible) ########################################################################### # '''To add a new module first add it to the import list at the top # # and then add it to this list using this format: # # SampleModule([required pass-ins]) # # # # if your module requires from the main loop in order to display # # correctly it can be added in here # ########################################################################### timestamp("Loading modules...") modules = [PictureModule(), BOMWeatherModule(), RedditModule(), TimeModule() ] try: # Check if vcgencmd is installed, to see if it is running on a # raspberry pi with the requires software installed call("vcgencmd") modules.append(AutoOnModule()) except: pass timestamp("Completed loading modules.") module_display = [None] * len(modules) requires_update = False while True: game_clock.tick() while True: while requires_update is False: for module_no, module in enumerate(modules): if module.need_update() is True: module_display[module_no] = module.update() requires_update = True check_events() pygame.time.wait(200) timestamp("Commencing screen update...") screen.fill(colour[0]) for module in module_display: for item, item_pos in module: screen.blit(item, item_pos) pygame.display.flip() requires_update = False timestamp("Completed screen update...\n")
def ioerror(self): """Called in the case of a file read error. Re-downloads the file""" timestamp("Save file read error occurred. Trying again.") try: from urllib.request import Request, urlopen, URLError # For python 2 compatibility: except ImportError: from urllib2 import Request, urlopen, URLError try: with open(saved_weather_data_path, "w") as save_data: weatherurl = urlopen(Request(self.url)) self.weatherdata = weatherurl.read().decode("utf-8") save_data.write(str(self.nextupdatetime)) save_data.write("\n{}".format(self.weatherdata)) except URLError: self.ioerror()
def update(self, num): """called when update is triggered, and should return an array of arrays, each sub-array should contain one pygame object, and one pygame rect """ # Add a timestamp to stdout on each update call, priority # 0 ensures that it won't pop up constantly, priority=1 # ensures output will be seen no matter what debug settings # are enabled, and should be used sparingly: timestamp("Updating Yoga...", priority=0) print(num) rect = images[num].get_rect() rect.center = (800, 450) return [[images[num], rect]]
def truncate(self, text): """Truncates text passed in if it is too wide for screen""" try: textwidth = self.font[7].render(text, 0, self.colour) textwidth = textwidth.get_rect(left=self.width / 100, top=0) if textwidth[2] < self.width * 0.99: return u"{}".format(text) else: length = len(text) while textwidth[2] > self.width * 0.99: length -= 1 text = u" ".join(text[:length + 1].split(" ")[:-1]) + u"…" textwidth = self.font[7].render(text, 0, self.colour) textwidth = textwidth.get_rect(left=self.width / 100, top=0) return text except UnicodeError: timestamp("Error shortening string") return ""
def update(self): """Updates the time and date when called""" timestamp("Updating time module...") year, month, day, hour, minute = time.localtime()[0:5] date_string = self.dformat.format(y=year, m=month, d=day) # 24 hr time if self.tformat == 0: time_string = "{h:02d}:{m:02d}".format(h=hour, m=minute) else: if hour > 11: period = "pm" else: period = "am" if hour > 12: hour -= 12 if hour == 0: hour = 12 if self.tformat == 1: time_string = "{h}:{m:02d} {p}".format(h=hour, m=minute, p=period) elif self.tformat == 2: time_string = "{h}:{m:02d}".format(h=hour, m=minute) else: time_string = "Incorrect time format in settings" date_disp = self.font[1].render(date_string, 1, self.colour) time_disp = self.font[1].render(time_string, 1, self.colour) date_pos = date_disp.get_rect( right=self.width * 0.98, top=self.height * 0.01 ) if display_date is True: time_pos = time_disp.get_rect( right=self.width * 0.98, top=self.height * 0.01 + date_pos[3] ) else: time_pos = time_disp.get_rect( right=self.width * 0.98, top=self.height * 0.01 ) timestamp("Completed updating time module...") if display_date is True: return [[date_disp, date_pos], [time_disp, time_pos]] else: return [[time_disp, time_pos]]
def update(self): """ called when update is triggered, and should return an array of arrays, each sub-array should contain one pygame object, and one pygame rect """ timestamp("Updating picture module...") # Return image counter to 0 to properly scroll through images. if len(self.images) == 0: self.updatedelay = int(2e16) return [] try: image, imagepos = self.resize( pygame.image.load(self.images[self.counter % len(self.images)])) image.convert() image.set_alpha(128) self.counter += 1 except pygame.error: # If something goes wrong (not a properly formed image for example) # retry on the next image: timestamp("Image update failed, trying again...") return self.update() timestamp("Completed updating picture module...") return [[image, imagepos]]
def update(self): """ called when update is triggered, and should return an array of arrays, each sub-array should contain one pygame object, and one pygame rect """ timestamp("Updating picture module...") # Return image counter to 0 to properly scroll through images. if len(self.images) == 0: self.updatedelay = int(2e16) return [] try: image, imagepos = self.resize( pygame.image.load(self.images[ self.counter % len(self.images) ])) image.convert() image.set_alpha(128) self.counter += 1 except pygame.error: # If something goes wrong (not a properly formed image for example) # retry on the next image: timestamp("Image update failed, trying again...") return self.update() timestamp("Completed updating picture module...") return [[image, imagepos]]
def update(self): """called when update is triggered, and should return an array of arrays, each sub-array should contain one pygame object, and one pygame rect """ # Add a timestamp to stdout on each update call, priority # 0 ensures that it won't pop up constantly, priority=1 # ensures output will be seen no matter what debug settings # are enabled, and should be used sparingly: timestamp("Updating HelloWorldModule...", priority=0) # Defines text object hello, # any pygame object can be used: hello = self.font.render('Welcome Christopher', 1, self.colour) x = hello.get_width() y = hello.get_height() # Places the greeting in the bottom middle of the screen: hello_pos = hello.get_rect(left=(800 - x / 2), top=(800 - y)) return [[hello, hello_pos]]
def fetch_news(self): """Gets new stories when called""" stories = [] for subreddit in reddit_subreddits: timestamp("Fetching subreddit - {}...".format(subreddit)) useragent = ("{}:MagicMirror/Jackson-S/com.github:{} " + "(by /u/plainchips)") useragent = useragent.format(system(), version) prawagent = praw.Reddit(user_agent=useragent) sub = prawagent.get_subreddit(subreddit) sub = sub.get_top_from_day(limit=reddit_item_count) for item in sub: body = self.font[7].render(self.truncate(item.title), 1, self.colour) body_pos = body.get_rect(left=self.width / 100, bottom=self.height * 0.99) title = self.font[6].render(subreddit.title(), 1, self.colour) title_pos = title.get_rect(left=self.width / 100, bottom=self.height * 0.99 - body_pos[3]) stories.append([[body, body_pos], [title, title_pos]]) return stories
def update(self): """called when update is triggered, and should return an array of arrays, each sub-array should contain one pygame object, and one pygame rect """ # Add a timestamp to stdout on each update call, priority # 0 ensures that it won't pop up constantly, priority=1 # ensures output will be seen no matter what debug settings # are enabled, and should be used sparingly: timestamp("Updating Agenda...", priority=0) #gets the day for the agenda today = strftime("%A", localtime()) day = self.font1.render(today, 1, self.colour) day_pos = day.get_rect(left=30, top=30) schedule = [[day, day_pos]] intinerary = agenda[today] for x in intinerary: act, start, end = x if start > 12: begin = str(start - 12) + 'p.m.' else: begin = str(start) + 'a.m.' if end > 12: done = str(end - 12) + 'p.m.' else: done = str(end) + 'a.m.' activity = act + ' : ' + str(begin) + ' to ' + str(done) prev_obj = schedule[len(schedule) - 1] new_pos = prev_obj[1].y + prev_obj[1].height new_obj = self.font2.render(activity, 1, self.colour) x_pos = new_obj.get_rect(left=30, top=new_pos) schedule.append([new_obj, x_pos]) return schedule
def __init__(self): timestamp("Initialising time module") super(TimeModule, self).__init__() self.tformat = time_format self.dformat = date_format
def main(screen): state = 1 """UI of the program, loads and draws all modules.""" timestamp("Initialising main program...") loadingscreen(SCREEN) # Initialises the display # Enables clock, used for frame rate limiter: game_clock = pygame.time.Clock() pygame.mouse.set_visible(mouse_visible) try: # Check if vcgencmd is installed, to see if it is running on a # raspberry pi with the requires software installed call("vcgencmd") except: pass requires_update = False #main interface loop while True: game_clock.tick() while True: #set module list to the correct user state if state == 1: #no user state modules = [ TimeModule(), Agenda(), Quotes() ] elif state == 2 : #yoga instructor state modules = [ TimeModule(), YogaModule()] elif state == 3 : #general user state modules = [ TimeModule(), Greeting(), Routines()] module_display = [None] * len(modules) while requires_update is False: for module_no, module in enumerate(modules): if module.need_update() is True: if(module_no == 1 and state == 2): #case for updating yoga module num = check_Yoga_IR() module_display[module_no] = module.update(num) elif(module_no == 2 and state == 3): #case for updating routines module num1 = check_Routine_IR() module_display[module_no] = module.update(num1) else : module_display[module_no] = module.update() requires_update = True check_events() pygame.time.wait(200) timestamp("Commencing screen update...") screen.fill(colour[0]) for module in module_display: for item, item_pos in module: screen.blit(item, item_pos) pygame.display.flip() requires_update = False timestamp("Completed screen update...\n") #checks for profile update every loop state = checking_Serial(state)