start(); $configRepository = app_config_repository(); $message = null; $messageType = 'success'; if ($_SERVER['REQUEST_METHOD'] === 'POST') { $action = $_POST['action'] ?? ''; if ($action === 'login') { $success = $auth->login( trim((string) ($_POST['username'] ?? '')), (string) ($_POST['password'] ?? '') ); if ($success) { app_redirect(app_url('/admin/')); } $message = 'Login fehlgeschlagen. Bitte Zugangsdaten pruefen.'; $messageType = 'error'; } if ($action === 'save_config' && $auth->isAuthenticated()) { $config = $configRepository->getConfig(); $newPassword = trim((string) ($_POST['admin_password'] ?? '')); $config['app'] = [ 'name' => trim((string) ($_POST['app_name'] ?? 'Getraenkeautomat Monitor')), 'timezone' => trim((string) ($_POST['timezone'] ?? 'Europe/Berlin')), 'dashboard_refresh_seconds' => max(5, (int) ($_POST['dashboard_refresh_seconds'] ?? 15)), 'default_from_email' => trim((string) ($_POST['default_from_email'] ?? 'monitor@example.local')), 'base_path' => app_normalize_base_path((string) ($_POST['base_path'] ?? '')), ]; $config['api'] = [ 'bearer_token' => trim((string) ($_POST['bearer_token'] ?? 'change-me-token')), ]; $config['admin'] = [ 'username' => trim((string) ($_POST['admin_username'] ?? 'admin')), 'password_hash' => $newPassword !== '' ? password_hash($newPassword, PASSWORD_BCRYPT) : (string) ($config['admin']['password_hash'] ?? ''), ]; $config['alerts'] = [ 'webhooks' => normalizeWebhooks($_POST['webhooks'] ?? []), 'emails' => normalizeEmails($_POST['emails'] ?? []), ]; $config['machines'] = normalizeMachines($_POST['machines'] ?? []); $configRepository->saveConfig($config); $message = 'Konfiguration gespeichert.'; $messageType = 'success'; } } $config = $configRepository->getConfig(); if (!$auth->isAuthenticated()) { renderLogin($message, $messageType); exit; } renderAdmin($config, $message, $messageType); function renderLogin(?string $message, string $messageType): void { ?> Adminpanel Login

Adminbereich

Konfiguration sichern

Logge dich mit den statischen Zugangsdaten aus der JSON-Config ein.

Zurueck zum Dashboard
Adminpanel

Adminpanel

Konfiguration der Automaten

Hier werden API-Token, Zugangsdaten, Faecher und Alarmwege direkt in der JSON-Config gepflegt.

Allgemein

Leer lassen fuer den Domain-Root. Fuer Unterordner z. B. /auswertung eintragen.

API

ESP32-Clients senden dieses Token im Header Authorization: Bearer ....

Adminzugang

Webhooks

Mehrere Ziele sind moeglich. Header koennen als JSON hinterlegt werden.

$webhook): ?>

Email-Empfaenger

Emails werden ueber die Serverkonfiguration von mail() versendet.

$email): ?>

Automaten und Faecher

Jeder Automat enthaelt beliebig viele Faecher, die jeweils genau einem Sensor zugeordnet sind.

$machine): ?>

Webhook

Email-Empfaenger

Automat

Faecher koennen direkt darunter verwaltet werden.

$slot): ?>
Fach
$id, 'name' => trim((string) ($row['name'] ?? '')), 'url' => $url, 'enabled' => (string) ($row['enabled'] ?? '1') === '1', 'headers' => is_array($headers) ? $headers : [], ]; } return array_values($items); } function normalizeEmails(array $rows): array { $items = []; foreach ($rows as $row) { $id = trim((string) ($row['id'] ?? '')); $address = trim((string) ($row['address'] ?? '')); if ($id === '' && $address === '') { continue; } $items[] = [ 'id' => $id, 'name' => trim((string) ($row['name'] ?? '')), 'address' => $address, 'enabled' => (string) ($row['enabled'] ?? '1') === '1', ]; } return array_values($items); } function normalizeMachines(array $rows): array { $items = []; foreach ($rows as $row) { $id = trim((string) ($row['id'] ?? '')); $name = trim((string) ($row['name'] ?? '')); if ($id === '' && $name === '') { continue; } $slots = []; foreach (($row['slots'] ?? []) as $slot) { $sensorId = trim((string) ($slot['sensor_id'] ?? '')); if ($sensorId === '') { continue; } $slots[] = [ 'sensor_id' => $sensorId, 'label' => trim((string) ($slot['label'] ?? $sensorId)), 'product_name' => trim((string) ($slot['product_name'] ?? '')), 'full_distance_mm' => (float) ($slot['full_distance_mm'] ?? 0), 'empty_distance_mm' => (float) ($slot['empty_distance_mm'] ?? 0), 'distance_per_unit' => max(0.01, (float) ($slot['distance_per_unit'] ?? 1)), 'alert_below_units' => max(0, (int) ($slot['alert_below_units'] ?? 0)), 'webhook_ids' => parseIdList((string) ($slot['webhook_ids'] ?? '')), 'email_ids' => parseIdList((string) ($slot['email_ids'] ?? '')), ]; } $items[] = [ 'id' => $id, 'name' => $name, 'location' => trim((string) ($row['location'] ?? '')), 'slots' => $slots, ]; } return array_values($items); } function parseIdList(string $value): array { $parts = array_map('trim', explode(',', $value)); return array_values(array_filter($parts, static fn (string $item): bool => $item !== '')); }