deploy: secure weather caching
This commit is contained in:
+39
-1
@@ -803,7 +803,6 @@ def launch_chrome():
|
|||||||
"--disable-extensions",
|
"--disable-extensions",
|
||||||
"--disable-gpu",
|
"--disable-gpu",
|
||||||
"--disable-dev-shm-usage",
|
"--disable-dev-shm-usage",
|
||||||
"--disable-web-security",
|
|
||||||
"--allow-file-access-from-files",
|
"--allow-file-access-from-files",
|
||||||
f"--user-data-dir={profile_dir}",
|
f"--user-data-dir={profile_dir}",
|
||||||
f"--remote-debugging-port={CDP_PORT}",
|
f"--remote-debugging-port={CDP_PORT}",
|
||||||
@@ -827,9 +826,48 @@ if __name__ == "__main__":
|
|||||||
overlay = KioskOverlay(cdp)
|
overlay = KioskOverlay(cdp)
|
||||||
chrome_proc = launch_chrome()
|
chrome_proc = launch_chrome()
|
||||||
|
|
||||||
|
def update_weather_cache():
|
||||||
|
"""Fetch weather data in background via Python and cache as local JSON to bypass CORS securely."""
|
||||||
|
cache_file = _HOME / "kiosk-home" / "weather-data.json"
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
# 1. Geolocation lookup
|
||||||
|
req = urllib.request.Request(
|
||||||
|
"https://freeipapi.com/api/json",
|
||||||
|
headers={"User-Agent": "Mozilla/5.0"}
|
||||||
|
)
|
||||||
|
geo_raw = urllib.request.urlopen(req, timeout=8).read()
|
||||||
|
geo = json.loads(geo_raw)
|
||||||
|
|
||||||
|
loc_name = "Your Area"
|
||||||
|
if geo.get("cityName") and geo.get("regionName"):
|
||||||
|
loc_name = f"{geo['cityName']}, {geo['regionName']}"
|
||||||
|
elif geo.get("cityName"):
|
||||||
|
loc_name = geo["cityName"]
|
||||||
|
|
||||||
|
lat, lon = geo.get("latitude"), geo.get("longitude")
|
||||||
|
if lat and lon:
|
||||||
|
# 2. Weather forecast lookup
|
||||||
|
url = f"https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}¤t=temperature_2m,relative_humidity_2m,apparent_temperature,weather_code,wind_speed_10m&daily=weather_code,temperature_2m_max,temperature_2m_min&temperature_unit=fahrenheit&wind_speed_unit=mph&precipitation_unit=inch&timezone=auto"
|
||||||
|
fc_raw = urllib.request.urlopen(url, timeout=8).read()
|
||||||
|
fc = json.loads(fc_raw)
|
||||||
|
|
||||||
|
# 3. Save combined cache
|
||||||
|
payload = {"location": loc_name, "forecast": fc}
|
||||||
|
cache_file.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
cache_file.write_text(json.dumps(payload, indent=2))
|
||||||
|
print("Updated local weather-data.json cache successfully")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Weather cache background update failed: {e}")
|
||||||
|
|
||||||
|
# Update cache every 15 minutes
|
||||||
|
time.sleep(900)
|
||||||
|
|
||||||
def init_cdp():
|
def init_cdp():
|
||||||
if cdp.wait_ready(timeout=30):
|
if cdp.wait_ready(timeout=30):
|
||||||
print("CDP ready — persistent WebSocket connected successfully")
|
print("CDP ready — persistent WebSocket connected successfully")
|
||||||
|
|
||||||
|
threading.Thread(target=update_weather_cache, daemon=True).start()
|
||||||
threading.Thread(target=init_cdp, daemon=True).start()
|
threading.Thread(target=init_cdp, daemon=True).start()
|
||||||
|
|
||||||
sys.exit(app.exec_())
|
sys.exit(app.exec_())
|
||||||
|
|||||||
+8
-57
@@ -240,67 +240,19 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function initWeather() {
|
async function initWeather() {
|
||||||
// 1. Get coordinates using IP API fallback or direct Geolocation
|
|
||||||
try {
|
try {
|
||||||
if (navigator.geolocation) {
|
document.getElementById('loading-text').textContent = "📊 Loading local weather forecasts...";
|
||||||
navigator.geolocation.getCurrentPosition(
|
const resp = await fetch("weather-data.json");
|
||||||
async (pos) => {
|
|
||||||
// Successfully got GPS coordinates
|
|
||||||
await fetchForecast(pos.coords.latitude, pos.coords.longitude, "Local Location");
|
|
||||||
},
|
|
||||||
async () => {
|
|
||||||
// Denied or failed - fall back to IP lookup
|
|
||||||
await fetchViaIP();
|
|
||||||
},
|
|
||||||
{ timeout: 5000 }
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
await fetchViaIP();
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
document.getElementById('loading-text').textContent = "⚠️ Unable to load weather. Check internet connection.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchViaIP() {
|
|
||||||
try {
|
|
||||||
document.getElementById('loading-text').textContent = "🌐 Looking up location via IP...";
|
|
||||||
const resp = await fetch("https://freeipapi.com/api/json");
|
|
||||||
const data = await resp.json();
|
const data = await resp.json();
|
||||||
|
|
||||||
let locName = "Your Area";
|
const locName = data.location || "Your Area";
|
||||||
if (data.cityName && data.regionName) {
|
const fc = data.forecast;
|
||||||
locName = `${data.cityName}, ${data.regionName}`;
|
|
||||||
} else if (data.cityName) {
|
|
||||||
locName = data.cityName;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.latitude && data.longitude) {
|
|
||||||
await fetchForecast(data.latitude, data.longitude, locName);
|
|
||||||
} else {
|
|
||||||
throw new Error("Invalid IP response coordinates");
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
// Ultimate hard-coded default (e.g. general center of US/state if offline)
|
|
||||||
document.getElementById('loading-text').textContent = "⚠️ Location lookup failed. Please verify internet.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchForecast(lat, lon, locationLabel) {
|
|
||||||
try {
|
|
||||||
document.getElementById('loading-text').textContent = "📊 Loading weather forecasts...";
|
|
||||||
|
|
||||||
// Query the completely open, keyless Open-Meteo API
|
|
||||||
const url = `https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}¤t=temperature_2m,relative_humidity_2m,apparent_temperature,weather_code,wind_speed_10m&daily=weather_code,temperature_2m_max,temperature_2m_min&temperature_unit=fahrenheit&wind_speed_unit=mph&precipitation_unit=inch&timezone=auto`;
|
|
||||||
|
|
||||||
const resp = await fetch(url);
|
|
||||||
const data = await resp.json();
|
|
||||||
|
|
||||||
// Render current stats
|
// Render current stats
|
||||||
const current = data.current;
|
const current = fc.current;
|
||||||
const wInfo = getWeatherInfo(current.weather_code);
|
const wInfo = getWeatherInfo(current.weather_code);
|
||||||
|
|
||||||
document.getElementById('location-name').textContent = locationLabel;
|
document.getElementById('location-name').textContent = locName;
|
||||||
document.getElementById('temp-val').textContent = `${Math.round(current.temperature_2m)}°F`;
|
document.getElementById('temp-val').textContent = `${Math.round(current.temperature_2m)}°F`;
|
||||||
document.getElementById('main-icon').textContent = wInfo.emoji;
|
document.getElementById('main-icon').textContent = wInfo.emoji;
|
||||||
document.getElementById('condition-txt').textContent = wInfo.txt;
|
document.getElementById('condition-txt').textContent = wInfo.txt;
|
||||||
@@ -309,11 +261,10 @@
|
|||||||
document.getElementById('wind-val').textContent = `${Math.round(current.wind_speed_10m)} mph`;
|
document.getElementById('wind-val').textContent = `${Math.round(current.wind_speed_10m)} mph`;
|
||||||
|
|
||||||
// Render 3-Day Forecast
|
// Render 3-Day Forecast
|
||||||
const daily = data.daily;
|
const daily = fc.daily;
|
||||||
const forecastBox = document.getElementById('forecast-box');
|
const forecastBox = document.getElementById('forecast-box');
|
||||||
forecastBox.innerHTML = ""; // Clear loader
|
forecastBox.innerHTML = ""; // Clear loader
|
||||||
|
|
||||||
// We render days 1, 2, and 3 (index 1 to 3, as index 0 is today)
|
|
||||||
for (let i = 1; i <= 3; i++) {
|
for (let i = 1; i <= 3; i++) {
|
||||||
const dateStr = daily.time[i];
|
const dateStr = daily.time[i];
|
||||||
const dateObj = new Date(dateStr + "T00:00:00");
|
const dateObj = new Date(dateStr + "T00:00:00");
|
||||||
@@ -338,7 +289,7 @@
|
|||||||
document.getElementById('weather-content').style.display = 'block';
|
document.getElementById('weather-content').style.display = 'block';
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
document.getElementById('loading-text').textContent = "⚠️ Error pulling forecast data.";
|
document.getElementById('loading-text').textContent = "⚠️ Preparing weather data... Please wait a moment.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user