diff --git a/VERSION b/VERSION index 428b770..e516bb9 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.4.3 +1.4.5 diff --git a/changelog.json b/changelog.json index a1dd79b..dcef69e 100644 --- a/changelog.json +++ b/changelog.json @@ -1,5 +1,28 @@ { "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", "date": "2026-03-16", diff --git a/forget_wifi.sh b/forget_wifi.sh new file mode 100644 index 0000000..d661629 --- /dev/null +++ b/forget_wifi.sh @@ -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 "-------" diff --git a/html/assets/js/topbar-logo.js b/html/assets/js/topbar-logo.js index ba2293a..5ea5ccc 100644 --- a/html/assets/js/topbar-logo.js +++ b/html/assets/js/topbar-logo.js @@ -3,6 +3,8 @@ * Global configuration handler for UI elements * - Updates Topbar Logo 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', () => { let config = null; @@ -42,17 +44,28 @@ document.addEventListener('DOMContentLoaded', () => { if (navScreenElements.length > 0) { navScreenElements.forEach(navScreen => { if (isModuleAirPro) { - // Ensure it's visible (bootstrap nav-link usually block or flex) if (navScreen.style.display === 'none') { navScreen.style.display = 'flex'; } } else { - // Hide if not pro if (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'; + }); } }); diff --git a/html/launcher.php b/html/launcher.php index e4b63f4..f7b4ad2 100755 --- a/html/launcher.php +++ b/html/launcher.php @@ -1042,35 +1042,64 @@ if ($type == "sara_sendMessage") { } if ($type == "internet") { - //eth0 - $command = 'nmcli -g GENERAL.STATE device show eth0'; - $eth0_connStatus = shell_exec($command); - $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); + // eth0 + $eth0_connStatus = str_replace("\n", "", shell_exec('nmcli -g GENERAL.STATE device show eth0 2>/dev/null')); + $eth0_IPAddr = str_replace("\n", "", shell_exec('nmcli -g IP4.ADDRESS device show eth0 2>/dev/null')); - //wlan0 - $command = 'nmcli -g GENERAL.STATE device show wlan0'; - $wlan0_connStatus = shell_exec($command); - $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); + // wlan0 basic + $wlan0_connStatus = str_replace("\n", "", shell_exec('nmcli -g GENERAL.STATE device show wlan0 2>/dev/null')); + $wlan0_IPAddr = str_replace("\n", "", shell_exec('nmcli -g IP4.ADDRESS device show wlan0 2>/dev/null')); - $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( "connection" => $eth0_connStatus, "IP" => $eth0_IPAddr ), "wifi" => array( "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 @@ -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") { // Perform live WiFi scan instead of reading stale CSV file diff --git a/html/sidebar.html b/html/sidebar.html index 91a2850..0bfea5b 100755 --- a/html/sidebar.html +++ b/html/sidebar.html @@ -92,7 +92,17 @@
diff --git a/html/wifi.html b/html/wifi.html index 0d2b935..cbbc6d0 100755 --- a/html/wifi.html +++ b/html/wifi.html @@ -54,56 +54,143 @@