1212All text above must be included in any redistribution.
1313"""
1414
15- #pylint:disable=redefined-outer-name,no-member,global-statement,no-self-use
16- #pylint:disable=too-many-branches,too-many-statements,useless-super-delegation
15+ #pylint:disable=redefined-outer-name,no-member,global-statement
16+ #pylint:disable=no-self-use,too-many-branches,too-many-statements
17+ #pylint:disable=useless-super-delegation, too-many-locals
1718
1819import time
1920import json
2021from secrets import secrets
2122import board
2223from adafruit_pyportal import PyPortal
2324from adafruit_bitmap_font import bitmap_font
24- from adafruit_display_text .text_area import TextArea
25+ from adafruit_display_text .label import Label
2526from digitalio import DigitalInOut , Direction , Pull
2627import analogio
2728import displayio
29+ import adafruit_logging as logging
2830
2931# Set up where we'll be fetching data from
3032DATA_SOURCE = 'http://api.openweathermap.org/data/2.5/weather?id=' + secrets ['city_id' ]
3739
3840pyportal = PyPortal (url = DATA_SOURCE ,
3941 json_path = DATA_LOCATION ,
40- status_neopixel = board .NEOPIXEL ,
41- splash_max = 10 )
42+ status_neopixel = board .NEOPIXEL )
4243
4344light = analogio .AnalogIn (board .LIGHT )
4445
5657alarm_enabled = True
5758alarm_armed = True
5859alarm_interval = 5.0
59- alarm_hour = 23
60- alarm_minute = 20
60+ alarm_hour = 9
61+ alarm_minute = 45
6162snooze_time = None
6263snooze_interval = 600.0
6364
65+ # mugsy support
66+ mugsy_background = 'mugsy_background.bmp'
67+
6468# weather support
6569
6670icon_file = None
8185####################
8286# Load the fonts
8387
84- large_font = bitmap_font .load_font ('/fonts/Anton-Regular-104.bdf' )
85- large_font .load_glyphs (b'0123456789:' ) # pre-load glyphs for fast printing
88+ time_font = bitmap_font .load_font ('/fonts/Anton-Regular-104.bdf' )
89+ time_font .load_glyphs (b'0123456789:' ) # pre-load glyphs for fast printing
90+
91+ alarm_font = bitmap_font .load_font ('/fonts/Helvetica-Bold-36.bdf' )
92+ alarm_font .load_glyphs (b'0123456789:' )
8693
87- medium_font = bitmap_font .load_font ('/fonts/Helvetica-Bold-36 .bdf' )
88- medium_font .load_glyphs (b'0123456789: ' )
94+ temperature_font = bitmap_font .load_font ('/fonts/Arial-16 .bdf' )
95+ temperature_font .load_glyphs (b'0123456789CF ' )
8996
90- small_font = bitmap_font . load_font ( '/fonts/Arial-16.bdf' )
91- small_font . load_glyphs ( b'0123456789CF' )
97+ ####################
98+ # Set up logging
9299
100+ logger = logging .getLogger ('alarm_clock' )
101+ logger .setLevel (logging .ERROR ) # change as desired
93102
94103####################
95104# Functions
@@ -98,7 +107,7 @@ def create_text_areas(configs):
98107 """Given a list of area specifications, create and return test areas."""
99108 text_areas = []
100109 for cfg in configs :
101- textarea = TextArea (cfg ['font' ], text = ' ' * cfg ['size' ])
110+ textarea = Label (cfg ['font' ], text = ' ' * cfg ['size' ])
102111 textarea .x = cfg ['x' ]
103112 textarea .y = cfg ['y' ]
104113 textarea .color = cfg ['color' ]
@@ -112,7 +121,9 @@ def clear_splash():
112121
113122
114123def touch_in_button (t , b ):
115- return (b ['left' ] >= t [0 ] >= b ['right' ]) and (b ['top' ] <= t [1 ] <= b ['bottom' ])
124+ in_horizontal = b ['left' ] <= t [0 ] <= b ['right' ]
125+ in_vertical = b ['top' ] <= t [1 ] <= b ['bottom' ]
126+ return in_horizontal and in_vertical
116127
117128
118129touched = False
@@ -165,9 +176,9 @@ def __init__(self):
165176 self .refresh_time = None
166177 self .update_time = None
167178 self .weather_refresh = None
168- text_area_configs = [dict (x = 88 , y = 30 , size = 5 , color = 0xFFFFFF , font = large_font ),
169- dict (x = 210 , y = 10 , size = 5 , color = 0xFF0000 , font = medium_font ),
170- dict (x = 88 , y = 65 , size = 6 , color = 0xFFFFFF , font = small_font )]
179+ text_area_configs = [dict (x = 88 , y = 170 , size = 5 , color = 0xFFFFFF , font = time_font ),
180+ dict (x = 210 , y = 50 , size = 5 , color = 0xFF0000 , font = alarm_font ),
181+ dict (x = 88 , y = 90 , size = 6 , color = 0xFFFFFF , font = temperature_font )]
171182 self .text_areas = create_text_areas (text_area_configs )
172183 self .weather_icon = displayio .Group (max_size = 1 )
173184 self .weather_icon .x = 88
@@ -180,8 +191,8 @@ def __init__(self):
180191 self .snooze_file = None
181192
182193 # each button has it's edges as well as the state to transition to when touched
183- self .buttons = [dict (left = 320 , top = 50 , right = 240 , bottom = 120 , next_state = 'settings' ),
184- dict (left = 320 , top = 155 , right = 240 , bottom = 220 , next_state = 'mugsy' )]
194+ self .buttons = [dict (left = 0 , top = 50 , right = 80 , bottom = 120 , next_state = 'settings' ),
195+ dict (left = 0 , top = 155 , right = 80 , bottom = 220 , next_state = 'mugsy' )]
185196
186197
187198 @property
@@ -218,15 +229,16 @@ def tick(self, now):
218229 return
219230
220231 # check light level and adjust background & backlight
221- self .adjust_backlight_based_on_light ()
232+ # self.adjust_backlight_based_on_light()
222233
223234 # only query the online time once per hour (and on first run)
224235 if (not self .refresh_time ) or ((now - self .refresh_time ) > 3600 ):
225236 try :
226237 pyportal .get_local_time (location = secrets ['timezone' ])
227238 self .refresh_time = now
228239 except RuntimeError as e :
229- print ('Some error occured, retrying! -' , e )
240+ self .refresh_time = now - 3000 # delay 10 minutes before retrying
241+ logger .error ('Some error occured, retrying! - %s' , str (e ))
230242
231243 # only query the weather every 10 minutes (and on first run)
232244 if (not self .weather_refresh ) or (now - self .weather_refresh ) > 600 :
@@ -246,9 +258,15 @@ def tick(self, now):
246258 self .icon_file .close ()
247259 self .icon_file = open (filename , "rb" )
248260 icon = displayio .OnDiskBitmap (self .icon_file )
249- icon_sprite = displayio .TileGrid (icon ,
250- pixel_shader = displayio .ColorConverter (),
251- position = (0 , 0 ))
261+ try :
262+ icon_sprite = displayio .TileGrid (icon ,
263+ pixel_shader = displayio .ColorConverter (),
264+ x = 0 , y = 0 )
265+ except TypeError :
266+ icon_sprite = displayio .TileGrid (icon ,
267+ pixel_shader = displayio .ColorConverter (),
268+ position = (0 , 0 ))
269+
252270
253271 self .weather_icon .append (icon_sprite )
254272
@@ -263,13 +281,15 @@ def tick(self, now):
263281 board .DISPLAY .wait_for_frame ()
264282
265283 except RuntimeError as e :
266- print ("Some error occured, retrying! -" , e )
284+ self .weather_refresh = now - 540 # delay a minute before retrying
285+ logger .error ("Some error occured, retrying! - %s" , str (e ))
267286
268287 if (not update_time ) or ((now - update_time ) > 30 ):
269288 # Update the time
270289 update_time = now
271290 the_time = time .localtime ()
272- self .text_areas [0 ].text = '%02d:%02d' % (the_time .tm_hour ,the_time .tm_min )
291+ time_string = '%02d:%02d' % (the_time .tm_hour ,the_time .tm_min )
292+ self .text_areas [0 ].text = time_string
273293 board .DISPLAY .refresh_soon ()
274294 board .DISPLAY .wait_for_frame ()
275295
@@ -285,6 +305,8 @@ def tick(self, now):
285305
286306
287307 def touch (self , t , touched ):
308+ if t :
309+ logger .debug ('touched: %d, %d' , t [0 ], t [1 ])
288310 if t and not touched : # only process the initial touch
289311 for button_index in range (len (self .buttons )):
290312 b = self .buttons [button_index ]
@@ -304,9 +326,14 @@ def enter(self):
304326 self .snooze_file .close ()
305327 self .snooze_file = open ('/icons/zzz.bmp' , "rb" )
306328 icon = displayio .OnDiskBitmap (self .snooze_file )
307- icon_sprite = displayio .TileGrid (icon ,
308- pixel_shader = displayio .ColorConverter (),
309- position = (0 , 0 ))
329+ try :
330+ icon_sprite = displayio .TileGrid (icon ,
331+ pixel_shader = displayio .ColorConverter (),
332+ x = 0 , y = 0 )
333+ except TypeError :
334+ icon_sprite = displayio .TileGrid (icon ,
335+ pixel_shader = displayio .ColorConverter (),
336+ position = (0 , 0 ))
310337 self .snooze_icon .append (icon_sprite )
311338
312339 pyportal .splash .append (self .snooze_icon )
@@ -318,11 +345,6 @@ def enter(self):
318345 board .DISPLAY .wait_for_frame ()
319346
320347
321- def exit (self ):
322- super ().exit ()
323- for _ in range (len (self .snooze_icon )):
324- self .snooze_icon .pop ()
325-
326348
327349class Mugsy_State (Time_State ):
328350 """This state tells Mugsey 'Make me a coffee' """
@@ -340,6 +362,15 @@ def tick(self, now):
340362 # Once the job is done, go back to the main screen
341363 change_to_state ('time' )
342364
365+ def enter (self ):
366+ global low_light
367+ low_light = False
368+ pyportal .set_backlight (1.00 )
369+ pyportal .set_background (mugsy_background )
370+ board .DISPLAY .refresh_soon ()
371+ board .DISPLAY .wait_for_frame ()
372+
373+
343374
344375class Alarm_State (State ):
345376 """This state shows/sounds the alarm.
@@ -403,14 +434,14 @@ def __init__(self):
403434 super ().__init__ ()
404435 self .previous_touch = None
405436 self .background = 'settings_background.bmp'
406- text_area_configs = [dict (x = 88 , y = - 10 , size = 5 , color = 0xFFFFFF , font = large_font )]
437+ text_area_configs = [dict (x = 88 , y = 120 , size = 5 , color = 0xFFFFFF , font = time_font )]
407438
408439 self .text_areas = create_text_areas (text_area_configs )
409- self .buttons = [dict (left = 320 , top = 30 , right = 240 , bottom = 93 ), # on
410- dict (left = 320 , top = 98 , right = 240 , bottom = 152 ), # return
411- dict (left = 320 , top = 155 , right = 240 , bottom = 220 ), # off
412- dict (left = 240 , top = 0 , right = 120 , bottom = 240 ), # hours
413- dict (left = 120 , top = 0 , right = 0 , bottom = 240 )] # minutes
440+ self .buttons = [dict (left = 0 , top = 30 , right = 80 , bottom = 93 ), # on
441+ dict (left = 0 , top = 98 , right = 80 , bottom = 152 ), # return
442+ dict (left = 0 , top = 155 , right = 80 , bottom = 220 ), # off
443+ dict (left = 100 , top = 0 , right = 200 , bottom = 240 ), # hours
444+ dict (left = 220 , top = 0 , right = 320 , bottom = 240 )] # minutes
414445
415446
416447 @property
@@ -421,28 +452,34 @@ def name(self):
421452 def touch (self , t , touched ):
422453 global alarm_hour , alarm_minute , alarm_enabled
423454 if t :
455+ logger .debug ('touched: %d, %d' , t [0 ], t [1 ])
424456 if touch_in_button (t , self .buttons [0 ]): # on
457+ logger .debug ('ON touched' )
425458 alarm_enabled = True
426459 self .text_areas [0 ].text = '%02d:%02d' % (alarm_hour , alarm_minute )
427460 elif touch_in_button (t , self .buttons [1 ]): # return
461+ logger .debug ('RETURN touched' )
428462 change_to_state ('time' )
429463 elif touch_in_button (t , self .buttons [2 ]): # off
464+ logger .debug ('OFF touched' )
430465 alarm_enabled = False
431466 self .text_areas [0 ].text = ' '
432467 elif alarm_enabled :
433468 if not self .previous_touch :
434469 self .previous_touch = t
435470 else :
436471 if touch_in_button (t , self .buttons [3 ]): # HOURS
437- if t [1 ] < (self .previous_touch [1 ]): # moving up
472+ logger .debug ('HOURS touched' )
473+ if t [1 ] < (self .previous_touch [1 ] - 5 ): # moving up
438474 alarm_hour = (alarm_hour + 1 ) % 24
439- elif t [1 ] > (self .previous_touch [1 ]): # moving down
475+ elif t [1 ] > (self .previous_touch [1 ] + 5 ): # moving down
440476 alarm_hour = (alarm_hour - 1 ) % 24
441477 self .text_areas [0 ].text = '%02d:%02d' % (alarm_hour , alarm_minute )
442478 elif touch_in_button (t , self .buttons [4 ]): # MINUTES
443- if t [1 ] < (self .previous_touch [1 ]): # moving up
479+ logger .debug ('MINUTES touched' )
480+ if t [1 ] < (self .previous_touch [1 ] - 5 ): # moving up
444481 alarm_minute = (alarm_minute + 1 ) % 60
445- elif t [1 ] > (self .previous_touch [1 ]): # moving down
482+ elif t [1 ] > (self .previous_touch [1 ] + 5 ): # moving down
446483 alarm_minute = (alarm_minute - 1 ) % 60
447484 self .text_areas [0 ].text = '%02d:%02d' % (alarm_hour , alarm_minute )
448485 self .previous_touch = t
@@ -477,8 +514,10 @@ def enter(self):
477514def change_to_state (state_name ):
478515 global current_state
479516 if current_state :
517+ logger .debug ('Exiting %s' , current_state .name )
480518 current_state .exit ()
481519 current_state = states [state_name ]
520+ logger .debug ('Entering %s' , current_state .name )
482521 current_state .enter ()
483522
484523####################
0 commit comments