diff --git a/html/admin.html b/html/admin.html index c4ce27c..b643767 100755 --- a/html/admin.html +++ b/html/admin.html @@ -69,27 +69,51 @@ + +
- -
- + + +
+ +
+
- +
+
+ + +
+ +
+ + +
+ + @@ -138,6 +162,22 @@ + + + + +
+ +
+ + @@ -170,117 +210,208 @@ }); }); +//end document.addEventListener + window.onload = function() { - fetch('../config.json') // Replace 'deviceID.txt' with 'config.json' - .then(response => response.json()) // Parse response as JSON - .then(data => { - console.log("Getting config file (onload)"); - //get device ID - const deviceID = data.deviceID.trim().toUpperCase(); - //document.getElementById('pageTitle_plus_ID').innerText = 'token: ' + deviceID; - //get device Name - const deviceName = data.deviceName; + //NEW way to get config (SQLite) + $.ajax({ + url: 'launcher.php?type=get_config_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 table:"); + console.log(response); + //device name + const deviceName = document.getElementById("device_name"); + deviceName.value = response.deviceName; + //device name_side bar + const elements = document.querySelectorAll('.sideBar_sensorName'); + elements.forEach((element) => { + element.innerText = response.deviceName; + }); + //device ID + const deviceID = response.deviceID.trim().toUpperCase(); + const device_ID = document.getElementById("device_ID"); + device_ID.value = response.deviceID.toUpperCase(); + //nextPM send 5 channels + const checkbox_nmp5channels = document.getElementById("check_NPM_5channels"); + checkbox_nmp5channels.checked = response.npm_5channel; - console.log("Device Name: " + deviceName); - console.log("Device ID: " + deviceID); - - - const elements = document.querySelectorAll('.sideBar_sensorName'); - elements.forEach((element) => { - element.innerText = deviceName; - }); + }, + error: function(xhr, 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); - //get BME check - const checkbox = document.getElementById("check_bme280"); - checkbox.checked = data["BME280/get_data_v2.py"]; + const checkbox_NPM = document.getElementById("check_NPM"); + const checkbox_bme = document.getElementById("check_bme280"); + const checkbox_envea = document.getElementById("check_envea"); + const checkbox_solar = document.getElementById("check_solarBattery"); + const checkbox_wind = document.getElementById("check_WindMeter"); - //get NPM-5channels check - const checkbox_NPM_5channels = document.getElementById("check_NPM_5channels"); - checkbox_NPM_5channels.checked = data["NextPM_5channels"]; + checkbox_NPM.checked = response["NPM/get_data_modbus_v3.py"]; + checkbox_bme.checked = response["BME280/get_data_v2.py"]; + checkbox_envea.checked = response["envea/read_value_v2.py"]; + checkbox_solar.checked = response["MPPT/read.py"]; + checkbox_wind.checked = response["windMeter/read.py"]; + }, + error: function(xhr, status, error) { + console.error('AJAX request failed:', status, error); + } + });//end AJAX + - //get sonde Envea check - const checkbox_envea = document.getElementById("check_envea"); - checkbox_envea.checked = data["envea/read_value_v2.py"]; + //OLD way to get config (JSON) + /* + fetch('../config.json') // Replace 'deviceID.txt' with 'config.json' + .then(response => response.json()) // Parse response as JSON + .then(data => { + console.log("Getting config file (onload)"); + //get device ID + //document.getElementById('pageTitle_plus_ID').innerText = 'token: ' + deviceID; + //get device Name + //const deviceName = data.deviceName; - //device name - const device_name = document.getElementById("device_name"); - device_name.value = data.deviceName; + //get BME check + const checkbox = document.getElementById("check_bme280"); + checkbox.checked = data["BME280/get_data_v2.py"]; - //device ID - const device_ID = document.getElementById("device_ID"); - device_ID.value = data.deviceID.toUpperCase(); + //get NPM-5channels check + const checkbox_NPM_5channels = document.getElementById("check_NPM_5channels"); + checkbox_NPM_5channels.checked = data["NextPM_5channels"]; - //get system time and RTC module - $.ajax({ - url: 'launcher.php?type=sys_RTC_module_time', - dataType: 'json', // Specify that you expect a JSON response - method: 'GET', // Use GET or POST depending on your needs - success: function(response) { - console.log(response); - // Update the input fields with the received JSON data - document.getElementById("sys_local_time").value = response.system_local_time; - document.getElementById("sys_UTC_time").value = response.system_utc_time; - document.getElementById("RTC_utc_time").value = response.rtc_module_time; + //get sonde Envea check + const checkbox_envea = document.getElementById("check_envea"); + checkbox_envea.checked = data["envea/read_value_v2.py"]; - // Get the time difference - const timeDiff = response.time_difference_seconds; + //device name + //const device_name = document.getElementById("device_name"); + //device_name.value = data.deviceName; - // Reference to the alert container - const alertContainer = document.getElementById("alert_container"); + + }) + .catch(error => console.error('Error loading config.json:', error)); + */ - // Remove any previous alert - alertContainer.innerHTML = ""; - // Add an alert based on time difference - if (typeof timeDiff === "number") { - if (timeDiff >= 0 && timeDiff <= 10) { - alertContainer.innerHTML = ` - `; - } else if (timeDiff > 10) { - alertContainer.innerHTML = ` - `; - } - } - }, - error: function(xhr, status, error) { - console.error('AJAX request failed:', status, error); - } - }); - //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); - } - }); + //get system time and RTC module + $.ajax({ + url: 'launcher.php?type=sys_RTC_module_time', + 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 RTC times"); + + console.log(response); + // Update the input fields with the received JSON data + document.getElementById("sys_local_time").value = response.system_local_time; + document.getElementById("sys_UTC_time").value = response.system_utc_time; + document.getElementById("RTC_utc_time").value = response.rtc_module_time; - }) - .catch(error => console.error('Error loading config.json:', error)); - } + // Get the time difference + const timeDiff = response.time_difference_seconds; + // Reference to the alert container + const alertContainer = document.getElementById("alert_container"); + + // Remove any previous alert + alertContainer.innerHTML = ""; + + // Add an alert based on time difference + if (typeof timeDiff === "number") { + if (timeDiff >= 0 && timeDiff <= 10) { + alertContainer.innerHTML = ` + `; + } else if (timeDiff > 10) { + alertContainer.innerHTML = ` + `; + } + } + }, + error: function(xhr, status, error) { + console.error('AJAX request failed:', status, error); + } + });//end AJAX + + //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 AJAx + + +} //end window.onload + function update_config_sqlite(param, value){ console.log("Updating sqlite ",param," : ", value); + const toastLiveExample = document.getElementById('liveToast') + const toastBody = toastLiveExample.querySelector('.toast-body'); $.ajax({ url: 'launcher.php?type=update_config_sqlite¶m='+param+'&value='+value, - dataType: 'text', // Specify that you expect a JSON response + dataType: 'json', // Specify that you expect a JSON response method: 'GET', // Use GET or POST depending on your needs cache: false, // Prevent AJAX from caching success: function(response) { - console.log(response); + console.log(response); + // Format the response nicely + let formattedMessage = ''; + + if (response.success) { + // Success message + toastLiveExample.classList.remove('text-bg-danger'); + toastLiveExample.classList.add('text-bg-success'); + + formattedMessage = ` + Success!
+ Parameter: ${response.param || param}
+ Value: ${response.value || checked}
+ ${response.message || ''} + `; + } else { + // Error message + toastLiveExample.classList.remove('text-bg-success'); + toastLiveExample.classList.add('text-bg-danger'); + + formattedMessage = ` + Error!
+ ${response.error || 'Unknown error'}
+ Parameter: ${response.param || param} + `; + } + + // Update the toast body with formatted content + toastBody.innerHTML = formattedMessage; + // Show the toast + const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastLiveExample) + toastBootstrap.show() + }, error: function(xhr, status, error) { console.error('AJAX request failed:', status, error); @@ -288,6 +419,56 @@ function update_config_sqlite(param, value){ }); } +function update_config_scripts_sqlite(param, value) { + console.log("Updating scripts sqlite ", param, " : ", value); + const toastLiveExample = document.getElementById('liveToast') + const toastBody = toastLiveExample.querySelector('.toast-body'); + + $.ajax({ + url: 'launcher.php?type=update_config_scripts_sqlite¶m=' + param + '&value=' + value, + dataType: 'json', + method: 'GET', + cache: false, + success: function(response) { + console.log(response); + // Format the response nicely + let formattedMessage = ''; + + if (response.success) { + // Success message + toastLiveExample.classList.remove('text-bg-danger'); + toastLiveExample.classList.add('text-bg-success'); + + formattedMessage = ` + Success!
+ Parameter: ${response.script_path || param}
+ Value: ${response.enabled !== undefined ? response.enabled : value}
+ ${response.message || ''} + `; + } else { + // Error message + toastLiveExample.classList.remove('text-bg-success'); + toastLiveExample.classList.add('text-bg-danger'); + + formattedMessage = ` + Error!
+ ${response.error || 'Unknown error'}
+ Parameter: ${response.script_path || param} + `; + } + + // Update the toast body with formatted content + toastBody.innerHTML = formattedMessage; + // Show the toast + const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastLiveExample) + toastBootstrap.show() + }, + error: function(xhr, status, error) { + console.error('AJAX request failed:', status, error); + } + }); +} + function update_config(param, value){ console.log("Updating ",param," : ", value); @@ -346,7 +527,7 @@ function set_RTC_withNTP(){ error: function(xhr, status, error) { console.error('AJAX request failed:', status, error); } - }); + }); //end ajax } function set_RTC_withBrowser(){ @@ -374,7 +555,7 @@ function set_RTC_withBrowser(){ error: function(xhr, status, error) { console.error('AJAX request failed:', status, error); } - }); + }); //end ajax } diff --git a/html/index.html b/html/index.html index a72bc31..cce3822 100755 --- a/html/index.html +++ b/html/index.html @@ -135,6 +135,30 @@ window.onload = function() { + //NEW way to get data from SQLITE + $.ajax({ + url: 'launcher.php?type=get_config_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 table:"); + console.log(response); + + //get device Name (for the side bar) + const deviceName = response.deviceName; + const elements = document.querySelectorAll('.sideBar_sensorName'); + elements.forEach((element) => { + element.innerText = deviceName; + }); + + }, + error: function(xhr, status, error) { + console.error('AJAX request failed:', status, error); + } + }); + + /* OLD way of getting config data fetch('../config.json') // Replace 'deviceID.txt' with 'config.json' .then(response => response.json()) // Parse response as JSON .then(data => { @@ -151,7 +175,12 @@ window.onload = function() { elements.forEach((element) => { element.innerText = deviceName; }); - + + //end fetch config + }) + .catch(error => console.error('Error loading config.json:', error)); + //end windows on load + */ //get local RTC $.ajax({ url: 'launcher.php?type=RTC_time', @@ -421,10 +450,6 @@ window.onload = function() { - //end fetch config - }) - .catch(error => console.error('Error loading config.json:', error)); - //end windows on load } diff --git a/html/launcher.php b/html/launcher.php index 03afc46..ddb03d7 100755 --- a/html/launcher.php +++ b/html/launcher.php @@ -1,13 +1,16 @@ setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + // Get all main configuration entries + $config_query = $db->query("SELECT key, value, type FROM config_table"); + $config_data = $config_query->fetchAll(PDO::FETCH_ASSOC); + + // Convert data types according to their 'type' field + $result = []; + foreach ($config_data as $item) { + $key = $item['key']; + $value = $item['value']; + $type = $item['type']; + + // Convert value based on its type + switch ($type) { + case 'bool': + $parsed_value = ($value == '1' || $value == 'true') ? true : false; + break; + case 'int': + $parsed_value = intval($value); + break; + case 'float': + $parsed_value = floatval($value); + break; + default: + $parsed_value = $value; + } + + $result[$key] = $parsed_value; + } + + // Return JSON response + header('Content-Type: application/json'); + echo json_encode($result, JSON_PRETTY_PRINT); + + } catch (PDOException $e) { + // Return error as JSON + header('Content-Type: application/json'); + echo json_encode(['error' => 'Database error: ' . $e->getMessage()]); + } +} + +//GETING data from config_scrips_table (SQLite DB) +if ($type == "get_config_scripts_sqlite") { + + try { + $db = new PDO("sqlite:$database_path"); + $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + // Get all main configuration entries + $config_query = $db->query("SELECT * FROM config_scripts_table"); + $config_data = $config_query->fetchAll(PDO::FETCH_ASSOC); + + // Convert data types according to their 'type' field + $result = []; + foreach ($config_data as $item) { + $script_path = $item['script_path']; + $enabled = $item['enabled']; + + // Convert the enabled field to a proper boolean + $result[$script_path] = ($enabled == 1); + } + + // 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 if ($type == "update_config_sqlite") { - echo "updating...."; $param = $_GET['param'] ?? null; $value = $_GET['value'] ?? null; @@ -35,7 +118,6 @@ if ($type == "update_config_sqlite") { exit; } - $database_path = "/var/www/nebuleair_pro_4g/sqlite/sensors.db"; try { $db = new PDO("sqlite:$database_path"); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); @@ -85,9 +167,56 @@ if ($type == "update_config_sqlite") { } } +//UPDATING the config_scripts table from SQLite DB +if ($type == "update_config_scripts_sqlite") { + $script_path = $_GET['param'] ?? null; + $enabled = $_GET['value'] ?? null; + + if ($script_path === null || $enabled === null) { + echo json_encode(["error" => "Missing parameter or value"]); + exit; + } + + try { + $db = new PDO("sqlite:$database_path"); + $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + // First, check if parameter exists and get its type + $checkStmt = $db->prepare("SELECT enabled FROM config_scripts_table WHERE script_path = :script_path"); + $checkStmt->bindParam(':script_path', $script_path); + $checkStmt->execute(); + $result = $checkStmt->fetch(PDO::FETCH_ASSOC); + + if ($result) { + // Convert enabled value to 0 or 1 + $enabledValue = (filter_var($enabled, FILTER_VALIDATE_BOOLEAN)) ? 1 : 0; + + // Update the enabled status + $updateStmt = $db->prepare("UPDATE config_scripts_table SET enabled = :enabled WHERE script_path = :script_path"); + $updateStmt->bindParam(':enabled', $enabledValue, PDO::PARAM_INT); + $updateStmt->bindParam(':script_path', $script_path); + $updateStmt->execute(); + + echo json_encode([ + "success" => true, + "message" => "Script configuration updated successfully", + "script_path" => $script_path, + "enabled" => (bool)$enabledValue + ], JSON_UNESCAPED_SLASHES); // Prevent escaping forward slashes + } else { + echo json_encode([ + "error" => "Script path not found in configuration", + "script_path" => $script_path + ], JSON_UNESCAPED_SLASHES); // Prevent escaping forward slashes + } + } catch (PDOException $e) { + echo json_encode(["error" => $e->getMessage()]); + } +} +//update the config (old JSON updating) if ($type == "update_config") { - echo "updating...."; + echo "updating.... "; $param=$_GET['param']; $value=$_GET['value']; $configFile = '../config.json'; diff --git a/html/saraR4.html b/html/saraR4.html index f779680..4bf5ec3 100755 --- a/html/saraR4.html +++ b/html/saraR4.html @@ -59,11 +59,12 @@ +
@@ -71,7 +72,7 @@

General information.

- +
@@ -84,7 +85,7 @@

SIM card information.

- +
@@ -109,7 +110,7 @@

Signal strength

- +
@@ -121,7 +122,7 @@

Modem Reset

- +
@@ -304,7 +305,20 @@
- + + + +
+ +
+
@@ -317,35 +331,62 @@