0 is checked before the percentage, so a failed meminfo read yields 0 // rather than a division by zero that would fatal on every tab at once. // // Every count is cast on the way out. // (int) on the cached stream and transcode counts with ?? 0 defaults, so a cache file // written by an older schema cannot put a null or a string into the header payload. // // Media failures are already contained upstream — vv_media_sessions() time-boxes each // request at 3s and returns an empty session list on any failure, so an unreachable Emby // costs this poll nothing beyond that timeout, once every 30 seconds. // // REQUEST // GET, no parameters // // RESPONSE // {"cpu_pct","ram_pct","ram_used_mb","ram_total_mb","fallback","partner_enabled", // "peers":[…],"stream_count","transcode_count"} // // DEPENDS ON // include/common.php vv_cpu_per_core(), vv_system_resources() // (loaded transitively through include/monitor.php) // include/monitor.php vv_partner_state() // include/config.php vv_parse_kv_db(), vv_cache_read(), vv_cache_write(), STATE_DIR // include/media.php vv_media_sessions() // STATE_DIR fallback_state.db — written by Fallback/fallback.sh // ═══════════════════════════════════════════════════════════════════════════════════════════════ header('Content-Type: application/json'); require_once dirname(__DIR__) . '/include/monitor.php'; require_once dirname(__DIR__) . '/include/media.php'; // CPU% — shares /tmp/vv_cpu_stat.json with vv_cpu_per_core() so both read the same baseline $cpuPct = vv_cpu_per_core()['overall'] ?? 0; // RAM% $res = vv_system_resources(); $ramTotalMb = $res['ram_total_mb']; $ramUsedMb = $ramTotalMb - $res['ram_free_mb']; $ramPct = $ramTotalMb > 0 ? (int)round($ramUsedMb / $ramTotalMb * 100) : 0; // Fallback state (fast file read, no exec) $fbRaw = @file_get_contents(STATE_DIR . '/fallback_state.db') ?: ''; $fbData = vv_parse_kv_db($fbRaw); $fallbackState = $fbData['state'] ?? 'UNKNOWN'; // Partner $partner = vv_partner_state(); $peers = array_values(array_filter($partner['hosts'], fn($h) => !$h['is_me'])); // Media sessions — cached 30s so the HTTP calls don't hold up every snapshot poll $mediaCache = vv_cache_read('snap_media', 30); if (!$mediaCache) { $media = vv_media_sessions(); $mediaCache = [ 'stream_count' => count($media['sessions']), 'transcode_count' => count(array_filter($media['sessions'], fn($s) => !empty($s['is_tc']))), ]; vv_cache_write('snap_media', $mediaCache); } $streamCount = (int)($mediaCache['stream_count'] ?? 0); $transcodeCount = (int)($mediaCache['transcode_count'] ?? 0); echo json_encode([ 'cpu_pct' => $cpuPct, 'ram_pct' => $ramPct, 'ram_used_mb' => $ramUsedMb, 'ram_total_mb' => $ramTotalMb, 'fallback' => $fallbackState, 'partner_enabled' => $partner['enabled'], 'peers' => $peers, 'stream_count' => $streamCount, 'transcode_count' => $transcodeCount, ]);