Files
nebuleair_pro_4g/old/index_old.html
Your Name d095e53cd6 update
2025-01-28 18:14:55 +01:00

1235 lines
53 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 Pro</title>
<!-- Link Bootstrap CSS locally -->
<link rel="stylesheet" href="html/assets/css/bootstrap.min.css">
<style>
.deviceID {
margin-top: 2px; /* Add some top margin for spacing */
font-size: 1.5rem; /* Adjust the font size */
color: #33577c; /* Bootstrap primary color */
text-align: center;
}
</style>
</head>
<body>
<nav class="navbar bg-body-tertiary">
<div class="container-fluid d-flex justify-content-between align-items-center">
<!-- Texte aligné à gauche -->
<a class="navbar-brand" href="#">
<img src="html/assets/img/LogoNebuleAir.png" alt="Logo" height="30" class="d-inline-block align-text-top">
</a>
<!-- Texte centré au milieu -->
<div class="mx-auto text-center">
<span id="pageTitle_plus_ID">Texte au milieu</span>
</div>
<!-- Texte à droite -->
<div class="text-end">
<button type="button" class="btn btn-outline-secondary" id="RTC_time">loading...</button>
</div>
</div>
</nav>
<div class="container">
<h3>Capteurs</h3>
<!-- NEXT PM & I2C sound -->
<div class="row mb-3" id="card-container"></div>
<h3>
Modem 4G status
<span id="modem-status" class="badge">Loading...</span>
</h3>
<div class="row mb-3">
<div class="col-sm-4">
<div class="card">
<div class="card-body">
<p class="card-text">General information. </p>
<button class="btn btn-primary" onclick="getData_saraR4('ttyAMA2', 'ATI', 2)">Get Data</button>
<div id="loading_ttyAMA2_ATI" class="spinner-border spinner-border-sm" style="display: none;" role="status"></div>
<div id="response_ttyAMA2_ATI"></div>
</div>
</div>
</div>
<div class="col-sm-4">
<div class="card">
<div class="card-body">
<p class="card-text">SIM card information.</p>
<button class="btn btn-primary" onclick="getData_saraR4('ttyAMA2', 'AT+CCID?', 2)">Get Data</button>
<div id="loading_ttyAMA2_AT_CCID_" class="spinner-border spinner-border-sm" style="display: none;" role="status"></div>
<div id="response_ttyAMA2_AT_CCID_"></div>
</div>
</div>
</div>
<div class="col-sm-4">
<div class="card">
<div class="card-body">
<p class="card-text">Actual Network connection</p>
<button class="btn btn-primary" onclick="getData_saraR4('ttyAMA2', 'AT+COPS?', 2)">Get Data</button>
<div id="loading_ttyAMA2_AT_COPS_" class="spinner-border spinner-border-sm" style="display: none;" role="status"></div>
<div id="response_ttyAMA2_AT_COPS_"></div>
</table>
</div>
</div>
</div>
</div>
<h3>Connexion 4G Network</h3>
<div class="row mb-3">
<div class="col-sm-8">
<div class="card text-dark bg-light">
<div class="card-body">
<p class="card-text">Network scan. Attention: 2 min scan.</p>
<button class="btn btn-primary" onclick="getData_saraR4('ttyAMA2', 'AT+COPS=?', 120)">Scan</button>
<div id="loading_ttyAMA2_AT_COPS__" class="spinner-border spinner-border-sm" style="display: none;" role="status"></div>
<div id="response_ttyAMA2_AT_COPS__"></div>
<div id="table-network"></div>
</div>
</div>
</div>
<div class="col-sm-4">
<div class="card text-dark bg-light">
<div class="card-body">
<p class="card-text">Network connexion.</p>
<div class="input-group input-group-sm mb-3">
<span class="input-group-text" id="inputGroup-sizing-sm">Numeric Operator</span>
<input type="text" id="messageInput_network" class="form-control" aria-label="Sizing example input" aria-describedby="inputGroup-sizing-sm">
</div>
<button class="btn btn-primary" onclick="connectNetwork_saraR4('ttyAMA2', document.getElementById('messageInput_network').value, 60)">Connect</button>
<div id="loading_ttyAMA2_AT_COPS_Connect" class="spinner-border spinner-border-sm" style="display: none;" role="status"></div>
<div id="response_ttyAMA2_AT_COPS_Connect"></div>
</div>
</div>
</div>
</div>
<h3>MQTT</h3>
<div class="row mb-3">
<!-- Get CONFIG -->
<div class="col-sm-4">
<div class="card">
<div class="card-body">
<p class="card-text">Get config.</p>
<button class="btn btn-primary" onclick="mqtt_getConfig_saraR4('ttyAMA2', 2)">Get Data</button>
<div id="loading_mqtt_getConfig" class="spinner-border spinner-border-sm" style="display: none;" role="status"></div>
<div id="response_mqtt_getConfig"></div>
</div>
</div>
</div>
<!-- MQTT LOGIN -->
<div class="col-sm-4">
<div class="card">
<div class="card-body">
<p class="card-text">Login / logout</p>
<button class="btn btn-success" onclick="mqtt_login_logout('ttyAMA2', 1, 6)">Login </button>
<button class="btn btn-danger" onclick="mqtt_login_logout('ttyAMA2', 0, 6)">Logout </button>
<div id="loading_mqtt_login_logout" class="spinner-border spinner-border-sm" style="display: none;" role="status"></div>
<div id="response_mqtt_login_logout"></div>
</div>
</div>
</div>
<!-- Send MESSAGE -->
<div class="col-sm-4">
<div class="card">
<div class="card-body">
<p class="card-text">Send message (MQTT publish) .</p>
<div class="input-group input-group-sm mb-3">
<span class="input-group-text" id="inputGroup-sizing-sm">Text</span>
<input type="text" id="MQTTmessageInput" class="form-control" aria-label="Sizing example input" aria-describedby="inputGroup-sizing-sm">
</div>
<button class="btn btn-primary" onclick="mqtt_publish('ttyAMA2', document.getElementById('MQTTmessageInput').value, 2)">Send Message</button>
<div id="loading_mqtt_publish" class="spinner-border spinner-border-sm" style="display: none;" role="status"></div>
<div id="response_mqtt_publish"></div>
</div>
</div>
</div>
</div>
<h3>Send message (test)</h3>
<div class="row mb-3">
<!-- SET URL -->
<div class="col-sm-4">
<div class="card">
<div class="card-body">
<p class="card-text">Set url (HTTP).</p>
<button class="btn btn-primary" onclick="setURL_saraR4('ttyAMA2', 'data.nebuleair.fr')">Set URL</button>
<div id="loading_ttyAMA2_setURL" class="spinner-border spinner-border-sm" style="display: none;" role="status"></div>
<div id="response_ttyAMA2_setURL"></div>
</div>
</div>
</div>
<!-- WRITE MESSAGE to memory -->
<div class="col-sm-4">
<div class="card">
<div class="card-body">
<p class="card-text">Write message (local storage).</p>
<div class="input-group input-group-sm mb-3">
<span class="input-group-text" id="inputGroup-sizing-sm">Text</span>
<input type="text" id="messageInput" class="form-control" aria-label="Sizing example input" aria-describedby="inputGroup-sizing-sm">
</div>
<button class="btn btn-primary" onclick="writeMessage_saraR4('ttyAMA2', document.getElementById('messageInput').value , 'write')">Write </button>
<button class="btn btn-warning" onclick="writeMessage_saraR4('ttyAMA2', 'Hello', 'read')">Read </button>
<button class="btn btn-danger" onclick="writeMessage_saraR4('ttyAMA2', 'Hello', 'erase')">Empty </button>
<div id="loading_ttyAMA2_message_write" class="spinner-border spinner-border-sm" style="display: none;" role="status"></div>
<div id="response_ttyAMA2_message_write"></div>
</div>
</div>
</div>
<!-- Send MESSAGE -->
<div class="col-sm-4">
<div class="card">
<div class="card-body">
<p class="card-text">Send message .</p>
<button class="btn btn-primary" onclick="sendMessage_saraR4('ttyAMA2', '/pro_4G/notif_message.php')">Send Message</button>
<div id="loading_ttyAMA2_message_send" class="spinner-border spinner-border-sm" style="display: none;" role="status"></div>
<div id="response_ttyAMA2_message_send"></div>
</div>
</div>
</div>
</div>
<!-- WIFI -->
<h3>WIFI status
<span id="wifi-status" class="badge">Loading...</span>
</h3>
<div class="row mb-3">
<div class="col-sm-4">
<div class="card text-dark bg-light">
<div class="card-body">
<h5 class="card-title">WIFI / Ethernet</h5>
<p class="card-text">General information.</p>
<button class="btn btn-primary" onclick="get_internet()">Get Data</button>
<table class="table table-striped-columns">
<tbody id="data-table-body_internet_general"></tbody>
</table>
</div>
</div>
</div>
<div class="col-sm-8">
<div class="card text-dark bg-light">
<div class="card-body">
<h5 class="card-title">Wifi Scan</h5>
<p class="card-text">Scan des réseaux WIFI disponibles.</p>
<button class="btn btn-primary" onclick="wifi_scan()">Scan</button>
<table class="table">
<tbody id="data-table-body_wifi_scan"></tbody>
</table>
</table>
</div>
</div>
</div>
<!-- Modal WIFI PASSWORD -->
<!-- filled with JS -->
<div class="modal fade" id="myModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="myModalLabel">Modal title</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body" id="myModalBody">
...
</div>
<div class="modal-footer" id="myModalFooter">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
<!--
<div class="col-sm-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">WIFI Connect</h5>
<p class="card-text">Connect to WIFI.</p>
<form action="launcher.php" method="get" onsubmit="return confirmSubmit()">
<div class="mb-3">
<label for="SSID_" class="form-label">SSID</label>
<input type="text" name="SSID" class="form-control" id="SSID_" aria-describedby="emailHelp">
</div>
<div class="mb-3">
<label for="exampleInputPassword1" class="form-label">Password</label>
<input type="password" name="pass" class="form-control" id="exampleInputPassword1">
</div>
<input type="hidden" name="type" value="wifi_connect">
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<div id="response_hotspot_status"></div>
</div>
</div>
</div>
-->
<!--
<div class="col-sm-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">WIFI Hotspot</h5>
<p class="card-text">Check if wifi Hotspot (AP) is activated.</p>
<button class="btn btn-primary" onclick="get_hotspot_status()">Check</button>
<div id="response_hotspot_status"></div>
</div>
</div>
</div>
-->
</div>
<!-- end row -->
<h3>Logs</h3>
<div class="row mb-3">
<div class="col-sm-4">
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#bootLog_modal">
Boot Logs
</button>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#loopLog_modal">
Loop Logs
</button>
<!-- Modal Boot Logs -->
<div class="modal fade" id="bootLog_modal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable modal-xl">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">Boot logs</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<pre id="log-content" style="white-space: pre-wrap; word-wrap: break-word;"></pre>
...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" id="refreshBootLog">Refresh</button>
</div>
</div>
</div>
</div>
<!-- Modal Loop Logs -->
<div class="modal fade" id="loopLog_modal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable modal-xl">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">Loop logs</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" id="refreshLoopLog">Refresh</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- end row -->
<h3>Admin</h3>
<div class="row mb-3">
<div class="col-sm-10">
<button type="button" class="btn btn-danger" onclick="rebootDevice()">
Reboot
</button>
<button type="button" class="btn btn-info" onclick="startSSHTunnel()">
Start SSH Tunnel
</button>
<button type="button" id="updateButton" class="btn btn-success" onclick="updateGitPull()">
Update
</button>
</div>
</div>
</div>
<!-- end container -->
</body>
<!-- JAVASCRIPT -->
<!-- Link Ajax locally -->
<script src="html/assets/jquery/jquery-3.7.1.min.js"></script>
<!-- Link Bootstrap JS and Popper.js locally -->
<script src="html/assets/js/bootstrap.bundle.js"></script>
<script>
function updateGitPull(){
console.log("Updating device (git pull)");
$.ajax({
url: 'launcher.php?type=git_pull',
method: 'GET', // Use GET or POST depending on your needs
success: function(response) {
// Handle success response if needed
console.log(response);
alert(response);
// Reload the page after the device update
location.reload(); // This will reload the page
},
error: function(xhr, status, error) {
console.error('AJAX request failed:', status, error);
}
});
}
function startSSHTunnel(){
console.log("Will start ssh tunnel");
console.log("need to retreive ssh port");
fetch('config.json') // Replace 'deviceID.txt' with 'config.json'
.then(response => response.json()) // Parse response as JSON
.then(data => {
//get device ID
const deviceSSH_port = data.sshTunnel_port
console.log("Device SSH port retrieved: " + deviceSSH_port);
startSSHTunnel_2(deviceSSH_port);
})
.catch(error => {
console.error('Error retrieving device ssh port:', error);
alert('An error occurred while fetching the device ID.');
});
}
function startSSHTunnel_2(deviceSSH_port){
$.ajax({
url: 'launcher.php?type=sshTunnel&ssh_port='+deviceSSH_port,
method: 'GET', // Use GET or POST depending on your needs
success: function(response) {
// Handle success response if needed
console.log(response);
alert("Tunnel started");
},
error: function(xhr, status, error) {
console.error('AJAX request failed:', status, error);
}
});
}
function rebootDevice(){
console.log("Will reboot system");
var userConfirmed = confirm("Are you sure you want to reboot the system? If so, press ok and wait few seconds before reloading page.");
if (userConfirmed) {
$.ajax({
url: 'launcher.php?type=reboot',
method: 'GET', // Use GET or POST depending on your needs
success: function(response) {
// Handle success response if needed
},
error: function(xhr, status, error) {
console.error('AJAX request failed:', status, error);
}
});
} else {
console.log("Reboot canceled.");
}
}
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"];
// 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>
`);
}
});
},
error: function(xhr, status, error) {
console.error('AJAX request failed:', status, error);
}
});
}
function getNoise_values(){
console.log("Data from I2C Noise Sensor:");
$("#loading_noise").show();
$.ajax({
url: 'launcher.php?type=noise',
method: 'GET', // Use GET or POST depending on your needs
success: function(response) {
console.log(response);
const tableBody = document.getElementById("data-table-body_noise");
tableBody.innerHTML = "";
$("#loading_noise").hide();
// Create an array of the desired keys
const keysToShow = ["Noise"];
// Add only the specified elements to the table
keysToShow.forEach(key => {
if (response !== undefined) { // Check if the key exists in the response
const value = response;
$("#data-table-body_noise").append(`
<tr>
<td>${key}</td>
<td>${value} DB</td>
</tr>
`);
}
});
},
error: function(xhr, status, error) {
console.error('AJAX request failed:', status, error);
}
});
}
function getBME280_values(){
console.log("Data from I2C BME280:");
$("#loading_BME280").show();
$.ajax({
url: 'launcher.php?type=BME280',
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);
}
});
}
function getData_saraR4(port, command, timeout){
console.log("Data from SaraR4");
console.log("Port: " + port );
console.log("Command: " + command );
console.log("Timeout: " + timeout );
const safeCommand = command.replace(/[?+=]/g, "_");
console.log(safeCommand);
$("#loading_"+port+"_"+safeCommand).show();
$.ajax({
url: 'launcher.php?type=sara&port='+port+'&command='+encodeURIComponent(command)+'&timeout='+timeout,
//dataType: 'json', // Specify that you expect a JSON response
method: 'GET', // Use GET or POST depending on your needs
success: function(response) {
//log response
console.log(response);
//hide spinning wheel
$("#loading_"+port+"_"+safeCommand).hide();
// si on fait le scan de network on veut une liste des réseaux
if (command == "AT+COPS=?") {
// Extract data within parentheses
const matches = response.match(/\(.*?\)/g); // Matches all `(...)` sections
const container = document.getElementById('table-network'); // Bootstrap container
// Check if matches exist
if (matches) {
const table = document.createElement('table');
table.className = 'table table-striped'; // Add Bootstrap table styling
const thead = document.createElement('thead');
const tbody = document.createElement('tbody');
// Table header (you can customize this based on your data)
const headerRow = document.createElement('tr');
const header1 = document.createElement('th');
header1.textContent = 'Status';
const header2 = document.createElement('th');
header2.textContent = 'Long oper';
const header3 = document.createElement('th');
header3.textContent = 'Short opeer';
const header4 = document.createElement('th');
header4.textContent = 'Numeric oper';
const header5 = document.createElement('th');
header5.textContent = 'AcT';
headerRow.appendChild(header1);
headerRow.appendChild(header2);
headerRow.appendChild(header3);
headerRow.appendChild(header4);
headerRow.appendChild(header5);
thead.appendChild(headerRow);
table.appendChild(thead);
// Loop through each match and create a row in the table
matches.forEach((item) => {
// Skip empty sections
if (item === "()") return;
const row = document.createElement('tr');
const values = item.slice(1, -1).split(','); // Remove parentheses and split by commas
// Add table cells (td) for each value
values.forEach((value) => {
const cell = document.createElement('td');
cell.textContent = value.trim(); // Remove extra spaces
row.appendChild(cell);
});
tbody.appendChild(row);
});
// Add tbody to table and append the table to the container
table.appendChild(tbody);
container.appendChild(table);
} else {
console.error('No valid data found in response.');
}
} else{
// si c'est une commande AT normale
// Replace newline characters with <br> tags
const formattedResponse = response.replace(/\n/g, "<br>");
$("#response_"+port+"_"+safeCommand).html(formattedResponse);
}
},
error: function(xhr, status, error) {
console.error('AJAX request failed:', status, error);
}
});
}
function connectNetwork_saraR4(port, networkID, timeout){
console.log(" Connect to network (port "+port+" and network id "+networkID+"):");
$("#loading_"+port+"_AT_COPS_Connect").show();
$.ajax({
url: 'launcher.php?type=sara_connectNetwork&port='+port+'&networkID='+encodeURIComponent(networkID)+'&timeout='+timeout,
//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);
$("#loading_"+port+"_AT_COPS_Connect").hide();
// Replace newline characters with <br> tags
const formattedResponse = response.replace(/\n/g, "<br>");
$("#response_"+port+"_AT_COPS_Connect").html(formattedResponse);
},
error: function(xhr, status, error) {
console.error('AJAX request failed:', status, error);
}
});
}
function mqtt_getConfig_saraR4(port, timeout){
console.log("GET MQTT config (port "+port+"):");
$("#loading_mqtt_getConfig").show();
$.ajax({
url: 'launcher.php?type=sara_getMQTT_config&port='+port+'&timeout='+timeout,
//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);
$("#loading_mqtt_getConfig").hide();
// Replace newline characters with <br> tags
const formattedResponse = response.replace(/\n/g, "<br>");
$("#response_mqtt_getConfig").html(formattedResponse);
},
error: function(xhr, status, error) {
console.error('AJAX request failed:', status, error);
}
});
}
function mqtt_login_logout(port, login_logout, timeout){
console.log("GET MQTT login / logout (port "+port+"):");
$("#loading_mqtt_login_logout").show();
$.ajax({
url: 'launcher.php?type=sara_getMQTT_login_logout&port='+port+'&login_logout='+login_logout+'&timeout='+timeout,
//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);
$("#loading_mqtt_login_logout").hide();
const formattedResponse = response.replace(/\n/g, "<br>");
$("#response_mqtt_login_logout").html(formattedResponse);
const regex = /^\+UMQTTC:\s*(\d+),(\d+)/m; // Match "+UMQTTC:", followed by two numbers separated by a comma
const match = response.match(regex);
if (match) {
const firstNumber = match[1]; // The first number after ":"
const secondNumber = match[2]; // The second number after the ","
if (firstNumber == 0) {
console.log("MQTT LOGOUT:");
$("#response_mqtt_login_logout").append("<p>logout</p>");
}
if (firstNumber == 1) {
console.log("MQTT LOGIN:");
$("#response_mqtt_login_logout").append("<p>login</p>");
}
if (secondNumber == 0) {
console.log("ERROR");
$("#response_mqtt_login_logout").append("<p>error</p>");
}
if (secondNumber == 1) {
console.log("SUCCESS");
$("#response_mqtt_login_logout").append("<p>success</p>");
}
} else {
console.log("No matching line found");
}
},
error: function(xhr, status, error) {
console.error('AJAX request failed:', status, error);
}
});
}
function mqtt_publish(port, message, timeout){
console.log(" MQTT publish (port "+port+"):");
$("#loading_mqtt_publish").show();
$.ajax({
url: 'launcher.php?type=sara_MQTT_publish&port='+port+'&timeout='+timeout+'&message='+message,
//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);
$("#loading_mqtt_publish").hide();
// Replace newline characters with <br> tags
const formattedResponse = response.replace(/\n/g, "<br>");
$("#response_mqtt_publish").html(formattedResponse);
},
error: function(xhr, status, error) {
console.error('AJAX request failed:', status, error);
}
});
}
function setURL_saraR4(port, url){
console.log("Set URL for HTTP (port "+port+" and URL "+url+"):");
$("#loading_"+port+"_setURL").show();
$.ajax({
url: 'launcher.php?type=sara_setURL&port='+port+'&url='+encodeURIComponent(url),
//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);
$("#loading_"+port+"_setURL").hide();
// Replace newline characters with <br> tags
const formattedResponse = response.replace(/\n/g, "<br>");
$("#response_"+port+"_setURL").html(formattedResponse);
},
error: function(xhr, status, error) {
console.error('AJAX request failed:', status, error);
}
});
}
function writeMessage_saraR4(port, message, type){
console.log(type +" message to SARA R4 memory (port "+port+" and message "+message+"):");
$("#loading_"+port+"_message_write").show();
$.ajax({
url: 'launcher.php?type=sara_writeMessage&port='+port+'&message='+encodeURIComponent(message)+'&type2='+type,
//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);
$("#loading_"+port+"_message_write").hide();
// Replace newline characters with <br> tags
const formattedResponse = response.replace(/\n/g, "<br>");
$("#response_"+port+"_message_write").html(formattedResponse);
},
error: function(xhr, status, error) {
console.error('AJAX request failed:', status, error);
}
});
}
function sendMessage_saraR4(port, endpoint){
console.log("Send message from SaraR4 (port "+port+" and endpoint "+endpoint+"):");
$("#loading_"+port+"_message_send").show();
$.ajax({
url: 'launcher.php?type=sara_sendMessage&port='+port+'&endpoint='+encodeURIComponent(endpoint),
//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);
$("#loading_"+port+"_message_send").hide();
// Replace newline characters with <br> tags
const formattedResponse = response.replace(/\n/g, "<br>");
$("#response_"+port+"_message_send").html(formattedResponse);
},
error: function(xhr, status, error) {
console.error('AJAX request failed:', status, error);
}
});
}
function get_internet(){
console.log("Getting internet general infos");
$.ajax({
url: 'launcher.php?type=internet',
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);
let tableBody = document.getElementById('data-table-body_internet_general');
tableBody.innerHTML = ''; // Clear existing table content
// Iterate through the data and create rows
for (let key in response) {
let row = `
<tr>
<td>${key}</td>
<td>${response[key].connection}</td>
<td>${response[key].IP ? response[key].IP : "No IP"}</td>
</tr>
`;
tableBody.innerHTML += row; // Append row to table body
}
},
error: function(xhr, status, error) {
console.error('AJAX request failed:', status, error);
}
});
}
function wifi_connect(SSID, PASS){
console.log("Connecting to wifi");
console.log(SSID);
console.log(PASS);
if (typeof PASS === 'undefined') {
console.log("Need to add password");
//open bootstrap modal to ask for password
var myModal = new bootstrap.Modal(document.getElementById('myModal'));
//modifiy modal title
document.getElementById('myModalLabel').innerHTML = "Enter password for "+SSID;
//add input field to modal body
document.getElementById('myModalBody').innerHTML = "<input type='text' id='wifi_pass' class='form-control' placeholder='Password'>";
//add button to modal footer
document.getElementById('myModalFooter').innerHTML = "<button type='button' class='btn btn-secondary' data-bs-dismiss='modal'>Close</button><button type='button' class='btn btn-primary' onclick='wifi_connect(\""+SSID+"\", document.getElementById(\"wifi_pass\").value)'>Se connecter</button>";
myModal.show();
} else {
console.log("Will try to connect to "+SSID+" with password "+PASS);
console.log("Start PHP script:");
$.ajax({
url: 'launcher.php?type=wifi_connect&SSID='+SSID+'&pass='+PASS,
dataType: 'text', // Specify that you expect a JSON response
method: 'GET', // Use GET or POST depending on your needs
success: function(response) {
console.log(response);
},
error: function(xhr, status, error) {
console.error('AJAX request failed:', status, error);
}
});
}
}
function wifi_scan(){
console.log("Scanning Wifi");
$.ajax({
url: 'launcher.php?type=wifi_scan',
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_wifi_scan");
// Clear the existing table body
tableBody.innerHTML = "";
// Loop through the wifiNetworks array and create rows
response.forEach(network => {
const row = document.createElement("tr");
// Create and append cells for SSID, BARS, and SIGNAL
const ssidCell = document.createElement("td");
// Truncate SSID to 25 characters
const truncatedSSID = network.SSID.length > 20 ? network.SSID.substring(0, 20) + '...' : network.SSID;
ssidCell.textContent = truncatedSSID;
row.appendChild(ssidCell);
/*
const signalCell = document.createElement("td");
signalCell.textContent = network.SIGNAL;
row.appendChild(signalCell);
*/
// Create a button
const buttonCell = document.createElement("td");
const button = document.createElement("button");
button.textContent = "Connect"; // Button text
button.classList.add("btn", "btn-primary"); // Bootstrap button classes
// Determine button color based on SIGNAL value
const signalValue = parseInt(network.SIGNAL, 10); // Assuming SIGNAL is a numeric value
// Calculate color based on the signal strength
let buttonColor;
if (signalValue >= 100) {
buttonColor = "success"; // Green for strong signal
} else if (signalValue >= 50) {
buttonColor = "warning"; // Yellow for moderate signal
} else {
buttonColor = "danger"; // Red for weak signal
}
// Add Bootstrap button classes along with color
button.classList.add("btn", `btn-${buttonColor}`);
//Trigger function as soon as the button is clicked
button.addEventListener("click", () => wifi_connect(network.SSID));
// Append the button to the button cell
buttonCell.appendChild(button);
row.appendChild(buttonCell);
// Append the row to the table body
tableBody.appendChild(row);
});
},
error: function(xhr, status, error) {
console.error('AJAX request failed:', status, error);
}
});
}
function confirmSubmit() {
// You can display a simple confirmation message or customize the behavior
return confirm("Are you sure you want to connect to this Wi-Fi network?");
}
let intervalId;
function startNoise() {
// Check if interval is already running
if (!intervalId) {
intervalId = setInterval(getNoise_values, 1000);
console.log("Function started");
}
}
function stopNoise() {
if (intervalId) {
clearInterval(intervalId);
intervalId = null; // Reset intervalId to indicate that the function is stopped
console.log("Function stopped");
}
}
//setInterval(getNoise_values, 1000);
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 SARA_R4 connection status
const SARA_statusElement = document.getElementById("modem-status");
console.log("SARA R4 is: " + data.SARA_R4_network_status);
if (data.SARA_R4_network_status === "connected") {
SARA_statusElement.textContent = "Connected";
SARA_statusElement.className = "badge text-bg-success";
} else if (data.SARA_R4_network_status === "disconnected") {
SARA_statusElement.textContent = "Disconnected";
SARA_statusElement.className = "badge text-bg-danger";
} else {
SARA_statusElement.textContent = "Unknown";
SARA_statusElement.className = "badge text-bg-secondary";
}
//get wifi connection status
const WIFI_statusElement = document.getElementById("wifi-status");
console.log("WIFI is: " + data.WIFI_status);
if (data.WIFI_status === "connected") {
WIFI_statusElement.textContent = "Connected";
WIFI_statusElement.className = "badge text-bg-success";
} else if (data.WIFI_status === "hotspot") {
WIFI_statusElement.textContent = "Hotspot";
WIFI_statusElement.className = "badge text-bg-warning";
} else {
WIFI_statusElement.textContent = "Unknown";
WIFI_statusElement.className = "badge text-bg-secondary";
}
//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);
}
});
const container = document.getElementById('card-container'); // Conteneur des cartes
//creates NPM cards
const ports = data.NextPM_ports; // Récupère les ports
// Générer les cartes dynamiquement
ports.forEach((port, index) => {
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">NextPM ${String.fromCharCode(65 + index)}</h5>
<p class="card-text">Capteur particules fines.</p>
<button class="btn btn-primary" onclick="getNPM_values('${port}')">Get Data</button>
<div id="loading_${port}" class="spinner-border spinner-border-sm" style="display: none;" role="status"></div>
<table class="table table-striped-columns">
<tbody id="data-table-body_${port}"></tbody>
</table>
</div>
</div>
</div>`;
container.innerHTML += cardHTML; // Ajouter la carte au conteneur
});
//creates i2c BME280 card
if (data.i2c_BME) {
const i2C_BME_HTML = `
<div class="col-sm-3">
<div class="card">
<div class="card-header">
Port I2C
</div>
<div class="card-body">
<h5 class="card-title">BME280 Temp/Hum sensor</h5>
<p class="card-text">Capteur température et humidité sur le port I2C.</p>
<button class="btn btn-primary mb-1" onclick="getBME280_values()">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 i2c sound card
if (data.i2C_sound) {
const i2C_HTML = `
<div class="col-sm-3">
<div class="card">
<div class="card-header">
Port I2C
</div>
<div class="card-body">
<h5 class="card-title">Decibel Meter</h5>
<p class="card-text">Capteur bruit sur le port I2C.</p>
<button class="btn btn-primary mb-1" onclick="getNoise_values()">Get Data</button>
<br>
<button class="btn btn-success" onclick="startNoise()">Start recording</button>
<button class="btn btn-danger" onclick="stopNoise()">Stop recording</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 += i2C_HTML; // Add the I2C card if condition is met
}
})
.catch(error => console.error('Error loading config.json:', error));
}
// LOGS modal
document.addEventListener('DOMContentLoaded', () => {
// Get the modal body
const modal_loop_Body = document.querySelector('#loopLog_modal .modal-body');
const modal_boot_Body = document.querySelector('#bootLog_modal .modal-body');
// LOOP
function fetchLoopLogs() {
fetch('logs/loop.log')
.then((response) => {
if (!response.ok) {
throw new Error('Failed to fetch the log file.');
}
return response.text();
})
.then((data) => {
const lines = data.split('\n');
// Format log content
const formattedLog = lines
.map((line) => line.trim()) // Remove extra whitespace
.filter((line) => line) // Remove empty lines
.join('<br>'); // Join formatted lines with line breaks
modal_loop_Body.innerHTML = `<pre style="white-space: pre-wrap; word-wrap: break-word; margin: 0;">${formattedLog}</pre>`;
})
.catch((error) => {
console.error(error);
modal_loop_Body.textContent = 'Error loading log file.';
});
}
//BOOT
function fetchBootLogs() {
fetch('logs/app.log')
.then((response) => {
if (!response.ok) {
throw new Error('Failed to fetch the log file.');
}
return response.text();
})
.then((data) => {
const lines = data.split('\n');
// Format log content
const formattedLog = lines
.map((line) => line.trim()) // Remove extra whitespace
.filter((line) => line) // Remove empty lines
.join('<br>'); // Join formatted lines with line breaks
modal_boot_Body.innerHTML = `<pre style="white-space: pre-wrap; word-wrap: break-word; margin: 0;">${formattedLog}</pre>`;
})
.catch((error) => {
console.error(error);
modal_boot_Body.textContent = 'Error loading log file.';
});
}
document.getElementById('loopLog_modal').addEventListener('show.bs.modal', fetchLoopLogs);
document.getElementById('refreshLoopLog').addEventListener('click', fetchLoopLogs);
document.getElementById('bootLog_modal').addEventListener('show.bs.modal', fetchBootLogs);
document.getElementById('refreshBootLog').addEventListener('click', fetchBootLogs);
});
</script>
</html>