getDevices())->map(function ($d) { // radio_table_stats has actual live channel + per-radio client counts + rates $radioStats = collect($d['radio_table_stats'] ?? [])->keyBy('name'); // Device-level throughput: prefer device field, fall back to sum of radio stats $txRate = ($d['tx_bytes-r'] ?? 0) ?: $radioStats->sum(fn ($r) => $r['tx_bytes-r'] ?? 0); $rxRate = ($d['rx_bytes-r'] ?? 0) ?: $radioStats->sum(fn ($r) => $r['rx_bytes-r'] ?? 0); return [ 'mac' => $d['mac'], 'name' => $d['name'] ?? $d['model'] ?? 'Unknown', 'model' => $d['model'] ?? '', 'type' => $d['type'] ?? '', 'ip' => $d['ip'] ?? '', 'version' => $d['version'] ?? '', 'state' => $d['state'] ?? 0, 'adopted' => $d['adopted'] ?? false, 'upgradable' => $d['upgradable'] ?? false, 'uptime' => $d['uptime'] ?? 0, 'num_sta' => $d['num_sta'] ?? 0, 'tx_bytes' => $d['tx_bytes'] ?? 0, 'rx_bytes' => $d['rx_bytes'] ?? 0, 'tx_rate' => $txRate, 'rx_rate' => $rxRate, 'cpu' => $d['system-stats']['cpu'] ?? null, 'mem' => $d['system-stats']['mem'] ?? null, 'satisfaction' => $d['satisfaction'] ?? null, // Use radio_table_stats for actual channel (not 'auto' from config), // per-radio client count, and per-radio rates. 'channels' => collect($d['radio_table'] ?? [])->map(function ($r) use ($radioStats) { $stats = $radioStats->get($r['name'] ?? ''); // stats['channel'] is the real channel in use; 0 = not broadcasting $channel = $stats ? (($stats['channel'] ?? 0) ?: null) : null; return [ 'radio' => $r['radio'] ?? '', 'channel' => $channel, 'num_sta' => $stats['num_sta'] ?? 0, 'tx_rate' => $stats ? ($stats['tx_bytes-r'] ?? 0) : 0, 'rx_rate' => $stats ? ($stats['rx_bytes-r'] ?? 0) : 0, ]; })->values(), ]; })->values(); return Inertia::render('Unifi/Devices', ['devices' => $devices]); } catch (\Throwable $e) { return Inertia::render('Unifi/Devices', ['devices' => [], 'error' => $e->getMessage()]); } } public function reboot(Request $request, UnifiApiClient $unifi) { $request->validate(['mac' => 'required|string|regex:/^([0-9a-f]{2}:){5}[0-9a-f]{2}$/i']); try { // Suppress offline/online webhook alerts for planned reboots (15-minute window) Cache::put('unifi:planned_reboot:' . strtolower($request->mac), true, now()->addMinutes(15)); $unifi->rebootDevice($request->mac); return back()->with('success', 'Reboot command sent.'); } catch (\Throwable $e) { return back()->withErrors(['error' => $e->getMessage()]); } } }