2626
2727class StatusLight :
2828 """Provides a structured entry point for the Status-Light application"""
29+ # Instance Logger
30+ logger : logging .Logger = logging .getLogger ('status-light' )
31+
2932 # Instance Properties
3033 local_env = env .Environment ()
3134 current_status : enum .Status = enum .Status .UNKNOWN
@@ -62,27 +65,30 @@ def init(self):
6265 self .local_env .get_log_level ()]:
6366
6467 # We failed to gather some environment variables
65- logger .error ('Failed to find all environment variables!' )
68+ self . logger .error ('Failed to find all environment variables!' )
6669 sys .exit (1 )
6770
6871 # 23 - Make logging level configurable
69- logger .info ('Setting log level to %s' , self .local_env .log_level .name )
70- logger .setLevel (self .local_env .log_level .value )
72+ self .logger .info ('Setting log level to %s' , self .local_env .log_level .name )
73+ # Reset the root logger config to our epxected logging level
74+ logging .basicConfig (format = '%(asctime)s %(name)s.%(funcName)s %(levelname)s: %(message)s' ,
75+ datefmt = '[%Y-%m-%d %H:%M:%S]' , level = self .local_env .log_level .value , force = True )
76+ self .logger .setLevel (self .local_env .log_level .value )
7177
7278 # Depending on the selected sources, get the environment
7379 if enum .StatusSource .WEBEX in self .local_env .selected_sources :
7480 if self .local_env .get_webex ():
75- logger .info ('Requested Webex' )
81+ self . logger .info ('Requested Webex' )
7682 self .webex_api .bot_id = self .local_env .webex_bot_id
7783 self .webex_api .person_id = self .local_env .webex_person_id
7884 else :
79- logger .error (
85+ self . logger .error (
8086 'Requested Webex, but could not find all environment variables!' )
8187 sys .exit (1 )
8288
8389 if enum .StatusSource .SLACK in self .local_env .selected_sources :
8490 if self .local_env .get_slack ():
85- logger .info ('Requested Slack' )
91+ self . logger .info ('Requested Slack' )
8692 self .slack_api .user_id = self .local_env .slack_user_id
8793 self .slack_api .bot_token = self .local_env .slack_bot_token
8894 # 66 - Support Slack custom statuses
@@ -97,44 +103,44 @@ def init(self):
97103 self .slack_api .custom_scheduled_status_map = self .local_env .scheduled_status [
98104 0 ]
99105 else :
100- logger .error (
106+ self . logger .error (
101107 'Requested Slack, but could not find all environment variables!' )
102108 sys .exit (1 )
103109
104110 if enum .StatusSource .OFFICE365 in self .local_env .selected_sources :
105111 if self .local_env .get_office ():
106- logger .info ('Requested Office 365' )
112+ self . logger .info ('Requested Office 365' )
107113 self .office_api .appID = self .local_env .office_app_id
108114 self .office_api .appSecret = self .local_env .office_app_secret
109115 self .office_api .tokenStore = self .local_env .office_token_store
110116 # 81 - Make calendar lookahead configurable
111117 self .office_api .lookahead = self .local_env .calendar_lookahead
112118 self .office_api .authenticate ()
113119 else :
114- logger .error (
120+ self . logger .error (
115121 'Requested Office 365, but could not find all environment variables!' )
116122 sys .exit (1 )
117123
118124 # 47 - Add Google support
119125 if enum .StatusSource .GOOGLE in self .local_env .selected_sources :
120126 if self .local_env .get_google ():
121- logger .info ('Requested Google' )
127+ self . logger .info ('Requested Google' )
122128 self .google_api .credentialStore = self .local_env .google_credential_store
123129 self .google_api .tokenStore = self .local_env .google_token_store
124130 # 81 - Make calendar lookahead configurable
125131 self .google_api .lookahead = self .local_env .calendar_lookahead
126132 else :
127- logger .error (
133+ self . logger .error (
128134 'Requested Google, but could not find all environment variables!' )
129135 sys .exit (1 )
130136
131137 # Tuya
132138 self .light .device = self .local_env .tuya_device
133- logger .debug ('Retrieved TUYA_DEVICE variable: %s' , self .light .device )
139+ self . logger .debug ('Retrieved TUYA_DEVICE variable: %s' , self .light .device )
134140 tuya_status = self .light .get_status ()
135- logger .debug ('Found initial Tuya status: %s' , tuya_status )
141+ self . logger .debug ('Found initial Tuya status: %s' , tuya_status )
136142 if not tuya_status :
137- logger .error (
143+ self . logger .error (
138144 'Could not connect to Tuya device!' )
139145 sys .exit (1 )
140146
@@ -151,7 +157,7 @@ def run(self):
151157 self .local_env .active_hours_start ,
152158 self .local_env .active_hours_end ):
153159
154- logger .debug ('Within Active Hours, polling' )
160+ self . logger .debug ('Within Active Hours, polling' )
155161
156162 # Reset the "outside of active hours" handler
157163 already_handled_inactive_hours = False
@@ -193,7 +199,7 @@ def run(self):
193199 google_status .name .lower ())
194200
195201 # 74: Log enums as names, not values
196- logger .debug (logger_string .lstrip ().rstrip (' |' ))
202+ self . logger .debug (logger_string .lstrip ().rstrip (' |' ))
197203
198204 # TODO: Now that we have more than one calendar-based status source,
199205 # build a real precedence module for these
@@ -204,7 +210,7 @@ def run(self):
204210 if (webex_status == enum .Status .UNKNOWN or
205211 webex_status in self .local_env .off_status ):
206212 # 74: Log enums as names, not values
207- logger .debug ('Using slack_status: %s' ,
213+ self . logger .debug ('Using slack_status: %s' ,
208214 slack_status .name .lower ())
209215 # Fall through to Slack
210216 self .current_status = slack_status
@@ -214,15 +220,15 @@ def run(self):
214220 and (office_status not in self .local_env .off_status
215221 or google_status not in self .local_env .off_status ):
216222
217- logger .debug ('Using calendar-based status' )
223+ self . logger .debug ('Using calendar-based status' )
218224 # Office should take precedence over Google for now
219225 # 74: Log enums as names, not values
220226 if office_status != enum .Status .UNKNOWN :
221- logger .debug ('Using office_status: %s' ,
227+ self . logger .debug ('Using office_status: %s' ,
222228 office_status .name .lower ())
223229 self .current_status = office_status
224230 else :
225- logger .debug ('Using google_status: %s' ,
231+ self . logger .debug ('Using google_status: %s' ,
226232 google_status .name .lower ())
227233 self .current_status = google_status
228234
@@ -232,26 +238,26 @@ def run(self):
232238 status_changed = True
233239
234240 if status_changed :
235- logger .info ('Found new status: %s' ,
241+ self . logger .info ('Found new status: %s' ,
236242 self .current_status .name .lower ())
237243
238244 if not last_transition_result :
239- logger .warning (
245+ self . logger .warning (
240246 'Last attempt to set status failed. Retrying.' )
241247
242248 # If status changed this loop
243249 # 40: or the last transition failed,
244250 if status_changed or not last_transition_result :
245251 # 74: Log enums as names, not values
246- logger .info ('Transitioning to %s' ,
252+ self . logger .info ('Transitioning to %s' ,
247253 self .current_status .name .lower ())
248254 last_transition_result = self ._transition_status ()
249255
250256 else :
251- logger .debug ('Outside Active Hours, pausing' )
257+ self . logger .debug ('Outside Active Hours, pausing' )
252258
253259 if not already_handled_inactive_hours :
254- logger .info (
260+ self . logger .info (
255261 'Outside of active hours, transitioning to off' )
256262 last_transition_result = self .light .off ()
257263 self .last_status = enum .Status .UNKNOWN
@@ -264,14 +270,14 @@ def run(self):
264270 # Sleep for a few seconds
265271 time .sleep (self .local_env .sleep_seconds )
266272 except (SystemExit , KeyboardInterrupt ) as ex :
267- logger .info ('%s received; shutting down...' ,
273+ self . logger .info ('%s received; shutting down...' ,
268274 ex .__class__ .__name__ )
269275 self .should_continue = False
270276 except Exception as ex : # pylint: disable=broad-except
271- logger .warning ('Exception during main loop: %s' , ex )
272- logger .exception (ex )
277+ self . logger .warning ('Exception during main loop: %s' , ex )
278+ self . logger .exception (ex )
273279
274- logger .debug ('Turning light off' )
280+ self . logger .debug ('Turning light off' )
275281 self .light .off ()
276282
277283 def _transition_status (self ) -> bool :
@@ -302,7 +308,7 @@ def _transition_status(self) -> bool:
302308 # just turn the light off and warn about it
303309 # 74: Log enums as names, not values
304310 else :
305- logger .warning ('Called with an invalid status: %s' ,
311+ self . logger .warning ('Called with an invalid status: %s' ,
306312 self .current_status .name .lower ())
307313 return_value = self .light .off ()
308314
@@ -316,7 +322,7 @@ def _transition_status(self) -> bool:
316322# Default to INFO level until we load the environment
317323logging .basicConfig (format = '%(asctime)s %(name)s.%(funcName)s %(levelname)s: %(message)s' ,
318324 datefmt = '[%Y-%m-%d %H:%M:%S]' , level = logging .INFO )
319- logger : logging .Logger = logging .getLogger ('status-light' )
325+ global_logger : logging .Logger = logging .getLogger ('status-light' )
320326
321327
322328def receive_signal (signal_number , frame ): # pylint: disable=unused-argument
@@ -331,9 +337,9 @@ def receive_signal(signal_number, frame): # pylint: disable=unused-argument
331337 try :
332338 signal_name = signal .Signals (signal_number ).name
333339 except ValueError as value_ex :
334- logger .warning (
340+ global_logger .warning (
335341 'Exception encountered converting %s to signal.Signals: %s' , signal_number , value_ex )
336- logger .warning ('Signal received: %s' , signal_name )
342+ global_logger .warning ('Signal received: %s' , signal_name )
337343 status_light .should_continue = False
338344
339345
@@ -342,10 +348,10 @@ def receive_signal(signal_number, frame): # pylint: disable=unused-argument
342348
343349def main ():
344350 """Provides the entry point for the application"""
345- logger .info ('Startup' )
351+ global_logger .info ('Startup' )
346352 status_light .init ()
347353 status_light .run ()
348- logger .info ('Shutdown' )
354+ global_logger .info ('Shutdown' )
349355
350356
351357if __name__ == '__main__' :
0 commit comments