Skip to content

Commit ad19a70

Browse files
authored
Refactored code.py
Refactored code rather than blanket-disables
1 parent d7bad0a commit ad19a70

File tree

1 file changed

+55
-51
lines changed

1 file changed

+55
-51
lines changed

PyPortal_Art_Display/code.py

Lines changed: 55 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
# SPDX-FileCopyrightText: 2025 Pedro for Adafruit Industries
1+
# SPDX-FileCopyrightText: 2025 Pedro Ruiz for Adafruit Industries
22
#
33
# SPDX-License-Identifier: MIT
44

55
'''PyPortal Art Display - Multi-feed with mode switching'''
66

7-
# pylint: disable=global-statement,invalid-name,too-many-lines
8-
# pylint: disable=redefined-outer-name
9-
# pylint: disable=no-member,protected-access,too-many-return-statements
7+
# pylint: disable=too-many-lines
108

119
from os import getenv
1210
import os
@@ -91,7 +89,7 @@
9189
# Skip button on D3 (pull-up, active low)
9290
# Set to False if no button is wired to D3
9391
USE_BUTTON = False
94-
skip_btn = None
92+
skip_btn = None # pylint: disable=invalid-name
9593
if USE_BUTTON:
9694
skip_btn = digitalio.DigitalInOut(board.D3)
9795
skip_btn.direction = digitalio.Direction.INPUT
@@ -100,7 +98,7 @@
10098
# --- LIS3DH Accelerometer (STEMMA I2C) ---
10199
# Set to False if no accelerometer is connected
102100
USE_ACCEL = True
103-
lis3dh = None
101+
lis3dh = None # pylint: disable=invalid-name
104102

105103
# Tilt detection: LIS3DH on back of diamond-oriented display.
106104
# Resting position reads ~-10 to -16 degrees on Z-axis.
@@ -110,7 +108,7 @@
110108
TILT_THRESHOLD_LEFT = 6 # +/- tolerance (range: 0 to -3)
111109
TILT_THRESHOLD_RIGHT = 30 # +/- tolerance (range: -50 to -70)
112110
TILT_HOLD_TIME = 0.5 # seconds to hold at target before skip
113-
tilt_start = 0.0 # when tilt was first detected
111+
tilt_start = 0.0 # pylint: disable=invalid-name
114112

115113
# Shake detection: triggers skip on quick shake gesture
116114
SHAKE_THRESHOLD = 20.0 # m/s^2 total accel (1g = 9.8)
@@ -126,7 +124,7 @@
126124
print("LIS3DH accelerometer found!")
127125
except (ValueError, RuntimeError) as accel_err:
128126
print("No LIS3DH found:", accel_err)
129-
lis3dh = None
127+
lis3dh = None # pylint: disable=invalid-name
130128
USE_ACCEL = False
131129

132130
# --- Audio confirmation chirp ---
@@ -140,8 +138,8 @@ def play_beep():
140138
'''Play confirmation chirp via PyPortal's built-in audio.'''
141139
try:
142140
pyportal.play_file(BEEP_WAV)
143-
except (OSError, RuntimeError) as err:
144-
print("Beep error:", err)
141+
except (OSError, RuntimeError) as beep_err:
142+
print("Beep error:", beep_err)
145143

146144

147145
def get_tilt_angle():
@@ -248,15 +246,15 @@ def tap_aware_sleep(seconds):
248246
def count_taps():
249247
'''Count total taps within TAP_WINDOW after first tap.
250248
Returns tap count (1 if no extra taps detected).'''
251-
taps = 1
249+
tap_count = 1
252250
deadline = time.monotonic() + TAP_WINDOW
253251
while time.monotonic() < deadline:
254252
if check_tap():
255-
taps = taps + 1
253+
tap_count = tap_count + 1
256254
# Reset window on each tap
257255
deadline = time.monotonic() + TAP_WINDOW
258256
time.sleep(0.1)
259-
return taps
257+
return tap_count
260258

261259

262260
# ============================================
@@ -308,8 +306,8 @@ def wipe_transition(bg_path):
308306

309307
# Animate with ease-in (accelerates like dripping)
310308
for step in range(1, WIPE_STEPS + 1):
311-
t = step / WIPE_STEPS
312-
progress = t * t # ease-in: slow start, fast finish
309+
frac = step / WIPE_STEPS
310+
progress = frac * frac # ease-in: slow start, fast finish
313311
new_x = int(-WIDTH * WIPE_X_BIAS * (1.0 - progress))
314312
new_y = int(-HEIGHT * (1.0 - progress))
315313
new_tile.x = new_x
@@ -376,7 +374,7 @@ def url_encode(url_string):
376374
if not AIO_KEY:
377375
missing_keys.append("AIO_KEY")
378376
print("WARNING: ADAFRUIT_AIO_KEY missing")
379-
online_available = len(missing_keys) == 0
377+
online_available = len(missing_keys) == 0 # pylint: disable=invalid-name
380378

381379
BACKGROUND_FILE = "/background.bmp"
382380
if WIDTH > 320:
@@ -389,10 +387,9 @@ def url_encode(url_string):
389387
image_position=(0, 0),
390388
)
391389

392-
# Generate chirp WAV file on SD card at startup
393-
try:
394-
import struct
395-
# 16-bit mono PCM WAV at 16000 Hz
390+
def generate_chirp_wav():
391+
'''Generate chirp WAV file on SD card.'''
392+
import struct # pylint: disable=import-outside-toplevel
396393
sample_rate = 16000
397394
num_samples = int(sample_rate * BEEP_DURATION)
398395
data_size = num_samples * 2
@@ -410,14 +407,18 @@ def url_encode(url_string):
410407
# Phase accumulates based on instantaneous freq
411408
phase = 0.0
412409
for i in range(num_samples):
413-
t = i / num_samples # 0.0 to 1.0
410+
frac = i / num_samples # 0.0 to 1.0
414411
freq = (BEEP_FREQ_START
415-
+ (BEEP_FREQ_END - BEEP_FREQ_START) * t)
412+
+ (BEEP_FREQ_END - BEEP_FREQ_START) * frac)
416413
phase += 2 * math.pi * freq / sample_rate
417414
val = math.sin(phase)
418415
sample = int(val * 32000)
419416
wav_file.write(struct.pack("<h", sample))
420417
print("Chirp WAV generated!")
418+
419+
420+
try:
421+
generate_chirp_wav()
421422
except (OSError, RuntimeError) as wav_err:
422423
print("WAV generation error:", wav_err)
423424

@@ -454,8 +455,8 @@ def url_encode(url_string):
454455
# ============================================
455456
# MODE MANAGEMENT
456457
# ============================================
457-
feed_index = FEED_MODES.index(START_MODE)
458-
current_feed = FEED_MODES[feed_index]
458+
feed_index = FEED_MODES.index(START_MODE) # pylint: disable=invalid-name
459+
current_feed = FEED_MODES[feed_index] # pylint: disable=invalid-name
459460

460461
# Show startup warnings for missing hardware/settings
461462
startup_warnings = []
@@ -468,7 +469,7 @@ def url_encode(url_string):
468469

469470
# Force local mode if online features unavailable
470471
if not online_available:
471-
current_feed = "local"
472+
current_feed = "local" # pylint: disable=invalid-name
472473
feed_index = FEED_MODES.index("local")
473474
print("Online unavailable, forcing local mode")
474475

@@ -482,18 +483,18 @@ def url_encode(url_string):
482483

483484
# Prefetch state - alternate cache files to avoid
484485
# overwriting the currently displayed OnDiskBitmap
485-
prefetch_ready = False
486-
prefetch_title = ""
487-
prefetch_file = "/sd/cache2.bmp" # next prefetch target
488-
display_file = "/sd/cache.bmp" # currently shown file
486+
prefetch_ready = False # pylint: disable=invalid-name
487+
prefetch_title = "" # pylint: disable=invalid-name
488+
prefetch_file = "/sd/cache2.bmp" # pylint: disable=invalid-name
489+
display_file = "/sd/cache.bmp" # pylint: disable=invalid-name
489490

490491
# Cache list of local images
491492
local_images = []
492493

493494

494495
def load_local_images():
495496
'''Scan /sd/imgs/ for BMP files.'''
496-
global local_images
497+
global local_images # pylint: disable=global-statement
497498
local_images = []
498499
try:
499500
for fname in os.listdir(LOCAL_IMG_PATH):
@@ -660,8 +661,8 @@ def show_local_image():
660661
gc.collect()
661662
print("Local image displayed!")
662663
return True
663-
except (OSError, RuntimeError, MemoryError) as err:
664-
print("Local image error:", err)
664+
except (OSError, RuntimeError, MemoryError) as local_err:
665+
print("Local image error:", local_err)
665666
return False
666667

667668

@@ -687,14 +688,14 @@ def show_fallback_local():
687688
attempt, remaining))
688689
status_text.text = "Retry #%d..." % attempt
689690
try:
690-
result = show_online_image()
691-
if result is True:
691+
online_result = show_online_image()
692+
if online_result is True:
692693
print("Online image loaded!")
693694
return True
694-
if result == "mode":
695-
return result
696-
except (RuntimeError, Exception) as err: # pylint: disable=broad-except
697-
print("Retry error:", err)
695+
if online_result == "mode":
696+
return online_result
697+
except Exception as retry_err: # pylint: disable=broad-except
698+
print("Retry error:", retry_err)
698699
gc.collect()
699700
# Tap-aware wait between retries
700701
if tap_aware_sleep(3):
@@ -743,14 +744,15 @@ def show_online_image():
743744
try:
744745
json_data = json_data["data"][0]
745746
except (KeyError, IndexError, TypeError):
746-
print("No CMA data in response")
747-
return False
748-
749-
new_title = get_title(json_data)
750-
print("Title:", new_title)
751-
752-
# Validate image URL
753-
image_url = validate_image(json_data)
747+
json_data = None
748+
749+
# Validate data and image URL
750+
image_url = None
751+
new_title = ""
752+
if json_data:
753+
new_title = get_title(json_data)
754+
print("Title:", new_title)
755+
image_url = validate_image(json_data)
754756
json_data = None
755757
gc.collect()
756758
if not image_url:
@@ -898,7 +900,7 @@ def display_prefetched():
898900
Swaps cache file roles so next prefetch writes
899901
to the file that is no longer on screen.'''
900902
global prefetch_ready # pylint: disable=global-statement
901-
global display_file, prefetch_file
903+
global display_file, prefetch_file # pylint: disable=global-statement
902904
if not prefetch_ready:
903905
return False
904906
wipe_transition(prefetch_file)
@@ -926,7 +928,7 @@ def wait_for_input(duration):
926928
Returns "mode" for screen tap.
927929
Returns "timeout" if time expires.'''
928930
global tilt_start # pylint: disable=global-statement
929-
global shake_times
931+
global shake_times # pylint: disable=global-statement
930932
stamp = time.monotonic()
931933
tap_cooldown = stamp + 1.0 # ignore taps for 1s
932934
btn_was_pressed = False
@@ -967,13 +969,15 @@ def wait_for_input(duration):
967969
# MAIN LOOP
968970
# ============================================
969971
load_local_images()
970-
loopcount = 0
971-
errorcount = 0
972+
loopcount = 0 # pylint: disable=invalid-name
973+
errorcount = 0 # pylint: disable=invalid-name
972974

973975
print("Starting art display...")
974976
print("Mode:", current_feed)
975977
text_area.text = "Mode: " + current_feed
976978

979+
# Main loop variables use snake_case (not module constants)
980+
# pylint: disable=invalid-name
977981
while True:
978982
try:
979983
# Check for mode tap at start of each cycle
@@ -1083,7 +1087,7 @@ def wait_for_input(duration):
10831087
or "Expected" in error_str):
10841088
print("ESP32 SPI/WiFi error - resetting...")
10851089
try:
1086-
pyportal.network._wifi.esp.reset()
1090+
pyportal.network._wifi.esp.reset() # pylint: disable=protected-access
10871091
print("ESP32 reset complete, waiting...")
10881092
if tap_aware_sleep(10):
10891093
next_mode(count_taps())

0 commit comments

Comments
 (0)