0rbix / src /ssc_api.py
nicolasleiva's picture
Initial commit: Add complete Orbix project
3dc2617
Raw History Blame Contribute Delete
9.06 kB
import json
import logging
import requests
from typing import Dict, Any, List, Optional
from datetime import datetime
from .config import logger
class SSCApi:
"""
Cliente para la API del Space Science Center (SSC) que maneja solicitudes
y respuestas en formato JSON con las peculiaridades requeridas por la API.
"""
def __init__(self):
self.logger = logging.getLogger("Orbix.SSCApi")
from .config import SSC_API_URL, SSC_API_KEY
self.BASE_URL = SSC_API_URL
self.API_KEY = SSC_API_KEY
self.session = requests.Session()
self.session.headers.update({
"Content-Type": "application/json",
"Accept": "application/json",
"X-Api-Key": self.API_KEY
})
def _format_time(self, dt: datetime) -> str:
"""
Formatea una fecha y hora en el formato requerido por la API SSC.
"""
return dt.strftime("%Y-%m-%dT%H:%M:%S.000+00:00")
def create_data_request(self,
satellites: List[str],
start_time: datetime,
end_time: datetime,
resolution_factor: int = 1) -> Dict[str, Any]:
"""
Crea una solicitud de datos en el formato JSON requerido por la API SSC.
Args:
satellites: Lista de IDs de satélites
start_time: Tiempo de inicio para los datos
end_time: Tiempo de fin para los datos
resolution_factor: Factor de resolución para los datos (1=máxima resolución)
Returns:
Diccionario con la solicitud formateada para la API SSC
"""
# Crear especificaciones de satélites en el formato requerido
satellite_specs = [
[
"gov.nasa.gsfc.sscweb.schema.SatelliteSpecification",
{
"Id": sat_id,
"ResolutionFactor": resolution_factor
}
] for sat_id in satellites
]
# Construir la solicitud completa con el formato específico requerido
request_data = [
"gov.nasa.gsfc.sscweb.schema.DataRequest",
{
"Description": "Orbital data request from Orbix",
"TimeInterval": [
"gov.nasa.gsfc.sscweb.schema.TimeInterval",
{
"Start": [
"javax.xml.datatype.XMLGregorianCalendar",
self._format_time(start_time)
],
"End": [
"javax.xml.datatype.XMLGregorianCalendar",
self._format_time(end_time)
]
}
],
"Satellites": [
"java.util.ArrayList",
satellite_specs
],
"OutputOptions": [
"gov.nasa.gsfc.sscweb.schema.OutputOptions",
{
"CoordinateSystem": "gse",
"AllLocationFilters": True,
"RegionFilterDistance": 0.0,
"MinMaxPoints": 2
}
]
}
]
return request_data
def get_satellite_data(self,
satellites: List[str],
start_time: datetime,
end_time: datetime,
resolution_factor: int = 1) -> Dict[str, Any]:
"""
Obtiene datos de satélites de la API SSC.
Args:
satellites: Lista de IDs de satélites
start_time: Tiempo de inicio para los datos
end_time: Tiempo de fin para los datos
resolution_factor: Factor de resolución para los datos (1=máxima resolución)
Returns:
Datos de satélites procesados
"""
request_data = self.create_data_request(
satellites, start_time, end_time, resolution_factor
)
try:
response = self.session.post(
f"{self.BASE_URL}/locations",
json=request_data
)
response.raise_for_status()
return self._process_response(response.json())
except requests.RequestException as e:
self.logger.error(f"Error al obtener datos de satélites: {str(e)}")
return {"error": str(e)}
def _process_response(self, response_data: Dict[str, Any]) -> Dict[str, Any]:
"""
Procesa la respuesta de la API SSC y la convierte a un formato más
utilizable para el sistema Orbix.
Args:
response_data: Datos de respuesta de la API SSC
Returns:
Datos procesados en formato compatible con Orbix
"""
try:
# Extraer los datos relevantes de la estructura JSON compleja
# La estructura exacta dependerá de la respuesta de la API
result = {}
# Verificar si hay un error en la respuesta
if "Exception" in str(response_data):
error_msg = str(response_data)
self.logger.error(f"Error en la respuesta de la API SSC: {error_msg}")
return {"error": error_msg}
# Extraer datos de satélites
# Nota: Esta parte puede necesitar ajustes según la estructura exacta de la respuesta
if isinstance(response_data, list) and len(response_data) > 1:
data_container = response_data[1]
if "Result" in data_container and isinstance(data_container["Result"], list):
result_data = data_container["Result"][1]
# Procesar datos para cada satélite
satellites_data = {}
for sat_data in result_data:
if isinstance(sat_data, list) and len(sat_data) > 1:
sat_id = sat_data[1].get("Id")
if sat_id:
# Extraer coordenadas y tiempos
coordinates = sat_data[1].get("Coordinates", [])
times = sat_data[1].get("Time", [])
# Convertir a formato utilizable
trajectory_data = []
for i in range(min(len(coordinates), len(times))):
if i < len(coordinates) and i < len(times):
point = {
"time": times[i],
"x": coordinates[i][0],
"y": coordinates[i][1],
"z": coordinates[i][2]
}
trajectory_data.append(point)
satellites_data[sat_id] = trajectory_data
result["satellites"] = satellites_data
return result
except Exception as e:
self.logger.error(f"Error al procesar la respuesta: {str(e)}")
return {"error": str(e)}
def get_available_satellites(self) -> List[str]:
"""
Obtiene la lista de satélites disponibles en la API SSC.
Returns:
Lista de IDs de satélites disponibles
"""
try:
response = self.session.get(f"{self.BASE_URL}/observatories")
response.raise_for_status()
# Procesar la respuesta para extraer los IDs de satélites
# La estructura exacta dependerá de la respuesta de la API
satellites = []
response_data = response.json()
# Extraer IDs de satélites de la respuesta
# Nota: Esta parte puede necesitar ajustes según la estructura exacta de la respuesta
if isinstance(response_data, list) and len(response_data) > 1:
data_container = response_data[1]
if "Observatory" in data_container and isinstance(data_container["Observatory"], list):
for sat in data_container["Observatory"][1]:
if isinstance(sat, list) and len(sat) > 1:
sat_id = sat[1].get("Id")
if sat_id:
satellites.append(sat_id)
return satellites
except requests.RequestException as e:
self.logger.error(f"Error al obtener satélites disponibles: {str(e)}")
return []