persistent config file via config.template.json and migrate_config.sh

This commit is contained in:
Chuck
2025-09-15 10:27:16 -04:00
parent 4b36937a55
commit fcbc67464d
73 changed files with 429 additions and 1330 deletions

View File

@@ -0,0 +1,162 @@
#!/usr/bin/env python3
import json
import sys
import os
def add_custom_feed(feed_name, feed_url):
"""Add a custom RSS feed to the news manager configuration"""
config_path = "config/config.json"
try:
# Load current config
with open(config_path, 'r') as f:
config = json.load(f)
# Ensure news_manager section exists
if 'news_manager' not in config:
print("ERROR: News manager configuration not found!")
return False
# Add custom feed
if 'custom_feeds' not in config['news_manager']:
config['news_manager']['custom_feeds'] = {}
config['news_manager']['custom_feeds'][feed_name] = feed_url
# Add to enabled feeds if not already there
if feed_name not in config['news_manager']['enabled_feeds']:
config['news_manager']['enabled_feeds'].append(feed_name)
# Save updated config
with open(config_path, 'w') as f:
json.dump(config, f, indent=4)
print(f"SUCCESS: Successfully added custom feed: {feed_name}")
print(f" URL: {feed_url}")
print(f" Feed is now enabled and will appear in rotation")
return True
except Exception as e:
print(f"ERROR: Error adding custom feed: {e}")
return False
def list_all_feeds():
"""List all available feeds (default + custom)"""
config_path = "config/config.json"
try:
with open(config_path, 'r') as f:
config = json.load(f)
news_config = config.get('news_manager', {})
custom_feeds = news_config.get('custom_feeds', {})
enabled_feeds = news_config.get('enabled_feeds', [])
print("\nAvailable News Feeds:")
print("=" * 50)
# Default feeds (hardcoded in news_manager.py)
default_feeds = {
'MLB': 'http://espn.com/espn/rss/mlb/news',
'NFL': 'http://espn.go.com/espn/rss/nfl/news',
'NCAA FB': 'https://www.espn.com/espn/rss/ncf/news',
'NHL': 'https://www.espn.com/espn/rss/nhl/news',
'NBA': 'https://www.espn.com/espn/rss/nba/news',
'TOP SPORTS': 'https://www.espn.com/espn/rss/news',
'BIG10': 'https://www.espn.com/blog/feed?blog=bigten',
'NCAA': 'https://www.espn.com/espn/rss/ncaa/news',
'Other': 'https://www.coveringthecorner.com/rss/current.xml'
}
print("\nDefault Sports Feeds:")
for name, url in default_feeds.items():
status = "ENABLED" if name in enabled_feeds else "DISABLED"
print(f" {name}: {status}")
print(f" {url}")
if custom_feeds:
print("\nCustom Feeds:")
for name, url in custom_feeds.items():
status = "ENABLED" if name in enabled_feeds else "DISABLED"
print(f" {name}: {status}")
print(f" {url}")
else:
print("\nCustom Feeds: None added yet")
print(f"\nCurrently Enabled Feeds: {len(enabled_feeds)}")
print(f" {', '.join(enabled_feeds)}")
except Exception as e:
print(f"ERROR: Error listing feeds: {e}")
def remove_custom_feed(feed_name):
"""Remove a custom RSS feed"""
config_path = "config/config.json"
try:
with open(config_path, 'r') as f:
config = json.load(f)
news_config = config.get('news_manager', {})
custom_feeds = news_config.get('custom_feeds', {})
if feed_name not in custom_feeds:
print(f"ERROR: Custom feed '{feed_name}' not found!")
return False
# Remove from custom feeds
del config['news_manager']['custom_feeds'][feed_name]
# Remove from enabled feeds if present
if feed_name in config['news_manager']['enabled_feeds']:
config['news_manager']['enabled_feeds'].remove(feed_name)
# Save updated config
with open(config_path, 'w') as f:
json.dump(config, f, indent=4)
print(f"SUCCESS: Successfully removed custom feed: {feed_name}")
return True
except Exception as e:
print(f"ERROR: Error removing custom feed: {e}")
return False
def main():
if len(sys.argv) < 2:
print("Usage:")
print(" python3 add_custom_feed_example.py list")
print(" python3 add_custom_feed_example.py add <feed_name> <feed_url>")
print(" python3 add_custom_feed_example.py remove <feed_name>")
print("\nExamples:")
print(" # Add F1 news feed")
print(" python3 add_custom_feed_example.py add 'F1' 'https://www.espn.com/espn/rss/rpm/news'")
print(" # Add BBC F1 feed")
print(" python3 add_custom_feed_example.py add 'BBC F1' 'http://feeds.bbci.co.uk/sport/formula1/rss.xml'")
print(" # Add personal blog feed")
print(" python3 add_custom_feed_example.py add 'My Blog' 'https://myblog.com/rss.xml'")
return
command = sys.argv[1].lower()
if command == 'list':
list_all_feeds()
elif command == 'add':
if len(sys.argv) != 4:
print("ERROR: Usage: python3 add_custom_feed_example.py add <feed_name> <feed_url>")
return
feed_name = sys.argv[2]
feed_url = sys.argv[3]
add_custom_feed(feed_name, feed_url)
elif command == 'remove':
if len(sys.argv) != 3:
print("ERROR: Usage: python3 add_custom_feed_example.py remove <feed_name>")
return
feed_name = sys.argv[2]
remove_custom_feed(feed_name)
else:
print(f"ERROR: Unknown command: {command}")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@

107
test/debug_of_the_day.py Normal file
View File

@@ -0,0 +1,107 @@
#!/usr/bin/env python3
"""
Debug script for OfTheDayManager issues
Run this on the Raspberry Pi to diagnose the problem
Usage:
1. Copy this file to your Raspberry Pi
2. Run: python3 debug_of_the_day.py
3. Check the output for any errors or issues
This script will help identify why the OfTheDayManager is not loading data files.
"""
import json
import os
import sys
from datetime import date
def debug_of_the_day():
print("=== OfTheDayManager Debug Script ===")
print(f"Current working directory: {os.getcwd()}")
print(f"Python path: {sys.path}")
# Check if we're in the right directory
if not os.path.exists('config/config.json'):
print("ERROR: config/config.json not found. Make sure you're running from the LEDMatrix root directory.")
return
# Load the actual config
try:
with open('config/config.json', 'r') as f:
config = json.load(f)
print("✓ Successfully loaded config.json")
except Exception as e:
print(f"ERROR loading config.json: {e}")
return
# Check of_the_day configuration
of_the_day_config = config.get('of_the_day', {})
print(f"OfTheDay enabled: {of_the_day_config.get('enabled', False)}")
if not of_the_day_config.get('enabled', False):
print("OfTheDay is disabled in config!")
return
categories = of_the_day_config.get('categories', {})
print(f"Categories configured: {list(categories.keys())}")
# Test each category
today = date.today()
day_of_year = today.timetuple().tm_yday
print(f"Today is day {day_of_year} of the year")
for category_name, category_config in categories.items():
print(f"\n--- Testing category: {category_name} ---")
print(f"Category enabled: {category_config.get('enabled', True)}")
if not category_config.get('enabled', True):
print("Category is disabled, skipping...")
continue
data_file = category_config.get('data_file')
print(f"Data file: {data_file}")
# Test path resolution
if not os.path.isabs(data_file):
if data_file.startswith('of_the_day/'):
file_path = os.path.join(os.getcwd(), data_file)
else:
file_path = os.path.join(os.getcwd(), 'of_the_day', data_file)
else:
file_path = data_file
file_path = os.path.abspath(file_path)
print(f"Resolved path: {file_path}")
print(f"File exists: {os.path.exists(file_path)}")
if not os.path.exists(file_path):
print(f"ERROR: Data file not found at {file_path}")
continue
# Test JSON loading
try:
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
print(f"✓ Successfully loaded JSON with {len(data)} items")
# Check for today's entry
day_key = str(day_of_year)
if day_key in data:
item = data[day_key]
print(f"✓ Found entry for day {day_of_year}: {item.get('title', 'No title')}")
else:
print(f"✗ No entry found for day {day_of_year}")
# Show some nearby entries
nearby_days = [k for k in data.keys() if k.isdigit() and abs(int(k) - day_of_year) <= 5]
print(f"Nearby days with entries: {sorted(nearby_days)}")
except Exception as e:
print(f"ERROR loading JSON: {e}")
import traceback
traceback.print_exc()
print("\n=== Debug complete ===")
if __name__ == "__main__":
debug_of_the_day()

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@

657
test/missing_team_logos.txt Normal file
View File

@@ -0,0 +1,657 @@
================================================================================
MISSING TEAM LOGOS - COMPLETE LIST
================================================================================
Total missing teams: 309
MLB:
---
OAK => Oakland Athletics
NCAAF:
-----
AAMU => Alabama A&M Bulldogs
ACU => Abilene Christian Wildcats
ADA => Adams State Grizzlies
ADR => Adrian Bulldogs
AIC => American International Yellow Jackets
ALB => Albright Lions
ALBS => Albany State (GA) Golden Rams
ALCN => Alcorn State Braves
ALD => Alderson Broaddus Battlers
ALF => Alfred Saxons
ALL => Allegheny Gators
ALST => Alabama State Hornets
AMH => Amherst College Mammoths
AND => Anderson (IN) Ravens
ANG => Angelo State Rams
ANN => Anna Maria College Amcats
APSU => Austin Peay Governors
ASH => Ashland Eagles
ASP => Assumption Greyhounds
ASU => Arizona State Sun Devils
AUG => St. Augustine's Falcons
AUR => Aurora Spartans
AUS => Austin College 'Roos
AVE => Averett Cougars
AVI => Avila College Eagles
AZU => Azusa Pacific Cougars
BAK => Baker University Wildcats
BAL => Baldwin Wallace Yellow Jackets
BAT => Bates College Bobcats
BEC => Becker College Hawks
BEL => Beloit College Buccaneers
BEN => Benedictine University (IL) Eagles
BENT => Bentley Falcons
BET => Bethel (TN) Wildcats
BHS => Black Hills State Yellow Jackets
BIR => Birmingham-Southern Panthers
BKN => Bacone College Warriors
BLA => Blackburn Beavers
BLOM => Bloomsburg Huskies
BLU => Bluffton Beavers
BOW => Bowdoin Polar Bears
BRI => British Columbia Thunderbirds
BRWN => Brown Bears
BST => Bemidji State Beavers
BUCK => Bucknell Bison
BUE => Buena Vista Beavers
BUF => Buffalo State Bengals
BUT => Butler Bulldogs
CAM => Campbell Fighting Camels
CAP => Capital University Crusaders
CAR => Carthage College Red Men
CARK => Central Arkansas Bears
CAS => Castleton Spartans
CAT => Catholic University Cardinals
CCSU => Central Connecticut Blue Devils
CEN => Centre College Colonels
CHA => Chapman University Panthers
CHI => Chicago Maroons
CHSO => Charleston Southern Buccaneers
CLA => Clarion Golden Eagles
CLMB => Columbia Lions
COE => Coe College Kohawks
COL => Colorado School of Mines Orediggers
COLC => Colorado College Tigers
COLG => Colgate Raiders
CON => Concordia-Minnesota Cobbers
COR => Cornell College (IA) Rams
CP => Cal Poly Mustangs
CRO => Crown Storm
CSU => Colorado State Rams
CUL => Culver-Stockton Wildcats
CUM => Cumberland College Indians
CUR => Curry College Colonels
DAK => Dakota Wesleyan Tigers
DART => Dartmouth Big Green
DAV => Davidson Wildcats
DAY => Dayton Flyers
DEF => Defiance Yellow Jackets
DEL => Delta State Statesmen
DEN => Denison Big Red
DEP => DePauw Tigers
DIC => Dickinson State Blue Hawks
DRKE => Drake Bulldogs
DSU => Delaware State Hornets
DUB => Dubuque Spartans
DUQ => Duquesne Dukes
EAS => Eastern New Mexico Greyhounds
EDI => Edinboro Fighting Scots
EIU => Eastern Illinois Panthers
EKU => Eastern Kentucky Colonels
ELI => Elizabeth City State Vikings
ELM => Elmhurst Blue Jays
ELON => Elon Phoenix
EMO => Emory & Henry Wasps
EMP => Emporia State Hornets
END => Endicott College Gulls
EOR => Eastern Oregon Mountaineers
ETSU => East Tennessee State Buccaneers
EUR => Eureka College Red Devils
EWU => Eastern Washington Eagles
FAY => Fayetteville State Broncos
FDU => FDU-Florham Devils
FER => Ferrum Panthers
FIN => Findlay Oilers
FIT => Fitchburg State Falcons
FLA => Florida Gators
FOR => Fort Valley State Wildcats
FRA => Franklin Grizzlies
FRO => Frostburg State Bobcats
FRST => Ferris State Bulldogs
FTLW => Fort Lewis Skyhawks
FUR => Furman Paladins
GAL => Gallaudet Bison
GAN => Gannon Golden Knights
GEN => Geneva College Golden Tornadoes
GEO => George Fox University Bruins
GET => Gettysburg Bullets
GLE => Glenville State Pioneers
GMU => George Mason Patriots
GRA => Grand Valley State Lakers
GRE => Greenville Panthers
GRI => Grinnell Pioneers
GRO => Grove City College Wolverines
GUI => Guilford Quakers
GWEB => Gardner-Webb Bulldogs
HAM => Hampden-Sydney Tigers
HAMP => Hampton Pirates
HAN => Hanover Panthers
HAR => Hartwick Hawks
HARV => Harvard Crimson
HAS => Haskell Indian Nations Jayhawks
HAW => Hawai'i Rainbow Warriors
HBU => Houston Baptist Huskies
HC => Holy Cross Crusaders
HEI => Heidelberg Student Princes
HEN => Hendrix College Warriors
HIL => Hillsdale Chargers
HIR => Hiram College Terriers
HOB => Hobart Statesmen
HOW => Howard Bison
HUS => Husson Eagles
IDHO => Idaho Vandals
IDST => Idaho State Bengals
ILST => Illinois State Redbirds
ILW => Illinois Wesleyan Titans
IND => Indianapolis
INST => Indiana State Sycamores
IOW => Iowa Wesleyan Tigers
ITH => Ithaca Bombers
JKST => Jackson State Tigers
JOH => Johnson C Smith Golden Bulls
JUN => Juniata Eagles
KAL => Kalamazoo Hornets
KAN => Kansas Wesleyan University Coyotes
KEN => Kenyon Lords
KIN => King's College (PA) Monarchs
KNO => Knox College Prairie Fire
KUT => Kutztown Golden Bears
KYST => Kentucky State Thorobreds
KYW => Kentucky Wesleyan Panthers
LA => La Verne Leopards
LAG => LaGrange College Panthers
LAK => Lake Forest Foresters
LAM => Lambuth Eagles
LAN => Langston Lions
LAW => Lawrence Vikings
LEB => Lebanon Valley Flying Dutchmen
LEH => Lehigh Mountain Hawks
LEN => Lenoir-Rhyne Bears
LEW => Lewis & Clark Pioneers
LIM => Limestone Saints
LIN => Linfield Wildcats
LOC => Lock Haven Bald Eagles
LOR => Loras College Duhawks
LUT => Luther Norse
LYC => Lycoming Warriors
M-OH => Miami (OH) RedHawks
MAC => Macalester Scots
MAI => Maine Maritime Mariners
MAN => Mansfield Mountaineers
MAR => Maryville College Fighting Scots
MAS => Mass Maritime Buccaneers
MAY => Mayville State Comets
MCM => McMurry War Hawks
MCN => McNeese Cowboys
MEN => Menlo College Oaks
MER => Merchant Marine Mariners
MERC => Mercyhurst Lakers
MES => Colorado Mesa Mavericks
MET => Methodist Monarchs
MH => Mars Hill Mountain Lions
MID => Midwestern State Mustangs
MIL => Millsaps Majors
MIN => Minot State Beavers
MIS => Missouri Western Griffons
MNST => Minnesota State Mavericks
MONM => Monmouth Hawks
MONT => Montana Grizzlies
MOR => Morningside Chiefs
MORE => Morehead State Eagles
MORG => Morgan State Bears
MOU => Mount Union Raiders
MRST => Marist Red Foxes
MSU => Michigan State Spartans
MTST => Montana State Bobcats
MTU => Michigan Tech Huskies
MUH => Muhlenberg Mules
MUR => Murray State Racers
MUS => Muskingum Fighting Muskies
MVSU => Mississippi Valley State Delta Devils
NAU => Northern Arizona Lumberjacks
NBY => Newberry Wolves
NCAT => North Carolina A&T Aggies
NCCU => North Carolina Central Eagles
NCST => NC State Wolfpack
NDOH => Notre Dame College Falcons
NDSU => North Dakota State Bison
NH => New Haven Chargers
NICH => Nicholls Colonels
NMH => New Mexico Highlands Cowboys
NMI => Northern Michigan Wildcats
NOR => Univ. of Northwestern-St. Paul Eagles
NORF => Norfolk State Spartans
OBE => Oberlin Yeomen
OHI => Ohio Northern Polar Bears
OKL => Oklahoma Baptist Bison
OLI => Olivet College Comets
OMA => Omaha Mavericks
OTT => Otterbein Cardinals
PAC => Pacific (OR) Boxers
PENN => Pennsylvania Quakers
PIKE => Pikeville Bears
PRE => Presentation College Saints
PRI => Principia College Panthers
PRIN => Princeton Tigers
PST => Pittsburg State Gorillas
RED => Redlands Bulldogs
RICH => Richmond Spiders
RIT => Rochester Yellow Jackets
ROB => Robert Morris (IL) Eagles
ROS => Rose-Hulman Engineers
SAC => Sacramento State Hornets
SAG => Saginaw Valley Cardinals
SDAK => South Dakota Coyotes
SET => Seton Hill Griffins
SIU => Southern Illinois Salukis
SLI => Slippery Rock The Rock
SOU => Southwestern College Moundbuilders
SPR => Springfield College Pride
ST => St. Scholastica Saints
STE => Stevenson University Mustangs
STET => Stetson Hatters
STO => Stonehill College Skyhawks
SUS => Susquehanna University River Hawks
SUU => Southern Utah Thunderbirds
TA&M => Texas A&M Aggies
TAY => Taylor Trojans
TIF => Tiffin University Dragons
TRI => Trinity University (TX) Tigers
TUF => Tufts University Jumbos
TXST => Texas State Bobcats
UAPB => Arkansas-Pine Bluff Golden Lions
UCD => UC Davis Aggies
UCONN => UConn Huskies
ULM => UL Monroe Warhawks
UMD => Minnesota-Duluth Bulldogs
UMDA => UMASS Dartmouth Corsairs
UML => UMass Lowell River Hawks
UNA => North Alabama Lions
UNCO => Northern Colorado Bears
UND => North Dakota Fighting Hawks
UNH => New Hampshire Wildcats
UNI => University of Mary Marauders
UNNY => Union Dutchmen
UNT => North Texas Mean Green
UPP => Upper Iowa Peacocks
URI => Rhode Island Rams
USA => South Alabama Jaguars
USD => San Diego Toreros
UTC => Chattanooga Mocs
UTI => Utica College Pioneers
VAL => Valley City State Vikings
VILL => Villanova Wildcats
VIR => Virginia State Trojans
VT => Virginia Tech Hokies
WAB => Wabash College Little Giants
WAS => Washington-Missouri Bears
WAY => Wayne State (MI) Warriors
WES => Westminster College (MO) Blue Jays
WHE => Wheaton College Illinois Thunder
WIL => Wilkes University Colonels
WIN => Wingate Bulldogs
WIS => Wisconsin-Platteville Pioneers
WOR => Worcester State College Lancers
YALE => Yale Bulldogs
NHL:
---
ARI => Arizona Coyotes
VGS => Vegas Golden Knights
SOCCER - BUNDESLIGA (GERMANY):
-----------------------------
DOR => Borussia Dortmund
KOL => 1. FC Köln
LEV => Bayer Leverkusen
STU => VfB Stuttgart
SOCCER - LIGUE 1 (FRANCE):
-------------------------
LYON => Lyon
MAR => Marseille
NICE => Nice
PSG => Paris Saint-Germain
SOCCER - PREMIER LEAGUE (ENGLAND):
---------------------------------
BUR => Burnley
LUT => Luton Town
SHU => Sheffield United
================================================================================
SUMMARY BY SPORT:
================================================================================
MLB: 1 missing
NCAAF: 295 missing
NHL: 2 missing
Soccer - Bundesliga (Germany): 4 missing
Soccer - Ligue 1 (France): 4 missing
Soccer - Premier League (England): 3 missing
================================================================================
FILENAMES NEEDED:
================================================================================
Add these PNG files to their respective directories:
assets/sports/mlb_logos/OAK.png
assets/sports/ncaa_fbs_logos/AAMU.png
assets/sports/ncaa_fbs_logos/ACU.png
assets/sports/ncaa_fbs_logos/ADA.png
assets/sports/ncaa_fbs_logos/ADR.png
assets/sports/ncaa_fbs_logos/AIC.png
assets/sports/ncaa_fbs_logos/ALB.png
assets/sports/ncaa_fbs_logos/ALBS.png
assets/sports/ncaa_fbs_logos/ALCN.png
assets/sports/ncaa_fbs_logos/ALD.png
assets/sports/ncaa_fbs_logos/ALF.png
assets/sports/ncaa_fbs_logos/ALL.png
assets/sports/ncaa_fbs_logos/ALST.png
assets/sports/ncaa_fbs_logos/AMH.png
assets/sports/ncaa_fbs_logos/AND.png
assets/sports/ncaa_fbs_logos/ANG.png
assets/sports/ncaa_fbs_logos/ANN.png
assets/sports/ncaa_fbs_logos/APSU.png
assets/sports/ncaa_fbs_logos/ASH.png
assets/sports/ncaa_fbs_logos/ASP.png
assets/sports/ncaa_fbs_logos/ASU.png
assets/sports/ncaa_fbs_logos/AUG.png
assets/sports/ncaa_fbs_logos/AUR.png
assets/sports/ncaa_fbs_logos/AUS.png
assets/sports/ncaa_fbs_logos/AVE.png
assets/sports/ncaa_fbs_logos/AVI.png
assets/sports/ncaa_fbs_logos/AZU.png
assets/sports/ncaa_fbs_logos/BAK.png
assets/sports/ncaa_fbs_logos/BAL.png
assets/sports/ncaa_fbs_logos/BAT.png
assets/sports/ncaa_fbs_logos/BEC.png
assets/sports/ncaa_fbs_logos/BEL.png
assets/sports/ncaa_fbs_logos/BEN.png
assets/sports/ncaa_fbs_logos/BENT.png
assets/sports/ncaa_fbs_logos/BET.png
assets/sports/ncaa_fbs_logos/BHS.png
assets/sports/ncaa_fbs_logos/BIR.png
assets/sports/ncaa_fbs_logos/BKN.png
assets/sports/ncaa_fbs_logos/BLA.png
assets/sports/ncaa_fbs_logos/BLOM.png
assets/sports/ncaa_fbs_logos/BLU.png
assets/sports/ncaa_fbs_logos/BOW.png
assets/sports/ncaa_fbs_logos/BRI.png
assets/sports/ncaa_fbs_logos/BRWN.png
assets/sports/ncaa_fbs_logos/BST.png
assets/sports/ncaa_fbs_logos/BUCK.png
assets/sports/ncaa_fbs_logos/BUE.png
assets/sports/ncaa_fbs_logos/BUF.png
assets/sports/ncaa_fbs_logos/BUT.png
assets/sports/ncaa_fbs_logos/CAM.png
assets/sports/ncaa_fbs_logos/CAP.png
assets/sports/ncaa_fbs_logos/CAR.png
assets/sports/ncaa_fbs_logos/CARK.png
assets/sports/ncaa_fbs_logos/CAS.png
assets/sports/ncaa_fbs_logos/CAT.png
assets/sports/ncaa_fbs_logos/CCSU.png
assets/sports/ncaa_fbs_logos/CEN.png
assets/sports/ncaa_fbs_logos/CHA.png
assets/sports/ncaa_fbs_logos/CHI.png
assets/sports/ncaa_fbs_logos/CHSO.png
assets/sports/ncaa_fbs_logos/CLA.png
assets/sports/ncaa_fbs_logos/CLMB.png
assets/sports/ncaa_fbs_logos/COE.png
assets/sports/ncaa_fbs_logos/COL.png
assets/sports/ncaa_fbs_logos/COLC.png
assets/sports/ncaa_fbs_logos/COLG.png
assets/sports/ncaa_fbs_logos/CON.png
assets/sports/ncaa_fbs_logos/COR.png
assets/sports/ncaa_fbs_logos/CP.png
assets/sports/ncaa_fbs_logos/CRO.png
assets/sports/ncaa_fbs_logos/CSU.png
assets/sports/ncaa_fbs_logos/CUL.png
assets/sports/ncaa_fbs_logos/CUM.png
assets/sports/ncaa_fbs_logos/CUR.png
assets/sports/ncaa_fbs_logos/DAK.png
assets/sports/ncaa_fbs_logos/DART.png
assets/sports/ncaa_fbs_logos/DAV.png
assets/sports/ncaa_fbs_logos/DAY.png
assets/sports/ncaa_fbs_logos/DEF.png
assets/sports/ncaa_fbs_logos/DEL.png
assets/sports/ncaa_fbs_logos/DEN.png
assets/sports/ncaa_fbs_logos/DEP.png
assets/sports/ncaa_fbs_logos/DIC.png
assets/sports/ncaa_fbs_logos/DRKE.png
assets/sports/ncaa_fbs_logos/DSU.png
assets/sports/ncaa_fbs_logos/DUB.png
assets/sports/ncaa_fbs_logos/DUQ.png
assets/sports/ncaa_fbs_logos/EAS.png
assets/sports/ncaa_fbs_logos/EDI.png
assets/sports/ncaa_fbs_logos/EIU.png
assets/sports/ncaa_fbs_logos/EKU.png
assets/sports/ncaa_fbs_logos/ELI.png
assets/sports/ncaa_fbs_logos/ELM.png
assets/sports/ncaa_fbs_logos/ELON.png
assets/sports/ncaa_fbs_logos/EMO.png
assets/sports/ncaa_fbs_logos/EMP.png
assets/sports/ncaa_fbs_logos/END.png
assets/sports/ncaa_fbs_logos/EOR.png
assets/sports/ncaa_fbs_logos/ETSU.png
assets/sports/ncaa_fbs_logos/EUR.png
assets/sports/ncaa_fbs_logos/EWU.png
assets/sports/ncaa_fbs_logos/FAY.png
assets/sports/ncaa_fbs_logos/FDU.png
assets/sports/ncaa_fbs_logos/FER.png
assets/sports/ncaa_fbs_logos/FIN.png
assets/sports/ncaa_fbs_logos/FIT.png
assets/sports/ncaa_fbs_logos/FLA.png
assets/sports/ncaa_fbs_logos/FOR.png
assets/sports/ncaa_fbs_logos/FRA.png
assets/sports/ncaa_fbs_logos/FRO.png
assets/sports/ncaa_fbs_logos/FRST.png
assets/sports/ncaa_fbs_logos/FTLW.png
assets/sports/ncaa_fbs_logos/FUR.png
assets/sports/ncaa_fbs_logos/GAL.png
assets/sports/ncaa_fbs_logos/GAN.png
assets/sports/ncaa_fbs_logos/GEN.png
assets/sports/ncaa_fbs_logos/GEO.png
assets/sports/ncaa_fbs_logos/GET.png
assets/sports/ncaa_fbs_logos/GLE.png
assets/sports/ncaa_fbs_logos/GMU.png
assets/sports/ncaa_fbs_logos/GRA.png
assets/sports/ncaa_fbs_logos/GRE.png
assets/sports/ncaa_fbs_logos/GRI.png
assets/sports/ncaa_fbs_logos/GRO.png
assets/sports/ncaa_fbs_logos/GUI.png
assets/sports/ncaa_fbs_logos/GWEB.png
assets/sports/ncaa_fbs_logos/HAM.png
assets/sports/ncaa_fbs_logos/HAMP.png
assets/sports/ncaa_fbs_logos/HAN.png
assets/sports/ncaa_fbs_logos/HAR.png
assets/sports/ncaa_fbs_logos/HARV.png
assets/sports/ncaa_fbs_logos/HAS.png
assets/sports/ncaa_fbs_logos/HAW.png
assets/sports/ncaa_fbs_logos/HBU.png
assets/sports/ncaa_fbs_logos/HC.png
assets/sports/ncaa_fbs_logos/HEI.png
assets/sports/ncaa_fbs_logos/HEN.png
assets/sports/ncaa_fbs_logos/HIL.png
assets/sports/ncaa_fbs_logos/HIR.png
assets/sports/ncaa_fbs_logos/HOB.png
assets/sports/ncaa_fbs_logos/HOW.png
assets/sports/ncaa_fbs_logos/HUS.png
assets/sports/ncaa_fbs_logos/IDHO.png
assets/sports/ncaa_fbs_logos/IDST.png
assets/sports/ncaa_fbs_logos/ILST.png
assets/sports/ncaa_fbs_logos/ILW.png
assets/sports/ncaa_fbs_logos/IND.png
assets/sports/ncaa_fbs_logos/INST.png
assets/sports/ncaa_fbs_logos/IOW.png
assets/sports/ncaa_fbs_logos/ITH.png
assets/sports/ncaa_fbs_logos/JKST.png
assets/sports/ncaa_fbs_logos/JOH.png
assets/sports/ncaa_fbs_logos/JUN.png
assets/sports/ncaa_fbs_logos/KAL.png
assets/sports/ncaa_fbs_logos/KAN.png
assets/sports/ncaa_fbs_logos/KEN.png
assets/sports/ncaa_fbs_logos/KIN.png
assets/sports/ncaa_fbs_logos/KNO.png
assets/sports/ncaa_fbs_logos/KUT.png
assets/sports/ncaa_fbs_logos/KYST.png
assets/sports/ncaa_fbs_logos/KYW.png
assets/sports/ncaa_fbs_logos/LA.png
assets/sports/ncaa_fbs_logos/LAG.png
assets/sports/ncaa_fbs_logos/LAK.png
assets/sports/ncaa_fbs_logos/LAM.png
assets/sports/ncaa_fbs_logos/LAN.png
assets/sports/ncaa_fbs_logos/LAW.png
assets/sports/ncaa_fbs_logos/LEB.png
assets/sports/ncaa_fbs_logos/LEH.png
assets/sports/ncaa_fbs_logos/LEN.png
assets/sports/ncaa_fbs_logos/LEW.png
assets/sports/ncaa_fbs_logos/LIM.png
assets/sports/ncaa_fbs_logos/LIN.png
assets/sports/ncaa_fbs_logos/LOC.png
assets/sports/ncaa_fbs_logos/LOR.png
assets/sports/ncaa_fbs_logos/LUT.png
assets/sports/ncaa_fbs_logos/LYC.png
assets/sports/ncaa_fbs_logos/M-OH.png
assets/sports/ncaa_fbs_logos/MAC.png
assets/sports/ncaa_fbs_logos/MAI.png
assets/sports/ncaa_fbs_logos/MAN.png
assets/sports/ncaa_fbs_logos/MAR.png
assets/sports/ncaa_fbs_logos/MAS.png
assets/sports/ncaa_fbs_logos/MAY.png
assets/sports/ncaa_fbs_logos/MCM.png
assets/sports/ncaa_fbs_logos/MCN.png
assets/sports/ncaa_fbs_logos/MEN.png
assets/sports/ncaa_fbs_logos/MER.png
assets/sports/ncaa_fbs_logos/MERC.png
assets/sports/ncaa_fbs_logos/MES.png
assets/sports/ncaa_fbs_logos/MET.png
assets/sports/ncaa_fbs_logos/MH.png
assets/sports/ncaa_fbs_logos/MID.png
assets/sports/ncaa_fbs_logos/MIL.png
assets/sports/ncaa_fbs_logos/MIN.png
assets/sports/ncaa_fbs_logos/MIS.png
assets/sports/ncaa_fbs_logos/MNST.png
assets/sports/ncaa_fbs_logos/MONM.png
assets/sports/ncaa_fbs_logos/MONT.png
assets/sports/ncaa_fbs_logos/MOR.png
assets/sports/ncaa_fbs_logos/MORE.png
assets/sports/ncaa_fbs_logos/MORG.png
assets/sports/ncaa_fbs_logos/MOU.png
assets/sports/ncaa_fbs_logos/MRST.png
assets/sports/ncaa_fbs_logos/MSU.png
assets/sports/ncaa_fbs_logos/MTST.png
assets/sports/ncaa_fbs_logos/MTU.png
assets/sports/ncaa_fbs_logos/MUH.png
assets/sports/ncaa_fbs_logos/MUR.png
assets/sports/ncaa_fbs_logos/MUS.png
assets/sports/ncaa_fbs_logos/MVSU.png
assets/sports/ncaa_fbs_logos/NAU.png
assets/sports/ncaa_fbs_logos/NBY.png
assets/sports/ncaa_fbs_logos/NCAT.png
assets/sports/ncaa_fbs_logos/NCCU.png
assets/sports/ncaa_fbs_logos/NCST.png
assets/sports/ncaa_fbs_logos/NDOH.png
assets/sports/ncaa_fbs_logos/NDSU.png
assets/sports/ncaa_fbs_logos/NH.png
assets/sports/ncaa_fbs_logos/NICH.png
assets/sports/ncaa_fbs_logos/NMH.png
assets/sports/ncaa_fbs_logos/NMI.png
assets/sports/ncaa_fbs_logos/NOR.png
assets/sports/ncaa_fbs_logos/NORF.png
assets/sports/ncaa_fbs_logos/OBE.png
assets/sports/ncaa_fbs_logos/OHI.png
assets/sports/ncaa_fbs_logos/OKL.png
assets/sports/ncaa_fbs_logos/OLI.png
assets/sports/ncaa_fbs_logos/OMA.png
assets/sports/ncaa_fbs_logos/OTT.png
assets/sports/ncaa_fbs_logos/PAC.png
assets/sports/ncaa_fbs_logos/PENN.png
assets/sports/ncaa_fbs_logos/PIKE.png
assets/sports/ncaa_fbs_logos/PRE.png
assets/sports/ncaa_fbs_logos/PRI.png
assets/sports/ncaa_fbs_logos/PRIN.png
assets/sports/ncaa_fbs_logos/PST.png
assets/sports/ncaa_fbs_logos/RED.png
assets/sports/ncaa_fbs_logos/RICH.png
assets/sports/ncaa_fbs_logos/RIT.png
assets/sports/ncaa_fbs_logos/ROB.png
assets/sports/ncaa_fbs_logos/ROS.png
assets/sports/ncaa_fbs_logos/SAC.png
assets/sports/ncaa_fbs_logos/SAG.png
assets/sports/ncaa_fbs_logos/SDAK.png
assets/sports/ncaa_fbs_logos/SET.png
assets/sports/ncaa_fbs_logos/SIU.png
assets/sports/ncaa_fbs_logos/SLI.png
assets/sports/ncaa_fbs_logos/SOU.png
assets/sports/ncaa_fbs_logos/SPR.png
assets/sports/ncaa_fbs_logos/ST.png
assets/sports/ncaa_fbs_logos/STE.png
assets/sports/ncaa_fbs_logos/STET.png
assets/sports/ncaa_fbs_logos/STO.png
assets/sports/ncaa_fbs_logos/SUS.png
assets/sports/ncaa_fbs_logos/SUU.png
assets/sports/ncaa_fbs_logos/TA&M.png
assets/sports/ncaa_fbs_logos/TAY.png
assets/sports/ncaa_fbs_logos/TIF.png
assets/sports/ncaa_fbs_logos/TRI.png
assets/sports/ncaa_fbs_logos/TUF.png
assets/sports/ncaa_fbs_logos/TXST.png
assets/sports/ncaa_fbs_logos/UAPB.png
assets/sports/ncaa_fbs_logos/UCD.png
assets/sports/ncaa_fbs_logos/UCONN.png
assets/sports/ncaa_fbs_logos/ULM.png
assets/sports/ncaa_fbs_logos/UMD.png
assets/sports/ncaa_fbs_logos/UMDA.png
assets/sports/ncaa_fbs_logos/UML.png
assets/sports/ncaa_fbs_logos/UNA.png
assets/sports/ncaa_fbs_logos/UNCO.png
assets/sports/ncaa_fbs_logos/UND.png
assets/sports/ncaa_fbs_logos/UNH.png
assets/sports/ncaa_fbs_logos/UNI.png
assets/sports/ncaa_fbs_logos/UNNY.png
assets/sports/ncaa_fbs_logos/UNT.png
assets/sports/ncaa_fbs_logos/UPP.png
assets/sports/ncaa_fbs_logos/URI.png
assets/sports/ncaa_fbs_logos/USA.png
assets/sports/ncaa_fbs_logos/USD.png
assets/sports/ncaa_fbs_logos/UTC.png
assets/sports/ncaa_fbs_logos/UTI.png
assets/sports/ncaa_fbs_logos/VAL.png
assets/sports/ncaa_fbs_logos/VILL.png
assets/sports/ncaa_fbs_logos/VIR.png
assets/sports/ncaa_fbs_logos/VT.png
assets/sports/ncaa_fbs_logos/WAB.png
assets/sports/ncaa_fbs_logos/WAS.png
assets/sports/ncaa_fbs_logos/WAY.png
assets/sports/ncaa_fbs_logos/WES.png
assets/sports/ncaa_fbs_logos/WHE.png
assets/sports/ncaa_fbs_logos/WIL.png
assets/sports/ncaa_fbs_logos/WIN.png
assets/sports/ncaa_fbs_logos/WIS.png
assets/sports/ncaa_fbs_logos/WOR.png
assets/sports/ncaa_fbs_logos/YALE.png
assets/sports/nhl_logos/ARI.png
assets/sports/nhl_logos/VGS.png
assets/sports/soccer_logos/DOR.png
assets/sports/soccer_logos/KOL.png
assets/sports/soccer_logos/LEV.png
assets/sports/soccer_logos/STU.png
assets/sports/soccer_logos/LYON.png
assets/sports/soccer_logos/MAR.png
assets/sports/soccer_logos/NICE.png
assets/sports/soccer_logos/PSG.png
assets/sports/soccer_logos/BUR.png
assets/sports/soccer_logos/LUT.png
assets/sports/soccer_logos/SHU.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

160
test/save_missing_teams.py Normal file
View File

@@ -0,0 +1,160 @@
#!/usr/bin/env python3
"""
Script to save the missing teams list to a file for future reference.
"""
import os
from pathlib import Path
def save_missing_teams():
"""Save the missing teams list to a file."""
# Define the sports directories and their corresponding sections in the abbreviations file
sports_dirs = {
'mlb_logos': 'MLB',
'nba_logos': 'NBA',
'nfl_logos': 'NFL',
'nhl_logos': 'NHL',
'ncaa_fbs_logos': ['NCAAF', 'NCAA Conferences/Divisions', 'NCAA_big10', 'NCAA_big12', 'NCAA_acc', 'NCAA_sec', 'NCAA_pac12', 'NCAA_american', 'NCAA_cusa', 'NCAA_mac', 'NCAA_mwc', 'NCAA_sunbelt', 'NCAA_ind', 'NCAA_ovc', 'NCAA_col', 'NCAA_usa', 'NCAA_bigw'],
'soccer_logos': ['Soccer - Premier League (England)', 'Soccer - La Liga (Spain)', 'Soccer - Bundesliga (Germany)', 'Soccer - Serie A (Italy)', 'Soccer - Ligue 1 (France)', 'Soccer - Champions League', 'Soccer - Other Teams'],
'milb_logos': 'MiLB'
}
# Read the abbreviations file
abbreviations_file = Path("assets/sports/all_team_abbreviations.txt")
if not abbreviations_file.exists():
print("Error: all_team_abbreviations.txt not found")
return
with open(abbreviations_file, 'r') as f:
content = f.read()
# Parse teams from the abbreviations file
teams_by_sport = {}
current_section = None
for line in content.split('\n'):
original_line = line
line = line.strip()
# Check if this is a section header (not indented and no arrow)
if line and not original_line.startswith(' ') and ' => ' not in line:
current_section = line
continue
# Check if this is a team entry (indented and has arrow)
if original_line.startswith(' ') and ' => ' in line:
parts = line.split(' => ')
if len(parts) == 2:
abbr = parts[0].strip()
team_name = parts[1].strip()
if current_section not in teams_by_sport:
teams_by_sport[current_section] = []
teams_by_sport[current_section].append((abbr, team_name))
# Collect all missing teams
all_missing_teams = []
for logo_dir, sections in sports_dirs.items():
logo_path = Path(f"assets/sports/{logo_dir}")
if not logo_path.exists():
print(f"⚠️ Logo directory not found: {logo_path}")
continue
# Get all PNG files in the directory
logo_files = [f.stem for f in logo_path.glob("*.png")]
# Check teams for this sport
if isinstance(sections, str):
sections = [sections]
for section in sections:
if section not in teams_by_sport:
continue
missing_teams = []
for abbr, team_name in teams_by_sport[section]:
# Check if logo exists (case-insensitive)
logo_found = False
for logo_file in logo_files:
if logo_file.lower() == abbr.lower():
logo_found = True
break
if not logo_found:
missing_teams.append((abbr, team_name))
if missing_teams:
all_missing_teams.extend([(section, abbr, team_name) for abbr, team_name in missing_teams])
# Sort by sport and then by team abbreviation
all_missing_teams.sort(key=lambda x: (x[0], x[1]))
# Save to file
output_file = "missing_team_logos.txt"
with open(output_file, 'w') as f:
f.write("=" * 80 + "\n")
f.write("MISSING TEAM LOGOS - COMPLETE LIST\n")
f.write("=" * 80 + "\n")
f.write(f"Total missing teams: {len(all_missing_teams)}\n")
f.write("\n")
current_sport = None
for section, abbr, team_name in all_missing_teams:
if section != current_sport:
current_sport = section
f.write(f"\n{section.upper()}:\n")
f.write("-" * len(section) + "\n")
f.write(f" {abbr:>8} => {team_name}\n")
f.write("\n" + "=" * 80 + "\n")
f.write("SUMMARY BY SPORT:\n")
f.write("=" * 80 + "\n")
# Count by sport
sport_counts = {}
for section, abbr, team_name in all_missing_teams:
if section not in sport_counts:
sport_counts[section] = 0
sport_counts[section] += 1
for sport, count in sorted(sport_counts.items()):
f.write(f"{sport:>30}: {count:>3} missing\n")
f.write("\n" + "=" * 80 + "\n")
f.write("FILENAMES NEEDED:\n")
f.write("=" * 80 + "\n")
f.write("Add these PNG files to their respective directories:\n")
f.write("\n")
for section, abbr, team_name in all_missing_teams:
# Determine the directory based on the section
if 'MLB' in section:
dir_name = 'mlb_logos'
elif 'NBA' in section:
dir_name = 'nba_logos'
elif 'NFL' in section:
dir_name = 'nfl_logos'
elif 'NHL' in section:
dir_name = 'nhl_logos'
elif 'NCAA' in section:
dir_name = 'ncaa_fbs_logos'
elif 'Soccer' in section:
dir_name = 'soccer_logos'
elif 'MiLB' in section:
dir_name = 'milb_logos'
else:
dir_name = 'unknown'
f.write(f"assets/sports/{dir_name}/{abbr}.png\n")
print(f"✅ Missing teams list saved to: {output_file}")
print(f"📊 Total missing teams: {len(all_missing_teams)}")
if __name__ == "__main__":
save_missing_teams()

View File

@@ -0,0 +1,187 @@
#!/usr/bin/env python3
"""
Test script to demonstrate the graceful update system for scrolling displays.
This script shows how updates are deferred during scrolling periods to prevent lag.
"""
import time
import logging
import sys
import os
# Add the project root directory to Python path
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
# Configure logging first
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s.%(msecs)03d - %(levelname)s:%(name)s:%(message)s',
datefmt='%H:%M:%S',
stream=sys.stdout
)
logger = logging.getLogger(__name__)
# Mock rgbmatrix module for testing on non-Raspberry Pi systems
try:
from rgbmatrix import RGBMatrix, RGBMatrixOptions
except ImportError:
logger.info("rgbmatrix module not available, using mock for testing")
class MockRGBMatrixOptions:
def __init__(self):
self.rows = 32
self.cols = 64
self.chain_length = 2
self.parallel = 1
self.hardware_mapping = 'adafruit-hat-pwm'
self.brightness = 90
self.pwm_bits = 10
self.pwm_lsb_nanoseconds = 150
self.led_rgb_sequence = 'RGB'
self.pixel_mapper_config = ''
self.row_address_type = 0
self.multiplexing = 0
self.disable_hardware_pulsing = False
self.show_refresh_rate = False
self.limit_refresh_rate_hz = 90
self.gpio_slowdown = 2
class MockRGBMatrix:
def __init__(self, options=None):
self.width = 128 # 64 * 2 chain length
self.height = 32
def CreateFrameCanvas(self):
return MockCanvas()
def SwapOnVSync(self, canvas, dont_wait=False):
pass
def Clear(self):
pass
class MockCanvas:
def __init__(self):
self.width = 128
self.height = 32
def SetImage(self, image):
pass
def Clear(self):
pass
RGBMatrix = MockRGBMatrix
RGBMatrixOptions = MockRGBMatrixOptions
from src.display_manager import DisplayManager
from src.config_manager import ConfigManager
def simulate_scrolling_display(display_manager, duration=10):
"""Simulate a scrolling display for testing."""
logger.info(f"Starting scrolling simulation for {duration} seconds")
start_time = time.time()
while time.time() - start_time < duration:
# Signal that we're scrolling
display_manager.set_scrolling_state(True)
# Simulate some scrolling work
time.sleep(0.1)
# Every 2 seconds, try to defer an update
if int(time.time() - start_time) % 2 == 0:
logger.info("Attempting to defer an update during scrolling")
display_manager.defer_update(
lambda: logger.info("This update was deferred and executed later!"),
priority=1
)
# Signal that scrolling has stopped
display_manager.set_scrolling_state(False)
logger.info("Scrolling simulation completed")
def test_graceful_updates():
"""Test the graceful update system."""
logger.info("Testing graceful update system")
# Load config
config_manager = ConfigManager()
config = config_manager.load_config()
# Initialize display manager
display_manager = DisplayManager(config, force_fallback=True)
try:
# Test 1: Defer updates during scrolling
logger.info("=== Test 1: Defer updates during scrolling ===")
# Add some deferred updates
display_manager.defer_update(
lambda: logger.info("Update 1: High priority update"),
priority=1
)
display_manager.defer_update(
lambda: logger.info("Update 2: Medium priority update"),
priority=2
)
display_manager.defer_update(
lambda: logger.info("Update 3: Low priority update"),
priority=3
)
# Start scrolling simulation
simulate_scrolling_display(display_manager, duration=5)
# Check scrolling stats
stats = display_manager.get_scrolling_stats()
logger.info(f"Scrolling stats: {stats}")
# Test 2: Process deferred updates when not scrolling
logger.info("=== Test 2: Process deferred updates when not scrolling ===")
# Process any remaining deferred updates
display_manager.process_deferred_updates()
# Test 3: Test inactivity threshold
logger.info("=== Test 3: Test inactivity threshold ===")
# Signal scrolling started
display_manager.set_scrolling_state(True)
logger.info(f"Is scrolling: {display_manager.is_currently_scrolling()}")
# Wait longer than the inactivity threshold
time.sleep(3)
logger.info(f"Is scrolling after inactivity: {display_manager.is_currently_scrolling()}")
# Test 4: Test priority ordering
logger.info("=== Test 4: Test priority ordering ===")
# Add updates in reverse priority order
display_manager.defer_update(
lambda: logger.info("Priority 3 update"),
priority=3
)
display_manager.defer_update(
lambda: logger.info("Priority 1 update"),
priority=1
)
display_manager.defer_update(
lambda: logger.info("Priority 2 update"),
priority=2
)
# Process them (should execute in priority order: 1, 2, 3)
display_manager.process_deferred_updates()
logger.info("All tests completed successfully!")
except Exception as e:
logger.error(f"Test failed: {e}", exc_info=True)
finally:
# Cleanup
display_manager.cleanup()
if __name__ == "__main__":
test_graceful_updates()

144
test/test_web_interface.py Normal file
View File

@@ -0,0 +1,144 @@
#!/usr/bin/env python3
"""
Test script for the LED Matrix web interface
This script tests the basic functionality of the web interface
"""
import requests
import json
import time
import sys
def test_web_interface():
"""Test the web interface functionality"""
base_url = "http://localhost:5000"
print("Testing LED Matrix Web Interface...")
print("=" * 50)
# Test 1: Check if the web interface is running
try:
response = requests.get(base_url, timeout=5)
if response.status_code == 200:
print("✓ Web interface is running")
else:
print(f"✗ Web interface returned status code: {response.status_code}")
return False
except requests.exceptions.ConnectionError:
print("✗ Could not connect to web interface. Is it running?")
print(" Start it with: python3 web_interface.py")
return False
except Exception as e:
print(f"✗ Error connecting to web interface: {e}")
return False
# Test 2: Test schedule configuration
print("\nTesting schedule configuration...")
schedule_data = {
'schedule_enabled': 'on',
'start_time': '08:00',
'end_time': '22:00'
}
try:
response = requests.post(f"{base_url}/save_schedule", data=schedule_data, timeout=10)
if response.status_code == 200:
print("✓ Schedule configuration saved successfully")
else:
print(f"✗ Schedule configuration failed: {response.status_code}")
except Exception as e:
print(f"✗ Error saving schedule: {e}")
# Test 3: Test main configuration save
print("\nTesting main configuration save...")
test_config = {
"weather": {
"enabled": True,
"units": "imperial",
"update_interval": 1800
},
"location": {
"city": "Test City",
"state": "Test State"
}
}
try:
response = requests.post(f"{base_url}/save_config", data={
'config_type': 'main',
'config_data': json.dumps(test_config)
}, timeout=10)
if response.status_code == 200:
print("✓ Main configuration saved successfully")
else:
print(f"✗ Main configuration failed: {response.status_code}")
except Exception as e:
print(f"✗ Error saving main config: {e}")
# Test 4: Test secrets configuration save
print("\nTesting secrets configuration save...")
test_secrets = {
"weather": {
"api_key": "test_api_key_123"
},
"youtube": {
"api_key": "test_youtube_key",
"channel_id": "test_channel"
},
"music": {
"SPOTIFY_CLIENT_ID": "test_spotify_id",
"SPOTIFY_CLIENT_SECRET": "test_spotify_secret",
"SPOTIFY_REDIRECT_URI": "http://127.0.0.1:8888/callback"
}
}
try:
response = requests.post(f"{base_url}/save_config", data={
'config_type': 'secrets',
'config_data': json.dumps(test_secrets)
}, timeout=10)
if response.status_code == 200:
print("✓ Secrets configuration saved successfully")
else:
print(f"✗ Secrets configuration failed: {response.status_code}")
except Exception as e:
print(f"✗ Error saving secrets: {e}")
# Test 5: Test action execution
print("\nTesting action execution...")
try:
response = requests.post(f"{base_url}/run_action",
json={'action': 'git_pull'},
timeout=15)
if response.status_code == 200:
result = response.json()
print(f"✓ Action executed: {result.get('status', 'unknown')}")
if result.get('stderr'):
print(f" Note: {result['stderr']}")
else:
print(f"✗ Action execution failed: {response.status_code}")
except Exception as e:
print(f"✗ Error executing action: {e}")
print("\n" + "=" * 50)
print("Web interface testing completed!")
print("\nTo start the web interface:")
print("1. Make sure you're on the Raspberry Pi")
print("2. Run: python3 web_interface.py")
print("3. Open a web browser and go to: http://[PI_IP]:5000")
print("\nFeatures available:")
print("- Schedule configuration")
print("- Display hardware settings")
print("- Sports team configuration")
print("- Weather settings")
print("- Stocks & crypto configuration")
print("- Music settings")
print("- Calendar configuration")
print("- API key management")
print("- System actions (start/stop display, etc.)")
return True
if __name__ == "__main__":
success = test_web_interface()
sys.exit(0 if success else 1)