1+ import time
2+ import json
3+ import displayio
4+ from adafruit_display_text .label import Label
5+ from adafruit_bitmap_font import bitmap_font
6+
7+ cwd = ("/" + __file__ ).rsplit ('/' , 1 )[0 ] # the current working directory (where this file is)
8+
9+ small_font = cwd + "/fonts/Arial-12.bdf"
10+ medium_font = cwd + "/fonts/Arial-16.bdf"
11+
12+ class Electioncal_Graphics (displayio .Group ):
13+ def __init__ (self , root_group , * , am_pm = True ):
14+ super ().__init__ (max_size = 2 )
15+ self .am_pm = am_pm
16+ root_group .append (self )
17+ self ._icon_group = displayio .Group (max_size = 1 )
18+ self .append (self ._icon_group )
19+ self ._text_group = displayio .Group (max_size = 9 )
20+ self .append (self ._text_group )
21+
22+ self ._icon_sprite = None
23+ self ._icon_file = None
24+ self .set_icon (cwd + "/icons/electioncal.bmp" )
25+
26+ self .small_font = bitmap_font .load_font (small_font )
27+ self .medium_font = bitmap_font .load_font (medium_font )
28+ glyphs = b'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,.: '
29+ self .small_font .load_glyphs (glyphs )
30+ self .medium_font .load_glyphs (glyphs )
31+
32+ self .date_text = Label (self .small_font , max_glyphs = 21 )
33+ self .date_text .x = 15
34+ self .date_text .y = 195
35+ self .date_text .color = 0xFFFFFF
36+ self ._text_group .append (self .date_text )
37+
38+ self .url_text = Label (self .small_font , max_glyphs = 35 )
39+ self .url_text .x = 15
40+ self .url_text .y = 220
41+ self .url_text .color = 0xFFFFFF
42+ self ._text_group .append (self .url_text )
43+ self .url_text .text = "Visit us at https://electioncal.us"
44+
45+ self .state_text = Label (self .small_font , max_glyphs = 60 )
46+ self .state_text .x = 15
47+ self .state_text .y = 10
48+ self .state_text .color = 0xFFFFFF
49+ self ._text_group .append (self .state_text )
50+
51+ self .election_date_text = Label (self .medium_font , max_glyphs = 11 )
52+ self .election_date_text .x = 15
53+ self .election_date_text .y = 60
54+ self .election_date_text .color = 0xFFFFFF
55+ self ._text_group .append (self .election_date_text )
56+
57+ self .election_name_text = Label (self .small_font , max_glyphs = 60 )
58+ self .election_name_text .x = 15
59+ self .election_name_text .y = 95
60+ self .election_name_text .color = 0xFFFFFF
61+ self ._text_group .append (self .election_name_text )
62+
63+ self .election_name_text_line2 = Label (self .small_font , max_glyphs = 60 )
64+ self .election_name_text_line2 .x = 15
65+ self .election_name_text_line2 .y = 120
66+ self .election_name_text_line2 .color = 0xFFFFFF
67+ self ._text_group .append (self .election_name_text_line2 )
68+
69+
70+ def load_data (self , election_data ):
71+ try :
72+ self .electioncal = json .loads (election_data )
73+ self .state_text .text = self .electioncal ["dates" ][1 ]["county" ] + ", " + self .electioncal ["dates" ][0 ]["state" ]
74+ except ValueError :
75+ print ("Error loading JSON data: Please check the configuration of county and state, in code.py" )
76+ raise
77+
78+ def elections_cycle (self ):
79+ self .update_time ()
80+ num_elections = len (self .electioncal ["dates" ])
81+
82+ for i in range (0 ,num_elections ):
83+ if self .date_text .text [10 :] < self .electioncal ["dates" ][i ]["date" ]:
84+ self .election_date_text .text = self .electioncal ["dates" ][i ]["date" ]
85+ # splitting the line at around 40 chars seems ok for regular PyPortal
86+ self .election_name_text_line2 .text , self .election_name_text .text = self .paragrapher (self .electioncal ["dates" ][i ]["name" ], 40 )
87+ time .sleep (30 )
88+
89+ def update_time (self ):
90+ """Fetch the time.localtime(), parse it out and update the display text"""
91+ now = time .localtime ()
92+ hour = now [3 ]
93+ minute = now [4 ]
94+ year = now [0 ]
95+ month = now [1 ]
96+ day = now [2 ]
97+ time_format_str = "%d:%02d"
98+ date_format_str = "%d-%02d-%02d"
99+ if self .am_pm :
100+ if hour >= 12 :
101+ hour -= 12
102+ time_format_str = time_format_str + " PM"
103+ else :
104+ time_format_str = time_format_str + " AM"
105+ if hour == 0 :
106+ hour = 12
107+ time_str = time_format_str % (hour , minute )
108+ date_str = date_format_str % (year , month , day )
109+ self .date_text .text = "Today is: " + date_str
110+
111+ def paragrapher (self , text , cut ):
112+ """ Cuts a long line into two, having spaces in mind.
113+ Note we return line2 first as it looks better to clear the line2
114+ before printing a line1 with empty line2
115+ We run from cut, backwards till we find a space.
116+ """
117+ if len (text ) > cut :
118+ for i in range (cut ,0 ,- 1 ):
119+ if text [i ] == " " :
120+ break
121+ line1 = text [0 :i ]
122+ line2 = text [i + 1 :80 ]
123+ else :
124+ line1 = text
125+ line2 = ""
126+ return line2 , line1
127+
128+ def set_icon (self , filename ):
129+ """The background image to a bitmap file.
130+
131+ :param filename: The filename of the chosen icon
132+
133+ """
134+ print ("Set icon to " , filename )
135+ if self ._icon_group :
136+ self ._icon_group .pop ()
137+
138+ if not filename :
139+ return # we're done, no icon desired
140+ if self ._icon_file :
141+ self ._icon_file .close ()
142+ self ._icon_file = open (filename , "rb" )
143+ icon = displayio .OnDiskBitmap (self ._icon_file )
144+ try :
145+ self ._icon_sprite = displayio .TileGrid (icon ,
146+ pixel_shader = displayio .ColorConverter ())
147+ except TypeError :
148+ self ._icon_sprite = displayio .TileGrid (icon ,
149+ pixel_shader = displayio .ColorConverter (),
150+ position = (0 ,0 ))
151+ self ._icon_group .append (self ._icon_sprite )
0 commit comments