loadMe(); $this->me = $me; $this->layout()->set("me", $me); } protected function apiAction() { if (!$this->me->is("employee")) { $this->returnJson(["status" => "error", "message" => "Unauthorized"]); return; } $return = match($this->request->do) { "getDisplays" => $this->getDisplaysApi(), "getGroups" => RaspberryDisplayModel::getGroups(), "createDisplay" => $this->createDisplayApi(), "updateDisplay" => $this->updateDisplayApi(), "deleteDisplay" => RaspberryDisplayModel::delete((int)$this->request->id), "updateOrder" => $this->updateOrderApi(), "discoverPi" => $this->discoverPiApi(), "getStatus" => $this->getStatusApi(), "getBatchStatus" => $this->getBatchStatusApi(), "setUrl" => $this->setUrlApi(), "refreshDisplay" => $this->refreshDisplayApi(), "cecPower" => $this->cecPowerApi(), "rebootPi" => $this->rebootPiApi(), "refreshAll" => $this->refreshAllApi(), "powerAll" => $this->powerAllApi(), "rebootAll" => $this->rebootAllApi(), default => null }; if ($return === null) { $this->returnJson(["status" => "error", "message" => "Unknown action"]); } elseif ($return === true) { $this->returnJson(["status" => "success"]); } elseif ($return === false) { $this->returnJson(["status" => "error", "message" => "Operation failed"]); } else { $this->returnJson(["status" => "OK", "result" => $return]); } } protected function getDisplaysApi(): array { $grouped = []; foreach (RaspberryDisplayModel::getAll() as $display) { $grouped[$display->group_name][] = [ "id" => (int)$display->id, "display_label" => $display->display_label, "hostname" => $display->hostname, "ip_address" => $display->ip_address, "display_url" => $display->display_url, "group_name" => $display->group_name, "group_order" => (int)$display->group_order, "monitor_size" => $display->monitor_size, "hdmi_port" => (int)$display->hdmi_port, "agent_port" => (int)$display->agent_port, "custom_style" => $display->custom_style, ]; } foreach ($grouped as &$group) { usort($group, fn($a, $b) => $a['group_order'] <=> $b['group_order']); } return $grouped; } protected function createDisplayApi(): array|bool { $monitorSize = $this->request->monitor_size ?? '27'; if (!in_array($monitorSize, ['27', '42', '55', '65'])) $monitorSize = '27'; $data = [ 'display_label' => $this->request->display_label ?? '', 'hostname' => $this->request->hostname ?? '', 'ip_address' => $this->request->ip_address ?? '', 'display_url' => $this->request->display_url ?? '', 'group_name' => $this->request->group_name ?? '', 'group_order' => (int)($this->request->group_order ?? 0), 'monitor_size' => $monitorSize, 'hdmi_port' => (int)($this->request->hdmi_port ?? 0), 'agent_port' => (int)($this->request->agent_port ?? 5000), 'custom_style' => $this->request->custom_style ?? null, ]; if (empty($data['display_label']) || empty($data['ip_address']) || empty($data['group_name'])) { return false; } $display = RaspberryDisplayModel::create($data); $display->create_by = $this->me->id; $display->create = time(); RaspberryDisplayModel::save($display); return ['id' => $display->id]; } protected function updateDisplayApi(): bool { $display = RaspberryDisplayModel::get((int)$this->request->id); if (!$display) return false; foreach (['display_label', 'hostname', 'ip_address', 'display_url', 'group_name', 'group_order', 'monitor_size', 'hdmi_port', 'agent_port', 'custom_style'] as $field) { if (isset($this->request->$field)) $display->$field = $this->request->$field; } $display->edit_by = $this->me->id; $display->edit = time(); RaspberryDisplayModel::save($display); return true; } protected function updateOrderApi(): bool { if (!is_array($this->request->orders)) return false; foreach ($this->request->orders as $order) { $display = RaspberryDisplayModel::get((int)$order['id']); if ($display) { $display->group_name = $order['group_name'] ?? $display->group_name; $display->group_order = (int)($order['group_order'] ?? 0); $display->edit_by = $this->me->id; $display->edit = time(); RaspberryDisplayModel::save($display); } } return true; } protected function discoverPiApi(): array|bool { $ip = $this->request->ip_address ?? ''; if (empty($ip)) return false; $status = (new NocDisplayAgent($ip, (int)($this->request->agent_port ?? 5000)))->status(); if (!$status['success']) { return ['online' => false, 'error' => $status['error'] ?? 'Failed to connect']; } return [ 'online' => true, 'hostname' => $status['hostname'] ?? '', 'displays' => $status['displays'] ?? [], 'temperature_c' => $status['temperature_c'] ?? null, 'cpu_percent' => $status['cpu_percent'] ?? null, 'memory' => $status['memory'] ?? null, ]; } protected function getStatusApi(): array|bool { $display = RaspberryDisplayModel::get((int)$this->request->id); if (!$display) return false; return NocDisplayAgent::fromDisplay(['ip_address' => $display->ip_address, 'agent_port' => $display->agent_port])->status(); } protected function getBatchStatusApi(): array { $seen = []; $results = []; foreach (RaspberryDisplayModel::getAll() as $display) { $key = "{$display->ip_address}:{$display->agent_port}"; if (isset($seen[$key])) continue; $seen[$key] = true; $results[$display->ip_address] = NocDisplayAgent::fromDisplay(['ip_address' => $display->ip_address, 'agent_port' => $display->agent_port])->status(); } return $results; } protected function setUrlApi(): array|bool { $display = RaspberryDisplayModel::get((int)$this->request->id); if (!$display) return false; $result = NocDisplayAgent::fromDisplay(['ip_address' => $display->ip_address, 'agent_port' => $display->agent_port]) ->setUrl((int)$display->hdmi_port, $this->request->url ?? ''); if ($result['success'] ?? false) { $display->display_url = $this->request->url ?? ''; $display->edit_by = $this->me->id; $display->edit = time(); RaspberryDisplayModel::save($display); } return $result; } protected function refreshDisplayApi(): array|bool { $display = RaspberryDisplayModel::get((int)$this->request->id); if (!$display) return false; return NocDisplayAgent::fromDisplay(['ip_address' => $display->ip_address, 'agent_port' => $display->agent_port])->refresh((int)$display->hdmi_port); } protected function cecPowerApi(): array|bool { $display = RaspberryDisplayModel::get((int)$this->request->id); if (!$display) return false; $agent = NocDisplayAgent::fromDisplay(['ip_address' => $display->ip_address, 'agent_port' => $display->agent_port]); return ($this->request->state ?? 'on') === 'on' ? $agent->cecOn((int)$display->hdmi_port) : $agent->cecOff((int)$display->hdmi_port); } protected function rebootPiApi(): array|bool { $display = RaspberryDisplayModel::get((int)$this->request->id); if (!$display) return false; return NocDisplayAgent::fromDisplay(['ip_address' => $display->ip_address, 'agent_port' => $display->agent_port])->reboot(); } protected function refreshAllApi(): array { $results = []; foreach (RaspberryDisplayModel::getAll() as $display) { $results[$display->id] = NocDisplayAgent::fromDisplay(['ip_address' => $display->ip_address, 'agent_port' => $display->agent_port])->refresh((int)$display->hdmi_port); } return $results; } protected function powerAllApi(): array { $state = $this->request->state ?? 'on'; $results = []; foreach (RaspberryDisplayModel::getAll() as $display) { $agent = NocDisplayAgent::fromDisplay(['ip_address' => $display->ip_address, 'agent_port' => $display->agent_port]); $results[$display->id] = $state === 'on' ? $agent->cecOn((int)$display->hdmi_port) : $agent->cecOff((int)$display->hdmi_port); } return $results; } protected function rebootAllApi(): array { $seen = []; $results = []; foreach (RaspberryDisplayModel::getAll() as $display) { $key = "{$display->ip_address}:{$display->agent_port}"; if (isset($seen[$key])) continue; $seen[$key] = true; $results[$display->ip_address] = NocDisplayAgent::fromDisplay(['ip_address' => $display->ip_address, 'agent_port' => $display->agent_port])->reboot(); } return $results; } protected function indexAction(): void { if (!$this->me->is("employee")) { $this->redirect("dashboard"); return; } $this->layout()->set("vueViewName", "RaspberryDisplay"); $this->layout()->set("JSGlobals", [ "BASE_URL" => self::getUrl("RaspberryDisplay"), "DASHBOARD_URL" => self::getUrl("Dashboard"), "MFAPPNAME" => MFAPPNAME_SLUG, "PAGE_TITLE" => "NOC Display Verwaltung", "PATH" => [ ["text" => MFAPPNAME_SLUG, "href" => self::getUrl("Dashboard")], ["text" => "NOC Display Verwaltung", "href" => self::getUrl("RaspberryDisplay")] ] ]); $this->layout()->set("additionalCSS", ["css/views/RaspberryDisplay.css"]); $this->layout()->setTemplate("VueViews/Vue3"); } }