22
22
23
23
supervisor .runtime .autoreload = False
24
24
25
- SETTINGSFILE = "settings.json" # The file in which the settings are saved
26
- MACROFILE = "macros.json" # The file in which the macros are saved
25
+ # The file in which the settings are saved
26
+ SETTINGSFILE = "settings.json"
27
+ # The file in which the macros are saved
28
+ MACROFILE = "macros.json"
27
29
28
30
SETTINGS = {
29
- "sleeptime" : 2 , # Time in seconds until the display turns off
30
- "keyboardlayout" : "us" , # Supported keyboard layouts: br, cz, da, de, es, fr, hu, it, po, sw, tr, uk, us
31
- "useunicodefont" : False , # Use a unicode bitmap font, which will increas the initial load time!
32
- "fliprotation" : False , # Flips the rotation of the device by 180 degrees
33
- "brightness" : 0.1 # Set the LCD and LED Brightness
31
+ # Time in seconds until the display turns off
32
+ "sleeptime" : 2 ,
33
+ # Supported keyboard layouts: br, cz, da, de, es, fr, hu, it, po, sw, tr, uk, us
34
+ "keyboardlayout" : "us" ,
35
+ # Use a unicode bitmap font, which will increas the initial load time!
36
+ "useunicodefont" : False ,
37
+ # Flips the rotation of the device by 180 degrees
38
+ "fliprotation" : False ,
39
+ # Set the LCD and LED Brightness
40
+ "brightness" : 0.1
34
41
}
35
42
36
43
try :
85
92
86
93
class MacroApp ():
87
94
""" Main Class """
95
+
88
96
def __init__ (self ) -> None :
89
- self .macropad = MacroPad (layout_class = KeyboardLayout , rotation = 180 if SETTINGS ["fliprotation" ] else 0 )
90
-
97
+ self .macropad = MacroPad (
98
+ layout_class = KeyboardLayout ,
99
+ rotation = 180 if SETTINGS ["fliprotation" ] else 0
100
+ )
101
+
91
102
self .macropad .display .auto_refresh = False
92
103
self .macropad .display .brightness = SETTINGS ["brightness" ]
93
104
self .macropad .display .root_group = displayio .Group ()
@@ -97,6 +108,7 @@ def __init__(self) -> None:
97
108
98
109
self .readonly = storage .getmount ('/' ).readonly
99
110
self .serial_data = usb_cdc .data
111
+ self .serial_buffer = ""
100
112
self .serial_last_state = False
101
113
102
114
self .macroStack = [self ._init_macros ()]
@@ -127,16 +139,16 @@ def _init_macros(self) -> list[dict]:
127
139
macros = json .load (f )
128
140
if isinstance (macros , list ):
129
141
return {
130
- "label" : rootLabel ,
142
+ "label" : rootLabel ,
131
143
"content" : macros ,
132
144
}
133
145
return macros
134
146
except OSError :
135
147
return {
136
- "label" : rootLabel ,
148
+ "label" : rootLabel ,
137
149
"content" : [],
138
150
}
139
-
151
+
140
152
def _save_macros (self ) -> None :
141
153
""" store the macros in the macrofile
142
154
"""
@@ -148,17 +160,19 @@ def _save_macros(self) -> None:
148
160
149
161
def _init_group_label (self ) -> dict [str , Key ]:
150
162
group_label = Label (
151
- font = load_font ("/fonts/6x12.pcf" ) if SETTINGS ["useunicodefont" ] else terminalio .FONT ,
152
- text = "" ,
153
- padding_top = 0 ,
154
- padding_bottom = 0 ,
155
- padding_left = 0 ,
156
- padding_right = 0 ,
157
- color = 0xFFFFFF ,
158
- anchored_position = (self .macropad .display .width // 2 , self .macropad .display .height - 10 ),
159
- anchor_point = (0.5 , 0.0 )
160
- )
161
-
163
+ font = load_font (
164
+ "/fonts/6x12.pcf" ) if SETTINGS ["useunicodefont" ] else terminalio .FONT ,
165
+ text = "" ,
166
+ padding_top = 0 ,
167
+ padding_bottom = 0 ,
168
+ padding_left = 0 ,
169
+ padding_right = 0 ,
170
+ color = 0xFFFFFF ,
171
+ anchored_position = (self .macropad .display .width // 2 ,
172
+ self .macropad .display .height - 10 ),
173
+ anchor_point = (0.5 , 0.0 )
174
+ )
175
+
162
176
self .macropad .display .root_group .append (group_label )
163
177
164
178
return group_label
@@ -173,19 +187,20 @@ def _init_keys(self) -> list[Key]:
173
187
174
188
for i in range (self .macropad .keys .key_count ):
175
189
label = Label (
176
- font = load_font ("/fonts/6x12.pcf" ) if SETTINGS ["useunicodefont" ] else terminalio .FONT ,
177
- text = "" ,
178
- padding_top = 0 ,
179
- padding_bottom = 1 ,
180
- padding_left = 4 ,
181
- padding_right = 4 ,
182
- color = 0xFFFFFF ,
183
- anchored_position = (
184
- (self .macropad .display .width - 2 ) / 2 * (i % 3 ) + 1 ,
185
- self .macropad .display .height / 5 * (i // 3 ) + 2 ),
186
- anchor_point = ((i % 3 ) / 2 , 0.0 )
187
- )
188
-
190
+ font = load_font (
191
+ "/fonts/6x12.pcf" ) if SETTINGS ["useunicodefont" ] else terminalio .FONT ,
192
+ text = "" ,
193
+ padding_top = 0 ,
194
+ padding_bottom = 1 ,
195
+ padding_left = 4 ,
196
+ padding_right = 4 ,
197
+ color = 0xFFFFFF ,
198
+ anchored_position = (
199
+ (self .macropad .display .width - 2 ) / 2 * (i % 3 ) + 1 ,
200
+ self .macropad .display .height / 5 * (i // 3 ) + 2 ),
201
+ anchor_point = ((i % 3 ) / 2 , 0.0 )
202
+ )
203
+
189
204
keys .append (Key (self .macropad , i , label ))
190
205
self .macropad .display .root_group .append (label )
191
206
@@ -198,7 +213,7 @@ def _init_group(self) -> None:
198
213
199
214
self ._update_tab ()
200
215
201
- def run_macro (self , item :dict , * args ) -> None :
216
+ def run_macro (self , item : dict , * args ) -> None :
202
217
""" run the macro, can be:
203
218
Float (e.g. 0.25): delay in seconds
204
219
String (e.g. "Foo"): corresponding keys pressed & released
@@ -225,20 +240,23 @@ def run_macro(self, item:dict, *args) -> None:
225
240
key_name = key ['kc' ][1 :] if key ['kc' ][:1 ] == "-" else key ['kc' ]
226
241
key_code = getattr (Keycode , key_name .upper (), None )
227
242
if key_code :
228
- if key ['kc' ][:1 ] != "-" :
243
+ if key ['kc' ][:1 ] != "-" :
229
244
self .macropad .keyboard .press (key_code )
230
245
else :
231
246
self .macropad .keyboard .release (key_code )
232
247
if 'ccc' in key :
233
- control_code = getattr (ConsumerControlCode , key ['ccc' ].upper (), None )
248
+ control_code = getattr (
249
+ ConsumerControlCode , key ['ccc' ].upper (), None )
234
250
if control_code :
235
251
self .macropad .consumer_control .press (control_code )
236
252
self .macropad .consumer_control .release ()
237
253
if 'tone' in key :
238
- self .macropad .play_tone (key ['tone' ]['frequency' ], key ['tone' ]['duration' ])
254
+ self .macropad .play_tone (
255
+ key ['tone' ]['frequency' ], key ['tone' ]['duration' ])
239
256
if 'mse' in key :
240
257
if "b" in key ["mse" ]:
241
- btn = getattr (Mouse , f"{ key ['mse' ]['b' ].upper ()} _BUTTON" , None )
258
+ btn = getattr (
259
+ Mouse , f"{ key ['mse' ]['b' ].upper ()} _BUTTON" , None )
242
260
if btn :
243
261
self .macropad .mouse .click (btn )
244
262
self .macropad .mouse .move (
@@ -249,11 +267,11 @@ def run_macro(self, item:dict, *args) -> None:
249
267
method = getattr (System , key ['sys' ], None )
250
268
if method :
251
269
method (self )
252
-
270
+
253
271
self .macropad .keyboard .release_all ()
254
272
self .macropad .mouse .release_all ()
255
273
256
- def open_group (self , item :dict , * args ) -> None :
274
+ def open_group (self , item : dict , * args ) -> None :
257
275
""" open a group
258
276
259
277
Args:
@@ -284,16 +302,17 @@ def _update_tab(self) -> None:
284
302
285
303
for i , item in enumerate (self .macroStack [- 1 ]["content" ][:self .macropad .keys .key_count ]):
286
304
self .keys [i ].type = item ["type" ]
287
- self .keys [i ].label = "" if item ["type" ] == "blank" else item ["label" ]
288
- self .keys [i ].color = (0 , 0 , 0 ) if item ["type" ] == "blank" else item ["color" ]
305
+ self .keys [i ].label = "" if item ["type" ] == "blank" else item ["label" ]
306
+ self .keys [i ].color = (
307
+ 0 , 0 , 0 ) if item ["type" ] == "blank" else item ["color" ]
289
308
self .keys [i ].set_func (self ._get_key_func (item ["type" ]), item )
290
309
291
310
self .group_label .text = self .macroStack [- 1 ]["label" ]
292
311
293
312
for key in self .keys :
294
313
key .update_colors ()
295
314
296
- def _get_key_func (self , type :str ) -> function :
315
+ def _get_key_func (self , type : str ) -> function :
297
316
""" get the specific function for the type
298
317
299
318
Args:
@@ -313,12 +332,14 @@ def _update_encoder_macros(self) -> None:
313
332
""" update the rotary encoder macros defined for opened group
314
333
"""
315
334
self .encoder .update_encoder_macros (
316
- on_switch = self .macroStack [- 1 ].get ("encoder" , {}).get ("switch" ),
317
- on_increased = self .macroStack [- 1 ].get ("encoder" , {}).get ("increased" ),
318
- on_decreased = self .macroStack [- 1 ].get ("encoder" , {}).get ("decreased" )
335
+ on_switch = self .macroStack [- 1 ].get ("encoder" , {}).get ("switch" ),
336
+ on_increased = self .macroStack [- 1 ].get ("encoder" ,
337
+ {}).get ("increased" ),
338
+ on_decreased = self .macroStack [- 1 ].get ("encoder" ,
339
+ {}).get ("decreased" )
319
340
)
320
341
321
- def _handle_serial_data (self , payload :str ) -> dict :
342
+ def _handle_serial_data (self , payload : str ) -> dict :
322
343
""" handle the data comming over the serial connection
323
344
324
345
Args:
@@ -341,12 +362,12 @@ def _handle_serial_data(self, payload:str) -> dict:
341
362
response ['ACK' ] = 'settings'
342
363
response ['CONTENT' ] = SETTINGS
343
364
return response
344
-
365
+
345
366
elif command == 'set_settings' :
346
367
if 'content' not in payload .keys ():
347
368
response ['ERR' ] = 'No content: %s' % payload
348
369
return response
349
-
370
+
350
371
content = payload ['content' ]
351
372
352
373
if self ._save_settings (content ):
@@ -360,54 +381,54 @@ def _handle_serial_data(self, payload:str) -> dict:
360
381
response ['ACK' ] = 'macros'
361
382
response ['CONTENT' ] = self .macroStack [0 ]
362
383
return response
363
-
384
+
364
385
elif command == 'set_macros' :
365
386
if 'content' not in payload .keys ():
366
387
response ['ERR' ] = 'No content: %s' % payload
367
388
return response
368
-
389
+
369
390
content = payload ['content' ]
370
391
self .macroStack = [content ]
371
392
self ._display_on ()
372
393
self ._init_group ()
373
394
374
395
response ['ACK' ] = 'Macros received'
375
396
return response
376
-
397
+
377
398
elif command == 'save_macros' :
378
399
if self ._save_macros ():
379
400
response ['ACK' ] = 'Macros stored'
380
401
else :
381
402
response ['ERR' ] = 'Cannot store macros because USB storage is enabled'
382
403
383
404
return response
384
-
405
+
385
406
elif command == 'enable_usb' :
386
407
System .enable_usb ()
387
408
388
409
response ['ACK' ] = 'Enable USB'
389
410
return response
390
-
411
+
391
412
elif command == 'soft_reset' :
392
413
System .soft_reset ()
393
414
394
415
response ['ACK' ] = 'Softreset'
395
416
return response
396
-
417
+
397
418
elif command == 'hard_reset' :
398
419
System .hard_reset ()
399
420
400
421
response ['ACK' ] = 'Hardreset'
401
422
return response
402
-
423
+
403
424
else :
404
425
response ['ERR' ] = 'Unkown command: %s' % command
405
426
return response
406
427
except Exception as e :
407
428
response ['ERR' ] = str (e )
408
429
return response
409
430
410
- def _send_serial_data (self , payload :dict ) -> None :
431
+ def _send_serial_data (self , payload : dict ) -> None :
411
432
""" prepare and send data over serial connection
412
433
413
434
Args:
@@ -437,12 +458,20 @@ def start(self) -> None:
437
458
if self .serial_last_state != self .serial_data .connected :
438
459
self .serial_last_state = self .serial_data .connected
439
460
if self .serial_data .connected :
440
- self ._send_serial_data ({'ACK' : 'usbenabled' , 'CONTENT' : self .readonly })
461
+ self ._send_serial_data (
462
+ {'ACK' : 'usbenabled' , 'CONTENT' : self .readonly })
441
463
442
464
if self .serial_data .connected :
443
465
if self .serial_data .in_waiting > 0 :
444
- data = self .serial_data .readline ()
445
- self ._send_serial_data (self ._handle_serial_data (data .decode ("utf-8" ).strip ()))
466
+ while self .serial_data .in_waiting :
467
+ chunk = self .serial_data .read (
468
+ self .serial_data .in_waiting )
469
+ self .serial_buffer += chunk .decode ("utf-8" )
470
+
471
+ if self .serial_buffer .endswith ("\n " ):
472
+ self ._send_serial_data (
473
+ self ._handle_serial_data (self .serial_buffer [:- 1 ]))
474
+ self .serial_buffer = ""
446
475
447
476
# get key events, so no inputs will be stored during connection
448
477
# self.macropad.keys.events.get()
@@ -451,7 +480,8 @@ def start(self) -> None:
451
480
key_event = self .macropad .keys .events .get ()
452
481
if key_event :
453
482
self ._display_on ()
454
- self .keys [key_event .key_number ].pressed = True if key_event .pressed and not any ([key .pressed for key in self .keys ]) else False
483
+ self .keys [key_event .key_number ].pressed = True if key_event .pressed and not any (
484
+ [key .pressed for key in self .keys ]) else False
455
485
456
486
if self .encoder .switch and self .encoder .on_switch :
457
487
self ._display_on ()
@@ -469,5 +499,6 @@ def start(self) -> None:
469
499
"content" : self .encoder .on_decreased
470
500
})
471
501
502
+
472
503
app = MacroApp ()
473
- app .start ()
504
+ app .start ()
0 commit comments