AI bug squash sesh

This commit is contained in:
Chuck
2025-08-09 21:00:25 -05:00
parent 79cbc46f9b
commit 85d63243c7
13 changed files with 41 additions and 9 deletions

173
wiki/CACHE_STRATEGY.md Normal file
View File

@@ -0,0 +1,173 @@
# 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
}
}
```

245
wiki/CUSTOM_FEEDS_GUIDE.md Normal file
View File

@@ -0,0 +1,245 @@
# 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:5000`
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!

View File

@@ -0,0 +1,177 @@
# 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:5000`
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!

View File

@@ -0,0 +1,189 @@
# 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.

View File

@@ -0,0 +1,178 @@
# 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)

245
wiki/NEWS_MANAGER_README.md Normal file
View File

@@ -0,0 +1,245 @@
# 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 `enable_news_manager.py` script to manage the news manager:
```bash
# Check current status
python3 enable_news_manager.py status
# Enable news manager
python3 enable_news_manager.py enable
# Disable news manager
python3 enable_news_manager.py disable
```
### Web Interface
Access the news manager through the web interface:
1. Open your browser to `http://your-display-ip:5000`
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