[ 'title' => 'Wall Panel', 'poll_interval_ms' => 5000, 'main_room_name' => 'Главная', 'main_room_icon' => 'mdi:home', 'edit_mode' => false, 'battery_history_hours' => 4320, ], 'home_assistant' => [ 'base_url' => '', 'token' => '', 'verify_ssl' => true, 'weather_entity_id' => '', 'auto_label' => 'auto', 'auto_entity_ids' => [], ], 'camera' => [ 'rtsp_url' => 'rtsp://10.0.6.110:45321/feff99fa45f317e7', 'stream_url' => '', 'stream_mode' => 'hls', 'poster_url' => 'http://10.0.6.110:5000/api/doorbell/latest.jpg', 'popup_timeout_minutes' => 3, 'trigger_entities' => [ 'binary_sensor.door_all_occupancy', 'binary_sensor.barn_all_occupancy', 'binary_sensor.doorbell_all_occupancy', ], ], 'rooms' => [], ]; } function app_config_path(): string { return APP_ROOT . '/config/config.json'; } function app_storage_path(string $file): string { return APP_ROOT . '/storage/' . ltrim($file, '/'); } function app_ensure_directory(string $path): void { if (!is_dir($path)) { mkdir($path, 0775, true); } } function app_load_config(): array { $path = app_config_path(); app_ensure_directory(dirname($path)); if (!file_exists($path)) { $defaults = app_default_config(); file_put_contents($path, json_encode($defaults, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); return $defaults; } $raw = file_get_contents($path); if ($raw === false || trim($raw) === '') { return app_default_config(); } $decoded = json_decode($raw, true); if (!is_array($decoded)) { throw new RuntimeException('Invalid JSON in config/config.json'); } return array_replace_recursive(app_default_config(), $decoded); } function app_save_config(array $config): void { $path = app_config_path(); app_ensure_directory(dirname($path)); $json = json_encode($config, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); if ($json === false) { throw new RuntimeException('Failed to encode config'); } file_put_contents($path, $json . PHP_EOL, LOCK_EX); } function app_load_json_file(string $path, array $fallback = []): array { if (!file_exists($path)) { return $fallback; } $raw = file_get_contents($path); if ($raw === false || trim($raw) === '') { return $fallback; } $decoded = json_decode($raw, true); return is_array($decoded) ? $decoded : $fallback; } function app_save_json_file(string $path, array $data): void { app_ensure_directory(dirname($path)); $json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); if ($json === false) { throw new RuntimeException('Failed to encode JSON'); } file_put_contents($path, $json . PHP_EOL, LOCK_EX); }