This commit is contained in:
PaulVua
2025-02-10 10:06:16 +01:00
parent 7cac769795
commit 1cb1b05b51
10 changed files with 200 additions and 77 deletions

View File

@@ -15,9 +15,13 @@ sudo python3 /var/www/nebuleair_pro_4g/BME280/get_data_v2.py
import board import board
import busio import busio
import json import json
import sqlite3
from adafruit_bme280 import basic as adafruit_bme280 from adafruit_bme280 import basic as adafruit_bme280
# Connect to the SQLite database
conn = sqlite3.connect("/var/www/nebuleair_pro_4g/sqlite/sensors.db")
cursor = conn.cursor()
# Create I2C bus # Create I2C bus
i2c = busio.I2C(board.SCL, board.SDA) i2c = busio.I2C(board.SCL, board.SDA)
bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c, address=0x76) bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c, address=0x76)
@@ -32,12 +36,39 @@ bme280.sea_level_pressure = 1013.25 # Update this value for your location
#print(f"Pressure: {bme280.pressure:.2f} hPa") #print(f"Pressure: {bme280.pressure:.2f} hPa")
#print(f"Altitude: {bme280.altitude:.2f} m") #print(f"Altitude: {bme280.altitude:.2f} m")
temperature = round(bme280.temperature, 2)
humidity = round(bme280.humidity, 2)
pressure = round(bme280.pressure, 2)
sensor_data = { sensor_data = {
"temp": round(bme280.temperature, 2), # Temperature in °C "temp": temperature, # Temperature in °C
"hum": round(bme280.humidity, 2), # Humidity in % "hum": humidity, # Humidity in %
"press": round(bme280.pressure, 2), # Pressure in hPa "press": pressure # Pressure in hPa
} }
#GET RTC TIME from SQlite
cursor.execute("SELECT * FROM timestamp_table LIMIT 1")
row = cursor.fetchone() # Get the first (and only) row
rtc_time_str = row[1] # '2025-02-07 12:30:45'
# Convert to JSON and print # Convert to JSON and print
print(json.dumps(sensor_data, indent=4)) #print(json.dumps(sensor_data, indent=4))
#save to sqlite database
try:
cursor.execute('''
INSERT INTO data_BME280 (timestamp,temperature, humidity, pressure) VALUES (?,?,?,?)'''
, (rtc_time_str,temperature,humidity,pressure))
# Commit and close the connection
conn.commit()
#print("Sensor data saved successfully!")
except Exception as e:
print(f"Database error: {e}")
conn.close()

View File

@@ -8,7 +8,7 @@
Script to get NPM values Script to get NPM values
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 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/nebuleair_pro_4g/NPM/get_data_v2.py
''' '''
@@ -25,27 +25,6 @@ from datetime import datetime
conn = sqlite3.connect("/var/www/nebuleair_pro_4g/sqlite/sensors.db") conn = sqlite3.connect("/var/www/nebuleair_pro_4g/sqlite/sensors.db")
cursor = conn.cursor() cursor = conn.cursor()
#RTC module
DS3231_ADDR = 0x68
REG_TIME = 0x00
def bcd_to_dec(bcd):
return (bcd // 16 * 10) + (bcd % 16)
def read_time(bus):
"""Try to read and decode time from the RTC module (DS3231)."""
try:
data = bus.read_i2c_block_data(DS3231_ADDR, REG_TIME, 7)
seconds = bcd_to_dec(data[0] & 0x7F)
minutes = bcd_to_dec(data[1])
hours = bcd_to_dec(data[2] & 0x3F)
day = bcd_to_dec(data[4])
month = bcd_to_dec(data[5])
year = bcd_to_dec(data[6]) + 2000
return datetime(year, month, day, hours, minutes, seconds)
except OSError:
return None # RTC module not connected
def load_config(config_file): def load_config(config_file):
try: try:
with open(config_file, 'r') as file: with open(config_file, 'r') as file:
@@ -96,19 +75,11 @@ humidity = int.from_bytes(byte_data_temp_hum[5:7], byteorder='big') / 100.0
#print(f"PM10: {PM10}") #print(f"PM10: {PM10}")
#print(f"temp: {temperature}") #print(f"temp: {temperature}")
#print(f"hum: {humidity}") #print(f"hum: {humidity}")
#GET RTC TIME
# Read RTC time
bus = smbus2.SMBus(1)
# Try to read RTC time
rtc_time = read_time(bus)
if rtc_time:
rtc_time_str = rtc_time.strftime('%Y-%m-%d %H:%M:%S')
#print(rtc_time_str)
else:
print("Error! RTC module not connected")
rtc_time_str = "1970-01-01 00:00:00" # Default fallback time
#GET RTC TIME from SQlite
cursor.execute("SELECT * FROM timestamp_table LIMIT 1")
row = cursor.fetchone() # Get the first (and only) row
rtc_time_str = row[1] # '2025-02-07 12:30:45'
#save to sqlite database #save to sqlite database
try: try:

View File

@@ -42,7 +42,7 @@ To make things simpler we will allow all users to use "nmcli" as sudo without en
ALL ALL=(ALL) NOPASSWD: /usr/bin/nmcli, /usr/sbin/reboot ALL ALL=(ALL) NOPASSWD: /usr/bin/nmcli, /usr/sbin/reboot
www-data ALL=(ALL) NOPASSWD: /usr/bin/git pull www-data ALL=(ALL) NOPASSWD: /usr/bin/git pull
www-data ALL=(ALL) NOPASSWD: /usr/bin/ssh www-data ALL=(ALL) NOPASSWD: /usr/bin/ssh
www-data ALL=(ALL) NOPASSWD: /usr/bin/python3 *
``` ```
## Serial ## Serial

90
RTC/save_to_db.py Normal file
View File

@@ -0,0 +1,90 @@
'''
____ _____ ____
| _ \_ _/ ___|
| |_) || || |
| _ < | || |___
|_| \_\|_| \____|
Script to read time from RTC module and save it to DB
I2C connection
Address 0x68
/usr/bin/python3 /var/www/nebuleair_pro_4g/RTC/save_to_db.py
'''
import smbus2
import time
import json
from datetime import datetime
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()
# DS3231 I2C address
DS3231_ADDR = 0x68
# Registers for DS3231
REG_TIME = 0x00
def bcd_to_dec(bcd):
return (bcd // 16 * 10) + (bcd % 16)
def read_time(bus):
"""Try to read and decode time from the RTC module (DS3231)."""
try:
data = bus.read_i2c_block_data(DS3231_ADDR, REG_TIME, 7)
seconds = bcd_to_dec(data[0] & 0x7F)
minutes = bcd_to_dec(data[1])
hours = bcd_to_dec(data[2] & 0x3F)
day = bcd_to_dec(data[4])
month = bcd_to_dec(data[5])
year = bcd_to_dec(data[6]) + 2000
return datetime(year, month, day, hours, minutes, seconds)
except OSError:
return None # RTC module not connected
def main():
# Read RTC time
bus = smbus2.SMBus(1)
# Try to read RTC time
rtc_time = read_time(bus)
# Get current system time
system_time = datetime.now() #local
utc_time = datetime.utcnow() #UTC
# If RTC is not connected, set default message
# Calculate time difference (in seconds) if RTC is connected
if rtc_time:
rtc_time_str = rtc_time.strftime('%Y-%m-%d %H:%M:%S')
time_difference = int((utc_time - rtc_time).total_seconds()) # Convert to int
else:
rtc_time_str = "not connected"
time_difference = "N/A" # Not applicable
# Print both times
#print(f"RTC module Time: {rtc_time.strftime('%Y-%m-%d %H:%M:%S')}")
#print(f"Sys local Time: {system_time.strftime('%Y-%m-%d %H:%M:%S')}")
#print(f"Sys UTC Time: {utc_time.strftime('%Y-%m-%d %H:%M:%S')}")
# Create JSON output
time_data = {
"rtc_module_time":rtc_time_str,
"system_local_time": system_time.strftime('%Y-%m-%d %H:%M:%S'),
"system_utc_time": utc_time.strftime('%Y-%m-%d %H:%M:%S'),
"time_difference_seconds": time_difference
}
#print(json.dumps(time_data, indent=4))
cursor.execute("UPDATE timestamp_table SET last_updated = ? WHERE id = 1", (rtc_time_str,))
# Commit and close the connection
conn.commit()
conn.close()
#print("Sensor data saved successfully!")
if __name__ == "__main__":
main()

View File

@@ -2,9 +2,9 @@
"loop_activation": true, "loop_activation": true,
"loop_log": true, "loop_log": true,
"boot_log": true, "boot_log": true,
"NPM/get_data.py": true, "NPM/get_data_v2.py": true,
"tests/script2.py": false, "loop/SARA_send_data_v2.py": true,
"tests/script3.py": true, "RTC/save_to_db.py": true,
"deviceID": "XXXX", "deviceID": "XXXX",
"deviceName": "NebuleAir-proXXX", "deviceName": "NebuleAir-proXXX",
"SaraR4_baudrate": 115200, "SaraR4_baudrate": 115200,

View File

@@ -53,10 +53,21 @@
<main class="col-md-9 ms-sm-auto col-lg-10 offset-md-3 offset-lg-2 px-md-4"> <main class="col-md-9 ms-sm-auto col-lg-10 offset-md-3 offset-lg-2 px-md-4">
<h1 class="mt-4">Votre capteur</h1> <h1 class="mt-4">Votre capteur</h1>
<p>Bienvenue sur votre interface de configuration de votre capteur.</p> <p>Bienvenue sur votre interface de configuration de votre capteur.</p>
<div class="row mb-3"> <div class="row mb-3">
<!-- Card 1 Linux Stats --> <!-- Card NPM values -->
<div class="col-sm-4"> <div class="col-sm-4 mt-2">
<div class="card">
<div class="card-body">
<h5 class="card-title">Mesures PM</h5>
<canvas id="sensorPMChart" style="width: 100%; max-width: 600px; height: 200px;"></canvas>
</div>
</div>
</div>
<!-- Card Linux Stats -->
<div class="col-sm-4 mt-2">
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">Linux stats</h5> <h5 class="card-title">Linux stats</h5>
@@ -69,19 +80,24 @@
</div> </div>
</div> </div>
<!-- Card 2 NPM values -->
<div class="col-sm-4">
</div>
<div class="row mb-3">
<!-- Card BME values -->
<div class="col-sm-4 mt-2">
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">Mesures PM</h5> <h5 class="card-title">Mesures Temperature</h5>
<canvas id="sensorPMChart" style="width: 100%; max-width: 600px; height: 200px;"></canvas> <canvas id="sensorBME_temp" style="width: 100%; max-width: 600px; height: 200px;"></canvas>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</main> </main>
</div> </div>
</div> </div>

View File

@@ -45,7 +45,7 @@ if ($type == "update_config") {
} }
if ($type == "getModem_busy") { if ($type == "getModem_busy") {
$command = '/usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/check_running.py'; $command = 'sudo /usr/bin/python3 /var/www/nebuleair_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 = '/usr/bin/python3 /var/www/nebuleair_pro_4g/RTC/read.py'; $command = 'sudo /usr/bin/python3 /var/www/nebuleair_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 = '/usr/bin/python3 /var/www/nebuleair_pro_4g/RTC/set_with_NTP.py'; $command = 'sudo /usr/bin/python3 /var/www/nebuleair_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("/usr/bin/python3 /var/www/nebuleair_pro_4g/RTC/set_with_browserTime.py '$rtc_time'"); $command = escapeshellcmd("sudo /usr/bin/python3 /var/www/nebuleair_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']);
@@ -177,7 +177,7 @@ if ($type == "reboot") {
if ($type == "npm") { if ($type == "npm") {
$port=$_GET['port']; $port=$_GET['port'];
$command = '/usr/bin/python3 /var/www/nebuleair_pro_4g/NPM/get_data.py ' . $port; $command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/NPM/get_data.py ' . $port;
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} }
@@ -185,7 +185,7 @@ if ($type == "npm") {
if ($type == "envea") { if ($type == "envea") {
$port=$_GET['port']; $port=$_GET['port'];
$name=$_GET['name']; $name=$_GET['name'];
$command = '/usr/bin/python3 /var/www/nebuleair_pro_4g/envea/read_value.py ' . $port; $command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/envea/read_value.py ' . $port;
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} }
@@ -197,7 +197,7 @@ if ($type == "noise") {
} }
if ($type == "BME280") { if ($type == "BME280") {
$command = '/usr/bin/python3 /var/www/nebuleair_pro_4g/BME280/read.py'; $command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/BME280/read.py';
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} }
@@ -208,7 +208,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 = '/usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara.py ' . $port . ' ' . $sara_command . ' ' . $timeout; $command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara.py ' . $port . ' ' . $sara_command . ' ' . $timeout;
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} }
@@ -227,7 +227,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 = '/usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/MQTT/login_logout.py ' . $port . ' ' . $login_logout . ' ' . $timeout; $command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/MQTT/login_logout.py ' . $port . ' ' . $login_logout . ' ' . $timeout;
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} }
@@ -237,7 +237,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 = '/usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/MQTT/publish.py ' . $port . ' ' . $message . ' ' . $timeout; $command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/MQTT/publish.py ' . $port . ' ' . $message . ' ' . $timeout;
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} }
@@ -247,7 +247,7 @@ if ($type == "sara_connectNetwork") {
$port=$_GET['port']; $port=$_GET['port'];
$timeout=$_GET['timeout']; $timeout=$_GET['timeout'];
$networkID=$_GET['networkID']; $networkID=$_GET['networkID'];
$command = '/usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_connectNetwork.py ' . $port . ' ' . $networkID . ' ' . $timeout; $command = 'sudo /usr/bin/python3 /var/www/nebuleair_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
@@ -283,7 +283,7 @@ if ($type == "sara_setURL") {
$port=$_GET['port']; $port=$_GET['port'];
$url=$_GET['url']; $url=$_GET['url'];
$profile_id = 2; $profile_id = 2;
$command = '/usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_setURL.py ' . $port . ' ' . $url . ' ' . $profile_id; $command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_setURL.py ' . $port . ' ' . $url . ' ' . $profile_id;
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} }
@@ -293,7 +293,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 = '/usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_setAPN.py ' . $port . ' ' . $APN_address . ' ' . $timeout; $command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_setAPN.py ' . $port . ' ' . $APN_address . ' ' . $timeout;
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} }
@@ -306,15 +306,15 @@ if ($type == "sara_writeMessage") {
$type2=$_GET['type2']; $type2=$_GET['type2'];
if ($type2 === "write") { if ($type2 === "write") {
$command = '/usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_writeMessage.py ' . $port . ' ' . $message; $command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_writeMessage.py ' . $port . ' ' . $message;
$output = shell_exec($command); $output = shell_exec($command);
} }
if ($type2 === "read") { if ($type2 === "read") {
$command = '/usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_readMessage.py ' . $port . ' ' . $message; $command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_readMessage.py ' . $port . ' ' . $message;
$output = shell_exec($command); $output = shell_exec($command);
} }
if ($type2 === "erase") { if ($type2 === "erase") {
$command = '/usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_eraseMessage.py ' . $port . ' ' . $message; $command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_eraseMessage.py ' . $port . ' ' . $message;
$output = shell_exec($command); $output = shell_exec($command);
} }
@@ -327,7 +327,7 @@ if ($type == "sara_sendMessage") {
$endpoint=$_GET['endpoint']; $endpoint=$_GET['endpoint'];
$endpoint = escapeshellcmd($endpoint); $endpoint = escapeshellcmd($endpoint);
$profile_id = 2; $profile_id = 2;
$command = '/usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_sendMessage.py ' . $port . ' ' . $endpoint. ' ' . $profile_id; $command = 'sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_sendMessage.py ' . $port . ' ' . $endpoint. ' ' . $profile_id;
$output = shell_exec($command); $output = shell_exec($command);
echo $output; echo $output;
} }

View File

@@ -76,8 +76,9 @@ def run_script(script_name, interval):
# Define scripts and their execution intervals (seconds) # Define scripts and their execution intervals (seconds)
SCRIPTS = [ SCRIPTS = [
("NPM/get_data_v2.py", 60), # Get NPM data every 60s ("NPM/get_data_v2.py", 60), # Get NPM data every 60s
("loop/SARA_send_data_v2.py", 60), # Runs every 60 seconds ("loop/SARA_send_data_v2.py", 60), # Send data every 60 seconds
("tests/script3.py", 10), # Runs every 10 seconds ("RTC/save_to_db.py", 1), # SAVE RTC time every 1 second
("BME280/get_data_v2.py", 120) # Get BME280 data every 120 seconds
] ]
# Start threads for enabled scripts # Start threads for enabled scripts

View File

@@ -15,7 +15,19 @@ import sqlite3
conn = sqlite3.connect("/var/www/nebuleair_pro_4g/sqlite/sensors.db") conn = sqlite3.connect("/var/www/nebuleair_pro_4g/sqlite/sensors.db")
cursor = conn.cursor() cursor = conn.cursor()
# Create a table 1 # 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(""" cursor.execute("""
CREATE TABLE IF NOT EXISTS data_NPM ( CREATE TABLE IF NOT EXISTS data_NPM (
timestamp TEXT, timestamp TEXT,
@@ -27,7 +39,7 @@ CREATE TABLE IF NOT EXISTS data_NPM (
) )
""") """)
# Create a table 2 # Create a table BME280
cursor.execute(""" cursor.execute("""
CREATE TABLE IF NOT EXISTS data_BME280 ( CREATE TABLE IF NOT EXISTS data_BME280 (
timestamp TEXT, timestamp TEXT,
@@ -37,7 +49,7 @@ CREATE TABLE IF NOT EXISTS data_BME280 (
) )
""") """)
# Create a table 3 # Create a table cairsens
cursor.execute(""" cursor.execute("""
CREATE TABLE IF NOT EXISTS data_envea ( CREATE TABLE IF NOT EXISTS data_envea (
timestamp TEXT, timestamp TEXT,
@@ -49,7 +61,7 @@ CREATE TABLE IF NOT EXISTS data_envea (
) )
""") """)
# Create a table 4 # Create a table NPM_5ch
cursor.execute(""" cursor.execute("""
CREATE TABLE IF NOT EXISTS data_NPM_5channels ( CREATE TABLE IF NOT EXISTS data_NPM_5channels (
timestamp TEXT, timestamp TEXT,

View File

@@ -17,7 +17,9 @@ conn = sqlite3.connect("/var/www/nebuleair_pro_4g/sqlite/sensors.db")
cursor = conn.cursor() cursor = conn.cursor()
# Retrieve the last 10 sensor readings # Retrieve the last 10 sensor readings
cursor.execute("SELECT * FROM data_NPM ORDER BY timestamp DESC LIMIT 10") #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")
rows = cursor.fetchall() rows = cursor.fetchall()
rows.reverse() # Reverse the order in Python (to get ascending order) rows.reverse() # Reverse the order in Python (to get ascending order)