mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-04-10 13:02:59 +00:00
wiki changes
This commit is contained in:
51
ubmodule status
Normal file
51
ubmodule status
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
[33m8c03e651[m[33m ([m[1;36mHEAD[m[33m -> [m[1;32mdevelopment[m[33m, [m[1;31morigin/development[m[33m)[m wiki page about team abbreviations
|
||||||
|
[33m764d80e8[m added more missing soccer logos
|
||||||
|
[33m854c236a[m added portuguese soccer league to documentation for soccer manager and added auto-download missing logos for soccer teams
|
||||||
|
[33m4b1b343a[m shift album font down 2 pixels
|
||||||
|
[33m65f04bff[m adjust music manager album text location
|
||||||
|
[33m80558561[m shift of the day description and subtitle down in more situations
|
||||||
|
[33m17a79976[m shift of the day description down one more pixel for total of 4
|
||||||
|
[33m38062d0b[m shift album and artist font down
|
||||||
|
[33m2ce25205[m shift of the day description down one more pixel
|
||||||
|
[33mc7ee9468[m shift music album and artist font down the height of the text font
|
||||||
|
[33m3afcbb75[m add freetype error handling
|
||||||
|
[33mbc182027[m shift of the day underline up one pixel
|
||||||
|
[33ma0973a2a[m shift whole display down 8 pixels
|
||||||
|
[33mc18ab3f9[m dialing of the day text spacing - revert back to too much spacing
|
||||||
|
[33m97185950[m dialing of the day text spacing
|
||||||
|
[33m5f803f34[m dialing of the day text spacing
|
||||||
|
[33m03208307[m of the day manager text refactor
|
||||||
|
[33m9dd74425[m of the day manager text positioning placement fix
|
||||||
|
[33m67b6a6fd[m adjust spacing on of the day manager text
|
||||||
|
[33mca62fd71[m Make sure sports displays are properly processing number of recent games to show
|
||||||
|
[33m49346f9a[m change of the day file path detection
|
||||||
|
[33m9200c9ca[m update logic on all sports displays that upcoming and recent games to show are based on each team, not just the first X # of games found
|
||||||
|
[33mdbdb730b[m fix upcoming game logic for NFL display too
|
||||||
|
[33m91211d5c[m fix upcoming game logic
|
||||||
|
[33md78c592d[m NCAA FB season now downloads in full but it slows down the display significantly, data fetch has been moved to the background and deferred during scrolling displays
|
||||||
|
[33m4771ec8b[m add black buffer behind odds ticker to finish scroll
|
||||||
|
[33m60f68ff2[m add permission handling of the day to first time install script
|
||||||
|
[33mc7634cbf[m NCAA FB odds fix
|
||||||
|
[33m96cd3834[m NCAA FB logging to figure out why recent and upcoming games aren't loading well
|
||||||
|
[33me39dd1e0[m NCAA FB logging
|
||||||
|
[33m7b133963[m of the day try block fix
|
||||||
|
[33m0579b3b8[m more of the day debug logging and fix datetime duplicate in NCAA FB
|
||||||
|
[33me7e76eea[m more robust NCAA FB manager upcoming game check
|
||||||
|
[33m3f431a54[m path resolution for of the day manager
|
||||||
|
[33md0f87859[m troubleshooting of the day manager
|
||||||
|
[33m7618eafa[m troubleshooting of the day manager
|
||||||
|
[33mf8f45390[m hopefully fix of the day settings
|
||||||
|
[33m0ab978d5[m web ui config setting accuracy changes
|
||||||
|
[33mc4a51d0f[m espn api update for NCAAFB
|
||||||
|
[33mb20c3880[m make sure web ui is pulling existing config options
|
||||||
|
[33m652461a8[m ensure leaderboard is in webui
|
||||||
|
[33m691d3967[m web ui bug fixes
|
||||||
|
[33m9bc0cd56[m moving away from dict errors
|
||||||
|
[33m625a501d[m further dict wrapper update
|
||||||
|
[33m28c2dcd2[m fix dict class for web ui
|
||||||
|
[33mc55511c0[m webui changes to launch after config file changes
|
||||||
|
[33mb96f1e39[m make sure web ui save buttons work
|
||||||
|
[33mfcbc6746[m persistent config file via config.template.json and migrate_config.sh
|
||||||
|
[33m4b36937a[m Update sports league logos
|
||||||
|
[33m8ead8ad8[m Fix NCAA Football recent games to show truly recent games (last 14 days) instead of entire season
|
||||||
|
[33mfbff65fb[m fix NCAA FB Quarter logic. Fix -1th and 10 status text when negative yards are received
|
||||||
@@ -1,173 +0,0 @@
|
|||||||
# LEDMatrix Cache Strategy Analysis
|
|
||||||
|
|
||||||
## Current Implementation
|
|
||||||
|
|
||||||
Your LEDMatrix system uses a sophisticated multi-tier caching strategy that balances data freshness with API efficiency.
|
|
||||||
|
|
||||||
### Cache Duration Categories
|
|
||||||
|
|
||||||
#### 1. **Ultra Time-Sensitive Data (15-60 seconds)**
|
|
||||||
- **Live Sports Scores**: Now respects sport-specific `live_update_interval` configuration
|
|
||||||
- Soccer live data: Uses `soccer_scoreboard.live_update_interval` (default: 60 seconds)
|
|
||||||
- NFL live data: Uses `nfl_scoreboard.live_update_interval` (default: 60 seconds)
|
|
||||||
- NHL live data: Uses `nhl_scoreboard.live_update_interval` (default: 60 seconds)
|
|
||||||
- NBA live data: Uses `nba_scoreboard.live_update_interval` (default: 60 seconds)
|
|
||||||
- MLB live data: Uses `mlb.live_update_interval` (default: 60 seconds)
|
|
||||||
- NCAA sports: Use respective `live_update_interval` configurations (default: 60 seconds)
|
|
||||||
- **Current Weather**: 5 minutes (300 seconds)
|
|
||||||
|
|
||||||
#### 2. **Market Data (5-10 minutes)**
|
|
||||||
- **Stocks**: 10 minutes (600 seconds) - market hours aware
|
|
||||||
- **Crypto**: 5 minutes (300 seconds) - 24/7 trading
|
|
||||||
- **Stock News**: 1 hour (3600 seconds)
|
|
||||||
|
|
||||||
#### 3. **Sports Data (5 minutes to 24 hours)**
|
|
||||||
- **Recent Games**: 5 minutes (300 seconds)
|
|
||||||
- **Upcoming Games**: 1 hour (3600 seconds)
|
|
||||||
- **Season Schedules**: 24 hours (86400 seconds)
|
|
||||||
- **Team Information**: 1 week (604800 seconds)
|
|
||||||
|
|
||||||
#### 4. **Static Data (1 week to 30 days)**
|
|
||||||
- **Team Logos**: 30 days (2592000 seconds)
|
|
||||||
- **Configuration Data**: 1 week (604800 seconds)
|
|
||||||
|
|
||||||
### Smart Cache Invalidation
|
|
||||||
|
|
||||||
Beyond time limits, the system uses content-based invalidation:
|
|
||||||
|
|
||||||
```python
|
|
||||||
def has_data_changed(self, data_type: str, new_data: Dict[str, Any]) -> bool:
|
|
||||||
"""Check if data has changed from cached version."""
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Weather**: Compares temperature and conditions
|
|
||||||
- **Stocks**: Compares prices (only during market hours)
|
|
||||||
- **Sports**: Compares scores, game status, inning details
|
|
||||||
- **News**: Compares headlines and article IDs
|
|
||||||
|
|
||||||
### Market-Aware Caching
|
|
||||||
|
|
||||||
For stocks, the system extends cache duration during off-hours:
|
|
||||||
|
|
||||||
```python
|
|
||||||
def _is_market_open(self) -> bool:
|
|
||||||
"""Check if the US stock market is currently open."""
|
|
||||||
# Only invalidates cache during market hours
|
|
||||||
```
|
|
||||||
|
|
||||||
## Enhanced Cache Strategy
|
|
||||||
|
|
||||||
### Sport-Specific Live Update Intervals
|
|
||||||
|
|
||||||
The cache manager now automatically respects the `live_update_interval` configuration for each sport:
|
|
||||||
|
|
||||||
```python
|
|
||||||
def get_sport_live_interval(self, sport_key: str) -> int:
|
|
||||||
"""Get the live_update_interval for a specific sport from config."""
|
|
||||||
config = self.config_manager.get_config()
|
|
||||||
sport_config = config.get(f"{sport_key}_scoreboard", {})
|
|
||||||
return sport_config.get("live_update_interval", 30)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Automatic Sport Detection
|
|
||||||
|
|
||||||
The cache manager automatically detects the sport from cache keys:
|
|
||||||
|
|
||||||
```python
|
|
||||||
def get_sport_key_from_cache_key(self, key: str) -> Optional[str]:
|
|
||||||
"""Extract sport key from cache key to determine appropriate live_update_interval."""
|
|
||||||
# Maps cache key patterns to sport keys
|
|
||||||
sport_patterns = {
|
|
||||||
'nfl': ['nfl', 'football'],
|
|
||||||
'nba': ['nba', 'basketball'],
|
|
||||||
'mlb': ['mlb', 'baseball'],
|
|
||||||
'nhl': ['nhl', 'hockey'],
|
|
||||||
'soccer': ['soccer', 'football'],
|
|
||||||
# ... etc
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Configuration Examples
|
|
||||||
|
|
||||||
**Current Configuration (config/config.json):**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"nfl_scoreboard": {
|
|
||||||
"live_update_interval": 30,
|
|
||||||
"enabled": true
|
|
||||||
},
|
|
||||||
"soccer_scoreboard": {
|
|
||||||
"live_update_interval": 30,
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
"mlb": {
|
|
||||||
"live_update_interval": 30,
|
|
||||||
"enabled": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Cache Behavior:**
|
|
||||||
- NFL live data: 30-second cache (from config)
|
|
||||||
- Soccer live data: 30-second cache (from config)
|
|
||||||
- MLB live data: 30-second cache (from config)
|
|
||||||
|
|
||||||
### Fallback Strategy
|
|
||||||
|
|
||||||
If configuration is unavailable, the system uses sport-specific defaults:
|
|
||||||
|
|
||||||
```python
|
|
||||||
default_intervals = {
|
|
||||||
'soccer': 60, # Soccer default
|
|
||||||
'nfl': 60, # NFL default
|
|
||||||
'nhl': 60, # NHL default
|
|
||||||
'nba': 60, # NBA default
|
|
||||||
'mlb': 60, # MLB default
|
|
||||||
'milb': 60, # Minor league default
|
|
||||||
'ncaa_fb': 60, # College football default
|
|
||||||
'ncaa_baseball': 60, # College baseball default
|
|
||||||
'ncaam_basketball': 60, # College basketball default
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage Examples
|
|
||||||
|
|
||||||
### Automatic Sport Detection
|
|
||||||
```python
|
|
||||||
# Cache manager automatically detects NFL and uses nfl_scoreboard.live_update_interval
|
|
||||||
cached_data = cache_manager.get_with_auto_strategy("nfl_live_20241201")
|
|
||||||
|
|
||||||
# Cache manager automatically detects soccer and uses soccer_scoreboard.live_update_interval
|
|
||||||
cached_data = cache_manager.get_with_auto_strategy("soccer_live_20241201")
|
|
||||||
```
|
|
||||||
|
|
||||||
### Manual Sport Specification
|
|
||||||
```python
|
|
||||||
# Explicitly specify sport for custom cache keys
|
|
||||||
cached_data = cache_manager.get_cached_data_with_strategy("custom_live_key", "sports_live")
|
|
||||||
```
|
|
||||||
|
|
||||||
## Benefits
|
|
||||||
|
|
||||||
1. **Configuration-Driven**: Cache respects your sport-specific settings
|
|
||||||
2. **Automatic Detection**: No manual cache duration management needed
|
|
||||||
3. **Sport-Optimized**: Each sport uses its appropriate update interval
|
|
||||||
4. **Backward Compatible**: Existing code continues to work
|
|
||||||
5. **Flexible**: Easy to adjust intervals per sport in config
|
|
||||||
|
|
||||||
## Migration
|
|
||||||
|
|
||||||
The enhanced cache manager is backward compatible. Existing code will automatically benefit from sport-specific intervals without any changes needed.
|
|
||||||
|
|
||||||
To customize intervals for specific sports, simply update the `live_update_interval` in your `config/config.json`:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"nfl_scoreboard": {
|
|
||||||
"live_update_interval": 15 // More aggressive for NFL
|
|
||||||
},
|
|
||||||
"mlb": {
|
|
||||||
"live_update_interval": 45 // Slower pace for MLB
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
@@ -1,245 +0,0 @@
|
|||||||
# Adding Custom RSS Feeds & Sports - Complete Guide
|
|
||||||
|
|
||||||
This guide shows you **3 different ways** to add custom RSS feeds like F1, MotoGP, or any personal feeds to your news manager.
|
|
||||||
|
|
||||||
## Quick Examples
|
|
||||||
|
|
||||||
### F1 Racing Feeds
|
|
||||||
```bash
|
|
||||||
# BBC F1 (Recommended - works well)
|
|
||||||
python3 add_custom_feed_example.py add "BBC F1" "http://feeds.bbci.co.uk/sport/formula1/rss.xml"
|
|
||||||
|
|
||||||
# Motorsport.com F1
|
|
||||||
python3 add_custom_feed_example.py add "Motorsport F1" "https://www.motorsport.com/rss/f1/news/"
|
|
||||||
|
|
||||||
# Formula1.com Official
|
|
||||||
python3 add_custom_feed_example.py add "F1 Official" "https://www.formula1.com/en/latest/all.xml"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Other Sports
|
|
||||||
```bash
|
|
||||||
# MotoGP
|
|
||||||
python3 add_custom_feed_example.py add "MotoGP" "https://www.motogp.com/en/rss/news"
|
|
||||||
|
|
||||||
# Tennis
|
|
||||||
python3 add_custom_feed_example.py add "Tennis" "https://www.atptour.com/en/rss/news"
|
|
||||||
|
|
||||||
# Golf
|
|
||||||
python3 add_custom_feed_example.py add "Golf" "https://www.pgatour.com/news.rss"
|
|
||||||
|
|
||||||
# Soccer/Football
|
|
||||||
python3 add_custom_feed_example.py add "ESPN Soccer" "https://www.espn.com/espn/rss/soccer/news"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Personal/Blog Feeds
|
|
||||||
```bash
|
|
||||||
# Personal blog
|
|
||||||
python3 add_custom_feed_example.py add "My Blog" "https://myblog.com/rss.xml"
|
|
||||||
|
|
||||||
# Tech news
|
|
||||||
python3 add_custom_feed_example.py add "TechCrunch" "https://techcrunch.com/feed/"
|
|
||||||
|
|
||||||
# Local news
|
|
||||||
python3 add_custom_feed_example.py add "Local News" "https://localnews.com/rss"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Method 1: Command Line (Easiest)
|
|
||||||
|
|
||||||
### Add a Feed
|
|
||||||
```bash
|
|
||||||
python3 add_custom_feed_example.py add "FEED_NAME" "RSS_URL"
|
|
||||||
```
|
|
||||||
|
|
||||||
### List All Feeds
|
|
||||||
```bash
|
|
||||||
python3 add_custom_feed_example.py list
|
|
||||||
```
|
|
||||||
|
|
||||||
### Remove a Feed
|
|
||||||
```bash
|
|
||||||
python3 add_custom_feed_example.py remove "FEED_NAME"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Example: Adding F1
|
|
||||||
```bash
|
|
||||||
# Step 1: Check current feeds
|
|
||||||
python3 add_custom_feed_example.py list
|
|
||||||
|
|
||||||
# Step 2: Add BBC F1 feed
|
|
||||||
python3 add_custom_feed_example.py add "BBC F1" "http://feeds.bbci.co.uk/sport/formula1/rss.xml"
|
|
||||||
|
|
||||||
# Step 3: Verify it was added
|
|
||||||
python3 add_custom_feed_example.py list
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Method 2: Web Interface
|
|
||||||
|
|
||||||
1. **Open Web Interface**: Go to `http://your-display-ip:5001`
|
|
||||||
2. **Navigate to News Tab**: Click the "News Manager" tab
|
|
||||||
3. **Add Custom Feed**:
|
|
||||||
- Enter feed name in "Feed Name" field (e.g., "BBC F1")
|
|
||||||
- Enter RSS URL in "RSS Feed URL" field
|
|
||||||
- Click "Add Feed" button
|
|
||||||
4. **Enable the Feed**: Check the checkbox next to your new feed
|
|
||||||
5. **Save Settings**: Click "Save News Settings"
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Method 3: Direct Config Edit
|
|
||||||
|
|
||||||
Edit `config/config.json` directly:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"news_manager": {
|
|
||||||
"enabled": true,
|
|
||||||
"enabled_feeds": ["NFL", "NCAA FB", "BBC F1"],
|
|
||||||
"custom_feeds": {
|
|
||||||
"BBC F1": "http://feeds.bbci.co.uk/sport/formula1/rss.xml",
|
|
||||||
"Motorsport F1": "https://www.motorsport.com/rss/f1/news/",
|
|
||||||
"My Blog": "https://myblog.com/rss.xml"
|
|
||||||
},
|
|
||||||
"headlines_per_feed": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Finding RSS Feeds
|
|
||||||
|
|
||||||
### Popular Sports RSS Feeds
|
|
||||||
|
|
||||||
| Sport | Source | RSS URL |
|
|
||||||
|-------|--------|---------|
|
|
||||||
| **F1** | BBC Sport | `http://feeds.bbci.co.uk/sport/formula1/rss.xml` |
|
|
||||||
| **F1** | Motorsport.com | `https://www.motorsport.com/rss/f1/news/` |
|
|
||||||
| **MotoGP** | Official | `https://www.motogp.com/en/rss/news` |
|
|
||||||
| **Tennis** | ATP Tour | `https://www.atptour.com/en/rss/news` |
|
|
||||||
| **Golf** | PGA Tour | `https://www.pgatour.com/news.rss` |
|
|
||||||
| **Soccer** | ESPN | `https://www.espn.com/espn/rss/soccer/news` |
|
|
||||||
| **Boxing** | ESPN | `https://www.espn.com/espn/rss/boxing/news` |
|
|
||||||
| **UFC/MMA** | ESPN | `https://www.espn.com/espn/rss/mma/news` |
|
|
||||||
|
|
||||||
### How to Find RSS Feeds
|
|
||||||
1. **Look for RSS icons** on websites
|
|
||||||
2. **Check `/rss`, `/feed`, or `/rss.xml`** paths
|
|
||||||
3. **Use RSS discovery tools** like RSS Feed Finder
|
|
||||||
4. **Check site footers** for RSS links
|
|
||||||
|
|
||||||
### Testing RSS Feeds
|
|
||||||
```bash
|
|
||||||
# Test if a feed works before adding it
|
|
||||||
python3 -c "
|
|
||||||
import feedparser
|
|
||||||
import requests
|
|
||||||
url = 'YOUR_RSS_URL_HERE'
|
|
||||||
try:
|
|
||||||
response = requests.get(url, timeout=10)
|
|
||||||
feed = feedparser.parse(response.content)
|
|
||||||
print(f'SUCCESS: Feed works! Title: {feed.feed.get(\"title\", \"N/A\")}')
|
|
||||||
print(f'{len(feed.entries)} articles found')
|
|
||||||
if feed.entries:
|
|
||||||
print(f'Latest: {feed.entries[0].title}')
|
|
||||||
except Exception as e:
|
|
||||||
print(f'ERROR: {e}')
|
|
||||||
"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Advanced Configuration
|
|
||||||
|
|
||||||
### Controlling Feed Behavior
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"news_manager": {
|
|
||||||
"headlines_per_feed": 3, // Headlines from each feed
|
|
||||||
"scroll_speed": 2, // Pixels per frame
|
|
||||||
"scroll_delay": 0.02, // Seconds between updates
|
|
||||||
"rotation_enabled": true, // Rotate content to avoid repetition
|
|
||||||
"rotation_threshold": 3, // Cycles before rotating
|
|
||||||
"update_interval": 300 // Seconds between feed updates
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Feed Priority
|
|
||||||
Feeds are displayed in the order they appear in `enabled_feeds`:
|
|
||||||
```json
|
|
||||||
"enabled_feeds": ["NFL", "BBC F1", "NCAA FB"] // NFL first, then F1, then NCAA
|
|
||||||
```
|
|
||||||
|
|
||||||
### Custom Display Names
|
|
||||||
You can use any display name for feeds:
|
|
||||||
```bash
|
|
||||||
python3 add_custom_feed_example.py add "Formula 1" "http://feeds.bbci.co.uk/sport/formula1/rss.xml"
|
|
||||||
python3 add_custom_feed_example.py add "Basketball News" "https://www.espn.com/espn/rss/nba/news"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Feed Not Working?
|
|
||||||
1. **Test the RSS URL** using the testing command above
|
|
||||||
2. **Check for HTTPS vs HTTP** - some feeds require secure connections
|
|
||||||
3. **Verify the feed format** - must be valid RSS or Atom
|
|
||||||
4. **Check rate limiting** - some sites block frequent requests
|
|
||||||
|
|
||||||
### Common Issues
|
|
||||||
- **403 Forbidden**: Site blocks automated requests (try different feed)
|
|
||||||
- **SSL Errors**: Use HTTP instead of HTTPS if available
|
|
||||||
- **No Content**: Feed might be empty or incorrectly formatted
|
|
||||||
- **Slow Loading**: Increase timeout in news manager settings
|
|
||||||
|
|
||||||
### Feed Alternatives
|
|
||||||
If one feed doesn't work, try alternatives:
|
|
||||||
- **ESPN feeds** sometimes have access restrictions
|
|
||||||
- **BBC feeds** are generally reliable
|
|
||||||
- **Official sport websites** often have RSS feeds
|
|
||||||
- **News aggregators** like Google News have topic-specific feeds
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Real-World Example: Complete F1 Setup
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. List current setup
|
|
||||||
python3 add_custom_feed_example.py list
|
|
||||||
|
|
||||||
# 2. Add multiple F1 sources for better coverage
|
|
||||||
python3 add_custom_feed_example.py add "BBC F1" "http://feeds.bbci.co.uk/sport/formula1/rss.xml"
|
|
||||||
python3 add_custom_feed_example.py add "Motorsport F1" "https://www.motorsport.com/rss/f1/news/"
|
|
||||||
|
|
||||||
# 3. Add other racing series
|
|
||||||
python3 add_custom_feed_example.py add "MotoGP" "https://www.motogp.com/en/rss/news"
|
|
||||||
|
|
||||||
# 4. Verify all feeds work
|
|
||||||
python3 simple_news_test.py
|
|
||||||
|
|
||||||
# 5. Check final configuration
|
|
||||||
python3 add_custom_feed_example.py list
|
|
||||||
```
|
|
||||||
|
|
||||||
Result: Your display will now rotate between NFL, NCAA FB, BBC F1, Motorsport F1, and MotoGP headlines!
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Pro Tips
|
|
||||||
|
|
||||||
1. **Start Small**: Add one feed at a time and test it
|
|
||||||
2. **Mix Sources**: Use multiple sources for the same sport for better coverage
|
|
||||||
3. **Monitor Performance**: Too many feeds can slow down updates
|
|
||||||
4. **Use Descriptive Names**: "BBC F1" is better than just "F1"
|
|
||||||
5. **Test Regularly**: RSS feeds can change or break over time
|
|
||||||
6. **Backup Config**: Save your `config.json` before making changes
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Need help?** The news manager is designed to be flexible and user-friendly. Start with the command line method - it's the easiest way to get started!
|
|
||||||
@@ -1,177 +0,0 @@
|
|||||||
# Dynamic Duration Feature - Complete Guide
|
|
||||||
|
|
||||||
The news manager now includes intelligent **dynamic duration calculation** that automatically determines the exact time needed to display all your selected headlines without cutting off mid-scroll.
|
|
||||||
|
|
||||||
## How It Works
|
|
||||||
|
|
||||||
### Automatic Calculation
|
|
||||||
The system calculates the perfect display duration by:
|
|
||||||
|
|
||||||
1. **Measuring Text Width**: Calculates the exact pixel width of all headlines combined
|
|
||||||
2. **Computing Scroll Distance**: Determines how far text needs to scroll (display width + text width)
|
|
||||||
3. **Calculating Time**: Uses scroll speed and delay to compute exact timing
|
|
||||||
4. **Adding Buffer**: Includes configurable buffer time for smooth transitions
|
|
||||||
5. **Applying Limits**: Ensures duration stays within your min/max preferences
|
|
||||||
|
|
||||||
### Real-World Example
|
|
||||||
With current settings (4 feeds, 2 headlines each):
|
|
||||||
- **Total Headlines**: 8 headlines per cycle
|
|
||||||
- **Estimated Duration**: 57 seconds
|
|
||||||
- **Cycles per Hour**: ~63 cycles
|
|
||||||
- **Result**: Perfect timing, no cut-offs
|
|
||||||
|
|
||||||
## Configuration Options
|
|
||||||
|
|
||||||
### Core Settings
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"news_manager": {
|
|
||||||
"dynamic_duration": true, // Enable/disable feature
|
|
||||||
"min_duration": 30, // Minimum display time (seconds)
|
|
||||||
"max_duration": 300, // Maximum display time (seconds)
|
|
||||||
"duration_buffer": 0.1, // Buffer time (10% extra)
|
|
||||||
"headlines_per_feed": 2, // Headlines from each feed
|
|
||||||
"scroll_speed": 2, // Pixels per frame
|
|
||||||
"scroll_delay": 0.02 // Seconds per frame
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Duration Scenarios
|
|
||||||
|
|
||||||
| Scenario | Headlines | Est. Duration | Cycles/Hour |
|
|
||||||
|----------|-----------|---------------|-------------|
|
|
||||||
| **Light** | 4 headlines | 30s (min) | 120 |
|
|
||||||
| **Medium** | 6 headlines | 30s (min) | 120 |
|
|
||||||
| **Current** | 8 headlines | 57s | 63 |
|
|
||||||
| **Heavy** | 12 headlines | 85s | 42 |
|
|
||||||
| **Maximum** | 20+ headlines | 300s (max) | 12 |
|
|
||||||
|
|
||||||
## Benefits
|
|
||||||
|
|
||||||
### Perfect Timing
|
|
||||||
- **No Cut-offs**: Headlines never cut off mid-sentence
|
|
||||||
- **Complete Cycles**: Always shows full rotation of all selected content
|
|
||||||
- **Smooth Transitions**: Buffer time prevents jarring switches
|
|
||||||
|
|
||||||
### Intelligent Scaling
|
|
||||||
- **Adapts to Content**: More feeds = longer duration automatically
|
|
||||||
- **User Control**: Set your preferred min/max limits
|
|
||||||
- **Flexible**: Works with any combination of feeds and headlines
|
|
||||||
|
|
||||||
### Predictable Behavior
|
|
||||||
- **Consistent Experience**: Same content always takes same time
|
|
||||||
- **Reliable Cycling**: Know exactly when content will repeat
|
|
||||||
- **Configurable**: Adjust to your viewing preferences
|
|
||||||
|
|
||||||
## Usage Examples
|
|
||||||
|
|
||||||
### Command Line Testing
|
|
||||||
```bash
|
|
||||||
# Test dynamic duration calculations
|
|
||||||
python3 test_dynamic_duration.py
|
|
||||||
|
|
||||||
# Check current status
|
|
||||||
python3 test_dynamic_duration.py status
|
|
||||||
```
|
|
||||||
|
|
||||||
### Configuration Changes
|
|
||||||
```bash
|
|
||||||
# Add more feeds (increases duration)
|
|
||||||
python3 add_custom_feed_example.py add "Tennis" "https://www.atptour.com/en/rss/news"
|
|
||||||
|
|
||||||
# Check new duration
|
|
||||||
python3 test_dynamic_duration.py status
|
|
||||||
```
|
|
||||||
|
|
||||||
### Web Interface
|
|
||||||
1. Go to `http://display-ip:5001`
|
|
||||||
2. Click "News Manager" tab
|
|
||||||
3. Adjust "Duration Settings":
|
|
||||||
- **Min Duration**: Shortest acceptable cycle time
|
|
||||||
- **Max Duration**: Longest acceptable cycle time
|
|
||||||
- **Buffer**: Extra time for smooth transitions
|
|
||||||
|
|
||||||
## Advanced Configuration
|
|
||||||
|
|
||||||
### Fine-Tuning Duration
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"min_duration": 45, // Increase for longer minimum cycles
|
|
||||||
"max_duration": 180, // Decrease for shorter maximum cycles
|
|
||||||
"duration_buffer": 0.15 // Increase buffer for more transition time
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Scroll Speed Impact
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"scroll_speed": 3, // Faster scroll = shorter duration
|
|
||||||
"scroll_delay": 0.015 // Less delay = shorter duration
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Content Control
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"headlines_per_feed": 3, // More headlines = longer duration
|
|
||||||
"enabled_feeds": [ // More feeds = longer duration
|
|
||||||
"NFL", "NBA", "MLB", "NHL", "BBC F1", "Tennis"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Duration Too Short
|
|
||||||
- **Increase** `min_duration`
|
|
||||||
- **Add** more feeds or headlines per feed
|
|
||||||
- **Decrease** `scroll_speed`
|
|
||||||
|
|
||||||
### Duration Too Long
|
|
||||||
- **Decrease** `max_duration`
|
|
||||||
- **Remove** some feeds
|
|
||||||
- **Reduce** `headlines_per_feed`
|
|
||||||
- **Increase** `scroll_speed`
|
|
||||||
|
|
||||||
### Jerky Transitions
|
|
||||||
- **Increase** `duration_buffer`
|
|
||||||
- **Adjust** `scroll_delay`
|
|
||||||
|
|
||||||
## Disable Dynamic Duration
|
|
||||||
|
|
||||||
To use fixed timing instead:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"dynamic_duration": false,
|
|
||||||
"fixed_duration": 60 // Fixed 60-second cycles
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Technical Details
|
|
||||||
|
|
||||||
### Calculation Formula
|
|
||||||
```
|
|
||||||
total_scroll_distance = display_width + text_width
|
|
||||||
frames_needed = total_scroll_distance / scroll_speed
|
|
||||||
base_time = frames_needed * scroll_delay
|
|
||||||
buffer_time = base_time * duration_buffer
|
|
||||||
final_duration = base_time + buffer_time (within min/max limits)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Display Integration
|
|
||||||
The display controller automatically:
|
|
||||||
1. Calls `news_manager.get_dynamic_duration()`
|
|
||||||
2. Uses returned value for display timing
|
|
||||||
3. Switches to next mode after exact calculated time
|
|
||||||
4. Logs duration decisions for debugging
|
|
||||||
|
|
||||||
## Best Practices
|
|
||||||
|
|
||||||
1. **Start Conservative**: Use default settings initially
|
|
||||||
2. **Test Changes**: Use test script to preview duration changes
|
|
||||||
3. **Monitor Performance**: Watch for smooth transitions
|
|
||||||
4. **Adjust Gradually**: Make small changes to settings
|
|
||||||
5. **Consider Viewing**: Match duration to your typical viewing patterns
|
|
||||||
|
|
||||||
The dynamic duration feature ensures your news ticker always displays complete, perfectly-timed content cycles regardless of how many feeds or headlines you configure!
|
|
||||||
@@ -1,189 +0,0 @@
|
|||||||
# Dynamic Duration Implementation for Stocks and Stock News
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
This document describes the implementation of dynamic duration functionality for the `stock_manager` and `stock_news_manager` classes, following the same pattern as the existing `news_manager`.
|
|
||||||
|
|
||||||
## What Was Implemented
|
|
||||||
|
|
||||||
### 1. Configuration Updates
|
|
||||||
|
|
||||||
Added dynamic duration settings to both `stocks` and `stock_news` sections in `config/config.json`:
|
|
||||||
|
|
||||||
```json
|
|
||||||
"stocks": {
|
|
||||||
"enabled": true,
|
|
||||||
"update_interval": 600,
|
|
||||||
"scroll_speed": 1,
|
|
||||||
"scroll_delay": 0.01,
|
|
||||||
"toggle_chart": true,
|
|
||||||
"dynamic_duration": true,
|
|
||||||
"min_duration": 30,
|
|
||||||
"max_duration": 300,
|
|
||||||
"duration_buffer": 0.1,
|
|
||||||
"symbols": [...],
|
|
||||||
"display_format": "{symbol}: ${price} ({change}%)"
|
|
||||||
},
|
|
||||||
"stock_news": {
|
|
||||||
"enabled": true,
|
|
||||||
"update_interval": 3600,
|
|
||||||
"scroll_speed": 1,
|
|
||||||
"scroll_delay": 0.01,
|
|
||||||
"max_headlines_per_symbol": 1,
|
|
||||||
"headlines_per_rotation": 2,
|
|
||||||
"dynamic_duration": true,
|
|
||||||
"min_duration": 30,
|
|
||||||
"max_duration": 300,
|
|
||||||
"duration_buffer": 0.1
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Stock Manager Updates (`src/stock_manager.py`)
|
|
||||||
|
|
||||||
#### Added Dynamic Duration Properties
|
|
||||||
```python
|
|
||||||
# Dynamic duration settings
|
|
||||||
self.dynamic_duration_enabled = self.stocks_config.get('dynamic_duration', True)
|
|
||||||
self.min_duration = self.stocks_config.get('min_duration', 30)
|
|
||||||
self.max_duration = self.stocks_config.get('max_duration', 300)
|
|
||||||
self.duration_buffer = self.stocks_config.get('duration_buffer', 0.1)
|
|
||||||
self.dynamic_duration = 60 # Default duration in seconds
|
|
||||||
self.total_scroll_width = 0 # Track total width for dynamic duration calculation
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Added `calculate_dynamic_duration()` Method
|
|
||||||
This method calculates the exact time needed to display all stocks based on:
|
|
||||||
- Total scroll width of the content
|
|
||||||
- Display width
|
|
||||||
- Scroll speed and delay settings
|
|
||||||
- Configurable buffer time
|
|
||||||
- Min/max duration limits
|
|
||||||
|
|
||||||
#### Added `get_dynamic_duration()` Method
|
|
||||||
Returns the calculated dynamic duration for use by the display controller.
|
|
||||||
|
|
||||||
#### Updated `display_stocks()` Method
|
|
||||||
The method now calculates and stores the total scroll width and calls `calculate_dynamic_duration()` when creating the scrolling image.
|
|
||||||
|
|
||||||
### 3. Stock News Manager Updates (`src/stock_news_manager.py`)
|
|
||||||
|
|
||||||
#### Added Dynamic Duration Properties
|
|
||||||
```python
|
|
||||||
# Dynamic duration settings
|
|
||||||
self.dynamic_duration_enabled = self.stock_news_config.get('dynamic_duration', True)
|
|
||||||
self.min_duration = self.stock_news_config.get('min_duration', 30)
|
|
||||||
self.max_duration = self.stock_news_config.get('max_duration', 300)
|
|
||||||
self.duration_buffer = self.stock_news_config.get('duration_buffer', 0.1)
|
|
||||||
self.dynamic_duration = 60 # Default duration in seconds
|
|
||||||
self.total_scroll_width = 0 # Track total width for dynamic duration calculation
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Added `calculate_dynamic_duration()` Method
|
|
||||||
Similar to the stock manager, calculates duration based on content width and scroll settings.
|
|
||||||
|
|
||||||
#### Added `get_dynamic_duration()` Method
|
|
||||||
Returns the calculated dynamic duration for use by the display controller.
|
|
||||||
|
|
||||||
#### Updated `display_news()` Method
|
|
||||||
The method now calculates and stores the total scroll width and calls `calculate_dynamic_duration()` when creating the scrolling image.
|
|
||||||
|
|
||||||
### 4. Display Controller Updates (`src/display_controller.py`)
|
|
||||||
|
|
||||||
#### Updated `get_current_duration()` Method
|
|
||||||
Added dynamic duration handling for both `stocks` and `stock_news` modes:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Handle dynamic duration for stocks
|
|
||||||
if mode_key == 'stocks' and self.stocks:
|
|
||||||
try:
|
|
||||||
dynamic_duration = self.stocks.get_dynamic_duration()
|
|
||||||
# Only log if duration has changed or we haven't logged this duration yet
|
|
||||||
if not hasattr(self, '_last_logged_duration') or self._last_logged_duration != dynamic_duration:
|
|
||||||
logger.info(f"Using dynamic duration for stocks: {dynamic_duration} seconds")
|
|
||||||
self._last_logged_duration = dynamic_duration
|
|
||||||
return dynamic_duration
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Error getting dynamic duration for stocks: {e}")
|
|
||||||
# Fall back to configured duration
|
|
||||||
return self.display_durations.get(mode_key, 60)
|
|
||||||
|
|
||||||
# Handle dynamic duration for stock_news
|
|
||||||
if mode_key == 'stock_news' and self.news:
|
|
||||||
try:
|
|
||||||
dynamic_duration = self.news.get_dynamic_duration()
|
|
||||||
# Only log if duration has changed or we haven't logged this duration yet
|
|
||||||
if not hasattr(self, '_last_logged_duration') or self._last_logged_duration != dynamic_duration:
|
|
||||||
logger.info(f"Using dynamic duration for stock_news: {dynamic_duration} seconds")
|
|
||||||
self._last_logged_duration = dynamic_duration
|
|
||||||
return dynamic_duration
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Error getting dynamic duration for stock_news: {e}")
|
|
||||||
# Fall back to configured duration
|
|
||||||
return self.display_durations.get(mode_key, 60)
|
|
||||||
```
|
|
||||||
|
|
||||||
## How It Works
|
|
||||||
|
|
||||||
### Dynamic Duration Calculation
|
|
||||||
|
|
||||||
The dynamic duration is calculated using the following formula:
|
|
||||||
|
|
||||||
1. **Total Scroll Distance**: `display_width + total_scroll_width`
|
|
||||||
2. **Frames Needed**: `total_scroll_distance / scroll_speed`
|
|
||||||
3. **Base Time**: `frames_needed * scroll_delay`
|
|
||||||
4. **Buffer Time**: `base_time * duration_buffer`
|
|
||||||
5. **Final Duration**: `int(base_time + buffer_time)`
|
|
||||||
|
|
||||||
The final duration is then clamped between `min_duration` and `max_duration`.
|
|
||||||
|
|
||||||
### Integration with Display Controller
|
|
||||||
|
|
||||||
1. When the display controller needs to determine how long to show a particular mode, it calls `get_current_duration()`
|
|
||||||
2. For `stocks` and `stock_news` modes, it calls the respective manager's `get_dynamic_duration()` method
|
|
||||||
3. The manager returns the calculated duration based on the current content width
|
|
||||||
4. The display controller uses this duration to determine how long to display the content
|
|
||||||
|
|
||||||
### Benefits
|
|
||||||
|
|
||||||
1. **Consistent Display Time**: Content is displayed for an appropriate amount of time based on its length
|
|
||||||
2. **Configurable**: Users can adjust min/max durations and buffer percentages
|
|
||||||
3. **Fallback Support**: If dynamic duration fails, it falls back to configured fixed durations
|
|
||||||
4. **Performance**: Duration is calculated once when content is created, not on every frame
|
|
||||||
|
|
||||||
## Configuration Options
|
|
||||||
|
|
||||||
### Dynamic Duration Settings
|
|
||||||
|
|
||||||
- **`dynamic_duration`**: Enable/disable dynamic duration calculation (default: `true`)
|
|
||||||
- **`min_duration`**: Minimum display duration in seconds (default: `30`)
|
|
||||||
- **`max_duration`**: Maximum display duration in seconds (default: `300`)
|
|
||||||
- **`duration_buffer`**: Buffer percentage to add for smooth cycling (default: `0.1` = 10%)
|
|
||||||
|
|
||||||
### Example Configuration
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"dynamic_duration": true,
|
|
||||||
"min_duration": 20,
|
|
||||||
"max_duration": 180,
|
|
||||||
"duration_buffer": 0.15
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This would:
|
|
||||||
- Enable dynamic duration
|
|
||||||
- Set minimum display time to 20 seconds
|
|
||||||
- Set maximum display time to 3 minutes
|
|
||||||
- Add 15% buffer time for smooth cycling
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
The implementation has been tested to ensure:
|
|
||||||
- Configuration is properly loaded
|
|
||||||
- Dynamic duration calculation works correctly
|
|
||||||
- Display controller integration is functional
|
|
||||||
- Fallback behavior works when dynamic duration is disabled
|
|
||||||
|
|
||||||
## Compatibility
|
|
||||||
|
|
||||||
This implementation follows the exact same pattern as the existing `news_manager` dynamic duration functionality, ensuring consistency across the codebase and making it easy to maintain and extend.
|
|
||||||
@@ -1,146 +0,0 @@
|
|||||||
# Graceful Update System
|
|
||||||
|
|
||||||
The LED Matrix project now includes a graceful update system that prevents lag during scrolling displays by deferring updates until the display is not actively scrolling.
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
When displays like the odds ticker, stock ticker, or news ticker are actively scrolling, performing API updates or data fetching can cause visual lag or stuttering. The graceful update system solves this by:
|
|
||||||
|
|
||||||
1. **Tracking scrolling state** - The system monitors when displays are actively scrolling
|
|
||||||
2. **Deferring updates** - Updates that might cause lag are deferred during scrolling periods
|
|
||||||
3. **Processing when safe** - Deferred updates are processed when scrolling stops or during non-scrolling periods
|
|
||||||
4. **Priority-based execution** - Updates are executed in priority order when processed
|
|
||||||
|
|
||||||
## How It Works
|
|
||||||
|
|
||||||
### Scrolling State Tracking
|
|
||||||
|
|
||||||
The `DisplayManager` class now includes scrolling state tracking:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Signal when scrolling starts
|
|
||||||
display_manager.set_scrolling_state(True)
|
|
||||||
|
|
||||||
# Signal when scrolling stops
|
|
||||||
display_manager.set_scrolling_state(False)
|
|
||||||
|
|
||||||
# Check if currently scrolling
|
|
||||||
if display_manager.is_currently_scrolling():
|
|
||||||
# Defer updates
|
|
||||||
pass
|
|
||||||
```
|
|
||||||
|
|
||||||
### Deferred Updates
|
|
||||||
|
|
||||||
Updates can be deferred using the `defer_update` method:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Defer an update with priority
|
|
||||||
display_manager.defer_update(
|
|
||||||
lambda: self._perform_update(),
|
|
||||||
priority=1 # Lower numbers = higher priority
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Automatic Processing
|
|
||||||
|
|
||||||
Deferred updates are automatically processed when:
|
|
||||||
- A display signals it's not scrolling
|
|
||||||
- The main loop processes updates during non-scrolling periods
|
|
||||||
- The inactivity threshold is reached (default: 2 seconds)
|
|
||||||
|
|
||||||
## Implementation Details
|
|
||||||
|
|
||||||
### Display Manager Changes
|
|
||||||
|
|
||||||
The `DisplayManager` class now includes:
|
|
||||||
|
|
||||||
- `set_scrolling_state(is_scrolling)` - Signal scrolling state changes
|
|
||||||
- `is_currently_scrolling()` - Check if display is currently scrolling
|
|
||||||
- `defer_update(update_func, priority)` - Defer an update function
|
|
||||||
- `process_deferred_updates()` - Process all pending deferred updates
|
|
||||||
- `get_scrolling_stats()` - Get current scrolling statistics
|
|
||||||
|
|
||||||
### Manager Updates
|
|
||||||
|
|
||||||
The following managers have been updated to use the graceful update system:
|
|
||||||
|
|
||||||
#### Odds Ticker Manager
|
|
||||||
- Defers API updates during scrolling
|
|
||||||
- Signals scrolling state during display
|
|
||||||
- Processes deferred updates when not scrolling
|
|
||||||
|
|
||||||
#### Stock Manager
|
|
||||||
- Defers stock data updates during scrolling
|
|
||||||
- Always signals scrolling state (continuous scrolling)
|
|
||||||
- Priority 2 for stock updates
|
|
||||||
|
|
||||||
#### Stock News Manager
|
|
||||||
- Defers news data updates during scrolling
|
|
||||||
- Signals scrolling state during display
|
|
||||||
- Priority 2 for news updates
|
|
||||||
|
|
||||||
### Display Controller Changes
|
|
||||||
|
|
||||||
The main display controller now:
|
|
||||||
- Checks scrolling state before updating modules
|
|
||||||
- Defers scrolling-sensitive updates during scrolling periods
|
|
||||||
- Processes deferred updates in the main loop
|
|
||||||
- Continues non-scrolling-sensitive updates normally
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
The system uses these default settings:
|
|
||||||
|
|
||||||
- **Inactivity threshold**: 2.0 seconds
|
|
||||||
- **Update priorities**:
|
|
||||||
- Priority 1: Odds ticker updates
|
|
||||||
- Priority 2: Stock and news updates
|
|
||||||
- Priority 3+: Other updates
|
|
||||||
|
|
||||||
## Benefits
|
|
||||||
|
|
||||||
1. **Smoother Scrolling** - No more lag during ticker scrolling
|
|
||||||
2. **Better User Experience** - Displays remain responsive during updates
|
|
||||||
3. **Efficient Resource Usage** - Updates happen when the system is idle
|
|
||||||
4. **Priority-Based** - Important updates are processed first
|
|
||||||
5. **Automatic** - No manual intervention required
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
You can test the graceful update system using the provided test script:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python test_graceful_updates.py
|
|
||||||
```
|
|
||||||
|
|
||||||
This script demonstrates:
|
|
||||||
- Deferring updates during scrolling
|
|
||||||
- Processing updates when not scrolling
|
|
||||||
- Priority-based execution
|
|
||||||
- Inactivity threshold behavior
|
|
||||||
|
|
||||||
## Debugging
|
|
||||||
|
|
||||||
To debug the graceful update system, enable debug logging:
|
|
||||||
|
|
||||||
```python
|
|
||||||
import logging
|
|
||||||
logging.getLogger('src.display_manager').setLevel(logging.DEBUG)
|
|
||||||
```
|
|
||||||
|
|
||||||
The system will log:
|
|
||||||
- When scrolling state changes
|
|
||||||
- When updates are deferred
|
|
||||||
- When deferred updates are processed
|
|
||||||
- Current scrolling statistics
|
|
||||||
|
|
||||||
## Future Enhancements
|
|
||||||
|
|
||||||
Potential improvements to the system:
|
|
||||||
|
|
||||||
1. **Configurable thresholds** - Allow users to adjust inactivity thresholds
|
|
||||||
2. **More granular priorities** - Add more priority levels for different update types
|
|
||||||
3. **Update batching** - Group similar updates to reduce processing overhead
|
|
||||||
4. **Performance metrics** - Track and report update deferral statistics
|
|
||||||
5. **Web interface integration** - Show deferred update status in the web UI
|
|
||||||
@@ -1,343 +0,0 @@
|
|||||||
# LED Matrix Installation Guide
|
|
||||||
|
|
||||||
## Quick Start (Recommended for First-Time Installation)
|
|
||||||
|
|
||||||
# System Setup & Installation
|
|
||||||
|
|
||||||
1. Open PowerShell and ssh into your Raspberry Pi with ledpi@ledpi (or Username@Hostname)
|
|
||||||
```bash
|
|
||||||
ssh ledpi@ledpi
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Update repositories, upgrade raspberry pi OS, install git
|
|
||||||
```bash
|
|
||||||
sudo apt update && sudo apt upgrade -y
|
|
||||||
sudo apt install -y git python3-pip cython3 build-essential python3-dev python3-pillow scons
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Clone this repository:
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/ChuckBuilds/LEDMatrix.git
|
|
||||||
cd LEDMatrix
|
|
||||||
```
|
|
||||||
|
|
||||||
4. First-time installation (recommended)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
chmod +x first_time_install.sh
|
|
||||||
sudo ./first_time_install.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
----- Old Instructions left for posterity ------
|
|
||||||
|
|
||||||
4. Install dependencies:
|
|
||||||
```bash
|
|
||||||
sudo pip3 install --break-system-packages -r requirements.txt
|
|
||||||
```
|
|
||||||
--break-system-packages allows us to install without a virtual environment
|
|
||||||
|
|
||||||
|
|
||||||
5. Install rpi-rgb-led-matrix dependencies:
|
|
||||||
```bash
|
|
||||||
cd rpi-rgb-led-matrix-master
|
|
||||||
```
|
|
||||||
```bash
|
|
||||||
sudo make build-python PYTHON=$(which python3)
|
|
||||||
```
|
|
||||||
```bash
|
|
||||||
cd bindings/python
|
|
||||||
sudo python3 setup.py install
|
|
||||||
```
|
|
||||||
Test it with:
|
|
||||||
```bash
|
|
||||||
python3 -c 'from rgbmatrix import RGBMatrix, RGBMatrixOptions; print("Success!")'
|
|
||||||
```
|
|
||||||
|
|
||||||
## Important: Sound Module Configuration
|
|
||||||
|
|
||||||
1. Remove unnecessary services that might interfere with the LED matrix:
|
|
||||||
```bash
|
|
||||||
sudo apt-get remove bluez bluez-firmware pi-bluetooth triggerhappy pigpio
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Blacklist the sound module:
|
|
||||||
```bash
|
|
||||||
cat <<EOF | sudo tee /etc/modprobe.d/blacklist-rgb-matrix.conf
|
|
||||||
blacklist snd_bcm2835
|
|
||||||
EOF
|
|
||||||
```
|
|
||||||
|
|
||||||
then execute
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo update-initramfs -u
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Reboot:
|
|
||||||
```bash
|
|
||||||
sudo reboot
|
|
||||||
```
|
|
||||||
|
|
||||||
## Performance Optimization
|
|
||||||
|
|
||||||
To reduce flickering and improve display quality:
|
|
||||||
|
|
||||||
1. Edit `/boot/firmware/cmdline.txt`:
|
|
||||||
```bash
|
|
||||||
sudo nano /boot/firmware/cmdline.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Add `isolcpus=3` at the end of the line
|
|
||||||
|
|
||||||
3. Ctrl + X to exit, Y to save, Enter to Confirm
|
|
||||||
|
|
||||||
4. Edit /boot/firmware/config.txt with
|
|
||||||
```bash
|
|
||||||
sudo nano /boot/firmware/config.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
6. Edit the `dtparam=audio=on` section to `dtparam=audio=off`
|
|
||||||
|
|
||||||
7. Ctrl + X to exit, Y to save, Enter to Confirm
|
|
||||||
|
|
||||||
8. Save and reboot:
|
|
||||||
```bash
|
|
||||||
sudo reboot
|
|
||||||
```
|
|
||||||
|
|
||||||
9. Run the first_time_install.sh
|
|
||||||
```bash
|
|
||||||
chmod +x first_time_install.sh
|
|
||||||
sudo ./first_time_install.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
This handles dependency setup, service installation, permissions, and sudoers configuration.
|
|
||||||
|
|
||||||
10. Web Interface (V2)
|
|
||||||
|
|
||||||
- If `"web_display_autostart": true` is set in `config/config.json` (recommended), the web interface will be started by the installed service.
|
|
||||||
- Access the web UI at:
|
|
||||||
```
|
|
||||||
http://your-pi-ip:5001
|
|
||||||
```
|
|
||||||
- To launch manually instead of using the service:
|
|
||||||
```bash
|
|
||||||
python3 start_web_v2.py
|
|
||||||
```
|
|
||||||
This installs any missing dependencies and starts `web_interface_v2.py` on port 5001.
|
|
||||||
-----------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
1.Edit `config/config.json` with your preferences via `sudo nano config/config.json`
|
|
||||||
|
|
||||||
###API Keys
|
|
||||||
|
|
||||||
For sensitive settings like API keys:
|
|
||||||
Copy the template: `cp config/config_secrets.template.json config/config_secrets.json`
|
|
||||||
Edit `config/config_secrets.json` with your API keys via `sudo nano config/config_secrets.json`
|
|
||||||
Ctrl + X to exit, Y to overwrite, Enter to Confirm
|
|
||||||
|
|
||||||
Everything is configured via `config/config.json` and `config/config_secrets.json`.
|
|
||||||
|
|
||||||
|
|
||||||
For a complete first-time installation, run:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
chmod +x first_time_install.sh
|
|
||||||
```
|
|
||||||
then
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo ./first_time_install.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
This single script handles everything you need for a new installation.
|
|
||||||
|
|
||||||
## Individual Scripts Explained
|
|
||||||
|
|
||||||
### **First-Time Installation Scripts**
|
|
||||||
|
|
||||||
#### `first_time_install.sh` ⭐ **RECOMMENDED**
|
|
||||||
- **When to use**: New installations only
|
|
||||||
- **What it does**: Complete setup including all steps below
|
|
||||||
- **Usage**: `sudo ./first_time_install.sh`
|
|
||||||
|
|
||||||
### **Service Installation Scripts**
|
|
||||||
|
|
||||||
#### `install_service.sh`
|
|
||||||
- **When to use**: Install main LED Matrix display service
|
|
||||||
- **What it does**:
|
|
||||||
- Creates systemd service for main display
|
|
||||||
- Creates systemd service for web interface
|
|
||||||
- Enables services to start on boot
|
|
||||||
- **Usage**: `sudo ./install_service.sh`
|
|
||||||
|
|
||||||
#### `install_web_service.sh`
|
|
||||||
- **When to use**: Install only the web interface service (legacy)
|
|
||||||
- **What it does**: Installs the web interface systemd service
|
|
||||||
- **Usage**: `sudo ./install_web_service.sh`
|
|
||||||
- **Note**: `install_service.sh` now handles this automatically
|
|
||||||
|
|
||||||
### **Permission Fix Scripts**
|
|
||||||
|
|
||||||
#### `fix_cache_permissions.sh`
|
|
||||||
- **When to use**: When you see cache permission errors
|
|
||||||
- **What it does**:
|
|
||||||
- Creates cache directories (`/var/cache/ledmatrix`)
|
|
||||||
- Sets proper permissions for cache access
|
|
||||||
- Creates placeholder logo directories
|
|
||||||
- **Usage**: `sudo ./fix_cache_permissions.sh`
|
|
||||||
|
|
||||||
#### `fix_web_permissions.sh`
|
|
||||||
- **When to use**: When web interface can't access logs or system commands
|
|
||||||
- **What it does**:
|
|
||||||
- Adds user to `systemd-journal` group (for log access)
|
|
||||||
- Adds user to `adm` group (for system access)
|
|
||||||
- Sets proper file ownership
|
|
||||||
- **Usage**: `./fix_web_permissions.sh` (run as regular user)
|
|
||||||
|
|
||||||
#### `configure_web_sudo.sh`
|
|
||||||
- **When to use**: When web interface buttons don't work (sudo password errors)
|
|
||||||
- **What it does**:
|
|
||||||
- Configures passwordless sudo access for web interface
|
|
||||||
- Allows web interface to start/stop services without password
|
|
||||||
- **Usage**: `./configure_web_sudo.sh` (run as regular user)
|
|
||||||
|
|
||||||
### **Dependency Installation Scripts**
|
|
||||||
|
|
||||||
#### `scripts/install_dependencies_apt.py`
|
|
||||||
- **When to use**: When you want to install packages via apt first, then pip
|
|
||||||
- **What it does**:
|
|
||||||
- Tries to install packages via apt (system packages)
|
|
||||||
- Falls back to pip with `--break-system-packages`
|
|
||||||
- Handles externally managed Python environments
|
|
||||||
- **Usage**: `sudo python3 scripts/install_dependencies_apt.py`
|
|
||||||
|
|
||||||
#### `start_web_v2.py`
|
|
||||||
- **When to use**: Manual web interface startup
|
|
||||||
- **What it does**:
|
|
||||||
- Installs dependencies
|
|
||||||
- Starts web interface directly
|
|
||||||
- Includes comprehensive logging
|
|
||||||
- **Usage**: `python3 start_web_v2.py`
|
|
||||||
|
|
||||||
#### `run_web_v2.sh`
|
|
||||||
- **When to use**: Manual web interface startup (shell script version)
|
|
||||||
- **What it does**: Same as `start_web_v2.py` but as a shell script
|
|
||||||
- **Usage**: `./run_web_v2.sh`
|
|
||||||
|
|
||||||
### **Utility Scripts**
|
|
||||||
|
|
||||||
#### `cleanup_venv.sh`
|
|
||||||
- **When to use**: Remove virtual environment if you don't want to use it
|
|
||||||
- **What it does**: Removes `venv_web_v2` directory
|
|
||||||
- **Usage**: `./cleanup_venv.sh`
|
|
||||||
|
|
||||||
#### `start_web_conditionally.py`
|
|
||||||
- **When to use**: Called by systemd service (don't run manually)
|
|
||||||
- **What it does**:
|
|
||||||
- Checks config for `web_display_autostart` setting
|
|
||||||
- Starts web interface only if enabled
|
|
||||||
- Used by the systemd service
|
|
||||||
|
|
||||||
## Installation Scenarios
|
|
||||||
|
|
||||||
### **Scenario 1: Brand New Installation**
|
|
||||||
```bash
|
|
||||||
# One command does everything
|
|
||||||
sudo ./first_time_install.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
### **Scenario 2: Adding Web Interface to Existing Installation**
|
|
||||||
```bash
|
|
||||||
# Install web interface dependencies
|
|
||||||
sudo python3 scripts/install_dependencies_apt.py
|
|
||||||
|
|
||||||
# Fix permissions
|
|
||||||
./fix_web_permissions.sh
|
|
||||||
|
|
||||||
# Configure sudo access
|
|
||||||
./configure_web_sudo.sh
|
|
||||||
|
|
||||||
# Install services
|
|
||||||
sudo ./install_service.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
### **Scenario 3: Fixing Permission Issues**
|
|
||||||
```bash
|
|
||||||
# Fix cache permissions
|
|
||||||
sudo ./fix_cache_permissions.sh
|
|
||||||
|
|
||||||
# Fix web interface permissions
|
|
||||||
./fix_web_permissions.sh
|
|
||||||
|
|
||||||
# Configure sudo access
|
|
||||||
./configure_web_sudo.sh
|
|
||||||
|
|
||||||
# Log out and back in for group changes to take effect
|
|
||||||
```
|
|
||||||
|
|
||||||
### **Scenario 4: Manual Web Interface Startup**
|
|
||||||
```bash
|
|
||||||
# Start web interface manually (for testing)
|
|
||||||
python3 start_web_v2.py
|
|
||||||
```
|
|
||||||
|
|
||||||
## Post-Installation Steps
|
|
||||||
|
|
||||||
### **1. Log Out and Log Back In**
|
|
||||||
After running permission scripts, you need to log out and back in for group changes to take effect:
|
|
||||||
```bash
|
|
||||||
# Or use this command to apply group changes immediately
|
|
||||||
newgrp systemd-journal
|
|
||||||
```
|
|
||||||
|
|
||||||
### **2. Configure the Web Interface**
|
|
||||||
Edit `config/config.json` and set:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"web_display_autostart": true
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### **3. Access the Web Interface**
|
|
||||||
Open your browser and go to:
|
|
||||||
```
|
|
||||||
http://your-pi-ip:5001
|
|
||||||
```
|
|
||||||
|
|
||||||
### **4. Test Everything**
|
|
||||||
- Check if services are running: `sudo systemctl status ledmatrix.service`
|
|
||||||
- Check web interface: `sudo systemctl status ledmatrix-web.service`
|
|
||||||
- View logs: `journalctl -u ledmatrix.service -f`
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### **Web Interface Not Accessible**
|
|
||||||
1. Check if service is running: `sudo systemctl status ledmatrix-web.service`
|
|
||||||
2. Check logs: `journalctl -u ledmatrix-web.service -f`
|
|
||||||
3. Ensure `web_display_autostart` is `true` in config
|
|
||||||
|
|
||||||
### **Permission Errors**
|
|
||||||
1. Run: `./fix_web_permissions.sh`
|
|
||||||
2. Run: `./configure_web_sudo.sh`
|
|
||||||
3. Log out and back in
|
|
||||||
|
|
||||||
### **Cache Permission Errors**
|
|
||||||
1. Run: `sudo ./fix_cache_permissions.sh`
|
|
||||||
|
|
||||||
### **Sudo Password Prompts**
|
|
||||||
1. Run: `./configure_web_sudo.sh`
|
|
||||||
2. Log out and back in
|
|
||||||
|
|
||||||
### **Dependency Installation Errors**
|
|
||||||
1. Run: `sudo python3 scripts/install_dependencies_apt.py`
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
|
|
||||||
For **first-time installations**: Use `first_time_install.sh`
|
|
||||||
|
|
||||||
For **existing installations with issues**: Use the individual permission and configuration scripts as needed.
|
|
||||||
|
|
||||||
The `first_time_install.sh` script is designed to handle everything automatically, so you typically only need to run individual scripts if you're troubleshooting specific issues.
|
|
||||||
@@ -1,178 +0,0 @@
|
|||||||
# MiLB Manager Troubleshooting Guide
|
|
||||||
|
|
||||||
## **Issue Summary**
|
|
||||||
The MiLB manager is no longer pulling accurate game information due to several factors, primarily the current offseason period.
|
|
||||||
|
|
||||||
## **Root Causes**
|
|
||||||
|
|
||||||
### 1. **Primary Issue: MiLB Offseason**
|
|
||||||
- **Problem**: MiLB season runs from **April to September**
|
|
||||||
- **Current Status**: We're in January 2025 (offseason)
|
|
||||||
- **Impact**: No regular season games are scheduled during offseason
|
|
||||||
- **Solution**: Enable test mode for offseason testing
|
|
||||||
|
|
||||||
### 2. **Secondary Issues**
|
|
||||||
- **API Endpoint Changes**: MLB Stats API endpoints may have changed
|
|
||||||
- **Sport ID Updates**: Some sport IDs might be outdated
|
|
||||||
- **Team Mapping**: Team abbreviations may have changed
|
|
||||||
|
|
||||||
## **Solutions Implemented**
|
|
||||||
|
|
||||||
### **Immediate Fix: Enable Test Mode**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"milb": {
|
|
||||||
"test_mode": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### **Code Improvements**
|
|
||||||
1. **Season Awareness**: Added offseason detection
|
|
||||||
2. **Better Logging**: More informative error messages
|
|
||||||
3. **Test Mode Enhancement**: Improved test data
|
|
||||||
|
|
||||||
## **Diagnostic Tools Created**
|
|
||||||
|
|
||||||
### 1. **Basic API Test**
|
|
||||||
```bash
|
|
||||||
python test/test_milb_api.py
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. **Comprehensive Diagnostic**
|
|
||||||
```bash
|
|
||||||
python test/diagnose_milb_issues.py
|
|
||||||
```
|
|
||||||
|
|
||||||
## **Testing the Fixes**
|
|
||||||
|
|
||||||
### **Step 1: Run Diagnostic**
|
|
||||||
```bash
|
|
||||||
cd /path/to/LEDMatrix
|
|
||||||
python test/diagnose_milb_issues.py
|
|
||||||
```
|
|
||||||
|
|
||||||
### **Step 2: Test with Test Mode**
|
|
||||||
1. Ensure `test_mode: true` in config
|
|
||||||
2. Restart the display system
|
|
||||||
3. Check if test games appear
|
|
||||||
|
|
||||||
### **Step 3: Verify API (When Season Returns)**
|
|
||||||
```bash
|
|
||||||
python test/test_milb_api.py
|
|
||||||
```
|
|
||||||
|
|
||||||
## **Expected Behavior**
|
|
||||||
|
|
||||||
### **During Offseason (October-March)**
|
|
||||||
- No real games found
|
|
||||||
- Test mode shows sample games
|
|
||||||
- Logs indicate offseason status
|
|
||||||
|
|
||||||
### **During Season (April-September)**
|
|
||||||
- Real games should be found
|
|
||||||
- Live games display correctly
|
|
||||||
- Upcoming games show properly
|
|
||||||
|
|
||||||
## **Configuration Options**
|
|
||||||
|
|
||||||
### **Test Mode**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"milb": {
|
|
||||||
"test_mode": true,
|
|
||||||
"enabled": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### **Season Override (For Testing)**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"milb": {
|
|
||||||
"test_mode": true,
|
|
||||||
"force_season": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## **Common Issues and Solutions**
|
|
||||||
|
|
||||||
### **Issue: No Games Found**
|
|
||||||
- **Cause**: Offseason or API issues
|
|
||||||
- **Solution**: Enable test mode
|
|
||||||
|
|
||||||
### **Issue: API Errors**
|
|
||||||
- **Cause**: Network or endpoint issues
|
|
||||||
- **Solution**: Check internet connection and API status
|
|
||||||
|
|
||||||
### **Issue: Wrong Team Names**
|
|
||||||
- **Cause**: Team mapping outdated
|
|
||||||
- **Solution**: Update `milb_team_mapping.json`
|
|
||||||
|
|
||||||
### **Issue: Wrong Sport IDs**
|
|
||||||
- **Cause**: MLB API changes
|
|
||||||
- **Solution**: Update sport IDs in config
|
|
||||||
|
|
||||||
## **Monitoring and Logs**
|
|
||||||
|
|
||||||
### **Key Log Messages**
|
|
||||||
- `"MiLB is currently in offseason"` - Normal during offseason
|
|
||||||
- `"Using test mode data for MiLB"` - Test mode active
|
|
||||||
- `"No games returned from API"` - API issue or offseason
|
|
||||||
|
|
||||||
### **Debug Mode**
|
|
||||||
Enable debug logging to see detailed API calls:
|
|
||||||
```python
|
|
||||||
logger.setLevel(logging.DEBUG)
|
|
||||||
```
|
|
||||||
|
|
||||||
## **Future Improvements**
|
|
||||||
|
|
||||||
### **Planned Enhancements**
|
|
||||||
1. **Season Schedule Integration**: Use official season dates
|
|
||||||
2. **API Fallback**: Multiple API endpoints
|
|
||||||
3. **Caching Improvements**: Better cache management
|
|
||||||
4. **Error Recovery**: Automatic retry mechanisms
|
|
||||||
|
|
||||||
### **Configuration Enhancements**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"milb": {
|
|
||||||
"season_start_month": 4,
|
|
||||||
"season_end_month": 9,
|
|
||||||
"api_fallback": true,
|
|
||||||
"cache_duration": 3600
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## **Contact and Support**
|
|
||||||
|
|
||||||
For additional issues:
|
|
||||||
1. Run the diagnostic tools
|
|
||||||
2. Check the logs for specific errors
|
|
||||||
3. Verify network connectivity
|
|
||||||
4. Test API endpoints directly
|
|
||||||
|
|
||||||
## **Quick Reference**
|
|
||||||
|
|
||||||
### **Enable Test Mode**
|
|
||||||
```bash
|
|
||||||
# Edit config/config.json
|
|
||||||
# Change "test_mode": false to "test_mode": true
|
|
||||||
```
|
|
||||||
|
|
||||||
### **Run Diagnostics**
|
|
||||||
```bash
|
|
||||||
python test/diagnose_milb_issues.py
|
|
||||||
```
|
|
||||||
|
|
||||||
### **Test API Directly**
|
|
||||||
```bash
|
|
||||||
python test/test_milb_api.py
|
|
||||||
```
|
|
||||||
|
|
||||||
### **Check Season Status**
|
|
||||||
- **April-September**: Season active
|
|
||||||
- **October-March**: Offseason (use test mode)
|
|
||||||
@@ -1,245 +0,0 @@
|
|||||||
# Sports News Manager
|
|
||||||
|
|
||||||
A comprehensive RSS feed ticker system for displaying sports news headlines with dynamic scrolling and intelligent rotation.
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
### 🏈 Multiple Sports Feeds
|
|
||||||
- **NFL**: Latest NFL news and updates
|
|
||||||
- **NCAA Football**: College football news
|
|
||||||
- **MLB**: Major League Baseball news
|
|
||||||
- **NBA**: Basketball news and updates
|
|
||||||
- **NHL**: Hockey news
|
|
||||||
- **NCAA Basketball**: College basketball updates
|
|
||||||
- **Big 10**: Big Ten conference news
|
|
||||||
- **Top Sports**: General ESPN sports news
|
|
||||||
- **Custom Feeds**: Add your own RSS feeds
|
|
||||||
|
|
||||||
### 📺 Smart Display Features
|
|
||||||
- **Dynamic Length Detection**: Automatically calculates headline length and adjusts scroll timing
|
|
||||||
- **Perfect Spacing**: Ensures headlines don't cut off mid-text or loop unnecessarily
|
|
||||||
- **Intelligent Rotation**: Prevents repetitive content by rotating through different headlines
|
|
||||||
- **Configurable Speed**: Adjustable scroll speed and timing
|
|
||||||
- **Visual Separators**: Color-coded separators between different news sources
|
|
||||||
|
|
||||||
### ⚙️ Configuration Options
|
|
||||||
- Enable/disable individual sports feeds
|
|
||||||
- Set number of headlines per feed (1-5)
|
|
||||||
- Adjust scroll speed and timing
|
|
||||||
- Configure rotation behavior
|
|
||||||
- Customize fonts and colors
|
|
||||||
- Add custom RSS feeds
|
|
||||||
|
|
||||||
## Default RSS Feeds
|
|
||||||
|
|
||||||
The system comes pre-configured with these ESPN RSS 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
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Command Line Management
|
|
||||||
|
|
||||||
Use the `scripts/enable_news_manager.py` script to manage the news manager:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Check current status
|
|
||||||
python3 scripts/enable_news_manager.py status
|
|
||||||
|
|
||||||
# Enable news manager
|
|
||||||
python3 scripts/enable_news_manager.py enable
|
|
||||||
|
|
||||||
# Disable news manager
|
|
||||||
python3 scripts/enable_news_manager.py disable
|
|
||||||
```
|
|
||||||
|
|
||||||
### Web Interface
|
|
||||||
|
|
||||||
Access the news manager through the web interface:
|
|
||||||
|
|
||||||
1. Open your browser to `http://your-display-ip:5001`
|
|
||||||
2. Click on the "News Manager" tab
|
|
||||||
3. Configure your preferred settings:
|
|
||||||
- Enable/disable the news manager
|
|
||||||
- Select which sports feeds to display
|
|
||||||
- Set headlines per feed (1-5)
|
|
||||||
- Configure scroll speed and timing
|
|
||||||
- Add custom RSS feeds
|
|
||||||
- Enable/disable rotation
|
|
||||||
|
|
||||||
### Configuration File
|
|
||||||
|
|
||||||
Direct configuration via `config/config.json`:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"news_manager": {
|
|
||||||
"enabled": true,
|
|
||||||
"update_interval": 300,
|
|
||||||
"scroll_speed": 2,
|
|
||||||
"scroll_delay": 0.02,
|
|
||||||
"headlines_per_feed": 2,
|
|
||||||
"enabled_feeds": ["NFL", "NCAA FB"],
|
|
||||||
"custom_feeds": {
|
|
||||||
"My Team": "https://example.com/rss"
|
|
||||||
},
|
|
||||||
"rotation_enabled": true,
|
|
||||||
"rotation_threshold": 3,
|
|
||||||
"font_size": 12,
|
|
||||||
"font_path": "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
|
|
||||||
"text_color": [255, 255, 255],
|
|
||||||
"separator_color": [255, 0, 0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## How It Works
|
|
||||||
|
|
||||||
### Dynamic Length Calculation
|
|
||||||
|
|
||||||
The system intelligently calculates the display time for each headline:
|
|
||||||
|
|
||||||
1. **Text Measurement**: Uses PIL to measure the exact pixel width of each headline
|
|
||||||
2. **Scroll Distance**: Calculates total distance needed (text width + display width)
|
|
||||||
3. **Timing Calculation**: Determines exact scroll time based on speed settings
|
|
||||||
4. **Perfect Spacing**: Ensures smooth transitions between headlines
|
|
||||||
|
|
||||||
### Rotation Algorithm
|
|
||||||
|
|
||||||
Prevents repetitive content by:
|
|
||||||
|
|
||||||
1. **Tracking Display Count**: Monitors how many times each headline has been shown
|
|
||||||
2. **Threshold Management**: After a configured number of cycles, rotates to new content
|
|
||||||
3. **Feed Balancing**: Ensures even distribution across selected feeds
|
|
||||||
4. **Freshness**: Prioritizes newer headlines when available
|
|
||||||
|
|
||||||
### Example Calculation
|
|
||||||
|
|
||||||
For a headline "Breaking: Major trade shakes up NFL draft prospects" (51 characters):
|
|
||||||
|
|
||||||
- **Estimated Width**: ~306 pixels (6 pixels per character average)
|
|
||||||
- **Display Width**: 128 pixels
|
|
||||||
- **Total Scroll Distance**: 306 + 128 = 434 pixels
|
|
||||||
- **Scroll Speed**: 2 pixels per frame
|
|
||||||
- **Frame Delay**: 0.02 seconds
|
|
||||||
- **Total Time**: (434 ÷ 2) × 0.02 = 4.34 seconds
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
### RSS Feed Test
|
|
||||||
|
|
||||||
Test the RSS feeds directly:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python3 simple_news_test.py
|
|
||||||
```
|
|
||||||
|
|
||||||
This will:
|
|
||||||
- Test connectivity to ESPN RSS feeds
|
|
||||||
- Parse sample headlines
|
|
||||||
- Calculate scroll timing
|
|
||||||
- Demonstrate rotation logic
|
|
||||||
|
|
||||||
### Integration Test
|
|
||||||
|
|
||||||
Test the full news manager without hardware dependencies:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python3 test_news_manager.py
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Endpoints
|
|
||||||
|
|
||||||
The system provides REST API endpoints for external control:
|
|
||||||
|
|
||||||
- `GET /news_manager/status` - Get current status and configuration
|
|
||||||
- `POST /news_manager/update` - Update configuration
|
|
||||||
- `POST /news_manager/refresh` - Force refresh of news data
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Common Issues
|
|
||||||
|
|
||||||
1. **RSS Feed Not Loading**
|
|
||||||
- Check internet connectivity
|
|
||||||
- Verify RSS URL is valid
|
|
||||||
- Check for rate limiting
|
|
||||||
|
|
||||||
2. **Slow Performance**
|
|
||||||
- Reduce number of enabled feeds
|
|
||||||
- Increase update interval
|
|
||||||
- Check network latency
|
|
||||||
|
|
||||||
3. **Text Not Displaying**
|
|
||||||
- Verify font path exists
|
|
||||||
- Check text color settings
|
|
||||||
- Ensure display dimensions are correct
|
|
||||||
|
|
||||||
### Debug Mode
|
|
||||||
|
|
||||||
Enable debug logging by setting the log level:
|
|
||||||
|
|
||||||
```python
|
|
||||||
import logging
|
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Customization
|
|
||||||
|
|
||||||
### Adding Custom Feeds
|
|
||||||
|
|
||||||
Add your own RSS feeds through the web interface or configuration:
|
|
||||||
|
|
||||||
```json
|
|
||||||
"custom_feeds": {
|
|
||||||
"My Local Team": "https://myteam.com/rss",
|
|
||||||
"Sports Blog": "https://sportsblog.com/feed"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Styling Options
|
|
||||||
|
|
||||||
Customize the appearance:
|
|
||||||
|
|
||||||
- **Font Size**: Adjust text size (8-24 pixels)
|
|
||||||
- **Colors**: RGB values for text and separators
|
|
||||||
- **Font Path**: Use different system fonts
|
|
||||||
- **Scroll Speed**: 1-10 pixels per frame
|
|
||||||
- **Timing**: 0.01-0.1 seconds per frame
|
|
||||||
|
|
||||||
## Performance
|
|
||||||
|
|
||||||
The news manager is optimized for:
|
|
||||||
|
|
||||||
- **Low Memory Usage**: Efficient caching and cleanup
|
|
||||||
- **Network Efficiency**: Smart update intervals and retry logic
|
|
||||||
- **Smooth Scrolling**: Consistent frame rates
|
|
||||||
- **Fast Loading**: Parallel RSS feed processing
|
|
||||||
|
|
||||||
## Future Enhancements
|
|
||||||
|
|
||||||
Planned features:
|
|
||||||
- Breaking news alerts
|
|
||||||
- Team-specific filtering
|
|
||||||
- Score integration
|
|
||||||
- Social media feeds
|
|
||||||
- Voice announcements
|
|
||||||
- Mobile app control
|
|
||||||
|
|
||||||
## Support
|
|
||||||
|
|
||||||
For issues or questions:
|
|
||||||
1. Check the troubleshooting section
|
|
||||||
2. Review the logs for error messages
|
|
||||||
3. Test individual RSS feeds
|
|
||||||
4. Verify configuration settings
|
|
||||||
@@ -1,442 +0,0 @@
|
|||||||
# Team Abbreviations and League Slugs
|
|
||||||
|
|
||||||
This page provides comprehensive information about team abbreviations and league slugs used in the LEDMatrix system for sports displays.
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
The LEDMatrix system uses standardized abbreviations for teams and league slugs to identify and display sports information. This document serves as a reference for:
|
|
||||||
|
|
||||||
- Team abbreviations used in configuration files
|
|
||||||
- League slugs for ESPN API integration
|
|
||||||
- Logo file naming conventions
|
|
||||||
- Configuration examples
|
|
||||||
|
|
||||||
## Soccer League Slugs
|
|
||||||
|
|
||||||
The following league slugs are supported for soccer displays:
|
|
||||||
|
|
||||||
| League Slug | League Name | ESPN API Endpoint |
|
|
||||||
|-------------|-------------|-------------------|
|
|
||||||
| `eng.1` | Premier League | `soccer_eng.1` |
|
|
||||||
| `esp.1` | La Liga | `soccer_esp.1` |
|
|
||||||
| `ger.1` | Bundesliga | `soccer_ger.1` |
|
|
||||||
| `ita.1` | Serie A | `soccer_ita.1` |
|
|
||||||
| `fra.1` | Ligue 1 | `soccer_fra.1` |
|
|
||||||
| `por.1` | Liga Portugal | `soccer_por.1` |
|
|
||||||
| `uefa.champions` | Champions League | `soccer_uefa.champions` |
|
|
||||||
| `uefa.europa` | Europa League | `soccer_uefa.europa` |
|
|
||||||
| `usa.1` | MLS | `soccer_usa.1` |
|
|
||||||
|
|
||||||
## Soccer Team Abbreviations
|
|
||||||
|
|
||||||
### Premier League (eng.1)
|
|
||||||
|
|
||||||
| Abbreviation | Team Name | Logo File |
|
|
||||||
|--------------|-----------|-----------|
|
|
||||||
| `ARS` | Arsenal | `ARS.png` |
|
|
||||||
| `AVL` | Aston Villa | `AVL.png` |
|
|
||||||
| `BHA` | Brighton & Hove Albion | `BHA.png` |
|
|
||||||
| `BOU` | AFC Bournemouth | `BOU.png` |
|
|
||||||
| `BRE` | Brentford | `BRE.png` |
|
|
||||||
| `BUR` | Burnley | `BUR.png` |
|
|
||||||
| `CHE` | Chelsea | `CHE.png` |
|
|
||||||
| `CRY` | Crystal Palace | `CRY.png` |
|
|
||||||
| `EVE` | Everton | `EVE.png` |
|
|
||||||
| `FUL` | Fulham | `FUL.png` |
|
|
||||||
| `LIV` | Liverpool | `LIV.png` |
|
|
||||||
| `LUT` | Luton Town | `LUT.png` |
|
|
||||||
| `MCI` | Manchester City | `MCI.png` |
|
|
||||||
| `MUN` | Manchester United | `MUN.png` |
|
|
||||||
| `NEW` | Newcastle United | `NEW.png` |
|
|
||||||
| `NFO` | Nottingham Forest | `NFO.png` |
|
|
||||||
| `SHU` | Sheffield United | `SHU.png` |
|
|
||||||
| `TOT` | Tottenham Hotspur | `TOT.png` |
|
|
||||||
| `WHU` | West Ham United | `WHU.png` |
|
|
||||||
| `WOL` | Wolverhampton Wanderers | `WOL.png` |
|
|
||||||
|
|
||||||
### La Liga (esp.1)
|
|
||||||
|
|
||||||
| Abbreviation | Team Name | Logo File |
|
|
||||||
|--------------|-----------|-----------|
|
|
||||||
| `ALA` | Alavés | `ALA.png` |
|
|
||||||
| `ATH` | Athletic Bilbao | `ATH.png` |
|
|
||||||
| `ATM` | Atlético Madrid | `ATM.png` |
|
|
||||||
| `BAR` | Barcelona | `BAR.png` |
|
|
||||||
| `BET` | Real Betis | `BET.png` |
|
|
||||||
| `CEL` | Celta Vigo | `CEL.png` |
|
|
||||||
| `ESP` | Espanyol | `ESP.png` |
|
|
||||||
| `GET` | Getafe | `GET.png` |
|
|
||||||
| `GIR` | Girona | `GIR.png` |
|
|
||||||
| `LEG` | Leganés | `LEG.png` |
|
|
||||||
| `RAY` | Rayo Vallecano | `RAY.png` |
|
|
||||||
| `RMA` | Real Madrid | `RMA.png` |
|
|
||||||
| `SEV` | Sevilla | `SEV.png` |
|
|
||||||
| `VAL` | Valencia | `VAL.png` |
|
|
||||||
| `VLD` | Valladolid | `VLD.png` |
|
|
||||||
|
|
||||||
### Bundesliga (ger.1)
|
|
||||||
|
|
||||||
| Abbreviation | Team Name | Logo File |
|
|
||||||
|--------------|-----------|-----------|
|
|
||||||
| `BOC` | VfL Bochum | `BOC.png` |
|
|
||||||
| `DOR` | Borussia Dortmund | `DOR.png` |
|
|
||||||
| `FCA` | FC Augsburg | `FCA.png` |
|
|
||||||
| `FCB` | Bayern Munich | `FCB.png` |
|
|
||||||
| `FCU` | FC Union Berlin | `FCU.png` |
|
|
||||||
| `KOL` | 1. FC Köln | `KOL.png` |
|
|
||||||
| `LEV` | Bayer Leverkusen | `LEV.png` |
|
|
||||||
| `M05` | Mainz 05 | `M05.png` |
|
|
||||||
| `RBL` | RB Leipzig | `RBL.png` |
|
|
||||||
| `SCF` | SC Freiburg | `SCF.png` |
|
|
||||||
| `SGE` | Eintracht Frankfurt | `SGE.png` |
|
|
||||||
| `STU` | VfB Stuttgart | `STU.png` |
|
|
||||||
| `SVW` | Werder Bremen | `SVW.png` |
|
|
||||||
| `TSG` | TSG Hoffenheim | `TSG.png` |
|
|
||||||
| `WOB` | VfL Wolfsburg | `WOB.png` |
|
|
||||||
|
|
||||||
### Serie A (ita.1)
|
|
||||||
|
|
||||||
| Abbreviation | Team Name | Logo File |
|
|
||||||
|--------------|-----------|-----------|
|
|
||||||
| `ATA` | Atalanta | `ATA.png` |
|
|
||||||
| `CAG` | Cagliari | `CAG.png` |
|
|
||||||
| `EMP` | Empoli | `EMP.png` |
|
|
||||||
| `FIO` | Fiorentina | `FIO.png` |
|
|
||||||
| `INT` | Inter Milan | `INT.png` |
|
|
||||||
| `JUV` | Juventus | `JUV.png` |
|
|
||||||
| `LAZ` | Lazio | `LAZ.png` |
|
|
||||||
| `MIL` | AC Milan | `MIL.png` |
|
|
||||||
| `MON` | Monza | `MON.png` |
|
|
||||||
| `NAP` | Napoli | `NAP.png` |
|
|
||||||
| `ROM` | Roma | `ROM.png` |
|
|
||||||
| `TOR` | Torino | `TOR.png` |
|
|
||||||
| `UDI` | Udinese | `UDI.png` |
|
|
||||||
| `VER` | Hellas Verona | `VER.png` |
|
|
||||||
|
|
||||||
### Ligue 1 (fra.1)
|
|
||||||
|
|
||||||
| Abbreviation | Team Name | Logo File |
|
|
||||||
|--------------|-----------|-----------|
|
|
||||||
| `LIL` | Lille | `LIL.png` |
|
|
||||||
| `LYON` | Lyon | `LYON.png` |
|
|
||||||
| `MAR` | Marseille | `MAR.png` |
|
|
||||||
| `MON` | Monaco | `MON.png` |
|
|
||||||
| `NAN` | Nantes | `NAN.png` |
|
|
||||||
| `NICE` | Nice | `NICE.png` |
|
|
||||||
| `OL` | Olympique Lyonnais | `OL.png` |
|
|
||||||
| `OM` | Olympique de Marseille | `OM.png` |
|
|
||||||
| `PAR` | Paris Saint-Germain | `PAR.png` |
|
|
||||||
| `PSG` | Paris Saint-Germain | `PSG.png` |
|
|
||||||
| `REN` | Rennes | `REN.png` |
|
|
||||||
| `STR` | Strasbourg | `STR.png` |
|
|
||||||
|
|
||||||
### Liga Portugal (por.1)
|
|
||||||
|
|
||||||
| Abbreviation | Team Name | Logo File |
|
|
||||||
|--------------|-----------|-----------|
|
|
||||||
| `ARO` | Arouca | `ARO.png` |
|
|
||||||
| `BEN` | SL Benfica | `BEN.png` |
|
|
||||||
| `BRA` | SC Braga | `BRA.png` |
|
|
||||||
| `CHA` | Chaves | `CHA.png` |
|
|
||||||
| `EST` | Estoril Praia | `EST.png` |
|
|
||||||
| `FAM` | Famalicão | `FAM.png` |
|
|
||||||
| `GIL` | Gil Vicente | `GIL.png` |
|
|
||||||
| `MOR` | Moreirense | `MOR.png` |
|
|
||||||
| `POR` | FC Porto | `POR.png` |
|
|
||||||
| `PTM` | Portimonense | `PTM.png` |
|
|
||||||
| `RIO` | Rio Ave | `RIO.png` |
|
|
||||||
| `SR` | Sporting CP | `SR.png` |
|
|
||||||
| `SCP` | Sporting CP (Alternative) | `SCP.png` |
|
|
||||||
| `VGU` | Vitória de Guimarães | `VGU.png` |
|
|
||||||
| `VSC` | Vitória de Setúbal | `VSC.png` |
|
|
||||||
|
|
||||||
### Champions League (uefa.champions)
|
|
||||||
|
|
||||||
| Abbreviation | Team Name | Logo File |
|
|
||||||
|--------------|-----------|-----------|
|
|
||||||
| `AJX` | Ajax | `AJX.png` |
|
|
||||||
| `ATM` | Atlético Madrid | `ATM.png` |
|
|
||||||
| `BAR` | Barcelona | `BAR.png` |
|
|
||||||
| `BAY` | Bayern Munich | `BAY.png` |
|
|
||||||
| `CHE` | Chelsea | `CHE.png` |
|
|
||||||
| `INT` | Inter Milan | `INT.png` |
|
|
||||||
| `JUV` | Juventus | `JUV.png` |
|
|
||||||
| `LIV` | Liverpool | `LIV.png` |
|
|
||||||
| `MCI` | Manchester City | `MCI.png` |
|
|
||||||
| `MUN` | Manchester United | `MUN.png` |
|
|
||||||
| `PSG` | Paris Saint-Germain | `PSG.png` |
|
|
||||||
| `RMA` | Real Madrid | `RMA.png` |
|
|
||||||
| `TOT` | Tottenham Hotspur | `TOT.png` |
|
|
||||||
|
|
||||||
### Europa League (uefa.europa)
|
|
||||||
|
|
||||||
| Abbreviation | Team Name | Logo File |
|
|
||||||
|--------------|-----------|-----------|
|
|
||||||
| `ARS` | Arsenal | `ARS.png` |
|
|
||||||
| `ATM` | Atlético Madrid | `ATM.png` |
|
|
||||||
| `BAR` | Barcelona | `BAR.png` |
|
|
||||||
| `CHE` | Chelsea | `CHE.png` |
|
|
||||||
| `INT` | Inter Milan | `INT.png` |
|
|
||||||
| `JUV` | Juventus | `JUV.png` |
|
|
||||||
| `LIV` | Liverpool | `LIV.png` |
|
|
||||||
| `MUN` | Manchester United | `MUN.png` |
|
|
||||||
| `NAP` | Napoli | `NAP.png` |
|
|
||||||
| `ROM` | Roma | `ROM.png` |
|
|
||||||
| `SEV` | Sevilla | `SEV.png` |
|
|
||||||
|
|
||||||
### MLS (usa.1)
|
|
||||||
|
|
||||||
| Abbreviation | Team Name | Logo File |
|
|
||||||
|--------------|-----------|-----------|
|
|
||||||
| `ATL` | Atlanta United | `ATL.png` |
|
|
||||||
| `AUS` | Austin FC | `AUS.png` |
|
|
||||||
| `CHI` | Chicago Fire | `CHI.png` |
|
|
||||||
| `CIN` | FC Cincinnati | `CIN.png` |
|
|
||||||
| `CLB` | Columbus Crew | `CLB.png` |
|
|
||||||
| `DAL` | FC Dallas | `DAL.png` |
|
|
||||||
| `DC` | D.C. United | `DC.png` |
|
|
||||||
| `HOU` | Houston Dynamo | `HOU.png` |
|
|
||||||
| `LA` | LA Galaxy | `LA.png` |
|
|
||||||
| `LAFC` | Los Angeles FC | `LAFC.png` |
|
|
||||||
| `MIA` | Inter Miami | `MIA.png` |
|
|
||||||
| `MIN` | Minnesota United | `MIN.png` |
|
|
||||||
| `MTL` | CF Montréal | `MTL.png` |
|
|
||||||
| `NSC` | Nashville SC | `NSC.png` |
|
|
||||||
| `NYC` | New York City FC | `NYC.png` |
|
|
||||||
| `NYR` | New York Red Bulls | `NYR.png` |
|
|
||||||
| `ORL` | Orlando City | `ORL.png` |
|
|
||||||
| `PHI` | Philadelphia Union | `PHI.png` |
|
|
||||||
| `POR` | Portland Timbers | `POR.png` |
|
|
||||||
| `RSL` | Real Salt Lake | `RSL.png` |
|
|
||||||
| `SEA` | Seattle Sounders | `SEA.png` |
|
|
||||||
| `SJ` | San Jose Earthquakes | `SJ.png` |
|
|
||||||
| `SKC` | Sporting Kansas City | `SKC.png` |
|
|
||||||
| `TOR` | Toronto FC | `TOR.png` |
|
|
||||||
| `VAN` | Vancouver Whitecaps | `VAN.png` |
|
|
||||||
|
|
||||||
## Other Sports Leagues
|
|
||||||
|
|
||||||
### NFL
|
|
||||||
|
|
||||||
| Abbreviation | Team Name | Logo File |
|
|
||||||
|--------------|-----------|-----------|
|
|
||||||
| `ARI` | Arizona Cardinals | `ARI.png` |
|
|
||||||
| `ATL` | Atlanta Falcons | `ATL.png` |
|
|
||||||
| `BAL` | Baltimore Ravens | `BAL.png` |
|
|
||||||
| `BUF` | Buffalo Bills | `BUF.png` |
|
|
||||||
| `CAR` | Carolina Panthers | `CAR.png` |
|
|
||||||
| `CHI` | Chicago Bears | `CHI.png` |
|
|
||||||
| `CIN` | Cincinnati Bengals | `CIN.png` |
|
|
||||||
| `CLE` | Cleveland Browns | `CLE.png` |
|
|
||||||
| `DAL` | Dallas Cowboys | `DAL.png` |
|
|
||||||
| `DEN` | Denver Broncos | `DEN.png` |
|
|
||||||
| `DET` | Detroit Lions | `DET.png` |
|
|
||||||
| `GB` | Green Bay Packers | `GB.png` |
|
|
||||||
| `HOU` | Houston Texans | `HOU.png` |
|
|
||||||
| `IND` | Indianapolis Colts | `IND.png` |
|
|
||||||
| `JAX` | Jacksonville Jaguars | `JAX.png` |
|
|
||||||
| `KC` | Kansas City Chiefs | `KC.png` |
|
|
||||||
| `LV` | Las Vegas Raiders | `LV.png` |
|
|
||||||
| `LAC` | Los Angeles Chargers | `LAC.png` |
|
|
||||||
| `LAR` | Los Angeles Rams | `LAR.png` |
|
|
||||||
| `MIA` | Miami Dolphins | `MIA.png` |
|
|
||||||
| `MIN` | Minnesota Vikings | `MIN.png` |
|
|
||||||
| `NE` | New England Patriots | `NE.png` |
|
|
||||||
| `NO` | New Orleans Saints | `NO.png` |
|
|
||||||
| `NYG` | New York Giants | `NYG.png` |
|
|
||||||
| `NYJ` | New York Jets | `NYJ.png` |
|
|
||||||
| `PHI` | Philadelphia Eagles | `PHI.png` |
|
|
||||||
| `PIT` | Pittsburgh Steelers | `PIT.png` |
|
|
||||||
| `SF` | San Francisco 49ers | `SF.png` |
|
|
||||||
| `SEA` | Seattle Seahawks | `SEA.png` |
|
|
||||||
| `TB` | Tampa Bay Buccaneers | `TB.png` |
|
|
||||||
| `TEN` | Tennessee Titans | `TEN.png` |
|
|
||||||
| `WAS` | Washington Commanders | `WAS.png` |
|
|
||||||
|
|
||||||
### NBA
|
|
||||||
|
|
||||||
| Abbreviation | Team Name | Logo File |
|
|
||||||
|--------------|-----------|-----------|
|
|
||||||
| `ATL` | Atlanta Hawks | `ATL.png` |
|
|
||||||
| `BOS` | Boston Celtics | `BOS.png` |
|
|
||||||
| `BKN` | Brooklyn Nets | `BKN.png` |
|
|
||||||
| `CHA` | Charlotte Hornets | `CHA.png` |
|
|
||||||
| `CHI` | Chicago Bulls | `CHI.png` |
|
|
||||||
| `CLE` | Cleveland Cavaliers | `CLE.png` |
|
|
||||||
| `DAL` | Dallas Mavericks | `DAL.png` |
|
|
||||||
| `DEN` | Denver Nuggets | `DEN.png` |
|
|
||||||
| `DET` | Detroit Pistons | `DET.png` |
|
|
||||||
| `GSW` | Golden State Warriors | `GSW.png` |
|
|
||||||
| `HOU` | Houston Rockets | `HOU.png` |
|
|
||||||
| `IND` | Indiana Pacers | `IND.png` |
|
|
||||||
| `LAC` | LA Clippers | `LAC.png` |
|
|
||||||
| `LAL` | Los Angeles Lakers | `LAL.png` |
|
|
||||||
| `MEM` | Memphis Grizzlies | `MEM.png` |
|
|
||||||
| `MIA` | Miami Heat | `MIA.png` |
|
|
||||||
| `MIL` | Milwaukee Bucks | `MIL.png` |
|
|
||||||
| `MIN` | Minnesota Timberwolves | `MIN.png` |
|
|
||||||
| `NOP` | New Orleans Pelicans | `NOP.png` |
|
|
||||||
| `NYK` | New York Knicks | `NYK.png` |
|
|
||||||
| `OKC` | Oklahoma City Thunder | `OKC.png` |
|
|
||||||
| `ORL` | Orlando Magic | `ORL.png` |
|
|
||||||
| `PHI` | Philadelphia 76ers | `PHI.png` |
|
|
||||||
| `PHX` | Phoenix Suns | `PHX.png` |
|
|
||||||
| `POR` | Portland Trail Blazers | `POR.png` |
|
|
||||||
| `SAC` | Sacramento Kings | `SAC.png` |
|
|
||||||
| `SAS` | San Antonio Spurs | `SAS.png` |
|
|
||||||
| `TOR` | Toronto Raptors | `TOR.png` |
|
|
||||||
| `UTA` | Utah Jazz | `UTA.png` |
|
|
||||||
| `WAS` | Washington Wizards | `WAS.png` |
|
|
||||||
|
|
||||||
### MLB
|
|
||||||
|
|
||||||
| Abbreviation | Team Name | Logo File |
|
|
||||||
|--------------|-----------|-----------|
|
|
||||||
| `ARI` | Arizona Diamondbacks | `ARI.png` |
|
|
||||||
| `ATL` | Atlanta Braves | `ATL.png` |
|
|
||||||
| `BAL` | Baltimore Orioles | `BAL.png` |
|
|
||||||
| `BOS` | Boston Red Sox | `BOS.png` |
|
|
||||||
| `CHC` | Chicago Cubs | `CHC.png` |
|
|
||||||
| `CWS` | Chicago White Sox | `CWS.png` |
|
|
||||||
| `CIN` | Cincinnati Reds | `CIN.png` |
|
|
||||||
| `CLE` | Cleveland Guardians | `CLE.png` |
|
|
||||||
| `COL` | Colorado Rockies | `COL.png` |
|
|
||||||
| `DET` | Detroit Tigers | `DET.png` |
|
|
||||||
| `HOU` | Houston Astros | `HOU.png` |
|
|
||||||
| `KC` | Kansas City Royals | `KC.png` |
|
|
||||||
| `LAA` | Los Angeles Angels | `LAA.png` |
|
|
||||||
| `LAD` | Los Angeles Dodgers | `LAD.png` |
|
|
||||||
| `MIA` | Miami Marlins | `MIA.png` |
|
|
||||||
| `MIL` | Milwaukee Brewers | `MIL.png` |
|
|
||||||
| `MIN` | Minnesota Twins | `MIN.png` |
|
|
||||||
| `NYM` | New York Mets | `NYM.png` |
|
|
||||||
| `NYY` | New York Yankees | `NYY.png` |
|
|
||||||
| `OAK` | Oakland Athletics | `OAK.png` |
|
|
||||||
| `PHI` | Philadelphia Phillies | `PHI.png` |
|
|
||||||
| `PIT` | Pittsburgh Pirates | `PIT.png` |
|
|
||||||
| `SD` | San Diego Padres | `SD.png` |
|
|
||||||
| `SF` | San Francisco Giants | `SF.png` |
|
|
||||||
| `SEA` | Seattle Mariners | `SEA.png` |
|
|
||||||
| `STL` | St. Louis Cardinals | `STL.png` |
|
|
||||||
| `TB` | Tampa Bay Rays | `TB.png` |
|
|
||||||
| `TEX` | Texas Rangers | `TEX.png` |
|
|
||||||
| `TOR` | Toronto Blue Jays | `TOR.png` |
|
|
||||||
| `WSH` | Washington Nationals | `WSH.png` |
|
|
||||||
|
|
||||||
### NHL
|
|
||||||
|
|
||||||
| Abbreviation | Team Name | Logo File |
|
|
||||||
|--------------|-----------|-----------|
|
|
||||||
| `ANA` | Anaheim Ducks | `ANA.png` |
|
|
||||||
| `ARI` | Arizona Coyotes | `ARI.png` |
|
|
||||||
| `BOS` | Boston Bruins | `BOS.png` |
|
|
||||||
| `BUF` | Buffalo Sabres | `BUF.png` |
|
|
||||||
| `CGY` | Calgary Flames | `CGY.png` |
|
|
||||||
| `CAR` | Carolina Hurricanes | `CAR.png` |
|
|
||||||
| `CHI` | Chicago Blackhawks | `CHI.png` |
|
|
||||||
| `COL` | Colorado Avalanche | `COL.png` |
|
|
||||||
| `CBJ` | Columbus Blue Jackets | `CBJ.png` |
|
|
||||||
| `DAL` | Dallas Stars | `DAL.png` |
|
|
||||||
| `DET` | Detroit Red Wings | `DET.png` |
|
|
||||||
| `EDM` | Edmonton Oilers | `EDM.png` |
|
|
||||||
| `FLA` | Florida Panthers | `FLA.png` |
|
|
||||||
| `LAK` | Los Angeles Kings | `LAK.png` |
|
|
||||||
| `MIN` | Minnesota Wild | `MIN.png` |
|
|
||||||
| `MTL` | Montreal Canadiens | `MTL.png` |
|
|
||||||
| `NSH` | Nashville Predators | `NSH.png` |
|
|
||||||
| `NJ` | New Jersey Devils | `NJ.png` |
|
|
||||||
| `NYI` | New York Islanders | `NYI.png` |
|
|
||||||
| `NYR` | New York Rangers | `NYR.png` |
|
|
||||||
| `OTT` | Ottawa Senators | `OTT.png` |
|
|
||||||
| `PHI` | Philadelphia Flyers | `PHI.png` |
|
|
||||||
| `PIT` | Pittsburgh Penguins | `PIT.png` |
|
|
||||||
| `SJ` | San Jose Sharks | `SJ.png` |
|
|
||||||
| `SEA` | Seattle Kraken | `SEA.png` |
|
|
||||||
| `STL` | St. Louis Blues | `STL.png` |
|
|
||||||
| `TB` | Tampa Bay Lightning | `TB.png` |
|
|
||||||
| `TOR` | Toronto Maple Leafs | `TOR.png` |
|
|
||||||
| `VAN` | Vancouver Canucks | `VAN.png` |
|
|
||||||
| `VGS` | Vegas Golden Knights | `VGS.png` |
|
|
||||||
| `WSH` | Washington Capitals | `WSH.png` |
|
|
||||||
| `WPG` | Winnipeg Jets | `WPG.png` |
|
|
||||||
|
|
||||||
## Configuration Examples
|
|
||||||
|
|
||||||
### Soccer Configuration
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"soccer_scoreboard": {
|
|
||||||
"enabled": true,
|
|
||||||
"leagues": ["eng.1", "esp.1", "por.1"],
|
|
||||||
"favorite_teams": ["LIV", "BAR", "BEN"],
|
|
||||||
"show_favorite_teams_only": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### NFL Configuration
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"nfl_scoreboard": {
|
|
||||||
"enabled": true,
|
|
||||||
"favorite_teams": ["TB", "DAL"],
|
|
||||||
"show_favorite_teams_only": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### NBA Configuration
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"nba_scoreboard": {
|
|
||||||
"enabled": true,
|
|
||||||
"favorite_teams": ["LAL", "GSW"],
|
|
||||||
"show_favorite_teams_only": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Logo File Locations
|
|
||||||
|
|
||||||
- **Soccer Logos**: `assets/sports/soccer_logos/`
|
|
||||||
- **NFL Logos**: `assets/sports/nfl_logos/`
|
|
||||||
- **NBA Logos**: `assets/sports/nba_logos/`
|
|
||||||
- **MLB Logos**: `assets/sports/mlb_logos/`
|
|
||||||
- **NHL Logos**: `assets/sports/nhl_logos/`
|
|
||||||
- **NCAA Logos**: `assets/sports/ncaa_fbs_logos/`
|
|
||||||
|
|
||||||
## Logo Download
|
|
||||||
|
|
||||||
Logos are automatically downloaded from ESPN API when missing. Use the logo checker script:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd test
|
|
||||||
python check_soccer_logos.py
|
|
||||||
```
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
- Team abbreviations are case-sensitive
|
|
||||||
- Logo files must be in PNG format
|
|
||||||
- All logos are automatically converted to RGBA format for LEDMatrix compatibility
|
|
||||||
- Placeholder logos are created if real logos cannot be downloaded
|
|
||||||
- The system supports both light and dark logo variants when available
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
**Missing Logos:**
|
|
||||||
1. Check if the team abbreviation is correct
|
|
||||||
2. Verify the league is supported
|
|
||||||
3. Run the logo downloader script
|
|
||||||
4. Check file permissions in the logo directory
|
|
||||||
|
|
||||||
**Configuration Issues:**
|
|
||||||
1. Ensure team abbreviations match exactly (case-sensitive)
|
|
||||||
2. Verify league slugs are correct
|
|
||||||
3. Check that the sport is enabled in configuration
|
|
||||||
4. Review log files for detailed error messages
|
|
||||||
|
|
||||||
For additional help, refer to the main [Configuration Guide](Configuration.md) or [Troubleshooting Guide](Troubleshooting.md).
|
|
||||||
@@ -1,379 +0,0 @@
|
|||||||
# Web Interface Installation Guide
|
|
||||||
|
|
||||||
The LEDMatrix system includes a modern web interface that allows you to control and configure the display remotely. This guide covers installation, configuration, and troubleshooting.
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
The web interface provides:
|
|
||||||
- **Real-time Display Preview**: See what's currently displayed on the LED matrix
|
|
||||||
- **Configuration Management**: Edit settings through a web interface
|
|
||||||
- **On-Demand Controls**: Start specific displays (weather, stocks, sports) on demand
|
|
||||||
- **Service Management**: Start/stop the main display service
|
|
||||||
- **System Controls**: Restart, update code, and manage the system
|
|
||||||
- **API Metrics**: Monitor API usage and system performance
|
|
||||||
- **Logs**: View system logs in real-time
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
### Prerequisites
|
|
||||||
|
|
||||||
- LEDMatrix system already installed and configured (or run `first_time_install.sh` first)
|
|
||||||
- Python 3.7+ installed
|
|
||||||
- Network access to the Raspberry Pi
|
|
||||||
|
|
||||||
### Step 1: Install the Web Interface Service
|
|
||||||
|
|
||||||
1. Navigate to your LEDMatrix directory:
|
|
||||||
```bash
|
|
||||||
cd /home/ledpi/LEDMatrix
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Make the install script executable:
|
|
||||||
```bash
|
|
||||||
chmod +x install_web_service.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Run the install script with sudo:
|
|
||||||
```bash
|
|
||||||
sudo ./install_web_service.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
The script will:
|
|
||||||
- Copy the web service file to `/etc/systemd/system/`
|
|
||||||
- Reload systemd to recognize the new service
|
|
||||||
- Enable the service to start on boot
|
|
||||||
- Start the service immediately
|
|
||||||
- Show the service status
|
|
||||||
|
|
||||||
**Note**: The first time the service starts, it will automatically:
|
|
||||||
- Create a Python virtual environment (`venv_web_v2`)
|
|
||||||
- Install required dependencies (Flask, numpy, requests, Google APIs, Spotify, etc.)
|
|
||||||
- Install the rgbmatrix module from the local source
|
|
||||||
|
|
||||||
This process may take several minutes on the first run as it installs all dependencies needed by the LEDMatrix system.
|
|
||||||
|
|
||||||
### Step 2: Configure Web Interface Autostart
|
|
||||||
|
|
||||||
1. Edit your configuration file:
|
|
||||||
```bash
|
|
||||||
sudo nano config/config.json
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Ensure the web interface autostart is enabled:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"web_display_autostart": true
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Save and exit (Ctrl+X, Y, Enter)
|
|
||||||
|
|
||||||
### Step 3: Access the Web Interface
|
|
||||||
|
|
||||||
Once installed, you can access the web interface at:
|
|
||||||
```
|
|
||||||
http://your-pi-ip:5001
|
|
||||||
```
|
|
||||||
|
|
||||||
Replace `your-pi-ip` with your Raspberry Pi's IP address.
|
|
||||||
|
|
||||||
## Service Management
|
|
||||||
|
|
||||||
### Check Service Status
|
|
||||||
```bash
|
|
||||||
sudo systemctl status ledmatrix-web.service
|
|
||||||
```
|
|
||||||
|
|
||||||
### View Service Logs
|
|
||||||
```bash
|
|
||||||
journalctl -u ledmatrix-web.service -f
|
|
||||||
```
|
|
||||||
|
|
||||||
### Start/Stop the Service
|
|
||||||
```bash
|
|
||||||
# Start the service
|
|
||||||
sudo systemctl start ledmatrix-web.service
|
|
||||||
|
|
||||||
# Stop the service
|
|
||||||
sudo systemctl stop ledmatrix-web.service
|
|
||||||
|
|
||||||
# Restart the service
|
|
||||||
sudo systemctl restart ledmatrix-web.service
|
|
||||||
```
|
|
||||||
|
|
||||||
### Enable/Disable Autostart
|
|
||||||
```bash
|
|
||||||
# Enable autostart on boot
|
|
||||||
sudo systemctl enable ledmatrix-web.service
|
|
||||||
|
|
||||||
# Disable autostart on boot
|
|
||||||
sudo systemctl disable ledmatrix-web.service
|
|
||||||
```
|
|
||||||
|
|
||||||
## Web Interface Features
|
|
||||||
|
|
||||||
### Overview Tab
|
|
||||||
- System status and uptime
|
|
||||||
- Current display mode
|
|
||||||
- API usage metrics
|
|
||||||
- Quick controls for starting/stopping services
|
|
||||||
|
|
||||||
### Configuration Tab
|
|
||||||
- Edit main configuration settings
|
|
||||||
- Modify display durations
|
|
||||||
- Configure sports teams and preferences
|
|
||||||
- Update API keys and endpoints
|
|
||||||
|
|
||||||
### Sports Tab
|
|
||||||
- Configure individual sports leagues
|
|
||||||
- Set favorite teams
|
|
||||||
- Enable/disable specific display modes
|
|
||||||
- On-demand controls for each sport
|
|
||||||
|
|
||||||
### Weather Tab
|
|
||||||
- Configure weather settings
|
|
||||||
- Set location and units
|
|
||||||
- On-demand weather display controls
|
|
||||||
|
|
||||||
### Stocks Tab
|
|
||||||
- Configure stock and crypto symbols
|
|
||||||
- Set update intervals
|
|
||||||
- On-demand stock display controls
|
|
||||||
|
|
||||||
### On-Demand Controls
|
|
||||||
- Start specific displays immediately
|
|
||||||
- Stop on-demand displays
|
|
||||||
- View current on-demand status
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Web Interface Not Accessible After Restart
|
|
||||||
|
|
||||||
**Symptoms:**
|
|
||||||
- Can't access `http://your-pi-ip:5001` after system restart
|
|
||||||
- Service appears to be running but web interface doesn't respond
|
|
||||||
|
|
||||||
**Diagnosis:**
|
|
||||||
1. Check if the web service is running:
|
|
||||||
```bash
|
|
||||||
sudo systemctl status ledmatrix-web.service
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Verify the service is enabled:
|
|
||||||
```bash
|
|
||||||
sudo systemctl is-enabled ledmatrix-web.service
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Check logs for errors:
|
|
||||||
```bash
|
|
||||||
journalctl -u ledmatrix-web.service -f
|
|
||||||
```
|
|
||||||
|
|
||||||
4. Ensure `web_display_autostart` is set to `true` in `config/config.json`
|
|
||||||
|
|
||||||
**Solutions:**
|
|
||||||
1. If service is not running, start it:
|
|
||||||
```bash
|
|
||||||
sudo systemctl start ledmatrix-web.service
|
|
||||||
```
|
|
||||||
|
|
||||||
2. If service is not enabled, enable it:
|
|
||||||
```bash
|
|
||||||
sudo systemctl enable ledmatrix-web.service
|
|
||||||
```
|
|
||||||
|
|
||||||
3. If configuration is incorrect, fix it:
|
|
||||||
```bash
|
|
||||||
sudo nano config/config.json
|
|
||||||
# Set "web_display_autostart": true
|
|
||||||
```
|
|
||||||
|
|
||||||
### Port 5001 Not Accessible
|
|
||||||
|
|
||||||
**Symptoms:**
|
|
||||||
- Connection refused on port 5001
|
|
||||||
- Service running but can't connect
|
|
||||||
|
|
||||||
**Diagnosis:**
|
|
||||||
1. Check if the service is running on the correct port:
|
|
||||||
```bash
|
|
||||||
sudo netstat -tlnp | grep 5001
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Verify firewall settings:
|
|
||||||
```bash
|
|
||||||
sudo ufw status
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Check if another service is using port 5001:
|
|
||||||
```bash
|
|
||||||
sudo lsof -i :5001
|
|
||||||
```
|
|
||||||
|
|
||||||
**Solutions:**
|
|
||||||
1. If port is blocked by firewall, allow it:
|
|
||||||
```bash
|
|
||||||
sudo ufw allow 5001
|
|
||||||
```
|
|
||||||
|
|
||||||
2. If another service is using the port, stop it or change the web interface port
|
|
||||||
|
|
||||||
### Service Fails to Start
|
|
||||||
|
|
||||||
**Symptoms:**
|
|
||||||
- Service shows as failed in systemctl status
|
|
||||||
- Error messages in logs
|
|
||||||
- Common errors:
|
|
||||||
- `ModuleNotFoundError: No module named 'numpy'`
|
|
||||||
- `ModuleNotFoundError: No module named 'google'`
|
|
||||||
- `ModuleNotFoundError: No module named 'spotipy'`
|
|
||||||
|
|
||||||
**Diagnosis:**
|
|
||||||
1. Check service logs:
|
|
||||||
```bash
|
|
||||||
journalctl -u ledmatrix-web.service -n 50
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Verify Python dependencies:
|
|
||||||
```bash
|
|
||||||
python3 -c "import flask, flask_socketio, PIL, numpy, google, spotipy"
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Check virtual environment:
|
|
||||||
```bash
|
|
||||||
ls -la venv_web_v2/
|
|
||||||
```
|
|
||||||
|
|
||||||
**Solutions:**
|
|
||||||
1. **Most Common Fix**: The service will automatically create the virtual environment and install dependencies on first run. If it fails, restart the service:
|
|
||||||
```bash
|
|
||||||
sudo systemctl restart ledmatrix-web.service
|
|
||||||
```
|
|
||||||
|
|
||||||
2. If dependencies are missing, install them manually:
|
|
||||||
```bash
|
|
||||||
# Create virtual environment
|
|
||||||
python3 -m venv venv_web_v2
|
|
||||||
source venv_web_v2/bin/activate
|
|
||||||
pip install -r requirements_web_v2.txt
|
|
||||||
|
|
||||||
# Install rgbmatrix module
|
|
||||||
pip install -e rpi-rgb-led-matrix-master/bindings/python
|
|
||||||
```
|
|
||||||
|
|
||||||
3. If virtual environment is corrupted, recreate it:
|
|
||||||
```bash
|
|
||||||
rm -rf venv_web_v2
|
|
||||||
sudo systemctl restart ledmatrix-web.service
|
|
||||||
```
|
|
||||||
|
|
||||||
4. If permissions are wrong, fix them:
|
|
||||||
```bash
|
|
||||||
sudo chown -R ledpi:ledpi /home/ledpi/LEDMatrix
|
|
||||||
sudo chmod +x install_web_service.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
### Missing Dependencies
|
|
||||||
|
|
||||||
**Symptoms:**
|
|
||||||
- Import errors for specific modules (google, spotipy, numpy, etc.)
|
|
||||||
- Service fails during startup with ModuleNotFoundError
|
|
||||||
|
|
||||||
**Cause:**
|
|
||||||
The web interface imports all LEDMatrix modules, which require the same dependencies as the main system.
|
|
||||||
|
|
||||||
**Solution:**
|
|
||||||
The updated `requirements_web_v2.txt` now includes all necessary dependencies. If you're still seeing issues:
|
|
||||||
|
|
||||||
1. Ensure you're using the latest requirements file
|
|
||||||
2. Recreate the virtual environment:
|
|
||||||
```bash
|
|
||||||
rm -rf venv_web_v2
|
|
||||||
sudo systemctl restart ledmatrix-web.service
|
|
||||||
```
|
|
||||||
|
|
||||||
3. If specific modules are still missing, install them manually:
|
|
||||||
```bash
|
|
||||||
source venv_web_v2/bin/activate
|
|
||||||
pip install google-auth-oauthlib google-api-python-client spotipy
|
|
||||||
```
|
|
||||||
|
|
||||||
### Import Errors
|
|
||||||
|
|
||||||
**Symptoms:**
|
|
||||||
- Service fails with ImportError messages
|
|
||||||
- Main display service also fails to start
|
|
||||||
|
|
||||||
**Cause:**
|
|
||||||
The source modules try to import from `web_interface_v2`, which can fail when the web interface isn't running.
|
|
||||||
|
|
||||||
**Solution:**
|
|
||||||
The import errors have been fixed with try/except blocks. If you still see issues, ensure all source files have the proper import handling:
|
|
||||||
|
|
||||||
```python
|
|
||||||
try:
|
|
||||||
from web_interface_v2 import increment_api_counter
|
|
||||||
except ImportError:
|
|
||||||
# Fallback if web interface is not available
|
|
||||||
def increment_api_counter(kind: str, count: int = 1):
|
|
||||||
pass
|
|
||||||
```
|
|
||||||
|
|
||||||
## Manual Installation (Alternative)
|
|
||||||
|
|
||||||
If the automated installation script doesn't work, you can install manually:
|
|
||||||
|
|
||||||
1. Copy the service file:
|
|
||||||
```bash
|
|
||||||
sudo cp ledmatrix-web.service /etc/systemd/system/
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Reload systemd:
|
|
||||||
```bash
|
|
||||||
sudo systemctl daemon-reload
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Enable and start the service:
|
|
||||||
```bash
|
|
||||||
sudo systemctl enable ledmatrix-web.service
|
|
||||||
sudo systemctl start ledmatrix-web.service
|
|
||||||
```
|
|
||||||
|
|
||||||
## Security Considerations
|
|
||||||
|
|
||||||
- The web interface runs on port 5001 by default
|
|
||||||
- Consider using a reverse proxy (nginx) for production use
|
|
||||||
- Change default ports if needed
|
|
||||||
- Use HTTPS in production environments
|
|
||||||
- Restrict access to trusted networks
|
|
||||||
|
|
||||||
## Uninstallation
|
|
||||||
|
|
||||||
To remove the web interface service:
|
|
||||||
|
|
||||||
1. Stop and disable the service:
|
|
||||||
```bash
|
|
||||||
sudo systemctl stop ledmatrix-web.service
|
|
||||||
sudo systemctl disable ledmatrix-web.service
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Remove the service file:
|
|
||||||
```bash
|
|
||||||
sudo rm /etc/systemd/system/ledmatrix-web.service
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Reload systemd:
|
|
||||||
```bash
|
|
||||||
sudo systemctl daemon-reload
|
|
||||||
```
|
|
||||||
|
|
||||||
4. Set `web_display_autostart` to `false` in `config/config.json` if desired
|
|
||||||
|
|
||||||
## Support
|
|
||||||
|
|
||||||
If you continue to have issues:
|
|
||||||
|
|
||||||
1. Check the main README.md for general troubleshooting
|
|
||||||
2. Review the service logs for specific error messages
|
|
||||||
3. Verify your system meets all prerequisites
|
|
||||||
4. Ensure all dependencies are properly installed
|
|
||||||
@@ -1,156 +0,0 @@
|
|||||||
# LED Matrix Web Interface V2 - Enhanced Summary
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
The enhanced LED Matrix Web Interface V2 now includes comprehensive configuration options, improved display preview, CPU utilization monitoring, and all features from the original web interface while maintaining a modern, user-friendly design.
|
|
||||||
|
|
||||||
## Key Enhancements
|
|
||||||
|
|
||||||
### 1. Complete LED Matrix Configuration Options
|
|
||||||
- **Hardware Settings**: All LED Matrix hardware options are now configurable through the web UI
|
|
||||||
- Rows, Columns, Chain Length, Parallel chains
|
|
||||||
- Brightness (with real-time slider)
|
|
||||||
- Hardware Mapping (Adafruit HAT PWM, HAT, Regular, Pi1)
|
|
||||||
- GPIO Slowdown, Scan Mode
|
|
||||||
- PWM Bits, PWM Dither Bits, PWM LSB Nanoseconds
|
|
||||||
- Limit Refresh Rate, Hardware Pulsing, Inverse Colors
|
|
||||||
- Show Refresh Rate, Short Date Format options
|
|
||||||
|
|
||||||
### 2. Enhanced System Monitoring
|
|
||||||
- **CPU Utilization**: Real-time CPU usage percentage display
|
|
||||||
- **Memory Usage**: Improved memory monitoring using psutil
|
|
||||||
- **Disk Usage**: Added disk space monitoring
|
|
||||||
- **CPU Temperature**: Existing temperature monitoring preserved
|
|
||||||
- **System Uptime**: Real-time uptime display
|
|
||||||
- **Service Status**: LED Matrix service status monitoring
|
|
||||||
|
|
||||||
### 3. Improved Display Preview
|
|
||||||
- **8x Scaling**: Increased from 4x to 8x scaling for better visibility
|
|
||||||
- **Better Error Handling**: Proper fallback when no display data is available
|
|
||||||
- **Smoother Updates**: Increased update frequency from 10fps to 20fps
|
|
||||||
- **Enhanced Styling**: Better border and background styling for the preview area
|
|
||||||
|
|
||||||
### 4. Comprehensive Configuration Tabs
|
|
||||||
- **Overview**: System stats with CPU, memory, temperature, disk usage
|
|
||||||
- **Schedule**: Display on/off scheduling
|
|
||||||
- **Display**: Complete LED Matrix hardware configuration
|
|
||||||
- **Sports**: Sports leagues configuration (placeholder for full implementation)
|
|
||||||
- **Weather**: Weather service configuration
|
|
||||||
- **Stocks**: Stock and cryptocurrency ticker configuration
|
|
||||||
- **Features**: Additional features like clock, text display, etc.
|
|
||||||
- **Music**: Music display configuration (YouTube Music, Spotify)
|
|
||||||
- **Calendar**: Google Calendar integration settings
|
|
||||||
- **News**: RSS news feeds management with custom feeds
|
|
||||||
- **API Keys**: Secure API key management for all services
|
|
||||||
- **Editor**: Visual display editor for custom layouts
|
|
||||||
- **Actions**: System control actions (start/stop, reboot, updates)
|
|
||||||
- **Raw JSON**: Direct JSON configuration editing with validation
|
|
||||||
- **Logs**: System logs viewing and refresh
|
|
||||||
|
|
||||||
### 5. Enhanced JSON Editor
|
|
||||||
- **Real-time Validation**: Live JSON syntax validation
|
|
||||||
- **Visual Status Indicators**: Color-coded status (Valid/Invalid/Warning)
|
|
||||||
- **Format Function**: Automatic JSON formatting
|
|
||||||
- **Error Details**: Detailed error messages with line numbers
|
|
||||||
- **Syntax Highlighting**: Monospace font with proper styling
|
|
||||||
|
|
||||||
### 6. News Manager Integration
|
|
||||||
- **RSS Feed Management**: Add/remove custom RSS feeds
|
|
||||||
- **Feed Selection**: Enable/disable built-in news feeds
|
|
||||||
- **Headlines Configuration**: Configure headlines per feed
|
|
||||||
- **Rotation Settings**: Enable headline rotation
|
|
||||||
- **Status Monitoring**: Real-time news manager status
|
|
||||||
|
|
||||||
### 7. Form Handling & Validation
|
|
||||||
- **Async Form Submission**: All forms use modern async/await patterns
|
|
||||||
- **Real-time Feedback**: Immediate success/error notifications
|
|
||||||
- **Input Validation**: Client-side and server-side validation
|
|
||||||
- **Auto-save Features**: Some settings auto-save on change
|
|
||||||
|
|
||||||
### 8. Responsive Design Improvements
|
|
||||||
- **Mobile Friendly**: Better mobile responsiveness
|
|
||||||
- **Flexible Layout**: Grid-based responsive layout
|
|
||||||
- **Tab Wrapping**: Tabs wrap on smaller screens
|
|
||||||
- **Scrollable Content**: Tab content scrolls when needed
|
|
||||||
|
|
||||||
### 9. Backend Enhancements
|
|
||||||
- **psutil Integration**: Added psutil for better system monitoring
|
|
||||||
- **Route Compatibility**: All original web interface routes preserved
|
|
||||||
- **Error Handling**: Improved error handling and logging
|
|
||||||
- **Configuration Management**: Better config file handling
|
|
||||||
|
|
||||||
### 10. User Experience Improvements
|
|
||||||
- **Loading States**: Loading indicators for async operations
|
|
||||||
- **Connection Status**: WebSocket connection status indicator
|
|
||||||
- **Notifications**: Toast-style notifications for all actions
|
|
||||||
- **Tooltips & Descriptions**: Helpful descriptions for all settings
|
|
||||||
- **Visual Feedback**: Hover effects and transitions
|
|
||||||
|
|
||||||
## Technical Implementation
|
|
||||||
|
|
||||||
### Dependencies Added
|
|
||||||
- `psutil>=5.9.0` - System monitoring
|
|
||||||
- Updated Flask and related packages for better compatibility
|
|
||||||
|
|
||||||
### File Structure
|
|
||||||
```
|
|
||||||
├── web_interface_v2.py # Enhanced backend with all features
|
|
||||||
├── templates/index_v2.html # Complete frontend with all tabs
|
|
||||||
├── requirements_web_v2.txt # Updated dependencies
|
|
||||||
├── start_web_v2.py # Startup script (unchanged)
|
|
||||||
└── WEB_INTERFACE_V2_ENHANCED_SUMMARY.md # This summary
|
|
||||||
```
|
|
||||||
|
|
||||||
### Key Features Preserved from Original
|
|
||||||
- All configuration options from the original web interface
|
|
||||||
- JSON linter with validation and formatting
|
|
||||||
- System actions (start/stop service, reboot, git pull)
|
|
||||||
- API key management
|
|
||||||
- News manager functionality
|
|
||||||
- Sports configuration
|
|
||||||
- Display duration settings
|
|
||||||
- All form validation and error handling
|
|
||||||
|
|
||||||
### New Features Added
|
|
||||||
- CPU utilization monitoring
|
|
||||||
- Enhanced display preview (8x scaling, 20fps)
|
|
||||||
- Complete LED Matrix hardware configuration
|
|
||||||
- Improved responsive design
|
|
||||||
- Better error handling and user feedback
|
|
||||||
- Real-time system stats updates
|
|
||||||
- Enhanced JSON editor with validation
|
|
||||||
- Visual status indicators throughout
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
1. **Start the Enhanced Interface**:
|
|
||||||
```bash
|
|
||||||
python3 start_web_v2.py
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Access the Interface**:
|
|
||||||
Open browser to `http://your-pi-ip:5001`
|
|
||||||
|
|
||||||
3. **Configure LED Matrix**:
|
|
||||||
- Go to "Display" tab for hardware settings
|
|
||||||
- Use "Schedule" tab for timing
|
|
||||||
- Configure services in respective tabs
|
|
||||||
|
|
||||||
4. **Monitor System**:
|
|
||||||
- "Overview" tab shows real-time stats
|
|
||||||
- CPU, memory, disk, and temperature monitoring
|
|
||||||
|
|
||||||
5. **Edit Configurations**:
|
|
||||||
- Use individual tabs for specific settings
|
|
||||||
- "Raw JSON" tab for direct configuration editing
|
|
||||||
- Real-time validation and error feedback
|
|
||||||
|
|
||||||
## Benefits
|
|
||||||
|
|
||||||
1. **Complete Control**: Every LED Matrix configuration option is now accessible
|
|
||||||
2. **Better Monitoring**: Real-time system performance monitoring
|
|
||||||
3. **Improved Usability**: Modern, responsive interface with better UX
|
|
||||||
4. **Enhanced Preview**: Better display preview with higher resolution
|
|
||||||
5. **Comprehensive Management**: All features in one unified interface
|
|
||||||
6. **Backward Compatibility**: All original features preserved and enhanced
|
|
||||||
|
|
||||||
The enhanced web interface provides a complete, professional-grade management system for LED Matrix displays while maintaining ease of use and reliability.
|
|
||||||
@@ -1,587 +0,0 @@
|
|||||||
# 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**:
|
|
||||||
```python
|
|
||||||
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**:
|
|
||||||
```python
|
|
||||||
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**:
|
|
||||||
```python
|
|
||||||
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**:
|
|
||||||
```python
|
|
||||||
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:
|
|
||||||
|
|
||||||
```python
|
|
||||||
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:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# 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:
|
|
||||||
|
|
||||||
```python
|
|
||||||
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:
|
|
||||||
|
|
||||||
```python
|
|
||||||
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
|
|
||||||
|
|
||||||
```python
|
|
||||||
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
|
|
||||||
|
|
||||||
```python
|
|
||||||
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
|
|
||||||
|
|
||||||
```python
|
|
||||||
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
|
|
||||||
|
|
||||||
```python
|
|
||||||
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
|
|
||||||
|
|
||||||
```python
|
|
||||||
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
|
|
||||||
|
|
||||||
```python
|
|
||||||
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
|
|
||||||
|
|
||||||
```python
|
|
||||||
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
|
|
||||||
|
|
||||||
```python
|
|
||||||
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
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[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
|
|
||||||
|
|
||||||
```python
|
|
||||||
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
|
|
||||||
|
|
||||||
```python
|
|
||||||
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.*
|
|
||||||
@@ -1,654 +0,0 @@
|
|||||||
# Configuration Guide
|
|
||||||
|
|
||||||
The LEDMatrix system is configured through JSON files that control every aspect of the display. This guide covers all configuration options and their effects.
|
|
||||||
|
|
||||||
## Configuration Files
|
|
||||||
|
|
||||||
### Main Configuration (`config/config.json`)
|
|
||||||
Contains all non-sensitive settings for the system.
|
|
||||||
|
|
||||||
### Secrets Configuration (`config/config_secrets.json`)
|
|
||||||
Contains API keys and sensitive credentials.
|
|
||||||
|
|
||||||
## System Configuration
|
|
||||||
|
|
||||||
### Display Hardware Settings
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"display": {
|
|
||||||
"hardware": {
|
|
||||||
"rows": 32,
|
|
||||||
"cols": 64,
|
|
||||||
"chain_length": 2,
|
|
||||||
"parallel": 1,
|
|
||||||
"brightness": 95,
|
|
||||||
"hardware_mapping": "adafruit-hat-pwm",
|
|
||||||
"scan_mode": 0,
|
|
||||||
"pwm_bits": 9,
|
|
||||||
"pwm_dither_bits": 1,
|
|
||||||
"pwm_lsb_nanoseconds": 130,
|
|
||||||
"disable_hardware_pulsing": false,
|
|
||||||
"inverse_colors": false,
|
|
||||||
"show_refresh_rate": false,
|
|
||||||
"limit_refresh_rate_hz": 120
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"gpio_slowdown": 3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Hardware Settings Explained**:
|
|
||||||
- **`rows`/`cols`**: Physical LED matrix dimensions (32x64 for 2 panels)
|
|
||||||
- **`chain_length`**: Number of LED panels connected (2 for 128x32 total)
|
|
||||||
- **`parallel`**: Number of parallel chains (usually 1)
|
|
||||||
- **`brightness`**: Display brightness (0-100)
|
|
||||||
- **`hardware_mapping`**:
|
|
||||||
- `"adafruit-hat-pwm"`: With jumper mod (recommended)
|
|
||||||
- `"adafruit-hat"`: Without jumper mod
|
|
||||||
- **`pwm_bits`**: Color depth (8-11, higher = better colors)
|
|
||||||
- **`gpio_slowdown`**: Timing adjustment (3 for Pi 3, 4 for Pi 4)
|
|
||||||
|
|
||||||
### Display Durations
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"display": {
|
|
||||||
"display_durations": {
|
|
||||||
"clock": 15,
|
|
||||||
"weather": 30,
|
|
||||||
"stocks": 30,
|
|
||||||
"hourly_forecast": 30,
|
|
||||||
"daily_forecast": 30,
|
|
||||||
"stock_news": 20,
|
|
||||||
"odds_ticker": 60,
|
|
||||||
"nhl_live": 30,
|
|
||||||
"nhl_recent": 30,
|
|
||||||
"nhl_upcoming": 30,
|
|
||||||
"nba_live": 30,
|
|
||||||
"nba_recent": 30,
|
|
||||||
"nba_upcoming": 30,
|
|
||||||
"nfl_live": 30,
|
|
||||||
"nfl_recent": 30,
|
|
||||||
"nfl_upcoming": 30,
|
|
||||||
"ncaa_fb_live": 30,
|
|
||||||
"ncaa_fb_recent": 30,
|
|
||||||
"ncaa_fb_upcoming": 30,
|
|
||||||
"ncaa_baseball_live": 30,
|
|
||||||
"ncaa_baseball_recent": 30,
|
|
||||||
"ncaa_baseball_upcoming": 30,
|
|
||||||
"calendar": 30,
|
|
||||||
"youtube": 30,
|
|
||||||
"mlb_live": 30,
|
|
||||||
"mlb_recent": 30,
|
|
||||||
"mlb_upcoming": 30,
|
|
||||||
"milb_live": 30,
|
|
||||||
"milb_recent": 30,
|
|
||||||
"milb_upcoming": 30,
|
|
||||||
"text_display": 10,
|
|
||||||
"soccer_live": 30,
|
|
||||||
"soccer_recent": 30,
|
|
||||||
"soccer_upcoming": 30,
|
|
||||||
"ncaam_basketball_live": 30,
|
|
||||||
"ncaam_basketball_recent": 30,
|
|
||||||
"ncaam_basketball_upcoming": 30,
|
|
||||||
"music": 30,
|
|
||||||
"of_the_day": 40
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Duration Settings**:
|
|
||||||
- Each value controls how long (in seconds) that display mode shows
|
|
||||||
- Higher values = more time for that content
|
|
||||||
- Total rotation time = sum of all enabled durations
|
|
||||||
|
|
||||||
### System Settings
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"web_display_autostart": true,
|
|
||||||
"schedule": {
|
|
||||||
"enabled": true,
|
|
||||||
"start_time": "07:00",
|
|
||||||
"end_time": "23:00"
|
|
||||||
},
|
|
||||||
"timezone": "America/Chicago",
|
|
||||||
"location": {
|
|
||||||
"city": "Dallas",
|
|
||||||
"state": "Texas",
|
|
||||||
"country": "US"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**System Settings Explained**:
|
|
||||||
- **`web_display_autostart`**: Start web interface automatically
|
|
||||||
- **`schedule`**: Control when display is active
|
|
||||||
- **`timezone`**: System timezone for accurate times
|
|
||||||
- **`location`**: Default location for weather and other location-based services
|
|
||||||
|
|
||||||
## Display Manager Configurations
|
|
||||||
|
|
||||||
### Clock Configuration
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"clock": {
|
|
||||||
"enabled": false,
|
|
||||||
"format": "%I:%M %p",
|
|
||||||
"update_interval": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Clock Settings**:
|
|
||||||
- **`enabled`**: Enable/disable clock display
|
|
||||||
- **`format`**: Time format string (Python strftime)
|
|
||||||
- **`update_interval`**: Update frequency in seconds
|
|
||||||
|
|
||||||
**Common Time Formats**:
|
|
||||||
- `"%I:%M %p"` → `12:34 PM`
|
|
||||||
- `"%H:%M"` → `14:34`
|
|
||||||
- `"%I:%M:%S %p"` → `12:34:56 PM`
|
|
||||||
|
|
||||||
### Weather Configuration
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"weather": {
|
|
||||||
"enabled": false,
|
|
||||||
"update_interval": 1800,
|
|
||||||
"units": "imperial",
|
|
||||||
"display_format": "{temp}°F\n{condition}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Weather Settings**:
|
|
||||||
- **`enabled`**: Enable/disable weather display
|
|
||||||
- **`update_interval`**: Update frequency in seconds (1800 = 30 minutes)
|
|
||||||
- **`units`**: `"imperial"` (Fahrenheit) or `"metric"` (Celsius)
|
|
||||||
- **`display_format`**: Custom format string for weather display
|
|
||||||
|
|
||||||
**Weather Display Modes**:
|
|
||||||
- Current weather with icon
|
|
||||||
- Hourly forecast (next 24 hours)
|
|
||||||
- Daily forecast (next 7 days)
|
|
||||||
|
|
||||||
### Stocks Configuration
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"stocks": {
|
|
||||||
"enabled": false,
|
|
||||||
"update_interval": 600,
|
|
||||||
"scroll_speed": 1,
|
|
||||||
"scroll_delay": 0.01,
|
|
||||||
"toggle_chart": false,
|
|
||||||
"symbols": ["ASTS", "SCHD", "INTC", "NVDA", "T", "VOO", "SMCI"]
|
|
||||||
},
|
|
||||||
"crypto": {
|
|
||||||
"enabled": false,
|
|
||||||
"update_interval": 600,
|
|
||||||
"symbols": ["BTC-USD", "ETH-USD"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Stock Settings**:
|
|
||||||
- **`enabled`**: Enable/disable stock display
|
|
||||||
- **`update_interval`**: Update frequency in seconds (600 = 10 minutes)
|
|
||||||
- **`scroll_speed`**: Pixels per scroll update
|
|
||||||
- **`scroll_delay`**: Delay between scroll updates
|
|
||||||
- **`toggle_chart`**: Show/hide mini price charts
|
|
||||||
- **`symbols`**: Array of stock symbols to display
|
|
||||||
|
|
||||||
**Crypto Settings**:
|
|
||||||
- **`enabled`**: Enable/disable crypto display
|
|
||||||
- **`symbols`**: Array of crypto symbols (use `-USD` suffix)
|
|
||||||
|
|
||||||
### Stock News Configuration
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"stock_news": {
|
|
||||||
"enabled": false,
|
|
||||||
"update_interval": 3600,
|
|
||||||
"scroll_speed": 1,
|
|
||||||
"scroll_delay": 0.01,
|
|
||||||
"max_headlines_per_symbol": 1,
|
|
||||||
"headlines_per_rotation": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**News Settings**:
|
|
||||||
- **`enabled`**: Enable/disable news display
|
|
||||||
- **`update_interval`**: Update frequency in seconds
|
|
||||||
- **`max_headlines_per_symbol`**: Max headlines per stock
|
|
||||||
- **`headlines_per_rotation`**: Headlines shown per rotation
|
|
||||||
|
|
||||||
### Music Configuration
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"music": {
|
|
||||||
"enabled": true,
|
|
||||||
"preferred_source": "ytm",
|
|
||||||
"YTM_COMPANION_URL": "http://192.168.86.12:9863",
|
|
||||||
"POLLING_INTERVAL_SECONDS": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Music Settings**:
|
|
||||||
- **`enabled`**: Enable/disable music display
|
|
||||||
- **`preferred_source`**: `"spotify"` or `"ytm"`
|
|
||||||
- **`YTM_COMPANION_URL`**: YouTube Music companion server URL
|
|
||||||
- **`POLLING_INTERVAL_SECONDS`**: How often to check for updates
|
|
||||||
|
|
||||||
### Calendar Configuration
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"calendar": {
|
|
||||||
"enabled": false,
|
|
||||||
"credentials_file": "credentials.json",
|
|
||||||
"token_file": "token.pickle",
|
|
||||||
"update_interval": 3600,
|
|
||||||
"max_events": 3,
|
|
||||||
"calendars": ["birthdays"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Calendar Settings**:
|
|
||||||
- **`enabled`**: Enable/disable calendar display
|
|
||||||
- **`credentials_file`**: Google API credentials file
|
|
||||||
- **`token_file`**: Authentication token file
|
|
||||||
- **`update_interval`**: Update frequency in seconds
|
|
||||||
- **`max_events`**: Maximum events to display
|
|
||||||
- **`calendars`**: Array of calendar IDs to monitor
|
|
||||||
|
|
||||||
## Sports Configurations
|
|
||||||
|
|
||||||
### Common Sports Settings
|
|
||||||
|
|
||||||
All sports managers share these common settings:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"nhl_scoreboard": {
|
|
||||||
"enabled": false,
|
|
||||||
"live_priority": true,
|
|
||||||
"live_game_duration": 20,
|
|
||||||
"show_odds": true,
|
|
||||||
"test_mode": false,
|
|
||||||
"update_interval_seconds": 3600,
|
|
||||||
"live_update_interval": 30,
|
|
||||||
"recent_update_interval": 3600,
|
|
||||||
"upcoming_update_interval": 3600,
|
|
||||||
"show_favorite_teams_only": true,
|
|
||||||
"favorite_teams": ["TB"],
|
|
||||||
"logo_dir": "assets/sports/nhl_logos",
|
|
||||||
"show_records": true,
|
|
||||||
"display_modes": {
|
|
||||||
"nhl_live": true,
|
|
||||||
"nhl_recent": true,
|
|
||||||
"nhl_upcoming": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Common Sports Settings**:
|
|
||||||
- **`enabled`**: Enable/disable this sport
|
|
||||||
- **`live_priority`**: Give live games priority over other content
|
|
||||||
- **`live_game_duration`**: How long to show live games
|
|
||||||
- **`show_odds`**: Display betting odds (where available)
|
|
||||||
- **`test_mode`**: Use test data instead of live API
|
|
||||||
- **`update_interval_seconds`**: How often to fetch new data
|
|
||||||
- **`live_update_interval`**: How often to update live games
|
|
||||||
- **`show_favorite_teams_only`**: Only show games for favorite teams
|
|
||||||
- **`favorite_teams`**: Array of team abbreviations
|
|
||||||
- **`logo_dir`**: Directory containing team logos
|
|
||||||
- **`show_records`**: Display team win/loss records
|
|
||||||
- **`display_modes`**: Enable/disable specific display modes
|
|
||||||
|
|
||||||
### Football-Specific Settings
|
|
||||||
|
|
||||||
NFL and NCAA Football use game-based fetching:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"nfl_scoreboard": {
|
|
||||||
"enabled": false,
|
|
||||||
"recent_games_to_show": 0,
|
|
||||||
"upcoming_games_to_show": 2,
|
|
||||||
"favorite_teams": ["TB", "DAL"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Football Settings**:
|
|
||||||
- **`recent_games_to_show`**: Number of recent games to display
|
|
||||||
- **`upcoming_games_to_show`**: Number of upcoming games to display
|
|
||||||
|
|
||||||
### Soccer Configuration
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"soccer_scoreboard": {
|
|
||||||
"enabled": false,
|
|
||||||
"recent_game_hours": 168,
|
|
||||||
"favorite_teams": ["LIV"],
|
|
||||||
"leagues": ["eng.1", "esp.1", "ger.1", "ita.1", "fra.1", "uefa.champions", "usa.1"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Soccer Settings**:
|
|
||||||
- **`recent_game_hours`**: Hours back to show recent games
|
|
||||||
- **`leagues`**: Array of league codes to monitor
|
|
||||||
|
|
||||||
## Odds Ticker Configuration
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"odds_ticker": {
|
|
||||||
"enabled": false,
|
|
||||||
"show_favorite_teams_only": true,
|
|
||||||
"games_per_favorite_team": 1,
|
|
||||||
"max_games_per_league": 5,
|
|
||||||
"show_odds_only": false,
|
|
||||||
"sort_order": "soonest",
|
|
||||||
"enabled_leagues": ["nfl", "mlb", "ncaa_fb", "milb"],
|
|
||||||
"update_interval": 3600,
|
|
||||||
"scroll_speed": 1,
|
|
||||||
"scroll_delay": 0.01,
|
|
||||||
"loop": true,
|
|
||||||
"future_fetch_days": 50,
|
|
||||||
"show_channel_logos": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Odds Ticker Settings**:
|
|
||||||
- **`enabled`**: Enable/disable odds ticker
|
|
||||||
- **`show_favorite_teams_only`**: Only show odds for favorite teams
|
|
||||||
- **`games_per_favorite_team`**: Games per team to show
|
|
||||||
- **`max_games_per_league`**: Maximum games per league
|
|
||||||
- **`enabled_leagues`**: Leagues to include in ticker
|
|
||||||
- **`sort_order`**: `"soonest"` or `"latest"`
|
|
||||||
- **`future_fetch_days`**: Days ahead to fetch games
|
|
||||||
- **`show_channel_logos`**: Display broadcast network logos
|
|
||||||
|
|
||||||
## Custom Display Configurations
|
|
||||||
|
|
||||||
### Text Display
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"text_display": {
|
|
||||||
"enabled": false,
|
|
||||||
"text": "Subscribe to ChuckBuilds",
|
|
||||||
"font_path": "assets/fonts/press-start-2p.ttf",
|
|
||||||
"font_size": 8,
|
|
||||||
"scroll": true,
|
|
||||||
"scroll_speed": 40,
|
|
||||||
"text_color": [255, 0, 0],
|
|
||||||
"background_color": [0, 0, 0],
|
|
||||||
"scroll_gap_width": 32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Text Display Settings**:
|
|
||||||
- **`enabled`**: Enable/disable text display
|
|
||||||
- **`text`**: Text to display
|
|
||||||
- **`font_path`**: Path to TTF font file
|
|
||||||
- **`font_size`**: Font size in pixels
|
|
||||||
- **`scroll`**: Enable/disable scrolling
|
|
||||||
- **`scroll_speed`**: Scroll speed in pixels
|
|
||||||
- **`text_color`**: RGB color for text
|
|
||||||
- **`background_color`**: RGB color for background
|
|
||||||
- **`scroll_gap_width`**: Gap between text repetitions
|
|
||||||
|
|
||||||
### YouTube Display
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"youtube": {
|
|
||||||
"enabled": false,
|
|
||||||
"update_interval": 3600
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**YouTube Settings**:
|
|
||||||
- **`enabled`**: Enable/disable YouTube stats
|
|
||||||
- **`update_interval`**: Update frequency in seconds
|
|
||||||
|
|
||||||
### Of The Day Display
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"of_the_day": {
|
|
||||||
"enabled": true,
|
|
||||||
"display_rotate_interval": 20,
|
|
||||||
"update_interval": 3600,
|
|
||||||
"subtitle_rotate_interval": 10,
|
|
||||||
"category_order": ["word_of_the_day", "slovenian_word_of_the_day", "bible_verse_of_the_day"],
|
|
||||||
"categories": {
|
|
||||||
"word_of_the_day": {
|
|
||||||
"enabled": true,
|
|
||||||
"data_file": "of_the_day/word_of_the_day.json",
|
|
||||||
"display_name": "Word of the Day"
|
|
||||||
},
|
|
||||||
"slovenian_word_of_the_day": {
|
|
||||||
"enabled": true,
|
|
||||||
"data_file": "of_the_day/slovenian_word_of_the_day.json",
|
|
||||||
"display_name": "Slovenian Word of the Day"
|
|
||||||
},
|
|
||||||
"bible_verse_of_the_day": {
|
|
||||||
"enabled": true,
|
|
||||||
"data_file": "of_the_day/bible_verse_of_the_day.json",
|
|
||||||
"display_name": "Bible Verse of the Day"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Of The Day Settings**:
|
|
||||||
- **`enabled`**: Enable/disable of the day display
|
|
||||||
- **`display_rotate_interval`**: How long to show each category
|
|
||||||
- **`update_interval`**: Update frequency in seconds
|
|
||||||
- **`subtitle_rotate_interval`**: How long to show subtitles
|
|
||||||
- **`category_order`**: Order of categories to display
|
|
||||||
- **`categories`**: Configuration for each category
|
|
||||||
|
|
||||||
## API Configuration (config_secrets.json)
|
|
||||||
|
|
||||||
### Weather API
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"weather": {
|
|
||||||
"api_key": "your_openweathermap_api_key"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### YouTube API
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"youtube": {
|
|
||||||
"api_key": "your_youtube_api_key",
|
|
||||||
"channel_id": "your_channel_id"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Music APIs
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"music": {
|
|
||||||
"SPOTIFY_CLIENT_ID": "your_spotify_client_id",
|
|
||||||
"SPOTIFY_CLIENT_SECRET": "your_spotify_client_secret",
|
|
||||||
"SPOTIFY_REDIRECT_URI": "http://127.0.0.1:8888/callback"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Configuration Best Practices
|
|
||||||
|
|
||||||
### Performance Optimization
|
|
||||||
|
|
||||||
1. **Update Intervals**: Balance between fresh data and API limits
|
|
||||||
- Weather: 1800 seconds (30 minutes)
|
|
||||||
- Stocks: 600 seconds (10 minutes)
|
|
||||||
- Sports: 3600 seconds (1 hour)
|
|
||||||
- Music: 1 second (real-time)
|
|
||||||
|
|
||||||
2. **Display Durations**: Balance content visibility
|
|
||||||
- Live sports: 20-30 seconds
|
|
||||||
- Weather: 30 seconds
|
|
||||||
- Stocks: 30-60 seconds
|
|
||||||
- Clock: 15 seconds
|
|
||||||
|
|
||||||
3. **Favorite Teams**: Reduce API calls by focusing on specific teams
|
|
||||||
|
|
||||||
### Caching Strategy
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"cache_settings": {
|
|
||||||
"persistent_cache": true,
|
|
||||||
"cache_directory": "/var/cache/ledmatrix",
|
|
||||||
"fallback_cache": "/tmp/ledmatrix_cache"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Error Handling
|
|
||||||
|
|
||||||
- Failed API calls use cached data
|
|
||||||
- Network timeouts are handled gracefully
|
|
||||||
- Invalid data is filtered out
|
|
||||||
- Logging provides debugging information
|
|
||||||
|
|
||||||
## Configuration Validation
|
|
||||||
|
|
||||||
### Required Settings
|
|
||||||
|
|
||||||
1. **Hardware Configuration**: Must match your physical setup
|
|
||||||
2. **API Keys**: Required for enabled services
|
|
||||||
3. **Location**: Required for weather and timezone
|
|
||||||
4. **Team Abbreviations**: Must match official team codes
|
|
||||||
|
|
||||||
### Optional Settings
|
|
||||||
|
|
||||||
1. **Display Durations**: Defaults provided if missing
|
|
||||||
2. **Update Intervals**: Defaults provided if missing
|
|
||||||
3. **Favorite Teams**: Can be empty for all teams
|
|
||||||
4. **Custom Text**: Can be any string
|
|
||||||
|
|
||||||
## Configuration Examples
|
|
||||||
|
|
||||||
### Minimal Configuration
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"display": {
|
|
||||||
"hardware": {
|
|
||||||
"rows": 32,
|
|
||||||
"cols": 64,
|
|
||||||
"chain_length": 2,
|
|
||||||
"brightness": 90,
|
|
||||||
"hardware_mapping": "adafruit-hat-pwm"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"clock": {
|
|
||||||
"enabled": true
|
|
||||||
},
|
|
||||||
"weather": {
|
|
||||||
"enabled": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Full Sports Configuration
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"nhl_scoreboard": {
|
|
||||||
"enabled": true,
|
|
||||||
"favorite_teams": ["TB", "DAL"],
|
|
||||||
"show_favorite_teams_only": true
|
|
||||||
},
|
|
||||||
"nba_scoreboard": {
|
|
||||||
"enabled": true,
|
|
||||||
"favorite_teams": ["DAL"],
|
|
||||||
"show_favorite_teams_only": true
|
|
||||||
},
|
|
||||||
"nfl_scoreboard": {
|
|
||||||
"enabled": true,
|
|
||||||
"favorite_teams": ["TB", "DAL"],
|
|
||||||
"show_favorite_teams_only": true
|
|
||||||
},
|
|
||||||
"odds_ticker": {
|
|
||||||
"enabled": true,
|
|
||||||
"enabled_leagues": ["nfl", "nba", "mlb"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Financial Focus Configuration
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"stocks": {
|
|
||||||
"enabled": true,
|
|
||||||
"symbols": ["AAPL", "MSFT", "GOOGL", "TSLA", "NVDA"],
|
|
||||||
"update_interval": 300
|
|
||||||
},
|
|
||||||
"crypto": {
|
|
||||||
"enabled": true,
|
|
||||||
"symbols": ["BTC-USD", "ETH-USD", "ADA-USD"]
|
|
||||||
},
|
|
||||||
"stock_news": {
|
|
||||||
"enabled": true,
|
|
||||||
"update_interval": 1800
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Troubleshooting Configuration
|
|
||||||
|
|
||||||
### Common Issues
|
|
||||||
|
|
||||||
1. **No Display**: Check hardware configuration
|
|
||||||
2. **No Data**: Verify API keys and network
|
|
||||||
3. **Wrong Times**: Check timezone setting
|
|
||||||
4. **Performance Issues**: Reduce update frequencies
|
|
||||||
|
|
||||||
### Validation Commands
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Validate JSON syntax
|
|
||||||
python3 -m json.tool config/config.json
|
|
||||||
|
|
||||||
# Check configuration loading
|
|
||||||
python3 -c "from src.config_manager import ConfigManager; c = ConfigManager(); print('Config valid')"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*For detailed information about specific display managers, see the [Display Managers](WIKI_DISPLAY_MANAGERS.md) page.*
|
|
||||||
@@ -1,501 +0,0 @@
|
|||||||
# Display Managers Guide
|
|
||||||
|
|
||||||
The LEDMatrix system uses a modular architecture where each feature is implemented as a separate "Display Manager". This guide covers all available display managers and their configuration options.
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
Each display manager is responsible for:
|
|
||||||
1. **Data Fetching**: Retrieving data from APIs or local sources
|
|
||||||
2. **Data Processing**: Transforming raw data into displayable format
|
|
||||||
3. **Display Rendering**: Creating visual content for the LED matrix
|
|
||||||
4. **Caching**: Storing data to reduce API calls
|
|
||||||
5. **Configuration**: Managing settings and preferences
|
|
||||||
|
|
||||||
## Core Display Managers
|
|
||||||
|
|
||||||
### 🕐 Clock Manager (`src/clock.py`)
|
|
||||||
**Purpose**: Displays current time in various formats
|
|
||||||
|
|
||||||
**Configuration**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"clock": {
|
|
||||||
"enabled": true,
|
|
||||||
"format": "%I:%M %p",
|
|
||||||
"update_interval": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Features**:
|
|
||||||
- Real-time clock display
|
|
||||||
- Configurable time format
|
|
||||||
- Automatic timezone handling
|
|
||||||
- Minimal resource usage
|
|
||||||
|
|
||||||
**Display Format**: `12:34 PM`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 🌤️ Weather Manager (`src/weather_manager.py`)
|
|
||||||
**Purpose**: Displays current weather, hourly forecasts, and daily forecasts
|
|
||||||
|
|
||||||
**Configuration**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"weather": {
|
|
||||||
"enabled": true,
|
|
||||||
"update_interval": 1800,
|
|
||||||
"units": "imperial",
|
|
||||||
"display_format": "{temp}°F\n{condition}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Features**:
|
|
||||||
- Current weather conditions
|
|
||||||
- Hourly forecast (next 24 hours)
|
|
||||||
- Daily forecast (next 7 days)
|
|
||||||
- Weather icons and animations
|
|
||||||
- UV index display
|
|
||||||
- Wind speed and direction
|
|
||||||
- Humidity and pressure data
|
|
||||||
|
|
||||||
**Display Modes**:
|
|
||||||
- Current weather with icon
|
|
||||||
- Hourly forecast with temperature trend
|
|
||||||
- Daily forecast with high/low temps
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 💰 Stock Manager (`src/stock_manager.py`)
|
|
||||||
**Purpose**: Displays stock prices, crypto prices, and financial data
|
|
||||||
|
|
||||||
**Configuration**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"stocks": {
|
|
||||||
"enabled": true,
|
|
||||||
"update_interval": 600,
|
|
||||||
"scroll_speed": 1,
|
|
||||||
"scroll_delay": 0.01,
|
|
||||||
"toggle_chart": false,
|
|
||||||
"symbols": ["AAPL", "MSFT", "GOOGL", "TSLA"]
|
|
||||||
},
|
|
||||||
"crypto": {
|
|
||||||
"enabled": true,
|
|
||||||
"update_interval": 600,
|
|
||||||
"symbols": ["BTC-USD", "ETH-USD"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Features**:
|
|
||||||
- Real-time stock prices
|
|
||||||
- Cryptocurrency prices
|
|
||||||
- Price change indicators (green/red)
|
|
||||||
- Percentage change display
|
|
||||||
- Optional mini charts
|
|
||||||
- Scrolling ticker format
|
|
||||||
- Company/crypto logos
|
|
||||||
|
|
||||||
**Data Sources**:
|
|
||||||
- Yahoo Finance API for stocks
|
|
||||||
- Yahoo Finance API for crypto
|
|
||||||
- Automatic market hours detection
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 📰 Stock News Manager (`src/stock_news_manager.py`)
|
|
||||||
**Purpose**: Displays financial news headlines for configured stocks
|
|
||||||
|
|
||||||
**Configuration**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"stock_news": {
|
|
||||||
"enabled": true,
|
|
||||||
"update_interval": 3600,
|
|
||||||
"scroll_speed": 1,
|
|
||||||
"scroll_delay": 0.01,
|
|
||||||
"max_headlines_per_symbol": 1,
|
|
||||||
"headlines_per_rotation": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Features**:
|
|
||||||
- Financial news headlines
|
|
||||||
- Stock-specific news filtering
|
|
||||||
- Scrolling text display
|
|
||||||
- Configurable headline limits
|
|
||||||
- Automatic rotation
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 🎵 Music Manager (`src/music_manager.py`)
|
|
||||||
**Purpose**: Displays currently playing music from Spotify or YouTube Music
|
|
||||||
|
|
||||||
**Configuration**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"music": {
|
|
||||||
"enabled": true,
|
|
||||||
"preferred_source": "ytm",
|
|
||||||
"YTM_COMPANION_URL": "http://192.168.86.12:9863",
|
|
||||||
"POLLING_INTERVAL_SECONDS": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Features**:
|
|
||||||
- Spotify integration
|
|
||||||
- YouTube Music integration
|
|
||||||
- Album art display
|
|
||||||
- Song title and artist
|
|
||||||
- Playback status
|
|
||||||
- Real-time updates
|
|
||||||
|
|
||||||
**Supported Sources**:
|
|
||||||
- Spotify (requires API credentials)
|
|
||||||
- YouTube Music (requires YTMD companion server)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 📅 Calendar Manager (`src/calendar_manager.py`)
|
|
||||||
**Purpose**: Displays upcoming Google Calendar events
|
|
||||||
|
|
||||||
**Configuration**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"calendar": {
|
|
||||||
"enabled": true,
|
|
||||||
"credentials_file": "credentials.json",
|
|
||||||
"token_file": "token.pickle",
|
|
||||||
"update_interval": 3600,
|
|
||||||
"max_events": 3,
|
|
||||||
"calendars": ["birthdays"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Features**:
|
|
||||||
- Google Calendar integration
|
|
||||||
- Event date and time display
|
|
||||||
- Event title (wrapped to fit display)
|
|
||||||
- Multiple calendar support
|
|
||||||
- Configurable event limits
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 🏈 Sports Managers
|
|
||||||
|
|
||||||
The system includes separate managers for each sports league:
|
|
||||||
|
|
||||||
#### NHL Managers (`src/nhl_managers.py`)
|
|
||||||
- **NHLLiveManager**: Currently playing games
|
|
||||||
- **NHLRecentManager**: Completed games (last 48 hours)
|
|
||||||
- **NHLUpcomingManager**: Scheduled games
|
|
||||||
|
|
||||||
#### NBA Managers (`src/nba_managers.py`)
|
|
||||||
- **NBALiveManager**: Currently playing games
|
|
||||||
- **NBARecentManager**: Completed games
|
|
||||||
- **NBAUpcomingManager**: Scheduled games
|
|
||||||
|
|
||||||
#### MLB Managers (`src/mlb_manager.py`)
|
|
||||||
- **MLBLiveManager**: Currently playing games
|
|
||||||
- **MLBRecentManager**: Completed games
|
|
||||||
- **MLBUpcomingManager**: Scheduled games
|
|
||||||
|
|
||||||
#### NFL Managers (`src/nfl_managers.py`)
|
|
||||||
- **NFLLiveManager**: Currently playing games
|
|
||||||
- **NFLRecentManager**: Completed games
|
|
||||||
- **NFLUpcomingManager**: Scheduled games
|
|
||||||
|
|
||||||
#### NCAA Managers
|
|
||||||
- **NCAA Football** (`src/ncaa_fb_managers.py`)
|
|
||||||
- **NCAA Baseball** (`src/ncaa_baseball_managers.py`)
|
|
||||||
- **NCAA Basketball** (`src/ncaam_basketball_managers.py`)
|
|
||||||
|
|
||||||
#### Soccer Managers (`src/soccer_managers.py`)
|
|
||||||
- **SoccerLiveManager**: Currently playing games
|
|
||||||
- **SoccerRecentManager**: Completed games
|
|
||||||
- **SoccerUpcomingManager**: Scheduled games
|
|
||||||
|
|
||||||
#### MiLB Managers (`src/milb_manager.py`)
|
|
||||||
- **MiLBLiveManager**: Currently playing games
|
|
||||||
- **MiLBRecentManager**: Completed games
|
|
||||||
- **MiLBUpcomingManager**: Scheduled games
|
|
||||||
|
|
||||||
**Common Sports Configuration**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"nhl_scoreboard": {
|
|
||||||
"enabled": true,
|
|
||||||
"live_priority": true,
|
|
||||||
"live_game_duration": 20,
|
|
||||||
"show_odds": true,
|
|
||||||
"test_mode": false,
|
|
||||||
"update_interval_seconds": 3600,
|
|
||||||
"live_update_interval": 30,
|
|
||||||
"show_favorite_teams_only": true,
|
|
||||||
"favorite_teams": ["TB"],
|
|
||||||
"logo_dir": "assets/sports/nhl_logos",
|
|
||||||
"show_records": true,
|
|
||||||
"display_modes": {
|
|
||||||
"nhl_live": true,
|
|
||||||
"nhl_recent": true,
|
|
||||||
"nhl_upcoming": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Sports Features**:
|
|
||||||
- Live game scores and status
|
|
||||||
- Team logos and records
|
|
||||||
- Game times and venues
|
|
||||||
- Odds integration (where available)
|
|
||||||
- Favorite team filtering
|
|
||||||
- Automatic game switching
|
|
||||||
- ESPN API integration
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 🎲 Odds Ticker Manager (`src/odds_ticker_manager.py`)
|
|
||||||
**Purpose**: Displays betting odds for upcoming sports games
|
|
||||||
|
|
||||||
**Configuration**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"odds_ticker": {
|
|
||||||
"enabled": true,
|
|
||||||
"show_favorite_teams_only": true,
|
|
||||||
"games_per_favorite_team": 1,
|
|
||||||
"max_games_per_league": 5,
|
|
||||||
"show_odds_only": false,
|
|
||||||
"sort_order": "soonest",
|
|
||||||
"enabled_leagues": ["nfl", "mlb", "ncaa_fb", "milb"],
|
|
||||||
"update_interval": 3600,
|
|
||||||
"scroll_speed": 1,
|
|
||||||
"scroll_delay": 0.01,
|
|
||||||
"loop": true,
|
|
||||||
"future_fetch_days": 50,
|
|
||||||
"show_channel_logos": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Features**:
|
|
||||||
- Multi-league support (NFL, NBA, MLB, NCAA)
|
|
||||||
- Spread, money line, and over/under odds
|
|
||||||
- Team logos display
|
|
||||||
- Scrolling text format
|
|
||||||
- Game time display
|
|
||||||
- ESPN API integration
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 🎨 Custom Display Managers
|
|
||||||
|
|
||||||
#### Text Display Manager (`src/text_display.py`)
|
|
||||||
**Purpose**: Displays custom text messages
|
|
||||||
|
|
||||||
**Configuration**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"text_display": {
|
|
||||||
"enabled": true,
|
|
||||||
"text": "Subscribe to ChuckBuilds",
|
|
||||||
"font_path": "assets/fonts/press-start-2p.ttf",
|
|
||||||
"font_size": 8,
|
|
||||||
"scroll": true,
|
|
||||||
"scroll_speed": 40,
|
|
||||||
"text_color": [255, 0, 0],
|
|
||||||
"background_color": [0, 0, 0],
|
|
||||||
"scroll_gap_width": 32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Features**:
|
|
||||||
- Custom text messages
|
|
||||||
- Configurable fonts and colors
|
|
||||||
- Scrolling text support
|
|
||||||
- Static text display
|
|
||||||
- Background color options
|
|
||||||
|
|
||||||
#### YouTube Display Manager (`src/youtube_display.py`)
|
|
||||||
**Purpose**: Displays YouTube channel statistics
|
|
||||||
|
|
||||||
**Configuration**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"youtube": {
|
|
||||||
"enabled": true,
|
|
||||||
"update_interval": 3600
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Features**:
|
|
||||||
- Subscriber count display
|
|
||||||
- Video count display
|
|
||||||
- View count display
|
|
||||||
- YouTube API integration
|
|
||||||
|
|
||||||
#### Of The Day Manager (`src/of_the_day_manager.py`)
|
|
||||||
**Purpose**: Displays various "of the day" content
|
|
||||||
|
|
||||||
**Configuration**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"of_the_day": {
|
|
||||||
"enabled": true,
|
|
||||||
"display_rotate_interval": 20,
|
|
||||||
"update_interval": 3600,
|
|
||||||
"subtitle_rotate_interval": 10,
|
|
||||||
"category_order": ["word_of_the_day", "slovenian_word_of_the_day", "bible_verse_of_the_day"],
|
|
||||||
"categories": {
|
|
||||||
"word_of_the_day": {
|
|
||||||
"enabled": true,
|
|
||||||
"data_file": "of_the_day/word_of_the_day.json",
|
|
||||||
"display_name": "Word of the Day"
|
|
||||||
},
|
|
||||||
"slovenian_word_of_the_day": {
|
|
||||||
"enabled": true,
|
|
||||||
"data_file": "of_the_day/slovenian_word_of_the_day.json",
|
|
||||||
"display_name": "Slovenian Word of the Day"
|
|
||||||
},
|
|
||||||
"bible_verse_of_the_day": {
|
|
||||||
"enabled": true,
|
|
||||||
"data_file": "of_the_day/bible_verse_of_the_day.json",
|
|
||||||
"display_name": "Bible Verse of the Day"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Features**:
|
|
||||||
- Word of the day
|
|
||||||
- Slovenian word of the day
|
|
||||||
- Bible verse of the day
|
|
||||||
- Rotating display categories
|
|
||||||
- Local JSON data files
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Display Manager Architecture
|
|
||||||
|
|
||||||
### Common Interface
|
|
||||||
All display managers follow a consistent interface:
|
|
||||||
|
|
||||||
```python
|
|
||||||
class DisplayManager:
|
|
||||||
def __init__(self, config, display_manager):
|
|
||||||
# Initialize with configuration and display manager
|
|
||||||
|
|
||||||
def update_data(self):
|
|
||||||
# Fetch and process new data
|
|
||||||
|
|
||||||
def display(self, force_clear=False):
|
|
||||||
# Render content to the display
|
|
||||||
|
|
||||||
def is_enabled(self):
|
|
||||||
# Check if manager is enabled
|
|
||||||
```
|
|
||||||
|
|
||||||
### Data Flow
|
|
||||||
1. **Configuration**: Manager reads settings from `config.json`
|
|
||||||
2. **Data Fetching**: Retrieves data from APIs or local sources
|
|
||||||
3. **Caching**: Stores data using `CacheManager`
|
|
||||||
4. **Processing**: Transforms data into display format
|
|
||||||
5. **Rendering**: Uses `DisplayManager` to show content
|
|
||||||
6. **Rotation**: Returns to main display controller
|
|
||||||
|
|
||||||
### Error Handling
|
|
||||||
- API failures fall back to cached data
|
|
||||||
- Network timeouts are handled gracefully
|
|
||||||
- Invalid data is filtered out
|
|
||||||
- Logging provides debugging information
|
|
||||||
|
|
||||||
## Configuration Best Practices
|
|
||||||
|
|
||||||
### Enable/Disable Managers
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"weather": {
|
|
||||||
"enabled": true // Set to false to disable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Set Display Durations
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"display": {
|
|
||||||
"display_durations": {
|
|
||||||
"weather": 30, // 30 seconds
|
|
||||||
"stocks": 60, // 1 minute
|
|
||||||
"nhl_live": 20 // 20 seconds
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Configure Update Intervals
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"weather": {
|
|
||||||
"update_interval": 1800 // Update every 30 minutes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Set Favorite Teams
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"nhl_scoreboard": {
|
|
||||||
"show_favorite_teams_only": true,
|
|
||||||
"favorite_teams": ["TB", "DAL"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Performance Considerations
|
|
||||||
|
|
||||||
### API Rate Limits
|
|
||||||
- Weather: 1000 calls/day (OpenWeatherMap)
|
|
||||||
- Stocks: 2000 calls/hour (Yahoo Finance)
|
|
||||||
- Sports: ESPN API (no documented limits)
|
|
||||||
- Music: Spotify/YouTube Music APIs
|
|
||||||
|
|
||||||
### Caching Strategy
|
|
||||||
- Data cached based on `update_interval`
|
|
||||||
- Cache persists across restarts
|
|
||||||
- Failed API calls use cached data
|
|
||||||
- Automatic cache invalidation
|
|
||||||
|
|
||||||
### Resource Usage
|
|
||||||
- Each manager runs independently
|
|
||||||
- Disabled managers use no resources
|
|
||||||
- Memory usage scales with enabled features
|
|
||||||
- CPU usage minimal during idle periods
|
|
||||||
|
|
||||||
## Troubleshooting Display Managers
|
|
||||||
|
|
||||||
### Common Issues
|
|
||||||
1. **No Data Displayed**: Check API keys and network connectivity
|
|
||||||
2. **Outdated Data**: Verify update intervals and cache settings
|
|
||||||
3. **Display Errors**: Check font files and display configuration
|
|
||||||
4. **Performance Issues**: Reduce update frequency or disable unused managers
|
|
||||||
|
|
||||||
### Debugging
|
|
||||||
- Enable logging for specific managers
|
|
||||||
- Check cache directory for data files
|
|
||||||
- Verify API credentials in `config_secrets.json`
|
|
||||||
- Test individual managers in isolation
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*For detailed technical information about each display manager, see the [Display Manager Details](WIKI_DISPLAY_MANAGER_DETAILS.md) page.*
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
# LEDMatrix Wiki
|
|
||||||
|
|
||||||
Welcome to the LEDMatrix Wiki! This comprehensive documentation will help you understand, configure, and customize your LED matrix display system.
|
|
||||||
|
|
||||||
## 🏠 [Home](WIKI_HOME.md) - You are here
|
|
||||||
The main wiki page with overview and navigation.
|
|
||||||
|
|
||||||
## 📋 [Quick Start Guide](WIKI_QUICK_START.md)
|
|
||||||
Get your LEDMatrix up and running in minutes with this step-by-step guide.
|
|
||||||
|
|
||||||
## 🏗️ [System Architecture](WIKI_ARCHITECTURE.md)
|
|
||||||
Understand how the LEDMatrix system is organized and how all components work together.
|
|
||||||
|
|
||||||
## ⚙️ [Configuration Guide](WIKI_CONFIGURATION.md)
|
|
||||||
Complete guide to configuring all aspects of your LEDMatrix system.
|
|
||||||
|
|
||||||
## 🎯 [Display Managers](WIKI_DISPLAY_MANAGERS.md)
|
|
||||||
Detailed documentation for each display manager and their configuration options.
|
|
||||||
|
|
||||||
## 🌐 Web Interface
|
|
||||||
- [Web Interface Installation](WEB_INTERFACE_INSTALLATION.md)
|
|
||||||
- [Web Interface V2 Enhancements](WEB_INTERFACE_V2_ENHANCED_SUMMARY.md)
|
|
||||||
|
|
||||||
## 📰 News & Feeds
|
|
||||||
- [Sports News Manager](NEWS_MANAGER_README.md)
|
|
||||||
- [Add Custom RSS Feeds](CUSTOM_FEEDS_GUIDE.md)
|
|
||||||
|
|
||||||
## ⏱️ Dynamic Duration
|
|
||||||
- [Feature Overview](dynamic_duration.md)
|
|
||||||
- [Implementation Guide](DYNAMIC_DURATION_GUIDE.md)
|
|
||||||
- [Stocks Implementation Details](DYNAMIC_DURATION_STOCKS_IMPLEMENTATION.md)
|
|
||||||
|
|
||||||
## 🗄️ Caching
|
|
||||||
- [Cache Strategy](CACHE_STRATEGY.md)
|
|
||||||
- [Cache Management](cache_management.md)
|
|
||||||
|
|
||||||
## 🧩 Troubleshooting
|
|
||||||
- [General Troubleshooting](WIKI_TROUBLESHOOTING.md)
|
|
||||||
- [MiLB Troubleshooting](MILB_TROUBLESHOOTING.md)
|
|
||||||
|
|
||||||
## 🚀 Install & Quick Start
|
|
||||||
- [Installation Guide](INSTALLATION_GUIDE.md)
|
|
||||||
- [Quick Start](WIKI_QUICK_START.md)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Quick Navigation
|
|
||||||
|
|
||||||
### Core Features
|
|
||||||
- [Display Managers](WIKI_DISPLAY_MANAGERS.md) - All display modules
|
|
||||||
- [Configuration](WIKI_CONFIGURATION.md) - Complete config guide
|
|
||||||
- [Hardware Setup](WIKI_HARDWARE.md) - Physical setup
|
|
||||||
|
|
||||||
### Integrations
|
|
||||||
- [Sports](WIKI_SPORTS.md) - All sports leagues
|
|
||||||
- [Music](WIKI_MUSIC.md) - Spotify & YouTube Music
|
|
||||||
- [Weather](WIKI_WEATHER.md) - Weather display
|
|
||||||
- [Financial](WIKI_FINANCIAL.md) - Stocks & crypto
|
|
||||||
- [Calendar](WIKI_CALENDAR.md) - Google Calendar
|
|
||||||
|
|
||||||
### Technical
|
|
||||||
- [Architecture](WIKI_ARCHITECTURE.md) - System design
|
|
||||||
- [API Reference](WIKI_API_REFERENCE.md) - Technical docs
|
|
||||||
- [Development](WIKI_DEVELOPMENT.md) - Extending the system
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## About LEDMatrix
|
|
||||||
|
|
||||||
LEDMatrix is a comprehensive LED matrix display system that provides real-time information display capabilities for various data sources. The system is highly configurable and supports multiple display modes that can be enabled or disabled based on user preferences.
|
|
||||||
|
|
||||||
### Key Features
|
|
||||||
- **Modular Design**: Each feature is a separate manager that can be enabled/disabled
|
|
||||||
- **Real-time Updates**: Live data from APIs with intelligent caching
|
|
||||||
- **Multiple Sports**: NHL, NBA, MLB, NFL, NCAA, Soccer, and more
|
|
||||||
- **Financial Data**: Stock ticker, crypto prices, and financial news
|
|
||||||
- **Weather**: Current conditions, hourly and daily forecasts
|
|
||||||
- **Music**: Spotify and YouTube Music integration
|
|
||||||
- **Custom Content**: Text display, YouTube stats, and more
|
|
||||||
- **Scheduling**: Configurable display rotation and timing
|
|
||||||
- **Caching**: Intelligent caching to reduce API calls
|
|
||||||
|
|
||||||
### System Requirements
|
|
||||||
- Raspberry Pi 3B+ or 4 (NOT Pi 5)
|
|
||||||
- Adafruit RGB Matrix Bonnet/HAT
|
|
||||||
- 2x LED Matrix panels (64x32)
|
|
||||||
- 5V 4A DC Power Supply
|
|
||||||
- Internet connection for API access
|
|
||||||
|
|
||||||
### Quick Links
|
|
||||||
- [YouTube Setup Video](https://www.youtube.com/watch?v=_HaqfJy1Y54)
|
|
||||||
- [Project Website](https://www.chuck-builds.com/led-matrix/)
|
|
||||||
- [GitHub Repository](https://github.com/ChuckBuilds/LEDMatrix)
|
|
||||||
- [Discord Community](https://discord.com/invite/uW36dVAtcT)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*This wiki is designed to help you get the most out of your LEDMatrix system. Each page contains detailed information, configuration examples, and troubleshooting tips.*
|
|
||||||
@@ -1,407 +0,0 @@
|
|||||||
# Quick Start Guide
|
|
||||||
|
|
||||||
Get your LEDMatrix system up and running in minutes! This guide covers the essential steps to get your display working.
|
|
||||||
|
|
||||||
## Fast Path (Recommended)
|
|
||||||
|
|
||||||
If this is a brand new install, you can run the all-in-one installer and then use the web UI:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
chmod +x first_time_install.sh
|
|
||||||
sudo ./first_time_install.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Then open the web UI at:
|
|
||||||
|
|
||||||
```
|
|
||||||
http://your-pi-ip:5001
|
|
||||||
```
|
|
||||||
|
|
||||||
The steps below document the manual process for advanced users.
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
### Hardware Requirements
|
|
||||||
- Raspberry Pi 3B+ or 4 (NOT Pi 5)
|
|
||||||
- Adafruit RGB Matrix Bonnet/HAT
|
|
||||||
- 2x LED Matrix panels (64x32 each)
|
|
||||||
- 5V 4A DC Power Supply
|
|
||||||
- Micro SD card (8GB or larger)
|
|
||||||
|
|
||||||
### Software Requirements
|
|
||||||
- Internet connection
|
|
||||||
- SSH access to Raspberry Pi
|
|
||||||
- Basic command line knowledge
|
|
||||||
|
|
||||||
## Step 1: Prepare Raspberry Pi
|
|
||||||
|
|
||||||
### 1.1 Create Raspberry Pi Image
|
|
||||||
1. Download [Raspberry Pi Imager](https://www.raspberrypi.com/software/)
|
|
||||||
2. Choose your Raspberry Pi model
|
|
||||||
3. Select "Raspbian OS Lite (64-bit)"
|
|
||||||
4. Choose your micro SD card
|
|
||||||
5. Click "Next" then "Edit Settings"
|
|
||||||
|
|
||||||
### 1.2 Configure OS Settings
|
|
||||||
1. **General Tab**:
|
|
||||||
- Set hostname: `ledpi`
|
|
||||||
- Enable SSH
|
|
||||||
- Set username and password
|
|
||||||
- Configure WiFi
|
|
||||||
|
|
||||||
2. **Services Tab**:
|
|
||||||
- Enable SSH
|
|
||||||
- Use password authentication
|
|
||||||
|
|
||||||
3. Click "Save" and write the image
|
|
||||||
|
|
||||||
### 1.3 Boot and Connect
|
|
||||||
1. Insert SD card into Raspberry Pi
|
|
||||||
2. Power on and wait for boot
|
|
||||||
3. Connect via SSH:
|
|
||||||
```bash
|
|
||||||
ssh ledpi@ledpi
|
|
||||||
```
|
|
||||||
|
|
||||||
## Step 2: Install LEDMatrix
|
|
||||||
|
|
||||||
### 2.1 Update System
|
|
||||||
```bash
|
|
||||||
sudo apt update && sudo apt upgrade -y
|
|
||||||
sudo apt install -y git python3-pip cython3 build-essential python3-dev python3-pillow scons
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.2 Clone Repository
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/ChuckBuilds/LEDMatrix.git
|
|
||||||
cd LEDMatrix
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.3 First-time installation (recommended)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
chmod +x first_time_install.sh
|
|
||||||
sudo ./first_time_install.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Or manually
|
|
||||||
|
|
||||||
### 2.3 Install Dependencies
|
|
||||||
```bash
|
|
||||||
sudo pip3 install --break-system-packages -r requirements.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.4 Install RGB Matrix Library
|
|
||||||
```bash
|
|
||||||
cd rpi-rgb-led-matrix-master
|
|
||||||
sudo make build-python PYTHON=$(which python3)
|
|
||||||
cd bindings/python
|
|
||||||
sudo python3 setup.py install
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.5 Test Installation
|
|
||||||
```bash
|
|
||||||
python3 -c 'from rgbmatrix import RGBMatrix, RGBMatrixOptions; print("Success!")'
|
|
||||||
```
|
|
||||||
|
|
||||||
## Step 3: Configure Hardware
|
|
||||||
|
|
||||||
### 3.1 Remove Audio Services
|
|
||||||
```bash
|
|
||||||
sudo apt-get remove bluez bluez-firmware pi-bluetooth triggerhappy pigpio
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3.2 Blacklist Sound Module
|
|
||||||
```bash
|
|
||||||
cat <<EOF | sudo tee /etc/modprobe.d/blacklist-rgb-matrix.conf
|
|
||||||
blacklist snd_bcm2835
|
|
||||||
EOF
|
|
||||||
|
|
||||||
sudo update-initramfs -u
|
|
||||||
sudo reboot
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3.3 Optimize Performance
|
|
||||||
```bash
|
|
||||||
# Edit cmdline.txt
|
|
||||||
sudo nano /boot/firmware/cmdline.txt
|
|
||||||
# Add "isolcpus=3" at the end
|
|
||||||
|
|
||||||
# Edit config.txt
|
|
||||||
sudo nano /boot/firmware/config.txt
|
|
||||||
# Change "dtparam=audio=on" to "dtparam=audio=off"
|
|
||||||
|
|
||||||
sudo reboot
|
|
||||||
```
|
|
||||||
|
|
||||||
## Step 4: Configure LEDMatrix
|
|
||||||
|
|
||||||
### 4.1 Basic Configuration
|
|
||||||
```bash
|
|
||||||
sudo nano config/config.json
|
|
||||||
```
|
|
||||||
|
|
||||||
**Minimal Configuration**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"display": {
|
|
||||||
"hardware": {
|
|
||||||
"rows": 32,
|
|
||||||
"cols": 64,
|
|
||||||
"chain_length": 2,
|
|
||||||
"brightness": 90,
|
|
||||||
"hardware_mapping": "adafruit-hat-pwm"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"clock": {
|
|
||||||
"enabled": true
|
|
||||||
},
|
|
||||||
"weather": {
|
|
||||||
"enabled": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.2 Set Permissions
|
|
||||||
```bash
|
|
||||||
sudo chmod o+x /home/ledpi
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.3 Setup Cache (Optional)
|
|
||||||
```bash
|
|
||||||
chmod +x setup_cache.sh
|
|
||||||
./setup_cache.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
## Step 5: Test Basic Display
|
|
||||||
|
|
||||||
### 5.1 Run Display
|
|
||||||
```bash
|
|
||||||
sudo python3 display_controller.py
|
|
||||||
```
|
|
||||||
|
|
||||||
**Expected Behavior**:
|
|
||||||
- Display should show "Initializing" message
|
|
||||||
- Clock should display current time
|
|
||||||
- Weather should show current conditions (if API key configured)
|
|
||||||
|
|
||||||
### 5.2 Stop Display
|
|
||||||
Press `Ctrl+C` to stop the display
|
|
||||||
|
|
||||||
## Step 6: Configure APIs (Optional)
|
|
||||||
|
|
||||||
### 6.1 Weather API
|
|
||||||
1. Get free API key from [OpenWeatherMap](https://openweathermap.org/api)
|
|
||||||
2. Create secrets file:
|
|
||||||
```bash
|
|
||||||
cp config/config_secrets.template.json config/config_secrets.json
|
|
||||||
sudo nano config/config_secrets.json
|
|
||||||
```
|
|
||||||
3. Add your API key:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"weather": {
|
|
||||||
"api_key": "your_api_key_here"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6.2 Test Weather Display
|
|
||||||
```bash
|
|
||||||
sudo python3 display_controller.py
|
|
||||||
```
|
|
||||||
|
|
||||||
## Step 7: Install as Service
|
|
||||||
|
|
||||||
### 7.1 Install Service
|
|
||||||
```bash
|
|
||||||
chmod +x install_service.sh
|
|
||||||
sudo ./install_service.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
### 7.2 Control Service
|
|
||||||
```bash
|
|
||||||
# Start display
|
|
||||||
sudo systemctl start ledmatrix.service
|
|
||||||
|
|
||||||
# Stop display
|
|
||||||
sudo systemctl stop ledmatrix.service
|
|
||||||
|
|
||||||
# Check status
|
|
||||||
sudo systemctl status ledmatrix.service
|
|
||||||
|
|
||||||
# Enable autostart
|
|
||||||
sudo systemctl enable ledmatrix.service
|
|
||||||
```
|
|
||||||
|
|
||||||
### 7.3 Convenience Scripts
|
|
||||||
```bash
|
|
||||||
chmod +x start_display.sh stop_display.sh
|
|
||||||
|
|
||||||
# Start display
|
|
||||||
sudo ./start_display.sh
|
|
||||||
|
|
||||||
# Stop display
|
|
||||||
sudo ./stop_display.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
## Step 8: Web Interface (V2)
|
|
||||||
|
|
||||||
### 8.1 Start the web interface manually (optional)
|
|
||||||
```bash
|
|
||||||
python3 start_web_v2.py
|
|
||||||
```
|
|
||||||
|
|
||||||
### 8.2 Autostart the web interface (recommended)
|
|
||||||
Set `"web_display_autostart": true` in `config/config.json`.
|
|
||||||
The installed `ledmatrix-web.service` will call `start_web_conditionally.py` to start the web UI on boot.
|
|
||||||
|
|
||||||
Access the web interface at:
|
|
||||||
```
|
|
||||||
http://your-pi-ip:5001
|
|
||||||
```
|
|
||||||
|
|
||||||
## Step 9: Add More Features
|
|
||||||
|
|
||||||
### 8.1 Enable Stocks
|
|
||||||
Edit `config/config.json`:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"stocks": {
|
|
||||||
"enabled": true,
|
|
||||||
"symbols": ["AAPL", "MSFT", "GOOGL", "TSLA"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 8.2 Enable Sports
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"nhl_scoreboard": {
|
|
||||||
"enabled": true,
|
|
||||||
"favorite_teams": ["TB"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 8.3 Enable Music
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"music": {
|
|
||||||
"enabled": true,
|
|
||||||
"preferred_source": "ytm"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Common Issues
|
|
||||||
|
|
||||||
1. **No Display**:
|
|
||||||
- Check hardware connections
|
|
||||||
- Verify `hardware_mapping` setting
|
|
||||||
- Ensure power supply is adequate
|
|
||||||
|
|
||||||
2. **Permission Errors**:
|
|
||||||
```bash
|
|
||||||
sudo chmod o+x /home/ledpi
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Import Errors**:
|
|
||||||
```bash
|
|
||||||
cd rpi-rgb-led-matrix-master/bindings/python
|
|
||||||
sudo python3 setup.py install
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Cache Issues**:
|
|
||||||
```bash
|
|
||||||
chmod +x fix_cache_permissions.sh
|
|
||||||
./fix_cache_permissions.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test Individual Components
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Test clock
|
|
||||||
python3 -c "from src.clock import Clock; from src.display_manager import DisplayManager; c = Clock(DisplayManager({})); c.display()"
|
|
||||||
|
|
||||||
# Test weather (requires API key)
|
|
||||||
python3 -c "from src.weather_manager import WeatherManager; from src.display_manager import DisplayManager; w = WeatherManager({'weather': {'enabled': True}}, DisplayManager({})); w.display_weather()"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Next Steps
|
|
||||||
|
|
||||||
### 1. Configure Your Preferences
|
|
||||||
- Edit `config/config.json` to enable desired features
|
|
||||||
- Add API keys to `config/config_secrets.json`
|
|
||||||
- Customize display durations and settings
|
|
||||||
|
|
||||||
### 2. Add Sports Teams
|
|
||||||
- Configure favorite teams for each sport
|
|
||||||
- Set up odds ticker for betting information
|
|
||||||
- Customize display modes
|
|
||||||
|
|
||||||
### 3. Set Up Music Integration
|
|
||||||
- Configure Spotify or YouTube Music
|
|
||||||
- Set up authentication
|
|
||||||
- Test music display
|
|
||||||
|
|
||||||
### 4. Customize Display
|
|
||||||
- Add custom text messages
|
|
||||||
- Configure YouTube stats
|
|
||||||
- Set up "of the day" content
|
|
||||||
|
|
||||||
### 5. Web Interface
|
|
||||||
- Access web interface at `http://ledpi:5001`
|
|
||||||
- Control display remotely
|
|
||||||
- Monitor system status
|
|
||||||
|
|
||||||
## Quick Reference
|
|
||||||
|
|
||||||
### Essential Commands
|
|
||||||
```bash
|
|
||||||
# Start display manually
|
|
||||||
sudo python3 display_controller.py
|
|
||||||
|
|
||||||
# Start service
|
|
||||||
sudo systemctl start ledmatrix.service
|
|
||||||
|
|
||||||
# Stop service
|
|
||||||
sudo systemctl stop ledmatrix.service
|
|
||||||
|
|
||||||
# Check status
|
|
||||||
sudo systemctl status ledmatrix.service
|
|
||||||
|
|
||||||
# View logs
|
|
||||||
journalctl -u ledmatrix.service
|
|
||||||
|
|
||||||
# Edit configuration
|
|
||||||
sudo nano config/config.json
|
|
||||||
|
|
||||||
# Edit secrets
|
|
||||||
sudo nano config/config_secrets.json
|
|
||||||
```
|
|
||||||
|
|
||||||
### Configuration Files
|
|
||||||
- `config/config.json` - Main configuration
|
|
||||||
- `config/config_secrets.json` - API keys
|
|
||||||
- `ledmatrix.service` - Systemd service
|
|
||||||
|
|
||||||
### Important Directories
|
|
||||||
- `/var/cache/ledmatrix/` - Cache directory
|
|
||||||
- `assets/` - Logos, fonts, icons
|
|
||||||
- `src/` - Source code
|
|
||||||
- `config/` - Configuration files
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Congratulations!** Your LEDMatrix system is now running. Check out the other wiki pages for detailed configuration options and advanced features.
|
|
||||||
|
|
||||||
## Need Help?
|
|
||||||
|
|
||||||
- [YouTube Setup Video](https://www.youtube.com/watch?v=_HaqfJy1Y54)
|
|
||||||
- [Discord Community](https://discord.com/invite/uW36dVAtcT)
|
|
||||||
- [Project Website](https://www.chuck-builds.com/led-matrix/)
|
|
||||||
- [GitHub Issues](https://github.com/ChuckBuilds/LEDMatrix/issues)
|
|
||||||
@@ -1,516 +0,0 @@
|
|||||||
# Troubleshooting Guide
|
|
||||||
|
|
||||||
This guide covers common issues you may encounter with your LEDMatrix system and their solutions.
|
|
||||||
|
|
||||||
## Quick Diagnosis
|
|
||||||
|
|
||||||
### Check System Status
|
|
||||||
```bash
|
|
||||||
# Check service status
|
|
||||||
sudo systemctl status ledmatrix.service
|
|
||||||
|
|
||||||
# Check logs
|
|
||||||
journalctl -u ledmatrix.service -f
|
|
||||||
|
|
||||||
# Check display manually
|
|
||||||
sudo python3 display_controller.py
|
|
||||||
```
|
|
||||||
|
|
||||||
### Check Hardware
|
|
||||||
```bash
|
|
||||||
# Check GPIO access
|
|
||||||
sudo python3 -c "import RPi.GPIO as GPIO; GPIO.setmode(GPIO.BCM); print('GPIO OK')"
|
|
||||||
|
|
||||||
# Check RGB matrix library
|
|
||||||
python3 -c 'from rgbmatrix import RGBMatrix, RGBMatrixOptions; print("RGB Matrix OK")'
|
|
||||||
```
|
|
||||||
|
|
||||||
## Common Issues
|
|
||||||
|
|
||||||
### 1. No Display Output
|
|
||||||
|
|
||||||
**Symptoms**: LED matrix shows no output or remains dark
|
|
||||||
|
|
||||||
**Possible Causes**:
|
|
||||||
- Hardware connection issues
|
|
||||||
- Incorrect hardware configuration
|
|
||||||
- Power supply problems
|
|
||||||
- GPIO conflicts
|
|
||||||
|
|
||||||
**Solutions**:
|
|
||||||
|
|
||||||
1. **Check Hardware Connections**:
|
|
||||||
```bash
|
|
||||||
# Verify Adafruit HAT is properly seated
|
|
||||||
# Check ribbon cable connections
|
|
||||||
# Ensure power supply is 5V 4A
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Verify Hardware Configuration**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"display": {
|
|
||||||
"hardware": {
|
|
||||||
"rows": 32,
|
|
||||||
"cols": 64,
|
|
||||||
"chain_length": 2,
|
|
||||||
"hardware_mapping": "adafruit-hat-pwm"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Test Basic Display**:
|
|
||||||
```bash
|
|
||||||
# Test minimal configuration
|
|
||||||
sudo python3 -c "
|
|
||||||
from rgbmatrix import RGBMatrix, RGBMatrixOptions
|
|
||||||
options = RGBMatrixOptions()
|
|
||||||
options.rows = 32
|
|
||||||
options.cols = 64
|
|
||||||
options.chain_length = 2
|
|
||||||
options.hardware_mapping = 'adafruit-hat-pwm'
|
|
||||||
matrix = RGBMatrix(options=options)
|
|
||||||
print('Matrix initialized successfully')
|
|
||||||
"
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Check Audio Conflicts**:
|
|
||||||
```bash
|
|
||||||
# Remove audio services
|
|
||||||
sudo apt-get remove bluez bluez-firmware pi-bluetooth triggerhappy pigpio
|
|
||||||
|
|
||||||
# Blacklist sound module
|
|
||||||
echo "blacklist snd_bcm2835" | sudo tee /etc/modprobe.d/blacklist-rgb-matrix.conf
|
|
||||||
sudo update-initramfs -u
|
|
||||||
sudo reboot
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Permission Errors
|
|
||||||
|
|
||||||
**Symptoms**: `Permission denied` or `Access denied` errors
|
|
||||||
|
|
||||||
**Solutions**:
|
|
||||||
|
|
||||||
1. **Set Home Directory Permissions**:
|
|
||||||
```bash
|
|
||||||
sudo chmod o+x /home/ledpi
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Check File Permissions**:
|
|
||||||
```bash
|
|
||||||
# Check config file permissions
|
|
||||||
ls -la config/
|
|
||||||
|
|
||||||
# Fix permissions if needed
|
|
||||||
sudo chown ledpi:ledpi config/config.json
|
|
||||||
sudo chmod 644 config/config.json
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Cache Directory Permissions**:
|
|
||||||
```bash
|
|
||||||
chmod +x fix_cache_permissions.sh
|
|
||||||
./fix_cache_permissions.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Import Errors
|
|
||||||
|
|
||||||
**Symptoms**: `ModuleNotFoundError` or `ImportError`
|
|
||||||
|
|
||||||
**Solutions**:
|
|
||||||
|
|
||||||
1. **Reinstall RGB Matrix Library**:
|
|
||||||
```bash
|
|
||||||
cd rpi-rgb-led-matrix-master
|
|
||||||
sudo make build-python PYTHON=$(which python3)
|
|
||||||
cd bindings/python
|
|
||||||
sudo python3 setup.py install
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Check Python Path**:
|
|
||||||
```bash
|
|
||||||
python3 -c "import sys; print(sys.path)"
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Reinstall Dependencies**:
|
|
||||||
```bash
|
|
||||||
sudo pip3 install --break-system-packages -r requirements.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. No Data Displayed
|
|
||||||
|
|
||||||
**Symptoms**: Display shows but no content appears
|
|
||||||
|
|
||||||
**Solutions**:
|
|
||||||
|
|
||||||
1. **Check Configuration**:
|
|
||||||
```bash
|
|
||||||
# Validate JSON syntax
|
|
||||||
python3 -m json.tool config/config.json
|
|
||||||
|
|
||||||
# Check if features are enabled
|
|
||||||
grep -A 5 '"enabled"' config/config.json
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Check API Keys**:
|
|
||||||
```bash
|
|
||||||
# Verify secrets file exists
|
|
||||||
ls -la config/config_secrets.json
|
|
||||||
|
|
||||||
# Check API key format
|
|
||||||
cat config/config_secrets.json
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Test Individual Components**:
|
|
||||||
```bash
|
|
||||||
# Test clock
|
|
||||||
python3 -c "from src.clock import Clock; from src.display_manager import DisplayManager; c = Clock(DisplayManager({})); c.display()"
|
|
||||||
|
|
||||||
# Test weather (requires API key)
|
|
||||||
python3 -c "from src.weather_manager import WeatherManager; from src.display_manager import DisplayManager; w = WeatherManager({'weather': {'enabled': True}}, DisplayManager({})); w.display_weather()"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. Performance Issues
|
|
||||||
|
|
||||||
**Symptoms**: Flickering, slow updates, or system lag
|
|
||||||
|
|
||||||
**Solutions**:
|
|
||||||
|
|
||||||
1. **Optimize Hardware Settings**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"display": {
|
|
||||||
"hardware": {
|
|
||||||
"gpio_slowdown": 3,
|
|
||||||
"limit_refresh_rate_hz": 120,
|
|
||||||
"pwm_bits": 9
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Reduce Update Frequency**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"weather": {
|
|
||||||
"update_interval": 3600
|
|
||||||
},
|
|
||||||
"stocks": {
|
|
||||||
"update_interval": 1800
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Disable Unused Features**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"stock_news": {
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
"odds_ticker": {
|
|
||||||
"enabled": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6. Network/API Issues
|
|
||||||
|
|
||||||
**Symptoms**: No weather, stocks, or sports data
|
|
||||||
|
|
||||||
**Solutions**:
|
|
||||||
|
|
||||||
1. **Check Internet Connection**:
|
|
||||||
```bash
|
|
||||||
ping -c 3 google.com
|
|
||||||
curl -I https://api.openweathermap.org
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Verify API Keys**:
|
|
||||||
```bash
|
|
||||||
# Test OpenWeatherMap API
|
|
||||||
curl "http://api.openweathermap.org/data/2.5/weather?q=London&appid=YOUR_API_KEY"
|
|
||||||
|
|
||||||
# Test Yahoo Finance
|
|
||||||
curl "https://query1.finance.yahoo.com/v8/finance/chart/AAPL"
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Check Rate Limits**:
|
|
||||||
- OpenWeatherMap: 1000 calls/day
|
|
||||||
- Yahoo Finance: 2000 calls/hour
|
|
||||||
- ESPN API: No documented limits
|
|
||||||
|
|
||||||
### 7. Service Issues
|
|
||||||
|
|
||||||
**Symptoms**: Service won't start or stops unexpectedly
|
|
||||||
|
|
||||||
**Solutions**:
|
|
||||||
|
|
||||||
1. **Check Service Status**:
|
|
||||||
```bash
|
|
||||||
sudo systemctl status ledmatrix.service
|
|
||||||
sudo journalctl -u ledmatrix.service -f
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Reinstall Service**:
|
|
||||||
```bash
|
|
||||||
sudo systemctl stop ledmatrix.service
|
|
||||||
sudo systemctl disable ledmatrix.service
|
|
||||||
chmod +x install_service.sh
|
|
||||||
sudo ./install_service.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Check Service File**:
|
|
||||||
```bash
|
|
||||||
cat /etc/systemd/system/ledmatrix.service
|
|
||||||
```
|
|
||||||
|
|
||||||
### 8. Cache Issues
|
|
||||||
|
|
||||||
**Symptoms**: Data not updating or cache warnings
|
|
||||||
|
|
||||||
**Solutions**:
|
|
||||||
|
|
||||||
1. **Setup Persistent Cache**:
|
|
||||||
```bash
|
|
||||||
chmod +x setup_cache.sh
|
|
||||||
./setup_cache.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Clear Cache**:
|
|
||||||
```bash
|
|
||||||
sudo rm -rf /var/cache/ledmatrix/*
|
|
||||||
sudo rm -rf /tmp/ledmatrix_cache/*
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Check Cache Permissions**:
|
|
||||||
```bash
|
|
||||||
ls -la /var/cache/ledmatrix/
|
|
||||||
ls -la /tmp/ledmatrix_cache/
|
|
||||||
```
|
|
||||||
|
|
||||||
### 9. Font/Display Issues
|
|
||||||
|
|
||||||
**Symptoms**: Text not displaying correctly or missing fonts
|
|
||||||
|
|
||||||
**Solutions**:
|
|
||||||
|
|
||||||
1. **Check Font Files**:
|
|
||||||
```bash
|
|
||||||
ls -la assets/fonts/
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Reinstall Fonts**:
|
|
||||||
```bash
|
|
||||||
# Copy fonts from repository
|
|
||||||
sudo cp assets/fonts/* /usr/share/fonts/truetype/
|
|
||||||
sudo fc-cache -fv
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Test Font Loading**:
|
|
||||||
```bash
|
|
||||||
python3 -c "from PIL import ImageFont; font = ImageFont.truetype('assets/fonts/PressStart2P-Regular.ttf', 8); print('Font loaded')"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 10. Music Integration Issues
|
|
||||||
|
|
||||||
**Symptoms**: Spotify or YouTube Music not working
|
|
||||||
|
|
||||||
**Solutions**:
|
|
||||||
|
|
||||||
1. **Spotify Authentication**:
|
|
||||||
```bash
|
|
||||||
sudo python3 src/authenticate_spotify.py
|
|
||||||
sudo chmod 644 config/spotify_auth.json
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **YouTube Music Setup**:
|
|
||||||
```bash
|
|
||||||
# Ensure YTMD companion server is running
|
|
||||||
# Check URL in config
|
|
||||||
sudo python3 src/authenticate_ytm.py
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Check Music Configuration**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"music": {
|
|
||||||
"enabled": true,
|
|
||||||
"preferred_source": "ytm",
|
|
||||||
"YTM_COMPANION_URL": "http://192.168.1.100:9863"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Advanced Troubleshooting
|
|
||||||
|
|
||||||
### Debug Mode
|
|
||||||
|
|
||||||
Enable detailed logging:
|
|
||||||
```bash
|
|
||||||
# Edit display_controller.py
|
|
||||||
# Change logging level to DEBUG
|
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test Individual Managers
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Test weather manager
|
|
||||||
python3 -c "
|
|
||||||
from src.weather_manager import WeatherManager
|
|
||||||
from src.display_manager import DisplayManager
|
|
||||||
config = {'weather': {'enabled': True}}
|
|
||||||
w = WeatherManager(config, DisplayManager(config))
|
|
||||||
w.display_weather()
|
|
||||||
"
|
|
||||||
|
|
||||||
# Test stock manager
|
|
||||||
python3 -c "
|
|
||||||
from src.stock_manager import StockManager
|
|
||||||
from src.display_manager import DisplayManager
|
|
||||||
config = {'stocks': {'enabled': True, 'symbols': ['AAPL']}}
|
|
||||||
s = StockManager(config, DisplayManager(config))
|
|
||||||
s.display_stocks()
|
|
||||||
"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Hardware Diagnostics
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Check GPIO pins
|
|
||||||
sudo python3 -c "
|
|
||||||
import RPi.GPIO as GPIO
|
|
||||||
GPIO.setmode(GPIO.BCM)
|
|
||||||
pins = [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]
|
|
||||||
for pin in pins:
|
|
||||||
try:
|
|
||||||
GPIO.setup(pin, GPIO.OUT)
|
|
||||||
GPIO.output(pin, GPIO.HIGH)
|
|
||||||
print(f'Pin {pin}: OK')
|
|
||||||
except:
|
|
||||||
print(f'Pin {pin}: ERROR')
|
|
||||||
"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Performance Monitoring
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Monitor system resources
|
|
||||||
htop
|
|
||||||
|
|
||||||
# Check memory usage
|
|
||||||
free -h
|
|
||||||
|
|
||||||
# Monitor network
|
|
||||||
iftop
|
|
||||||
|
|
||||||
# Check disk usage
|
|
||||||
df -h
|
|
||||||
```
|
|
||||||
|
|
||||||
## Recovery Procedures
|
|
||||||
|
|
||||||
### Complete Reset
|
|
||||||
|
|
||||||
If all else fails, perform a complete reset:
|
|
||||||
|
|
||||||
1. **Backup Configuration**:
|
|
||||||
```bash
|
|
||||||
cp config/config.json config/config.json.backup
|
|
||||||
cp config/config_secrets.json config/config_secrets.json.backup
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Reinstall System**:
|
|
||||||
```bash
|
|
||||||
sudo systemctl stop ledmatrix.service
|
|
||||||
sudo systemctl disable ledmatrix.service
|
|
||||||
sudo rm -rf /var/cache/ledmatrix
|
|
||||||
sudo rm -rf /tmp/ledmatrix_cache
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Fresh Installation**:
|
|
||||||
```bash
|
|
||||||
cd ~
|
|
||||||
rm -rf LEDMatrix
|
|
||||||
git clone https://github.com/ChuckBuilds/LEDMatrix.git
|
|
||||||
cd LEDMatrix
|
|
||||||
# Follow installation steps again
|
|
||||||
```
|
|
||||||
|
|
||||||
### Emergency Mode
|
|
||||||
|
|
||||||
If the system won't start, try emergency mode:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Stop all services
|
|
||||||
sudo systemctl stop ledmatrix.service
|
|
||||||
|
|
||||||
# Run with minimal config
|
|
||||||
sudo python3 display_controller.py --emergency
|
|
||||||
|
|
||||||
# Or run individual components
|
|
||||||
sudo python3 -c "
|
|
||||||
from src.clock import Clock
|
|
||||||
from src.display_manager import DisplayManager
|
|
||||||
c = Clock(DisplayManager({}))
|
|
||||||
while True:
|
|
||||||
c.display()
|
|
||||||
import time
|
|
||||||
time.sleep(1)
|
|
||||||
"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Getting Help
|
|
||||||
|
|
||||||
### Before Asking for Help
|
|
||||||
|
|
||||||
1. **Collect Information**:
|
|
||||||
```bash
|
|
||||||
# System info
|
|
||||||
uname -a
|
|
||||||
cat /etc/os-release
|
|
||||||
|
|
||||||
# Service status
|
|
||||||
sudo systemctl status ledmatrix.service
|
|
||||||
|
|
||||||
# Recent logs
|
|
||||||
journalctl -u ledmatrix.service --since "1 hour ago"
|
|
||||||
|
|
||||||
# Configuration
|
|
||||||
cat config/config.json
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Test Basic Functionality**:
|
|
||||||
```bash
|
|
||||||
# Test RGB matrix
|
|
||||||
python3 -c 'from rgbmatrix import RGBMatrix, RGBMatrixOptions; print("RGB Matrix OK")'
|
|
||||||
|
|
||||||
# Test display
|
|
||||||
sudo python3 display_controller.py
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Check Common Issues**:
|
|
||||||
- Verify hardware connections
|
|
||||||
- Check API keys
|
|
||||||
- Validate configuration
|
|
||||||
- Test network connectivity
|
|
||||||
|
|
||||||
### Where to Get Help
|
|
||||||
|
|
||||||
1. **Discord Community**: [ChuckBuilds Discord](https://discord.com/invite/uW36dVAtcT)
|
|
||||||
2. **GitHub Issues**: [LEDMatrix Issues](https://github.com/ChuckBuilds/LEDMatrix/issues)
|
|
||||||
3. **YouTube**: [ChuckBuilds Channel](https://www.youtube.com/@ChuckBuilds)
|
|
||||||
4. **Project Website**: [ChuckBuilds.com](https://www.chuck-builds.com/led-matrix/)
|
|
||||||
|
|
||||||
### When Reporting Issues
|
|
||||||
|
|
||||||
Include the following information:
|
|
||||||
- Hardware setup (Pi model, matrix type)
|
|
||||||
- Software version (OS, Python version)
|
|
||||||
- Error messages and logs
|
|
||||||
- Steps to reproduce
|
|
||||||
- What you've already tried
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*This troubleshooting guide covers the most common issues. If you're still having problems, check the community resources for additional help.*
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
## LEDMatrix Wiki
|
|
||||||
|
|
||||||
- [Home](WIKI_HOME.md)
|
|
||||||
|
|
||||||
### Get Started
|
|
||||||
- [Quick Start](WIKI_QUICK_START.md)
|
|
||||||
- [Installation Guide](INSTALLATION_GUIDE.md)
|
|
||||||
|
|
||||||
### Configure & Use
|
|
||||||
- [Configuration Guide](WIKI_CONFIGURATION.md)
|
|
||||||
- [Display Managers](WIKI_DISPLAY_MANAGERS.md)
|
|
||||||
- [Web Interface Installation](WEB_INTERFACE_INSTALLATION.md)
|
|
||||||
- [Web Interface V2 Enhancements](WEB_INTERFACE_V2_ENHANCED_SUMMARY.md)
|
|
||||||
|
|
||||||
### Features
|
|
||||||
- [News Manager](NEWS_MANAGER_README.md)
|
|
||||||
- [Custom RSS Feeds](CUSTOM_FEEDS_GUIDE.md)
|
|
||||||
- [Dynamic Duration (Overview)](dynamic_duration.md)
|
|
||||||
- [Dynamic Duration Guide](DYNAMIC_DURATION_GUIDE.md)
|
|
||||||
- [Dynamic Duration (Stocks)](DYNAMIC_DURATION_STOCKS_IMPLEMENTATION.md)
|
|
||||||
|
|
||||||
### Performance & Caching
|
|
||||||
- [Cache Strategy](CACHE_STRATEGY.md)
|
|
||||||
- [Cache Management](cache_management.md)
|
|
||||||
|
|
||||||
### Troubleshooting
|
|
||||||
- [General Troubleshooting](WIKI_TROUBLESHOOTING.md)
|
|
||||||
- [MiLB Troubleshooting](MILB_TROUBLESHOOTING.md)
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,231 +0,0 @@
|
|||||||
# Cache Management
|
|
||||||
|
|
||||||
The LEDMatrix application uses caching to improve performance and reduce API calls. However, sometimes cache data can become stale or corrupted, leading to issues like false live game detection or outdated information.
|
|
||||||
|
|
||||||
## Cache Clearing Utility
|
|
||||||
|
|
||||||
The `clear_cache.py` script provides a command-line interface for managing the LEDMatrix cache. This utility is essential for debugging cache-related issues and ensuring fresh data retrieval.
|
|
||||||
|
|
||||||
### Basic Usage
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Show help and current cache status
|
|
||||||
python clear_cache.py
|
|
||||||
|
|
||||||
# List all available cache keys
|
|
||||||
python clear_cache.py --list
|
|
||||||
|
|
||||||
# Clear all cache data
|
|
||||||
python clear_cache.py --clear-all
|
|
||||||
|
|
||||||
# Clear a specific cache key
|
|
||||||
python clear_cache.py --clear KEY_NAME
|
|
||||||
|
|
||||||
# Show information about a specific cache key
|
|
||||||
python clear_cache.py --info KEY_NAME
|
|
||||||
```
|
|
||||||
|
|
||||||
### Command Reference
|
|
||||||
|
|
||||||
| Command | Short | Description |
|
|
||||||
|---------|-------|-------------|
|
|
||||||
| `--list` | `-l` | List all available cache keys |
|
|
||||||
| `--clear-all` | `-a` | Clear all cache data |
|
|
||||||
| `--clear KEY` | `-c` | Clear a specific cache key |
|
|
||||||
| `--info KEY` | `-i` | Show information about a specific cache key |
|
|
||||||
|
|
||||||
## Common Cache Keys
|
|
||||||
|
|
||||||
### MiLB (Minor League Baseball)
|
|
||||||
- `milb_live_api_data` - Live game data from MiLB API
|
|
||||||
- `milb_upcoming_api_data` - Upcoming game schedules
|
|
||||||
- `milb_recent_api_data` - Recent game results
|
|
||||||
|
|
||||||
### MLB (Major League Baseball)
|
|
||||||
- `mlb_live_api_data` - Live game data from MLB API
|
|
||||||
- `mlb_upcoming_api_data` - Upcoming game schedules
|
|
||||||
- `mlb_recent_api_data` - Recent game results
|
|
||||||
|
|
||||||
### Soccer
|
|
||||||
- `soccer_live_api_data` - Live soccer match data
|
|
||||||
- `soccer_upcoming_api_data` - Upcoming soccer matches
|
|
||||||
|
|
||||||
### Other Services
|
|
||||||
- `weather_api_data` - Weather information
|
|
||||||
- `news_api_data` - News headlines
|
|
||||||
- `stocks_api_data` - Stock market data
|
|
||||||
|
|
||||||
## Usage Examples
|
|
||||||
|
|
||||||
### Scenario 1: False Live Game Detection
|
|
||||||
|
|
||||||
**Problem**: The MiLB manager is showing "Tam vs Dun" as a live game when it's actually old data.
|
|
||||||
|
|
||||||
**Solution**:
|
|
||||||
```bash
|
|
||||||
# First, check what's in the MiLB live cache
|
|
||||||
python clear_cache.py --info milb_live_api_data
|
|
||||||
|
|
||||||
# Clear the problematic cache
|
|
||||||
python clear_cache.py --clear milb_live_api_data
|
|
||||||
|
|
||||||
# Restart the application to fetch fresh data
|
|
||||||
```
|
|
||||||
|
|
||||||
### Scenario 2: Stale Upcoming Games
|
|
||||||
|
|
||||||
**Problem**: The display is showing outdated game schedules.
|
|
||||||
|
|
||||||
**Solution**:
|
|
||||||
```bash
|
|
||||||
# Clear all MiLB cache data
|
|
||||||
python clear_cache.py --clear milb_upcoming_api_data
|
|
||||||
python clear_cache.py --clear milb_live_api_data
|
|
||||||
python clear_cache.py --clear milb_recent_api_data
|
|
||||||
```
|
|
||||||
|
|
||||||
### Scenario 3: Complete Cache Reset
|
|
||||||
|
|
||||||
**Problem**: Multiple cache-related issues or corrupted data.
|
|
||||||
|
|
||||||
**Solution**:
|
|
||||||
```bash
|
|
||||||
# Nuclear option - clear everything
|
|
||||||
python clear_cache.py --clear-all
|
|
||||||
|
|
||||||
# Verify cache is empty
|
|
||||||
python clear_cache.py --list
|
|
||||||
```
|
|
||||||
|
|
||||||
### Scenario 4: Debugging Cache Issues
|
|
||||||
|
|
||||||
**Problem**: Unusual behavior that might be cache-related.
|
|
||||||
|
|
||||||
**Solution**:
|
|
||||||
```bash
|
|
||||||
# List all cache keys to see what's stored
|
|
||||||
python clear_cache.py --list
|
|
||||||
|
|
||||||
# Inspect specific cache entries
|
|
||||||
python clear_cache.py --info milb_live_api_data
|
|
||||||
python clear_cache.py --info weather_api_data
|
|
||||||
|
|
||||||
# Clear specific problematic caches
|
|
||||||
python clear_cache.py --clear milb_live_api_data
|
|
||||||
```
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Cache Directory Issues
|
|
||||||
|
|
||||||
If you encounter errors about cache directories:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Check if cache directory exists
|
|
||||||
ls -la ~/.ledmatrix_cache/
|
|
||||||
|
|
||||||
# If it doesn't exist, the application will create it automatically
|
|
||||||
# You can also manually create it:
|
|
||||||
mkdir -p ~/.ledmatrix_cache/
|
|
||||||
```
|
|
||||||
|
|
||||||
### Permission Issues
|
|
||||||
|
|
||||||
If you get permission errors:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Check cache directory permissions
|
|
||||||
ls -la ~/.ledmatrix_cache/
|
|
||||||
|
|
||||||
# Fix permissions if needed
|
|
||||||
chmod 755 ~/.ledmatrix_cache/
|
|
||||||
chown $USER:$USER ~/.ledmatrix_cache/
|
|
||||||
```
|
|
||||||
|
|
||||||
### Import Errors
|
|
||||||
|
|
||||||
If you get import errors when running the script:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Make sure you're in the LEDMatrix root directory
|
|
||||||
cd /path/to/LEDMatrix
|
|
||||||
|
|
||||||
# Check that the src directory exists
|
|
||||||
ls -la src/
|
|
||||||
|
|
||||||
# Run the script from the correct location
|
|
||||||
python clear_cache.py --list
|
|
||||||
```
|
|
||||||
|
|
||||||
## When to Use Cache Clearing
|
|
||||||
|
|
||||||
### Recommended Times to Clear Cache
|
|
||||||
|
|
||||||
1. **After configuration changes** - Clear relevant caches when you modify team preferences or display settings
|
|
||||||
2. **When experiencing false live data** - Clear live game caches if old games appear as "live"
|
|
||||||
3. **After API changes** - Clear caches if you notice API endpoints have changed
|
|
||||||
4. **For debugging** - Clear caches when investigating display or data issues
|
|
||||||
5. **After long periods of inactivity** - Clear caches if the application hasn't been used for days
|
|
||||||
|
|
||||||
### Cache Types and Their Impact
|
|
||||||
|
|
||||||
| Cache Type | Impact of Clearing | When to Clear |
|
|
||||||
|------------|-------------------|---------------|
|
|
||||||
| Live game data | Forces fresh live data fetch | False live game detection |
|
|
||||||
| Upcoming games | Refreshes schedules | Outdated game times |
|
|
||||||
| Recent games | Updates final scores | Missing recent results |
|
|
||||||
| Weather | Gets current conditions | Stale weather data |
|
|
||||||
| News | Fetches latest headlines | Old news stories |
|
|
||||||
|
|
||||||
## Best Practices
|
|
||||||
|
|
||||||
1. **Targeted Clearing**: Clear specific cache keys rather than all cache when possible
|
|
||||||
2. **Verify Results**: Use `--info` to check cache contents before and after clearing
|
|
||||||
3. **Restart Application**: Restart the LEDMatrix application after clearing caches
|
|
||||||
4. **Monitor Logs**: Check application logs after cache clearing to ensure fresh data is fetched
|
|
||||||
5. **Backup Important Data**: Cache data is automatically regenerated, but be aware that clearing will force new API calls
|
|
||||||
|
|
||||||
## Integration with Application
|
|
||||||
|
|
||||||
The cache clearing utility works independently of the main application. You can run it while the application is running, but for best results:
|
|
||||||
|
|
||||||
1. Stop the LEDMatrix application
|
|
||||||
2. Clear relevant caches
|
|
||||||
3. Restart the application
|
|
||||||
|
|
||||||
This ensures the application starts with fresh data and doesn't immediately re-cache potentially problematic data.
|
|
||||||
|
|
||||||
## Advanced Usage
|
|
||||||
|
|
||||||
### Scripting Cache Management
|
|
||||||
|
|
||||||
You can integrate cache clearing into scripts or cron jobs:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
#!/bin/bash
|
|
||||||
# Daily cache cleanup script
|
|
||||||
|
|
||||||
# Clear old live game data at midnight
|
|
||||||
python clear_cache.py --clear milb_live_api_data
|
|
||||||
python clear_cache.py --clear mlb_live_api_data
|
|
||||||
|
|
||||||
# Log the cleanup
|
|
||||||
echo "$(date): Cache cleared" >> /var/log/ledmatrix_cache.log
|
|
||||||
```
|
|
||||||
|
|
||||||
### Conditional Cache Clearing
|
|
||||||
|
|
||||||
```bash
|
|
||||||
#!/bin/bash
|
|
||||||
# Only clear cache if it's older than 24 hours
|
|
||||||
|
|
||||||
# Check cache age and clear if needed
|
|
||||||
# (This would require additional logic to check cache timestamps)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Related Documentation
|
|
||||||
|
|
||||||
- [Configuration Guide](../config/README.md)
|
|
||||||
- [Troubleshooting Guide](troubleshooting.md)
|
|
||||||
- [API Integration](api_integration.md)
|
|
||||||
- [Display Controller](display_controller.md)
|
|
||||||
@@ -1,243 +0,0 @@
|
|||||||
# Dynamic Duration Implementation
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
Dynamic Duration is a feature that calculates the exact time needed to display scrolling content (like news headlines or stock tickers) based on the content's length, scroll speed, and display characteristics, rather than using a fixed duration. This ensures optimal viewing time for users while maintaining smooth content flow.
|
|
||||||
|
|
||||||
## How It Works
|
|
||||||
|
|
||||||
The dynamic duration calculation considers several factors:
|
|
||||||
|
|
||||||
1. **Content Width**: The total width of the text/image content to be displayed
|
|
||||||
2. **Display Width**: The width of the LED matrix display
|
|
||||||
3. **Scroll Speed**: How many pixels the content moves per frame
|
|
||||||
4. **Scroll Delay**: Time between each frame update
|
|
||||||
5. **Buffer Time**: Additional time added for smooth cycling (configurable percentage)
|
|
||||||
|
|
||||||
### Calculation Formula
|
|
||||||
|
|
||||||
```
|
|
||||||
Total Scroll Distance = Display Width + Content Width
|
|
||||||
Frames Needed = Total Scroll Distance / Scroll Speed
|
|
||||||
Base Time = Frames Needed × Scroll Delay
|
|
||||||
Buffer Time = Base Time × Duration Buffer
|
|
||||||
Calculated Duration = Base Time + Buffer Time
|
|
||||||
```
|
|
||||||
|
|
||||||
The final duration is then capped between the configured minimum and maximum values.
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
Add the following settings to your `config/config.json` file:
|
|
||||||
|
|
||||||
### For Stocks (`stocks` section)
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"stocks": {
|
|
||||||
"dynamic_duration": true,
|
|
||||||
"min_duration": 30,
|
|
||||||
"max_duration": 300,
|
|
||||||
"duration_buffer": 0.1,
|
|
||||||
// ... other existing settings
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### For Stock News (`stock_news` section)
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"stock_news": {
|
|
||||||
"dynamic_duration": true,
|
|
||||||
"min_duration": 30,
|
|
||||||
"max_duration": 300,
|
|
||||||
"duration_buffer": 0.1,
|
|
||||||
// ... other existing settings
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### For Odds Ticker (`odds_ticker` section)
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"odds_ticker": {
|
|
||||||
"dynamic_duration": true,
|
|
||||||
"min_duration": 30,
|
|
||||||
"max_duration": 300,
|
|
||||||
"duration_buffer": 0.1,
|
|
||||||
// ... other existing settings
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Configuration Options
|
|
||||||
|
|
||||||
- **`dynamic_duration`** (boolean): Enable/disable dynamic duration calculation
|
|
||||||
- **`min_duration`** (seconds): Minimum display time regardless of content length
|
|
||||||
- **`max_duration`** (seconds): Maximum display time to prevent excessive delays
|
|
||||||
- **`duration_buffer`** (decimal): Additional time as a percentage of calculated time (e.g., 0.1 = 10% extra)
|
|
||||||
|
|
||||||
## Implementation Details
|
|
||||||
|
|
||||||
### StockManager Updates
|
|
||||||
|
|
||||||
The `StockManager` class has been enhanced with dynamic duration capabilities:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# In __init__ method
|
|
||||||
self.dynamic_duration_enabled = self.stocks_config.get('dynamic_duration', True)
|
|
||||||
self.min_duration = self.stocks_config.get('min_duration', 30)
|
|
||||||
self.max_duration = self.stocks_config.get('max_duration', 300)
|
|
||||||
self.duration_buffer = self.stocks_config.get('duration_buffer', 0.1)
|
|
||||||
self.dynamic_duration = 60 # Default duration in seconds
|
|
||||||
self.total_scroll_width = 0 # Track total width for calculation
|
|
||||||
```
|
|
||||||
|
|
||||||
#### New Methods
|
|
||||||
|
|
||||||
**`calculate_dynamic_duration()`**
|
|
||||||
- Calculates the exact time needed to display all stock information
|
|
||||||
- Considers display width, content width, scroll speed, and delays
|
|
||||||
- Applies min/max duration limits
|
|
||||||
- Includes detailed debug logging
|
|
||||||
|
|
||||||
**`get_dynamic_duration()`**
|
|
||||||
- Returns the calculated dynamic duration for external use
|
|
||||||
- Used by the DisplayController to determine display timing
|
|
||||||
|
|
||||||
### StockNewsManager Updates
|
|
||||||
|
|
||||||
Similar enhancements have been applied to the `StockNewsManager`:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# In __init__ method
|
|
||||||
self.dynamic_duration_enabled = self.stock_news_config.get('dynamic_duration', True)
|
|
||||||
self.min_duration = self.stock_news_config.get('min_duration', 30)
|
|
||||||
self.max_duration = self.stock_news_config.get('max_duration', 300)
|
|
||||||
self.duration_buffer = self.stock_news_config.get('duration_buffer', 0.1)
|
|
||||||
self.dynamic_duration = 60 # Default duration in seconds
|
|
||||||
self.total_scroll_width = 0 # Track total width for calculation
|
|
||||||
```
|
|
||||||
|
|
||||||
#### New Methods
|
|
||||||
|
|
||||||
**`calculate_dynamic_duration()`**
|
|
||||||
- Calculates display time for news headlines
|
|
||||||
- Uses the same logic as StockManager but with stock news configuration
|
|
||||||
- Handles text width calculation from cached images
|
|
||||||
|
|
||||||
**`get_dynamic_duration()`**
|
|
||||||
- Returns the calculated duration for news display
|
|
||||||
|
|
||||||
### OddsTickerManager Updates
|
|
||||||
|
|
||||||
The `OddsTickerManager` class has been enhanced with dynamic duration capabilities:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# In __init__ method
|
|
||||||
self.dynamic_duration_enabled = self.odds_ticker_config.get('dynamic_duration', True)
|
|
||||||
self.min_duration = self.odds_ticker_config.get('min_duration', 30)
|
|
||||||
self.max_duration = self.odds_ticker_config.get('max_duration', 300)
|
|
||||||
self.duration_buffer = self.odds_ticker_config.get('duration_buffer', 0.1)
|
|
||||||
self.dynamic_duration = 60 # Default duration in seconds
|
|
||||||
self.total_scroll_width = 0 # Track total width for calculation
|
|
||||||
```
|
|
||||||
|
|
||||||
#### New Methods
|
|
||||||
|
|
||||||
**`calculate_dynamic_duration()`**
|
|
||||||
- Calculates display time for odds ticker content
|
|
||||||
- Uses the same logic as other managers but with odds ticker configuration
|
|
||||||
- Handles width calculation from the composite ticker image
|
|
||||||
|
|
||||||
**`get_dynamic_duration()`**
|
|
||||||
- Returns the calculated duration for odds ticker display
|
|
||||||
|
|
||||||
### DisplayController Integration
|
|
||||||
|
|
||||||
The `DisplayController` has been updated to use dynamic durations:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# In get_current_duration() method
|
|
||||||
# Handle dynamic duration for stocks
|
|
||||||
if mode_key == 'stocks' and self.stocks:
|
|
||||||
try:
|
|
||||||
dynamic_duration = self.stocks.get_dynamic_duration()
|
|
||||||
logger.info(f"Using dynamic duration for stocks: {dynamic_duration} seconds")
|
|
||||||
return dynamic_duration
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Error getting dynamic duration for stocks: {e}")
|
|
||||||
return self.display_durations.get(mode_key, 60)
|
|
||||||
|
|
||||||
# Handle dynamic duration for stock_news
|
|
||||||
if mode_key == 'stock_news' and self.news:
|
|
||||||
try:
|
|
||||||
dynamic_duration = self.news.get_dynamic_duration()
|
|
||||||
logger.info(f"Using dynamic duration for stock_news: {dynamic_duration} seconds")
|
|
||||||
return dynamic_duration
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Error getting dynamic duration for stock_news: {e}")
|
|
||||||
return self.display_durations.get(mode_key, 60)
|
|
||||||
|
|
||||||
# Handle dynamic duration for odds_ticker
|
|
||||||
if mode_key == 'odds_ticker' and self.odds_ticker:
|
|
||||||
try:
|
|
||||||
dynamic_duration = self.odds_ticker.get_dynamic_duration()
|
|
||||||
logger.info(f"Using dynamic duration for odds_ticker: {dynamic_duration} seconds")
|
|
||||||
return dynamic_duration
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Error getting dynamic duration for odds_ticker: {e}")
|
|
||||||
return self.display_durations.get(mode_key, 60)
|
|
||||||
|
|
||||||
## Benefits
|
|
||||||
|
|
||||||
1. **Optimal Viewing Time**: Content is displayed for exactly the right amount of time
|
|
||||||
2. **Smooth Transitions**: Buffer time ensures smooth cycling between content
|
|
||||||
3. **Configurable Limits**: Min/max durations prevent too short or too long displays
|
|
||||||
4. **Consistent Experience**: All scrolling content uses the same timing logic
|
|
||||||
5. **Debug Visibility**: Detailed logging helps troubleshoot timing issues
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
The implementation includes comprehensive logging to verify calculations:
|
|
||||||
|
|
||||||
```
|
|
||||||
Stock dynamic duration calculation:
|
|
||||||
Display width: 128px
|
|
||||||
Text width: 450px
|
|
||||||
Total scroll distance: 578px
|
|
||||||
Frames needed: 578.0
|
|
||||||
Base time: 5.78s
|
|
||||||
Buffer time: 0.58s (10%)
|
|
||||||
Calculated duration: 6s
|
|
||||||
Final duration: 30s (capped to minimum)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Duration Always at Minimum
|
|
||||||
If your calculated duration is always capped at the minimum value, check:
|
|
||||||
- Scroll speed settings (higher speed = shorter duration)
|
|
||||||
- Scroll delay settings (lower delay = shorter duration)
|
|
||||||
- Content width calculation
|
|
||||||
- Display width configuration
|
|
||||||
|
|
||||||
### Duration Too Long
|
|
||||||
If content displays for too long:
|
|
||||||
- Reduce the `duration_buffer` percentage
|
|
||||||
- Increase `scroll_speed` or decrease `scroll_delay`
|
|
||||||
- Lower the `max_duration` limit
|
|
||||||
|
|
||||||
### Dynamic Duration Not Working
|
|
||||||
If dynamic duration isn't being used:
|
|
||||||
- Verify `dynamic_duration: true` in configuration
|
|
||||||
- Check that the manager instances are properly initialized
|
|
||||||
- Review error logs for calculation failures
|
|
||||||
|
|
||||||
## Related Files
|
|
||||||
|
|
||||||
- `config/config.json` - Configuration settings
|
|
||||||
- `src/stock_manager.py` - Stock display with dynamic duration
|
|
||||||
- `src/stock_news_manager.py` - Stock news with dynamic duration
|
|
||||||
- `src/odds_ticker_manager.py` - Odds ticker with dynamic duration
|
|
||||||
- `src/display_controller.py` - Integration and duration management
|
|
||||||
- `src/news_manager.py` - Original implementation reference
|
|
||||||
Reference in New Issue
Block a user