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