mirror of
https://github.com/Death916/deathclock.git
synced 2026-04-10 03:04:40 -07:00
begin adding radio
This commit is contained in:
parent
bb266d405b
commit
f859756f46
4 changed files with 71 additions and 17 deletions
|
|
@ -12,6 +12,7 @@ from typing import Any, Dict, List
|
||||||
import reflex as rx
|
import reflex as rx
|
||||||
|
|
||||||
from utils.news import News
|
from utils.news import News
|
||||||
|
from utils.radio import Radio
|
||||||
from utils.scores import NBAScores, mlbScores, nflScores
|
from utils.scores import NBAScores, mlbScores, nflScores
|
||||||
from utils.weather import Weather
|
from utils.weather import Weather
|
||||||
|
|
||||||
|
|
@ -36,6 +37,8 @@ class State(rx.State):
|
||||||
nba_scores: List[Dict[str, Any]] = []
|
nba_scores: List[Dict[str, Any]] = []
|
||||||
mlb_scores: List[Dict[str, Any]] = []
|
mlb_scores: List[Dict[str, Any]] = []
|
||||||
nfl_scores: List[Dict[str, Any]] = []
|
nfl_scores: List[Dict[str, Any]] = []
|
||||||
|
radio_stations: List[str] = []
|
||||||
|
current_radio_station: str = ""
|
||||||
_news_client: News | None = None # This will be set in the constructor
|
_news_client: News | None = None # This will be set in the constructor
|
||||||
last_weather_update: str = "Never"
|
last_weather_update: str = "Never"
|
||||||
weather_img: str = WEATHER_IMAGE_PATH
|
weather_img: str = WEATHER_IMAGE_PATH
|
||||||
|
|
@ -43,6 +46,7 @@ class State(rx.State):
|
||||||
_mlb_client: mlbScores | None = None
|
_mlb_client: mlbScores | None = None
|
||||||
_nba_client: NBAScores | None = None
|
_nba_client: NBAScores | None = None
|
||||||
_nfl_client: nflScores | None = None
|
_nfl_client: nflScores | None = None
|
||||||
|
_radio_client: Radio = Radio()
|
||||||
last_sports_update: float = 0.0
|
last_sports_update: float = 0.0
|
||||||
|
|
||||||
# --- Initialize Utility Client ---
|
# --- Initialize Utility Client ---
|
||||||
|
|
@ -55,6 +59,8 @@ class State(rx.State):
|
||||||
self._mlb_client = mlbScores()
|
self._mlb_client = mlbScores()
|
||||||
self._nba_client = NBAScores()
|
self._nba_client = NBAScores()
|
||||||
self._nfl_client = nflScores()
|
self._nfl_client = nflScores()
|
||||||
|
self._radio_client = Radio()
|
||||||
|
|
||||||
logging.info("Weather client initialized successfully.")
|
logging.info("Weather client initialized successfully.")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Failed to initialize Weather client: {e}", exc_info=True)
|
logging.error(f"Failed to initialize Weather client: {e}", exc_info=True)
|
||||||
|
|
@ -418,6 +424,7 @@ def index() -> rx.Component:
|
||||||
rx.theme_panel(default_open=False),
|
rx.theme_panel(default_open=False),
|
||||||
rx.flex(
|
rx.flex(
|
||||||
rx.vstack(
|
rx.vstack(
|
||||||
|
State._radio_client.radio_card(),
|
||||||
clock_button,
|
clock_button,
|
||||||
main_flex,
|
main_flex,
|
||||||
news_card,
|
news_card,
|
||||||
|
|
|
||||||
21
shell.nix
Normal file
21
shell.nix
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
let
|
||||||
|
nixconfig = builtins.getFlake "github:death916/nixconfig";
|
||||||
|
unstable = nixconfig.inputs.nixpkgs-unstable.legacyPackages.x86_64-linux;
|
||||||
|
pkgs = nixconfig.inputs.nixpkgs.legacyPackages.x86_64-linux;
|
||||||
|
in
|
||||||
|
pkgs.mkShell {
|
||||||
|
packages = with pkgs; [
|
||||||
|
python313Packages.uv
|
||||||
|
python313Packages.ninja
|
||||||
|
python313Packages.numpy
|
||||||
|
bun
|
||||||
|
|
||||||
|
];
|
||||||
|
shellHook = ''
|
||||||
|
source .venv/bin/activate
|
||||||
|
# export PATH="${pkgs.bun}/bin:$PATH"
|
||||||
|
# export BUN_INSTALL="${pkgs.bun}/bin/bun"
|
||||||
|
export REFLEX_USE_SYSTEM_BUN=True
|
||||||
|
echo venv activated and bun version set
|
||||||
|
'';
|
||||||
|
}
|
||||||
17
utils/radio.py
Normal file
17
utils/radio.py
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
# connect to rda5807 chip and control it and display the current station
|
||||||
|
|
||||||
|
import reflex as rx
|
||||||
|
|
||||||
|
|
||||||
|
class Radio(rx.Base):
|
||||||
|
def open_radio_button(self):
|
||||||
|
return rx.button("Radio", on_click=self.open_radio_button)
|
||||||
|
|
||||||
|
def radio_card(self):
|
||||||
|
return rx.card(title="Radio")
|
||||||
|
|
||||||
|
|
||||||
|
class Radio_Control:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
@ -1,17 +1,21 @@
|
||||||
# /home/death916/code/python/deathclock/utils/weather.py
|
# /home/death916/code/python/deathclock/utils/weather.py
|
||||||
|
import datetime
|
||||||
|
import logging # Optional: Use logging for better error messages
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import datetime
|
|
||||||
import reflex as rx
|
import reflex as rx
|
||||||
import logging # Optional: Use logging for better error messages
|
|
||||||
|
|
||||||
# Configure logging (optional but recommended)
|
# Configure logging (optional but recommended)
|
||||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
logging.basicConfig(
|
||||||
|
level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
|
||||||
|
)
|
||||||
|
|
||||||
# Define the target filename consistently
|
# Define the target filename consistently
|
||||||
WEATHER_FILENAME = "weather.jpg"
|
WEATHER_FILENAME = "weather.jpg"
|
||||||
# Define the web path expected by the frontend
|
# Define the web path expected by the frontend
|
||||||
WEATHER_WEB_PATH = f"/{WEATHER_FILENAME}" # This should be relative to the assets dir
|
WEATHER_WEB_PATH = f"/{WEATHER_FILENAME}" # This should be relative to the assets dir
|
||||||
|
|
||||||
|
|
||||||
class Weather(rx.Base):
|
class Weather(rx.Base):
|
||||||
# No __init__ needed here for Pydantic compatibility
|
# No __init__ needed here for Pydantic compatibility
|
||||||
|
|
@ -23,7 +27,7 @@ class Weather(rx.Base):
|
||||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
project_root = os.path.dirname(script_dir)
|
project_root = os.path.dirname(script_dir)
|
||||||
assets_dir = os.path.join(project_root, 'assets')
|
assets_dir = os.path.join(project_root, "assets")
|
||||||
|
|
||||||
# Ensure the assets directory exists
|
# Ensure the assets directory exists
|
||||||
if not os.path.exists(assets_dir):
|
if not os.path.exists(assets_dir):
|
||||||
|
|
@ -38,11 +42,11 @@ class Weather(rx.Base):
|
||||||
"""Deletes the specific weather file in the given 'assets' directory."""
|
"""Deletes the specific weather file in the given 'assets' directory."""
|
||||||
target_file = os.path.join(assets_dir, WEATHER_FILENAME)
|
target_file = os.path.join(assets_dir, WEATHER_FILENAME)
|
||||||
if os.path.exists(target_file):
|
if os.path.exists(target_file):
|
||||||
try:
|
try:
|
||||||
os.remove(target_file)
|
os.remove(target_file)
|
||||||
logging.info(f"Deleted old weather file: {target_file}")
|
logging.info(f"Deleted old weather file: {target_file}")
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
logging.error(f"Failed to delete old weather file {target_file}: {e}")
|
logging.error(f"Failed to delete old weather file {target_file}: {e}")
|
||||||
|
|
||||||
def get_weather_screenshot(self) -> str | None:
|
def get_weather_screenshot(self) -> str | None:
|
||||||
"""
|
"""
|
||||||
|
|
@ -56,24 +60,29 @@ class Weather(rx.Base):
|
||||||
curl_command = [
|
curl_command = [
|
||||||
"curl",
|
"curl",
|
||||||
"-s", # Silent mode
|
"-s", # Silent mode
|
||||||
"v2.wttr.in/Sacramento.png?0u", # Fetch PNG, no border, no terminal escapes
|
"v2.wttr.in/Sacramento.png?0u", # Fetch PNG, no border, no terminal escapes
|
||||||
"-o",
|
"-o",
|
||||||
screenshot_path, # Save to the correct assets path
|
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
|
||||||
self.delete_old_screenshots(assets_dir)
|
self.delete_old_screenshots(assets_dir)
|
||||||
|
|
||||||
logging.info(f"Running curl command to fetch weather: {' '.join(curl_command)}")
|
logging.info(
|
||||||
process = subprocess.run(curl_command, check=True, capture_output=True, text=True)
|
f"Running curl command to fetch weather: {' '.join(curl_command)}"
|
||||||
logging.info(f"Curl command successful. Weather image saved to: {screenshot_path}") # Log correct save path
|
)
|
||||||
|
logging.info(
|
||||||
|
f"Curl command successful. Weather image saved to: {screenshot_path}"
|
||||||
|
) # Log correct save path
|
||||||
|
|
||||||
return WEATHER_WEB_PATH # e.g., "/weather.jpg"
|
return WEATHER_WEB_PATH # e.g., "/weather.jpg"
|
||||||
|
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
logging.error(f"Curl command failed for path {screenshot_path}: {e}")
|
logging.error(f"Curl command failed for path {screenshot_path}: {e}")
|
||||||
logging.error(f"Curl stderr: {e.stderr}")
|
logging.error(f"Curl stderr: {e.stderr}")
|
||||||
return None
|
return None
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"An unexpected error occurred saving to {screenshot_path}: {e}")
|
logging.error(
|
||||||
|
f"An unexpected error occurred saving to {screenshot_path}: {e}"
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue