v1.4.5 — Page WiFi: oublier réseau + badge hotspot sidebar + refonte UI

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
PaulVua
2026-03-17 17:28:46 +01:00
parent 5a2b3bb19d
commit 6e17f39a2c
7 changed files with 549 additions and 210 deletions

View File

@@ -1 +1 @@
1.4.3 1.4.5

View File

@@ -1,5 +1,28 @@
{ {
"versions": [ "versions": [
{
"version": "1.4.5",
"date": "2026-03-17",
"changes": {
"features": [
"Page WiFi: bouton Oublier le reseau pour passer en mode hotspot sans reboot",
"Sidebar: badge Mode Hotspot visible sur toutes les pages quand le capteur est en hotspot (lien vers page WiFi)"
],
"improvements": [
"Page WiFi: refonte UI avec cards contextuelles (infos connexion si connecte, scan si hotspot)",
"Page WiFi: affichage detaille de la connexion WiFi (SSID, signal, IP, passerelle, hostname, frequence, securite)",
"Page WiFi: chargement automatique des infos au chargement (plus de bouton Get Data)",
"Page WiFi: scan WiFi masque quand deja connecte (inutile)",
"Page WiFi: migration de config.json vers get_config_sqlite (coherent avec les autres pages)",
"topbar-logo.js: gestion centralisee du nom capteur sidebar et badge hotspot pour toutes les pages"
],
"fixes": [
"Correction VERSION 1.4.3 -> 1.4.4 (fichier VERSION non mis a jour lors du commit precedent)"
],
"compatibility": []
},
"notes": "Le bouton Oublier le reseau supprime la connexion WiFi sauvegardee et demarre le hotspot immediatement (pas de reboot necessaire). Le badge hotspot dans la sidebar permet de voir rapidement le mode reseau depuis n'importe quelle page."
},
{ {
"version": "1.4.4", "version": "1.4.4",
"date": "2026-03-16", "date": "2026-03-16",

42
forget_wifi.sh Normal file
View File

@@ -0,0 +1,42 @@
#!/bin/bash
echo "-------"
echo "Start forget WiFi shell script at $(date)"
# Get deviceName from database for hotspot SSID
DEVICE_NAME=$(sqlite3 /var/www/nebuleair_pro_4g/sqlite/sensors.db "SELECT value FROM config_table WHERE key='deviceName'")
echo "Device Name: $DEVICE_NAME"
# Get current active WiFi connection name
ACTIVE_WIFI=$(nmcli -t -f NAME,TYPE,DEVICE connection show --active | grep ':802-11-wireless:wlan0' | cut -d: -f1)
if [ -z "$ACTIVE_WIFI" ]; then
echo "No active WiFi connection found on wlan0"
echo "End forget WiFi shell script"
echo "-------"
exit 1
fi
echo "Forgetting WiFi connection: $ACTIVE_WIFI"
# Delete (forget) the saved connection
sudo nmcli connection delete "$ACTIVE_WIFI"
if [ $? -eq 0 ]; then
echo "Connection '$ACTIVE_WIFI' deleted successfully"
else
echo "Failed to delete connection '$ACTIVE_WIFI'"
fi
sleep 2
# Start hotspot
echo "Starting hotspot with SSID: $DEVICE_NAME"
sudo nmcli device wifi hotspot ifname wlan0 ssid "$DEVICE_NAME" password nebuleaircfg
# Update SQLite to reflect hotspot mode
sqlite3 /var/www/nebuleair_pro_4g/sqlite/sensors.db "UPDATE config_table SET value='hotspot' WHERE key='WIFI_status'"
echo "Updated database: WIFI_status = hotspot"
echo "Hotspot started with SSID: $DEVICE_NAME"
echo "End forget WiFi shell script"
echo "-------"

View File

@@ -3,6 +3,8 @@
* Global configuration handler for UI elements * Global configuration handler for UI elements
* - Updates Topbar Logo based on device type * - Updates Topbar Logo based on device type
* - Shows/Hides "Screen" sidebar tab based on device type * - Shows/Hides "Screen" sidebar tab based on device type
* - Updates sidebar device name
* - Shows hotspot badge in sidebar when in hotspot mode
*/ */
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
let config = null; let config = null;
@@ -42,17 +44,28 @@ document.addEventListener('DOMContentLoaded', () => {
if (navScreenElements.length > 0) { if (navScreenElements.length > 0) {
navScreenElements.forEach(navScreen => { navScreenElements.forEach(navScreen => {
if (isModuleAirPro) { if (isModuleAirPro) {
// Ensure it's visible (bootstrap nav-link usually block or flex)
if (navScreen.style.display === 'none') { if (navScreen.style.display === 'none') {
navScreen.style.display = 'flex'; navScreen.style.display = 'flex';
} }
} else { } else {
// Hide if not pro
if (navScreen.style.display !== 'none') { if (navScreen.style.display !== 'none') {
navScreen.style.display = 'none'; navScreen.style.display = 'none';
} }
} }
}); });
} }
// 3. Sidebar device name
if (config.deviceName) {
document.querySelectorAll('.sideBar_sensorName').forEach(el => {
el.textContent = config.deviceName;
});
document.title = config.deviceName;
}
// 4. Hotspot badge in sidebar
document.querySelectorAll('.sidebar-hotspot-badge').forEach(badge => {
badge.style.display = (config.WIFI_status === 'hotspot') ? '' : 'none';
});
} }
}); });

View File

@@ -1042,35 +1042,64 @@ if ($type == "sara_sendMessage") {
} }
if ($type == "internet") { if ($type == "internet") {
//eth0 // eth0
$command = 'nmcli -g GENERAL.STATE device show eth0'; $eth0_connStatus = str_replace("\n", "", shell_exec('nmcli -g GENERAL.STATE device show eth0 2>/dev/null'));
$eth0_connStatus = shell_exec($command); $eth0_IPAddr = str_replace("\n", "", shell_exec('nmcli -g IP4.ADDRESS device show eth0 2>/dev/null'));
$eth0_connStatus = str_replace("\n", "", $eth0_connStatus);
$command = 'nmcli -g IP4.ADDRESS device show eth0';
$eth0_IPAddr = shell_exec($command);
$eth0_IPAddr = str_replace("\n", "", $eth0_IPAddr);
//wlan0 // wlan0 basic
$command = 'nmcli -g GENERAL.STATE device show wlan0'; $wlan0_connStatus = str_replace("\n", "", shell_exec('nmcli -g GENERAL.STATE device show wlan0 2>/dev/null'));
$wlan0_connStatus = shell_exec($command); $wlan0_IPAddr = str_replace("\n", "", shell_exec('nmcli -g IP4.ADDRESS device show wlan0 2>/dev/null'));
$wlan0_connStatus = str_replace("\n", "", $wlan0_connStatus);
$command = 'nmcli -g IP4.ADDRESS device show wlan0';
$wlan0_IPAddr = shell_exec($command);
$wlan0_IPAddr = str_replace("\n", "", $wlan0_IPAddr);
$data= array( // wlan0 detailed info (connection name, signal, frequency, security, gateway, etc.)
$wlan0_connection = str_replace("\n", "", shell_exec("nmcli -t -f GENERAL.CONNECTION device show wlan0 2>/dev/null | cut -d: -f2"));
$wlan0_gateway = str_replace("\n", "", shell_exec('nmcli -g IP4.GATEWAY device show wlan0 2>/dev/null'));
// Get active WiFi details (signal, frequency, security) from nmcli
$wifi_signal = '';
$wifi_freq = '';
$wifi_security = '';
$wifi_ssid = '';
$wifi_output = shell_exec('nmcli -t -f ACTIVE,SSID,SIGNAL,FREQ,SECURITY device wifi list ifname wlan0 2>/dev/null');
if ($wifi_output) {
$lines = explode("\n", trim($wifi_output));
foreach ($lines as $line) {
// Active connection line starts with "yes:" (nmcli -t uses : separator)
if (strpos($line, 'yes:') === 0) {
// Format: yes:SSID:SIGNAL:FREQ:SECURITY
// Use explode with limit to handle SSIDs containing ':'
$parts = explode(':', $line);
if (count($parts) >= 5) {
$wifi_ssid = $parts[1];
$wifi_signal = $parts[2];
$wifi_freq = $parts[3];
$wifi_security = $parts[4];
}
break;
}
}
}
// Hostname
$hostname = trim(shell_exec('hostname 2>/dev/null'));
$data = array(
"ethernet" => array( "ethernet" => array(
"connection" => $eth0_connStatus, "connection" => $eth0_connStatus,
"IP" => $eth0_IPAddr "IP" => $eth0_IPAddr
), ),
"wifi" => array( "wifi" => array(
"connection" => $wlan0_connStatus, "connection" => $wlan0_connStatus,
"IP" => $wlan0_IPAddr "IP" => $wlan0_IPAddr,
"ssid" => $wifi_ssid ?: $wlan0_connection,
"signal" => $wifi_signal,
"frequency" => $wifi_freq,
"security" => $wifi_security,
"gateway" => $wlan0_gateway,
"hostname" => $hostname
) )
); );
$json_data = json_encode($data);
echo $json_data; echo json_encode($data);
} }
# IMPORTANT # IMPORTANT
@@ -1126,6 +1155,51 @@ if ($type == "wifi_connect") {
} }
if ($type == "wifi_forget") {
// Get device name from database
try {
$db = new PDO("sqlite:$database_path");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $db->prepare("SELECT value FROM config_table WHERE key = 'deviceName'");
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
$deviceName = $result ? $result['value'] : 'NebuleAir';
$db = null;
} catch (PDOException $e) {
$deviceName = 'NebuleAir';
}
// Launch forget script in background
$script_path = '/var/www/nebuleair_pro_4g/forget_wifi.sh';
$log_file = '/var/www/nebuleair_pro_4g/logs/app.log';
shell_exec("$script_path >> $log_file 2>&1 &");
header('Content-Type: application/json');
echo json_encode([
'success' => true,
'deviceName' => $deviceName,
'instructions' => [
'fr' => [
'title' => 'Réseau WiFi oublié',
'step1' => "Le capteur oublie le réseau WiFi actuel",
'step2' => "Le hotspot va démarrer automatiquement",
'step3' => "Connectez-vous au WiFi « $deviceName » (mot de passe : nebuleaircfg)",
'step4' => "Accédez au capteur via http://192.168.43.1/html/",
'warning' => "Le capteur ne se reconnectera plus automatiquement à ce réseau"
],
'en' => [
'title' => 'WiFi network forgotten',
'step1' => "The sensor is forgetting the current WiFi network",
'step2' => "The hotspot will start automatically",
'step3' => "Connect to WiFi « $deviceName » (password: nebuleaircfg)",
'step4' => "Access the sensor via http://192.168.43.1/html/",
'warning' => "The sensor will no longer auto-connect to this network"
]
]
]);
}
if ($type == "wifi_scan") { if ($type == "wifi_scan") {
// Perform live WiFi scan instead of reading stale CSV file // Perform live WiFi scan instead of reading stale CSV file

View File

@@ -92,7 +92,17 @@
<!-- New content at the bottom --> <!-- New content at the bottom -->
<div class="sidebar-footer text-center text-white"> <div class="sidebar-footer text-center text-white">
<hr> <hr>
<span class="sideBar_sensorName"> NebuleAir</span> <span class="sideBar_sensorName">NebuleAir</span>
<div class="sidebar-hotspot-badge mt-2" style="display:none;">
<a href="wifi.html" class="text-decoration-none">
<span class="badge text-bg-warning w-100 py-2" style="font-size: 0.75rem;">
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="currentColor" class="bi bi-broadcast me-1" viewBox="0 0 16 16">
<path d="M3.05 3.05a7 7 0 0 0 0 9.9.5.5 0 0 1-.707.707 8 8 0 0 1 0-11.314.5.5 0 0 1 .707.707m2.122 2.122a4 4 0 0 0 0 5.656.5.5 0 1 1-.708.708 5 5 0 0 1 0-7.072.5.5 0 0 1 .708.708m5.656-.708a.5.5 0 0 1 .708 0 5 5 0 0 1 0 7.072.5.5 0 1 1-.708-.708 4 4 0 0 0 0-5.656.5.5 0 0 1 0-.708m2.122-2.12a.5.5 0 0 1 .707 0 8 8 0 0 1 0 11.313.5.5 0 0 1-.707-.707 7 7 0 0 0 0-9.9.5.5 0 0 1 0-.707zM10 8a2 2 0 1 1-4 0 2 2 0 0 1 4 0"/>
</svg>
Mode Hotspot
</span>
</a>
</div>
</div> </div>

View File

@@ -54,56 +54,143 @@
<h3>Status <h3>Status
<span id="wifi-status" class="badge">Loading...</span> <span id="wifi-status" class="badge">Loading...</span>
<button id="btn-forget-wifi" class="btn btn-outline-danger btn-sm ms-2" style="display:none;" onclick="wifi_forget()">Oublier le réseau</button>
</h3> </h3>
<div class="row mb-3"> <div class="row mb-3">
<div class="col-sm-4"> <!-- Connection Info Card (shown when connected to WiFi) -->
<div class="card text-dark bg-light"> <div class="col-sm-6" id="card-connection-info" style="display:none;">
<div class="card border-success">
<div class="card-header bg-success text-white">
<h5 class="card-title mb-0">Connexion WiFi</h5>
</div>
<div class="card-body"> <div class="card-body">
<h5 class="card-title">WIFI / Ethernet</h5> <div id="connection-info-loading" class="text-center py-3">
<p class="card-text">General information.</p> <div class="spinner-border spinner-border-sm text-primary" role="status"></div>
<button class="btn btn-primary" onclick="get_internet()">Get Data</button> <span class="ms-2">Chargement...</span>
<table class="table table-striped-columns"> </div>
<tbody id="data-table-body_internet_general"></tbody> <table class="table table-sm mb-0" id="connection-info-table" style="display:none;">
<tbody>
<tr>
<td class="text-muted" style="width:40%">SSID</td>
<td><strong id="info-ssid">-</strong></td>
</tr>
<tr>
<td class="text-muted">Signal</td>
<td><span id="info-signal-bar"></span> <span id="info-signal">-</span></td>
</tr>
<tr>
<td class="text-muted">Adresse IP</td>
<td><code id="info-ip">-</code></td>
</tr>
<tr>
<td class="text-muted">Passerelle</td>
<td><code id="info-gateway">-</code></td>
</tr>
<tr>
<td class="text-muted">Hostname</td>
<td><code id="info-hostname">-</code></td>
</tr>
<tr>
<td class="text-muted">Frequence</td>
<td id="info-freq">-</td>
</tr>
<tr>
<td class="text-muted">Securite</td>
<td id="info-security">-</td>
</tr>
</tbody>
</table>
<button class="btn btn-outline-primary btn-sm mt-2" onclick="get_internet()">Rafraichir</button>
</div>
</div>
</div>
<!-- Ethernet Card -->
<div class="col-sm-6" id="card-ethernet">
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">Ethernet</h5>
</div>
<div class="card-body">
<table class="table table-sm mb-0">
<tbody>
<tr>
<td class="text-muted" style="width:40%">Etat</td>
<td id="info-eth-status">-</td>
</tr>
<tr>
<td class="text-muted">Adresse IP</td>
<td><code id="info-eth-ip">-</code></td>
</tr>
</tbody>
</table> </table>
</div> </div>
</div> </div>
</div> </div>
<div class="col-sm-8"> <!-- Hotspot Info Card (shown when in hotspot mode) -->
<div class="card text-dark bg-light"> <div class="col-sm-6" id="card-hotspot-info" style="display:none;">
<div class="card border-warning">
<div class="card-header bg-warning">
<h5 class="card-title mb-0">Mode Hotspot</h5>
</div>
<div class="card-body"> <div class="card-body">
<h5 class="card-title">Wifi Scan</h5> <p class="mb-1">Le capteur n'est connecte a aucun reseau WiFi.</p>
<p class="card-text">Scan des réseaux WIFI disponibles.</p> <p class="text-muted mb-0">Utilisez le scan ci-dessous pour vous connecter a un reseau.</p>
<button class="btn btn-primary" onclick="wifi_scan()">Scan</button> </div>
<table class="table"> </div>
</div>
</div>
<!-- WiFi Scan Card (hidden when connected) -->
<div class="row mb-3" id="card-wifi-scan" style="display:none;">
<div class="col-12">
<div class="card">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="card-title mb-0">Reseaux WiFi disponibles</h5>
<button class="btn btn-primary btn-sm" onclick="wifi_scan()">Scan</button>
</div>
<div class="card-body">
<div id="wifi-scan-empty" class="text-center text-muted py-3">
Cliquez sur "Scan" pour rechercher les reseaux WiFi.
</div>
<table class="table table-hover mb-0" id="wifi-scan-table" style="display:none;">
<thead>
<tr>
<th>SSID</th>
<th>Signal</th>
<th>Securite</th>
<th></th>
</tr>
</thead>
<tbody id="data-table-body_wifi_scan"></tbody> <tbody id="data-table-body_wifi_scan"></tbody>
</table> </table>
</table>
</div> </div>
</div> </div>
</div> </div>
</div>
<!-- Modal WIFI PASSWORD --> <!-- Modal WIFI PASSWORD -->
<!-- filled with JS --> <div class="modal fade" id="myModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal fade" id="myModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true"> <div class="modal-dialog">
<div class="modal-dialog"> <div class="modal-content">
<div class="modal-content"> <div class="modal-header">
<div class="modal-header"> <h1 class="modal-title fs-5" id="myModalLabel">Modal title</h1>
<h1 class="modal-title fs-5" id="myModalLabel">Modal title</h1> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div>
</div> <div class="modal-body" id="myModalBody">
<div class="modal-body" id="myModalBody"> ...
... </div>
</div> <div class="modal-footer" id="myModalFooter">
<div class="modal-footer" id="myModalFooter"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button> <button type="button" class="btn btn-primary">Save changes</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div> </div>
</div> </div>
</div>
</div>
<div> <div>
@@ -147,34 +234,67 @@
}); });
function get_internet(){ function load_ethernet_info() {
console.log("Getting internet general infos"); $.ajax({
$.ajax({ url: 'launcher.php?type=internet',
url: 'launcher.php?type=internet', dataType: 'json',
dataType: 'json', // Specify that you expect a JSON response method: 'GET',
method: 'GET', // Use GET or POST depending on your needs success: function(response) {
success: function(response) { const eth = response.ethernet;
console.log(response); document.getElementById('info-eth-status').textContent = eth.connection || '-';
let tableBody = document.getElementById('data-table-body_internet_general'); document.getElementById('info-eth-ip').textContent = eth.IP || '-';
tableBody.innerHTML = ''; // Clear existing table content }
});
}
// Iterate through the data and create rows function getSignalBadge(signal) {
for (let key in response) { const val = parseInt(signal, 10);
let row = ` if (isNaN(val)) return '';
<tr> let color, label;
<td>${key}</td> if (val >= 70) { color = 'success'; label = 'Excellent'; }
<td>${response[key].connection}</td> else if (val >= 50) { color = 'primary'; label = 'Bon'; }
<td>${response[key].IP ? response[key].IP : "No IP"}</td> else if (val >= 30) { color = 'warning'; label = 'Faible'; }
</tr> else { color = 'danger'; label = 'Tres faible'; }
`; return `<span class="badge text-bg-${color}">${val}% — ${label}</span>`;
tableBody.innerHTML += row; // Append row to table body }
}
}, function get_internet(){
error: function(xhr, status, error) { console.log("Getting internet general infos");
console.error('AJAX request failed:', status, error); document.getElementById('connection-info-loading').style.display = '';
} document.getElementById('connection-info-table').style.display = 'none';
});
} $.ajax({
url: 'launcher.php?type=internet',
dataType: 'json',
method: 'GET',
success: function(response) {
console.log(response);
const wifi = response.wifi;
const eth = response.ethernet;
// WiFi info
document.getElementById('info-ssid').textContent = wifi.ssid || '-';
document.getElementById('info-signal').innerHTML = wifi.signal ? getSignalBadge(wifi.signal) : '-';
document.getElementById('info-ip').textContent = wifi.IP || '-';
document.getElementById('info-gateway').textContent = wifi.gateway || '-';
document.getElementById('info-hostname').textContent = wifi.hostname || '-';
document.getElementById('info-freq').textContent = wifi.frequency ? wifi.frequency + ' MHz' : '-';
document.getElementById('info-security').textContent = wifi.security || '-';
// Ethernet info
const ethStatus = eth.connection || '-';
document.getElementById('info-eth-status').textContent = ethStatus;
document.getElementById('info-eth-ip').textContent = eth.IP || '-';
document.getElementById('connection-info-loading').style.display = 'none';
document.getElementById('connection-info-table').style.display = '';
},
error: function(xhr, status, error) {
console.error('AJAX request failed:', status, error);
document.getElementById('connection-info-loading').innerHTML = '<span class="text-danger">Erreur de chargement</span>';
}
});
}
function wifi_connect(SSID, PASS){ function wifi_connect(SSID, PASS){
@@ -293,151 +413,208 @@ function get_internet(){
}, 30000); }, 30000);
} }
function wifi_forget(){
if (!confirm('Oublier le réseau WiFi actuel et passer en mode hotspot ?')) return;
$.ajax({
url: 'launcher.php?type=wifi_forget',
dataType: 'json',
method: 'GET',
success: function(response) {
console.log(response);
showForgetStatus(response);
},
error: function(xhr, status, error) {
console.error('AJAX request failed:', status, error);
alert('Error: Could not forget WiFi network');
}
});
}
function showForgetStatus(response) {
const lang = localStorage.getItem('language') || 'fr';
const instructions = response.instructions[lang] || response.instructions['fr'];
const overlay = document.createElement('div');
overlay.id = 'connection-status-overlay';
overlay.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.9);
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
color: white;
`;
overlay.innerHTML = `
<div style="max-width: 600px; padding: 40px; text-align: center;">
<div class="spinner-border text-warning mb-4" role="status" style="width: 4rem; height: 4rem;">
<span class="visually-hidden">Loading...</span>
</div>
<h2 class="mb-4">${instructions.title}</h2>
<div class="alert alert-info text-start" role="alert">
<ol class="mb-0" style="padding-left: 20px;">
<li class="mb-2"><strong>${instructions.step1}</strong></li>
<li class="mb-2">${instructions.step2}</li>
<li class="mb-2">${instructions.step3}</li>
<li class="mb-2">${instructions.step4}</li>
</ol>
</div>
<div class="alert alert-warning text-start" role="alert">
<strong>Important:</strong> ${instructions.warning}
</div>
<div class="mt-4">
<p class="text-muted">
${lang === 'fr' ? 'Hotspot' : 'Hotspot'}:
<strong class="text-white">${response.deviceName}</strong>
</p>
</div>
</div>
`;
document.body.appendChild(overlay);
setTimeout(() => {
if (document.getElementById('connection-status-overlay')) {
document.getElementById('connection-status-overlay').remove();
}
}, 30000);
}
function wifi_scan(){ function wifi_scan(){
console.log("Scanning Wifi"); console.log("Scanning Wifi");
$.ajax({ document.getElementById('wifi-scan-empty').innerHTML = '<div class="spinner-border spinner-border-sm text-primary" role="status"></div> Scan en cours...';
url: 'launcher.php?type=wifi_scan',
dataType: 'json', // Specify that you expect a JSON response
method: 'GET', // Use GET or POST depending on your needs
success: function(response) {
console.log(response);
const tableBody = document.getElementById("data-table-body_wifi_scan");
// Clear the existing table body $.ajax({
tableBody.innerHTML = ""; url: 'launcher.php?type=wifi_scan',
dataType: 'json',
method: 'GET',
success: function(response) {
console.log(response);
const tableBody = document.getElementById("data-table-body_wifi_scan");
tableBody.innerHTML = "";
// Loop through the wifiNetworks array and create rows if (response.length === 0) {
response.forEach(network => { document.getElementById('wifi-scan-empty').textContent = 'Aucun reseau WiFi trouve.';
const row = document.createElement("tr"); document.getElementById('wifi-scan-empty').style.display = '';
document.getElementById('wifi-scan-table').style.display = 'none';
return;
}
// Create and append cells for SSID, BARS, and SIGNAL document.getElementById('wifi-scan-empty').style.display = 'none';
const ssidCell = document.createElement("td"); document.getElementById('wifi-scan-table').style.display = '';
// Truncate SSID to 25 characters
const truncatedSSID = network.SSID.length > 20 ? network.SSID.substring(0, 20) + '...' : network.SSID;
ssidCell.textContent = truncatedSSID;
row.appendChild(ssidCell);
/* response.forEach(network => {
const signalCell = document.createElement("td"); const row = document.createElement("tr");
signalCell.textContent = network.SIGNAL;
row.appendChild(signalCell);
*/
// Create a button // SSID
const buttonCell = document.createElement("td"); const ssidCell = document.createElement("td");
const button = document.createElement("button"); const truncatedSSID = network.SSID.length > 25 ? network.SSID.substring(0, 25) + '...' : network.SSID;
button.textContent = "Connect"; // Button text ssidCell.textContent = truncatedSSID;
button.classList.add("btn", "btn-primary"); // Bootstrap button classes row.appendChild(ssidCell);
// Determine button color based on SIGNAL value // Signal with badge
const signalValue = parseInt(network.SIGNAL, 10); // Assuming SIGNAL is a numeric value const signalCell = document.createElement("td");
// Calculate color based on the signal strength signalCell.innerHTML = getSignalBadge(network.SIGNAL);
let buttonColor; row.appendChild(signalCell);
if (signalValue >= 100) {
buttonColor = "success"; // Green for strong signal // Security
} else if (signalValue >= 50) { const securityCell = document.createElement("td");
buttonColor = "warning"; // Yellow for moderate signal securityCell.textContent = network.SECURITY || '--';
} else { securityCell.classList.add('text-muted');
buttonColor = "danger"; // Red for weak signal row.appendChild(securityCell);
}
// Add Bootstrap button classes along with color // Connect button
button.classList.add("btn", `btn-${buttonColor}`); const buttonCell = document.createElement("td");
buttonCell.classList.add('text-end');
const button = document.createElement("button");
button.textContent = "Connecter";
button.classList.add("btn", "btn-primary", "btn-sm");
button.addEventListener("click", () => wifi_connect(network.SSID));
buttonCell.appendChild(button);
row.appendChild(buttonCell);
tableBody.appendChild(row);
});
},
error: function(xhr, status, error) {
console.error('AJAX request failed:', status, error);
document.getElementById('wifi-scan-empty').innerHTML = '<span class="text-danger">Erreur lors du scan</span>';
}
});
}
//Trigger function as soon as the button is clicked
button.addEventListener("click", () => wifi_connect(network.SSID));
// Append the button to the button cell
buttonCell.appendChild(button);
row.appendChild(buttonCell);
// Append the row to the table body
tableBody.appendChild(row);
});
},
error: function(xhr, status, error) {
console.error('AJAX request failed:', status, error);
}
});
}
function confirmSubmit() {
// You can display a simple confirmation message or customize the behavior
return confirm("Are you sure you want to connect to this Wi-Fi network?");
}
window.onload = function() { window.onload = function() {
fetch('../config.json') // Replace 'deviceID.txt' with 'config.json' $.ajax({
.then(response => response.json()) // Parse response as JSON url: 'launcher.php?type=get_config_sqlite',
.then(data => { dataType: 'json',
console.log("Getting config file (onload)"); method: 'GET',
//get device ID success: function(data) {
const deviceID = data.deviceID.trim().toUpperCase(); console.log("Getting SQLite config table (wifi page):");
//document.getElementById('pageTitle_plus_ID').innerText = 'token: ' + deviceID; console.log(data);
//get device Name // WiFi connection status — toggle cards
const deviceName = data.deviceName; const WIFI_statusElement = document.getElementById("wifi-status");
console.log("WIFI is: " + data.WIFI_status);
// Function to update sidebar device name if (data.WIFI_status === "connected") {
function updateSidebarDeviceName(deviceName) { WIFI_statusElement.textContent = "Connected";
const elements = document.querySelectorAll('.sideBar_sensorName'); WIFI_statusElement.className = "badge text-bg-success";
if (elements.length > 0) { document.getElementById('btn-forget-wifi').style.display = 'inline-block';
elements.forEach((element) => { document.getElementById('card-connection-info').style.display = '';
element.innerText = deviceName; document.getElementById('card-hotspot-info').style.display = 'none';
}); document.getElementById('card-wifi-scan').style.display = 'none';
console.log("Device name updated in sidebar:", deviceName); // Auto-load connection details
} get_internet();
} } else if (data.WIFI_status === "hotspot") {
WIFI_statusElement.textContent = "Hotspot";
WIFI_statusElement.className = "badge text-bg-warning";
document.getElementById('btn-forget-wifi').style.display = 'none';
document.getElementById('card-connection-info').style.display = 'none';
document.getElementById('card-hotspot-info').style.display = '';
document.getElementById('card-wifi-scan').style.display = '';
} else {
WIFI_statusElement.textContent = "Unknown";
WIFI_statusElement.className = "badge text-bg-secondary";
document.getElementById('btn-forget-wifi').style.display = 'none';
document.getElementById('card-connection-info').style.display = 'none';
document.getElementById('card-hotspot-info').style.display = 'none';
document.getElementById('card-wifi-scan').style.display = '';
}
// Update device name immediately and with retries to handle async sidebar loading // Always load ethernet info
if (deviceName) { load_ethernet_info();
updateSidebarDeviceName(deviceName); },
// Retry after delays to catch async sidebar load error: function(xhr, status, error) {
setTimeout(() => updateSidebarDeviceName(deviceName), 100); console.error('AJAX request failed:', status, error);
setTimeout(() => updateSidebarDeviceName(deviceName), 500);
//device name html page title
document.title = deviceName;
}
//get wifi connection status
const WIFI_statusElement = document.getElementById("wifi-status");
console.log("WIFI is: " + data.WIFI_status);
if (data.WIFI_status === "connected") {
WIFI_statusElement.textContent = "Connected";
WIFI_statusElement.className = "badge text-bg-success";
} else if (data.WIFI_status === "hotspot") {
WIFI_statusElement.textContent = "Hotspot";
WIFI_statusElement.className = "badge text-bg-warning";
} else {
WIFI_statusElement.textContent = "Unknown";
WIFI_statusElement.className = "badge text-bg-secondary";
}
//get local RTC
$.ajax({
url: 'launcher.php?type=RTC_time',
dataType: 'text', // Specify that you expect a JSON response
method: 'GET', // Use GET or POST depending on your needs
success: function(response) {
console.log("Local RTC: " + response);
const RTC_Element = document.getElementById("RTC_time");
RTC_Element.textContent = response;
},
error: function(xhr, status, error) {
console.error('AJAX request failed:', status, error);
}
});
})
.catch(error => console.error('Error loading config.json:', error));
} }
});
// Load RTC time
$.ajax({
url: 'launcher.php?type=RTC_time',
dataType: 'text',
method: 'GET',
success: function(response) {
const RTC_Element = document.getElementById("RTC_time");
if (RTC_Element) RTC_Element.textContent = response;
},
error: function(xhr, status, error) {
console.error('AJAX request failed:', status, error);
}
});
}
</script> </script>