54 lines
2.6 KiB
PHP
54 lines
2.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
const DASHBOARD_BVG_STOP = '900086103';
|
|
|
|
function dashboard_fetch_departures(): array
|
|
{
|
|
$directory = __DIR__ . '/../cache';
|
|
if (!is_dir($directory) && !@mkdir($directory, 0775, true) && !is_dir($directory)) {
|
|
throw new RuntimeException('BVG-Cache nicht beschreibbar.');
|
|
}
|
|
$file = fopen($directory . '/bvg-' . DASHBOARD_BVG_STOP . '.json', 'c+');
|
|
if (!$file) {
|
|
throw new RuntimeException('BVG-Cache nicht verfügbar.');
|
|
}
|
|
try {
|
|
// Gemeinsamer Cache: alle 12 Sekunden und zusätzlich zum Minutenwechsel.
|
|
if (!flock($file, LOCK_EX)) {
|
|
throw new RuntimeException('BVG-Cache konnte nicht gesperrt werden.');
|
|
}
|
|
$cache = json_decode(stream_get_contents($file), true) ?: [];
|
|
if (microtime(true) >= ($cache['retryAt'] ?? 0)) {
|
|
try {
|
|
$data = dashboard_http_json('https://v6.bvg.transport.rest/stops/' . DASHBOARD_BVG_STOP . '/departures?'
|
|
. 'duration=120&results=30&bus=true&suburban=false&subway=false&tram=false'
|
|
. '&ferry=false&express=false®ional=false&remarks=false&language=de&pretty=false');
|
|
if (!isset($data['departures']) || !is_array($data['departures'])) {
|
|
throw new RuntimeException('Unerwartete BVG-Antwort.');
|
|
}
|
|
$now = microtime(true);
|
|
$cache = ['departures' => array_values(array_filter($data['departures'], static fn(array $d): bool =>
|
|
($d['line']['product'] ?? '') === 'bus'
|
|
&& in_array($d['stop']['id'] ?? '', [DASHBOARD_BVG_STOP, '900000' . substr(DASHBOARD_BVG_STOP, 3)], true))),
|
|
'updatedAt' => (int) round($now * 1000), 'retryAt' => min($now + 12, (floor($now / 60) + 1) * 60),
|
|
'unavailable' => false];
|
|
} catch (Throwable $error) {
|
|
// Letzte Antwort behalten; auch bei 429/503 nicht sofort erneut anfragen.
|
|
error_log('Dashboard BVG: ' . $error->getMessage());
|
|
$cache['unavailable'] = true;
|
|
$cache['retryAt'] = microtime(true) + 30;
|
|
}
|
|
rewind($file);
|
|
$json = json_encode($cache, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);
|
|
if (!ftruncate($file, 0) || fwrite($file, $json) !== strlen($json) || !fflush($file)) {
|
|
throw new RuntimeException('BVG-Cache konnte nicht gespeichert werden.');
|
|
}
|
|
}
|
|
return $cache + ['departures' => [], 'updatedAt' => 0];
|
|
} finally {
|
|
fclose($file);
|
|
}
|
|
}
|