feat: initial commit — UniFi snap-in package
Full UniFi dashboard snap-in including: - WiFi/client/device stats with time-series snapshots - Client Dashboard with traffic, satisfaction, signal, download charts - Webhook alerting with debounced offline/online detection - AP snapshot collection, client snapshot collection - Device classification (type and OS) from OUI/hostname heuristics - Webhook cooldown, templates, and multi-platform delivery Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
126
src/Http/Controllers/WifiController.php
Normal file
126
src/Http/Controllers/WifiController.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
namespace Dashboard\Unifi\Http\Controllers;
|
||||
|
||||
use App\Models\Setting;
|
||||
use Dashboard\Unifi\Services\UnifiApiClient;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Inertia\Inertia;
|
||||
|
||||
class WifiController extends Controller
|
||||
{
|
||||
public function index(UnifiApiClient $unifi)
|
||||
{
|
||||
try {
|
||||
$wlans = collect($unifi->getWlans())->map(fn ($w) => [
|
||||
'id' => $w['_id'],
|
||||
'name' => $w['name'],
|
||||
'enabled' => $w['enabled'] ?? true,
|
||||
'security' => $w['security'] ?? 'open',
|
||||
'wpa_mode' => $w['wpa_mode'] ?? '',
|
||||
'is_guest' => $w['is_guest'] ?? false,
|
||||
'vlan_enabled' => $w['vlan_enabled'] ?? false,
|
||||
'vlan' => $w['vlan'] ?? null,
|
||||
'hide_ssid' => $w['hide_ssid'] ?? false,
|
||||
'passphrase' => $w['x_passphrase'] ?? '',
|
||||
'band' => $this->detectBand($w),
|
||||
])->values();
|
||||
|
||||
// Load saved groups: { "Staff": ["id1", "id2"], ... }
|
||||
$raw = Setting::get('unifi.ssid_groups', '{}');
|
||||
$groups = json_decode($raw, true);
|
||||
if (! is_array($groups) || array_is_list($groups)) $groups = [];
|
||||
// Force object cast so Vue gets {} not []
|
||||
$groups = (object) $groups;
|
||||
|
||||
return Inertia::render('Unifi/Wifi', [
|
||||
'wlans' => $wlans,
|
||||
'groups' => $groups,
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
return Inertia::render('Unifi/Wifi', ['wlans' => [], 'groups' => [], 'error' => $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
public function update(Request $request, string $wlanId, UnifiApiClient $unifi)
|
||||
{
|
||||
$data = $request->validate([
|
||||
'name' => 'sometimes|string|max:255',
|
||||
'enabled' => 'sometimes|boolean',
|
||||
'x_passphrase' => 'sometimes|string|min:8|max:63',
|
||||
'hide_ssid' => 'sometimes|boolean',
|
||||
]);
|
||||
|
||||
try {
|
||||
// If this WLAN is in a group, apply the same change to all grouped WLANs
|
||||
$groups = json_decode(Setting::get('unifi.ssid_groups', '{}'), true) ?: [];
|
||||
$groupedIds = collect($groups)->first(fn ($ids) => in_array($wlanId, $ids));
|
||||
|
||||
if ($groupedIds) {
|
||||
foreach ($groupedIds as $id) {
|
||||
$unifi->updateWlan($id, $data);
|
||||
}
|
||||
} else {
|
||||
$unifi->updateWlan($wlanId, $data);
|
||||
}
|
||||
|
||||
return back()->with('success', 'WiFi network updated.');
|
||||
} catch (\Throwable $e) {
|
||||
return back()->withErrors(['error' => $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
public function toggle(Request $request, string $wlanId, UnifiApiClient $unifi)
|
||||
{
|
||||
$request->validate(['enabled' => 'required|boolean']);
|
||||
|
||||
try {
|
||||
$groups = json_decode(Setting::get('unifi.ssid_groups', '{}'), true) ?: [];
|
||||
$groupedIds = collect($groups)->first(fn ($ids) => in_array($wlanId, $ids));
|
||||
$enabled = $request->boolean('enabled');
|
||||
|
||||
if ($groupedIds) {
|
||||
foreach ($groupedIds as $id) {
|
||||
$unifi->updateWlan($id, ['enabled' => $enabled]);
|
||||
}
|
||||
} else {
|
||||
$unifi->updateWlan($wlanId, ['enabled' => $enabled]);
|
||||
}
|
||||
|
||||
return back()->with('success', 'WiFi network ' . ($enabled ? 'enabled' : 'disabled') . '.');
|
||||
} catch (\Throwable $e) {
|
||||
return back()->withErrors(['error' => $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Group/ungroup SSIDs. Groups are stored as { "GroupName": ["wlan_id_1", "wlan_id_2"] }
|
||||
*/
|
||||
public function saveGroups(Request $request)
|
||||
{
|
||||
$request->validate(['groups' => 'present']);
|
||||
$groups = $request->input('groups', []);
|
||||
if (is_array($groups) && array_is_list($groups)) $groups = (object) [];
|
||||
Setting::set('unifi.ssid_groups', json_encode($groups ?: (object) []));
|
||||
return back()->with('success', 'SSID groups saved.');
|
||||
}
|
||||
|
||||
private function detectBand(array $w): string
|
||||
{
|
||||
// UniFi stores band info in wlan_band or in the radio settings
|
||||
$band = $w['wlan_band'] ?? null;
|
||||
if ($band === 'ng' || $band === '2g') return '2.4 GHz';
|
||||
if ($band === 'na' || $band === '5g') return '5 GHz';
|
||||
if ($band === 'a6' || $band === '6g' || $band === '6e') return '6 GHz';
|
||||
if ($band === 'both' || $band === null) return 'All bands';
|
||||
|
||||
// Try to detect from SSID name as fallback
|
||||
$name = strtolower($w['name'] ?? '');
|
||||
if (preg_match('/2\.?4\s*g/i', $name)) return '2.4 GHz';
|
||||
if (preg_match('/5\s*g/i', $name)) return '5 GHz';
|
||||
if (preg_match('/6\s*g/i', $name)) return '6 GHz';
|
||||
|
||||
return 'All bands';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user