diff --git a/SARA/reboot/hardware_reboot.py b/SARA/reboot/hardware_reboot.py new file mode 100644 index 0000000..40886a8 --- /dev/null +++ b/SARA/reboot/hardware_reboot.py @@ -0,0 +1,72 @@ +''' + ____ _ ____ _ + / ___| / \ | _ \ / \ + \___ \ / _ \ | |_) | / _ \ + ___) / ___ \| _ < / ___ \ + |____/_/ \_\_| \_\/_/ \_\ + +sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/reboot/hardware_reboot.py + +Hardware reboot of the SARA R5 modem using GPIO 16 (GND control via transistor). +Cuts power for 3 seconds, then verifies modem is responsive with ATI command. +Returns JSON result for web interface. +''' + +import RPi.GPIO as GPIO +import serial +import time +import json +import sqlite3 + +SARA_GND_GPIO = 16 + +# Load baudrate from config +conn = sqlite3.connect("/var/www/nebuleair_pro_4g/sqlite/sensors.db") +cursor = conn.cursor() +cursor.execute("SELECT value FROM config_table WHERE key='SaraR4_baudrate'") +row = cursor.fetchone() +baudrate = int(row[0]) if row else 115200 +conn.close() + +result = { + "reboot": False, + "modem_response": None, + "error": None +} + +try: + # Step 1: Cut GND (modem off) + GPIO.setmode(GPIO.BCM) + GPIO.setup(SARA_GND_GPIO, GPIO.OUT) + GPIO.output(SARA_GND_GPIO, GPIO.LOW) + time.sleep(3) + + # Step 2: Restore GND (modem on) + GPIO.output(SARA_GND_GPIO, GPIO.HIGH) + time.sleep(5) # wait for modem boot + + # Step 3: Check modem with ATI + ser = serial.Serial('/dev/ttyAMA2', baudrate=baudrate, timeout=3) + ser.reset_input_buffer() + + for attempt in range(5): + ser.write(b'ATI\r') + time.sleep(1) + response = ser.read(ser.in_waiting or 1).decode('utf-8', errors='replace') + if "OK" in response: + result["reboot"] = True + result["modem_response"] = response.strip() + break + time.sleep(2) + else: + result["error"] = "Modem ne repond pas apres le redemarrage" + + ser.close() + +except Exception as e: + result["error"] = str(e) + +finally: + GPIO.cleanup(SARA_GND_GPIO) + +print(json.dumps(result)) diff --git a/SARA/reboot/start.py b/SARA/reboot/start.py index 3ecf0e9..bca10f6 100644 --- a/SARA/reboot/start.py +++ b/SARA/reboot/start.py @@ -175,6 +175,11 @@ def read_complete_response(serial_connection, timeout=2, end_of_response_timeout try: print('

Start reboot python script

') + # Reset modem_config_mode at boot to prevent capteur from staying stuck in config mode + cursor.execute("UPDATE config_table SET value = '0' WHERE key = 'modem_config_mode'") + conn.commit() + print("modem_config_mode reset to 0 (boot safety)") + #First we need to power on the module (if connected to mosfet via gpio16) GPIO.output(SARA_power_GPIO, GPIO.HIGH) time.sleep(5) diff --git a/html/launcher.php b/html/launcher.php index ccb19af..d541cbb 100755 --- a/html/launcher.php +++ b/html/launcher.php @@ -880,6 +880,13 @@ if ($type == "sara") { echo $output; } +# SARA HARDWARE REBOOT (GPIO 16) +if ($type == "sara_hardware_reboot") { + $command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/reboot/hardware_reboot.py'; + $output = shell_exec($command); + echo $output; +} + # SARA R4 COMMANDS (MQTT) if ($type == "sara_getMQTT_config") { $port=$_GET['port']; diff --git a/html/saraR4.html b/html/saraR4.html index 749ed6d..de45751 100755 --- a/html/saraR4.html +++ b/html/saraR4.html @@ -58,6 +58,16 @@ + + +

Modem Reset

+ +

Reset software (AT+CFUN=15) : redémarre le firmware du modem.

+
- + +
+ +

Reset hardware (GPIO 16) : coupe et rétablit l'alimentation du modem.

+ + +
@@ -446,6 +464,9 @@ document.addEventListener('DOMContentLoaded', function () { if (check_modem_configMode) { check_modem_configMode.checked = response.modem_config_mode; console.log("Modem configuration: " + response.modem_config_mode); + // Show/hide config mode alert banner + const alertEl = document.getElementById("configmode_alert"); + if (alertEl) alertEl.style.display = response.modem_config_mode ? "flex" : "none"; } else { console.error("Checkbox element not found"); } @@ -1024,6 +1045,48 @@ function getSignalInfo(port, timeout) { }); } +function hardwareRebootSara() { + if (!confirm("Couper l'alimentation du modem SARA via GPIO 16 ?\nLe modem sera éteint pendant ~3 secondes puis redémarré.")) return; + + console.log("Hardware reboot SARA via GPIO 16"); + $("#loading_hw_reboot").show(); + $("#response_hw_reboot").empty(); + + $.ajax({ + url: 'launcher.php?type=sara_hardware_reboot', + dataType: 'json', + method: 'GET', + timeout: 30000, + success: function(response) { + console.log(response); + $("#loading_hw_reboot").hide(); + + if (response.reboot) { + $("#response_hw_reboot").html(` +
+ Modem redémarré
+ ${response.modem_response} +
`); + } else { + $("#response_hw_reboot").html(` +
+ Echec
+ ${response.error || 'Modem ne répond pas'} +
`); + } + }, + error: function(xhr, status, error) { + console.error('Hardware reboot failed:', status, error); + $("#loading_hw_reboot").hide(); + $("#response_hw_reboot").html(` +
+ Erreur de communication
+ ${error} +
`); + } + }); +} + function getData_saraR4(port, command, timeout){ console.log("Data from SaraR4"); console.log("Port: " + port ); @@ -1429,6 +1492,10 @@ function update_modem_configMode(param, checked){ const toastBody = toastLiveExample.querySelector('.toast-body'); console.log("updating modem config mode to :" + checked); + // Toggle alert banner immediately + const alertEl = document.getElementById("configmode_alert"); + if (alertEl) alertEl.style.display = checked ? "flex" : "none"; + $.ajax({ url: 'launcher.php?type=update_config_sqlite¶m='+param+'&value='+checked, dataType: 'json', // Specify that you expect a JSON response