From 46a8e21e64d494345e40eb07b728d74f3eb2f33f Mon Sep 17 00:00:00 2001 From: PaulVua Date: Tue, 25 Mar 2025 16:20:19 +0100 Subject: [PATCH] update --- NPM/get_data_modbus_v3.py | 4 +- envea/read_value_v2.py | 29 ++--------- html/admin.html | 15 ++++-- loop/SARA_send_data_v2.py | 4 +- master.py | 104 ++++++++++++++++++++++++++++++-------- 5 files changed, 103 insertions(+), 53 deletions(-) diff --git a/NPM/get_data_modbus_v3.py b/NPM/get_data_modbus_v3.py index 4e26897..0c9c141 100755 --- a/NPM/get_data_modbus_v3.py +++ b/NPM/get_data_modbus_v3.py @@ -52,9 +52,7 @@ def load_config(config_file): return {} # Load the configuration data -config_file = '/var/www/nebuleair_pro_4g/config.json' -config = load_config(config_file) -npm_solo_port = config.get('NPM_solo_port', '') #port du NPM solo +npm_solo_port = "/dev/ttyAMA5" #port du NPM solo #GET RTC TIME from SQlite cursor.execute("SELECT * FROM timestamp_table LIMIT 1") diff --git a/envea/read_value_v2.py b/envea/read_value_v2.py index 469c381..3e91f7f 100755 --- a/envea/read_value_v2.py +++ b/envea/read_value_v2.py @@ -28,31 +28,14 @@ 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' -# Function to load config data -def load_config(config_file): - try: - with open(config_file, 'r') as file: - config_data = json.load(file) - return config_data - except Exception as e: - print(f"Error loading config file: {e}") - return {} +# Fetch connected ENVEA sondes from SQLite config table +cursor.execute("SELECT port, name, coefficient FROM envea_sondes_table WHERE connected = 1") +connected_envea_sondes = cursor.fetchall() # List of tuples (port, name, coefficient) -# Define the config file path -config_file = '/var/www/nebuleair_pro_4g/config.json' - -# Load the configuration data -config = load_config(config_file) - -# Initialize sensors and serial connections -envea_sondes = config.get('envea_sondes', []) -connected_envea_sondes = [sonde for sonde in envea_sondes if sonde.get('connected', False)] serial_connections = {} if connected_envea_sondes: - for device in connected_envea_sondes: - port = device.get('port', 'Unknown') - name = device.get('name', 'Unknown') + for port, name, coefficient in connected_envea_sondes: try: serial_connections[name] = serial.Serial( port=f'/dev/{port}', @@ -74,9 +57,7 @@ data_nh3 = 0 try: if connected_envea_sondes: - for device in connected_envea_sondes: - name = device.get('name', 'Unknown') - coefficient = device.get('coefficient', 1) + for port, name, coefficient in connected_envea_sondes: if name in serial_connections: serial_connection = serial_connections[name] try: diff --git a/html/admin.html b/html/admin.html index a237e92..e9f6cdd 100755 --- a/html/admin.html +++ b/html/admin.html @@ -114,10 +114,9 @@ -
+
- -
+
@@ -611,10 +610,18 @@ function add_sondeEnveaContainer() { // Create container div if it doesn't exist if ($('#sondes_envea_div').length === 0) { - $('#advanced_options').append('
Sondes Envea
'); + $('#advanced_options').append('
Sondes Envea

Plouf

'); } else { // Clear existing content if container exists $('#sondes_envea_div').html('Sondes Envea'); + $('#envea_table').html(''+ + ''+ + '' + + '' + + '' + + '' + + '' + + '
SoftwareHardware (PCB)
ttyAMA5NPM1
ttyAMA4NPM2
ttyAMA3NPM3
ttyAMA2SARA
'); } // Loop through each sonde and create UI elements diff --git a/loop/SARA_send_data_v2.py b/loop/SARA_send_data_v2.py index 3104af7..8f7c5d2 100755 --- a/loop/SARA_send_data_v2.py +++ b/loop/SARA_send_data_v2.py @@ -577,9 +577,9 @@ try: payload_csv[10] = averages[1] # envea_h2s payload_csv[11] = averages[2] # envea_nh3 - #Add data to payload JSON + #Add data to payload JSON payload_json["sensordatavalues"].append({"value_type": "CAIRSENS_NO2", "value": str(averages[0])}) - payload_json["sensordatavalues"].append({"value_type": "CAIRSENS_NO2", "value": str(averages[1])}) + payload_json["sensordatavalues"].append({"value_type": "CAIRSENS_H2S", "value": str(averages[1])}) payload_json["sensordatavalues"].append({"value_type": "CAIRSENS_NH3", "value": str(averages[2])}) #Wind meter diff --git a/master.py b/master.py index 96305b3..0cb008a 100755 --- a/master.py +++ b/master.py @@ -52,17 +52,73 @@ Specific scripts can be disabled with config.json import time import threading import subprocess -import json import os +import sqlite3 + # Base directory where scripts are stored SCRIPT_DIR = "/var/www/nebuleair_pro_4g/" -CONFIG_FILE = "/var/www/nebuleair_pro_4g/config.json" +DB_PATH = "/var/www/nebuleair_pro_4g/sqlite/sensors.db" + +# Lock file path for SARA script +SARA_LOCK_FILE = "/var/www/nebuleair_pro_4g/sara_script.lock" + + +def is_script_enabled(script_name): + """Check if a script is enabled in the database.""" + try: + conn = sqlite3.connect(DB_PATH) + cursor = conn.cursor() + + cursor.execute( + "SELECT enabled FROM config_scripts_table WHERE script_path = ?", + (script_name,) + ) + + result = cursor.fetchone() + conn.close() + + if result is None: + return True # Default to enabled if not found in database + + return bool(result[0]) + except Exception: + # If any database error occurs, default to enabled + return True + + +def create_lock_file(): + """Create a lock file for the SARA script.""" + with open(SARA_LOCK_FILE, 'w') as f: + f.write(str(int(time.time()))) + + +def remove_lock_file(): + """Remove the SARA script lock file.""" + if os.path.exists(SARA_LOCK_FILE): + os.remove(SARA_LOCK_FILE) + + +def is_script_locked(): + """Check if the SARA script is currently locked.""" + if not os.path.exists(SARA_LOCK_FILE): + return False + + # Check if lock is older than 60 seconds (stale) + with open(SARA_LOCK_FILE, 'r') as f: + try: + lock_time = int(f.read().strip()) + if time.time() - lock_time > 60: + # Lock is stale, remove it + remove_lock_file() + return False + except ValueError: + # Invalid lock file content + remove_lock_file() + return False + + return True -def load_config(): - """Load the configuration file to determine which scripts to run.""" - with open(CONFIG_FILE, "r") as f: - return json.load(f) def run_script(script_name, interval, delay=0): """Run a script in a synchronized loop with an optional start delay.""" @@ -70,33 +126,41 @@ def run_script(script_name, interval, delay=0): next_run = time.monotonic() + delay # Apply the initial delay while True: - config = load_config() - if config.get(script_name, True): # Default to True if not found - subprocess.run(["python3", script_path]) + if is_script_enabled(script_name): + # Special handling for SARA script to prevent concurrent runs + if script_name == "loop/SARA_send_data_v2.py": + if not is_script_locked(): + create_lock_file() + try: + subprocess.run(["python3", script_path]) + finally: + remove_lock_file() + else: + # Run other scripts normally + subprocess.run(["python3", script_path]) # Wait until the next exact interval next_run += interval 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), # --> will run as a separated system service (rtc_save_to_db.service) - ("NPM/get_data_modbus_v3.py", 10, 0), # Get NPM data (modbus 5 channels) every 10s, with 2s delay - ("envea/read_value_v2.py", 10, 0), # Get NPM data (modbus 5 channels) every 10s, with 2s delay - ("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 - ("MPPT/read.py", 120, 0), # Get MPPT data every 120 seconds, no delay - #("windMeter/read.py", 60, 2), # --> will run as a separated system service () - ("sqlite/flush_old_data.py", 86400, 0) # flush old data inside db every day () + # Format: (script_name, interval_in_seconds, start_delay_in_seconds) + ("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 + ("loop/SARA_send_data_v2.py", 60, 1), # Send data every 60 seconds, with 1s delay + ("BME280/get_data_v2.py", 120, 0), # Get BME280 data every 120 seconds + ("MPPT/read.py", 120, 0), # Get MPPT data every 120 seconds + ("sqlite/flush_old_data.py", 86400, 0) # Flush old data inside db every day ] -# Start threads for enabled scripts +# Start threads for scripts for script_name, interval, delay in SCRIPTS: thread = threading.Thread(target=run_script, args=(script_name, interval, delay), daemon=True) thread.start() # Keep the main script running while True: - time.sleep(1) - + time.sleep(1) \ No newline at end of file