File size: 5,439 Bytes
31c0f24 759e937 eb2aa42 31c0f24 eb2aa42 31c0f24 d661a05 31c0f24 d661a05 31c0f24 759e937 91d6263 759e937 31c0f24 759e937 31c0f24 d661a05 31c0f24 d661a05 31c0f24 d661a05 31c0f24 d661a05 31c0f24 d661a05 31c0f24 d661a05 31c0f24 d661a05 31c0f24 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | import requests
import json
import os
import time
from datetime import datetime
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class WaveDataPuller:
def __init__(self, space_url="https://huggingface.co/spaces/nakas/NWPS_SWAN"):
self.space_url = space_url
self.api_url = f"{space_url}/run/predict"
self.output_dir = os.getenv('OUTPUT_DIR', '/tmp/wave_data')
self.poll_interval = int(os.getenv('POLL_INTERVAL', '3600')) # 1 hour default
# Create output directory with error handling for restricted environments
try:
os.makedirs(self.output_dir, exist_ok=True)
except PermissionError:
# Fall back to /tmp if we can't create in the specified location
self.output_dir = '/tmp/wave_data'
os.makedirs(self.output_dir, exist_ok=True)
def fetch_wave_data(self, lat=40.0, lon=-74.0):
"""Fetch wave data from the Hugging Face space for a specific location."""
try:
logger.info(f"Fetching wave data for lat={lat}, lon={lon} from Hugging Face space...")
# Construct the payload for the Gradio API call
# Assuming the NWPS_SWAN space has a function at fn_index 0 that takes lat and lon
payload = {
"fn_index": 0,
"data": [float(lat), float(lon)]
}
headers = {"Content-Type": "application/json"}
response = requests.post(self.api_url, headers=headers, data=json.dumps(payload))
response.raise_for_status() # Raise an exception for HTTP errors
result = response.json()
# Gradio API responses have a specific structure, usually with 'data' key
if "data" in result and len(result["data"]) > 0:
# Assuming the first element of the data array is the relevant wave data
return result["data"][0]
else:
logger.warning(f"Unexpected API response structure: {result}")
logger.warning("No accessible endpoints found, returning mock data")
return self.generate_mock_data(lat, lon)
except requests.exceptions.RequestException as e:
logger.error(f"Request to Hugging Face Space failed: {e}")
logger.warning("No accessible endpoints found, returning mock data")
return self.generate_mock_data(lat, lon)
except Exception as e:
logger.error(f"Error fetching wave data: {e}")
return None
def generate_mock_data(self, lat=40.0, lon=-74.0):
"""Generate mock SWAN wave data for testing"""
import random
return {
"timestamp": datetime.utcnow().isoformat(),
"location": {"lat": lat, "lon": lon},
"wave_data": {
"significant_wave_height": round(random.uniform(0.5, 3.0), 2),
"peak_wave_period": round(random.uniform(4.0, 12.0), 2),
"wave_direction": round(random.uniform(0, 360), 1),
"wind_speed": round(random.uniform(2.0, 15.0), 2),
"wind_direction": round(random.uniform(0, 360), 1)
},
"model": "NWPS_SWAN",
"forecast_hours": [0, 6, 12, 18, 24]
}
def save_data(self, data):
"""Save wave data to file"""
if not data:
return
timestamp = datetime.utcnow().strftime("%Y%m%d_%H%M%S")
filename = f"wave_data_{timestamp}.json"
filepath = os.path.join(self.output_dir, filename)
try:
with open(filepath, 'w') as f:
json.dump(data, f, indent=2)
logger.info(f"Data saved to {filepath}")
except Exception as e:
logger.error(f"Error saving data: {e}")
def run_continuous(self, lat=40.0, lon=-74.0):
"""Run continuous data pulling"""
logger.info(f"Starting continuous wave data pulling every {self.poll_interval} seconds")
while True:
try:
data = self.fetch_wave_data(lat, lon)
if data:
self.save_data(data)
logger.info("Wave data fetched and saved successfully")
else:
logger.warning("No data received")
time.sleep(self.poll_interval)
except KeyboardInterrupt:
logger.info("Stopping wave data puller...")
break
except Exception as e:
logger.error(f"Unexpected error: {e}")
time.sleep(60) # Wait 1 minute before retrying
def run_once(self, lat=40.0, lon=-74.0):
"""Run a single data pull"""
logger.info("Fetching wave data once...")
data = self.fetch_wave_data(lat, lon)
if data:
self.save_data(data)
logger.info("Wave data fetched and saved successfully")
else:
logger.error("Failed to fetch wave data")
if __name__ == "__main__":
puller = WaveDataPuller()
# Check if we should run once or continuously
run_mode = os.getenv('RUN_MODE', 'once')
if run_mode.lower() == 'continuous':
puller.run_continuous()
else:
puller.run_once() |