add radio module drom github and fix weather hot reloads

This commit is contained in:
death916 2025-12-10 04:41:33 -08:00
parent 7d0a0cdfa6
commit 4ea3436128
5 changed files with 1174 additions and 773 deletions

View file

@ -9,6 +9,8 @@ from typing import Any, Dict, List
import reflex as rx
_background_tasks_registered = False
from utils.news import News
from utils.radio import Radio
from utils.scores import NBAScores, mlbScores, nflScores
@ -45,6 +47,7 @@ class State(rx.State):
_nfl_client: nflScores | None = None
_radio_client: Radio = Radio()
last_sports_update: float = 0.0
last_weather_fetch_time: float = 0.0
# --- Initialize Utility Client ---
def __init__(self, *args, **kwargs):
@ -65,18 +68,22 @@ class State(rx.State):
# Set error state if needed
self.weather_img = "/error_placeholder.png"
self.last_weather_update = "Client Init Error"
self.mlb_scores = ""
self.nba_scores = ""
self.mlb_scores = []
self.nba_scores = []
self.last_sports_update = 0.0
# --- on_load Handler ---
async def start_background_tasks(self):
global _background_tasks_registered
"""Starts the weather background task when the page loads."""
rx.remove_local_storage(
"chakra-ui-color-mode"
) # trying to test themes remove after
rx.remove_local_storage("chakra-ui-color-mode")
if _background_tasks_registered:
logging.info(
"Background tasks already registered in this process; skipping."
)
return []
_background_tasks_registered = True
logging.info("Triggering background tasks: Weather")
# Return a list containing the handler references
return [
State.fetch_weather,
State.fetch_sports,
@ -190,7 +197,6 @@ class State(rx.State):
@rx.event(background=True)
async def fetch_weather(self):
"""Fetches the weather screenshot periodically."""
# Check if the client initialized correctly
if not hasattr(self, "_weather_client") or self._weather_client is None:
logging.warning(
"Weather client not initialized. Stopping fetch_weather task."
@ -199,31 +205,40 @@ class State(rx.State):
async with self:
self.last_weather_update = "Error: Weather client unavailable"
yield
return # Exit the task permanently if client init failed
return
while True:
try:
if (
self.last_weather_fetch_time
and (time.time() - self.last_weather_fetch_time)
< WEATHER_FETCH_INTERVAL
):
logging.info(
"Recent weather fetch detected; skipping immediate fetch to avoid thrashing."
)
await asyncio.sleep(WEATHER_FETCH_INTERVAL)
continue
logging.info("Attempting to fetch weather screenshot...")
# Call the method from the initialized client
img_web_path = self._weather_client.get_weather_screenshot()
if img_web_path:
async with self:
timestamp = int(time.time())
self.weather_img = f"{img_web_path}"
self.last_weather_update = datetime.now(timezone.utc).strftime(
"%Y-%m-%d %H:%M:%S UTC"
)
self.last_weather_fetch_time = time.time()
logging.info(
f"State.weather_img updated to: {self.weather_img}"
)
yield # Update frontend
yield
else:
logging.warning(
"get_weather_screenshot returned None. State not updated."
)
# Optionally update status
async with self:
self.last_weather_update = f"Failed fetch @ {datetime.now(timezone.utc).strftime('%H:%M:%S UTC')}"
yield
@ -232,12 +247,13 @@ class State(rx.State):
logging.error(
f"Error in fetch_weather background task: {e}", exc_info=True
)
async with self: # Update state to show error
async with self:
self.last_weather_update = (
f"Error @ {datetime.now(timezone.utc).strftime('%H:%M:%S UTC')}"
)
yield
logging.info("Weather fetch completed")
logging.info("Sleeping for next fetch")
await asyncio.sleep(WEATHER_FETCH_INTERVAL)

View file

@ -16,6 +16,7 @@ dependencies = [
"reflex>=0.6.8",
"aiohttp>=3.11.18",
"reflex-text-loop>=0.0.1",
"pigpio>=1.78",
]
[dependency-groups]

View file

@ -1,8 +1,10 @@
#!/usr/bin/python3
# connect to rda5807 chip and control it and display the current station
# TODO: reference rd library in readme
import reflex as rx
# from utils.python_rd5807m.radio import Radio as Radio_lib
CURRENT_STATION = "90.9 FM"
PLAYING = False
@ -31,8 +33,15 @@ class Radio(rx.Base):
class Radio_Control:
def __init__(self):
pass
def init_radio(self):
self.radio = Radio_lib()
self.radio.initialize()
def play_radio(self):
pass
## for testing chip
# if __name__ == "__main__":
# radio = Radio_Control()
# radio.play_radio()

View file

@ -11,7 +11,7 @@ logging.basicConfig(
)
# Define the target filename consistently
WEATHER_FILENAME = "weather.jpg"
WEATHER_FILENAME = "weather.png"
# Define the web path expected by the frontend
WEATHER_WEB_PATH = f"/{WEATHER_FILENAME}" # This should be relative to the assets dir
@ -51,28 +51,26 @@ class Weather(rx.Base):
"""
assets_dir = self._get_assets_dir()
screenshot_path = os.path.join(assets_dir, WEATHER_FILENAME)
try:
curl_command = [
"curl",
"-s", # Silent mode
"v2.wttr.in/Sacramento.png?0u", # Fetch PNG, no border, no terminal escapes
"-o",
screenshot_path, # Save to the correct assets path
]
# Delete the old file before creating the new one
# Delete the old file before creating the new one
if os.path.exists(screenshot_path):
self.delete_old_screenshots(assets_dir)
logging.info(
f"Running curl command to fetch weather: {' '.join(curl_command)}"
)
curl_command = [
"curl",
"-s", # Silent mode
"v2.wttr.in/Sacramento.png?u0", # Fetch PNG, no border, no terminal escapes
"-o",
screenshot_path, # Save to the correct assets path
]
logging.info(f"Running curl command to fetch weather: {' '.join(curl_command)}")
try:
subprocess.run(curl_command)
logging.info(
f"Curl command successful. Weather image saved to: {screenshot_path}"
) # Log correct save path
)
return WEATHER_WEB_PATH
except subprocess.CalledProcessError as e:
logging.error(f"Curl command failed for path {screenshot_path}: {e}")
logging.error(f"Curl stderr: {e.stderr}")

1853
uv.lock generated Executable file → Normal file

File diff suppressed because it is too large Load diff