wallpanell/wall_panel/api.php
2026-03-25 13:49:13 +03:00

255 lines
9.2 KiB
PHP
Executable File

<?php
declare(strict_types=1);
require_once __DIR__ . '/lib/bootstrap.php';
header('Content-Type: application/json; charset=utf-8');
function api_json(array $payload, int $status = 200): never
{
http_response_code($status);
echo json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
exit;
}
function api_input(): array
{
$raw = file_get_contents('php://input');
if ($raw === false || trim($raw) === '') {
return $_POST ?: [];
}
$decoded = json_decode($raw, true);
if (is_array($decoded)) {
return $decoded;
}
return $_POST ?: [];
}
function api_mirror_config_change(array $config, string $action, array $payload): array
{
$response = app_sync_remote_action($config, $action, $payload);
if (is_array($response) && is_array($response['config'] ?? null)) {
$config = app_merge_synced_config($config, $response['config']);
app_save_config($config);
}
return $config;
}
try {
$config = app_load_config();
$client = new HomeAssistantClient($config);
$action = strtolower((string)($_GET['action'] ?? 'snapshot'));
if ($action === 'bootstrap') {
api_json(app_build_snapshot($config, $client, 'main'));
}
if ($action === 'snapshot') {
$spaceId = (string)($_GET['space_id'] ?? ($_GET['room_id'] ?? 'main'));
api_json(app_build_snapshot($config, $client, $spaceId));
}
if ($action === 'history') {
$entityId = trim((string)($_GET['entity_id'] ?? ''));
$hours = max(1, (int)($_GET['hours'] ?? 24));
if ($entityId === '') {
api_json(['ok' => false, 'error' => 'entity_id is required'], 400);
}
api_json([
'ok' => true,
'entity_id' => $entityId,
'hours' => $hours,
'history' => $client->fetchEntityHistory($entityId, $hours),
]);
}
if ($action === 'service') {
$payload = api_input();
$entityId = trim((string)($payload['entity_id'] ?? ''));
$command = trim((string)($payload['command'] ?? 'toggle'));
$value = $payload['value'] ?? null;
if ($entityId === '') {
api_json(['ok' => false, 'error' => 'entity_id is required'], 400);
}
[$domain, $service, $serviceData] = app_service_for_entity($entityId, $command);
if ($command === 'set_temperature' && $value !== null) {
$serviceData['temperature'] = $value;
}
if ($command === 'set_hvac_mode' && $value !== null) {
$serviceData['hvac_mode'] = $value;
}
if ($command === 'set_fan_mode' && $value !== null) {
$serviceData['fan_mode'] = $value;
}
if ($command === 'set_swing_mode' && $value !== null) {
$serviceData['swing_mode'] = $value;
}
if ($command === 'set_preset_mode' && $value !== null) {
$serviceData['preset_mode'] = $value;
}
if ($command === 'set_position' && $value !== null) {
$serviceData['position'] = $value;
}
$result = $client->callService($domain, $service, $serviceData);
api_json(['ok' => true, 'result' => $result]);
}
if ($action === 'save-entity-override') {
$payload = api_input();
$roomId = trim((string)($payload['room_id'] ?? ''));
$entityId = trim((string)($payload['entity_id'] ?? ''));
if ($roomId === '' || $entityId === '') {
api_json(['ok' => false, 'error' => 'room_id and entity_id are required'], 400);
}
$patch = [
'visible' => array_key_exists('visible', $payload) ? (bool)$payload['visible'] : null,
'order' => array_key_exists('order', $payload) ? (int)$payload['order'] : null,
'card_type' => array_key_exists('card_type', $payload) ? (string)$payload['card_type'] : null,
'title' => array_key_exists('title', $payload) ? (string)$payload['title'] : null,
'icon' => array_key_exists('icon', $payload) ? (string)$payload['icon'] : null,
];
$config = app_update_entity_override($config, $roomId, $entityId, $patch);
$config = api_mirror_config_change($config, $action, $payload);
app_save_config($config);
api_json(['ok' => true, 'config' => ['rooms' => $config['rooms']]]);
}
if ($action === 'save-space-override') {
$payload = api_input();
$roomId = trim((string)($payload['room_id'] ?? ''));
if ($roomId === '') {
api_json(['ok' => false, 'error' => 'room_id is required'], 400);
}
$patch = [
'visible' => array_key_exists('visible', $payload) ? (bool)$payload['visible'] : null,
'order' => array_key_exists('order', $payload) ? (int)$payload['order'] : null,
'name' => array_key_exists('name', $payload) ? (string)$payload['name'] : null,
'icon' => array_key_exists('icon', $payload) ? (string)$payload['icon'] : null,
];
if (array_key_exists('temperature_sensor_entity_id', $payload)) {
$patch['temperature_sensor_entity_id'] = (string)$payload['temperature_sensor_entity_id'];
}
$config = app_update_room_override($config, $roomId, $patch);
$config = api_mirror_config_change($config, $action, $payload);
app_save_config($config);
api_json(['ok' => true, 'config' => ['rooms' => $config['rooms']]]);
}
if ($action === 'create-room-layout-item') {
$payload = api_input();
$roomId = trim((string)($payload['room_id'] ?? ''));
if ($roomId === '') {
api_json(['ok' => false, 'error' => 'room_id is required'], 400);
}
$layoutItemId = trim((string)($payload['layout_item_id'] ?? ''));
if ($layoutItemId === '') {
$layoutItemId = 'slot_' . str_replace('.', '', uniqid('', true));
}
$order = array_key_exists('order', $payload) ? (int)$payload['order'] : null;
$config = app_update_room_layout_item($config, $roomId, $layoutItemId, [
'order' => $order,
]);
$config = api_mirror_config_change($config, $action, $payload);
app_save_config($config);
api_json([
'ok' => true,
'layout_item_id' => $layoutItemId,
'config' => ['rooms' => $config['rooms']],
]);
}
if ($action === 'save-room-layout-item') {
$payload = api_input();
$roomId = trim((string)($payload['room_id'] ?? ''));
$layoutItemId = trim((string)($payload['layout_item_id'] ?? ''));
if ($roomId === '' || $layoutItemId === '') {
api_json(['ok' => false, 'error' => 'room_id and layout_item_id are required'], 400);
}
$patch = [
'order' => array_key_exists('order', $payload) ? (int)$payload['order'] : null,
];
$config = app_update_room_layout_item($config, $roomId, $layoutItemId, $patch);
$config = api_mirror_config_change($config, $action, $payload);
app_save_config($config);
api_json(['ok' => true, 'config' => ['rooms' => $config['rooms']]]);
}
if ($action === 'delete-room-layout-item') {
$payload = api_input();
$roomId = trim((string)($payload['room_id'] ?? ''));
$layoutItemId = trim((string)($payload['layout_item_id'] ?? ''));
if ($roomId === '' || $layoutItemId === '') {
api_json(['ok' => false, 'error' => 'room_id and layout_item_id are required'], 400);
}
$config = app_delete_room_layout_item($config, $roomId, $layoutItemId);
$config = api_mirror_config_change($config, $action, $payload);
app_save_config($config);
api_json(['ok' => true, 'config' => ['rooms' => $config['rooms']]]);
}
if ($action === 'reorder-room-grid') {
$payload = api_input();
$roomId = trim((string)($payload['room_id'] ?? ''));
$entries = $payload['entries'] ?? [];
if ($roomId === '' || !is_array($entries)) {
api_json(['ok' => false, 'error' => 'room_id and entries are required'], 400);
}
$config = app_reorder_room_grid($config, $roomId, $entries);
$config = api_mirror_config_change($config, $action, $payload);
app_save_config($config);
api_json(['ok' => true, 'config' => ['rooms' => $config['rooms']]]);
}
if ($action === 'save-settings') {
$payload = api_input();
if (array_key_exists('edit_mode', $payload)) {
$config['app']['edit_mode'] = (bool)$payload['edit_mode'];
}
if (array_key_exists('title', $payload) && trim((string)$payload['title']) !== '') {
$config['app']['title'] = trim((string)$payload['title']);
}
$config = api_mirror_config_change($config, $action, $payload);
app_save_config($config);
api_json(['ok' => true, 'settings' => $config['app']]);
}
if ($action === 'popup') {
$payload = api_input();
$popup = app_handle_popup_event($config, $payload);
api_json(['ok' => true, 'popup' => $popup]);
}
api_json(['ok' => false, 'error' => 'Unknown action'], 404);
} catch (Throwable $e) {
api_json([
'ok' => false,
'error' => $e->getMessage(),
], 500);
}