wavelog/application/controllers/Amsatstatus.php
2026-08-06 18:10:53 +02:00

204 lines
5.9 KiB
PHP

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Amsatstatus extends CI_Controller {
function __construct() {
parent::__construct();
if(!$this->user_model->authorize(2)) { $this->session->set_flashdata('error', __("You're not allowed to do that!")); redirect('dashboard'); }
}
public function index() {
$this->load->driver('cache', [
'adapter' => $this->config->item('cache_adapter') ?? 'file',
'backup' => $this->config->item('cache_backup') ?? 'file',
'key_prefix' => $this->config->item('cache_key_prefix') ?? ''
]);
$cache_key = 'amsatstatus_reports_24h';
$json = $this->cache->get($cache_key);
if ($json === false) {
$url = 'https://www.amsat.org/status/api/v1/reports.php?hours=24&limit=500';
$ctx = stream_context_create(['http' => [
'method' => 'GET',
'timeout' => 15,
'user_agent' => 'Wavelog/'.$this->optionslib->get_option('version')
]]);
$fetched = @file_get_contents($url, false, $ctx);
if ($fetched === false) {
$this->session->set_flashdata('message', __("The AMSAT status service is currently unavailable. Please try again later."));
$data['matrix'] = [];
$data['sat_order'] = [];
$data['display_names'] = [];
$data['wl_link'] = [];
$data['next_pass'] = [];
$data['now'] = time();
$data['page_title'] = __("AMSAT Satellite Status");
$this->load->view('interface_assets/header', $data);
$this->load->view('/amsatstatus/index', $data);
$this->load->view('interface_assets/footer', []);
return;
}
$this->cache->save($cache_key, $fetched, 60*15);
$json = $fetched;
}
$decoded = json_decode($json, true);
$reports = $decoded['data'] ?? [];
$status_priority = [
'Heard' => 1,
'Crew Active' => 2,
'Telemetry Only' => 3,
'Not Heard' => 4,
];
$now = time();
$buckets = [];
$sat_latest = [];
$display_names = [];
foreach ($reports as $r) {
$name = $r['name'] ?? '';
if ($name === '') continue;
if (!empty($r['satellite_display_name'])) {
$display_names[$name] = $r['satellite_display_name'];
} elseif (!isset($display_names[$name])) {
$display_names[$name] = $name;
}
$epoch = strtotime($r['reported_time'] ?? '');
if ($epoch === false) continue;
$age_h = (int)floor(($now - $epoch) / 3600);
if ($age_h < 0 || $age_h > 23) continue;
$col = $age_h;
$status = $r['report'] ?? '';
$callsign = $r['callsign'] ?? '';
$grid = $r['grid_square'] ?? '';
if (!isset($buckets[$name][$col])) {
$buckets[$name][$col] = [
'counts' => [],
'reporters' => [],
'winning' => $status,
'winning_priority' => $status_priority[$status] ?? 99,
'total' => 0,
'latest_epoch' => $epoch,
'latest_callsign' => $callsign,
'latest_grid' => $grid,
];
}
$cell =& $buckets[$name][$col];
$cell['counts'][$status] = ($cell['counts'][$status] ?? 0) + 1;
$cell['total']++;
$cell['reporters'][] = ['epoch' => $epoch, 'callsign' => $callsign, 'grid' => $grid, 'status' => $status];
$p = $status_priority[$status] ?? 99;
if ($p < $cell['winning_priority']) {
$cell['winning'] = $status;
$cell['winning_priority'] = $p;
}
if ($epoch > $cell['latest_epoch']) {
$cell['latest_epoch'] = $epoch;
$cell['latest_callsign'] = $callsign;
$cell['latest_grid'] = $grid;
}
unset($cell);
if (!isset($sat_latest[$name]) || $epoch > $sat_latest[$name]) {
$sat_latest[$name] = $epoch;
}
}
foreach ($buckets as $name => &$cells) {
foreach ($cells as &$cell) {
usort($cell['reporters'], function($a, $b) { return $b['epoch'] - $a['epoch']; });
}
unset($cell);
}
unset($cells);
$sat_order = array_keys($sat_latest);
usort($sat_order, fn($a, $b) => strnatcasecmp($display_names[$a] ?? $a, $display_names[$b] ?? $b));
$matrix = [];
foreach ($buckets as $name => $cells) {
$row = [];
for ($col = 0; $col < 24; $col++) {
$row[$col] = $cells[$col] ?? null;
}
$matrix[$name] = $row;
}
$this->load->model('satellite_model');
$this->load->model('stations');
$this->load->library('satpredict');
$wl_map = [];
foreach ($this->satellite_model->get_all_satellites_with_tle() as $wl) {
$base = $wl->satname ?: ($wl->displayname ?? '');
if ($base === '') continue;
$key = strtoupper(trim(preg_replace('/[\[_].*/', '', $base)));
if ($key !== '' && !isset($wl_map[$key])) {
$wl_map[$key] = $wl;
}
}
$grid = $this->stations->find_gridsquare();
$have_grid = ($grid && strtoupper((string)$grid) !== '0');
$alias = [
'ISS' => 'ARISS',
'SONATE-2' => 'SONATE',
];
$prefix_alias = [
'TEVEL2-' => 'TEV2-',
];
$wl_link = [];
$next_pass = [];
foreach ($sat_order as $name) {
$key = strtoupper(trim(preg_replace('/[\[_].*/', '', $name)));
if (isset($alias[$key])) {
$key = $alias[$key];
} else {
foreach ($prefix_alias as $from => $to) {
if (str_starts_with($key, $from)) {
$key = $to . substr($key, strlen($from));
break;
}
}
}
$wl = $wl_map[$key] ?? null;
if (!$wl) continue;
$wl_link[$name] = $wl->satname ?: $wl->displayname;
if ($have_grid) {
$pass = $this->satpredict->next_pass($wl, $grid, 0, 1);
if ($pass) {
$next_pass[$name] = [
'aos' => (float) $pass->aos,
'time' => Predict_Time::daynum2readable($pass->aos, 'UTC', 'H:i'),
'maxel' => isset($pass->max_el) ? (int)round($pass->max_el) : null,
];
}
}
}
$data['matrix'] = $matrix;
$data['sat_order'] = $sat_order;
$data['display_names'] = $display_names;
$data['wl_link'] = $wl_link;
$data['next_pass'] = $next_pass;
$data['now'] = $now;
$data['page_title'] = __("AMSAT Satellite Status");
$footerData = [];
$footerData['scripts'] = ['assets/js/sections/amsatstatus.js'];
$this->load->view('interface_assets/header', $data);
$this->load->view('/amsatstatus/index', $data);
$this->load->view('interface_assets/footer', $footerData);
}
}