mirror of
https://github.com/skinnyrad/Lora-Scanner.git
synced 2026-03-28 17:43:00 +01:00
981 lines
58 KiB
HTML
981 lines
58 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
|
<meta name="description" content="" />
|
|
<meta name="author" content="" />
|
|
<script type="text/javascript" src="static/js/socket.io.js"></script>
|
|
<title>LoRa Scanner</title>
|
|
<link rel="icon" type="image/x-icon" href="assets/img/favicon.ico" />
|
|
<!-- Font Awesome icons (free version)-->
|
|
<script src="static/js/all.js" crossorigin="anonymous"></script>
|
|
<!-- Google fonts-->
|
|
|
|
<!-- Core theme CSS (includes Bootstrap)-->
|
|
<link href="static/css/styles.css" rel="stylesheet" />
|
|
<!-- Include SweetAlert2 CSS -->
|
|
<link rel="stylesheet" href="static/css/sweetalert2.css">
|
|
|
|
<!-- Include SweetAlert2 JS -->
|
|
<script src="static/js/sweetalert2.js"></script>
|
|
<script src="static/js/jquery.min.js"></script>
|
|
|
|
</head>
|
|
<body id="page-top">
|
|
<!-- Navigation-->
|
|
<nav class="navbar navbar-expand-lg navbar-dark bg-primary fixed-top" id="sideNav">
|
|
<a class="navbar-brand js-scroll-trigger" href="#page-top">
|
|
<span class="d-block d-lg-none">LoRa Scanner</span>
|
|
<span class="d-none d-lg-block"><img class="img-fluid img-profile rounded-circle mx-auto mb-2" src="static/assets/img/profile.jpg" alt="..." /></span>
|
|
</a>
|
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button>
|
|
<div class="collapse navbar-collapse" id="navbarResponsive">
|
|
<ul class="navbar-nav">
|
|
<li class="nav-item"><a class="nav-link js-scroll-trigger" href="/">Home</a></li>
|
|
<li class="nav-item"><a class="nav-link js-scroll-trigger" href="/#config">Configuration</a></li>
|
|
<li class="nav-item"><a class="nav-link js-scroll-trigger" href="/analysis">Analysis Mode</a></li>
|
|
<li class="nav-item"><a class="nav-link js-scroll-trigger" href="/survey">Survey Mode</a></li>
|
|
<li class="nav-item"><a class="nav-link js-scroll-trigger" href="#">Tracking Mode</a></li>
|
|
</ul>
|
|
</div>
|
|
</nav>
|
|
<!-- Page Content-->
|
|
<div class="container-fluid p-0">
|
|
<!-- About-->
|
|
<section class="resume-section" id="about">
|
|
<div class="resume-section-content">
|
|
<h1 class="mb-0" style="text-align: center;">
|
|
Tracking Mode
|
|
</h1>
|
|
<br>
|
|
<h2 class="lead mb-5" style="text-align: center;">Select A Device You Would Like To Track</h2>
|
|
<br>
|
|
<div class="scrollable-table">
|
|
|
|
<div class="resume-section-content">
|
|
<table id="data-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Device Name</th>
|
|
<th>Frequency</th>
|
|
<th>Signal Strength</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<!-- Rows will be inserted here -->
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<br>
|
|
|
|
<button id="clear-selection-button" class="btn btn-secondary btn-sm" style="display: none; display: block; margin: 0 auto; text-align: center;">Clear Filter</button>
|
|
|
|
|
|
|
|
<br>
|
|
<script>
|
|
function clearDataPort1() {
|
|
var serialDataDiv1 = document.getElementById('serial-data-port1');
|
|
serialDataDiv1.innerHTML = '';
|
|
}
|
|
|
|
function clearDataPort2() {
|
|
var serialDataDiv2 = document.getElementById('serial-data-port2');
|
|
serialDataDiv2.innerHTML = '';
|
|
}
|
|
|
|
function clearDataPort3() {
|
|
var serialDataDiv3 = document.getElementById('serial-data-port3');
|
|
serialDataDiv3.innerHTML = '';
|
|
}
|
|
</script>
|
|
<script>
|
|
let selectedDeviceName = null; // Global variable to store the selected device name
|
|
let dataCache = {}; // Cache for storing fetched data
|
|
|
|
|
|
|
|
function updateTableData() {
|
|
fetch('/get_table_data')
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
const tableBody = document.getElementById('data-table').getElementsByTagName('tbody')[0];
|
|
tableBody.innerHTML = ''; // Clear existing table rows
|
|
|
|
let isRowSelected = selectedDeviceName !== null;
|
|
|
|
for (let key in data) {
|
|
let row = tableBody.insertRow();
|
|
row.addEventListener('click', function() {
|
|
// Handle row click event for selection
|
|
handleRowSelection(row, key);
|
|
});
|
|
|
|
let cell1 = row.insertCell();
|
|
let cell2 = row.insertCell();
|
|
let cell3 = row.insertCell();
|
|
cell1.innerHTML = key; // Device Name
|
|
|
|
// Assuming that the latest data is the most relevant
|
|
let latestData = data[key][data[key].length - 1];
|
|
cell2.innerHTML = latestData[0]; // Frequency
|
|
|
|
// Check for RSSI value and display 'unknown' if it is 0
|
|
let rssiValue = latestData[1];
|
|
cell3.innerHTML = rssiValue === 0 ? 'unknown' : rssiValue; // Signal Strength
|
|
|
|
// Apply hiding logic based on selection
|
|
if (isRowSelected) {
|
|
if (key !== selectedDeviceName) {
|
|
row.classList.add('hidden-row');
|
|
} else {
|
|
row.classList.add('selected-row');
|
|
}
|
|
}
|
|
}
|
|
|
|
updateSelectedDataDisplay(); // Update the selected data display after refreshing the table
|
|
})
|
|
.catch(error => console.error('Error:', error));
|
|
}
|
|
|
|
function handleRowSelection(row, key) {
|
|
// Reset all rows
|
|
const tableBody = document.getElementById('data-table').getElementsByTagName('tbody')[0];
|
|
const allRows = tableBody.getElementsByTagName('tr');
|
|
for (let i = 0; i < allRows.length; i++) {
|
|
allRows[i].classList.remove('hidden-row', 'selected-row');
|
|
}
|
|
|
|
// Highlight and show the clicked row
|
|
row.classList.add('selected-row');
|
|
|
|
// Display the "Clear Filter" button
|
|
const clearButton = document.getElementById('clear-selection-button');
|
|
clearButton.style.display = 'block';
|
|
|
|
selectedDeviceName = key; // Update the global variable with the selected device name
|
|
updateSelectedDataDisplay(); // Update the selected data display
|
|
}
|
|
|
|
// ... rest of your existing code for updateSelectedDataDisplay, clearButton event listener, etc.
|
|
|
|
// Initial update of the table
|
|
updateTableData();
|
|
|
|
// Periodically update the table every second
|
|
setInterval(updateTableData, 10000);
|
|
|
|
|
|
|
|
|
|
|
|
const clearButton = document.getElementById('clear-selection-button');
|
|
clearButton.addEventListener('click', function () {
|
|
const tableBody = document.getElementById('data-table').getElementsByTagName('tbody')[0];
|
|
const selectedRow = tableBody.getElementsByClassName('selected-row')[0];
|
|
if (selectedRow) {
|
|
selectedRow.classList.remove('selected-row');
|
|
}
|
|
|
|
// Show all rows
|
|
const allRows = tableBody.getElementsByTagName('tr');
|
|
for (let i = 0; i < allRows.length; i++) {
|
|
allRows[i].classList.remove('hidden-row');
|
|
}
|
|
|
|
// Hide the "Clear Filter" button
|
|
clearButton.style.display = 'none';
|
|
|
|
selectedDeviceName = null; // Reset the global variable when selection is cleared
|
|
updateSelectedDataDisplay(); // Clear the selected data display
|
|
});
|
|
|
|
|
|
</script>
|
|
|
|
|
|
</div>
|
|
|
|
<!-- 433 -->
|
|
<div class="resume-section-content">
|
|
<!-- Collapsible content -->
|
|
<div class="collapse" id="collapse433">
|
|
<div class="d-flex flex-column flex-md-row justify-content-between mb-5">
|
|
<div class="flex-grow-1">
|
|
<h3 class="mb-0">433 MHz LoRa Transceiver</h3><br>
|
|
<div class="serial-data" id="serial-data-port1">
|
|
</div>
|
|
|
|
<div style="text-align:center;">
|
|
<button class="styled-button" onclick="promptUser433()">Select Device</button>
|
|
<button class="disconnect-button" onclick="deleteSerial433()">Disconnect Device</button>
|
|
<button class="transmit-button" onclick="transmit433()">Start Beacon</button>
|
|
<button class="disconnect-button" onclick="confirmStopTransmission433()">Stop Beacon</button><br><br>
|
|
<button class="transmit-button" onclick="clearDataPort1()">Clear Data</button>
|
|
<input type="checkbox" id="autoscroll-port1" checked>
|
|
<label for="autoscroll-port1">Autoscroll</label>
|
|
<p id="status-label433" style="text-align: center">Status: Checking...</p>
|
|
<div class="indicator-container">
|
|
<div id="indicator433" class="indicator"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- JavaScript for updating the indicator -->
|
|
<script>
|
|
function updateIndicator433() {
|
|
// Fetch the status from the Flask route
|
|
$.ajax({
|
|
url: '/checkSer',
|
|
type: 'GET',
|
|
data: {
|
|
port: 'port1',
|
|
|
|
},
|
|
success: function(response) {
|
|
|
|
if (response['result'] === 'True') {
|
|
$('#indicator433').removeClass('red').addClass('green');
|
|
$('#status-label433').text('Status: Connected');
|
|
} else {
|
|
$('#indicator433').removeClass('green').addClass('red');
|
|
$('#status-label433').text('Serial Port Status: Disconnected');
|
|
}
|
|
},
|
|
error: function() {
|
|
$('#indicator433').removeClass('green').addClass('red');
|
|
$('#status-label433').text('Serial Port Status: Disconnected');
|
|
}
|
|
});
|
|
}
|
|
|
|
// Initial update of the indicator
|
|
updateIndicator433();
|
|
|
|
// Periodically check and update the indicator (e.g., every 5 seconds)
|
|
setInterval(updateIndicator433, 5000);
|
|
</script>
|
|
<script type="text/javascript">
|
|
var socket = io.connect('http://' + document.domain + ':' + location.port);
|
|
|
|
// For port1
|
|
socket.on('initial_serial_data_port1', function(data) {
|
|
var serialDataDiv = document.getElementById('serial-data-port1');
|
|
data.data.forEach(function(line) {
|
|
serialDataDiv.innerHTML += line + '<br>';
|
|
});
|
|
// Scroll to the bottom for new data
|
|
//serialDataDiv.scrollTop = serialDataDiv.scrollHeight;
|
|
});
|
|
|
|
socket.on('serial_data_port1', function(data) {
|
|
var serialDataDiv = document.getElementById('serial-data-port1');
|
|
serialDataDiv.innerHTML += data.data + '<br>';
|
|
var autoscrollCheckbox = document.getElementById('autoscroll-port1');
|
|
if (autoscrollCheckbox.checked) {
|
|
serialDataDiv.scrollTop = serialDataDiv.scrollHeight;
|
|
}
|
|
});
|
|
|
|
</script>
|
|
|
|
<script>
|
|
function promptUser433() {
|
|
// First, fetch the list of available ports
|
|
fetch('/get_serial_ports')
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
const ports = data.ports;
|
|
|
|
// Create the select options
|
|
const selectOptions = ports.map(port => `<option value="${port}">${port}</option>`).join('');
|
|
|
|
Swal.fire({
|
|
title: 'Select Serial Port:',
|
|
html: `<select id="port-select" class="swal2-input">${selectOptions}</select>`,
|
|
showCancelButton: true,
|
|
confirmButtonText: 'Connect',
|
|
cancelButtonText: 'Cancel',
|
|
preConfirm: () => {
|
|
const selectedPort = document.getElementById('port-select').value;
|
|
return fetch(`/attach_serial_433?user_input=${encodeURIComponent(selectedPort)}`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
Swal.fire({
|
|
title: 'Result',
|
|
text: data.result,
|
|
icon: 'info'
|
|
});
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
Swal.fire('Oops!', 'Something went wrong. The port might already be in use.', 'error');
|
|
});
|
|
}
|
|
});
|
|
})
|
|
.catch(error => {
|
|
console.error('Error fetching ports:', error);
|
|
Swal.fire('Oops!', 'Failed to fetch available ports.', 'error');
|
|
});
|
|
}
|
|
</script>
|
|
|
|
<script>
|
|
function deleteSerial433() {
|
|
Swal.fire({
|
|
title: 'Are you sure you want to disconnect the 433 MHz port?',
|
|
icon: 'question',
|
|
showCancelButton: true,
|
|
confirmButtonText: 'Yes',
|
|
cancelButtonText: 'No',
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
// User clicked "Yes" - Send HTTP GET request to Flask
|
|
fetch('/delete_serial_433')
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
Swal.fire({
|
|
title: 'Confirmation Result',
|
|
text: data.result,
|
|
icon: 'info'
|
|
});
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
Swal.fire('Oops!', 'Something went wrong.', 'error');
|
|
});
|
|
}
|
|
});
|
|
}
|
|
</script>
|
|
<script>
|
|
var transmitIntervalId433 = null;
|
|
|
|
function transmit433() {
|
|
Swal.fire({
|
|
title: 'Enter data to transmit and set interval:',
|
|
html:
|
|
'<input id="swal-input1" class="swal2-input" placeholder="Enter data">' +
|
|
'<input id="swal-input2" class="swal2-input" placeholder="Interval in milliseconds">',
|
|
focusConfirm: false,
|
|
showCancelButton: true,
|
|
confirmButtonText: 'Submit',
|
|
cancelButtonText: 'Cancel',
|
|
preConfirm: () => {
|
|
const data = document.getElementById('swal-input1').value;
|
|
const interval = document.getElementById('swal-input2').value;
|
|
|
|
if (!data || !interval) {
|
|
Swal.showValidationMessage('Please enter both data and interval');
|
|
} else if (isNaN(interval) || interval < 1000) { // Ensuring the interval is a number and at least 1 second (1000 milliseconds)
|
|
Swal.showValidationMessage('Please enter a valid interval (number >= 1000)');
|
|
} else {
|
|
return { data: data, interval: interval };
|
|
}
|
|
}
|
|
}).then((result) => {
|
|
if (result.isConfirmed && result.value) {
|
|
startTransmission433(result.value.data, result.value.interval);
|
|
Swal.fire({
|
|
title: 'Transmission Started!',
|
|
html: `Data: ${result.value.data}<br>Interval: ${result.value.interval} milliseconds`,
|
|
icon: 'success'
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
|
|
function startTransmission433(data, interval) {
|
|
if (transmitIntervalId433) {
|
|
clearInterval(transmitIntervalId433); // Clear existing interval
|
|
}
|
|
transmitIntervalId433 = setInterval(() => {
|
|
sendTransmissionData433(data);
|
|
}, parseInt(interval)); // Use the user-provided interval, ensuring it's an integer
|
|
|
|
// Send the first transmission immediately
|
|
sendTransmissionData433(data);
|
|
}
|
|
|
|
|
|
|
|
function sendTransmissionData433(data) {
|
|
return fetch('/transmit433', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({ user_input: data })
|
|
})
|
|
.then(response => {
|
|
if (!response.ok) {
|
|
throw new Error('Network response was not ok');
|
|
}
|
|
return response.json();
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
Swal.fire('Error', 'Transmission failed: ' + error.message, 'error');
|
|
clearInterval(transmitIntervalId433); // Stop the interval on error
|
|
});
|
|
}
|
|
|
|
|
|
function stopTransmission433() {
|
|
if (transmitIntervalId433) {
|
|
clearInterval(transmitIntervalId433);
|
|
transmitIntervalId433 = null;
|
|
Swal.fire('Transmission Stopped', '', 'info');
|
|
}
|
|
}
|
|
|
|
function confirmStopTransmission433() {
|
|
Swal.fire({
|
|
title: 'Are you sure?',
|
|
text: "Do you want to stop the transmission?",
|
|
icon: 'warning',
|
|
showCancelButton: true,
|
|
confirmButtonColor: '#3085d6',
|
|
cancelButtonColor: '#d33',
|
|
confirmButtonText: 'Yes, stop it!'
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
stopTransmission433();
|
|
}
|
|
});
|
|
}
|
|
</script>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Collapsible button -->
|
|
<a class="btn btn-primary" data-bs-toggle="collapse" href="#collapse433" role="button" aria-expanded="false" aria-controls="collapse433">
|
|
Toggle 433 MHz Beacon
|
|
</a>
|
|
</div>
|
|
<br><br>
|
|
<div class="resume-section-content">
|
|
<div class="collapse" id="collapse868">
|
|
<div class="d-flex flex-column flex-md-row justify-content-between mb-5">
|
|
<div class="flex-grow-1">
|
|
<h3 class="mb-0">868 MHz LoRa Transceiver</h3><br>
|
|
<div class="serial-data" id="serial-data-port2">
|
|
</div>
|
|
<div style="text-align:center;">
|
|
<button class="styled-button" onclick="promptUser868()">Select Device</button>
|
|
<button class="disconnect-button" onclick="deleteSerial868()">Disconnect Device</button>
|
|
<button class="transmit-button" onclick="transmit868()">Start Beacon</button>
|
|
<button class="disconnect-button" onclick="confirmStopTransmission868()">Stop Beacon</button><br><br>
|
|
<button class="transmit-button" onclick="clearDataPort2()">Clear Data</button>
|
|
<input type="checkbox" id="autoscroll-port2" checked>
|
|
<label for="autoscroll-port2">Autoscroll</label>
|
|
<p id="status-label868" style="text-align: center">Status: Checking...</p>
|
|
<div class="indicator-container">
|
|
<div id="indicator868" class="indicator"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
function updateIndicator868() {
|
|
// Fetch the status from the Flask route
|
|
$.ajax({
|
|
url: '/checkSer',
|
|
type: 'GET',
|
|
data: {
|
|
port: 'port2',
|
|
|
|
},
|
|
success: function(response) {
|
|
|
|
if (response['result'] === 'True') {
|
|
$('#indicator868').removeClass('red').addClass('green');
|
|
$('#status-label868').text('Status: Connected');
|
|
} else {
|
|
$('#indicator868').removeClass('green').addClass('red');
|
|
$('#status-label868').text('Serial Port Status: Disconnected');
|
|
}
|
|
},
|
|
error: function() {
|
|
$('#indicator868').removeClass('green').addClass('red');
|
|
$('#status-label868a').text('Serial Port Status: Disconnected');
|
|
}
|
|
});
|
|
}
|
|
|
|
// Initial update of the indicator
|
|
updateIndicator868();
|
|
|
|
// Periodically check and update the indicator (e.g., every 5 seconds)
|
|
setInterval(updateIndicator868, 5000);
|
|
</script>
|
|
|
|
<script>
|
|
// For port2
|
|
var socket = io.connect('http://' + document.domain + ':' + location.port);
|
|
socket.on('initial_serial_data_port2', function(data) {
|
|
var serialDataDiv2 = document.getElementById('serial-data-port2');
|
|
data.data.forEach(function(line) {
|
|
serialDataDiv2.innerHTML += line + '<br>';
|
|
});
|
|
});
|
|
|
|
socket.on('serial_data_port2', function(data) {
|
|
var serialDataDiv2 = document.getElementById('serial-data-port2');
|
|
serialDataDiv2.innerHTML += data.data + '<br>';
|
|
var autoscrollCheckbox2 = document.getElementById('autoscroll-port2');
|
|
if (autoscrollCheckbox2.checked) {
|
|
serialDataDiv2.scrollTop = serialDataDiv2.scrollHeight;
|
|
}
|
|
});
|
|
|
|
</script>
|
|
|
|
<script>
|
|
function promptUser868() {
|
|
// First, fetch the list of available ports
|
|
fetch('/get_serial_ports')
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
const ports = data.ports;
|
|
|
|
// Create the select options
|
|
const selectOptions = ports.map(port => `<option value="${port}">${port}</option>`).join('');
|
|
|
|
Swal.fire({
|
|
title: 'Select Serial Port:',
|
|
html: `<select id="port-select" class="swal2-input">${selectOptions}</select>`,
|
|
showCancelButton: true,
|
|
confirmButtonText: 'Connect',
|
|
cancelButtonText: 'Cancel',
|
|
preConfirm: () => {
|
|
const selectedPort = document.getElementById('port-select').value;
|
|
return fetch(`/attach_serial_868?user_input=${encodeURIComponent(selectedPort)}`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
Swal.fire({
|
|
title: 'Result',
|
|
text: data.result,
|
|
icon: 'info'
|
|
});
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
Swal.fire('Oops!', 'Something went wrong. The port might already be in use.', 'error');
|
|
});
|
|
}
|
|
});
|
|
})
|
|
.catch(error => {
|
|
console.error('Error fetching ports:', error);
|
|
Swal.fire('Oops!', 'Failed to fetch available ports.', 'error');
|
|
});
|
|
}
|
|
</script>
|
|
|
|
<script>
|
|
function deleteSerial868() {
|
|
Swal.fire({
|
|
title: 'Are you sure you want to disconnect the 868 MHz port?',
|
|
icon: 'question',
|
|
showCancelButton: true,
|
|
confirmButtonText: 'Yes',
|
|
cancelButtonText: 'No',
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
// User clicked "Yes" - Send HTTP GET request to Flask
|
|
fetch('/delete_serial_868')
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
Swal.fire({
|
|
title: 'Confirmation Result',
|
|
text: data.result,
|
|
icon: 'info'
|
|
});
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
Swal.fire('Oops!', 'Something went wrong.', 'error');
|
|
});
|
|
}
|
|
});
|
|
}
|
|
</script>
|
|
|
|
<script>
|
|
var transmitIntervalId868 = null;
|
|
|
|
function transmit868() {
|
|
Swal.fire({
|
|
title: 'Enter data to transmit and set interval:',
|
|
html:
|
|
'<input id="swal-input1-868" class="swal2-input" placeholder="Enter data">' +
|
|
'<input id="swal-input2-868" class="swal2-input" placeholder="Interval in milliseconds">',
|
|
focusConfirm: false,
|
|
showCancelButton: true,
|
|
confirmButtonText: 'Submit',
|
|
cancelButtonText: 'Cancel',
|
|
preConfirm: () => {
|
|
const data = document.getElementById('swal-input1-868').value;
|
|
const interval = document.getElementById('swal-input2-868').value;
|
|
|
|
if (!data || !interval) {
|
|
Swal.showValidationMessage('Please enter both data and interval');
|
|
} else if (isNaN(interval) || interval < 1000) {
|
|
Swal.showValidationMessage('Please enter a valid interval (number >= 1000)');
|
|
} else {
|
|
return { data: data, interval: interval };
|
|
}
|
|
}
|
|
}).then((result) => {
|
|
if (result.isConfirmed && result.value) {
|
|
startTransmission868(result.value.data, result.value.interval);
|
|
Swal.fire({
|
|
title: 'Transmission Started!',
|
|
html: `Data: ${result.value.data}<br>Interval: ${result.value.interval} milliseconds`,
|
|
icon: 'success'
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
|
|
function startTransmission868(data, interval) {
|
|
if (transmitIntervalId868) {
|
|
clearInterval(transmitIntervalId868); // Clear existing interval
|
|
}
|
|
transmitIntervalId868 = setInterval(() => {
|
|
sendTransmissionData868(data);
|
|
}, parseInt(interval));
|
|
|
|
// Send the first transmission immediately
|
|
sendTransmissionData868(data);
|
|
}
|
|
|
|
|
|
|
|
function sendTransmissionData868(data) {
|
|
return fetch('/transmit868', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({ user_input: data })
|
|
})
|
|
.then(response => {
|
|
if (!response.ok) {
|
|
throw new Error('Network response was not ok');
|
|
}
|
|
return response.json();
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
Swal.fire('Error', 'Transmission failed: ' + error.message, 'error');
|
|
clearInterval(transmitIntervalId868); // Stop the interval on error
|
|
});
|
|
}
|
|
|
|
|
|
function stopTransmission868() {
|
|
if (transmitIntervalId868) {
|
|
clearInterval(transmitIntervalId868);
|
|
transmitIntervalId868 = null;
|
|
Swal.fire('Transmission Stopped', '', 'info');
|
|
}
|
|
}
|
|
|
|
function confirmStopTransmission868() {
|
|
Swal.fire({
|
|
title: 'Are you sure?',
|
|
text: "Do you want to stop the transmission?",
|
|
icon: 'warning',
|
|
showCancelButton: true,
|
|
confirmButtonColor: '#3085d6',
|
|
cancelButtonColor: '#d33',
|
|
confirmButtonText: 'Yes, stop it!'
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
stopTransmission868();
|
|
}
|
|
});
|
|
}
|
|
</script>
|
|
</div>
|
|
</div>
|
|
<!-- Collapsible button -->
|
|
<a class="btn btn-primary" data-bs-toggle="collapse" href="#collapse868" role="button" aria-expanded="false" aria-controls="collapse868">
|
|
Toggle 868 MHz Beacon
|
|
</a>
|
|
</div>
|
|
<br><br>
|
|
|
|
<!--915 MHz-->
|
|
<div class="resume-section-content">
|
|
<div class="collapse" id="collapse915">
|
|
<div class="d-flex flex-column flex-md-row justify-content-between mb-5">
|
|
<div class="flex-grow-1">
|
|
<h3 class="mb-0">915 MHZ LoRa Transceiver</h3><br>
|
|
<div class="serial-data" id="serial-data-port3">
|
|
</div>
|
|
<div style="text-align:center;">
|
|
<button class="styled-button" onclick="promptUser915()">Select Device</button>
|
|
<button class="disconnect-button" onclick="deleteSerial915()">Disconnect Device</button>
|
|
<button class="transmit-button" onclick="transmit915()">Start Beacon</button>
|
|
<button class="disconnect-button" onclick="confirmStopTransmission915()">Stop Beacon</button><br><br>
|
|
<button class="transmit-button" onclick="clearDataPort3()">Clear Data</button>
|
|
<input type="checkbox" id="autoscroll-port3" checked>
|
|
<label for="autoscroll-port3">Autoscroll</label>
|
|
<p id="status-label915" style="text-align: center">Status: Checking...</p>
|
|
<div class="indicator-container">
|
|
<div id="indicator915" class="indicator"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
function updateIndicator915() {
|
|
// Fetch the status from the Flask route
|
|
$.ajax({
|
|
url: '/checkSer',
|
|
type: 'GET',
|
|
data: {
|
|
port: 'port3',
|
|
|
|
},
|
|
success: function(response) {
|
|
|
|
if (response['result'] === 'True') {
|
|
$('#indicator915').removeClass('red').addClass('green');
|
|
$('#status-label915').text('Status: Connected');
|
|
} else {
|
|
$('#indicator915').removeClass('green').addClass('red');
|
|
$('#status-label915').text('Serial Port Status: Disconnected');
|
|
}
|
|
},
|
|
error: function() {
|
|
$('#indicator915').removeClass('green').addClass('red');
|
|
$('#status-label915').text('Serial Port Status: Disconnected');
|
|
}
|
|
});
|
|
}
|
|
|
|
// Initial update of the indicator
|
|
updateIndicator915();
|
|
|
|
// Periodically check and update the indicator (e.g., every 5 seconds)
|
|
setInterval(updateIndicator915, 5000);
|
|
</script>
|
|
<script>
|
|
// For port3
|
|
var socket = io.connect('http://' + document.domain + ':' + location.port);
|
|
socket.on('initial_serial_data_port3', function(data) {
|
|
var serialDataDiv3 = document.getElementById('serial-data-port3');
|
|
data.data.forEach(function(line) {
|
|
serialDataDiv3.innerHTML += line + '<br>';
|
|
});
|
|
|
|
});
|
|
|
|
socket.on('serial_data_port3', function(data) {
|
|
var serialDataDiv3 = document.getElementById('serial-data-port3');
|
|
serialDataDiv3.innerHTML += data.data + '<br>';
|
|
var autoscrollCheckbox3 = document.getElementById('autoscroll-port3');
|
|
if (autoscrollCheckbox3.checked) {
|
|
serialDataDiv3.scrollTop = serialDataDiv3.scrollHeight;
|
|
}
|
|
});
|
|
|
|
</script>
|
|
|
|
<script>
|
|
function promptUser915() {
|
|
// First, fetch the list of available ports
|
|
fetch('/get_serial_ports')
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
const ports = data.ports;
|
|
|
|
// Create the select options
|
|
const selectOptions = ports.map(port => `<option value="${port}">${port}</option>`).join('');
|
|
|
|
Swal.fire({
|
|
title: 'Select Serial Port:',
|
|
html: `<select id="port-select" class="swal2-input">${selectOptions}</select>`,
|
|
showCancelButton: true,
|
|
confirmButtonText: 'Connect',
|
|
cancelButtonText: 'Cancel',
|
|
preConfirm: () => {
|
|
const selectedPort = document.getElementById('port-select').value;
|
|
return fetch(`/attach_serial_915?user_input=${encodeURIComponent(selectedPort)}`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
Swal.fire({
|
|
title: 'Result',
|
|
text: data.result,
|
|
icon: 'info'
|
|
});
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
Swal.fire('Oops!', 'Something went wrong. The port might already be in use.', 'error');
|
|
});
|
|
}
|
|
});
|
|
})
|
|
.catch(error => {
|
|
console.error('Error fetching ports:', error);
|
|
Swal.fire('Oops!', 'Failed to fetch available ports.', 'error');
|
|
});
|
|
}
|
|
</script>
|
|
|
|
<script>
|
|
function deleteSerial915() {
|
|
Swal.fire({
|
|
title: 'Are you sure you want to disconnect the 915 MHz port?',
|
|
icon: 'question',
|
|
showCancelButton: true,
|
|
confirmButtonText: 'Yes',
|
|
cancelButtonText: 'No',
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
// User clicked "Yes" - Send HTTP GET request to Flask
|
|
fetch('/delete_serial_915')
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
Swal.fire({
|
|
title: 'Confirmation Result',
|
|
text: data.result,
|
|
icon: 'info'
|
|
});
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
Swal.fire('Oops!', 'Something went wrong.', 'error');
|
|
});
|
|
}
|
|
});
|
|
}
|
|
</script>
|
|
<script>
|
|
var transmitIntervalId915 = null;
|
|
|
|
function transmit915() {
|
|
Swal.fire({
|
|
title: 'Enter data to transmit and set interval:',
|
|
html:
|
|
'<input id="swal-input1-915" class="swal2-input" placeholder="Enter data">' +
|
|
'<input id="swal-input2-915" class="swal2-input" placeholder="Interval in milliseconds">',
|
|
focusConfirm: false,
|
|
showCancelButton: true,
|
|
confirmButtonText: 'Submit',
|
|
cancelButtonText: 'Cancel',
|
|
preConfirm: () => {
|
|
const data = document.getElementById('swal-input1-915').value;
|
|
const interval = document.getElementById('swal-input2-915').value;
|
|
|
|
if (!data || !interval) {
|
|
Swal.showValidationMessage('Please enter both data and interval');
|
|
} else if (isNaN(interval) || interval < 1000) {
|
|
Swal.showValidationMessage('Please enter a valid interval (number >= 1000)');
|
|
} else {
|
|
return { data: data, interval: interval };
|
|
}
|
|
}
|
|
}).then((result) => {
|
|
if (result.isConfirmed && result.value) {
|
|
startTransmission915(result.value.data, result.value.interval);
|
|
Swal.fire({
|
|
title: 'Transmission Started!',
|
|
html: `Data: ${result.value.data}<br>Interval: ${result.value.interval} milliseconds`,
|
|
icon: 'success'
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
|
|
function startTransmission915(data, interval) {
|
|
if (transmitIntervalId915) {
|
|
clearInterval(transmitIntervalId915); // Clear existing interval
|
|
}
|
|
transmitIntervalId915 = setInterval(() => {
|
|
sendTransmissionData915(data);
|
|
}, parseInt(interval));
|
|
|
|
// Send the first transmission immediately
|
|
sendTransmissionData915(data);
|
|
}
|
|
|
|
|
|
|
|
function sendTransmissionData915(data) {
|
|
return fetch('/transmit915', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({ user_input: data })
|
|
})
|
|
.then(response => {
|
|
if (!response.ok) {
|
|
throw new Error('Network response was not ok');
|
|
}
|
|
return response.json();
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
Swal.fire('Error', 'Transmission failed: ' + error.message, 'error');
|
|
clearInterval(transmitIntervalId915); // Stop the interval on error
|
|
});
|
|
}
|
|
|
|
|
|
function stopTransmission915() {
|
|
if (transmitIntervalId915) {
|
|
clearInterval(transmitIntervalId915);
|
|
transmitIntervalId915 = null;
|
|
Swal.fire('Transmission Stopped', '', 'info');
|
|
}
|
|
}
|
|
|
|
function confirmStopTransmission915() {
|
|
Swal.fire({
|
|
title: 'Are you sure?',
|
|
text: "Do you want to stop the transmission?",
|
|
icon: 'warning',
|
|
showCancelButton: true,
|
|
confirmButtonColor: '#3085d6',
|
|
cancelButtonColor: '#d33',
|
|
confirmButtonText: 'Yes, stop it!'
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
stopTransmission915();
|
|
}
|
|
});
|
|
}
|
|
</script>
|
|
</div>
|
|
</div>
|
|
<!-- Collapsible button -->
|
|
<a class="btn btn-primary" data-bs-toggle="collapse" href="#collapse915" role="button" aria-expanded="false" aria-controls="collapse915">
|
|
Toggle 915 MHz Beacon
|
|
</a>
|
|
</div>
|
|
</section>
|
|
|
|
|
|
</div>
|
|
<!-- Bootstrap core JS-->
|
|
<script src="static/js/bootstrap.bundle.min.js"></script>
|
|
<!-- Core theme JS-->
|
|
<script src="static/js/scripts.js"></script>
|
|
</body>
|
|
</html>
|