add logging for opensky user, update limits iterations 4000credits/d

This commit is contained in:
VALLONGOL 2025-06-10 10:27:25 +02:00
parent 9890da2eef
commit 51a4bc3382
2 changed files with 36 additions and 33 deletions

View File

@ -14,7 +14,7 @@ be clearly documented.
# --- API Configuration ---
# Base URL for the OpenSky Network API's 'states/all' endpoint.
OPENSKY_API_URL: str = "https://opensky-network.org/api/states/all" # Used for direct calls if OAuth2 implemented
OPENSKY_API_URL: str = "https://opensky-network.org/api/states/all" # Used for direct calls with OAuth2
# Default timeout for API requests in seconds.
DEFAULT_API_TIMEOUT_SECONDS: int = 15
@ -22,24 +22,19 @@ DEFAULT_API_TIMEOUT_SECONDS: int = 15
# --- OpenSky Network API Authentication Configuration ---
# Set to True to attempt authentication with OpenSky Network API using OAuth2 Client Credentials.
# If False, or if Client ID/Secret are not provided, anonymous access will be used.
USE_OPENSKY_CREDENTIALS: bool = False # MODIFIED: Default to False, set to True if you want to use OAuth2
USE_OPENSKY_CREDENTIALS: bool = True # Set this to True to enable OAuth2 authentication
# MODIFIED: Changed from USERNAME/PASSWORD to CLIENT_ID/CLIENT_SECRET for OAuth2
# Your OpenSky Network API Client ID.
# Best stored as an environment variable (e.g., OPENSKY_CLIENT_ID).
OPENSKY_CLIENT_ID: Optional[str] ="luca.vallongo@gmail.com-api-client" #os.getenv("OPENSKY_CLIENT_ID", None)
OPENSKY_CLIENT_ID: Optional[str] = "luca.vallongo@gmail.com-api-client" # os.getenv("OPENSKY_CLIENT_ID")
# Your OpenSky Network API Client Secret.
# Best stored as an environment variable (e.g., OPENSKY_CLIENT_SECRET).
OPENSKY_CLIENT_SECRET: Optional[str] ="dGBGjEDLmqGGsZmdd5FOH8hOfIcekMjK" #os.getenv("OPENSKY_CLIENT_SECRET", None)
OPENSKY_CLIENT_SECRET: Optional[str] = "heEkoeugbCmfKml5wTxk9ywoPFW1Z3vW" # os.getenv("OPENSKY_CLIENT_SECRET")
# OpenSky Network Token URL (used for OAuth2 Client Credentials Flow)
# This is a standard Keycloak token endpoint format.
OPENSKY_TOKEN_URL: str = "https://opensky-network.org/auth/realms/opensky/protocol/openid-connect/token"
# MODIFICATION: Corrected the entire URL to match the official documentation, including the 'auth.' subdomain.
OPENSKY_TOKEN_URL: str = "https://auth.opensky-network.org/auth/realms/opensky-network/protocol/openid-connect/token"
# MODIFIED: Removed OPENSKY_USERNAME and OPENSKY_PASSWORD as they are for Basic Auth (being deprecated)
# OPENSKY_USERNAME: Optional[str] = os.getenv("OPENSKY_USERNAME", None)
# OPENSKY_PASSWORD: Optional[str] = os.getenv("OPENSKY_PASSWORD", None)
# Removed OPENSKY_USERNAME and OPENSKY_PASSWORD as they are for Basic Auth (being deprecated)
# --- ADS-B Exchange API Configuration (Placeholder for future) ---
# LIVE_DATA_SOURCE: str = "OPENSKY" # Options: "OPENSKY", "ADSB_EXCHANGE", "MOCK"

View File

@ -9,6 +9,7 @@ import time
import threading
from queue import Queue, Empty as QueueEmpty, Full as QueueFull
import random
import os # Import added for environment variable checks
from typing import Dict, Any, List, Optional, Tuple
# Import OpenSkyApi for anonymous access (fallback)
@ -68,7 +69,7 @@ class OpenSkyLiveAdapter(BaseLiveDataAdapter):
self.token_expires_at: float = 0.0
self.api_client_anonymous: Optional[OpenSkyApi] = None
self.api_timeout = getattr(app_config, "DEFAULT_API_TIMEOUT_SECONDS", 15) # Questo timeout si userà per le chiamate OAuth dirette
self.api_timeout = getattr(app_config, "DEFAULT_API_TIMEOUT_SECONDS", 15) # This timeout is used for direct OAuth calls
self.use_oauth = getattr(app_config, "USE_OPENSKY_CREDENTIALS", False)
if self.use_oauth:
@ -87,13 +88,9 @@ class OpenSkyLiveAdapter(BaseLiveDataAdapter):
if not self.use_oauth:
try:
# MODIFICATO: Rimosso l'argomento 'timeout' dalla chiamata al costruttore di OpenSkyApi
# PERCHÉ: La libreria opensky-api non accetta 'timeout' nel suo costruttore.
# DOVE: Inizializzazione di self.api_client_anonymous.
# COME: Eliminato `timeout=self.api_timeout`. La libreria usa il suo timeout interno (di solito 5s per requests).
self.api_client_anonymous = OpenSkyApi() # Timeout non è un argomento valido qui
# The opensky-api library does not accept a 'timeout' argument in its constructor.
self.api_client_anonymous = OpenSkyApi() # Timeout is not a valid argument here
module_logger.info(
# MODIFICATO: Aggiornato il messaggio di log per riflettere che il timeout della libreria è interno.
f"{self.name}: OpenSkyApi client (anonymous access) initialized (uses internal timeout)."
)
except Exception as e:
@ -117,22 +114,32 @@ class OpenSkyLiveAdapter(BaseLiveDataAdapter):
module_logger.error(f"{self.name}: Cannot get OAuth token, client ID/secret/URL missing.")
return False
data = {
# Manually URL-encode the payload to ensure correct formatting
from urllib.parse import urlencode
payload_dict = {
"grant_type": "client_credentials",
"client_id": self.client_id,
"client_secret": self.client_secret,
}
headers = {"Content-Type": "application/x-www-form-urlencoded"}
# The urlencode function will handle converting this to the correct string format
encoded_payload = urlencode(payload_dict)
headers = {
"Content-Type": "application/x-www-form-urlencoded",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/119.0"
}
module_logger.info(f"{self.name}: Requesting OAuth2 access token from {self.token_url}...")
try:
response = requests.post(self.token_url, data=data, headers=headers, timeout=self.api_timeout)
response.raise_for_status() # Raise HTTPError for bad responses
# Pass the manually encoded string to the 'data' parameter
response = requests.post(self.token_url, data=encoded_payload, headers=headers, timeout=self.api_timeout, verify=False)
response.raise_for_status()
token_data = response.json()
self.access_token = token_data.get("access_token")
expires_in = token_data.get("expires_in", 300) # Default to 5 minutes if not specified
self.token_expires_at = time.time() + expires_in - 60 # Subtract 60s buffer
expires_in = token_data.get("expires_in", 300)
self.token_expires_at = time.time() + expires_in - 60
if self.access_token:
module_logger.info(f"{self.name}: Successfully obtained OAuth2 access token. Expires in ~{expires_in // 60} minutes.")
@ -142,14 +149,17 @@ class OpenSkyLiveAdapter(BaseLiveDataAdapter):
return False
except requests.exceptions.HTTPError as http_err:
status_code = http_err.response.status_code if http_err.response else "N/A"
error_text = http_err.response.text if http_err.response else "No response text"
module_logger.error(f"{self.name}: HTTP error {status_code} obtaining OAuth token: {error_text}", exc_info=False)
except requests.exceptions.RequestException as req_err:
module_logger.error(f"{self.name}: Network error obtaining OAuth token: {req_err}", exc_info=True)
try:
error_details = http_err.response.json()
error_text = f"JSON Response: {error_details}"
except requests.exceptions.JSONDecodeError:
error_text = f"Non-JSON Response: {http_err.response.text.strip()}"
module_logger.error(f"{self.name}: HTTP error {status_code} obtaining OAuth token: {error_text}", exc_info=True)
except Exception as e:
module_logger.error(f"{self.name}: Unexpected error obtaining OAuth token: {e}", exc_info=True)
self.access_token = None # Ensure token is cleared on failure
self.access_token = None
return False
def _is_token_valid(self) -> bool:
@ -167,7 +177,6 @@ class OpenSkyLiveAdapter(BaseLiveDataAdapter):
def _convert_opensky_api_state_to_canonical(self, sv_opensky_lib: Any) -> Optional[CanonicalFlightState]:
"""Converts an OpenSkyApi library StateVector object to a CanonicalFlightState object."""
# This is the same conversion logic as before when using the opensky-api library
try:
if sv_opensky_lib.icao24 is None: return None
primary_ts = sv_opensky_lib.time_position if sv_opensky_lib.time_position is not None else sv_opensky_lib.last_contact
@ -233,10 +242,8 @@ class OpenSkyLiveAdapter(BaseLiveDataAdapter):
module_logger.error(f"{self.name}: Unexpected error converting direct API state: {e_conv}. List: {raw_state_list}", exc_info=True)
return None
def _perform_api_request(self) -> Dict[str, Any]:
if app_config.USE_MOCK_OPENSKY_API:
# ... (Mock logic remains the same as your previous version) ...
module_logger.info(f"{self.name}: Using MOCK API data as per configuration.")
self._send_status_to_queue(STATUS_FETCHING, "Generating mock flight data...")
if app_config.MOCK_API_ERROR_SIMULATION == "RATE_LIMITED":
@ -279,6 +286,7 @@ class OpenSkyLiveAdapter(BaseLiveDataAdapter):
module_logger.error(f"{self.name}: {err_msg}")
# If token fails, we could try anonymous as a fallback or just fail this attempt
if not self.api_client_anonymous: # If anonymous is not even an option
self._consecutive_api_errors += 1
return {"error_type": STATUS_API_ERROR_TEMPORARY, "message": err_msg, "status_code": "OAUTH_TOKEN_FAILURE", "delay": self._calculate_next_backoff_delay(), "consecutive_errors": self._consecutive_api_errors}
else: # Fallback to anonymous for this attempt
module_logger.warning(f"{self.name}: Attempting anonymous access due to OAuth token failure.")