getAccessPoints(); } catch (\Throwable $e) { $this->error('Failed to fetch APs: ' . $e->getMessage()); return self::FAILURE; } // ── 1. Store snapshot ───────────────────────────────────────────── $now = now(); $rows = []; foreach ($aps as $ap) { $rows[] = [ 'ap_mac' => $ap['mac'], 'ap_name' => $ap['name'] ?? $ap['model'] ?? null, 'num_sta' => $ap['num_sta'] ?? 0, 'rx_bytes' => $ap['rx_bytes'] ?? 0, 'tx_bytes' => $ap['tx_bytes'] ?? 0, 'tx_retries' => $ap['stat']['ap']['tx_retries'] ?? 0, 'tx_dropped' => $ap['stat']['ap']['tx_dropped'] ?? 0, 'rx_dropped' => $ap['stat']['ap']['rx_dropped'] ?? 0, 'tx_errors' => $ap['stat']['ap']['tx_errors'] ?? 0, 'rx_errors' => $ap['stat']['ap']['rx_errors'] ?? 0, 'satisfaction' => ($ap['satisfaction'] ?? -1) >= 0 ? $ap['satisfaction'] : null, 'cu_2g' => $this->getRadioStat($ap, 'ng'), 'cu_5g' => $this->getRadioStat($ap, 'na'), 'cu_6g' => $this->getRadioStat($ap, 'a6'), 'captured_at' => $now, ]; } if (! empty($rows)) { ApSnapshot::insert($rows); } // ── 1b. Store per-client snapshot ───────────────────────────────── try { $clients = $unifi->getActiveClients(); $clientRows = []; foreach ($clients as $c) { if (empty($c['mac'])) continue; $clientRows[] = [ 'mac' => strtolower($c['mac']), 'name' => $c['hostname'] ?? $c['name'] ?? null, 'dev_cat' => $c['dev_cat'] ?? null, 'os_name' => $c['os_name'] ?? null, 'is_wired' => (bool) ($c['is_wired'] ?? false), 'rx_bytes' => $c['rx_bytes'] ?? 0, 'tx_bytes' => $c['tx_bytes'] ?? 0, 'satisfaction' => ($c['satisfaction'] ?? -1) >= 0 ? $c['satisfaction'] : null, 'signal' => isset($c['signal']) ? (int) $c['signal'] : null, 'captured_at' => $now, ]; } if (! empty($clientRows)) { ClientSnapshot::insert($clientRows); } } catch (\Throwable $e) { $this->warn('Client snapshot failed: ' . $e->getMessage()); } // ── 2. Check webhook alerts with the same data ──────────────────── $fired = $webhooks->checkAll($unifi); if ($fired > 0) { $this->info("Fired {$fired} webhook(s)."); } return self::SUCCESS; } private function getRadioStat(array $ap, string $radio): ?int { foreach ($ap['radio_table_stats'] ?? [] as $stat) { if (($stat['radio'] ?? '') === $radio && isset($stat['cu_total'])) { return (int) $stat['cu_total']; } } return null; } }