Stock news joins the lineup

Stock News added to the display controller and drawing display instead of image
This commit is contained in:
Chuck
2025-04-10 21:23:54 -05:00
parent 5be0d59d7e
commit 7925bf515b
3 changed files with 70 additions and 30 deletions

View File

@@ -35,10 +35,12 @@
} }
}, },
"clock": { "clock": {
"enabled": true,
"format": "%H:%M:%S", "format": "%H:%M:%S",
"update_interval": 1 "update_interval": 1
}, },
"weather": { "weather": {
"enabled": true,
"update_interval": 300, "update_interval": 300,
"units": "imperial", "units": "imperial",
"display_format": "{temp}°F\n{condition}" "display_format": "{temp}°F\n{condition}"

View File

@@ -54,28 +54,62 @@ class DisplayController:
# Check if we need to switch display mode # Check if we need to switch display mode
if current_time - self.last_switch > self.get_current_duration(): if current_time - self.last_switch > self.get_current_duration():
# Cycle through: clock -> weather (current) -> weather (hourly) -> weather (daily) -> stocks -> stock_news # Find next enabled display mode
next_display = None
if self.current_display == 'clock': if self.current_display == 'clock':
self.current_display = 'weather' if self.config.get('weather', {}).get('enabled', False):
self.weather_mode = 'current' next_display = 'weather'
self.weather_mode = 'current'
elif self.config.get('stocks', {}).get('enabled', False):
next_display = 'stocks'
elif self.config.get('stock_news', {}).get('enabled', False):
next_display = 'stock_news'
else:
next_display = 'clock'
elif self.current_display == 'weather': elif self.current_display == 'weather':
if self.weather_mode == 'current': if self.weather_mode == 'current':
next_display = 'weather'
self.weather_mode = 'hourly' self.weather_mode = 'hourly'
elif self.weather_mode == 'hourly': elif self.weather_mode == 'hourly':
next_display = 'weather'
self.weather_mode = 'daily' self.weather_mode = 'daily'
else: # daily else: # daily
if self.config.get('stocks', {}).get('enabled', False): if self.config.get('stocks', {}).get('enabled', False):
self.current_display = 'stocks' next_display = 'stocks'
elif self.config.get('stock_news', {}).get('enabled', False):
next_display = 'stock_news'
elif self.config.get('clock', {}).get('enabled', False):
next_display = 'clock'
else: else:
self.current_display = 'clock' next_display = 'weather'
self.weather_mode = 'current'
elif self.current_display == 'stocks': elif self.current_display == 'stocks':
if self.config.get('stock_news', {}).get('enabled', False): if self.config.get('stock_news', {}).get('enabled', False):
self.current_display = 'stock_news' next_display = 'stock_news'
elif self.config.get('clock', {}).get('enabled', False):
next_display = 'clock'
elif self.config.get('weather', {}).get('enabled', False):
next_display = 'weather'
self.weather_mode = 'current'
else: else:
self.current_display = 'clock' next_display = 'stocks'
else: # stock_news else: # stock_news
self.current_display = 'clock' if self.config.get('clock', {}).get('enabled', False):
next_display = 'clock'
elif self.config.get('weather', {}).get('enabled', False):
next_display = 'weather'
self.weather_mode = 'current'
elif self.config.get('stocks', {}).get('enabled', False):
next_display = 'stocks'
else:
next_display = 'stock_news'
# Update current display
self.current_display = next_display
logger.info(f"Switching display to: {self.current_display} {self.weather_mode if self.current_display == 'weather' else ''}") logger.info(f"Switching display to: {self.current_display} {self.weather_mode if self.current_display == 'weather' else ''}")
self.last_switch = current_time self.last_switch = current_time
self.force_clear = True self.force_clear = True
@@ -83,18 +117,18 @@ class DisplayController:
# Display current screen # Display current screen
try: try:
if self.current_display == 'clock': if self.current_display == 'clock' and self.config.get('clock', {}).get('enabled', False):
self.clock.display_time(force_clear=self.force_clear) self.clock.display_time(force_clear=self.force_clear)
elif self.current_display == 'weather': elif self.current_display == 'weather' and self.config.get('weather', {}).get('enabled', False):
if self.weather_mode == 'current': if self.weather_mode == 'current':
self.weather.display_weather(force_clear=self.force_clear) self.weather.display_weather(force_clear=self.force_clear)
elif self.weather_mode == 'hourly': elif self.weather_mode == 'hourly':
self.weather.display_hourly_forecast(force_clear=self.force_clear) self.weather.display_hourly_forecast(force_clear=self.force_clear)
else: # daily else: # daily
self.weather.display_daily_forecast(force_clear=self.force_clear) self.weather.display_daily_forecast(force_clear=self.force_clear)
elif self.current_display == 'stocks': elif self.current_display == 'stocks' and self.config.get('stocks', {}).get('enabled', False):
self.stocks.display_stocks(force_clear=self.force_clear) self.stocks.display_stocks(force_clear=self.force_clear)
else: # stock_news elif self.current_display == 'stock_news' and self.config.get('stock_news', {}).get('enabled', False):
self.news.display_news() self.news.display_news()
except Exception as e: except Exception as e:
logger.error(f"Error updating display: {e}") logger.error(f"Error updating display: {e}")

View File

@@ -205,36 +205,40 @@ class StockNewsManager:
separator = " - " # Visual separator between news items separator = " - " # Visual separator between news items
news_text = separator.join(news_texts) news_text = separator.join(news_texts)
# Create and display the scrolling text image # Clear the display
text_image = self._create_text_image(news_text) self.display_manager.clear()
# Calculate total scroll width # Calculate text width for scrolling
total_width = text_image.width + self.display_manager.matrix.width bbox = self.display_manager.draw.textbbox((0, 0), news_text, font=self.display_manager.small_font)
text_width = bbox[2] - bbox[0]
# Calculate scroll position
display_width = self.display_manager.matrix.width
total_width = text_width + display_width
# Update scroll position # Update scroll position
self.scroll_position = (self.scroll_position + self.scroll_speed) % total_width self.scroll_position = (self.scroll_position + self.scroll_speed) % total_width
# Create a new black image for the display # Draw the text at the current scroll position
display_image = Image.new('RGB', (self.display_manager.matrix.width, self.display_manager.matrix.height)) self.display_manager.draw_text(
news_text,
x=display_width - self.scroll_position,
y=None, # Center vertically
color=(255, 255, 255),
small_font=True
)
# Paste the appropriate portion of the text image # Update the display
display_image.paste(text_image, (-self.scroll_position, 0)) self.display_manager.update_display()
# If we've wrapped around, paste the beginning of the text again
if self.scroll_position + self.display_manager.matrix.width > text_image.width:
display_image.paste(text_image, (text_image.width - self.scroll_position, 0))
# Display the image
self.display_manager.display_image(display_image)
# If we've completed a full scroll, move to the next group # If we've completed a full scroll, move to the next group
if self.scroll_position == 0: if self.scroll_position == 0:
self.current_news_group = (self.current_news_group + 1) % ((total_headlines + headlines_per_rotation - 1) // headlines_per_rotation) self.current_news_group = (self.current_news_group + 1) % ((total_headlines + headlines_per_rotation - 1) // headlines_per_rotation)
# Log frame rate
self._log_frame_rate()
# Small delay to control scroll speed # Small delay to control scroll speed
time.sleep(self.scroll_delay) time.sleep(self.scroll_delay)
# Log frame rate
self._log_frame_rate()
return True return True