diff --git a/README.md b/README.md
index 7e4426c..ae66099 100755
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ Line by line installation.
```
sudo apt update
-sudo apt install git gh apache2 php php-sqlite3 python3 python3-pip jq autossh i2c-tools python3-smbus -y
+sudo apt install git gh apache2 sqlite3 php php-sqlite3 python3 python3-pip jq autossh i2c-tools python3-smbus -y
sudo pip3 install pyserial requests RPi.GPIO adafruit-circuitpython-bme280 crcmod psutil ntplib pytz gpiozero adafruit-circuitpython-ads1x15 numpy --break-system-packages
sudo mkdir -p /var/www/.ssh
sudo ssh-keygen -t rsa -b 4096 -f /var/www/.ssh/id_rsa -N ""
diff --git a/SARA/sara_connectNetwork.py b/SARA/sara_connectNetwork.py
index 96b9a8f..6342cca 100755
--- a/SARA/sara_connectNetwork.py
+++ b/SARA/sara_connectNetwork.py
@@ -36,6 +36,51 @@ def load_config(config_file):
print(f"Error loading config file: {e}")
return {}
+def read_complete_response(serial_connection, timeout=2, end_of_response_timeout=2, wait_for_lines=None, debug=True):
+ '''
+ Fonction très importante !!!
+ Reads the complete response from a serial connection and waits for specific lines.
+ '''
+ if wait_for_lines is None:
+ wait_for_lines = [] # Default to an empty list if not provided
+
+ response = bytearray()
+ serial_connection.timeout = timeout
+ end_time = time.time() + end_of_response_timeout
+ start_time = time.time()
+
+ while True:
+ elapsed_time = time.time() - start_time # Time since function start
+ if serial_connection.in_waiting > 0:
+ data = serial_connection.read(serial_connection.in_waiting)
+ response.extend(data)
+ end_time = time.time() + end_of_response_timeout # Reset timeout on new data
+
+ # Decode and check for any target line
+ decoded_response = response.decode('utf-8', errors='replace')
+ for target_line in wait_for_lines:
+ if target_line in decoded_response:
+ if debug:
+ print(f"[DEBUG] 🔎 Found target line: {target_line} (in {elapsed_time:.2f}s)")
+ return decoded_response # Return response immediately if a target line is found
+ elif time.time() > end_time:
+ if debug:
+ print(f"[DEBUG] Timeout reached. No more data received.")
+ break
+ time.sleep(0.1) # Short sleep to prevent busy waiting
+
+ # Final response and debug output
+ total_elapsed_time = time.time() - start_time
+ if debug:
+ print(f"[DEBUG] ⏱️ elapsed time: {total_elapsed_time:.2f}s. ⏱️")
+ # Check if the elapsed time exceeded 10 seconds
+ if total_elapsed_time > 10 and debug:
+ print(f"[ALERT] 🚨 The operation took too long 🚨")
+ print(f'[ALERT] ⚠️{total_elapsed_time:.2f}s⚠️')
+
+ return response.decode('utf-8', errors='replace') # Return the full response if no target line is found
+
+
# Define the config file path
config_file = '/var/www/nebuleair_pro_4g/config.json'
# Load the configuration data
@@ -57,17 +102,11 @@ ser.write((command + '\r').encode('utf-8'))
try:
- # Read lines until a timeout occurs
- response_lines = []
- while True:
- line = ser.readline().decode('utf-8').strip()
- if not line:
- break # Break the loop if an empty line is encountered
- response_lines.append(line)
-
- # Print the response
- for line in response_lines:
- print(line)
+ response = read_complete_response(ser, wait_for_lines=["OK", "ERROR"],timeout=5, end_of_response_timeout=120, debug=True)
+
+ print('
')
+ print(response)
+ print("
", end="")
except serial.SerialException as e:
print(f"Error: {e}")
diff --git a/boot_hotspot.sh b/boot_hotspot.sh
index 8dac2f8..e616d81 100755
--- a/boot_hotspot.sh
+++ b/boot_hotspot.sh
@@ -25,13 +25,18 @@ for i in {1..5}; do
sleep 1
done
-echo "getting SARA R4 serial number"
+echo "getting RPI serial number"
# Get the last 8 characters of the serial number and write to text file
serial_number=$(cat /proc/cpuinfo | grep Serial | awk '{print substr($3, length($3) - 7)}')
# Use jq to update the "deviceID" in the JSON file
-jq --arg serial_number "$serial_number" '.deviceID = $serial_number' "$JSON_FILE" > temp.json && mv temp.json "$JSON_FILE"
+#jq --arg serial_number "$serial_number" '.deviceID = $serial_number' "$JSON_FILE" > temp.json && mv temp.json "$JSON_FILE"
+# update Sqlite database
+echo "Updating SQLite database with device ID: $serial_number"
+sqlite3 /var/www/nebuleair_pro_4g/sqlite/sensors.db "UPDATE config_table SET value='$serial_number' WHERE key='deviceID';"
+
echo "id: $serial_number"
+
#get the SSH port for tunneling
SSH_TUNNEL_PORT=$(jq -r '.sshTunnel_port' "$JSON_FILE")
diff --git a/html/admin.html b/html/admin.html
index 8f5ef6b..c4ce27c 100755
--- a/html/admin.html
+++ b/html/admin.html
@@ -55,28 +55,20 @@
-
Parameters
+
Parameters (config)
@@ -117,13 +101,6 @@
Clock
-
-
-
-
-
@@ -227,11 +204,6 @@ window.onload = function() {
const checkbox_envea = document.getElementById("check_envea");
checkbox_envea.checked = data["envea/read_value_v2.py"];
- //get RTC check
- const checkbox_RTC = document.getElementById("check_RTC");
- checkbox_RTC.checked = data.i2c_RTC;
-
-
//device name
const device_name = document.getElementById("device_name");
device_name.value = data.deviceName;
@@ -300,6 +272,22 @@ window.onload = function() {
.catch(error => console.error('Error loading config.json:', error));
}
+function update_config_sqlite(param, value){
+ console.log("Updating sqlite ",param," : ", value);
+ $.ajax({
+ url: 'launcher.php?type=update_config_sqlite¶m='+param+'&value='+value,
+ dataType: 'text', // Specify that you expect a JSON response
+ method: 'GET', // Use GET or POST depending on your needs
+ cache: false, // Prevent AJAX from caching
+ success: function(response) {
+ console.log(response);
+ },
+ error: function(xhr, status, error) {
+ console.error('AJAX request failed:', status, error);
+ }
+ });
+}
+
function update_config(param, value){
console.log("Updating ",param," : ", value);
diff --git a/html/launcher.php b/html/launcher.php
index bb60cbe..03afc46 100755
--- a/html/launcher.php
+++ b/html/launcher.php
@@ -25,6 +25,67 @@ if ($type == "get_npm_sqlite_data") {
}
}
+if ($type == "update_config_sqlite") {
+ echo "updating....";
+ $param = $_GET['param'] ?? null;
+ $value = $_GET['value'] ?? null;
+
+ if ($param === null || $value === null) {
+ echo json_encode(["error" => "Missing parameter or value"]);
+ exit;
+ }
+
+ $database_path = "/var/www/nebuleair_pro_4g/sqlite/sensors.db";
+ try {
+ $db = new PDO("sqlite:$database_path");
+ $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+ // First, check if parameter exists and get its type
+ $checkStmt = $db->prepare("SELECT type FROM config_table WHERE key = :param");
+ $checkStmt->bindParam(':param', $param);
+ $checkStmt->execute();
+ $result = $checkStmt->fetch(PDO::FETCH_ASSOC);
+
+ if ($result) {
+ // Parameter exists, determine type and update
+ $type = $result['type'];
+
+ // Convert value according to type if needed
+ $convertedValue = $value;
+ if ($type == "bool") {
+ // Convert various boolean representations to 0/1
+ $convertedValue = (filter_var($value, FILTER_VALIDATE_BOOLEAN)) ? "1" : "0";
+ } elseif ($type == "int") {
+ $convertedValue = (string)intval($value);
+ } elseif ($type == "float") {
+ $convertedValue = (string)floatval($value);
+ }
+
+ // Update the value
+ $updateStmt = $db->prepare("UPDATE config_table SET value = :value WHERE key = :param");
+ $updateStmt->bindParam(':value', $convertedValue);
+ $updateStmt->bindParam(':param', $param);
+ $updateStmt->execute();
+
+ echo json_encode([
+ "success" => true,
+ "message" => "Configuration updated successfully",
+ "param" => $param,
+ "value" => $convertedValue,
+ "type" => $type
+ ]);
+ } else {
+ echo json_encode([
+ "error" => "Parameter not found in configuration",
+ "param" => $param
+ ]);
+ }
+ } catch (PDOException $e) {
+ echo json_encode(["error" => $e->getMessage()]);
+ }
+}
+
+
if ($type == "update_config") {
echo "updating....";
$param=$_GET['param'];
@@ -269,7 +330,7 @@ if ($type == "sara_connectNetwork") {
$timeout=$_GET['timeout'];
$networkID=$_GET['networkID'];
- echo "updating SARA_R4_networkID in config file";
+ //echo "updating SARA_R4_networkID in config file";
// Convert `networkID` to an integer (or float if needed)
$networkID = is_numeric($networkID) ? (strpos($networkID, '.') !== false ? (float)$networkID : (int)$networkID) : 0;
#save to config.json
@@ -296,10 +357,10 @@ if ($type == "sara_connectNetwork") {
die("Error: Could not write to JSON file.");
}
- echo "SARA_R4_networkID updated successfully.";
+ //echo "SARA_R4_networkID updated successfully.";
- echo "connecting to network... please wait...";
+ //echo "connecting to network... please wait...";
$command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_connectNetwork.py ' . $port . ' ' . $networkID . ' ' . $timeout;
$output = shell_exec($command);
echo $output;
diff --git a/installation_part1.sh b/installation_part1.sh
index 8935d60..400912a 100644
--- a/installation_part1.sh
+++ b/installation_part1.sh
@@ -23,7 +23,7 @@ fi
# Update and install necessary packages
info "Updating package list and installing necessary packages..."
-sudo apt update && sudo apt install -y git gh apache2 php php-sqlite3 python3 python3-pip jq autossh i2c-tools python3-smbus || error "Failed to install required packages."
+sudo apt update && sudo apt install -y git gh apache2 sqlite3 php php-sqlite3 python3 python3-pip jq autossh i2c-tools python3-smbus || error "Failed to install required packages."
# Install Python libraries
info "Installing Python libraries..."
diff --git a/loop/SARA_send_data_v2.py b/loop/SARA_send_data_v2.py
index b5a5a19..29f677b 100755
--- a/loop/SARA_send_data_v2.py
+++ b/loop/SARA_send_data_v2.py
@@ -217,7 +217,6 @@ bme_280_config = config.get('BME280/get_data_v2.py', False) #présence d
envea_cairsens= config.get('envea/read_value_v2.py', False)
mppt_charger= config.get('MPPT/read.py', False)
wind_meter= config.get('windMeter/read.py', False)
-send_aircarto = config.get('send_aircarto', True) #envoi sur AirCarto (data.nebuleair.fr)
send_uSpot = config.get('send_uSpot', False) #envoi sur MicroSpot ()
reset_uSpot_url = False
selected_networkID = int(config.get('SARA_R4_neworkID', 0))
diff --git a/sqlite/create_db.py b/sqlite/create_db.py
index 22b8553..0b430ec 100755
--- a/sqlite/create_db.py
+++ b/sqlite/create_db.py
@@ -18,6 +18,35 @@ import sqlite3
conn = sqlite3.connect("/var/www/nebuleair_pro_4g/sqlite/sensors.db")
cursor = conn.cursor()
+#create a config table
+cursor.execute("""
+CREATE TABLE IF NOT EXISTS config_table (
+ key TEXT PRIMARY KEY,
+ value TEXT NOT NULL,
+ type TEXT NOT NULL
+)
+""")
+
+#creates a config_scripts table
+cursor.execute('''
+CREATE TABLE IF NOT EXISTS config_scripts_table (
+ script_path TEXT PRIMARY KEY,
+ enabled INTEGER NOT NULL
+)
+''')
+
+#creates a config table for envea sondes
+cursor.execute("""
+CREATE TABLE IF NOT EXISTS envea_sondes_table (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ connected INTEGER NOT NULL,
+ port TEXT NOT NULL,
+ name TEXT NOT NULL,
+ coefficient REAL NOT NULL
+)
+""")
+
+
# Create a table timer
cursor.execute("""
CREATE TABLE IF NOT EXISTS timestamp_table (
diff --git a/sqlite/read.py b/sqlite/read.py
index e75713b..c5a47ea 100755
--- a/sqlite/read.py
+++ b/sqlite/read.py
@@ -36,7 +36,6 @@ cursor = conn.cursor()
#cursor.execute("SELECT * FROM timestamp_table")
if table_name == "timestamp_table":
cursor.execute("SELECT * FROM timestamp_table")
-
else:
query = f"SELECT * FROM {table_name} ORDER BY timestamp DESC LIMIT ?"
cursor.execute(query, (limit_num,))
diff --git a/sqlite/read_config.py b/sqlite/read_config.py
new file mode 100644
index 0000000..bc7b2b7
--- /dev/null
+++ b/sqlite/read_config.py
@@ -0,0 +1,43 @@
+'''
+ ____ ___ _ _ _
+ / ___| / _ \| | (_) |_ ___
+ \___ \| | | | | | | __/ _ \
+ ___) | |_| | |___| | || __/
+ |____/ \__\_\_____|_|\__\___|
+
+Script to read data from a sqlite database
+/usr/bin/python3 /var/www/nebuleair_pro_4g/sqlite/read_config.py config_table
+
+Available table are
+config_table
+config_scripts_table
+envea_sondes_table
+
+'''
+
+import sqlite3
+import sys
+parameter = sys.argv[1:] # Exclude the script name
+#print("Parameters received:")
+table_name=parameter[0]
+
+
+# Connect to the SQLite database
+conn = sqlite3.connect("/var/www/nebuleair_pro_4g/sqlite/sensors.db")
+cursor = conn.cursor()
+
+# Retrieve the data
+query = f"SELECT * FROM {table_name}"
+cursor.execute(query)
+
+
+rows = cursor.fetchall()
+rows.reverse() # Reverse the order in Python (to get ascending order)
+
+
+# Display the results
+for row in rows:
+ print(row)
+
+# Close the database connection
+conn.close()
diff --git a/sqlite/set_config.py b/sqlite/set_config.py
new file mode 100644
index 0000000..2a9460c
--- /dev/null
+++ b/sqlite/set_config.py
@@ -0,0 +1,95 @@
+'''
+ ____ ___ _ _ _
+ / ___| / _ \| | (_) |_ ___
+ \___ \| | | | | | | __/ _ \
+ ___) | |_| | |___| | || __/
+ |____/ \__\_\_____|_|\__\___|
+
+Script to set the config
+/usr/bin/python3 /var/www/nebuleair_pro_4g/sqlite/set_config.py
+
+in case of readonly error:
+sudo chmod 777 /var/www/nebuleair_pro_4g/sqlite/sensors.db
+'''
+
+import sqlite3
+
+# Connect to (or create if not existent) the database
+conn = sqlite3.connect("/var/www/nebuleair_pro_4g/sqlite/sensors.db")
+cursor = conn.cursor()
+
+print(f"Connected to database")
+
+# Clear existing data (if any)
+cursor.execute("DELETE FROM config_table")
+cursor.execute("DELETE FROM config_scripts_table")
+cursor.execute("DELETE FROM envea_sondes_table")
+print("Existing data cleared")
+
+#add values
+
+# Insert script configurations
+script_configs = [
+ ("NPM/get_data_modbus_v3.py", True),
+ ("loop/SARA_send_data_v2.py", True),
+ ("RTC/save_to_db.py", True),
+ ("BME280/get_data_v2.py", True),
+ ("envea/read_value_v2.py", False),
+ ("MPPT/read.py", False),
+ ("windMeter/read.py", False),
+ ("sqlite/flush_old_data.py", True)
+]
+
+for script_path, enabled in script_configs:
+ cursor.execute(
+ "INSERT INTO config_scripts_table (script_path, enabled) VALUES (?, ?)",
+ (script_path, 1 if enabled else 0)
+ )
+
+# Insert general configurations
+config_entries = [
+ ("modem_config_mode", "0", "bool"),
+ ("deviceID", "XXXX", "str"),
+ ("npm_5channel", "0", "bool"),
+ ("latitude_raw", "0", "int"),
+ ("longitude_raw", "0", "int"),
+ ("latitude_precision", "0", "int"),
+ ("longitude_precision", "0", "int"),
+ ("deviceName", "NebuleAir-proXXX", "str"),
+ ("SaraR4_baudrate", "115200", "int"),
+ ("NPM_solo_port", "/dev/ttyAMA5", "str"),
+ ("sshTunnel_port", "59228", "int"),
+ ("SARA_R4_general_status", "connected", "str"),
+ ("SARA_R4_SIM_status", "connected", "str"),
+ ("SARA_R4_network_status", "connected", "str"),
+ ("SARA_R4_neworkID", "20810", "int"),
+ ("WIFI_status", "connected", "str"),
+ ("send_uSpot", "0", "bool"),
+ ("modem_version", "XXX", "str")
+]
+
+for key, value, value_type in config_entries:
+ cursor.execute(
+ "INSERT INTO config_table (key, value, type) VALUES (?, ?, ?)",
+ (key, value, value_type)
+ )
+
+# Insert envea sondes
+envea_sondes = [
+ (False, "ttyAMA4", "h2s", 4),
+ (False, "ttyAMA3", "no2", 1),
+ (False, "ttyAMA2", "o3", 1)
+]
+
+for connected, port, name, coefficient in envea_sondes:
+ cursor.execute(
+ "INSERT INTO envea_sondes_table (connected, port, name, coefficient) VALUES (?, ?, ?, ?)",
+ (1 if connected else 0, port, name, coefficient)
+ )
+
+
+# Commit and close the connection
+conn.commit()
+conn.close()
+
+print("Database updated successfully!")