['id' => '25338', 'frequencies' => ['137.620 MHz']], 'NOAA 18' => ['id' => '28654', 'frequencies' => ['137.9125 MHz']], 'NOAA 19' => ['id' => '33591', 'frequencies' => ['137.100 MHz']], 'ISS' => ['id' => '25544', 'frequencies' => ['145.800 MHz']], 'GOES-16' => ['id' => '41866', 'frequencies' => ['1686.0 MHz']], 'GOES-17' => ['id' => '43226', 'frequencies' => ['1686.0 MHz']], 'Himawari-8' => ['id' => '40267', 'frequencies' => ['1687.0 MHz']], 'Meteosat-11' => ['id' => '41588', 'frequencies' => ['1691.0 MHz']], 'Fengyun-4A' => ['id' => '43010', 'frequencies' => ['1675.0 MHz']], 'ELEKTRO-L N2' => ['id' => '40570', 'frequencies' => ['1690.0 MHz']], 'Aqua' => ['id' => '27424', 'frequencies' => ['2030.0 MHz']], 'Terra' => ['id' => '25994', 'frequencies' => ['2030.0 MHz']], 'Suomi NPP' => ['id' => '37849', 'frequencies' => ['2030.0 MHz']], 'JPSS-1' => ['id' => '43013', 'frequencies' => ['2030.0 MHz']], 'MetOp-A' => ['id' => '29499', 'frequencies' => ['1700.0 MHz']], 'MetOp-B' => ['id' => '38771', 'frequencies' => ['1700.0 MHz']], 'MetOp-C' => ['id' => '43689', 'frequencies' => ['1700.0 MHz']] ]; private $userLocation = []; public function __construct() { $this->getUserLocation(); $this->loadTLEData(); } /** * Obtém a localização do usuário com base no IP */ private function getUserLocation() { // Primeiro tenta obter via API de geolocalização por IP try { $ip = $_SERVER['REMOTE_ADDR']; if ($ip === '127.0.0.1' || $ip === '::1') { $ip = file_get_contents('http://api.ipify.org'); } $locationData = @file_get_contents("http://ip-api.com/json/{$ip}"); if ($locationData !== false) { $location = json_decode($locationData, true); if ($location && $location['status'] === 'success') { $this->userLocation = [ 'lat' => $location['lat'], 'lon' => $location['lon'], 'city' => $location['city'], 'country' => $location['country'], 'ip' => $ip ]; return; } } } catch (Exception $e) { // Falha silenciosa, usaremos valores padrão } // Valores padrão (Carapicuíba, SP, Brasil) $this->userLocation = [ 'lat' => -23.5235, 'lon' => -46.8360, 'city' => 'Carapicuíba', 'country' => 'Brasil', 'ip' => $_SERVER['REMOTE_ADDR'] ?? '127.0.0.1' ]; } /** * Carrega dados TLE (Two-Line Element) dos satélites */ private function loadTLEData() { $tleUrl = "https://celestrak.org/NORAD/elements/gp.php?GROUP=weather&FORMAT=tle"; try { $content = @file_get_contents($tleUrl); if ($content === false) { throw new Exception("Não foi possível carregar dados TLE"); } $lines = explode("\n", $content); $currentSatellite = null; foreach ($lines as $line) { $line = trim($line); if (empty($line)) continue; // Verifica se é linha de nome do satélite if (!is_numeric(substr($line, 0, 1))) { $currentSatellite = trim($line); if (isset($this->allSatellites[$currentSatellite])) { $this->tleData[$currentSatellite] = ['name' => $currentSatellite]; } } // Verifica se é linha 1 do TLE elseif (isset($this->tleData[$currentSatellite]) && !isset($this->tleData[$currentSatellite]['line1'])) { $this->tleData[$currentSatellite]['line1'] = $line; } // Verifica se é linha 2 do TLE elseif (isset($this->tleData[$currentSatellite]) && isset($this->tleData[$currentSatellite]['line1']) && !isset($this->tleData[$currentSatellite]['line2'])) { $this->tleData[$currentSatellite]['line2'] = $line; } } } catch (Exception $e) { // Fallback para dados TLE estáticos em caso de erro $this->loadStaticTLE(); } } /** * Dados TLE estáticos como fallback */ private function loadStaticTLE() { $this->tleData = [ 'NOAA 15' => [ 'name' => 'NOAA 15', 'line1' => '1 25338U 98030A 24123.45833333 .00000078 00000+0 00000+0 0 9998', 'line2' => '2 25338 98.7242 103.3862 0011016 73.1596 287.0574 14.25911785421652' ], 'NOAA 18' => [ 'name' => 'NOAA 18', 'line1' => '1 28654U 05018A 24123.45833333 .00000078 00000+0 00000+0 0 9997', 'line2' => '2 28654 98.9242 103.3862 0011016 73.1596 287.0574 14.25911785421652' ], 'NOAA 19' => [ 'name' => 'NOAA 19', 'line1' => '1 33591U 09005A 24123.45833333 .00000078 00000+0 00000+0 0 9996', 'line2' => '2 33591 99.0242 103.3862 0011016 73.1596 287.0574 14.25911785421652' ], 'ISS' => [ 'name' => 'ISS', 'line1' => '1 25544U 98067A 24124.51736111 .00020000 00000+0 35000-3 0 9997', 'line2' => '2 25544 51.6414 55.6236 0003506 28.6667 22.5333 15.49859216437524' ] ]; } /** * Calcula a próxima passagem do satélite */ private function calculateNextPass($satellite, $observerLat, $observerLon, $observerAlt = 0) { if (!isset($this->tleData[$satellite])) { return null; } $tle = $this->tleData[$satellite]; $now = time(); // Simulação simplificada de cálculo de passagem $passes = []; for ($i = 0; $i < 5; $i++) { $timestamp = $now + ($i * 3600 * 3); // A cada 3 horas $elevation = rand(10, 90); // Simulação de elevação $passes[] = [ 'start' => date('Y-m-d H:i:s', $timestamp), 'max_elevation' => $elevation, 'duration' => rand(300, 900) // 5-15 minutos ]; } return $passes; } /** * Obtém dados meteorológicos atuais */ private function getWeatherData() { // Simulação de dados meteorológicos return [ 'temperature' => rand(15, 30), 'humidity' => rand(40, 90), 'pressure' => rand(1000, 1020), 'visibility' => rand(5, 20) ]; } /** * Gera a interface web com globo 3D */ public function renderInterface() { $observerLat = isset($_GET['lat']) ? floatval($_GET['lat']) : $this->userLocation['lat']; $observerLon = isset($_GET['lon']) ? floatval($_GET['lon']) : $this->userLocation['lon']; // Obter satélites selecionados (padrão: todos os NOAA) $selectedSatellites = []; if (isset($_GET['satellites']) && is_array($_GET['satellites'])) { $selectedSatellites = $_GET['satellites']; } else { $selectedSatellites = ['NOAA 15', 'NOAA 18', 'NOAA 19']; } $weather = $this->getWeatherData(); $currentTime = new DateTime('now', new DateTimeZone('America/Sao_Paulo')); // Preparar dados dos satélites selecionados $satelliteData = []; foreach ($selectedSatellites as $satellite) { if (isset($this->tleData[$satellite])) { $passes = $this->calculateNextPass($satellite, $observerLat, $observerLon); $satelliteData[$satellite] = [ 'info' => $this->allSatellites[$satellite], 'passes' => $passes ]; } } // Preparar lista de satélites para JavaScript $jsSatellites = json_encode($selectedSatellites); echo '
Acompanhe a posição e trajetória de satélites meteorológicos e de observação terrestre
Nenhuma passagem prevista
'; } echo '