Files
thetool/application/RaspberryDisplay/RaspberryDisplayController.php
2026-02-03 15:38:55 +01:00

247 lines
10 KiB
PHP

<?php
class RaspberryDisplayController extends mfBaseController {
protected function init(): void {
$me = new User();
$me->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 {
$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' => $this->request->monitor_size ?? '27',
'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 Manager",
"PATH" => [
["text" => MFAPPNAME_SLUG, "href" => self::getUrl("Dashboard")],
["text" => "NOC Display Manager", "href" => self::getUrl("RaspberryDisplay")]
]
]);
$this->layout()->set("additionalCSS", ["css/views/RaspberryDisplay.css"]);
$this->layout()->setTemplate("VueViews/Vue3");
}
}