Files
LEDMatrix/WIKI_ARCHITECTURE.md
ChuckBuilds 3a81e16490 wiki updates
2025-07-26 18:20:39 -05:00

15 KiB

System Architecture

The LEDMatrix system is built with a modular, extensible architecture that separates concerns and allows for easy maintenance and extension. This guide explains how all components work together.

System Overview

┌─────────────────────────────────────────────────────────────┐
│                    LEDMatrix System                        │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐      │
│  │   Display   │  │   Display   │  │   Display   │      │
│  │ Controller  │  │  Manager    │  │  Managers   │      │
│  │             │  │             │  │             │      │
│  │ • Main Loop │  │ • Hardware  │  │ • Weather   │      │
│  │ • Rotation  │  │ • Rendering │  │ • Stocks    │      │
│  │ • Scheduling│  │ • Fonts     │  │ • Sports    │      │
│  │ • Live Mode │  │ • Graphics  │  │ • Music     │      │
│  └─────────────┘  └─────────────┘  └─────────────┘      │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐      │
│  │   Config    │  │   Cache     │  │   Web       │      │
│  │  Manager    │  │  Manager    │  │ Interface   │      │
│  │             │  │             │  │             │      │
│  │ • Settings  │  │ • Data      │  │ • Control   │      │
│  │ • Validation│  │ • Persistence│  │ • Status    │      │
│  │ • Loading   │  │ • Fallbacks │  │ • Settings  │      │
│  └─────────────┘  └─────────────┘  └─────────────┘      │
└─────────────────────────────────────────────────────────────┘

Core Components

1. Display Controller (src/display_controller.py)

Purpose: Main orchestrator that manages the entire display system.

Responsibilities:

  • Initialize all display managers
  • Control display rotation and timing
  • Handle live game priority
  • Manage system scheduling
  • Coordinate data updates
  • Handle error recovery

Key Methods:

class DisplayController:
    def __init__(self):
        # Initialize all managers and configuration
        
    def run(self):
        # Main display loop
        
    def _update_modules(self):
        # Update all enabled modules
        
    def _check_live_games(self):
        # Check for live games and prioritize
        
    def _rotate_team_games(self, sport):
        # Rotate through team games

Data Flow:

  1. Load configuration
  2. Initialize display managers
  3. Start main loop
  4. Check for live games
  5. Rotate through enabled displays
  6. Handle scheduling and timing

2. Display Manager (src/display_manager.py)

Purpose: Low-level hardware interface and graphics rendering.

Responsibilities:

  • Initialize RGB LED matrix hardware
  • Handle font loading and management
  • Provide drawing primitives
  • Manage display buffers
  • Handle hardware configuration
  • Provide text rendering utilities

Key Features:

class DisplayManager:
    def __init__(self, config):
        # Initialize hardware and fonts
        
    def draw_text(self, text, x, y, color, font):
        # Draw text on display
        
    def update_display(self):
        # Update physical display
        
    def clear(self):
        # Clear display
        
    def draw_weather_icon(self, condition, x, y, size):
        # Draw weather icons

Hardware Interface:

  • RGB Matrix library integration
  • GPIO pin management
  • PWM timing control
  • Double buffering for smooth updates
  • Font rendering (TTF and BDF)

3. Configuration Manager (src/config_manager.py)

Purpose: Load, validate, and manage system configuration.

Responsibilities:

  • Load JSON configuration files
  • Validate configuration syntax
  • Provide default values
  • Handle configuration updates
  • Manage secrets and API keys

Configuration Sources:

class ConfigManager:
    def load_config(self):
        # Load main config.json
        
    def load_secrets(self):
        # Load config_secrets.json
        
    def validate_config(self):
        # Validate configuration
        
    def get_defaults(self):
        # Provide default values

Configuration Structure:

  • Main settings in config/config.json
  • API keys in config/config_secrets.json
  • Validation and error handling
  • Default value fallbacks

4. Cache Manager (src/cache_manager.py)

Purpose: Intelligent data caching to reduce API calls and improve performance.

Responsibilities:

  • Store API responses
  • Manage cache expiration
  • Handle cache persistence
  • Provide fallback data
  • Optimize storage usage

Cache Strategy:

class CacheManager:
    def get(self, key):
        # Retrieve cached data
        
    def set(self, key, data, ttl):
        # Store data with expiration
        
    def is_valid(self, key):
        # Check if cache is still valid
        
    def clear_expired(self):
        # Remove expired cache entries

Cache Locations (in order of preference):

  1. ~/.ledmatrix_cache/ (user's home directory)
  2. /var/cache/ledmatrix/ (system cache directory)
  3. /tmp/ledmatrix_cache/ (temporary directory)

Display Manager Architecture

Manager Interface

All display managers follow a consistent interface:

class BaseManager:
    def __init__(self, config, display_manager):
        self.config = config
        self.display_manager = display_manager
        self.cache_manager = CacheManager()
        
    def update_data(self):
        """Fetch and process new data"""
        pass
        
    def display(self, force_clear=False):
        """Render content to display"""
        pass
        
    def is_enabled(self):
        """Check if manager is enabled"""
        return self.config.get('enabled', False)
        
    def get_duration(self):
        """Get display duration"""
        return self.config.get('duration', 30)

Data Flow Pattern

Each manager follows this pattern:

  1. Initialization: Load configuration and setup
  2. Data Fetching: Retrieve data from APIs or local sources
  3. Caching: Store data using CacheManager
  4. Processing: Transform raw data into display format
  5. Rendering: Use DisplayManager to show content
  6. Cleanup: Return control to main controller

Error Handling

  • API Failures: Fall back to cached data
  • Network Issues: Use last known good data
  • Invalid Data: Filter out bad entries
  • Hardware Errors: Graceful degradation
  • Configuration Errors: Use safe defaults

Sports Manager Architecture

Sports Manager Pattern

Each sport follows a three-manager pattern:

# Live games (currently playing)
class NHLLiveManager(BaseSportsManager):
    def fetch_games(self):
        # Get currently playing games
        
    def display_games(self):
        # Show live scores and status

# Recent games (completed)
class NHLRecentManager(BaseSportsManager):
    def fetch_games(self):
        # Get recently completed games
        
    def display_games(self):
        # Show final scores

# Upcoming games (scheduled)
class NHLUpcomingManager(BaseSportsManager):
    def fetch_games(self):
        # Get scheduled games
        
    def display_games(self):
        # Show game times and matchups

Base Sports Manager

Common functionality shared by all sports:

class BaseSportsManager:
    def __init__(self, config, display_manager):
        # Common initialization
        
    def fetch_espn_data(self, sport, endpoint):
        # Fetch from ESPN API
        
    def process_game_data(self, games):
        # Process raw game data
        
    def display_game(self, game):
        # Display individual game
        
    def get_team_logo(self, team_abbr):
        # Load team logo
        
    def format_score(self, score):
        # Format score display

ESPN API Integration

All sports use ESPN's API for data:

def fetch_espn_data(self, sport, endpoint):
    url = f"http://site.api.espn.com/apis/site/v2/sports/{sport}/{endpoint}"
    response = requests.get(url)
    return response.json()

Supported Sports:

  • NHL (hockey)
  • NBA (basketball)
  • MLB (baseball)
  • NFL (football)
  • NCAA Football
  • NCAA Basketball
  • NCAA Baseball
  • Soccer (multiple leagues)
  • MiLB (minor league baseball)

Financial Data Architecture

Stock Manager

class StockManager:
    def __init__(self, config, display_manager):
        # Initialize stock and crypto settings
        
    def fetch_stock_data(self, symbol):
        # Fetch from Yahoo Finance
        
    def fetch_crypto_data(self, symbol):
        # Fetch crypto data
        
    def display_stocks(self):
        # Show stock ticker
        
    def display_crypto(self):
        # Show crypto prices

Stock News Manager

class StockNewsManager:
    def __init__(self, config, display_manager):
        # Initialize news settings
        
    def fetch_news(self, symbols):
        # Fetch financial news
        
    def display_news(self):
        # Show news headlines

Weather Architecture

Weather Manager

class WeatherManager:
    def __init__(self, config, display_manager):
        # Initialize weather settings
        
    def fetch_weather(self):
        # Fetch from OpenWeatherMap
        
    def display_current_weather(self):
        # Show current conditions
        
    def display_hourly_forecast(self):
        # Show hourly forecast
        
    def display_daily_forecast(self):
        # Show daily forecast

Weather Icons

class WeatherIcons:
    def __init__(self):
        # Load weather icon definitions
        
    def get_icon(self, condition):
        # Get icon for weather condition
        
    def draw_icon(self, condition, x, y, size):
        # Draw weather icon

Music Architecture

Music Manager

class MusicManager:
    def __init__(self, display_manager, config):
        # Initialize music settings
        
    def start_polling(self):
        # Start background polling
        
    def update_music_display(self):
        # Update music information
        
    def display_spotify(self):
        # Display Spotify info
        
    def display_ytm(self):
        # Display YouTube Music info

Spotify Client

class SpotifyClient:
    def __init__(self, config):
        # Initialize Spotify API
        
    def authenticate(self):
        # Handle OAuth authentication
        
    def get_current_track(self):
        # Get currently playing track

YouTube Music Client

class YTMClient:
    def __init__(self, config):
        # Initialize YTM companion server
        
    def get_current_track(self):
        # Get current track from YTMD

Web Interface Architecture

Web Interface

class WebInterface:
    def __init__(self, config):
        # Initialize Flask app
        
    def start_server(self):
        # Start web server
        
    def get_status(self):
        # Get system status
        
    def control_display(self, action):
        # Control display actions

Features:

  • System status monitoring
  • Display control (start/stop)
  • Configuration management
  • Service management
  • Real-time status updates

Service Architecture

Systemd Service

[Unit]
Description=LEDMatrix Display Service
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/home/ledpi/LEDMatrix
ExecStart=/usr/bin/python3 display_controller.py
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

Service Features:

  • Automatic startup
  • Crash recovery
  • Log management
  • Resource monitoring

Data Flow Architecture

1. Configuration Loading

config.json → ConfigManager → DisplayController → Display Managers

2. Data Fetching

API Sources → CacheManager → Display Managers → Display Manager

3. Display Rendering

Display Managers → Display Manager → RGB Matrix → LED Display

4. User Control

Web Interface → Display Controller → Display Managers

Performance Architecture

Caching Strategy

  1. API Response Caching: Store API responses with TTL
  2. Processed Data Caching: Cache processed display data
  3. Font Caching: Cache loaded fonts
  4. Image Caching: Cache team logos and icons

Resource Management

  1. Memory Usage: Monitor and optimize memory usage
  2. CPU Usage: Minimize processing overhead
  3. Network Usage: Optimize API calls
  4. Storage Usage: Manage cache storage

Error Recovery

  1. API Failures: Use cached data
  2. Network Issues: Retry with exponential backoff
  3. Hardware Errors: Graceful degradation
  4. Configuration Errors: Use safe defaults

Extension Architecture

Adding New Display Managers

  1. Create Manager Class: Extend base manager pattern
  2. Add Configuration: Add to config.json
  3. Register in Controller: Add to DisplayController
  4. Add Assets: Include logos, icons, fonts
  5. Test Integration: Verify with main system

Example New Manager

class CustomManager(BaseManager):
    def __init__(self, config, display_manager):
        super().__init__(config, display_manager)
        
    def update_data(self):
        # Fetch custom data
        
    def display(self, force_clear=False):
        # Display custom content

Security Architecture

API Key Management

  1. Separate Secrets: Store in config_secrets.json
  2. Environment Variables: Support for env vars
  3. Access Control: Restrict file permissions
  4. Key Rotation: Support for key updates

Network Security

  1. HTTPS Only: Use secure API endpoints
  2. Rate Limiting: Respect API limits
  3. Error Handling: Don't expose sensitive data
  4. Logging: Secure log management

Monitoring Architecture

Logging System

import logging

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s:%(name)s:%(message)s'
)

Health Monitoring

  1. API Health: Monitor API availability
  2. Display Health: Monitor display functionality
  3. Cache Health: Monitor cache performance
  4. System Health: Monitor system resources

This architecture provides a solid foundation for the LEDMatrix system while maintaining flexibility for future enhancements and customizations.