Toggle Navigation
Hatchery
Eggs
Event schedule
event_schedule.py
Users
Badges
Login
Register
MCH2022 badge?
go to mch2022.badge.team
event_schedule.py
raw
Content
import ugfx, badge, wifi, json, time, utime, deepsleep, easydraw import urequests as requests from event_schedule import event_alarm import os callback = lambda: print("NO CALLBACK?!?!?!") class EventGUI(): # {chr(i):ugfx.get_string_width(chr(i),'pixelade13') for i in range(0,256) if ugfx.get_string_width(chr(i),'pixelade13')!=6} charwidths={ 'Roboto_Regular12': {'^': 5, 'Y': 7, 'X': 8, '[': 3, 'Z': 7, '%': 9, '$': 7, "'": 2, '&': 7, '!': 3, ' ': 3, '#': 7, '"': 4, '-': 3, ',': 2, '/': 5, '.': 3, ')': 4, '(': 4, '+': 7, '*': 5, '5': 7, '4': 7, '7': 7, '6': 7, '1': 7, '0': 7, '3': 7, '2': 7, '=': 7, '9': 7, '8': 7, ';': 3, ':': 3, '\x00': 0, '\t': 87, 'd': 7, 'g': 7, 'f': 4, 'a': 7, '`': 4, 'b': 7, 'm': 11, 'l': 3, 'o': 7, 'n': 7, 'i': 3, 'h': 7, 'j': 3, 'u': 7, 't': 4, 'w': 9, 'q': 7, 'p': 7, 'r': 4, '}': 4, '|': 3, '~': 8, '{': 4, 'E': 7, 'D': 8, 'G': 8, 'F': 7, 'A': 8, '@': 11, 'C': 8, 'B': 7, 'M': 10, 'O': 8, 'N': 9, 'I': 3, 'H': 9, 'K': 8, 'J': 7, 'U': 8, 'T': 7, 'W': 11, 'V': 8, 'Q': 8, 'P': 8, 'S': 7, 'R': 7, ']': 3, '\\': 5, '_': 5}, 'pixelade13': {'r': 5, ',': 3, ';': 3, ':': 3, '/': 8, '.': 2, ')': 4, '(': 4, 'e': 5, '\x00': 0, 'E': 5, '7': 5, 'F': 5, 'w': 8, '@': 8, 'z': 5, '\t': 64, 'M': 7, '{': 4, '|': 3, '}': 4, 'I': 4, '~': 5, 'T': 7, 'W': 8, '%': 8, '$': 7, ']': 4, '\\': 8, '!': 2, '^': 4, ' ': 3, "'": 3, '[': 4, 'a': 5, '`': 3, 'c': 5, 'b': 5, 'm': 8, 'l': 3, 'o': 5, '&': 8, 'i': 3, '#': 8, '"': 4, '1': 3, 'j': 3, 't': 3, 'u': 5, 'v': 5, '-': 5, 'p': 5, 's': 5} } def splitlines(self,txt,width,font): words=txt.split(" ") sentencelen=0 sentence="" lines=[] for word in words: wordlen=self.charwidths[font][' '] for letter in word: if letter in self.charwidths[font]: wordlen+=self.charwidths[font][letter] else: wordlen+=6 if sentencelen+wordlen<width: sentencelen+=wordlen sentence=sentence+" "+word if len(sentence) else word else: lines+=[sentence] sentencelen=wordlen sentence=word lines+=[sentence] return lines def errormsg(self,title,errormsg): print("ERROR: %s",errormsg) ugfx.clear(ugfx.WHITE) ugfx.string(0, 0, title, "PermanentMarker22", ugfx.BLACK) ugfx.string(0, 25, errormsg, "Roboto_Regular12", ugfx.BLACK) ugfx.flush() def listdates(self): ugfx.clear(ugfx.WHITE) ugfx.string(0, 0, "Select Date", "Roboto_Regular12", ugfx.BLACK) options = ugfx.List(0,15,ugfx.width(),ugfx.height()-15*4) for day in sorted(self.schedule_data["days"]): options.add_item("%s" % self.schedule_data["days"][day]) options.selected_index(self.dayselect) ugfx.string(0, ugfx.height()-45, "Right: Select A: Alarms", "Roboto_Regular12", ugfx.BLACK) ugfx.string(0, ugfx.height()-30, "Left: Refresh B: Exit", "Roboto_Regular12", ugfx.BLACK) ugfx.string(0, ugfx.height()-15, self.schedule_data['version'], "Roboto_Regular12", ugfx.BLACK) ugfx.flush() def listrooms(self): ugfx.clear(ugfx.WHITE) ugfx.string(0, 0, "Select Room", "Roboto_Regular12", ugfx.BLACK) options = ugfx.List(0,15,ugfx.width(),ugfx.height()-15*4) for room in self.rooms: options.add_item("%s" % room) options.selected_index(self.roomselect) ugfx.string(0, ugfx.height()-45, "Right: Select", "Roboto_Regular12", ugfx.BLACK) ugfx.string(0, ugfx.height()-30, "Left: Days", "Roboto_Regular12", ugfx.BLACK) ugfx.string(0, ugfx.height()-15, self.schedule_data['version'], "Roboto_Regular12", ugfx.BLACK) ugfx.flush() def showhomescreen(self,position): if badge.nvs_get_u8('splash', 'nickname', True): position += easydraw.nickname() position += 4 ugfx.line(0, position, ugfx.width(), position, ugfx.BLACK) position += 4 ugfx.line(0, ugfx.height()-16, ugfx.width(), ugfx.height()-16, ugfx.BLACK) if len(sorted(self.later.keys())) and self.later[sorted(self.later.keys())[0]]['timestamp'] < time.time(): self.get_later() ugfx.string(5, position, "Upcoming", "Roboto_Regular18", ugfx.BLACK) if not len(sorted(self.later.keys())): ugfx.string(5, position+24, "Nothing", "Roboto_Regular18", ugfx.BLACK) ugfx.string(5, position+48, "Today", "Roboto_Regular18", ugfx.BLACK) return i=0 height = 45 for idx in sorted(self.later.keys())[0:4]: talk=self.later[idx] window= ugfx.Container(0,position+24+i*height,ugfx.width(),height) window.show() if ugfx.orientation() in [0,180]: window.text(3,0,talk['day']+" "+talk['start']+": "+talk['title'],ugfx.BLACK) else: window.text(3,0,talk['day']+" "+talk['start']+(" @@" if event_alarm.alarm_exists(talk['guid']) else "") ,ugfx.BLACK) lines = self.splitlines(talk['title'],ugfx.width()-4,'pixelade13') for j in range(0,2): if len(lines) > j: window.text(3,12+12*j,lines[j],ugfx.BLACK) i+=1 def listtalks(self): ugfx.clear(ugfx.WHITE) ugfx.string(0, 0, "Select Talk: "+self.room, "Roboto_Regular12", ugfx.BLACK) ugfx.set_default_font('pixelade13') height = int((ugfx.height()-2*30)/4) stringlen = int(ugfx.width() / 6) for i in range(0,4): skip=(self.talkselect - 2 if self.talkselect<len(self.talks)-2 else len(self.talks)-4) if self.talkselect > 2 else 0 if len(self.talks)> i+skip: window= ugfx.Container(0,15+i*height,ugfx.width(),height) window.show() if i+skip==self.talkselect: ugfx.area(0,15+i*height,ugfx.width(),height,ugfx.BLACK) if ugfx.orientation() in [0,180]: window.text(3,0,self.schedule_data["days"][self.day]+" "+self.talks[i+skip]['start']+": "+self.talks[i+skip]['title'],ugfx.BLACK if i+skip!=self.talkselect else ugfx.WHITE) else: window.text(3,0,self.schedule_data["days"][self.day]+" "+self.talks[i+skip]['start']+(" @@" if event_alarm.alarm_exists(self.talks[i+skip]['guid']) else ""),ugfx.BLACK if i+skip!=self.talkselect else ugfx.WHITE) lines = self.splitlines(self.talks[i+skip]['title'],ugfx.width()-4,'pixelade13') for j in range(0,3): if len(lines) > j: window.text(3,12+12*j,lines[j],ugfx.BLACK if i+skip!=self.talkselect else ugfx.WHITE) ugfx.string(0, ugfx.height()-45, "Right: Select", "Roboto_Regular12", ugfx.BLACK) ugfx.string(0, ugfx.height()-30, "Left: Rooms", "Roboto_Regular12", ugfx.BLACK) ugfx.string(0, ugfx.height()-15, self.schedule_data['version'], "Roboto_Regular12", ugfx.BLACK) ugfx.flush() def listalarms(self): ugfx.clear(ugfx.WHITE) ugfx.string(0, 0, "Talks with alarm:", "Roboto_Regular12", ugfx.BLACK) ugfx.set_default_font('pixelade13') height = int((ugfx.height()-2*30)/4) stringlen = int(ugfx.width() / 6) for i in range(0,4): skip=(self.talkselect - 2 if self.talkselect<len(self.talks)-2 else len(self.talks)-4) if self.talkselect > 2 else 0 if len(self.talks)> i+skip: window= ugfx.Container(0,15+i*height,ugfx.width(),height) window.show() if i+skip==self.talkselect: ugfx.area(0,15+i*height,ugfx.width(),height,ugfx.BLACK) if ugfx.orientation() in [0,180]: window.text(3,0,self.talks[i+skip]['day']+" "+self.talks[i+skip]['start']+": "+self.talks[i+skip]['title'],ugfx.BLACK if i+skip!=self.talkselect else ugfx.WHITE) else: window.text(3,0,self.talks[i+skip]['day']+" "+self.talks[i+skip]['start']+(" @@" if event_alarm.alarm_exists(self.talks[i+skip]['guid']) else "") ,ugfx.BLACK if i+skip!=self.talkselect else ugfx.WHITE) lines = self.splitlines(self.talks[i+skip]['title'],ugfx.width()-4,'pixelade13') for j in range(0,3): if len(lines) > j: window.text(3,12+12*j,lines[j],ugfx.BLACK if i+skip!=self.talkselect else ugfx.WHITE) ugfx.string(0, ugfx.height()-45, "Right: Select", "Roboto_Regular12", ugfx.BLACK) ugfx.string(0, ugfx.height()-30, "Left: Main", "Roboto_Regular12", ugfx.BLACK) ugfx.string(0, ugfx.height()-15, self.schedule_data['version'], "Roboto_Regular12", ugfx.BLACK) ugfx.flush() def talkdetails(self): ugfx.orientation(self.orientation) ugfx.clear(ugfx.WHITE) ugfx.set_default_font('pixelade13') height = int((ugfx.height()-2*30)/4) stringlen = int(ugfx.width() / 5) ugfx.string(0, 0, "Room: "+self.talk['room'], "Roboto_Regular12", ugfx.BLACK) ugfx.string(0, 15, self.talk['day']+" "+self.talk['start'], "Roboto_Regular12", ugfx.BLACK) ugfx.string(0, 30, "Duration: "+self.talk['duration'], "Roboto_Regular12", ugfx.BLACK) ugfx.string(0, 45, "Speaker:", "Roboto_Regular12", ugfx.BLACK) ugfx.string(0, 60," "+", ".join(self.details['persons']), "Roboto_Regular12", ugfx.BLACK) ugfx.box(0,75,ugfx.width(),ugfx.height()-75-45,ugfx.BLACK) for i in range(0,self.maxlines): if len(self.lines)>self.lineselect+i: ugfx.string(2, 75+i*15,self.lines[self.lineselect+i], "Roboto_Regular12", ugfx.BLACK) ugfx.string(0, ugfx.height()-45, "A: Remove Alarm" if event_alarm.alarm_exists(self.talk['guid']) else "A: Set Alarm", "Roboto_Regular12", ugfx.BLACK) ugfx.string(0, ugfx.height()-30, "Left: Talks", "Roboto_Regular12", ugfx.BLACK) ugfx.string(0, ugfx.height()-15, self.schedule_data['version'], "Roboto_Regular12", ugfx.BLACK) ugfx.flush() class EventSchedule(EventGUI): selected = 0 offset = 500 selected = None oldscreen = "" screen = "main" days = {} rooms = {} talks = {} dayselect = None talkselect = None roomselect = None lineselect = None schedule_data = {} day_data = {} # as python does NOT sort dicts (don't trust it!) use: # showindex = sorted(event_schedule.schedule.now)[0:4] # ... # showindex = sorted(event_schedule.schedule.later)[0:4] # ... now = {} later = {} def get_later(self): self.get_now() def get_now(self): self.now = {} self.later = {} for day in self.schedule_data["days"]: self.day_data[day] = self.download("day/"+day+".json") realday=self.days[day] if realday == time.strftime("%Y-%m-%d"): roomnum=0 timestamp=time.time() for room in self.day_data[day]["rooms"]: roomnum +=1 for event in self.day_data[day]["rooms"][room]: event['day']=realday event['room']=room if event['timestamp'] < timestamp and event['end'] > timestamp and event['type']=='lecture': self.now[event['timestamp']*1000+roomnum]=event elif event['timestamp'] > timestamp and event['type']=='lecture': self.later[event['timestamp']*1000+roomnum]=event def init(self,force=False): if self.schedule_data != {} and not force: return try: os.mkdir("/lib/event_schedule/event") except: pass try: os.mkdir("/lib/event_schedule/day") except: pass # Fuck no directories. try: os.rename('/lib/event_schedule/0.json','/lib/event_schedule/day/0.json') except: pass try: os.rename('/lib/event_schedule/1.json','/lib/event_schedule/day/1.json') except: pass try: os.rename('/lib/event_schedule/2.json','/lib/event_schedule/day/2.json') except: pass self.schedule_data = self.download("schedule.json") self.days = self.schedule_data["days"] self.get_now() def refreshschedule(self,filename): self.errormsg("Loading...", "WiFi: starting radio...") wifi.connect() if not wifi.wait(30,True): self.exitapp() self.errormsg("Loading...", "Downloading file...") try: data = requests.get(self.url+"schedule.json") except: self.errormsg("Error", "Could not download JSON!") utime.sleep(5) self.screen="main" try: jsondata = data.json() except: data.close() self.errormsg("Error", "Could not decode JSON!") utime.sleep(5) self.screen="main" if jsondata['version']!=self.schedule_data['version']: try: f = open("/lib/event_schedule/schedule.json","w") f.write(json.dumps(jsondata)) f.close() self.schedule_data=jsondata for bestand in os.listdir('/lib/event_schedule/event'): os.remove('/lib/event_schedule/event'+bestand) for bestand in os.listdir('/lib/event_schedule/day'): os.remove('/lib/event_schedule/event'+bestand) except: pass def download(self,filename): try: f=open("/lib/event_schedule/"+filename,"r") data=f.read() f.close() return json.loads(data) except: self.errormsg("Loading...", "WiFi: starting radio...") wifi.connect() if not wifi.wait(30,True): self.exitapp() self.errormsg("Loading...", "Downloading file...") try: data = requests.get(self.url+filename) except: self.errormsg("Error", "Could not download JSON!") utime.sleep(5) self.screen="main" try: jsondata = data.json() except: data.close() self.errormsg("Error", "Could not decode JSON!") utime.sleep(5) self.screen="main" try: f = open("/lib/event_schedule/"+filename,"w") f.write(json.dumps(jsondata)) f.close() except: pass data.close() return jsondata def initscreen_main(self): self.dayselect = 0 if self.dayselect == None else self.dayselect def initscreen_day(self): self.day = sorted(self.schedule_data['days'])[ self.dayselect ] self.rooms = [ room for room in self.day_data[self.day]['rooms'] ] self.rooms.sort() self.roomselect = 0 if self.roomselect == None or self.oldscreen!="room" else self.roomselect def initscreen_room(self): self.room = self.rooms[ self.roomselect ] self.talks = sorted(self.day_data[self.day]['rooms'][self.room], key=lambda kv: kv['start']) self.talkselect = 0 if self.talkselect == None or self.oldscreen!="talk" else self.talkselect def initscreen_alarm(self): self.talks = [] for alarm in event_alarm.alarms: guid=alarm['guid'] room=alarm['room'] for day in self.schedule_data['days'].keys(): if room in self.day_data[day]['rooms']: for talk in self.day_data[day]['rooms'][room]: if talk['guid']==guid: talk['day']=self.schedule_data['days'][day] talk['room']=room self.talks.append(talk) self.talkselect = 0 if self.talkselect == None or self.oldscreen!="talk" else self.talkselect def initscreen_talk(self): self.talk = self.talks[self.talkselect] self.talk['room'] = self.room if self.oldscreen=='room' else self.talk['room'] self.talk['day'] = self.day if self.oldscreen=='room' else self.talk['day'] self.details = self.download("event/"+self.talk['guid']) self.lineselect = 0 stringlen = int(ugfx.width() / 6) self.lines = self.splitlines(self.details['description'],ugfx.width()-4,'Roboto_Regular12') self.maxlines = int((ugfx.height()-75-45)/15) def drawscreen(self): if self.oldscreen!=self.screen: ugfx.clear(ugfx.BLACK) ugfx.flush() getattr(self,"initscreen_"+self.screen)() self.previousscreen=self.oldscreen self.oldscreen=self.screen if self.screen=="main": self.listdates() if self.screen=="day": self.listrooms() if self.screen=="room": self.listtalks() if self.screen=="talk": self.talkdetails() if self.screen=="alarm": self.listalarms() def knopje(self,selected,active): if active: getattr(self,"knopje_"+self.screen)(selected) self.drawscreen() def setscreen(self,screen): self.screen=screen def knopje_main(self,selected): def up(): self.dayselect = self.dayselect - 1 if self.dayselect > 0 else 0 def down(): self.dayselect = self.dayselect + 1 if self.dayselect < len(self.days)-2 else len(self.days)-1 actions = { ugfx.JOY_DOWN : lambda: down() , ugfx.JOY_UP : lambda: up() , ugfx.JOY_LEFT : lambda: self.refreshschedule() , ugfx.JOY_RIGHT : lambda: self.setscreen("day") , ugfx.BTN_B : lambda: self.exitapp() , ugfx.BTN_A : lambda: self.setscreen("alarm") } if selected in actions: actions[selected]() def knopje_day(self,selected): def up(): self.roomselect = self.roomselect - 1 if self.roomselect > 0 else 0 def down(): self.roomselect = self.roomselect + 1 if self.roomselect < len(self.rooms)-2 else len(self.rooms)-1 actions = { ugfx.JOY_DOWN : lambda: down() , ugfx.JOY_UP : lambda: up() , ugfx.JOY_LEFT : lambda: self.setscreen("main") , ugfx.JOY_RIGHT : lambda: self.setscreen("room") , ugfx.BTN_B : lambda: self.exitapp() } if selected in actions: actions[selected]() def knopje_room(self,selected): def up(): self.talkselect = self.talkselect - 1 if self.talkselect > 0 else 0 def down(): self.talkselect = self.talkselect + 1 if self.talkselect < len(self.talks)-2 else len(self.talks)-1 actions = { ugfx.JOY_DOWN : lambda: down() , ugfx.JOY_UP : lambda: up() , ugfx.JOY_LEFT : lambda: self.setscreen("day") , ugfx.JOY_RIGHT : lambda: self.setscreen("talk") , ugfx.BTN_B : lambda: self.exitapp() } if selected in actions: actions[selected]() def knopje_alarm(self,selected): def up(): self.talkselect = self.talkselect - 1 if self.talkselect > 0 else 0 def down(): self.talkselect = self.talkselect + 1 if self.talkselect < len(self.talks)-2 else len(self.talks)-1 actions = { ugfx.JOY_DOWN : lambda: down() , ugfx.JOY_UP : lambda: up() , ugfx.JOY_LEFT : lambda: self.setscreen("main") , ugfx.JOY_RIGHT : lambda: self.setscreen("talk") , ugfx.BTN_B : lambda: self.exitapp() } if selected in actions: actions[selected]() def knopje_talk(self,selected): def up(): self.lineselect = self.lineselect - 1 if self.lineselect > 0 else 0 def down(): self.lineselect = self.lineselect + 1 if self.lineselect < len(self.lines)-self.maxlines else len(self.lines)-self.maxlines if len(self.lines)-self.maxlines > 0 else 0 actions = { ugfx.JOY_DOWN : lambda: down() , ugfx.JOY_UP : lambda: up() , ugfx.JOY_LEFT : lambda: self.setscreen( self.previousscreen) , ugfx.BTN_A : lambda: event_alarm.alarms_remove(self.talk) if event_alarm.alarm_exists(self.talk['guid']) else event_alarm.alarms_add(self.talk) , ugfx.BTN_B : lambda: self.exitapp() } if selected in actions: actions[selected]() def exitapp(self): deepsleep.start_sleeping(1) def run(self): global callback event_alarm.alarms_read() self.callback=callback ugfx.init() ugfx.flush() ugfx.orientation(self.orientation) ugfx.flush() ugfx.input_attach(ugfx.JOY_RIGHT, lambda x: self.knopje(ugfx.JOY_RIGHT ,x)) ugfx.input_attach(ugfx.JOY_LEFT, lambda x: self.knopje(ugfx.JOY_LEFT ,x)) ugfx.input_attach(ugfx.JOY_UP, lambda x: self.knopje(ugfx.JOY_UP ,x)) ugfx.input_attach(ugfx.JOY_DOWN, lambda x: self.knopje(ugfx.JOY_DOWN ,x)) ugfx.input_attach(ugfx.BTN_A, lambda x: self.knopje(ugfx.BTN_A ,x)) ugfx.input_attach(ugfx.BTN_B, lambda x: self.knopje(ugfx.BTN_B ,x)) ugfx.input_attach(ugfx.BTN_START, lambda x: self.knopje(ugfx.BTN_START ,x)) ugfx.input_attach(ugfx.BTN_SELECT, lambda x: self.knopje(ugfx.BTN_SELECT,x)) self.drawscreen() class HackerHotelSchedule(EventSchedule): url="https://badge.team/schedule/" orientation = 90 schedule=HackerHotelSchedule() schedule.init()