From e609c38ca0e5f754ff93f1aa9b69c8e7c52d7dd2 Mon Sep 17 00:00:00 2001 From: PaulVua Date: Mon, 10 Feb 2025 15:41:52 +0100 Subject: [PATCH] update --- config.json.dist | 2 + html/database.html | 139 ++++++++++++++++++++++++++++++++++---- html/index.html | 4 +- html/launcher.php | 11 +++ html/logs.html | 4 +- html/saraR4.html | 43 ++++++++++-- loop/SARA_send_data_v2.py | 16 ++++- sqlite/read.py | 16 ++++- 8 files changed, 210 insertions(+), 25 deletions(-) diff --git a/config.json.dist b/config.json.dist index 150b131..db51d2c 100755 --- a/config.json.dist +++ b/config.json.dist @@ -2,9 +2,11 @@ "loop_activation": true, "loop_log": true, "boot_log": true, + "modem_config_mode": false, "NPM/get_data_v2.py": true, "loop/SARA_send_data_v2.py": true, "RTC/save_to_db.py": true, + "BME280/get_data_v2.py": true, "deviceID": "XXXX", "deviceName": "NebuleAir-proXXX", "SaraR4_baudrate": 115200, diff --git a/html/database.html b/html/database.html index eecdc60..568bf15 100644 --- a/html/database.html +++ b/html/database.html @@ -57,12 +57,9 @@
-
Consulter Base de donnée
-

General information.

- - - -
+
Consulter la base de donnée
+ +
@@ -71,19 +68,19 @@
Télécharger les données
-

Scan des réseaux WIFI disponibles.

- - - -
+ + +
- -
+ +
+
+
@@ -164,11 +161,125 @@ } }); - }) .catch(error => console.error('Error loading config.json:', error)); } + + +// TABLE PM +function get_data_sqlite(table, limit, download) { + console.log("Getting data for table mesure PM"); + + $.ajax({ + url: 'launcher.php?type=table_mesurePM&table='+table+'&limit='+limit+'&download='+download, + dataType: 'text', // Specify that you expect a JSON response + method: 'GET', // Use GET or POST depending on your needs + success: function(response) { + console.log(response); + + // If download is true, generate and trigger CSV download + if (download) { + downloadCSV(response, table); + return; // Exit function after triggering download + } + + let rows = response.trim().split("\n"); + // Generate Bootstrap table + + let tableHTML = ` + `; + + // Define column headers dynamically based on the table type + if (table === "data_NPM") { + tableHTML += ` + + + + + + + `; + } else if (table === "data_BME280") { + tableHTML += ` + + + + + `; + } + + tableHTML += ``; + + // Loop through rows and create table rows + rows.forEach(row => { + let columns = row.replace(/[()]/g, "").split(", "); // Remove parentheses and split + tableHTML += ""; + + if (table === "data_NPM") { + tableHTML += ` + + + + + + + `; + } else if (table === "data_BME280") { + tableHTML += ` + + + + + `; + } + + tableHTML += ""; + }); + + tableHTML += `
TimestampPM1PM2.5PM10Temperature (°C)Humidity (%)TimestampTemperature (°C)Humidity (%)Pressure (hPa)
${columns[0]}${columns[1]}${columns[2]}${columns[3]}${columns[4]}${columns[5]}${columns[0]}${columns[1]}${columns[2]}${columns[3]}
`; + + // Update the #table_data div with the generated table + document.getElementById("table_data").innerHTML = tableHTML; + }, + error: function(xhr, status, error) { + console.error('AJAX request failed:', status, error); + } + }); + + +} + +function downloadCSV(response, table) { + let rows = response.trim().split("\n"); + + let csvContent = ""; + + // Add headers based on table type + if (table === "data_NPM") { + csvContent += "Timestamp,PM1,PM2.5,PM10,Temperature (°C),Humidity (%)\n"; + } else if (table === "data_BME280") { + csvContent += "Timestamp,Temperature (°C),Humidity (%),Pressure (hPa)\n"; + } + + // Format rows as CSV + rows.forEach(row => { + let columns = row.replace(/[()]/g, "").split(", "); + csvContent += columns.join(",") + "\n"; + }); + + // Create a downloadable file + let blob = new Blob([csvContent], { type: "text/csv" }); + let url = window.URL.createObjectURL(blob); + let a = document.createElement("a"); + a.href = url; + a.download = table + "_data.csv"; // File name + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); +} + + diff --git a/html/index.html b/html/index.html index 4637062..a72bc31 100755 --- a/html/index.html +++ b/html/index.html @@ -84,9 +84,9 @@ +
@@ -97,7 +97,7 @@
- +-->
diff --git a/html/launcher.php b/html/launcher.php index b4db751..6bb7186 100755 --- a/html/launcher.php +++ b/html/launcher.php @@ -202,6 +202,17 @@ if ($type == "BME280") { echo $output; } + +if ($type == "table_mesurePM") { + $table=$_GET['table']; + $limit=$_GET['limit']; + $download=$_GET['download']; + + $command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/sqlite/read.py '.$table.' '.$limit; + $output = shell_exec($command); + echo $output; +} + # SARA R4 COMMANDS if ($type == "sara") { $port=$_GET['port']; diff --git a/html/logs.html b/html/logs.html index 3840845..6d76ecd 100755 --- a/html/logs.html +++ b/html/logs.html @@ -226,7 +226,7 @@ function clear_loopLogs(){ } function getModem_busy_status() { - console.log("Getting modem busy status"); + //console.log("Getting modem busy status"); const script_is_running = document.getElementById("script_running"); @@ -235,7 +235,7 @@ function getModem_busy_status() { dataType: 'json', // Expecting JSON response method: 'GET', success: function(response) { - console.log(response); + //console.log(response); if (response.running) { // Script is running → Show the Bootstrap spinner diff --git a/html/saraR4.html b/html/saraR4.html index 168e774..3d286ae 100755 --- a/html/saraR4.html +++ b/html/saraR4.html @@ -51,6 +51,12 @@

Modem 4G

Votre capteur est équipé d'un modem 4G et d'une carte SIM afin d'envoyer les mesures sur internet.

+ +
+ + +
+

Status @@ -298,6 +304,17 @@ }) .catch(error => console.error(`Error loading ${file}:`, error)); }); + fetch('../config.json') // Replace 'deviceID.txt' with 'config.json' + .then(response => response.json()) // Parse response as JSON + .then(data => { + console.log("Getting config file (onload)"); + //modem config mode + const check_modem_configMode = document.getElementById("check_modem_configMode"); + check_modem_configMode.checked = data.modem_config_mode; + console.log("Modem configuration: " + data.modem_config_mode); + + }) + }); function getData_saraR4(port, command, timeout){ @@ -595,7 +612,7 @@ function connectAPN_saraR4(port, APN_address, timeout){ } function getModem_busy_status() { - console.log("Getting modem busy status"); + //console.log("Getting modem busy status"); const SARA_busy_message = document.getElementById("modem_status_message"); @@ -604,19 +621,20 @@ function getModem_busy_status() { dataType: 'json', // Expecting JSON response method: 'GET', success: function(response) { - console.log(response); + //console.log(response); if (response.running) { // Script is running → Red button, "Modem is busy" SARA_busy_message.innerHTML= ` ` } else { // Script is NOT running → Green button, "Modem is available" SARA_busy_message.innerHTML= ` ` } }, @@ -628,6 +646,23 @@ function getModem_busy_status() { }); } +function update_modem_configMode(param, checked){ + console.log("updating modem config mode to :" + checked); + $.ajax({ + url: 'launcher.php?type=update_config¶m='+param+'&value='+checked, + 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); + } + }); +} + + window.onload = function() { getModem_busy_status(); diff --git a/loop/SARA_send_data_v2.py b/loop/SARA_send_data_v2.py index 8e3c38e..793f6ea 100644 --- a/loop/SARA_send_data_v2.py +++ b/loop/SARA_send_data_v2.py @@ -99,6 +99,7 @@ import sys import sqlite3 import RPi.GPIO as GPIO from threading import Thread +from datetime import datetime # Record the start time of the script start_time_script = time.time() @@ -205,10 +206,16 @@ need_to_log = config.get('loop_log', False) #inscription des logs send_aircarto = config.get('send_aircarto', True) #envoi sur AirCarto (data.nebuleair.fr) send_uSpot = config.get('send_uSpot', False) #envoi sur MicroSpot () selected_networkID = config.get('SARA_R4_neworkID', '') +modem_config_mode = config.get('modem_config_mode', False) #modem 4G en mode configuration #update device id in the payload json payload_json["nebuleairid"] = device_id +# Skip execution if modem_config_mode is true +if modem_config_mode: + print("Modem 4G (SARA R4) is in config mode -> EXIT") + sys.exit() + ser_sara = serial.Serial( port='/dev/ttyAMA2', baudrate=baudrate, #115200 ou 9600 @@ -279,6 +286,13 @@ try: # Display the result if last_row: print("SQLite DB last available row:", last_row) + + datetime_measure_PM = last_row[0] #on récupère le datetime de la table data_NPM + # Convert to a datetime object + dt_object = datetime.strptime(datetime_measure_PM, '%Y-%m-%d %H:%M:%S') + # Convert to InfluxDB RFC3339 format with UTC 'Z' suffix + influx_timestamp = dt_object.strftime('%Y-%m-%dT%H:%M:%SZ') + PM1 = last_row[1] PM25 = last_row[2] PM10 = last_row[3] @@ -358,7 +372,7 @@ try: #3. Send to endpoint (with device ID) print("Send data (POST REQUEST):") - command= f'AT+UHTTPC={aircarto_profile_id},4,"/pro_4G/data.php?sensor_id={device_id}&datetime=000","server_response.txt","sensordata_csv.json",4\r' + command= f'AT+UHTTPC={aircarto_profile_id},4,"/pro_4G/data.php?sensor_id={device_id}&datetime={influx_timestamp}","server_response.txt","sensordata_csv.json",4\r' ser_sara.write(command.encode('utf-8')) response_SARA_3 = read_complete_response(ser_sara, timeout=5, end_of_response_timeout=120, wait_for_lines=["+UUHTTPCR", "+CME ERROR"], debug=True) diff --git a/sqlite/read.py b/sqlite/read.py index 94039ce..6a283ad 100755 --- a/sqlite/read.py +++ b/sqlite/read.py @@ -6,11 +6,16 @@ |____/ \__\_\_____|_|\__\___| Script to read data from a sqlite database -/usr/bin/python3 /var/www/nebuleair_pro_4g/sqlite/read.py +/usr/bin/python3 /var/www/nebuleair_pro_4g/sqlite/read.py data_NPM 10 ''' import sqlite3 +import sys +parameter = sys.argv[1:] # Exclude the script name +#print("Parameters received:") +table_name=parameter[0] +limit_num=parameter[1] # Connect to the SQLite database conn = sqlite3.connect("/var/www/nebuleair_pro_4g/sqlite/sensors.db") @@ -18,8 +23,15 @@ cursor = conn.cursor() # Retrieve the last 10 sensor readings #cursor.execute("SELECT * FROM data_NPM ORDER BY timestamp DESC LIMIT 10") -cursor.execute("SELECT * FROM data_BME280 ORDER BY timestamp DESC LIMIT 10") +#cursor.execute("SELECT * FROM data_BME280 ORDER BY timestamp DESC LIMIT 10") #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,)) + rows = cursor.fetchall() rows.reverse() # Reverse the order in Python (to get ascending order)