dashboard - whole redesign and rewrite
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,8 @@ require_once __DIR__ . '/../../../general_files/ini/runtime_env.php';
|
||||
|
||||
const DASHBOARD_TIMEZONE = 'Europe/Berlin';
|
||||
const DASHBOARD_HA_ENTITY_ID = 'sensor.temp_temperatur';
|
||||
const DASHBOARD_OPENWEATHER_LATITUDE = '52.571291';
|
||||
const DASHBOARD_OPENWEATHER_LONGITUDE = '13.310422';
|
||||
const DASHBOARD_OPENWEATHER_LATITUDE = '52.571524';
|
||||
const DASHBOARD_OPENWEATHER_LONGITUDE = '13.312494';
|
||||
const DASHBOARD_NEWS_URL = '/intranet_repo/projects/contentpanel/insertion/news/png/';
|
||||
|
||||
function dashboard_now(): DateTimeImmutable
|
||||
@@ -91,15 +91,12 @@ function dashboard_prepare_announcement(array $announcement, DateTimeImmutable $
|
||||
$place = trim((string) ($announcement['ansage_ort'] ?? ''));
|
||||
|
||||
return [
|
||||
'start' => $start,
|
||||
'end' => $end,
|
||||
'date_label' => $label,
|
||||
'end_label' => $endLabel,
|
||||
'time' => $time,
|
||||
'place' => $place,
|
||||
'title' => trim((string) ($announcement['ansage_titel'] ?? '')),
|
||||
'subtitle' => trim((string) ($announcement['ansage_untertitel'] ?? '')),
|
||||
'meta' => implode(' · ', array_filter([$label, $endLabel, $time !== '' ? $time . ' Uhr' : '', $place])),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -146,8 +143,8 @@ function dashboard_list_posters(DateTimeImmutable $now, string $directory = CONT
|
||||
$title = str_replace('_', ' ', substr($match[1], 11));
|
||||
$posters[] = $image + [
|
||||
'document' => $match[1],
|
||||
'kind' => 'poster', 'expires' => $expiry, 'page' => (int) $match[2],
|
||||
'title' => $title, 'alt' => $title . ' · Seite ' . (int) $match[2],
|
||||
'expires' => $expiry, 'page' => (int) $match[2],
|
||||
'alt' => $title . ' · Seite ' . (int) $match[2],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -162,10 +159,7 @@ function dashboard_month_images(?string $directory = null): array
|
||||
$filename = 'terminuebersicht-' . $page . '.png';
|
||||
$image = dashboard_image($directory . '/' . $filename, 'month/' . $filename);
|
||||
if ($image) {
|
||||
$images[] = $image + [
|
||||
'kind' => 'month', 'page' => $page, 'title' => 'Monatsplan',
|
||||
'alt' => 'Monatsplan · Seite ' . $page,
|
||||
];
|
||||
$images[] = $image + ['alt' => 'Monatsplan · Seite ' . $page];
|
||||
}
|
||||
}
|
||||
return $images;
|
||||
@@ -183,7 +177,7 @@ function dashboard_fetch_indoor_temperature(): array
|
||||
}
|
||||
|
||||
return [
|
||||
'value' => round((float) $data['state'], 1),
|
||||
'value' => (int) ceil((float) $data['state'] - 0.4),
|
||||
'unit' => (string) ($data['attributes']['unit_of_measurement'] ?? '°C'),
|
||||
];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user