update
This commit is contained in:
@@ -17,15 +17,43 @@ import time
|
|||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
|
import sqlite3
|
||||||
|
|
||||||
#get data from config
|
# database connection
|
||||||
def load_config(config_file):
|
conn = sqlite3.connect("/var/www/nebuleair_pro_4g/sqlite/sensors.db")
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
#get config data from SQLite table
|
||||||
|
def load_config_sqlite():
|
||||||
|
"""
|
||||||
|
Load configuration data from SQLite config table
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: Configuration data with proper type conversion
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
with open(config_file, 'r') as file:
|
|
||||||
config_data = json.load(file)
|
# Query the config table
|
||||||
|
cursor.execute("SELECT key, value, type FROM config_table")
|
||||||
|
rows = cursor.fetchall()
|
||||||
|
|
||||||
|
# Create config dictionary
|
||||||
|
config_data = {}
|
||||||
|
for key, value, type_name in rows:
|
||||||
|
# Convert value based on its type
|
||||||
|
if type_name == 'bool':
|
||||||
|
config_data[key] = value == '1' or value == 'true'
|
||||||
|
elif type_name == 'int':
|
||||||
|
config_data[key] = int(value)
|
||||||
|
elif type_name == 'float':
|
||||||
|
config_data[key] = float(value)
|
||||||
|
else:
|
||||||
|
config_data[key] = value
|
||||||
|
|
||||||
return config_data
|
return config_data
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error loading config file: {e}")
|
print(f"Error loading config from SQLite: {e}")
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
#Fonction pour mettre à jour le JSON de configuration
|
#Fonction pour mettre à jour le JSON de configuration
|
||||||
@@ -57,10 +85,55 @@ def update_json_key(file_path, key, value):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error updating the JSON file: {e}")
|
print(f"Error updating the JSON file: {e}")
|
||||||
|
|
||||||
# Define the config file path
|
|
||||||
config_file = '/var/www/nebuleair_pro_4g/config.json'
|
def update_sqlite_config(key, value):
|
||||||
# Load the configuration data
|
"""
|
||||||
config = load_config(config_file)
|
Updates a specific key in the SQLite config_table with a new value.
|
||||||
|
|
||||||
|
:param key: The key to update in the config_table.
|
||||||
|
:param value: The new value to assign to the key.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
|
||||||
|
# Check if the key exists and get its type
|
||||||
|
cursor.execute("SELECT type FROM config_table WHERE key = ?", (key,))
|
||||||
|
result = cursor.fetchone()
|
||||||
|
|
||||||
|
if result is None:
|
||||||
|
print(f"Key '{key}' not found in the config_table.")
|
||||||
|
conn.close()
|
||||||
|
return
|
||||||
|
|
||||||
|
# Get the type of the value from the database
|
||||||
|
value_type = result[0]
|
||||||
|
|
||||||
|
# Convert the value to the appropriate string representation based on its type
|
||||||
|
if value_type == 'bool':
|
||||||
|
# Convert Python boolean or string 'true'/'false' to '1'/'0'
|
||||||
|
if isinstance(value, bool):
|
||||||
|
str_value = '1' if value else '0'
|
||||||
|
else:
|
||||||
|
str_value = '1' if str(value).lower() in ('true', '1', 'yes', 'y') else '0'
|
||||||
|
elif value_type == 'int':
|
||||||
|
str_value = str(int(value))
|
||||||
|
elif value_type == 'float':
|
||||||
|
str_value = str(float(value))
|
||||||
|
else:
|
||||||
|
str_value = str(value)
|
||||||
|
|
||||||
|
# Update the value in the database
|
||||||
|
cursor.execute("UPDATE config_table SET value = ? WHERE key = ?", (str_value, key))
|
||||||
|
|
||||||
|
# Commit the changes and close the connection
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
print(f"💾 Updated '{key}' to '{value}' in database.")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error updating the SQLite database: {e}")
|
||||||
|
|
||||||
|
#Load config
|
||||||
|
config = load_config_sqlite()
|
||||||
|
#config
|
||||||
baudrate = config.get('SaraR4_baudrate', 115200) #baudrate du sara R4
|
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
|
||||||
|
|
||||||
@@ -151,7 +224,7 @@ try:
|
|||||||
print("⚠️ Could not identify modem model")
|
print("⚠️ Could not identify modem model")
|
||||||
|
|
||||||
print(f"🔍 Model: {model}")
|
print(f"🔍 Model: {model}")
|
||||||
update_json_key(config_file, "modem_version", model)
|
update_sqlite_config("modem_version", model)
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@@ -332,9 +405,9 @@ try:
|
|||||||
else:
|
else:
|
||||||
print("❌ Failed to extract coordinates.")
|
print("❌ Failed to extract coordinates.")
|
||||||
|
|
||||||
#update config.json
|
#update sqlite table
|
||||||
update_json_key(config_file, "latitude_raw", float(latitude))
|
update_sqlite_config("latitude_raw", float(latitude))
|
||||||
update_json_key(config_file, "longitude_raw", float(longitude))
|
update_sqlite_config("longitude_raw", float(longitude))
|
||||||
|
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
# Script to check if wifi is connected and start hotspot if not
|
# Script to check if wifi is connected and start hotspot if not
|
||||||
# will also retreive unique RPi ID and store it to deviceID.txt
|
# will also retreive unique RPi ID and store it to deviceID.txt
|
||||||
|
# script that starts at boot:
|
||||||
|
# @reboot /var/www/nebuleair_pro_4g/boot_hotspot.sh >> /var/www/nebuleair_pro_4g/logs/app.log 2>&1
|
||||||
|
|
||||||
OUTPUT_FILE="/var/www/nebuleair_pro_4g/wifi_list.csv"
|
OUTPUT_FILE="/var/www/nebuleair_pro_4g/wifi_list.csv"
|
||||||
JSON_FILE="/var/www/nebuleair_pro_4g/config.json"
|
JSON_FILE="/var/www/nebuleair_pro_4g/config.json"
|
||||||
@@ -30,8 +32,7 @@ done
|
|||||||
echo "getting RPI serial number"
|
echo "getting RPI serial number"
|
||||||
# Get the last 8 characters of the serial number and write to text file
|
# Get the last 8 characters of the serial number and write to text file
|
||||||
serial_number=$(cat /proc/cpuinfo | grep Serial | awk '{print substr($3, length($3) - 7)}')
|
serial_number=$(cat /proc/cpuinfo | grep Serial | awk '{print substr($3, length($3) - 7)}')
|
||||||
# Use jq to update the "deviceID" in the JSON file
|
|
||||||
#jq --arg serial_number "$serial_number" '.deviceID = $serial_number' "$JSON_FILE" > temp.json && mv temp.json "$JSON_FILE"
|
|
||||||
# update Sqlite database
|
# update Sqlite database
|
||||||
echo "Updating SQLite database with device ID: $serial_number"
|
echo "Updating SQLite database with device ID: $serial_number"
|
||||||
sqlite3 /var/www/nebuleair_pro_4g/sqlite/sensors.db "UPDATE config_table SET value='$serial_number' WHERE key='deviceID';"
|
sqlite3 /var/www/nebuleair_pro_4g/sqlite/sensors.db "UPDATE config_table SET value='$serial_number' WHERE key='deviceID';"
|
||||||
@@ -39,8 +40,8 @@ sqlite3 /var/www/nebuleair_pro_4g/sqlite/sensors.db "UPDATE config_table SET val
|
|||||||
echo "id: $serial_number"
|
echo "id: $serial_number"
|
||||||
|
|
||||||
|
|
||||||
#get the SSH port for tunneling
|
# Get SSH tunnel port from SQLite config_table
|
||||||
SSH_TUNNEL_PORT=$(jq -r '.sshTunnel_port' "$JSON_FILE")
|
SSH_TUNNEL_PORT=$(sqlite3 /var/www/nebuleair_pro_4g/sqlite/sensors.db "SELECT value FROM config_table WHERE key='sshTunnel_port'")
|
||||||
|
|
||||||
#need to wait for the network manager to be ready
|
#need to wait for the network manager to be ready
|
||||||
sleep 20
|
sleep 20
|
||||||
@@ -58,17 +59,16 @@ if [ "$STATE" == "30 (disconnected)" ]; then
|
|||||||
echo "Starting hotspot..."
|
echo "Starting hotspot..."
|
||||||
sudo nmcli device wifi hotspot ifname wlan0 ssid nebuleair_pro password nebuleaircfg
|
sudo nmcli device wifi hotspot ifname wlan0 ssid nebuleair_pro password nebuleaircfg
|
||||||
|
|
||||||
# Update JSON to reflect hotspot mode
|
# Update SQLite to reflect hotspot mode
|
||||||
jq --arg status "hotspot" '.WIFI_status = $status' "$JSON_FILE" > temp.json && mv temp.json "$JSON_FILE"
|
sqlite3 /var/www/nebuleair_pro_4g/sqlite/sensors.db "UPDATE config_table SET value='hotspot' WHERE key='WIFI_status'"
|
||||||
|
|
||||||
|
|
||||||
else
|
else
|
||||||
echo "🛜Success: wlan0 is connected!🛜"
|
echo "🛜Success: wlan0 is connected!🛜"
|
||||||
CONN_SSID=$(nmcli -g GENERAL.CONNECTION device show wlan0)
|
CONN_SSID=$(nmcli -g GENERAL.CONNECTION device show wlan0)
|
||||||
echo "Connection: $CONN_SSID"
|
echo "Connection: $CONN_SSID"
|
||||||
|
|
||||||
#update config JSON file
|
# Update SQLite to reflect hotspot mode
|
||||||
jq --arg status "connected" '.WIFI_status = $status' "$JSON_FILE" > temp.json && mv temp.json "$JSON_FILE"
|
sqlite3 /var/www/nebuleair_pro_4g/sqlite/sensors.db "UPDATE config_table SET value='connected' WHERE key='WIFI_status'"
|
||||||
|
|
||||||
sudo chmod 777 "$JSON_FILE"
|
sudo chmod 777 "$JSON_FILE"
|
||||||
|
|
||||||
|
|||||||
336
html/admin.html
336
html/admin.html
@@ -114,6 +114,10 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="input-group mb-3" id="sondes_envea_div">
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<!--<button type="submit" class="btn btn-primary">Submit</button>-->
|
<!--<button type="submit" class="btn btn-primary">Submit</button>-->
|
||||||
@@ -212,6 +216,16 @@
|
|||||||
|
|
||||||
//end document.addEventListener
|
//end document.addEventListener
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
___ _ _
|
||||||
|
/ _ \ _ __ | | ___ __ _ __| |
|
||||||
|
| | | | '_ \| | / _ \ / _` |/ _` |
|
||||||
|
| |_| | | | | |__| (_) | (_| | (_| |
|
||||||
|
\___/|_| |_|_____\___/ \__,_|\__,_|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
window.onload = function() {
|
window.onload = function() {
|
||||||
|
|
||||||
//NEW way to get config (SQLite)
|
//NEW way to get config (SQLite)
|
||||||
@@ -267,6 +281,12 @@ window.onload = function() {
|
|||||||
checkbox_envea.checked = response["envea/read_value_v2.py"];
|
checkbox_envea.checked = response["envea/read_value_v2.py"];
|
||||||
checkbox_solar.checked = response["MPPT/read.py"];
|
checkbox_solar.checked = response["MPPT/read.py"];
|
||||||
checkbox_wind.checked = response["windMeter/read.py"];
|
checkbox_wind.checked = response["windMeter/read.py"];
|
||||||
|
|
||||||
|
//si sonde envea is true
|
||||||
|
if (response["envea/read_value_v2.py"]) {
|
||||||
|
add_sondeEnveaContainer();
|
||||||
|
|
||||||
|
}
|
||||||
},
|
},
|
||||||
error: function(xhr, status, error) {
|
error: function(xhr, status, error) {
|
||||||
console.error('AJAX request failed:', status, error);
|
console.error('AJAX request failed:', status, error);
|
||||||
@@ -369,6 +389,10 @@ window.onload = function() {
|
|||||||
|
|
||||||
} //end window.onload
|
} //end window.onload
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function update_config_sqlite(param, value){
|
function update_config_sqlite(param, value){
|
||||||
console.log("Updating sqlite ",param," : ", value);
|
console.log("Updating sqlite ",param," : ", value);
|
||||||
const toastLiveExample = document.getElementById('liveToast')
|
const toastLiveExample = document.getElementById('liveToast')
|
||||||
@@ -445,6 +469,12 @@ function update_config_scripts_sqlite(param, value) {
|
|||||||
Value: ${response.enabled !== undefined ? response.enabled : value}<br>
|
Value: ${response.enabled !== undefined ? response.enabled : value}<br>
|
||||||
${response.message || ''}
|
${response.message || ''}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
if (response.script_path == "envea/read_value_v2.py") {
|
||||||
|
console.log("envea sondes activated");
|
||||||
|
add_sondeEnveaContainer();
|
||||||
|
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Error message
|
// Error message
|
||||||
toastLiveExample.classList.remove('text-bg-success');
|
toastLiveExample.classList.remove('text-bg-success');
|
||||||
@@ -558,6 +588,312 @@ function set_RTC_withBrowser(){
|
|||||||
}); //end ajax
|
}); //end ajax
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
____ _ _____
|
||||||
|
/ ___| ___ _ __ __| | ___ ___ | ____|_ ____ _____ __ _
|
||||||
|
\___ \ / _ \| '_ \ / _` |/ _ \/ __| | _| | '_ \ \ / / _ \/ _` |
|
||||||
|
___) | (_) | | | | (_| | __/\__ \ | |___| | | \ V / __/ (_| |
|
||||||
|
|____/ \___/|_| |_|\__,_|\___||___/ |_____|_| |_|\_/ \___|\__,_|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
function add_sondeEnveaContainer() {
|
||||||
|
console.log("Sonde Envea is true: need to add container!");
|
||||||
|
|
||||||
|
// Getting envea_sondes_table data
|
||||||
|
$.ajax({
|
||||||
|
url: 'launcher.php?type=get_envea_sondes_table_sqlite',
|
||||||
|
dataType: 'json',
|
||||||
|
method: 'GET',
|
||||||
|
success: function(sondes) {
|
||||||
|
console.log("Getting SQLite envea sondes table:");
|
||||||
|
console.log(sondes);
|
||||||
|
|
||||||
|
// Create container div if it doesn't exist
|
||||||
|
if ($('#sondes_envea_div').length === 0) {
|
||||||
|
$('#advanced_options').append('<div id="sondes_envea_div" class="input-group mt-4 border p-3 rounded"><legend>Sondes Envea</legend></div>');
|
||||||
|
} else {
|
||||||
|
// Clear existing content if container exists
|
||||||
|
$('#sondes_envea_div').html('<legend>Sondes Envea</legend>');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop through each sonde and create UI elements
|
||||||
|
sondes.forEach(function(sonde) {
|
||||||
|
// Create a unique ID for this sonde
|
||||||
|
const sondeId = `sonde_${sonde.id}`;
|
||||||
|
|
||||||
|
// Create HTML for this sonde
|
||||||
|
const sondeHtml = `
|
||||||
|
<div class="input-group mb-3" id="${sondeId}_container">
|
||||||
|
<div class="input-group-text">
|
||||||
|
<input class="form-check-input mt-0" type="checkbox" id="${sondeId}_enabled"
|
||||||
|
${sonde.connected ? 'checked' : ''}
|
||||||
|
onchange="updateSondeStatus(${sonde.id}, this.checked)">
|
||||||
|
</div>
|
||||||
|
<input type="text" class="form-control" placeholder="Name" value="${sonde.name}"
|
||||||
|
id="${sondeId}_name" onchange="updateSondeName(${sonde.id}, this.value)">
|
||||||
|
<input type="text" class="form-control" placeholder="Port" value="${sonde.port}"
|
||||||
|
id="${sondeId}_port" onchange="updateSondePort(${sonde.id}, this.value)">
|
||||||
|
<input type="number" class="form-control" placeholder="Coefficient" value="${sonde.coefficient}"
|
||||||
|
id="${sondeId}_coefficient" onchange="updateSondeCoefficient(${sonde.id}, this.value)">
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Append this sonde to the container
|
||||||
|
$('#sondes_envea_div').append(sondeHtml);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
error: function(xhr, status, error) {
|
||||||
|
console.error('AJAX request failed:', status, error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper functions for updating sonde properties
|
||||||
|
function updateSondeStatus(id, connected) {
|
||||||
|
console.log(`Updating sonde ${id} connected status to: ${connected}`);
|
||||||
|
const toastLiveExample = document.getElementById('liveToast');
|
||||||
|
const toastBody = toastLiveExample.querySelector('.toast-body');
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: `launcher.php?type=update_sonde&id=${id}&field=connected&value=${connected ? 1 : 0}`,
|
||||||
|
dataType: 'json',
|
||||||
|
method: 'GET',
|
||||||
|
cache: false,
|
||||||
|
success: function(response) {
|
||||||
|
console.log('Sonde status updated:', response);
|
||||||
|
|
||||||
|
// Format the response for toast
|
||||||
|
let formattedMessage = '';
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
// Success message
|
||||||
|
toastLiveExample.classList.remove('text-bg-danger');
|
||||||
|
toastLiveExample.classList.add('text-bg-success');
|
||||||
|
|
||||||
|
formattedMessage = `
|
||||||
|
<strong>Success!</strong><br>
|
||||||
|
Sonde ID: ${response.id}<br>
|
||||||
|
Connected: ${connected ? "Yes" : "No"}<br>
|
||||||
|
${response.message || ''}
|
||||||
|
`;
|
||||||
|
} else {
|
||||||
|
// Error message
|
||||||
|
toastLiveExample.classList.remove('text-bg-success');
|
||||||
|
toastLiveExample.classList.add('text-bg-danger');
|
||||||
|
|
||||||
|
formattedMessage = `
|
||||||
|
<strong>Error!</strong><br>
|
||||||
|
${response.error || 'Unknown error'}<br>
|
||||||
|
Sonde ID: ${id}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update and show toast
|
||||||
|
toastBody.innerHTML = formattedMessage;
|
||||||
|
const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastLiveExample);
|
||||||
|
toastBootstrap.show();
|
||||||
|
},
|
||||||
|
error: function(xhr, status, error) {
|
||||||
|
console.error('Failed to update sonde status:', error);
|
||||||
|
|
||||||
|
// Show error toast
|
||||||
|
toastLiveExample.classList.remove('text-bg-success');
|
||||||
|
toastLiveExample.classList.add('text-bg-danger');
|
||||||
|
toastBody.innerHTML = `
|
||||||
|
<strong>Request Failed!</strong><br>
|
||||||
|
Error: ${error}<br>
|
||||||
|
Sonde ID: ${id}
|
||||||
|
`;
|
||||||
|
const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastLiveExample);
|
||||||
|
toastBootstrap.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSondeName(id, name) {
|
||||||
|
console.log(`Updating sonde ${id} name to: ${name}`);
|
||||||
|
const toastLiveExample = document.getElementById('liveToast');
|
||||||
|
const toastBody = toastLiveExample.querySelector('.toast-body');
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: `launcher.php?type=update_sonde&id=${id}&field=name&value=${encodeURIComponent(name)}`,
|
||||||
|
dataType: 'json',
|
||||||
|
method: 'GET',
|
||||||
|
cache: false,
|
||||||
|
success: function(response) {
|
||||||
|
console.log('Sonde name updated:', response);
|
||||||
|
|
||||||
|
// Format the response for toast
|
||||||
|
let formattedMessage = '';
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
// Success message
|
||||||
|
toastLiveExample.classList.remove('text-bg-danger');
|
||||||
|
toastLiveExample.classList.add('text-bg-success');
|
||||||
|
|
||||||
|
formattedMessage = `
|
||||||
|
<strong>Success!</strong><br>
|
||||||
|
Sonde ID: ${response.id}<br>
|
||||||
|
Name: ${name}<br>
|
||||||
|
${response.message || ''}
|
||||||
|
`;
|
||||||
|
} else {
|
||||||
|
// Error message
|
||||||
|
toastLiveExample.classList.remove('text-bg-success');
|
||||||
|
toastLiveExample.classList.add('text-bg-danger');
|
||||||
|
|
||||||
|
formattedMessage = `
|
||||||
|
<strong>Error!</strong><br>
|
||||||
|
${response.error || 'Unknown error'}<br>
|
||||||
|
Sonde ID: ${id}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update and show toast
|
||||||
|
toastBody.innerHTML = formattedMessage;
|
||||||
|
const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastLiveExample);
|
||||||
|
toastBootstrap.show();
|
||||||
|
},
|
||||||
|
error: function(xhr, status, error) {
|
||||||
|
console.error('Failed to update sonde name:', error);
|
||||||
|
|
||||||
|
// Show error toast
|
||||||
|
toastLiveExample.classList.remove('text-bg-success');
|
||||||
|
toastLiveExample.classList.add('text-bg-danger');
|
||||||
|
toastBody.innerHTML = `
|
||||||
|
<strong>Request Failed!</strong><br>
|
||||||
|
Error: ${error}<br>
|
||||||
|
Sonde ID: ${id}
|
||||||
|
`;
|
||||||
|
const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastLiveExample);
|
||||||
|
toastBootstrap.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSondePort(id, port) {
|
||||||
|
console.log(`Updating sonde ${id} port to: ${port}`);
|
||||||
|
const toastLiveExample = document.getElementById('liveToast');
|
||||||
|
const toastBody = toastLiveExample.querySelector('.toast-body');
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: `launcher.php?type=update_sonde&id=${id}&field=port&value=${encodeURIComponent(port)}`,
|
||||||
|
dataType: 'json',
|
||||||
|
method: 'GET',
|
||||||
|
cache: false,
|
||||||
|
success: function(response) {
|
||||||
|
console.log('Sonde port updated:', response);
|
||||||
|
|
||||||
|
// Format the response for toast
|
||||||
|
let formattedMessage = '';
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
// Success message
|
||||||
|
toastLiveExample.classList.remove('text-bg-danger');
|
||||||
|
toastLiveExample.classList.add('text-bg-success');
|
||||||
|
|
||||||
|
formattedMessage = `
|
||||||
|
<strong>Success!</strong><br>
|
||||||
|
Sonde ID: ${response.id}<br>
|
||||||
|
Port: ${port}<br>
|
||||||
|
${response.message || ''}
|
||||||
|
`;
|
||||||
|
} else {
|
||||||
|
// Error message
|
||||||
|
toastLiveExample.classList.remove('text-bg-success');
|
||||||
|
toastLiveExample.classList.add('text-bg-danger');
|
||||||
|
|
||||||
|
formattedMessage = `
|
||||||
|
<strong>Error!</strong><br>
|
||||||
|
${response.error || 'Unknown error'}<br>
|
||||||
|
Sonde ID: ${id}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update and show toast
|
||||||
|
toastBody.innerHTML = formattedMessage;
|
||||||
|
const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastLiveExample);
|
||||||
|
toastBootstrap.show();
|
||||||
|
},
|
||||||
|
error: function(xhr, status, error) {
|
||||||
|
console.error('Failed to update sonde port:', error);
|
||||||
|
|
||||||
|
// Show error toast
|
||||||
|
toastLiveExample.classList.remove('text-bg-success');
|
||||||
|
toastLiveExample.classList.add('text-bg-danger');
|
||||||
|
toastBody.innerHTML = `
|
||||||
|
<strong>Request Failed!</strong><br>
|
||||||
|
Error: ${error}<br>
|
||||||
|
Sonde ID: ${id}
|
||||||
|
`;
|
||||||
|
const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastLiveExample);
|
||||||
|
toastBootstrap.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSondeCoefficient(id, coefficient) {
|
||||||
|
console.log(`Updating sonde ${id} coefficient to: ${coefficient}`);
|
||||||
|
const toastLiveExample = document.getElementById('liveToast');
|
||||||
|
const toastBody = toastLiveExample.querySelector('.toast-body');
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: `launcher.php?type=update_sonde&id=${id}&field=coefficient&value=${coefficient}`,
|
||||||
|
dataType: 'json',
|
||||||
|
method: 'GET',
|
||||||
|
cache: false,
|
||||||
|
success: function(response) {
|
||||||
|
console.log('Sonde coefficient updated:', response);
|
||||||
|
|
||||||
|
// Format the response for toast
|
||||||
|
let formattedMessage = '';
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
// Success message
|
||||||
|
toastLiveExample.classList.remove('text-bg-danger');
|
||||||
|
toastLiveExample.classList.add('text-bg-success');
|
||||||
|
|
||||||
|
formattedMessage = `
|
||||||
|
<strong>Success!</strong><br>
|
||||||
|
Sonde ID: ${response.id}<br>
|
||||||
|
Coefficient: ${coefficient}<br>
|
||||||
|
${response.message || ''}
|
||||||
|
`;
|
||||||
|
} else {
|
||||||
|
// Error message
|
||||||
|
toastLiveExample.classList.remove('text-bg-success');
|
||||||
|
toastLiveExample.classList.add('text-bg-danger');
|
||||||
|
|
||||||
|
formattedMessage = `
|
||||||
|
<strong>Error!</strong><br>
|
||||||
|
${response.error || 'Unknown error'}<br>
|
||||||
|
Sonde ID: ${id}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update and show toast
|
||||||
|
toastBody.innerHTML = formattedMessage;
|
||||||
|
const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastLiveExample);
|
||||||
|
toastBootstrap.show();
|
||||||
|
},
|
||||||
|
error: function(xhr, status, error) {
|
||||||
|
console.error('Failed to update sonde coefficient:', error);
|
||||||
|
|
||||||
|
// Show error toast
|
||||||
|
toastLiveExample.classList.remove('text-bg-success');
|
||||||
|
toastLiveExample.classList.add('text-bg-danger');
|
||||||
|
toastBody.innerHTML = `
|
||||||
|
<strong>Request Failed!</strong><br>
|
||||||
|
Error: ${error}<br>
|
||||||
|
Sonde ID: ${id}
|
||||||
|
`;
|
||||||
|
const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastLiveExample);
|
||||||
|
toastBootstrap.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ if ($type == "get_npm_sqlite_data") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
*/
|
||||||
//GETING data from config_table (SQLite DB)
|
//GETING data from config_table (SQLite DB)
|
||||||
if ($type == "get_config_sqlite") {
|
if ($type == "get_config_sqlite") {
|
||||||
try {
|
try {
|
||||||
@@ -74,6 +77,9 @@ if ($type == "get_config_sqlite") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
*/
|
||||||
//GETING data from config_scrips_table (SQLite DB)
|
//GETING data from config_scrips_table (SQLite DB)
|
||||||
if ($type == "get_config_scripts_sqlite") {
|
if ($type == "get_config_scripts_sqlite") {
|
||||||
|
|
||||||
@@ -107,6 +113,51 @@ if ($type == "get_config_scripts_sqlite") {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
*/
|
||||||
|
//GETING data from envea_sondes_table (SQLite DB)
|
||||||
|
if ($type == "get_envea_sondes_table_sqlite") {
|
||||||
|
|
||||||
|
try {
|
||||||
|
$db = new PDO("sqlite:$database_path");
|
||||||
|
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||||
|
|
||||||
|
// Get all entries from envea_sondes_table
|
||||||
|
$query = $db->query("SELECT id, connected, port, name, coefficient FROM envea_sondes_table");
|
||||||
|
$data = $query->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
// Convert data types appropriately
|
||||||
|
$result = [];
|
||||||
|
foreach ($data as $item) {
|
||||||
|
// Create object for each sonde with proper data types
|
||||||
|
$sonde = [
|
||||||
|
'id' => (int)$item['id'],
|
||||||
|
'connected' => $item['connected'] == 1, // Convert to boolean
|
||||||
|
'port' => $item['port'],
|
||||||
|
'name' => $item['name'],
|
||||||
|
'coefficient' => (float)$item['coefficient'] // Convert to float
|
||||||
|
];
|
||||||
|
|
||||||
|
// Add to results array
|
||||||
|
$result[] = $sonde;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Return JSON response
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
|
||||||
|
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
// Return error as JSON
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//UPDATING the config_table from SQLite DB
|
//UPDATING the config_table from SQLite DB
|
||||||
if ($type == "update_config_sqlite") {
|
if ($type == "update_config_sqlite") {
|
||||||
@@ -214,6 +265,87 @@ if ($type == "update_config_scripts_sqlite") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//UPDATING the envea_sondes_table table from SQLite DB
|
||||||
|
if ($type == "update_sonde") {
|
||||||
|
$id = $_GET['id'] ?? null;
|
||||||
|
$field = $_GET['field'] ?? null;
|
||||||
|
$value = $_GET['value'] ?? null;
|
||||||
|
|
||||||
|
// Validate parameters
|
||||||
|
if ($id === null || $field === null || $value === null) {
|
||||||
|
echo json_encode([
|
||||||
|
"success" => false,
|
||||||
|
"error" => "Missing required parameters (id, field, or value)"
|
||||||
|
]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate field name (whitelist approach for security)
|
||||||
|
$allowed_fields = ['connected', 'port', 'name', 'coefficient'];
|
||||||
|
if (!in_array($field, $allowed_fields)) {
|
||||||
|
echo json_encode([
|
||||||
|
"success" => false,
|
||||||
|
"error" => "Invalid field name: " . $field
|
||||||
|
]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Connect to the database
|
||||||
|
$db = new PDO("sqlite:$database_path");
|
||||||
|
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||||
|
|
||||||
|
// Check if the sonde exists
|
||||||
|
$checkStmt = $db->prepare("SELECT id FROM envea_sondes_table WHERE id = :id");
|
||||||
|
$checkStmt->bindParam(':id', $id, PDO::PARAM_INT);
|
||||||
|
$checkStmt->execute();
|
||||||
|
|
||||||
|
if (!$checkStmt->fetch()) {
|
||||||
|
echo json_encode([
|
||||||
|
"success" => false,
|
||||||
|
"error" => "Sonde with ID $id not found"
|
||||||
|
]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process value based on field type
|
||||||
|
if ($field == 'connected') {
|
||||||
|
// Convert to integer (0 or 1)
|
||||||
|
$processedValue = filter_var($value, FILTER_VALIDATE_BOOLEAN) ? 1 : 0;
|
||||||
|
$paramType = PDO::PARAM_INT;
|
||||||
|
} else if ($field == 'coefficient') {
|
||||||
|
// Convert to float
|
||||||
|
$processedValue = floatval($value);
|
||||||
|
$paramType = PDO::PARAM_STR; // SQLite doesn't have PARAM_FLOAT
|
||||||
|
} else {
|
||||||
|
// For text fields (port, name)
|
||||||
|
$processedValue = $value;
|
||||||
|
$paramType = PDO::PARAM_STR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the sonde record
|
||||||
|
$updateStmt = $db->prepare("UPDATE envea_sondes_table SET $field = :value WHERE id = :id");
|
||||||
|
$updateStmt->bindParam(':value', $processedValue, $paramType);
|
||||||
|
$updateStmt->bindParam(':id', $id, PDO::PARAM_INT);
|
||||||
|
$updateStmt->execute();
|
||||||
|
|
||||||
|
// Return success response
|
||||||
|
echo json_encode([
|
||||||
|
"success" => true,
|
||||||
|
"message" => "Sonde $id updated successfully",
|
||||||
|
"field" => $field,
|
||||||
|
"value" => $processedValue
|
||||||
|
]);
|
||||||
|
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
// Return error as JSON
|
||||||
|
echo json_encode([
|
||||||
|
"success" => false,
|
||||||
|
"error" => "Database error: " . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//update the config (old JSON updating)
|
//update the config (old JSON updating)
|
||||||
if ($type == "update_config") {
|
if ($type == "update_config") {
|
||||||
echo "updating.... ";
|
echo "updating.... ";
|
||||||
|
|||||||
@@ -149,20 +149,18 @@ function getENVEA_values(port, name){
|
|||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: 'launcher.php?type=envea&port=' + port + '&name=' + name,
|
url: 'launcher.php?type=envea&port=' + port + '&name=' + name,
|
||||||
dataType: 'json', // Specify that you expect a JSON response
|
dataType: 'json',
|
||||||
method: 'GET', // Use GET or POST depending on your needs
|
method: 'GET',
|
||||||
success: function(response) {
|
success: function(response) {
|
||||||
console.log(response);
|
console.log(response);
|
||||||
const tableBody = document.getElementById("data-table-body_envea" + name);
|
const tableBody = document.getElementById("data-table-body_envea" + name);
|
||||||
tableBody.innerHTML = "";
|
tableBody.innerHTML = "";
|
||||||
|
|
||||||
$("#loading_envea" + name).hide();
|
$("#loading_envea" + name).hide();
|
||||||
// Create an array of the desired keys
|
|
||||||
// Create an array of the desired keys
|
|
||||||
const keysToShow = [name];
|
const keysToShow = [name];
|
||||||
// Add only the specified elements to the table
|
|
||||||
keysToShow.forEach(key => {
|
keysToShow.forEach(key => {
|
||||||
if (response !== undefined) { // Check if the key exists in the response
|
if (response !== undefined) {
|
||||||
const value = response;
|
const value = response;
|
||||||
$("#data-table-body_envea" + name).append(`
|
$("#data-table-body_envea" + name).append(`
|
||||||
<tr>
|
<tr>
|
||||||
@@ -175,10 +173,22 @@ function getENVEA_values(port, name){
|
|||||||
},
|
},
|
||||||
error: function(xhr, status, error) {
|
error: function(xhr, status, error) {
|
||||||
console.error('AJAX request failed:', status, error);
|
console.error('AJAX request failed:', status, error);
|
||||||
|
const tableBody = document.getElementById("data-table-body_envea" + name);
|
||||||
|
$("#loading_envea" + name).hide();
|
||||||
|
|
||||||
|
tableBody.innerHTML = `
|
||||||
|
<tr>
|
||||||
|
<td colspan="2" class="text-danger">
|
||||||
|
❌ Error: unable to get data from sensor.<br>
|
||||||
|
<small>${status}: ${error}</small>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function getNoise_values(){
|
function getNoise_values(){
|
||||||
console.log("Data from I2C Noise Sensor:");
|
console.log("Data from I2C Noise Sensor:");
|
||||||
$("#loading_noise").show();
|
$("#loading_noise").show();
|
||||||
@@ -261,92 +271,68 @@ function getBME280_values(){
|
|||||||
|
|
||||||
|
|
||||||
window.onload = function() {
|
window.onload = function() {
|
||||||
fetch('../config.json') // Replace 'deviceID.txt' with 'config.json'
|
|
||||||
.then(response => response.json()) // Parse response as JSON
|
|
||||||
.then(data => {
|
|
||||||
//get device ID
|
|
||||||
const deviceID = data.deviceID.trim().toUpperCase();
|
|
||||||
//document.getElementById('pageTitle_plus_ID').innerText = 'token: ' + deviceID;
|
|
||||||
//get device Name
|
|
||||||
const deviceName = data.deviceName;
|
|
||||||
|
|
||||||
const elements = document.querySelectorAll('.sideBar_sensorName');
|
//NEW way to get config (SQLite)
|
||||||
elements.forEach((element) => {
|
|
||||||
element.innerText = deviceName;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//get local RTC
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: 'launcher.php?type=RTC_time',
|
url: 'launcher.php?type=get_config_sqlite',
|
||||||
dataType: 'text', // Specify that you expect a JSON response
|
dataType:'json',
|
||||||
|
//dataType: 'json', // Specify that you expect a JSON response
|
||||||
method: 'GET', // Use GET or POST depending on your needs
|
method: 'GET', // Use GET or POST depending on your needs
|
||||||
success: function(response) {
|
success: function(response) {
|
||||||
console.log("Local RTC: " + response);
|
console.log("Getting SQLite config table:");
|
||||||
const RTC_Element = document.getElementById("RTC_time");
|
console.log(response);
|
||||||
RTC_Element.textContent = response;
|
|
||||||
|
|
||||||
|
//device name_side bar
|
||||||
|
const elements = document.querySelectorAll('.sideBar_sensorName');
|
||||||
|
elements.forEach((element) => {
|
||||||
|
element.innerText = response.deviceName;
|
||||||
|
});
|
||||||
|
|
||||||
},
|
},
|
||||||
error: function(xhr, status, error) {
|
error: function(xhr, status, error) {
|
||||||
console.error('AJAX request failed:', status, error);
|
console.error('AJAX request failed:', status, error);
|
||||||
}
|
}
|
||||||
});
|
});//end AJAX
|
||||||
|
|
||||||
|
//getting config_scripts table
|
||||||
|
$.ajax({
|
||||||
|
url: 'launcher.php?type=get_config_scripts_sqlite',
|
||||||
|
dataType:'json',
|
||||||
|
//dataType: 'json', // Specify that you expect a JSON response
|
||||||
|
method: 'GET', // Use GET or POST depending on your needs
|
||||||
|
success: function(response) {
|
||||||
|
console.log("Getting SQLite config scripts table:");
|
||||||
|
console.log(response);
|
||||||
|
|
||||||
const container = document.getElementById('card-container'); // Conteneur des cartes
|
const container = document.getElementById('card-container'); // Conteneur des cartes
|
||||||
|
|
||||||
//creates NPM cards
|
//creates NPM card
|
||||||
const NPM_ports = data.NextPM_ports; // Récupère les ports
|
if (response["NPM/get_data_modbus_v3.py"]) {
|
||||||
NPM_ports.forEach((port, index) => {
|
|
||||||
const cardHTML = `
|
const cardHTML = `
|
||||||
<div class="col-sm-3">
|
<div class="col-sm-3">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
Port UART ${port.replace('ttyAMA', '')}
|
Port UART
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">NextPM ${String.fromCharCode(65 + index)}</h5>
|
<h5 class="card-title">NextPM</h5>
|
||||||
<p class="card-text">Capteur particules fines.</p>
|
<p class="card-text">Capteur particules fines.</p>
|
||||||
<button class="btn btn-primary" onclick="getNPM_values('${port}')">Get Data</button>
|
<button class="btn btn-primary" onclick="getNPM_values('ttyAMA5')">Get Data</button>
|
||||||
<div id="loading_${port}" class="spinner-border spinner-border-sm" style="display: none;" role="status"></div>
|
<br>
|
||||||
|
<div id="loading_ttyAMA5" class="spinner-border spinner-border-sm" style="display: none;" role="status"></div>
|
||||||
<table class="table table-striped-columns">
|
<table class="table table-striped-columns">
|
||||||
<tbody id="data-table-body_${port}"></tbody>
|
<tbody id="data-table-body_ttyAMA5"></tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
container.innerHTML += cardHTML; // Ajouter la carte au conteneur
|
|
||||||
});
|
|
||||||
|
|
||||||
//creates ENVEA cards
|
container.innerHTML += cardHTML; // Add the I2C card if condition is met
|
||||||
const ENVEA_sensors = data.envea_sondes.filter(sonde => sonde.connected); // Filter only connected sondes
|
}
|
||||||
|
|
||||||
ENVEA_sensors.forEach((sensor, index) => {
|
|
||||||
const port = sensor.port; // Port from the sensor object
|
|
||||||
const name = sensor.name; // Port from the sensor object
|
|
||||||
const coefficient = sensor.coefficient;
|
|
||||||
const cardHTML = `
|
|
||||||
<div class="col-sm-3">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-header">
|
|
||||||
Port UART ${port.replace('ttyAMA', '')}
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Sonde Envea ${name}</h5>
|
|
||||||
<p class="card-text">Capteur gas.</p>
|
|
||||||
<button class="btn btn-primary" onclick="getENVEA_values('${port}','${name}','${coefficient}')">Get Data</button>
|
|
||||||
<div id="loading_envea${name}" class="spinner-border spinner-border-sm" style="display: none;" role="status"></div>
|
|
||||||
<table class="table table-striped-columns">
|
|
||||||
<tbody id="data-table-body_envea${name}"></tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>`;
|
|
||||||
container.innerHTML += cardHTML; // Ajouter la carte au conteneur
|
|
||||||
});
|
|
||||||
|
|
||||||
//creates i2c BME280 card
|
//creates i2c BME280 card
|
||||||
if (data["BME280/get_data_v2.py"]) {
|
if (response["BME280/get_data_v2.py"]) {
|
||||||
const i2C_BME_HTML = `
|
const i2C_BME_HTML = `
|
||||||
<div class="col-sm-3">
|
<div class="col-sm-3">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
@@ -370,7 +356,7 @@ window.onload = function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//creates i2c sound card
|
//creates i2c sound card
|
||||||
if (data.i2C_sound) {
|
if (response.i2C_sound) {
|
||||||
const i2C_HTML = `
|
const i2C_HTML = `
|
||||||
<div class="col-sm-3">
|
<div class="col-sm-3">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
@@ -395,9 +381,80 @@ window.onload = function() {
|
|||||||
container.innerHTML += i2C_HTML; // Add the I2C card if condition is met
|
container.innerHTML += i2C_HTML; // Add the I2C card if condition is met
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
//Si on a des SONDES ENVEA connectée il faut faire un deuxième call dans la table envea_sondes_table
|
||||||
.catch(error => console.error('Error loading config.json:', error));
|
//creates ENVEA cards
|
||||||
|
if (response["envea/read_value_v2.py"]) {
|
||||||
|
console.log("Need to display ENVEA sondes");
|
||||||
|
//getting config_scripts table
|
||||||
|
$.ajax({
|
||||||
|
url: 'launcher.php?type=get_envea_sondes_table_sqlite',
|
||||||
|
dataType:'json',
|
||||||
|
//dataType: 'json', // Specify that you expect a JSON response
|
||||||
|
method: 'GET', // Use GET or POST depending on your needs
|
||||||
|
success: function(sondes) {
|
||||||
|
console.log("Getting SQLite envea sondes table:");
|
||||||
|
console.log(sondes);
|
||||||
|
const ENVEA_sensors = sondes.filter(sonde => sonde.connected); // Filter only connected sondes
|
||||||
|
|
||||||
|
ENVEA_sensors.forEach((sensor, index) => {
|
||||||
|
const port = sensor.port; // Port from the sensor object
|
||||||
|
const name = sensor.name; // Port from the sensor object
|
||||||
|
const coefficient = sensor.coefficient;
|
||||||
|
const cardHTML = `
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
Port UART ${port.replace('ttyAMA', '')}
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Sonde Envea ${name}</h5>
|
||||||
|
<p class="card-text">Capteur gas.</p>
|
||||||
|
<button class="btn btn-primary" onclick="getENVEA_values('${port}','${name}')">Get Data</button>
|
||||||
|
<div id="loading_envea${name}" class="spinner-border spinner-border-sm" style="display: none;" role="status"></div>
|
||||||
|
<table class="table table-striped-columns">
|
||||||
|
<tbody id="data-table-body_envea${name}"></tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>`;
|
||||||
|
container.innerHTML += cardHTML; // Ajouter la carte au conteneur
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
error: function(xhr, status, error) {
|
||||||
|
console.error('AJAX request failed:', status, error);
|
||||||
}
|
}
|
||||||
|
});//end AJAX envea Sondes
|
||||||
|
|
||||||
|
|
||||||
|
}//end if
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
error: function(xhr, status, error) {
|
||||||
|
console.error('AJAX request failed:', status, error);
|
||||||
|
}
|
||||||
|
});//end AJAX (config_scripts)
|
||||||
|
|
||||||
|
//get local RTC
|
||||||
|
$.ajax({
|
||||||
|
url: 'launcher.php?type=RTC_time',
|
||||||
|
dataType: 'text', // Specify that you expect a JSON response
|
||||||
|
method: 'GET', // Use GET or POST depending on your needs
|
||||||
|
success: function(response) {
|
||||||
|
console.log("Local RTC: " + response);
|
||||||
|
const RTC_Element = document.getElementById("RTC_time");
|
||||||
|
RTC_Element.textContent = response;
|
||||||
|
|
||||||
|
},
|
||||||
|
error: function(xhr, status, error) {
|
||||||
|
console.error('AJAX request failed:', status, error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
} //end windows onload
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -165,16 +165,6 @@ def blink_led(pin, blink_count, delay=1):
|
|||||||
GPIO.output(pin, GPIO.LOW) # Ensure LED is off
|
GPIO.output(pin, GPIO.LOW) # Ensure LED is off
|
||||||
print(f"LED on GPIO {pin} turned OFF (cleanup avoided)")
|
print(f"LED on GPIO {pin} turned OFF (cleanup avoided)")
|
||||||
|
|
||||||
#get data from config (from JSON file)
|
|
||||||
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 {}
|
|
||||||
|
|
||||||
#get config data from SQLite table
|
#get config data from SQLite table
|
||||||
def load_config_sqlite():
|
def load_config_sqlite():
|
||||||
"""
|
"""
|
||||||
@@ -208,60 +198,51 @@ def load_config_sqlite():
|
|||||||
print(f"Error loading config from SQLite: {e}")
|
print(f"Error loading config from SQLite: {e}")
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
def load_config_scripts_sqlite():
|
||||||
|
|
||||||
#Fonction pour mettre à jour le JSON de configuration
|
|
||||||
def update_json_key(file_path, key, value):
|
|
||||||
"""
|
"""
|
||||||
Updates a specific key in a JSON file with a new value.
|
Load script configuration data from SQLite config_scripts_table
|
||||||
|
|
||||||
:param file_path: Path to the JSON file.
|
Returns:
|
||||||
:param key: The key to update in the JSON file.
|
dict: Script paths as keys and enabled status as boolean values
|
||||||
:param value: The new value to assign to the key.
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
# Load the existing data
|
# Query the config_scripts_table
|
||||||
with open(file_path, "r") as file:
|
cursor.execute("SELECT script_path, enabled FROM config_scripts_table")
|
||||||
data = json.load(file)
|
rows = cursor.fetchall()
|
||||||
|
|
||||||
# Check if the key exists in the JSON file
|
# Create config dictionary with script paths as keys and enabled status as boolean values
|
||||||
if key in data:
|
scripts_config = {}
|
||||||
data[key] = value # Update the key with the new value
|
for script_path, enabled in rows:
|
||||||
else:
|
# Convert integer enabled value (0/1) to boolean
|
||||||
print(f"Key '{key}' not found in the JSON file.")
|
scripts_config[script_path] = bool(enabled)
|
||||||
return
|
|
||||||
|
|
||||||
# Write the updated data back to the file
|
return scripts_config
|
||||||
with open(file_path, "w") as file:
|
|
||||||
json.dump(data, file, indent=2) # Use indent for pretty printing
|
|
||||||
|
|
||||||
print(f"💾updating '{key}' to '{value}'.")
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error updating the JSON file: {e}")
|
print(f"Error loading scripts config from SQLite: {e}")
|
||||||
|
return {}
|
||||||
|
|
||||||
# Define the config file path
|
#Load config
|
||||||
config_file = '/var/www/nebuleair_pro_4g/config.json'
|
config = load_config_sqlite()
|
||||||
|
#config
|
||||||
# Load the configuration data (JSON way)
|
device_id = config.get('deviceID', 'unknown')
|
||||||
config = load_config(config_file)
|
device_id = device_id.upper()
|
||||||
|
modem_config_mode = config.get('modem_config_mode', False)
|
||||||
device_latitude_raw = config.get('latitude_raw', 0)
|
device_latitude_raw = config.get('latitude_raw', 0)
|
||||||
device_longitude_raw = config.get('longitude_raw', 0)
|
device_longitude_raw = config.get('longitude_raw', 0)
|
||||||
baudrate = config.get('SaraR4_baudrate', 115200) #baudrate du sara R4
|
modem_version=config.get('modem_version', "")
|
||||||
device_id = config.get('deviceID', '').upper() #device ID en maj
|
Sara_baudrate = config.get('SaraR4_baudrate', 115200)
|
||||||
bme_280_config = config.get('BME280/get_data_v2.py', False) #présence du BME280
|
npm_5channel = config.get('NextPM_5channels', False) #5 canaux du NPM
|
||||||
envea_cairsens= config.get('envea/read_value_v2.py', False)
|
selected_networkID = int(config.get('SARA_R4_neworkID', 0))
|
||||||
mppt_charger= config.get('MPPT/read.py', False)
|
|
||||||
wind_meter= config.get('windMeter/read.py', False)
|
|
||||||
send_uSpot = config.get('send_uSpot', False) #envoi sur MicroSpot ()
|
send_uSpot = config.get('send_uSpot', False) #envoi sur MicroSpot ()
|
||||||
reset_uSpot_url = False
|
reset_uSpot_url = False
|
||||||
selected_networkID = int(config.get('SARA_R4_neworkID', 0))
|
|
||||||
npm_5channel = config.get('NextPM_5channels', False) #5 canaux du NPM
|
|
||||||
modem_version=config.get('modem_version', "")
|
|
||||||
modem_config_mode = config.get('modem_config_mode', False) #modem 4G en mode configuration
|
|
||||||
|
|
||||||
#Load config new way
|
|
||||||
config = load_config_sqlite()
|
|
||||||
|
|
||||||
|
#config_scripts
|
||||||
|
config_scripts = load_config_scripts_sqlite()
|
||||||
|
bme_280_config = config_scripts.get('BME280/get_data_v2.py', False)
|
||||||
|
envea_cairsens= config_scripts.get('envea/read_value_v2.py', False)
|
||||||
|
mppt_charger= config_scripts.get('MPPT/read.py', False)
|
||||||
|
wind_meter= config_scripts.get('windMeter/read.py', False)
|
||||||
|
|
||||||
#update device id in the payload json
|
#update device id in the payload json
|
||||||
payload_json["nebuleairid"] = device_id
|
payload_json["nebuleairid"] = device_id
|
||||||
@@ -273,7 +254,7 @@ if modem_config_mode:
|
|||||||
|
|
||||||
ser_sara = serial.Serial(
|
ser_sara = serial.Serial(
|
||||||
port='/dev/ttyAMA2',
|
port='/dev/ttyAMA2',
|
||||||
baudrate=baudrate, #115200 ou 9600
|
baudrate=Sara_baudrate, #115200 ou 9600
|
||||||
parity=serial.PARITY_NONE, #PARITY_NONE, PARITY_EVEN or PARITY_ODD
|
parity=serial.PARITY_NONE, #PARITY_NONE, PARITY_EVEN or PARITY_ODD
|
||||||
stopbits=serial.STOPBITS_ONE,
|
stopbits=serial.STOPBITS_ONE,
|
||||||
bytesize=serial.EIGHTBITS,
|
bytesize=serial.EIGHTBITS,
|
||||||
@@ -767,8 +748,6 @@ try:
|
|||||||
print('<span style="color: red;font-weight: bold;">ATTENTION: CME ERROR</span>')
|
print('<span style="color: red;font-weight: bold;">ATTENTION: CME ERROR</span>')
|
||||||
print("error:", lines[-1])
|
print("error:", lines[-1])
|
||||||
print("*****")
|
print("*****")
|
||||||
#update status
|
|
||||||
update_json_key(config_file, "SARA_R4_network_status", "disconnected")
|
|
||||||
|
|
||||||
# Gestion de l'erreur spécifique
|
# Gestion de l'erreur spécifique
|
||||||
if "No connection to phone" in lines[-1]:
|
if "No connection to phone" in lines[-1]:
|
||||||
@@ -807,7 +786,6 @@ try:
|
|||||||
if len(parts) == 3 and parts[-1] == '0': # The third value indicates success
|
if len(parts) == 3 and parts[-1] == '0': # The third value indicates success
|
||||||
print("*****")
|
print("*****")
|
||||||
print('<span style="color: red;font-weight: bold;">⛔ATTENTION: HTTP operation failed</span>')
|
print('<span style="color: red;font-weight: bold;">⛔ATTENTION: HTTP operation failed</span>')
|
||||||
update_json_key(config_file, "SARA_R4_network_status", "disconnected")
|
|
||||||
print("*****")
|
print("*****")
|
||||||
print("Blink red LED")
|
print("Blink red LED")
|
||||||
# Run LED blinking in a separate thread
|
# Run LED blinking in a separate thread
|
||||||
@@ -854,7 +832,6 @@ try:
|
|||||||
# 2.2 code 1 (✅✅HHTP / UUHTTPCR succeded✅✅)
|
# 2.2 code 1 (✅✅HHTP / UUHTTPCR succeded✅✅)
|
||||||
else:
|
else:
|
||||||
print('<span style="font-weight: bold;">✅✅HTTP operation successful.</span>')
|
print('<span style="font-weight: bold;">✅✅HTTP operation successful.</span>')
|
||||||
update_json_key(config_file, "SARA_R4_network_status", "connected")
|
|
||||||
print("Blink blue LED")
|
print("Blink blue LED")
|
||||||
led_thread = Thread(target=blink_led, args=(23, 5, 0.5))
|
led_thread = Thread(target=blink_led, args=(23, 5, 0.5))
|
||||||
led_thread.start()
|
led_thread.start()
|
||||||
@@ -1118,7 +1095,6 @@ try:
|
|||||||
print("error:", lines[-1])
|
print("error:", lines[-1])
|
||||||
print("*****")
|
print("*****")
|
||||||
#update status
|
#update status
|
||||||
#update_json_key(config_file, "SARA_R4_network_status", "disconnected")
|
|
||||||
|
|
||||||
# Gestion de l'erreur spécifique
|
# Gestion de l'erreur spécifique
|
||||||
if "No connection to phone" in lines[-1]:
|
if "No connection to phone" in lines[-1]:
|
||||||
@@ -1144,7 +1120,6 @@ try:
|
|||||||
if len(parts) == 3 and parts[-1] == '0': # The third value indicates success
|
if len(parts) == 3 and parts[-1] == '0': # The third value indicates success
|
||||||
print("*****")
|
print("*****")
|
||||||
print('<span style="color: red;font-weight: bold;">⛔ATTENTION: HTTP operation failed</span>')
|
print('<span style="color: red;font-weight: bold;">⛔ATTENTION: HTTP operation failed</span>')
|
||||||
update_json_key(config_file, "SARA_R4_network_status", "disconnected")
|
|
||||||
print("*****")
|
print("*****")
|
||||||
print("Blink red LED")
|
print("Blink red LED")
|
||||||
# Run LED blinking in a separate thread
|
# Run LED blinking in a separate thread
|
||||||
@@ -1184,7 +1159,6 @@ try:
|
|||||||
else:
|
else:
|
||||||
# Si la commande HTTP a réussi
|
# Si la commande HTTP a réussi
|
||||||
print('<span style="font-weight: bold;">✅✅HTTP operation successful.</span>')
|
print('<span style="font-weight: bold;">✅✅HTTP operation successful.</span>')
|
||||||
update_json_key(config_file, "SARA_R4_network_status", "connected")
|
|
||||||
print("Blink blue LED")
|
print("Blink blue LED")
|
||||||
led_thread = Thread(target=blink_led, args=(23, 5, 0.5))
|
led_thread = Thread(target=blink_led, args=(23, 5, 0.5))
|
||||||
led_thread.start()
|
led_thread.start()
|
||||||
|
|||||||
0
config.json.dist → old/config.json.dist
Executable file → Normal file
0
config.json.dist → old/config.json.dist
Executable file → Normal file
0
install_software.yaml → old/install_software.yaml
Executable file → Normal file
0
install_software.yaml → old/install_software.yaml
Executable file → Normal file
Reference in New Issue
Block a user