This commit is contained in:
Your Name
2025-03-26 17:17:40 +01:00
parent d0e1ad18e9
commit 76a676925d
10 changed files with 283 additions and 18 deletions

View File

@@ -74,11 +74,11 @@ def read_co2():
response = ser.read(9)
# Print the response to debug
print(f"Response: {response}")
#print(f"Response: {response}")
# Check if the response is valid (the first byte should be 0xFF)
if len(response) < 9:
print("Error: No data or incomplete data received.")
print("Error: No data or incomplete data received from co2 sensor.")
return None
if response[0] == 0xFF:
@@ -86,7 +86,7 @@ def read_co2():
co2_concentration = response[2] * 256 + response[3]
return co2_concentration
else:
print("Error reading data from sensor.")
print("Error reading data from co2 sensor.")
return None
@@ -95,12 +95,12 @@ def main():
try:
co2 = read_co2()
if co2 is not None:
print(f"CO2 Concentration: {co2} ppm")
#print(f"CO2 Concentration: {co2} ppm")
#save to file
output_file = "/var/www/moduleair_pro_4g/matrix/input_MHZ16.txt"
with open(output_file, "w") as file:
file.write(f"{co2} \n")
print(f"Data written to {output_file}")
#print(f"Data written to {output_file}")
#GET RTC TIME from SQlite
cursor.execute("SELECT * FROM timestamp_table LIMIT 1")
row = cursor.fetchone() # Get the first (and only) row

View File

@@ -66,7 +66,7 @@ def load_config():
return json.load(f)
def run_script(script_name, interval, delay=0):
"""Run a script in a synchronized loop with an optional start delay."""
"""Run a PYTHON script in a synchronized loop with an optional start delay."""
script_path = os.path.join(SCRIPT_DIR, script_name) # Build full path
next_run = time.monotonic() + delay # Apply the initial delay
@@ -80,22 +80,39 @@ def run_script(script_name, interval, delay=0):
sleep_time = max(0, next_run - time.monotonic()) # Prevent negative sleep times
time.sleep(sleep_time)
# Define scripts and their execution intervals (seconds)
SCRIPTS = [
("RTC/save_to_db.py", 1, 0), # SAVE RTC time every 1 second, no delay
("NPM/get_data_modbus_v3.py", 10, 0), # Get NPM data (modbus 5 channels) every 10s,
("envea/read_value_v2.py", 10, 0), # Get Envea data every 10s,
("MH-Z19/write_data.py", 10, 0), # Get CO2 values every 10s,
("loop/SARA_send_data_v2.py", 60, 1), # Send data every 60 seconds, with 2s delay
("BME280/get_data_v2.py", 120, 0), # Get BME280 data every 120 seconds, no delay
("sqlite/flush_old_data.py", 86400, 0) # flush old data inside db every day ()
# ✅ **Scripts that should start immediately**
IMMEDIATE_SCRIPTS = [
("RTC/save_to_db.py", 1, 0),
("NPM/get_data_modbus_v3.py", 10, 0),
("envea/read_value_v2.py", 10, 0),
("MH-Z19/write_data.py", 10, 0),
("loop/SARA_send_data_v2.py", 60, 1),
("BME280/get_data_v2.py", 120, 0),
("sqlite/flush_old_data.py", 86400, 0)
]
# Start threads for enabled scripts
for script_name, interval, delay in SCRIPTS:
# ✅ **The compiled binary that must wait for welcome_screen**
WAIT_BINARY = "/var/www/moduleair_pro_4g/matrix/test_forms" # Adjust path if needed
# 🚀 **Start all scripts that can run immediately**
for script_name, interval, delay in IMMEDIATE_SCRIPTS:
thread = threading.Thread(target=run_script, args=(script_name, interval, delay), daemon=True)
thread.start()
# 🚀 **Run welcome_screen in parallel**
print("🚀 Running welcome screen...")
welcome_process = subprocess.Popen(["sudo", "/var/www/moduleair_pro_4g/matrix/welcome_screen"])
print("✅ Welcome screen started in parallel with other scripts.")
# 🕒 **Wait for welcome_screen to finish before running WAIT_BINARY**
welcome_process.wait()
print("✅ Welcome screen finished. Starting another_screen...")
# 🚀 **Now run the compiled binary `another_screen`**
subprocess.run(["sudo", WAIT_BINARY])
print("✅ another_screen execution completed.")
# Keep the main script running
while True:
time.sleep(1)

Binary file not shown.

View File

@@ -1,4 +1,12 @@
/*
__ __ _ _____ ____ _____ __
| \/ | / \|_ _| _ \|_ _\ \/ /
| |\/| | / _ \ | | | |_) || | \ /
| | | |/ ___ \| | | _ < | | / \
|_| |_/_/ \_\_| |_| \_\___/_/\_\
Script to display a simple square on the matrix LED
sudo /var/www/moduleair_pro_4g/matrix/test_forms --led-no-hardware-pulse
@@ -25,7 +33,10 @@ int main(int argc, char *argv[]) {
defaults.row_address_type = 3;
defaults.show_refresh_rate = true;
defaults.brightness = 100;
defaults.pwm_bits = 1;
defaults.panel_type = "FM6126A";
defaults.disable_hardware_pulsing = false;
rgb_matrix::Color red(255, 0, 0); // Red color
rgb_matrix::Color bg_color(0, 0, 0); // Background color (black)

Binary file not shown.

View File

@@ -1,6 +1,13 @@
/*
__ __ _ _____ ____ _____ __
| \/ | / \|_ _| _ \|_ _\ \/ /
| |\/| | / _ \ | | | |_) || | \ /
| | | |/ ___ \| | | _ < | | / \
|_| |_/_/ \_\_| |_| \_\___/_/\_\
Script to display a simple text on the matrix LED
sudo /var/www/moduleair_pro_4g/matrix/test_text --led-no-hardware-pulse
sudo /var/www/moduleair_pro_4g/matrix/test_text
Pour compiler:
g++ -Iinclude -Llib test_text.cc -o test_text -lrgbmatrix
@@ -25,7 +32,9 @@ int main(int argc, char *argv[]) {
defaults.row_address_type=3;
defaults.show_refresh_rate = true;
defaults.brightness = 100;
defaults.pwm_bits = 1;
defaults.panel_type = "FM6126A";
defaults.disable_hardware_pulsing = false;
rgb_matrix::Color color1(255, 0, 0); // Red color for the first line
rgb_matrix::Color color2(0, 0, 255); // Blue color for the second line

BIN
matrix/welcome_screen Executable file

Binary file not shown.

96
matrix/welcome_screen.cc Normal file
View File

@@ -0,0 +1,96 @@
/*
__ __ _ _____ ____ _____ __
| \/ | / \|_ _| _ \|_ _\ \/ /
| |\/| | / _ \ | | | |_) || | \ /
| | | |/ ___ \| | | _ < | | / \
|_| |_/_/ \_\_| |_| \_\___/_/\_\
Script to launch the welcome screen
Pour compiler:
g++ -Iinclude -Llib welcome_screen.cc -o welcome_screen -lrgbmatrix
g++ -I /var/www/moduleair_pro_4g/matrix/include -L /var/www/moduleair_pro_4g/matrix/lib /var/www/moduleair_pro_4g/matrix/welcome_screen.cc -o /var/www/moduleair_pro_4g/matrix/welcome_screen -lrgbmatrix
Pour lancer:
sudo /var/www/moduleair_pro_4g/matrix/welcome_screen
*/
#include "led-matrix.h"
#include "graphics.h"
#include <unistd.h>
#include <string.h>
#include <fstream>
#include <iostream>
#include <signal.h>
#include <atomic>
using rgb_matrix::RGBMatrix;
using rgb_matrix::Canvas;
std::atomic<bool> running(true);
void signal_handler(int signum) {
running = false;
}
//message d'accueil
void draw_welcome_screen(Canvas *canvas) {
canvas->Clear();
rgb_matrix::Color myCYAN(0, 255, 255);
rgb_matrix::Color myWHITE(255, 255, 255);
rgb_matrix::Color bg_color(0, 0, 0);
rgb_matrix::Font font1;
rgb_matrix::Font font2;
if (!font1.LoadFont("/var/www/moduleair_pro_4g/matrix/fonts/6x9.bdf")) return;
if (!font2.LoadFont("/var/www/moduleair_pro_4g/matrix/fonts/9x18B.bdf")) return;
int letter_spacing = 0;
int x = 10, y1 = 20, y2 = 50;
rgb_matrix::DrawText(canvas, font2, x, y1, myCYAN, &bg_color, "Welcome to", letter_spacing);
rgb_matrix::DrawText(canvas, font2, x, y2, myWHITE, &bg_color, "ModuleAir", letter_spacing);
usleep(2000000); // Display the welcome screen for 2 seconds
}
int main(int argc, char *argv[]) {
// Handle signals for graceful exit
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
RGBMatrix::Options defaults;
defaults.hardware_mapping = "moduleair_pinout";
defaults.rows = 64;
defaults.cols = 128;
defaults.chain_length = 1;
defaults.parallel = 1;
defaults.row_address_type = 3;
defaults.show_refresh_rate = true;
defaults.brightness = 100;
defaults.pwm_bits = 1;
defaults.panel_type = "FM6126A";
defaults.disable_hardware_pulsing = false;
Canvas *canvas = RGBMatrix::CreateFromFlags(&argc, &argv, &defaults);
if (canvas == NULL)
return 1;
// Display welcome screen once
draw_welcome_screen(canvas);
// Sleep briefly to allow for updates
usleep(10000000); // 10 s
// Clean up
canvas->Clear();
delete canvas;
return 0;
}

View File

@@ -18,6 +18,34 @@ import sqlite3
conn = sqlite3.connect("/var/www/moduleair_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 (
@@ -30,6 +58,14 @@ cursor.execute("""
VALUES (1, CURRENT_TIMESTAMP);
""")
#create a modem status table
cursor.execute("""
CREATE TABLE IF NOT EXISTS modem_status (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TEXT,
status TEXT
)
""")
# Create a table NPM
cursor.execute("""

96
sqlite/set_config.py Normal file
View File

@@ -0,0 +1,96 @@
'''
____ ___ _ _ _
/ ___| / _ \| | (_) |_ ___
\___ \| | | | | | | __/ _ \
___) | |_| | |___| | || __/
|____/ \__\_\_____|_|\__\___|
Script to set the config
/usr/bin/python3 /var/www/moduleair_pro_4g/sqlite/set_config.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()
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"),
("windMeter", "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!")