Extraction du code self-test dans des fichiers partagés (selftest.js + selftest-modal.html) pour éviter la duplication. Ajout du bouton Run Self Test sur les pages index, sensors et admin. Nouveau test RTC qui vérifie la connexion du module DS3231 et la synchronisation horloge. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
635 lines
23 KiB
HTML
Executable File
635 lines
23 KiB
HTML
Executable File
<!DOCTYPE html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>NebuleAir</title>
|
|
<link rel="stylesheet" href="assets/css/bootstrap.min.css">
|
|
<style>
|
|
body {
|
|
overflow-x: hidden;
|
|
}
|
|
|
|
#sidebar a.nav-link {
|
|
position: relative;
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
#sidebar a.nav-link:hover {
|
|
background-color: rgba(0, 0, 0, 0.5);
|
|
}
|
|
|
|
#sidebar a.nav-link svg {
|
|
margin-right: 8px;
|
|
/* Add spacing between icons and text */
|
|
}
|
|
|
|
#sidebar {
|
|
transition: transform 0.3s ease-in-out;
|
|
}
|
|
|
|
.offcanvas-backdrop {
|
|
z-index: 1040;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
<!-- Topbar -->
|
|
<span id="topbar"></span>
|
|
|
|
<!-- Sidebar Offcanvas for Mobile -->
|
|
<div class="offcanvas offcanvas-start text-white bg-dark" tabindex="-1" id="sidebarOffcanvas"
|
|
aria-labelledby="sidebarOffcanvasLabel">
|
|
<div class="offcanvas-header">
|
|
<h5 class="offcanvas-title" id="sidebarOffcanvasLabel">NebuleAir</h5>
|
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
|
</div>
|
|
<div class="offcanvas-body" id="sidebar_mobile">
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<div class="container-fluid mt-5">
|
|
<div class="row">
|
|
<aside class="col-md-2 col-lg-1 d-none d-md-block vh-100 position-fixed bg-dark text-white" id="sidebar">
|
|
</aside>
|
|
<!-- Main content -->
|
|
<main class="col-md-10 ms-sm-auto col-lg-11 offset-md-2 offset-lg-1 px-md-4">
|
|
<h1 class="mt-4" data-i18n="sensors.title">Les sondes de mesure</h1>
|
|
<p data-i18n="sensors.description">Votre capteur NebuleAir est équipé de une ou plusieurs sondes qui permettent
|
|
de mesurer certaines variables environnementales. La mesure
|
|
est automatique mais vous pouvez ici vous assurer de leur bon fonctionnement.
|
|
</p>
|
|
<button class="btn btn-success mb-3 btn_selfTest" onclick="runSelfTest()">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-check2-circle me-1" viewBox="0 0 16 16">
|
|
<path d="M2.5 8a5.5 5.5 0 1 1 11 0 5.5 5.5 0 0 1-11 0z"/>
|
|
<path d="M15.354 3.354a.5.5 0 0 0-.708-.708L8 9.293 5.354 6.646a.5.5 0 1 0-.708.708l3 3a.5.5 0 0 0 .708 0l7-7z"/>
|
|
</svg>
|
|
Run Self Test
|
|
</button>
|
|
|
|
<div class="row mb-3" id="card-container"></div>
|
|
</main>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- JAVASCRIPT -->
|
|
|
|
<!-- Link Ajax locally -->
|
|
<script src="assets/jquery/jquery-3.7.1.min.js"></script>
|
|
<!-- Link Bootstrap JS and Popper.js locally -->
|
|
<script src="assets/js/bootstrap.bundle.js"></script>
|
|
<!-- i18n translation system -->
|
|
<script src="assets/js/i18n.js"></script>
|
|
<script src="assets/js/topbar-logo.js"></script>
|
|
<script src="assets/js/selftest.js"></script>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
const elementsToLoad = [
|
|
{ id: 'topbar', file: 'topbar.html' },
|
|
{ id: 'sidebar', file: 'sidebar.html' },
|
|
{ id: 'sidebar_mobile', file: 'sidebar.html' }
|
|
];
|
|
|
|
elementsToLoad.forEach(({ id, file }) => {
|
|
fetch(file)
|
|
.then(response => response.text())
|
|
.then(data => {
|
|
const element = document.getElementById(id);
|
|
if (element) {
|
|
element.innerHTML = data;
|
|
// Apply translations after loading dynamic content
|
|
if (window.i18n && typeof window.i18n.applyTranslations === 'function') {
|
|
window.i18n.applyTranslations();
|
|
}
|
|
}
|
|
})
|
|
.catch(error => console.error(`Error loading ${file}:`, error));
|
|
});
|
|
});
|
|
|
|
function getNPM_values(port) {
|
|
console.log("Data from NPM (port " + port + "):");
|
|
$("#loading_" + port).show();
|
|
|
|
$.ajax({
|
|
url: 'launcher.php?type=npm&port=' + port,
|
|
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);
|
|
const tableBody = document.getElementById("data-table-body_" + port);
|
|
tableBody.innerHTML = "";
|
|
|
|
$("#loading_" + port).hide();
|
|
// Create an array of the desired keys
|
|
const keysToShow = ["PM1", "PM25", "PM10", "message"];
|
|
// Error messages mapping
|
|
const errorMessages = {
|
|
"notReady": "Sensor is not ready",
|
|
"fanError": "Fan malfunction detected",
|
|
"laserError": "Laser malfunction detected",
|
|
"heatError": "Heating system error",
|
|
"t_rhError": "Temperature/Humidity sensor error",
|
|
"memoryError": "Memory failure detected",
|
|
"degradedState": "Sensor in degraded state"
|
|
};
|
|
// Add only the specified elements to the table
|
|
keysToShow.forEach(key => {
|
|
if (response[key] !== undefined) { // Check if the key exists in the response
|
|
const value = response[key];
|
|
$("#data-table-body_" + port).append(`
|
|
<tr>
|
|
<td>${key}</td>
|
|
<td>${value} µg/m³</td>
|
|
</tr>
|
|
`);
|
|
}
|
|
});
|
|
|
|
// Check for errors and add them to the table
|
|
Object.keys(errorMessages).forEach(errorKey => {
|
|
if (response[errorKey] === 1) {
|
|
$("#data-table-body_" + port).append(`
|
|
<tr class="error-row">
|
|
<td><b>${errorKey}</b></td>
|
|
<td style="color: red;">⚠ ${errorMessages[errorKey]}</td>
|
|
</tr>
|
|
`);
|
|
}
|
|
});
|
|
},
|
|
error: function (xhr, status, error) {
|
|
console.error('AJAX request failed:', status, error);
|
|
}
|
|
});
|
|
}
|
|
|
|
function getNPM_firmware(port) {
|
|
console.log("Firmware version from NPM (port " + port + "):");
|
|
$("#loading_fw_" + port).show();
|
|
|
|
$.ajax({
|
|
url: 'launcher.php?type=npm_firmware&port=' + port,
|
|
dataType: 'json',
|
|
method: 'GET',
|
|
success: function (response) {
|
|
console.log(response);
|
|
$("#loading_fw_" + port).hide();
|
|
const fwSpan = document.getElementById("fw_version_" + port);
|
|
if (response.firmware_version !== undefined) {
|
|
fwSpan.innerHTML = '<span class="badge bg-success">Firmware: ' + response.firmware_version + '</span>';
|
|
} else {
|
|
fwSpan.innerHTML = '<span class="badge bg-danger">Error reading firmware</span>';
|
|
}
|
|
},
|
|
error: function (xhr, status, error) {
|
|
console.error('AJAX request failed:', status, error);
|
|
$("#loading_fw_" + port).hide();
|
|
const fwSpan = document.getElementById("fw_version_" + port);
|
|
fwSpan.innerHTML = '<span class="badge bg-danger">Error</span>';
|
|
}
|
|
});
|
|
}
|
|
|
|
function getENVEA_values(port, name) {
|
|
console.log("Data from Envea " + name + " (port " + port + "):");
|
|
$("#loading_envea" + name).show();
|
|
|
|
$.ajax({
|
|
url: 'launcher.php?type=envea&port=' + port + '&name=' + name,
|
|
dataType: 'json',
|
|
method: 'GET',
|
|
success: function (response) {
|
|
console.log(response);
|
|
const tableBody = document.getElementById("data-table-body_envea" + name);
|
|
tableBody.innerHTML = "";
|
|
|
|
$("#loading_envea" + name).hide();
|
|
|
|
const keysToShow = [name];
|
|
keysToShow.forEach(key => {
|
|
if (response !== undefined) {
|
|
const value = response;
|
|
$("#data-table-body_envea" + name).append(`
|
|
<tr>
|
|
<td>${key}</td>
|
|
<td>${value} ppb</td>
|
|
</tr>
|
|
`);
|
|
}
|
|
});
|
|
},
|
|
error: function (xhr, 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 getENVEA_debug_values() {
|
|
console.log("Getting debug data from all Envea sensors");
|
|
$("#loading_envea_debug").show();
|
|
|
|
$.ajax({
|
|
url: 'launcher.php?type=envea_debug',
|
|
dataType: 'text',
|
|
method: 'GET',
|
|
success: function (response) {
|
|
console.log("Envea debug output:", response);
|
|
const outputDiv = document.getElementById("envea-debug-output");
|
|
$("#loading_envea_debug").hide();
|
|
|
|
// Display raw output in a pre block
|
|
outputDiv.innerHTML = `<pre style="background-color: #f5f5f5; padding: 10px; border-radius: 5px; max-height: 500px; overflow-y: auto; font-size: 12px;">${response}</pre>`;
|
|
},
|
|
error: function (xhr, status, error) {
|
|
console.error('AJAX request failed:', status, error);
|
|
const outputDiv = document.getElementById("envea-debug-output");
|
|
$("#loading_envea_debug").hide();
|
|
|
|
outputDiv.innerHTML = `
|
|
<div class="alert alert-danger">
|
|
❌ Error: unable to get debug data from sensors.<br>
|
|
<small>${status}: ${error}</small>
|
|
</div>
|
|
`;
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
function getNoise_values() {
|
|
console.log("Data from NSRT MK4 Noise Sensor:");
|
|
$("#loading_noise").show();
|
|
|
|
$.ajax({
|
|
url: 'launcher.php?type=noise',
|
|
dataType: 'json',
|
|
method: 'GET',
|
|
success: function (response) {
|
|
console.log(response);
|
|
const tableBody = document.getElementById("data-table-body_noise");
|
|
tableBody.innerHTML = "";
|
|
$("#loading_noise").hide();
|
|
|
|
if (response.error) {
|
|
$("#data-table-body_noise").append(`
|
|
<tr><td colspan="2" class="text-danger">${response.error}</td></tr>
|
|
`);
|
|
return;
|
|
}
|
|
|
|
const rows = [
|
|
{ label: "LEQ", value: response.LEQ + " dB" },
|
|
{ label: "dB(A)", value: response.dBA + " dBA" },
|
|
{ label: "Weighting", value: response.weighting },
|
|
{ label: "Tau", value: response.tau + " s" }
|
|
];
|
|
rows.forEach(row => {
|
|
$("#data-table-body_noise").append(`
|
|
<tr>
|
|
<td>${row.label}</td>
|
|
<td>${row.value}</td>
|
|
</tr>
|
|
`);
|
|
});
|
|
},
|
|
error: function (xhr, status, error) {
|
|
$("#loading_noise").hide();
|
|
console.error('AJAX request failed:', status, error);
|
|
}
|
|
});
|
|
}
|
|
|
|
function getMHZ19_values() {
|
|
console.log("Data from MH-Z19 CO2 sensor:");
|
|
$("#loading_mhz19").show();
|
|
|
|
$.ajax({
|
|
url: 'launcher.php?type=mhz19',
|
|
dataType: 'json',
|
|
method: 'GET',
|
|
success: function (response) {
|
|
console.log(response);
|
|
const tableBody = document.getElementById("data-table-body_mhz19");
|
|
tableBody.innerHTML = "";
|
|
$("#loading_mhz19").hide();
|
|
|
|
if (response.error) {
|
|
$("#data-table-body_mhz19").append(`
|
|
<tr>
|
|
<td colspan="2" class="text-danger">
|
|
⚠ ${response.error}
|
|
</td>
|
|
</tr>
|
|
`);
|
|
} else if (response.CO2 !== undefined) {
|
|
$("#data-table-body_mhz19").append(`
|
|
<tr>
|
|
<td>CO2</td>
|
|
<td>${response.CO2} ppm</td>
|
|
</tr>
|
|
`);
|
|
}
|
|
},
|
|
error: function (xhr, status, error) {
|
|
console.error('AJAX request failed:', status, error);
|
|
$("#loading_mhz19").hide();
|
|
const tableBody = document.getElementById("data-table-body_mhz19");
|
|
tableBody.innerHTML = `
|
|
<tr>
|
|
<td colspan="2" class="text-danger">
|
|
⚠ Erreur de communication avec le capteur
|
|
</td>
|
|
</tr>
|
|
`;
|
|
}
|
|
});
|
|
}
|
|
|
|
function getBME280_values() {
|
|
console.log("Data from I2C BME280:");
|
|
$("#loading_BME280").show();
|
|
|
|
$.ajax({
|
|
url: 'launcher.php?type=BME280',
|
|
dataType: 'text',
|
|
|
|
method: 'GET', // Use GET or POST depending on your needs
|
|
success: function (response) {
|
|
console.log(response);
|
|
|
|
const tableBody = document.getElementById("data-table-body_BME280");
|
|
tableBody.innerHTML = "";
|
|
$("#loading_BME280").hide();
|
|
|
|
// Parse the JSON response
|
|
const data = JSON.parse(response);
|
|
const keysToShow = ["temp", "hum", "press"];
|
|
|
|
|
|
// Add only the specified elements to the table
|
|
keysToShow.forEach(key => {
|
|
if (response !== undefined) { // Check if the key exists in the response
|
|
const value = data[key];
|
|
const unit = key === "temp" ? "°C"
|
|
: key === "hum" ? "%"
|
|
: key === "press" ? "hPa"
|
|
: ""; // Add appropriate units
|
|
|
|
$("#data-table-body_BME280").append(`
|
|
<tr>
|
|
<td>${key.charAt(0).toUpperCase() + key.slice(1)}</td>
|
|
<td>${value} ${unit}</td>
|
|
</tr>
|
|
`);
|
|
}
|
|
});
|
|
},
|
|
error: function (xhr, status, error) {
|
|
console.error('AJAX request failed:', status, error);
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
window.onload = function () {
|
|
|
|
//NEW way to get config (SQLite)
|
|
let mainConfig = {}; // Store main config for use in sensor card creation
|
|
|
|
$.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);
|
|
|
|
mainConfig = response; // Store for later use
|
|
|
|
// Function to update sidebar device name
|
|
function updateSidebarDeviceName(deviceName) {
|
|
const elements = document.querySelectorAll('.sideBar_sensorName');
|
|
if (elements.length > 0) {
|
|
elements.forEach((element) => {
|
|
element.innerText = deviceName;
|
|
});
|
|
console.log("Device name updated in sidebar:", deviceName);
|
|
}
|
|
}
|
|
|
|
// Update device name immediately and with retries to handle async sidebar loading
|
|
if (response.deviceName) {
|
|
updateSidebarDeviceName(response.deviceName);
|
|
// Retry after delays to catch async sidebar load
|
|
setTimeout(() => updateSidebarDeviceName(response.deviceName), 100);
|
|
setTimeout(() => updateSidebarDeviceName(response.deviceName), 500);
|
|
|
|
// Set page title
|
|
document.title = response.deviceName;
|
|
}
|
|
|
|
// After getting main config, create sensor cards
|
|
createSensorCards(mainConfig);
|
|
|
|
},
|
|
error: function (xhr, status, error) {
|
|
console.error('AJAX request failed:', status, error);
|
|
}
|
|
});//end AJAX
|
|
|
|
//Function to create sensor cards based on config
|
|
function createSensorCards(config) {
|
|
console.log("Creating sensor cards with config:");
|
|
console.log(config);
|
|
|
|
const container = document.getElementById('card-container'); // Conteneur des cartes
|
|
|
|
//creates NPM card (by default)
|
|
|
|
const cardHTML = `
|
|
<div class="col-sm-3">
|
|
<div class="card">
|
|
<div class="card-header" data-i18n="sensors.npm.headerUart">
|
|
Port UART
|
|
</div>
|
|
<div class="card-body">
|
|
<h5 class="card-title" data-i18n="sensors.npm.title">NextPM</h5>
|
|
<p class="card-text" data-i18n="sensors.npm.description">Capteur particules fines.</p>
|
|
<button class="btn btn-primary" onclick="getNPM_values('ttyAMA5')" data-i18n="common.getData">Get Data</button>
|
|
<button class="btn btn-secondary" onclick="getNPM_firmware('ttyAMA5')">Firmware Version</button>
|
|
<br>
|
|
<div id="loading_ttyAMA5" class="spinner-border spinner-border-sm" style="display: none;" role="status"></div>
|
|
<div id="loading_fw_ttyAMA5" class="spinner-border spinner-border-sm" style="display: none;" role="status"></div>
|
|
<div id="fw_version_ttyAMA5" class="mt-1"></div>
|
|
<table class="table table-striped-columns">
|
|
<tbody id="data-table-body_ttyAMA5"></tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>`;
|
|
|
|
container.innerHTML += cardHTML; // Add the I2C card if condition is met
|
|
|
|
|
|
//creates i2c BME280 card
|
|
if (config.BME280) {
|
|
const i2C_BME_HTML = `
|
|
<div class="col-sm-3">
|
|
<div class="card">
|
|
<div class="card-header" data-i18n="sensors.bme280.headerI2c">
|
|
Port I2C
|
|
</div>
|
|
<div class="card-body">
|
|
<h5 class="card-title" data-i18n="sensors.bme280.title">BME280 Temp/Hum sensor</h5>
|
|
<p class="card-text" data-i18n="sensors.bme280.description">Capteur température et humidité sur le port I2C.</p>
|
|
<button class="btn btn-primary mb-1" onclick="getBME280_values()" data-i18n="common.getData">Get Data</button>
|
|
<br>
|
|
<div id="loading_BME280" class="spinner-border spinner-border-sm" style="display: none;" role="status"></div>
|
|
<table class="table table-striped-columns">
|
|
<tbody id="data-table-body_BME280"></tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>`;
|
|
|
|
container.innerHTML += i2C_BME_HTML; // Add the I2C card if condition is met
|
|
}
|
|
|
|
//creates NSRT MK4 noise sensor card (USB)
|
|
if (config.NOISE) {
|
|
const noiseHTML = `
|
|
<div class="col-sm-3">
|
|
<div class="card">
|
|
<div class="card-header" data-i18n="sensors.noise.headerUsb">
|
|
Port USB
|
|
</div>
|
|
<div class="card-body">
|
|
<h5 class="card-title" data-i18n="sensors.noise.title">NSRT MK4</h5>
|
|
<p class="card-text" data-i18n="sensors.noise.description">Sonomètre NSRT MK4 sur port USB.</p>
|
|
<button class="btn btn-primary mb-1" onclick="getNoise_values()" data-i18n="common.getData">Get Data</button>
|
|
<div id="loading_noise" class="spinner-border spinner-border-sm" style="display: none;" role="status"></div>
|
|
<table class="table table-striped-columns">
|
|
<tbody id="data-table-body_noise"></tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>`;
|
|
|
|
container.innerHTML += noiseHTML;
|
|
}
|
|
|
|
//creates MH-Z19 CO2 card
|
|
if (config.MHZ19) {
|
|
const MHZ19_HTML = `
|
|
<div class="col-sm-3">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
Port UART 4
|
|
</div>
|
|
<div class="card-body">
|
|
<h5 class="card-title">MH-Z19 CO2</h5>
|
|
<p class="card-text">Capteur de dioxyde de carbone.</p>
|
|
<button class="btn btn-primary mb-1" onclick="getMHZ19_values()" data-i18n="common.getData">Get Data</button>
|
|
<div id="loading_mhz19" class="spinner-border spinner-border-sm" style="display: none;" role="status"></div>
|
|
<table class="table table-striped-columns">
|
|
<tbody id="data-table-body_mhz19"></tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>`;
|
|
|
|
container.innerHTML += MHZ19_HTML;
|
|
}
|
|
|
|
//Si on a des SONDES ENVEA connectée il faut faire un deuxième call dans la table envea_sondes_table
|
|
//creates ENVEA debug card
|
|
if (config.envea) {
|
|
console.log("Need to display ENVEA sondes");
|
|
//getting config_scripts table
|
|
$.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);
|
|
const ENVEA_sensors = sondes.filter(sonde => sonde.connected); // Filter only connected sondes
|
|
|
|
// Only create the card if there are connected sensors
|
|
if (ENVEA_sensors.length > 0) {
|
|
// Create a single debug card for all Envea sensors
|
|
const cardHTML = `
|
|
<div class="col-sm-6">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<strong>Sondes Envea (Debug)</strong>
|
|
</div>
|
|
<div class="card-body">
|
|
<h5 class="card-title" data-i18n="sensors.envea.title">Sonde Envea</h5>
|
|
<p class="card-text" data-i18n="sensors.envea.description">Capteur gaz.</p>
|
|
<p class="text-muted small">Sondes connectées: ${ENVEA_sensors.map(s => s.name).join(', ')}</p>
|
|
<button class="btn btn-primary" onclick="getENVEA_debug_values()" data-i18n="common.getData">Get Data</button>
|
|
<div id="loading_envea_debug" class="spinner-border spinner-border-sm" style="display: none;" role="status"></div>
|
|
<div id="envea-debug-output" class="mt-3"></div>
|
|
</div>
|
|
</div>
|
|
</div>`;
|
|
container.innerHTML += cardHTML;
|
|
}
|
|
|
|
// Apply translations to dynamically created Envea card
|
|
i18n.applyTranslations();
|
|
|
|
},
|
|
error: function (xhr, status, error) {
|
|
console.error('AJAX request failed:', status, error);
|
|
}
|
|
});//end AJAX envea Sondes
|
|
|
|
}//end if envea
|
|
|
|
// Apply translations to all dynamically created sensor cards
|
|
i18n.applyTranslations();
|
|
|
|
} // end createSensorCards function
|
|
|
|
//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>
|
|
|
|
</body>
|
|
|
|
</html> |