getLastChangeTs($uuid), 'now' => round(microtime(true) * 1000), ]; } elseif ($get === "machines") { $locationIds = LocationInfo::getLocationsOr404($uuid); $output = array(); InfoPanel::appendMachineData($output, $locationIds, true); $output = array_values($output); } elseif ($get === "config") { $type = InfoPanel::getConfig($uuid, $output); if ($type === null) { http_response_code(404); die('Panel not found'); } } elseif ($get === "pcstates") { $locationIds = LocationInfo::getLocationsOr404($uuid); $output = getPcStates($locationIds, $uuid); } elseif ($get === "locationtree") { $locationIds = LocationInfo::getLocationsOr404($uuid); $output = Location::getTree(...$locationIds); } elseif ($get === "calendar") { $locationIds = LocationInfo::getLocationsOr404($uuid); $output = LocationInfo::getCalendar($locationIds, time() + 3); } elseif ($get === "manifest") { $output = generateManifest($uuid); } elseif ($get === 'list') { $output = generatePublicPanelList(); } if ($output !== null) { Header('Content-Type: application/json; charset=utf-8'); echo json_encode($output); } else { http_response_code(404); echo 'Unknown get option'; } } /** * Get last config modification timestamp for given panel. * This is incomplete however, as it wouldn't react to the * linked room plan being edited, or added/removed PCs * etc. So the advice would simply be "if you want the * panel to reload automatically, hit the edit button * and click save". Might even add a shortcut * reload-button to the list of panels at some point. * * @param string $paneluuid panels uuid * @return int UNIX_TIMESTAMP */ function getLastChangeTs(string $paneluuid): int { $panel = Database::queryFirst('SELECT lastchange, locationids FROM locationinfo_panel WHERE paneluuid = :paneluuid', compact('paneluuid')); if ($panel === false) { http_response_code(404); die('Panel not found'); } $lastChange = array((int)$panel['lastchange']); if (!empty($panel['locationids'])) { $res = Database::simpleQuery('SELECT lastchange FROM locationinfo_locationconfig WHERE locationid IN (:locs)', array('locs' => explode(',', $panel['locationids']))); while (($lc = $res->fetchColumn()) !== false) { $lastChange[] = (int)$lc; } } return max($lastChange); } /** * Gets the pc states of the given locations. * * @param int[] $idList list of the location ids. * @return array aggregated PC states */ function getPcStates(array $idList, string $paneluuid): array { $pcStates = array(); foreach ($idList as $id) { $pcStates[$id] = array( 'id' => $id, 'idle' => 0, 'occupied' => 0, 'offline' => 0, 'broken' => 0, 'standby' => 0, ); } $locationInfoList = array(); InfoPanel::appendMachineData($locationInfoList, $idList); $panel = Database::queryFirst('SELECT paneluuid, panelconfig FROM locationinfo_panel WHERE paneluuid = :paneluuid', compact('paneluuid')); $config = json_decode($panel['panelconfig'], true); foreach ($locationInfoList as $locationInfo) { $id = $locationInfo['id']; foreach ($locationInfo['machines'] as $pc) { $key = strtolower($pc['pcState']); if (isset($pcStates[$id][$key])) { if ($config['roomplanner']) { if (isset($pc['x']) && isset($pc['y'])) { $pcStates[$id][$key]++; } } else { $pcStates[$id][$key]++; } } } } return array_values($pcStates); } /** * Generates a web application manifest for a panel. * * @param string $uuid The UUID of the panel. * @return array The generated manifest file data. */ function generateManifest(string $uuid): array { $row = Database::queryFirst("SELECT panelname FROM locationinfo_panel WHERE paneluuid = :paneluuid", ['paneluuid' => $uuid]); if ($row === false) return ['error' => 'Not found']; $data = [ "name" => $row['panelname'], "short_name" => $row['panelname'], "start_url" => "/panel/$uuid", "display_override" => [ "fullscreen", "standalone", "tabbed", "minimal-ui" ], "display" => "fullscreen", "icons" => [ [ "src" => "/panel/style/icon.svg", "sizes" => "any", "type" => "image/svg+xml" ] ], ]; foreach (glob('style/icon*.png', GLOB_NOSORT) as $file) { if (!preg_match('/icon(\d+)\.png$/', $file, $m)) continue; $data['icons'][] = [ "src" => "/panel/$file", "sizes" => "${m[1]}x${m[1]}", "type" => "image/png", ]; } return $data; } function generatePublicPanelList(): array { $base = Util::shouldRedirectDomain(); if ($base !== null) { $base = 'https://' . $base; } else { $base = ($_SERVER['HTTPS'] ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST']; } $result = [ 'server_name' => 'To be filled by O.E.M.', 'panels' => [], ]; $res = Database::simpleQuery("SELECT paneluuid, panelname FROM locationinfo_panel WHERE ispublic = 1"); foreach ($res as $row) { $result['panels'][] = [ 'title' => $row['panelname'], 'url' => $base . '/panel/' . $row['paneluuid'], ]; } return $result; }