Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
200 changes: 197 additions & 3 deletions src/reachy_mini/daemon/app/dashboard/static/js/wifi.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

const getStatus = async () => {
return await fetch('/wifi/status')
.then(response => response.json())
Expand Down Expand Up @@ -121,6 +120,9 @@ const handleStatus = (status) => {
});
}

const connectedDiv = document.getElementById('wifi-connected');
connectedDiv.classList.add('hidden');

if (mode == 'hotspot') {
statusDiv.innerText = 'Hotspot mode active. 🔌';

Expand All @@ -130,6 +132,9 @@ const handleStatus = (status) => {
}

statusDiv.innerText = `Connected to WiFi (SSID: ${status.connected_network}). 📶`;
document.getElementById('wifi-network').innerText = status.connected_network;
document.getElementById('wifi-ip').innerText = status.ip_address || '';
connectedDiv.classList.remove('hidden');

} else if (mode == 'disconnected') {
statusDiv.innerText = 'WiFi disconnected. ❌';
Expand Down Expand Up @@ -158,6 +163,9 @@ const cleanAndRefresh = async () => {
const statusDiv = document.getElementById('wifi-status');
statusDiv.innerText = 'Checking WiFi configuration...';

const connectedDiv = document.getElementById('wifi-connected');
connectedDiv.classList.add('hidden');

const knownNetworksDiv = document.getElementById('known-networks');
knownNetworksDiv.classList.add('hidden');

Expand All @@ -170,7 +178,193 @@ const cleanAndRefresh = async () => {
addWifi.classList.remove('hidden');
};

// --- Secondary WiFi (wlan1) — mirrors primary pattern ---

const getStatus2 = async () => {
return await fetch('/wifi/status2')
.then(response => response.json())
.catch(error => {
console.error('Error fetching secondary WiFi status:', error);
return { exists: false, connected: false, ssid: null, ip_address: null, known_networks: [], busy: false };
});
};

const refreshStatus2 = async () => {
const status = await getStatus2();
handleStatus2(status);
};

const scanAndListWifiNetworks2 = async () => {
await fetch('/wifi/scan2', { method: 'POST' })
.then(response => response.json())
.then(data => {
const ssidSelect = document.getElementById('ssid2');
ssidSelect.innerHTML = '<option value="" disabled selected>Select your WiFi network</option>';
data.forEach(ssid => {
const option = document.createElement('option');
option.value = ssid;
option.textContent = ssid;
ssidSelect.appendChild(option);
});
})
.catch(() => {
const ssidSelect = document.getElementById('ssid2');
const option = document.createElement('option');
option.value = "";
option.textContent = "Unable to load networks";
ssidSelect.appendChild(option);
});
};

const connectToWifi2 = (_) => {
const ssid = document.getElementById('ssid2').value;
const password = document.getElementById('password2').value;

if (!ssid) {
alert('Please enter an SSID.');
return;
}

fetch(`/wifi/connect2?ssid=${encodeURIComponent(ssid)}&password=${encodeURIComponent(password)}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
})
.then(response => {
if (!response.ok) {
return response.json().then(errData => {
throw new Error(errData.detail || 'Failed to connect to WiFi');
});
}

// Clear the form fields
document.getElementById('ssid2').value = '';
document.getElementById('password2').value = '';

return response.json();
})
.then(data => {
handleStatus2({ exists: true, connected: false, ssid: null, ip_address: null, known_networks: [], busy: true });
})
.catch(error => {
console.error('Error connecting to secondary WiFi:', error);
alert(`Error connecting to WiFi: ${error.message}`);
});
return false; // Prevent form submission
};

const handleStatus2 = (status) => {
const statusDiv = document.getElementById('wifi2-status');
const connectedDiv = document.getElementById('wifi2-connected');
const noAdapterDiv = document.getElementById('wifi2-no-adapter');

const knownNetworksDiv = document.getElementById('known-networks2');
const knownNetworksList = document.getElementById('known-networks-list2');

connectedDiv.classList.add('hidden');
noAdapterDiv.classList.add('hidden');

// Known networks — same rendering as primary
knownNetworksList.innerHTML = '';
if (status.known_networks !== undefined && Array.isArray(status.known_networks) && status.known_networks.length > 0) {
knownNetworksDiv.classList.remove('hidden');
status.known_networks.forEach((network) => {
const li = document.createElement('li');
li.classList = 'flex flex-row items-center mb-1 gap-4 justify-left';

const nameSpan = document.createElement('span');
nameSpan.innerText = network;
li.appendChild(nameSpan);

knownNetworksList.appendChild(li);
});
} else {
knownNetworksDiv.classList.add('hidden');
}

if (status.busy) {
statusDiv.innerText = 'Changing your WiFi configuration... Please wait ⏳';
return;
}

if (!status.exists) {
statusDiv.innerText = 'WiFi adapter not available. ❌';
document.getElementById('add-wifi2').classList.add('hidden');
noAdapterDiv.classList.remove('hidden');
return;
}

if (status.connected) {
statusDiv.innerText = `Connected to WiFi (SSID: ${status.ssid}). 📶`;
document.getElementById('wifi2-network').innerText = status.ssid;
document.getElementById('wifi2-ip').innerText = status.ip_address || '';
connectedDiv.classList.remove('hidden');
} else {
statusDiv.innerText = 'WiFi disconnected. ❌';
}

document.getElementById('add-wifi2').classList.remove('hidden');
};

const disconnectWifi2 = () => {
fetch('/wifi/disconnect2', { method: 'POST' })
.then(response => {
if (!response.ok) {
return response.json().then(errData => {
throw new Error(errData.detail || 'Failed to disconnect');
});
}
handleStatus2({ exists: true, connected: false, ssid: null, ip_address: null, known_networks: [], busy: true });
})
.catch(error => {
console.error('Error disconnecting secondary WiFi:', error);
alert(`Error disconnecting: ${error.message}`);
});
};

const createWlan1 = () => {
fetch('/wifi/create_interface', { method: 'POST' })
.then(response => {
if (!response.ok) {
return response.json().then(errData => {
throw new Error(errData.detail || 'Failed to create interface');
});
}
cleanAndRefresh2();
})
.catch(error => {
console.error('Error creating wlan1:', error);
alert(`Error creating interface: ${error.message}`);
});
};

const cleanAndRefresh2 = async () => {
const statusDiv = document.getElementById('wifi2-status');
statusDiv.innerText = 'Checking WiFi configuration...';

const knownNetworksDiv = document.getElementById('known-networks2');
knownNetworksDiv.classList.add('hidden');

const connectedDiv = document.getElementById('wifi2-connected');
connectedDiv.classList.add('hidden');

const addWifi = document.getElementById('add-wifi2');
addWifi.classList.add('hidden');

await scanAndListWifiNetworks2();
await refreshStatus2();

addWifi.classList.remove('hidden');
};

// --- Initialization ---

window.addEventListener('load', async () => {
await cleanAndRefresh();
setInterval(refreshStatus, 1000);
});
await cleanAndRefresh2();
setInterval(() => {
refreshStatus();
refreshStatus2();
}, 1000);
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@

<div class="flex flex-col p-4 gap-4">
<div id="wifi-status" class="wifi-status-info w-full">Checking WiFi configuration...</div>
<div id="wifi-connected" class="hidden wifi-status-info w-full">
Network: <span id="wifi-network" class="font-medium"></span>
<div>IP: <span id="wifi-ip"></span></div>
</div>
<div id="known-networks" class="wifi-status-info hidden w-full">
Known Networks:
<ul id="known-networks-list" class="list-disc list-inside px-4"></ul>
Expand Down Expand Up @@ -43,4 +47,69 @@
</div>
</div>
</div>
</div>
</div>

<div class="app-section mt-6">
<div class="flex flex-row items-center gap-2">
<div class="app-section-title">Secondary WiFi (wlan1)</div>
<button id="refresh-wifi2" title="Refresh" class="p-1 rounded hover:bg-gray-200 focus:outline-none"
onclick="cleanAndRefresh2()">
🔄
</button>
</div>

<div class="flex flex-col p-4 gap-4">
<div id="wifi2-status" class="wifi-status-info w-full">Checking WiFi configuration...</div>
<div id="wifi2-connected" class="hidden wifi-status-info w-full">
Network: <span id="wifi2-network" class="font-medium"></span>
<div>IP: <span id="wifi2-ip"></span></div>
<div class="mt-2">
<button onclick="disconnectWifi2()"
class="text-white bg-red-600 hover:bg-red-700 focus:ring-4 focus:outline-none focus:ring-red-300 font-medium rounded-lg text-sm px-4 py-2">
Disconnect
</button>
</div>
</div>
<div id="known-networks2" class="wifi-status-info hidden w-full">
Known Networks:
<ul id="known-networks-list2" class="list-disc list-inside px-4"></ul>
</div>
</div>
<div id="add-wifi2" class="hidden">
<div class="py-4 flex flex-col max-w-md">
<div class="app-section-title mb-2">Add new WiFi</div>

<div class="flex flex-row p-4">
<form id="wifi-form2" class="max-w-md" onsubmit="return false;">
<div class="mb-4">
<label for="ssid2" class="block mb-2 text-sm">SSID</label>
<select id="ssid2" name="ssid2"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
required>
<option value="" disabled selected>Select your WiFi network</option>
</select>
</div>
<div class="mb-4">
<label for="password2" class="block mb-2 text-sm">Password</label>
<input type="password" id="password2" name="password2"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
required>
</div>
<div class="">
<input type="button" onclick="connectToWifi2(event)" target="_blank" formtarget="_blank"
value="Connect"
class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
</div>
</form>
</div>
</div>
</div>

<div id="wifi2-no-adapter" class="hidden px-4 pb-4">
<p class="text-sm text-gray-500 mb-2">wlan1 interface not found.</p>
<button onclick="createWlan1()"
class="text-white bg-green-600 hover:bg-green-700 focus:ring-4 focus:outline-none focus:ring-green-300 font-medium rounded-lg text-sm px-4 py-2">
Create Interface
</button>
</div>
</div>
Loading