Toggle Navigation
Hatchery
Eggs
Calendar
__init__.py
Users
Badges
Login
Register
MCH2022 badge?
go to mch2022.badge.team
__init__.py
raw
Content
"""Displays the time and also alerts.""" # pylint: disable=bare-except # pylint: disable=import-error # pylint: disable=no-self-use # pylint: disable=too-few-public-methods import display import easydraw import machine import utime import wifi import urequests as requests import ubinascii EUROPE_LONDON = 'GMT+0BST-1,M3.5.0/01:00:00,M10.5.0/02:00:00' EUROPE_BRUSSELS = 'CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00' WHITE = 0xFFFFFF BLACK = 0x000000 FONTS = { '7x5': '7x5', 'Dejavu Sans': { 20: 'dejavusans20', }, 'Ocra': { 16: 'ocra16', 22: 'ocra22', }, 'Permanent Marker': { 22: 'permanentmarker22', 36: 'permanentmarker36', }, 'Roboto Regular': { 12: 'roboto_regular12', 18: 'roboto_regular18', 22: 'roboto_regular22', }, 'Roboto Black': { 22: 'roboto_black22', }, 'Roboto Black Italic': { 24: 'roboto_blackitalic24', }, } WEEKDAYS = { 1: 'Sunday', 2: 'Monday', 3: 'Tuesday', 4: 'Wednesday', 5: 'Thursday', 6: 'Friday', 7: 'Saturday' } TOPIC_INFO = b'home/house/alert/info_string' def main(): easydraw.msg('setting up WiFi...') if not init_wifi(): easydraw.msg('could not set up WiFi') return easydraw.msg('setting up RTC...') clock = Clock() output = Output() while True: output.draw(clock.get()) utime.sleep(1) def init_wifi(): """Set up the WiFi.""" if wifi.status(): return True wifi.connect() return wifi.wait() class Clock: """Manages the Real Time Clock and NTP.""" def __init__(self, default_timezone=EUROPE_LONDON): if utime.time() < 1585235437: # RTC is unset. wifi.ntp() self._rtc = machine.RTC() timezone = default_timezone try: timezone = machine.nvs_getstr('system', 'timezone') except AttributeError: easydraw.msg("Could not read timezone") if not timezone: timezone = default_timezone try: self._rtc.timezone(timezone) except AttributeError: easydraw.msg("Could not set timezone") def get(self): """Returns a datetime tuple of (y, m, d, h, m, s, wd, yd).""" try: return self._rtc.now() except AttributeError: (y, m, d, wd, h, m, s, subs) = self._rtc.datetime() return y, m, d, h, m, s, wd class VEvent: def __init__(self, properties): self.properties = properties def parse_date(self, datetime, isEndDate=False): year = int(datetime[0:4]) month = int(datetime[4:6]) day = int(datetime[6:8]) if len(datetime) <= 8 and isEndDate: return year, month, day, 23, 59, 59 if len(datetime) <= 8: return year, month, day, 0, 0, 0 hour = int(datetime[9:11]) min = int(datetime[11:13]) sec = int(datetime[13:15]) return year, month, day, hour, min, sec def start_time(self): for k in self.properties.keys(): if k.startswith("DTSTART"): return self.parse_date(self.properties[k]) print("Could not determine start-time for"+str(self.properties)) def end_time(self): for k in self.properties.keys(): if k.startswith("DTEND"): datetime = self.properties[k] return self.parse_date(datetime) print("Could not determine end-time for "+str(self.properties)) def activeDuring(self, start, end): return start < self.start_time() and self.end_time() < end def summary(self): print(self.properties) l = "" if "LOCATION" in self.properties: l = " location: "+ self.properties["LOCATION"] return self.properties["SUMMARY"] + l class Calendar: def __init__(self, password=None, url="https://caldav.sphinxpinastri.duckdns.org/pietervdvn/4e2a22bf-a05f-3325-1c3e-67b7dff894cd", username="pietervdvn"): self.password = password self.username = username self.url = url def fetch(self): if not wifi.status(): print("Connecting to wifi...") easydraw.msg("Connecting to wifi...") wifi.connect() wifi.wait() easydraw.msg("Connected!") print("Connected!") headers = {"Authorization": None} if self.password is not None: headers["Authorization"] = "Basic " + ubinascii.b2a_base64(self.username + ":" + self.password).decode( "UTF8") r = requests.request("GET", self.url, None, None, headers) txt = r.content r.close() return txt def from_file(self, path): f = open(path, 'r') txt = f.read() f.close() return txt def active_next(self, ical_text, start, end): """ Returns a list of all VEVENTs that are active between 'start' and 'end' :param ical_text: :param start: (y, m, d, h, m, s) :param end: (y, m, d, h, m, s) :return: list of dicts """ def f(event : VEvent): if event.activeDuring(start, end): print(event.summary()) else: # print("???" + str(event.properties)) pass self.parseIcal(ical_text, f) def parseIcal(self, ical_text, on_event): perline = ical_text.split("\n") current_properties = None key = None skip_line = False for line in perline: if line == "BEGIN:VEVENT": current_properties = {} continue if line == "END:VEVENT": on_event(VEvent(current_properties)) current_properties = None continue if current_properties is None: continue if skip_line: skip_line = False continue if line.startswith("ATTENDEE;"): skip_line = True continue if line.startswith(" "): current_properties[key] = current_properties[key] + line[1:] continue props = line.split(":") key = props[0] current_properties[key] = props[1] class Output: """Manages all formatting, display.""" def __init__(self): self._old_date_str = '' self._old_time_str = '' def draw(self, datetime): """Draw the date & time. Clear the screen to prevent ghosting: - When the date changes. - When entering an alert. - When leaving an alert. """ time_str = self._format_time(datetime) date_str = self._format_date(datetime) if time_str == self._old_time_str: return if date_str != self._old_date_str: # we've come out of an alert or the date changed, # so clear the screen to prevent ghosting. display.drawFill(BLACK) display.flush() self._old_date_str = date_str self._old_time_str = time_str display.drawFill(WHITE) display.drawText(0, 0, time_str, BLACK, FONTS['7x5'], 5, 5) bottom = display.height() - 2 # the bottom pixel seems to clip. date_y = bottom - (display.getTextHeight(date_str, FONTS['7x5']) * 3) display.drawText(0, date_y, date_str, BLACK, FONTS['7x5'], 3, 3) display.flush() def _format_time(self, datetime): hours = datetime[3] minutes = datetime[4] return '%02d:%02d' % (hours, minutes) def _format_date(self, datetime): weekday = datetime[6] return WEEKDAYS[weekday] c = Calendar(input("Password? ")) ics = c.fetch() c.active_next(ics, (2022, 7, 1, 0, 0, 0), (2022, 8, 1, 0, 0, 0))