This commit is contained in:
Your Name
2025-02-20 15:30:34 +01:00
parent d5f1acc025
commit 725ee971c7
38 changed files with 405 additions and 84 deletions

9
.gitignore vendored
View File

@@ -1,5 +1,4 @@
logs/app.log logs/*.log
logs/loop.log
deviceID.txt deviceID.txt
loop/loop.log loop/loop.log
loop/data.json loop/data.json
@@ -7,4 +6,8 @@ config.json
.ssh/ .ssh/
matrix/input.txt matrix/input.txt
matrix/input_NPM.txt matrix/input_NPM.txt
matrix/input_MHZ16.txt matrix/input_MHZ16.txt
wifi_list.csv
*.lock
sqlite/*.db
tests/

View File

@@ -1,4 +1,10 @@
''' '''
____ ___ ____
/ ___/ _ \___ \
| | | | | |__) |
| |__| |_| / __/
\____\___/_____|
Script to get CO2 values Script to get CO2 values
need parameter: CO2_port need parameter: CO2_port
/usr/bin/python3 /var/www/moduleair_pro_4g/MH-Z19/get_data.py ttyAMA4 /usr/bin/python3 /var/www/moduleair_pro_4g/MH-Z19/get_data.py ttyAMA4

View File

@@ -1,4 +1,10 @@
''' '''
____ ___ ____
/ ___/ _ \___ \
| | | | | |__) |
| |__| |_| / __/
\____\___/_____|
Script to get CO2 values and write it to text file Script to get CO2 values and write it to text file
need parameter: CO2_port need parameter: CO2_port
/usr/bin/python3 /var/www/moduleair_pro_4g/MH-Z19/write_data.py ttyAMA4 /usr/bin/python3 /var/www/moduleair_pro_4g/MH-Z19/write_data.py ttyAMA4

View File

@@ -1,7 +1,7 @@
''' '''
Script to get NPM firmware version Script to get NPM firmware version
need parameter: port need parameter: port
/usr/bin/python3 /var/www/nebuleair_pro_4g/NPM/firmware_version.py ttyAMA5 /usr/bin/python3 /var/www/moduleair_pro_4g/NPM/firmware_version.py ttyAMA5
''' '''
import serial import serial

View File

@@ -7,7 +7,7 @@
Script to get NPM values Script to get NPM values
need parameter: port need parameter: port
/usr/bin/python3 /var/www/nebuleair_pro_4g/NPM/get_data.py ttyAMA5 /usr/bin/python3 /var/www/moduleair_pro_4g/NPM/get_data.py ttyAMA5
''' '''
import serial import serial

View File

@@ -7,7 +7,7 @@
Script to get NPM data via Modbus Script to get NPM data via Modbus
need parameter: port need parameter: port
/usr/bin/python3 /var/www/nebuleair_pro_4g/NPM/get_data_modbus.py /usr/bin/python3 /var/www/moduleair_pro_4g/NPM/get_data_modbus.py
Modbus RTU Modbus RTU
[Slave Address][Function Code][Starting Address][Quantity of Registers][CRC] [Slave Address][Function Code][Starting Address][Quantity of Registers][CRC]

View File

@@ -7,7 +7,7 @@
Script to get NPM data via Modbus Script to get NPM data via Modbus
need parameter: port need parameter: port
/usr/bin/python3 /var/www/nebuleair_pro_4g/NPM/get_data_modbus_v2.py /usr/bin/python3 /var/www/moduleair_pro_4g/NPM/get_data_modbus_v2.py
Modbus RTU Modbus RTU
[Slave Address][Function Code][Starting Address][Quantity of Registers][CRC] [Slave Address][Function Code][Starting Address][Quantity of Registers][CRC]

View File

@@ -9,7 +9,7 @@ Script to get NPM data via Modbus
Improved version with data stream lenght check Improved version with data stream lenght check
/usr/bin/python3 /var/www/nebuleair_pro_4g/NPM/get_data_modbus_v3.py /usr/bin/python3 /var/www/moduleair_pro_4g/NPM/get_data_modbus_v3.py
Modbus RTU Modbus RTU
[Slave Address][Function Code][Starting Address][Quantity of Registers][CRC] [Slave Address][Function Code][Starting Address][Quantity of Registers][CRC]

View File

@@ -7,7 +7,7 @@
Script to get NPM values: ONLY temp and hum Script to get NPM values: ONLY temp and hum
need parameter: port need parameter: port
/usr/bin/python3 /var/www/nebuleair_pro_4g/NPM/get_data_temp_hum.py ttyAMA5 /usr/bin/python3 /var/www/moduleair_pro_4g/NPM/get_data_temp_hum.py ttyAMA5
''' '''
import serial import serial

View File

@@ -9,7 +9,7 @@ Script to get NPM values (PM1, PM2.5 and PM10)
PM and the sensor temp/hum PM and the sensor temp/hum
And store them inside sqlite database And store them inside sqlite database
Uses RTC module for timing (from SQLite db) Uses RTC module for timing (from SQLite db)
/usr/bin/python3 /var/www/nebuleair_pro_4g/NPM/get_data_v2.py /usr/bin/python3 /var/www/moduleair_pro_4g/NPM/get_data_v2.py
''' '''
import serial import serial

View File

@@ -1,6 +1,6 @@
''' '''
Check if the main loop is running Check if the main loop is running
/usr/bin/python3 /var/www/nebuleair_pro_4g/tests/check_running.py /usr/bin/python3 /var/www/moduleair_pro_4g/tests/check_running.py
''' '''
import psutil import psutil
import json import json
@@ -12,7 +12,7 @@ def is_script_running(script_name):
return True # Script is running return True # Script is running
return False # Script is not running return False # Script is not running
script_to_check = "/var/www/nebuleair_pro_4g/loop/SARA_send_data_v2.py" script_to_check = "/var/www/moduleair_pro_4g/loop/SARA_send_data_v2.py"
# Determine script status # Determine script status
is_running = is_script_running(script_to_check) is_running = is_script_running(script_to_check)

View File

@@ -1,13 +1,13 @@
''' '''
Script to see if the SARA-R410 is running Script to see if the SARA-R410 is running
ex: ex:
python3 /var/www/nebuleair_pro_4g/SARA/sara.py ttyAMA2 AT+CCID? 2 python3 /var/www/moduleair_pro_4g/SARA/sara.py ttyAMA2 AT+CCID? 2
ex 2 (turn on blue light): ex 2 (turn on blue light):
python3 /var/www/nebuleair_pro_4g/SARA/sara.py ttyAMA2 AT+UGPIOC=16,2 2 python3 /var/www/moduleair_pro_4g/SARA/sara.py ttyAMA2 AT+UGPIOC=16,2 2
ex 3 (reconnect network) ex 3 (reconnect network)
python3 /var/www/nebuleair_pro_4g/SARA/sara.py ttyAMA2 AT+COPS=1,2,20801 20 python3 /var/www/moduleair_pro_4g/SARA/sara.py ttyAMA2 AT+COPS=1,2,20801 20
ex 4 (get HTTP Profiles) ex 4 (get HTTP Profiles)
python3 /var/www/nebuleair_pro_4g/SARA/sara.py ttyAMA2 AT+UHTTP? 2 python3 /var/www/moduleair_pro_4g/SARA/sara.py ttyAMA2 AT+UHTTP? 2
''' '''
@@ -33,7 +33,7 @@ def load_config(config_file):
return {} return {}
# Define the config file path # Define the config file path
config_file = '/var/www/nebuleair_pro_4g/config.json' config_file = '/var/www/moduleair_pro_4g/config.json'
# Load the configuration data # Load the configuration data
config = load_config(config_file) config = load_config(config_file)
# Access the shared variables # Access the shared variables

View File

@@ -1,6 +1,6 @@
''' '''
Script to connect SARA-R410 to network SARA-R410 Script to connect SARA-R410 to network SARA-R410
python3 /var/www/nebuleair_pro_4g/SARA/sara_connectNetwork.py ttyAMA2 20801 10 python3 /var/www/moduleair_pro_4g/SARA/sara_connectNetwork.py ttyAMA2 20801 10
AT+COPS=1,2,20801 AT+COPS=1,2,20801
mode->1 pour manual mode->1 pour manual
@@ -30,7 +30,7 @@ def load_config(config_file):
return {} return {}
# Define the config file path # Define the config file path
config_file = '/var/www/nebuleair_pro_4g/config.json' config_file = '/var/www/moduleair_pro_4g/config.json'
# Load the configuration data # Load the configuration data
config = load_config(config_file) config = load_config(config_file)
# Access the shared variables # Access the shared variables

View File

@@ -22,7 +22,7 @@ def load_config(config_file):
return {} return {}
# Define the config file path # Define the config file path
config_file = '/var/www/nebuleair_pro_4g/config.json' config_file = '/var/www/moduleair_pro_4g/config.json'
# Load the configuration data # Load the configuration data
config = load_config(config_file) config = load_config(config_file)
# Access the shared variables # Access the shared variables

View File

@@ -22,7 +22,7 @@ def load_config(config_file):
return {} return {}
# Define the config file path # Define the config file path
config_file = '/var/www/nebuleair_pro_4g/config.json' config_file = '/var/www/moduleair_pro_4g/config.json'
# Load the configuration data # Load the configuration data
config = load_config(config_file) config = load_config(config_file)
# Access the shared variables # Access the shared variables

View File

@@ -23,7 +23,7 @@ def load_config(config_file):
return {} return {}
# Define the config file path # Define the config file path
config_file = '/var/www/nebuleair_pro_4g/config.json' config_file = '/var/www/moduleair_pro_4g/config.json'
# Load the configuration data # Load the configuration data
config = load_config(config_file) config = load_config(config_file)
# Access the shared variables # Access the shared variables

View File

@@ -2,7 +2,7 @@
Script to connect SARA-R410 to APN Script to connect SARA-R410 to APN
AT+CGDCONT=1,"IP","data.mono" AT+CGDCONT=1,"IP","data.mono"
/usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_setAPN.py ttyAMA2 data.mono 2 /usr/bin/python3 /var/www/moduleair_pro_4g/SARA/sara_setAPN.py ttyAMA2 data.mono 2
''' '''
import serial import serial
@@ -27,7 +27,7 @@ def load_config(config_file):
return {} return {}
# Define the config file path # Define the config file path
config_file = '/var/www/nebuleair_pro_4g/config.json' config_file = '/var/www/moduleair_pro_4g/config.json'
# Load the configuration data # Load the configuration data
config = load_config(config_file) config = load_config(config_file)
# Access the shared variables # Access the shared variables

View File

@@ -1,11 +1,11 @@
''' '''
Script to set the URL for a HTTP request Script to set the URL for a HTTP request
Ex: Ex:
/usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_setURL.py ttyAMA2 data.nebuleair.fr 0 /usr/bin/python3 /var/www/moduleair_pro_4g/SARA/sara_setURL.py ttyAMA2 data.moduleair.fr 0
To do: need to add profile id as parameter To do: need to add profile id as parameter
First profile id: First profile id:
AT+UHTTP=0,1,"data.nebuleair.fr" AT+UHTTP=0,1,"data.moduleair.fr"
Second profile id: Second profile id:
AT+UHTTP=1,1,"api-prod.uspot.probesys.net" AT+UHTTP=1,1,"api-prod.uspot.probesys.net"
''' '''
@@ -33,7 +33,7 @@ def load_config(config_file):
return {} return {}
# Define the config file path # Define the config file path
config_file = '/var/www/nebuleair_pro_4g/config.json' config_file = '/var/www/moduleair_pro_4g/config.json'
# Load the configuration data # Load the configuration data
config = load_config(config_file) config = load_config(config_file)
# Access the shared variables # Access the shared variables

View File

@@ -1,11 +1,11 @@
''' '''
Script to set the URL for a HTTP request Script to set the URL for a HTTP request
Ex: Ex:
/usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_setURL_uSpot_noSSL.py ttyAMA2 api-prod.uspot.probesys.net /usr/bin/python3 /var/www/moduleair_pro_4g/SARA/sara_setURL_uSpot_noSSL.py ttyAMA2 api-prod.uspot.probesys.net
To do: need to add profile id as parameter To do: need to add profile id as parameter
First profile id: First profile id:
AT+UHTTP=0,1,"data.nebuleair.fr" AT+UHTTP=0,1,"data.moduleair.fr"
Second profile id: Second profile id:
AT+UHTTP=1,1,"api-prod.uspot.probesys.net" AT+UHTTP=1,1,"api-prod.uspot.probesys.net"
''' '''
@@ -51,7 +51,7 @@ def load_config(config_file):
return {} return {}
# Define the config file path # Define the config file path
config_file = '/var/www/nebuleair_pro_4g/config.json' config_file = '/var/www/moduleair_pro_4g/config.json'
# Load the configuration data # Load the configuration data
config = load_config(config_file) config = load_config(config_file)
# Access the shared variables # Access the shared variables

View File

@@ -22,7 +22,7 @@ def load_config(config_file):
return {} return {}
# Define the config file path # Define the config file path
config_file = '/var/www/nebuleair_pro_4g/config.json' config_file = '/var/www/moduleair_pro_4g/config.json'
# Load the configuration data # Load the configuration data
config = load_config(config_file) config = load_config(config_file)
# Access the shared variables # Access the shared variables

View File

@@ -1,8 +1,14 @@
{ {
"loop_log": true, "modem_config_mode": false,
"boot_log": true, "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": true,
"sqlite/flush_old_data.py": true,
"deviceID": "XXXXX", "deviceID": "XXXXX",
"SaraR4_baudrate": 115200, "SaraR4_baudrate": 115200,
"NPM_solo_port": "/dev/ttyAMA3",
"NextPM_ports": ["ttyAMA3"], "NextPM_ports": ["ttyAMA3"],
"CO2_serial": true, "CO2_serial": true,
"sensirion_SFA30": false, "sensirion_SFA30": false,

View File

@@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NebuleAir</title> <title>ModuleAir</title>
<link rel="stylesheet" href="assets/css/bootstrap.min.css"> <link rel="stylesheet" href="assets/css/bootstrap.min.css">
<style> <style>
body { body {

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 KiB

View File

@@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NebuleAir</title> <title>ModuleAir</title>
<link rel="stylesheet" href="assets/css/bootstrap.min.css"> <link rel="stylesheet" href="assets/css/bootstrap.min.css">
<style> <style>
body { body {

View File

@@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NebuleAir</title> <title>ModuleAir</title>
<link rel="stylesheet" href="assets/css/bootstrap.min.css"> <link rel="stylesheet" href="assets/css/bootstrap.min.css">
<script src="assets/js/chart.js"></script> <!-- Local Chart.js --> <script src="assets/js/chart.js"></script> <!-- Local Chart.js -->

View File

@@ -7,7 +7,7 @@ header("Pragma: no-cache");
$type=$_GET['type']; $type=$_GET['type'];
if ($type == "get_npm_sqlite_data") { if ($type == "get_npm_sqlite_data") {
$database_path = "/var/www/nebuleair_pro_4g/sqlite/sensors.db"; $database_path = "/var/www/moduleair_pro_4g/sqlite/sensors.db";
//echo "Getting data from sqlite database"; //echo "Getting data from sqlite database";
try { try {
$db = new PDO("sqlite:$database_path"); $db = new PDO("sqlite:$database_path");
@@ -45,7 +45,7 @@ if ($type == "update_config") {
} }
if ($type == "getModem_busy") { if ($type == "getModem_busy") {
$command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/check_running.py'; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/SARA/check_running.py';
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} }
@@ -56,7 +56,7 @@ if ($type == "RTC_time") {
} }
if ($type == "sys_RTC_module_time") { if ($type == "sys_RTC_module_time") {
$command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/RTC/read.py'; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/RTC/read.py';
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} }
@@ -68,7 +68,7 @@ if ($type == "git_pull") {
} }
if ($type == "set_RTC_withNTP") { if ($type == "set_RTC_withNTP") {
$command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/RTC/set_with_NTP.py'; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/RTC/set_with_NTP.py';
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} }
@@ -84,7 +84,7 @@ if ($type == "set_RTC_withBrowser") {
$rtc_time = date('Y-m-d H:i:s', strtotime($time)); $rtc_time = date('Y-m-d H:i:s', strtotime($time));
// Execute Python script to update the RTC // Execute Python script to update the RTC
$command = escapeshellcmd("sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/RTC/set_with_browserTime.py '$rtc_time'"); $command = escapeshellcmd("sudo /usr/bin/python3 /var/www/moduleair_pro_4g/RTC/set_with_browserTime.py '$rtc_time'");
$output = shell_exec($command); $output = shell_exec($command);
if ($output === null) { if ($output === null) {
echo json_encode(['success' => false, 'message' => 'Failed to update RTC']); echo json_encode(['success' => false, 'message' => 'Failed to update RTC']);
@@ -95,7 +95,7 @@ if ($type == "set_RTC_withBrowser") {
if ($type == "clear_loopLogs") { if ($type == "clear_loopLogs") {
$command = 'truncate -s 0 /var/www/nebuleair_pro_4g/logs/loop.log'; $command = 'truncate -s 0 /var/www/moduleair_pro_4g/logs/loop.log';
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} }
@@ -103,7 +103,7 @@ if ($type == "clear_loopLogs") {
if ($type == "database_size") { if ($type == "database_size") {
// Path to the SQLite database file // Path to the SQLite database file
$databasePath = '/var/www/nebuleair_pro_4g/sqlite/sensors.db'; $databasePath = '/var/www/moduleair_pro_4g/sqlite/sensors.db';
// Check if the file exists // Check if the file exists
if (file_exists($databasePath)) { if (file_exists($databasePath)) {
@@ -172,7 +172,7 @@ if ($type == "reboot") {
if ($type == "npm") { if ($type == "npm") {
$port=$_GET['port']; $port=$_GET['port'];
$command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/NPM/get_data.py ' . $port; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/NPM/get_data.py ' . $port;
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} }
@@ -180,19 +180,19 @@ if ($type == "npm") {
if ($type == "envea") { if ($type == "envea") {
$port=$_GET['port']; $port=$_GET['port'];
$name=$_GET['name']; $name=$_GET['name'];
$command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/envea/read_value.py ' . $port; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/envea/read_value.py ' . $port;
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} }
if ($type == "noise") { if ($type == "noise") {
$command = '/var/www/nebuleair_pro_4g/sound_meter/sound_meter'; $command = '/var/www/moduleair_pro_4g/sound_meter/sound_meter';
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} }
if ($type == "BME280") { if ($type == "BME280") {
$command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/BME280/read.py'; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/BME280/read.py';
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} }
@@ -204,13 +204,13 @@ if ($type == "table_mesure") {
$download=$_GET['download']; $download=$_GET['download'];
if ($download==="false") { if ($download==="false") {
$command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/sqlite/read.py '.$table.' '.$limit; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/sqlite/read.py '.$table.' '.$limit;
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} else{ } else{
$start_date=$_GET['start_date']; $start_date=$_GET['start_date'];
$end_date=$_GET['end_date']; $end_date=$_GET['end_date'];
$command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/sqlite/read_select_date.py '.$table.' '.$start_date.' '.$end_date; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/sqlite/read_select_date.py '.$table.' '.$start_date.' '.$end_date;
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} }
@@ -223,7 +223,7 @@ if ($type == "sara") {
$sara_command=$_GET['command']; $sara_command=$_GET['command'];
$sara_command = escapeshellcmd($sara_command); $sara_command = escapeshellcmd($sara_command);
$timeout=$_GET['timeout']; $timeout=$_GET['timeout'];
$command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara.py ' . $port . ' ' . $sara_command . ' ' . $timeout; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/SARA/sara.py ' . $port . ' ' . $sara_command . ' ' . $timeout;
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} }
@@ -232,7 +232,7 @@ if ($type == "sara") {
if ($type == "sara_getMQTT_config") { if ($type == "sara_getMQTT_config") {
$port=$_GET['port']; $port=$_GET['port'];
$timeout=$_GET['timeout']; $timeout=$_GET['timeout'];
$command = '/usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/MQTT/get_config.py ' . $port . ' ' . $timeout; $command = '/usr/bin/python3 /var/www/moduleair_pro_4g/SARA/MQTT/get_config.py ' . $port . ' ' . $timeout;
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} }
@@ -242,7 +242,7 @@ if ($type == "sara_getMQTT_login_logout") {
$port=$_GET['port']; $port=$_GET['port'];
$timeout=$_GET['timeout']; $timeout=$_GET['timeout'];
$login_logout=$_GET['login_logout']; $login_logout=$_GET['login_logout'];
$command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/MQTT/login_logout.py ' . $port . ' ' . $login_logout . ' ' . $timeout; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/SARA/MQTT/login_logout.py ' . $port . ' ' . $login_logout . ' ' . $timeout;
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} }
@@ -252,7 +252,7 @@ if ($type == "sara_MQTT_publish") {
$port=$_GET['port']; $port=$_GET['port'];
$timeout=$_GET['timeout']; $timeout=$_GET['timeout'];
$message=$_GET['message']; $message=$_GET['message'];
$command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/MQTT/publish.py ' . $port . ' ' . $message . ' ' . $timeout; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/SARA/MQTT/publish.py ' . $port . ' ' . $message . ' ' . $timeout;
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} }
@@ -262,11 +262,11 @@ if ($type == "sara_connectNetwork") {
$port=$_GET['port']; $port=$_GET['port'];
$timeout=$_GET['timeout']; $timeout=$_GET['timeout'];
$networkID=$_GET['networkID']; $networkID=$_GET['networkID'];
$command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_connectNetwork.py ' . $port . ' ' . $networkID . ' ' . $timeout; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/SARA/sara_connectNetwork.py ' . $port . ' ' . $networkID . ' ' . $timeout;
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
#save to config.json #save to config.json
$configFile = '/var/www/nebuleair_pro_4g/config.json'; $configFile = '/var/www/moduleair_pro_4g/config.json';
// Read the JSON file // Read the JSON file
$jsonData = file_get_contents($configFile); $jsonData = file_get_contents($configFile);
// Decode JSON data into an associative array // Decode JSON data into an associative array
@@ -298,7 +298,7 @@ if ($type == "sara_setURL") {
$port=$_GET['port']; $port=$_GET['port'];
$url=$_GET['url']; $url=$_GET['url'];
$profile_id = 2; $profile_id = 2;
$command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_setURL.py ' . $port . ' ' . $url . ' ' . $profile_id; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/SARA/sara_setURL.py ' . $port . ' ' . $url . ' ' . $profile_id;
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} }
@@ -308,7 +308,7 @@ if ($type == "sara_APN") {
$port=$_GET['port']; $port=$_GET['port'];
$timeout=$_GET['timeout']; $timeout=$_GET['timeout'];
$APN_address=$_GET['APN_address']; $APN_address=$_GET['APN_address'];
$command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_setAPN.py ' . $port . ' ' . $APN_address . ' ' . $timeout; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/SARA/sara_setAPN.py ' . $port . ' ' . $APN_address . ' ' . $timeout;
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} }
@@ -321,15 +321,15 @@ if ($type == "sara_writeMessage") {
$type2=$_GET['type2']; $type2=$_GET['type2'];
if ($type2 === "write") { if ($type2 === "write") {
$command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_writeMessage.py ' . $port . ' ' . $message; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/SARA/sara_writeMessage.py ' . $port . ' ' . $message;
$output = shell_exec($command); $output = shell_exec($command);
} }
if ($type2 === "read") { if ($type2 === "read") {
$command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_readMessage.py ' . $port . ' ' . $message; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/SARA/sara_readMessage.py ' . $port . ' ' . $message;
$output = shell_exec($command); $output = shell_exec($command);
} }
if ($type2 === "erase") { if ($type2 === "erase") {
$command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_eraseMessage.py ' . $port . ' ' . $message; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/SARA/sara_eraseMessage.py ' . $port . ' ' . $message;
$output = shell_exec($command); $output = shell_exec($command);
} }
@@ -342,7 +342,7 @@ if ($type == "sara_sendMessage") {
$endpoint=$_GET['endpoint']; $endpoint=$_GET['endpoint'];
$endpoint = escapeshellcmd($endpoint); $endpoint = escapeshellcmd($endpoint);
$profile_id = 2; $profile_id = 2;
$command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_sendMessage.py ' . $port . ' ' . $endpoint. ' ' . $profile_id; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/SARA/sara_sendMessage.py ' . $port . ' ' . $endpoint. ' ' . $profile_id;
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} }
@@ -394,8 +394,8 @@ if ($type == "wifi_connect") {
echo "You will be disconnected. If connection is successfull you can find the device on your local network."; echo "You will be disconnected. If connection is successfull you can find the device on your local network.";
$script_path = '/var/www/nebuleair_pro_4g/connexion.sh'; $script_path = '/var/www/moduleair_pro_4g/connexion.sh';
$log_file = '/var/www/nebuleair_pro_4g/logs/app.log'; $log_file = '/var/www/moduleair_pro_4g/logs/app.log';
shell_exec("$script_path $SSID $PASS >> $log_file 2>&1 &"); shell_exec("$script_path $SSID $PASS >> $log_file 2>&1 &");
#$output = shell_exec('sudo nmcli connection down Hotspot'); #$output = shell_exec('sudo nmcli connection down Hotspot');
@@ -407,7 +407,7 @@ if ($type == "wifi_connect") {
if ($type == "wifi_scan") { if ($type == "wifi_scan") {
// Set the path to your CSV file // Set the path to your CSV file
$csvFile = '/var/www/nebuleair_pro_4g/wifi_list.csv'; $csvFile = '/var/www/moduleair_pro_4g/wifi_list.csv';
// Initialize an array to hold the JSON data // Initialize an array to hold the JSON data
$jsonData = []; $jsonData = [];

View File

@@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NebuleAir</title> <title>ModuleAir</title>
<link rel="stylesheet" href="assets/css/bootstrap.min.css"> <link rel="stylesheet" href="assets/css/bootstrap.min.css">
<style> <style>
body { body {

View File

@@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NebuleAir</title> <title>ModuleAir</title>
<link rel="stylesheet" href="assets/css/bootstrap.min.css"> <link rel="stylesheet" href="assets/css/bootstrap.min.css">
<style> <style>
body { body {

View File

@@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NebuleAir</title> <title>ModuleAir</title>
<link rel="stylesheet" href="assets/css/bootstrap.min.css"> <link rel="stylesheet" href="assets/css/bootstrap.min.css">
<style> <style>
body { body {

View File

@@ -51,7 +51,7 @@
<!-- 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"> ModuleAir</span>
</div> </div>

View File

@@ -2,7 +2,7 @@
<nav class="navbar navbar-dark fixed-top" style="background-color: #8d8d8f;" id="topbar"> <nav class="navbar navbar-dark fixed-top" style="background-color: #8d8d8f;" id="topbar">
<div class="container-fluid"> <div class="container-fluid">
<a class="navbar-brand" href="#"> <a class="navbar-brand" href="#">
<img src="assets/img/LogoNebuleAir.png" alt="Logo" height="30" class="d-inline-block align-text-top"> <img src="assets/img/logoModuleAirColor_long.png" alt="Logo" height="30" class="d-inline-block align-text-top">
</a> </a>
<div class="d-flex"> <div class="d-flex">
<button class="btn btn-outline-light d-md-none me-2" type="button" data-bs-toggle="offcanvas" data-bs-target="#sidebarOffcanvas" aria-controls="sidebarOffcanvas" aria-label="Toggle Sidebar"></button> <button class="btn btn-outline-light d-md-none me-2" type="button" data-bs-toggle="offcanvas" data-bs-target="#sidebarOffcanvas" aria-controls="sidebarOffcanvas" aria-label="Toggle Sidebar"></button>

View File

@@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NebuleAir</title> <title>ModuleAir</title>
<link rel="stylesheet" href="assets/css/bootstrap.min.css"> <link rel="stylesheet" href="assets/css/bootstrap.min.css">
<style> <style>
body { body {

View File

@@ -15,15 +15,15 @@ Main loop to gather data from sensor inside SQLite database:
and send it to AirCarto servers via SARA R4 HTTP post requests and send it to AirCarto servers via SARA R4 HTTP post requests
also send the timestamp (already stored inside the DB) ! also send the timestamp (already stored inside the DB) !
/usr/bin/python3 /var/www/nebuleair_pro_4g/loop/SARA_send_data_v2.py /usr/bin/python3 /var/www/moduleair_pro_4g/loop/SARA_send_data_v2.py
ATTENTION: ATTENTION:
# This script is triggered every minutes by /var/www/nebuleair_pro_4g/master.py (as a service) # This script is triggered every minutes by /var/www/moduleair_pro_4g/master.py (as a service)
CSV PAYLOAD (AirCarto Servers) CSV PAYLOAD (AirCarto Servers)
Endpoint: Endpoint:
data.nebuleair.fr data.moduleair.fr
/pro_4G/data.php?sensor_id={device_id}&timestamp={rtc_module_time} /pro_4G/data.php?sensor_id={device_id}&timestamp={rtc_module_time}
ATTENTION : do not change order ! ATTENTION : do not change order !
@@ -51,13 +51,13 @@ CSV PAYLOAD (AirCarto Servers)
19 -> NPM hum inside 19 -> NPM hum inside
JSON PAYLOAD (Micro-Spot Servers) JSON PAYLOAD (Micro-Spot Servers)
Same as NebuleAir wifi Same as moduleair wifi
Endpoint: Endpoint:
api-prod.uspot.probesys.net api-prod.uspot.probesys.net
nebuleair?token=2AFF6dQk68daFZ moduleair?token=2AFF6dQk68daFZ
port 443 port 443
{"nebuleairid": "82D25549434", {"moduleairid": "82D25549434",
"software_version": "ModuleAirV2-V1-042022", "software_version": "ModuleAirV2-V1-042022",
"sensordatavalues": "sensordatavalues":
[ [
@@ -113,11 +113,11 @@ if uptime_seconds < 120:
print(f"System just booted ({uptime_seconds:.2f} seconds uptime), skipping execution.") print(f"System just booted ({uptime_seconds:.2f} seconds uptime), skipping execution.")
sys.exit() sys.exit()
#Payload CSV to be sent to data.nebuleair.fr #Payload CSV to be sent to data.moduleair.fr
payload_csv = [None] * 25 payload_csv = [None] * 25
#Payload JSON to be sent to uSpot #Payload JSON to be sent to uSpot
payload_json = { payload_json = {
"nebuleairid": "XXX", "moduleairid": "XXX",
"software_version": "ModuleAirV2-V1-042022", "software_version": "ModuleAirV2-V1-042022",
"sensordatavalues": [] # Empty list to start with "sensordatavalues": [] # Empty list to start with
} }
@@ -127,7 +127,7 @@ aircarto_profile_id = 0
uSpot_profile_id = 1 uSpot_profile_id = 1
# database connection # database connection
conn = sqlite3.connect("/var/www/nebuleair_pro_4g/sqlite/sensors.db") conn = sqlite3.connect("/var/www/moduleair_pro_4g/sqlite/sensors.db")
cursor = conn.cursor() cursor = conn.cursor()
def blink_led(pin, blink_count, delay=1): def blink_led(pin, blink_count, delay=1):
@@ -196,7 +196,7 @@ def update_json_key(file_path, key, value):
print(f"Error updating the JSON file: {e}") print(f"Error updating the JSON file: {e}")
# Define the config file path # Define the config file path
config_file = '/var/www/nebuleair_pro_4g/config.json' config_file = '/var/www/moduleair_pro_4g/config.json'
# Load the configuration data # Load the configuration data
config = load_config(config_file) config = load_config(config_file)
@@ -204,7 +204,7 @@ baudrate = config.get('SaraR4_baudrate', 115200) #baudrate du sara R4
device_id = config.get('deviceID', '').upper() #device ID en maj device_id = config.get('deviceID', '').upper() #device ID en maj
bme_280_config = config.get('BME280/get_data_v2.py', False) #présence du BME280 bme_280_config = config.get('BME280/get_data_v2.py', False) #présence du BME280
envea_cairsens= config.get('envea/read_value_v2.py', False) envea_cairsens= config.get('envea/read_value_v2.py', False)
send_aircarto = config.get('send_aircarto', True) #envoi sur AirCarto (data.nebuleair.fr) send_aircarto = config.get('send_aircarto', True) #envoi sur AirCarto (data.moduleair.fr)
send_uSpot = config.get('send_uSpot', False) #envoi sur MicroSpot () send_uSpot = config.get('send_uSpot', False) #envoi sur MicroSpot ()
selected_networkID = config.get('SARA_R4_neworkID', '') selected_networkID = config.get('SARA_R4_neworkID', '')
npm_5channel = config.get('NextPM_5channels', False) #5 canaux du NPM npm_5channel = config.get('NextPM_5channels', False) #5 canaux du NPM
@@ -212,7 +212,7 @@ npm_5channel = config.get('NextPM_5channels', False) #5 canaux du NPM
modem_config_mode = config.get('modem_config_mode', False) #modem 4G en mode configuration modem_config_mode = config.get('modem_config_mode', False) #modem 4G en mode configuration
#update device id in the payload json #update device id in the payload json
payload_json["nebuleairid"] = device_id payload_json["moduleairid"] = device_id
# Skip execution if modem_config_mode is true # Skip execution if modem_config_mode is true
if modem_config_mode: if modem_config_mode:
@@ -555,7 +555,7 @@ try:
#Pas forcément un moyen de résoudre le soucis #Pas forcément un moyen de résoudre le soucis
#print("resetting the URL (domain name):") #print("resetting the URL (domain name):")
#command = f'AT+UHTTP={aircarto_profile_id},1,"{url_nebuleair}"\r' #command = f'AT+UHTTP={aircarto_profile_id},1,"{url_moduleair}"\r'
#ser_sara.write(command.encode('utf-8')) #ser_sara.write(command.encode('utf-8'))
#response_SARA_31 = read_complete_response(ser_sara) #response_SARA_31 = read_complete_response(ser_sara)
#print(response_SARA_31) #print(response_SARA_31)
@@ -610,7 +610,7 @@ try:
# Handle "Operation not allowed" error # Handle "Operation not allowed" error
if error_message == "Operation not allowed": if error_message == "Operation not allowed":
print('<span style="color: orange;font-weight: bold;">❓Try Resetting the HTTP Profile❓</span>') print('<span style="color: orange;font-weight: bold;">❓Try Resetting the HTTP Profile❓</span>')
command = f'AT+UHTTP={aircarto_profile_id},1,"data.nebuleair.fr"\r' command = f'AT+UHTTP={aircarto_profile_id},1,"data.moduleair.fr"\r'
ser_sara.write(command.encode('utf-8')) ser_sara.write(command.encode('utf-8'))
responseResetHTTP_profile = read_complete_response(ser_sara, timeout=5, end_of_response_timeout=5, wait_for_lines=["OK", "+CME ERROR"], debug=True) responseResetHTTP_profile = read_complete_response(ser_sara, timeout=5, end_of_response_timeout=5, wait_for_lines=["OK", "+CME ERROR"], debug=True)
print('<p class="text-danger-emphasis">') print('<p class="text-danger-emphasis">')

85
sqlite/create_db.py Normal file
View File

@@ -0,0 +1,85 @@
'''
____ ___ _ _ _
/ ___| / _ \| | (_) |_ ___
\___ \| | | | | | | __/ _ \
___) | |_| | |___| | || __/
|____/ \__\_\_____|_|\__\___|
Script to create a sqlite database
/usr/bin/python3 /var/www/moduleair_pro_4g/sqlite/create_db.py
in case of readonly error:
sudo chmod 777 /var/www/moduleair_pro_4g/sqlite/sensors.db
'''
import sqlite3
# Connect to (or create if not existent) the database
conn = sqlite3.connect("/var/www/moduleair_pro_4g/sqlite/sensors.db")
cursor = conn.cursor()
# Create a table timer
cursor.execute("""
CREATE TABLE IF NOT EXISTS timestamp_table (
id INTEGER PRIMARY KEY CHECK (id = 1), -- Enforce single row by using fixed ID
last_updated DATETIME NOT NULL
)
""")
cursor.execute("""
INSERT INTO timestamp_table (id, last_updated) VALUES (1, CURRENT_TIMESTAMP);
""")
# Create a table NPM
cursor.execute("""
CREATE TABLE IF NOT EXISTS data_NPM (
timestamp TEXT,
PM1 REAL,
PM25 REAL,
PM10 REAL,
temp_npm REAL,
hum_npm REAL
)
""")
# Create a table BME280
cursor.execute("""
CREATE TABLE IF NOT EXISTS data_BME280 (
timestamp TEXT,
temperature REAL,
humidity REAL,
pressure REAL
)
""")
# Create a table cairsens
cursor.execute("""
CREATE TABLE IF NOT EXISTS data_envea (
timestamp TEXT,
no2 REAL,
h2s REAL,
nh3 REAL,
co REAL,
o3 REAL
)
""")
# Create a table NPM_5ch
cursor.execute("""
CREATE TABLE IF NOT EXISTS data_NPM_5channels (
timestamp TEXT,
PM_ch1 INTEGER,
PM_ch2 INTEGER,
PM_ch3 INTEGER,
PM_ch4 INTEGER,
PM_ch5 INTEGER
)
""")
# Commit and close the connection
conn.commit()
conn.close()
print("Database and table created successfully!")

71
sqlite/flush_old_data.py Normal file
View File

@@ -0,0 +1,71 @@
'''
____ ___ _ _ _
/ ___| / _ \| | (_) |_ ___
\___ \| | | | | | | __/ _ \
___) | |_| | |___| | || __/
|____/ \__\_\_____|_|\__\___|
Script to flush (delete) data from a sqlite database
/usr/bin/python3 /var/www/moduleair_pro_4g/sqlite/flush_old_data.py
Available table are
data_NPM
data_NPM_5channels
data_BME280
data_envea
timestamp_table
'''
import sqlite3
import datetime
# Connect to the SQLite database
conn = sqlite3.connect("/var/www/moduleair_pro_4g/sqlite/sensors.db")
cursor = conn.cursor()
#GET RTC TIME from SQlite
cursor.execute("SELECT * FROM timestamp_table LIMIT 1")
row = cursor.fetchone() # Get the first (and only) row
if row:
rtc_time_str = row[1] # Assuming timestamp is stored as TEXT (YYYY-MM-DD HH:MM:SS)
print(f"[INFO] Last recorded timestamp: {rtc_time_str}")
# Convert last_updated to a datetime object
last_updated = datetime.datetime.strptime(rtc_time_str, "%Y-%m-%d %H:%M:%S")
# Calculate the cutoff date (3 months before last_updated)
cutoff_date = last_updated - datetime.timedelta(days=60)
cutoff_date_str = cutoff_date.strftime("%Y-%m-%d %H:%M:%S")
print(f"[INFO] Deleting records older than: {cutoff_date_str}")
# List of tables to delete old data from
tables_to_clean = ["data_NPM", "data_NPM_5channels", "data_BME280", "data_envea"]
# Loop through each table and delete old data
for table in tables_to_clean:
delete_query = f"DELETE FROM {table} WHERE timestamp < ?"
cursor.execute(delete_query, (cutoff_date_str,))
print(f"[INFO] Deleted old records from {table}")
# **Commit changes before running VACUUM**
conn.commit()
print("[INFO] Changes committed successfully!")
# Now it's safe to run VACUUM
print("[INFO] Running VACUUM to optimize database space...")
cursor.execute("VACUUM")
print("[SUCCESS] Old data flushed successfully!")
else:
print("[ERROR] No timestamp found in timestamp_table.")
# Close the database connection
conn.close()

52
sqlite/read.py Normal file
View File

@@ -0,0 +1,52 @@
'''
____ ___ _ _ _
/ ___| / _ \| | (_) |_ ___
\___ \| | | | | | | __/ _ \
___) | |_| | |___| | || __/
|____/ \__\_\_____|_|\__\___|
Script to read data from a sqlite database
/usr/bin/python3 /var/www/moduleair_pro_4g/sqlite/read.py data_NPM 10
Available table are
data_NPM
data_NPM_5channels
data_BME280
data_envea
timestamp_table
'''
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/moduleair_pro_4g/sqlite/sensors.db")
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 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)
# Display the results
for row in rows:
print(row)
# Close the database connection
conn.close()

View File

@@ -0,0 +1,59 @@
'''
____ ___ _ _ _
/ ___| / _ \| | (_) |_ ___
\___ \| | | | | | | __/ _ \
___) | |_| | |___| | || __/
|____/ \__\_\_____|_|\__\___|
Script to read data from a sqlite database using start date and end date
/usr/bin/python3 /var/www/moduleair_pro_4g/sqlite/read_select_date.py data_NPM 2025-02-09 2025-02-11
Available table are
data_NPM
data_NPM_5channels
data_BME280
data_envea
timestamp_table
'''
import sqlite3
import sys
parameter = sys.argv[1:] # Exclude the script name
#print("Parameters received:")
table_name=parameter[0]
start_date=parameter[1]
end_date=parameter[2]
# Convert to full timestamp range
start_timestamp = f"{start_date} 00:00:00"
end_timestamp = f"{end_date} 23:59:59"
# Connect to the SQLite database
conn = sqlite3.connect("/var/www/moduleair_pro_4g/sqlite/sensors.db")
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 timestamp_table")
if table_name == "timestamp_table":
cursor.execute("SELECT * FROM timestamp_table")
else:
query = f"SELECT * FROM {table_name} WHERE timestamp BETWEEN ? AND ? ORDER BY timestamp ASC"
cursor.execute(query, (start_timestamp, end_timestamp))
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()

33
sqlite/write.py Normal file
View File

@@ -0,0 +1,33 @@
'''
____ ___ _ _ _
/ ___| / _ \| | (_) |_ ___
\___ \| | | | | | | __/ _ \
___) | |_| | |___| | || __/
|____/ \__\_\_____|_|\__\___|
Script to write data to a sqlite database
/usr/bin/python3 /var/www/moduleair_pro_4g/sqlite/write.py
'''
import sqlite3
# Connect to the SQLite database
conn = sqlite3.connect("/var/www/moduleair_pro_4g/sqlite/sensors.db")
cursor = conn.cursor()
# Insert a sample temperature reading
timestamp = "2025-10-11"
PM1 = 25.3
PM25 = 18.3
PM10 = 9.3
cursor.execute('''
INSERT INTO data (timestamp, PM1, PM25, PM10) VALUES (?,?,?,?,?)'''
, (timestamp,PM1,PM25,PM10))
# Commit and close the connection
conn.commit()
conn.close()
print("Sensor data saved successfully!")