diff --git a/VERSION b/VERSION index dc1e644..9c6d629 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.6.0 +1.6.1 diff --git a/changelog.json b/changelog.json index 7ba4654..590e3b6 100644 --- a/changelog.json +++ b/changelog.json @@ -1,5 +1,26 @@ { "versions": [ + { + "version": "1.6.1", + "date": "2026-03-19", + "changes": { + "features": [ + "Sonometre NSRT MK4: detection deconnexion avec message explicite (page capteurs + self-test)", + "Colonne noise_status dans data_NOISE (0x00=OK, 0xFF=deconnecte)", + "ERR_NOISE (bit 5, byte 66) dans error_flags UDP quand sonometre deconnecte" + ], + "improvements": [ + "Script NSRT_mk4_get_data.py ecrit en base meme si capteur deconnecte (valeurs a 0, noise_status=0xFF)", + "Script read.py: message d'erreur clair au lieu de l'exception Python brute", + "Self-test: affiche 'Capteur deconnecte — verifiez le cablage USB' au lieu de l'erreur technique" + ], + "fixes": [], + "compatibility": [ + "Migration automatique: colonne noise_status ajoutee via set_config.py lors du firmware update" + ] + }, + "notes": "Gestion de la deconnexion du sonometre NSRT MK4 alignee sur le modele NPM: ecriture en base avec status d'erreur, flag ERR_NOISE dans la payload UDP, et messages utilisateur explicites sur l'interface web." + }, { "version": "1.6.0", "date": "2026-03-18", diff --git a/html/assets/js/selftest.js b/html/assets/js/selftest.js index 52b02af..aef89e1 100644 --- a/html/assets/js/selftest.js +++ b/html/assets/js/selftest.js @@ -412,7 +412,10 @@ async function selfTestSequence() { addSelfTestLog(`Noise response: ${JSON.stringify(noiseResult)}`); if (noiseResult.error) { - updateTestStatus(sensor.id, 'Failed', noiseResult.error, 'bg-danger'); + const noiseMsg = noiseResult.disconnected + ? 'Capteur déconnecté — vérifiez le câblage USB' + : noiseResult.error; + updateTestStatus(sensor.id, 'Failed', noiseMsg, 'bg-danger'); testsFailed++; } else if (noiseResult.LEQ > 0 && noiseResult.dBA > 0) { updateTestStatus(sensor.id, 'Passed', `LEQ: ${noiseResult.LEQ} dB | dB(A): ${noiseResult.dBA}`, 'bg-success'); diff --git a/loop/SARA_send_data_v2.py b/loop/SARA_send_data_v2.py index 98d768b..e222c13 100755 --- a/loop/SARA_send_data_v2.py +++ b/loop/SARA_send_data_v2.py @@ -1015,18 +1015,27 @@ try: print("No data available in the database.") # NOISE sensor + noise_disconnected = False if NOISE_sensor: print("➡️Getting NOISE sensor values") cursor.execute("SELECT * FROM data_NOISE ORDER BY rowid DESC LIMIT 1") last_row = cursor.fetchone() if last_row: print("SQLite DB last available row:", last_row) - cur_LEQ = last_row[1] + cur_LEQ = last_row[1] cur_level = last_row[2] + # noise_status: 0xFF = disconnected (column index 3) + noise_status_value = last_row[3] if len(last_row) > 3 and last_row[3] is not None else 0x00 + if noise_status_value == 0xFF: + noise_disconnected = True + print("Noise status: 0xFF (disconnected)") + else: + print(f"Noise status: 0x{noise_status_value:02X}") + #Add data to payload CSV payload_csv[6] = cur_level - + #Add data to payload UDP payload.set_noise( cur_leq=cur_LEQ, # current LEQ (dBA) @@ -1149,6 +1158,8 @@ try: error_flags |= ERR_RTC_RESET if npm_disconnected: error_flags |= ERR_NPM + if noise_disconnected: + error_flags |= ERR_NOISE payload.set_error_flags(error_flags) # ---- Firmware version (bytes 69-71) ---- diff --git a/sound_meter/NSRT_mk4_get_data.py b/sound_meter/NSRT_mk4_get_data.py index a1c00c5..7e7a2e2 100644 --- a/sound_meter/NSRT_mk4_get_data.py +++ b/sound_meter/NSRT_mk4_get_data.py @@ -28,7 +28,31 @@ write_fs(frequency: int) -> sampling freq import nsrt_mk3_dev import sqlite3 -nsrt = nsrt_mk3_dev.NsrtMk3Dev('/dev/ttyACM0') +# noise_status: 0x00 = OK, 0xFF = disconnected +noise_status = 0x00 +leq_level_rounded = 0 +weighted_level_rounded = 0 + +try: + nsrt = nsrt_mk3_dev.NsrtMk3Dev('/dev/ttyACM0') + + freq_level = nsrt.read_fs() #current sampling frequency + time_constant = nsrt.read_tau() #reads the current time constant + leq_level = nsrt.read_leq() #current running LEQ and starts the integration of a new LEQ. + weighting = nsrt.read_weighting() #weighting curve that is currently selected ( A ou C) + weighted_level = nsrt.read_level() #current running level in dB. + + leq_level_rounded = round(leq_level, 2) + weighted_level_rounded = round(weighted_level, 2) + +except Exception as e: + err_msg = str(e) + if "No such file or directory" in err_msg or "could not open port" in err_msg: + print(f"NSRT MK4 disconnected: {err_msg}") + noise_status = 0xFF + else: + print(f"NSRT MK4 error: {err_msg}") + noise_status = 0xFF # Connect to the SQLite database conn = sqlite3.connect("/var/www/nebuleair_pro_4g/sqlite/sensors.db") @@ -39,34 +63,15 @@ 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' -freq_level = nsrt.read_fs() #current sampling frequency -time_constant = nsrt.read_tau() #reads the current time constant -leq_level = nsrt.read_leq() #current running LEQ and starts the integration of a new LEQ. -weighting = nsrt.read_weighting() #weighting curve that is currently selected ( A ou C) -weighted_level = nsrt.read_level() #current running level in dB. - -#print(f'current sampling freq : {freq_level} Hz') -#print(f'current time constant : {time_constant} s') -#print(f'current LEQ level: {leq_level:0.2f} dB') -#print(f'{weighting} value: {weighted_level:0.2f} dBA') -# Round values to 2 decimal places before saving -leq_level_rounded = round(leq_level, 2) -weighted_level_rounded = round(weighted_level, 2) - -#save to db #save to sqlite database try: cursor.execute(''' - INSERT INTO data_NOISE (timestamp,current_LEQ, DB_A_value) VALUES (?,?,?)''' - , (rtc_time_str,leq_level_rounded,weighted_level_rounded)) + INSERT INTO data_NOISE (timestamp, current_LEQ, DB_A_value, noise_status) VALUES (?,?,?,?)''' + , (rtc_time_str, leq_level_rounded, weighted_level_rounded, noise_status)) - # Commit and close the connection conn.commit() - #print("Sensor data saved successfully!") - except Exception as e: - print(f"Database error: {e}") - + print(f"Database error: {e}") conn.close() \ No newline at end of file diff --git a/sound_meter/read.py b/sound_meter/read.py index 3a02623..a8cd6b6 100644 --- a/sound_meter/read.py +++ b/sound_meter/read.py @@ -31,4 +31,10 @@ try: print(json.dumps(data)) except Exception as e: - print(json.dumps({"error": str(e)})) + err_msg = str(e) + if "No such file or directory" in err_msg or "could not open port" in err_msg: + print(json.dumps({"error": "Capteur déconnecté — vérifiez le câblage USB du sonomètre NSRT MK4 (/dev/ttyACM0)", "disconnected": True})) + elif "Permission denied" in err_msg: + print(json.dumps({"error": "Permission refusée sur /dev/ttyACM0 — exécutez: sudo chmod 777 /dev/ttyACM0", "disconnected": False})) + else: + print(json.dumps({"error": err_msg})) diff --git a/sqlite/create_db.py b/sqlite/create_db.py index d627332..5ae8f7f 100755 --- a/sqlite/create_db.py +++ b/sqlite/create_db.py @@ -140,10 +140,18 @@ cursor.execute(""" CREATE TABLE IF NOT EXISTS data_NOISE ( timestamp TEXT, current_LEQ REAL, - DB_A_value REAL + DB_A_value REAL, + noise_status INTEGER DEFAULT 0 ) """) +# Add noise_status column to existing databases (migration) +try: + cursor.execute("ALTER TABLE data_NOISE ADD COLUMN noise_status INTEGER DEFAULT 0") + print("Added noise_status column to data_NOISE") +except: + pass # Column already exists + # Create a table MHZ19 (CO2 sensor) cursor.execute(""" CREATE TABLE IF NOT EXISTS data_MHZ19 ( diff --git a/sqlite/set_config.py b/sqlite/set_config.py index 6751220..6d6cb4c 100644 --- a/sqlite/set_config.py +++ b/sqlite/set_config.py @@ -110,6 +110,7 @@ for connected, port, name, coefficient in envea_sondes: # Database migrations (add columns to existing tables) migrations = [ ("data_NPM", "npm_status", "INTEGER DEFAULT 0"), + ("data_NOISE", "noise_status", "INTEGER DEFAULT 0"), ] for table, column, col_type in migrations: