Initial Site

This commit is contained in:
Halcy0nic
2023-12-13 14:15:05 -07:00
parent d86b7a8634
commit ae9c9a9d7e
11 changed files with 12274 additions and 0 deletions
+228
View File
@@ -0,0 +1,228 @@
from flask import Flask, render_template, request, jsonify
from markupsafe import escape
from flask_socketio import SocketIO, emit
import serial
import threading
import time
from collections import deque
import pandas as pd
app = Flask(__name__)
socketio = SocketIO(app)
serial_threads = {}
serial_buffers = {}
port1_status = True
port2_status = True
port3_status = True
global ser1
global ser2
global ser3
global_dataframe = pd.DataFrame(columns=['Device Name', 'Frequency', 'Signal Strength', 'Plaintext'])
frequency = lambda port: {'port1': 433, 'port2': 868,'port3': 915}.get(port, None)
def read_serial_data(port, ser, buffer):
global global_dataframe
while True:
try:
if ser.in_waiting > 0:
data = ser.readline().decode('utf-8').strip()
buffer.append(data)
socketio.emit(f'serial_data_{port}', {'data': data})
if (global_dataframe['Device Name'] == 'Unknown Raw LoRa Devices').any():
pass
else:
pandasdata = {'Device Name': 'Unknown Raw LoRa Devices', 'Frequency': frequency(port)}
global_dataframe = global_dataframe.append(pandasdata, ignore_index=True)
'''print(global_dataframe.head())'''
if (port == 'port1' and port1_status == False):
return
if (port == 'port2' and port2_status == False):
return
if (port == 'port3' and port3_status == False):
return
time.sleep(0.1)
except:
pass
def connect_serial(port,frequency):
global ser1
global ser2
global ser3
if frequency == 433:
try:
ser1 = serial.Serial(port, baudrate=9600)
serial_buffers['port1'] = deque(maxlen=10)
serial_threads['port1'] = threading.Thread(target=read_serial_data, args=('port1', ser1, serial_buffers['port1']))
serial_threads['port1'].daemon = True
serial_threads['port1'].start()
except:
print("\n\nPort for 433 MHz not available\n\n")
if frequency == 868:
try:
ser2 = serial.Serial(port, baudrate=9600)
serial_buffers['port2'] = deque(maxlen=10)
serial_threads['port2'] = threading.Thread(target=read_serial_data, args=('port2', ser2, serial_buffers['port2']))
serial_threads['port2'].daemon = True
serial_threads['port2'].start()
except:
print("\n\nPort for 868 MHz not available\n\n")
if frequency == 915:
try:
ser3 = serial.Serial(port, baudrate=9600)
serial_buffers['port3'] = deque(maxlen=10)
serial_threads['port3'] = threading.Thread(target=read_serial_data, args=('port3', ser3, serial_buffers['port3']))
serial_threads['port3'].daemon = True
serial_threads['port3'].start()
except:
print('\n\nPort for 915 MHz not available\n\n')
def disconnect_serial(port):
global ser1
global ser2
global ser3
try:
serial_threads[port].stop()
del serial_threads[port]
del serial_buffers[port]
except:
pass
if port == "port1":
ser1.close()
elif port == "port2":
ser2.close()
elif port == "port3":
ser3.close()
else:
print("Unkown port, something went wrong...")
@app.route('/')
def index():
return render_template('index.html')
@app.route('/analysis')
def analysis():
return render_template('analysis.html', initial_data={port: list(buffer) for port, buffer in serial_buffers.items()})
@app.route('/survey')
def survey():
return render_template('survey.html', initial_data={port: list(buffer) for port, buffer in serial_buffers.items()})
@app.route('/tracking')
def tracking():
return render_template('tracking.html', initial_data={port: list(buffer) for port, buffer in serial_buffers.items()})
@app.route('/attach_serial_433', methods=['GET'])
def attach_serial_433():
user_input = escape(request.args.get('user_input'))
port1_status = True
connect_serial(str(user_input), 433)
# Process the input as needed
result = f'Serial Port Requested for 433 MHz'
return jsonify(result=result)
@app.route('/delete_serial_433', methods=['GET'])
def delete433():
# Add your logic here to handle the confirmation
disconnect_serial("port1")
result = "Port Disconnected!"
return jsonify(result=result)
@app.route('/attach_serial_868', methods=['GET'])
def attach_serial_868():
user_input = escape(request.args.get('user_input'))
port2_status = True
connect_serial(str(user_input), 868)
# Process the input as needed
result = f'Serial Port Requested for 868 MHz'
return jsonify(result=result)
@app.route('/delete_serial_868', methods=['GET'])
def delete868():
# Add your logic here to handle the confirmation
disconnect_serial("port2")
result = "Port Disconnected!"
return jsonify(result=result)
@app.route('/attach_serial_915', methods=['GET'])
def attach_serial_915():
user_input = escape(request.args.get('user_input'))
connect_serial(str(user_input), 915)
# Process the input as needed
result = f'Serial Port Requested for 915 MHz'
return jsonify(result=result)
@app.route('/delete_serial_915', methods=['GET'])
def delete915():
# Add your logic here to handle the confirmation
disconnect_serial("port3")
result = "Port Disconnected!"
return jsonify(result=result)
@socketio.on('connect')
def handle_connect():
for port, buffer in serial_buffers.items():
emit(f'initial_serial_data_{port}', {'data': list(buffer)})
@app.route('/transmit433', methods=['POST'])
def transmit433():
global ser1
data = request.json # Get the data from the POST request
user_input = data.get('user_input') # Extract the user input
msg = "TX:"+user_input+" "
ser1.write(msg.encode())
return jsonify(result="Ok")
@app.route('/transmit868', methods=['POST'])
def transmit868():
global ser2
data = request.json # Get the data from the POST request
user_input = data.get('user_input') # Extract the user input
msg = "TX:"+user_input+" "
ser2.write(msg.encode())
return jsonify(result="Ok")
@app.route('/transmit915', methods=['POST'])
def transmit915():
global ser3
data = request.json # Get the data from the POST request
user_input = data.get('user_input') # Extract the user input
msg = "TX:"+user_input+" "
ser3.write(msg.encode())
return jsonify(result="Ok")
@app.route('/checkSer', methods=['GET'])
def checkSer():
data = request.args.get('port')
if data == 'port1':
try:
if ser1.is_open:
return jsonify(result="True")
except:
pass
elif data == 'port2':
try:
if ser2.is_open:
return jsonify(result="True")
except:
pass
elif data == 'port3':
try:
if ser3.is_open:
return jsonify(result="True")
except:
pass
return jsonify(result="False")
if __name__ == '__main__':
socketio.run(app, debug=True)
+49
View File
@@ -0,0 +1,49 @@
#!/usr/bin/env python3
import time
import sys
import serial
import argparse
from serial.threaded import LineReader, ReaderThread
parser = argparse.ArgumentParser(description='LoRa Radio mode receiver.')
parser.add_argument('port', help="Serial port descriptor")
args = parser.parse_args()
class PrintLines(LineReader):
def connection_made(self, transport):
print("connection made")
self.transport = transport
self.send_cmd('sys get ver')
self.send_cmd('mac pause')
self.send_cmd('radio set pwr 10')
self.send_cmd('radio rx 0')
self.send_cmd("sys set pindig GPIO10 0")
def handle_line(self, data):
if data == "ok" or data == 'busy':
return
if data == "radio_err":
self.send_cmd('radio rx 0')
return
self.send_cmd("sys set pindig GPIO10 1", delay=0)
print(data)
time.sleep(.1)
self.send_cmd("sys set pindig GPIO10 0", delay=1)
self.send_cmd('radio rx 0')
def connection_lost(self, exc):
if exc:
print(exc)
print("port closed")
def send_cmd(self, cmd, delay=.5):
self.transport.write(('%s\r\n' % cmd).encode('UTF-8'))
time.sleep(delay)
ser = serial.Serial(args.port, baudrate=57600)
with ReaderThread(ser, PrintLines) as protocol:
while(1):
pass
+56
View File
@@ -0,0 +1,56 @@
#!/usr/bin/env python3
import time
import sys
import serial
import argparse
from serial.threaded import LineReader, ReaderThread
parser = argparse.ArgumentParser(description='LoRa Radio mode sender.')
parser.add_argument('port', help="Serial port descriptor")
args = parser.parse_args()
class PrintLines(LineReader):
def connection_made(self, transport):
print("connection made")
self.transport = transport
self.send_cmd("sys set pindig GPIO11 0")
self.send_cmd('sys get ver')
self.send_cmd('radio get mod')
self.send_cmd('radio get freq')
self.send_cmd('radio get sf')
self.send_cmd('mac pause')
self.send_cmd('radio set pwr 10')
self.send_cmd("sys set pindig GPIO11 0")
self.frame_count = 0
def handle_line(self, data):
if data == "ok":
return
print("RECV: %s" % data)
def connection_lost(self, exc):
if exc:
print(exc)
print("port closed")
def tx(self):
self.send_cmd("sys set pindig GPIO11 1")
txmsg = 'radio tx %x%x' % (int(time.time()), self.frame_count)
self.send_cmd(txmsg)
time.sleep(.3)
self.send_cmd("sys set pindig GPIO11 0")
self.frame_count = self.frame_count + 1
def send_cmd(self, cmd, delay=.5):
print("SEND: %s" % cmd)
self.write_line(cmd)
time.sleep(delay)
ser = serial.Serial(args.port, baudrate=57600)
with ReaderThread(ser, PrintLines) as protocol:
while(1):
protocol.tx()
time.sleep(10)
Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

+11065
View File
File diff suppressed because it is too large Load Diff
+34
View File
@@ -0,0 +1,34 @@
/*!
* Start Bootstrap - Resume v7.0.6 (https://startbootstrap.com/theme/resume)
* Copyright 2013-2023 Start Bootstrap
* Licensed under MIT (https://github.com/StartBootstrap/startbootstrap-resume/blob/master/LICENSE)
*/
//
// Scripts
//
window.addEventListener('DOMContentLoaded', event => {
// Activate Bootstrap scrollspy on the main nav element
const sideNav = document.body.querySelector('#sideNav');
if (sideNav) {
new bootstrap.ScrollSpy(document.body, {
target: '#sideNav',
rootMargin: '0px 0px -40%',
});
};
// Collapse responsive navbar when toggler is visible
const navbarToggler = document.body.querySelector('.navbar-toggler');
const responsiveNavItems = [].slice.call(
document.querySelectorAll('#navbarResponsive .nav-link')
);
responsiveNavItems.map(function (responsiveNavItem) {
responsiveNavItem.addEventListener('click', () => {
if (window.getComputedStyle(navbarToggler).display !== 'none') {
navbarToggler.click();
}
});
});
});
+617
View File
@@ -0,0 +1,617 @@
<!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="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.1.2/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="https://use.fontawesome.com/releases/v6.3.0/js/all.js" crossorigin="anonymous"></script>
<!-- Google fonts-->
<link href="https://fonts.googleapis.com/css?family=Saira+Extra+Condensed:500,700" rel="stylesheet" type="text/css" />
<link href="https://fonts.googleapis.com/css?family=Muli:400,400i,800,800i" rel="stylesheet" type="text/css" />
<!-- Core theme CSS (includes Bootstrap)-->
<link href="static/css/styles.css" rel="stylesheet" />
<!-- Include SweetAlert2 CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@10">
<!-- Include SweetAlert2 JS -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@10"></script>
<script src="https://code.jquery.com/jquery-3.6.0.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="#">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">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">
Analysis Mode
</h1>
<h2 class="lead mb-5">Skinny Research and Development</h2>
<p>
Analyze LoRa traffic received at 433, 868, or 915 MHz. Click the desired frequency below to get started. Once you are on the appropriate page, click the 'Connect Serial Port' button to connect to a serial port on your computer. Once connected to your LoRa receiver, traffic will automatically be streamed to the web page for analysis. To disconnect a receiver, click the 'Disconnect Serial Port' button.
</p>
<h2 class="lead mb-5">
<a class="nav-link js-scroll-trigger" href="#433">433 MHz</a>
<br>
<a class="nav-link js-scroll-trigger" href="#868">868 MHz</a>
<br>
<a class="nav-link js-scroll-trigger" href="#915">915 MHz</a>
</h2>
</div>
</section>
<hr class="m-0" />
<!-- 433 -->
<section class="resume-section" id="433">
<div class="resume-section-content">
<h2 class="mb-5">433 MHz</h2>
<div class="d-flex flex-column flex-md-row justify-content-between mb-5">
<div class="flex-grow-1">
<h3 class="mb-0">LoRa Transceiver</h3><br>
<div class="serial-data" id="serial-data-port1">
</div>
<div style="text-align:center;">
<button class="styled-button" onclick="promptUser433()">Connect Serial Port</button>
<button class="disconnect-button" onclick="deleteSerial433()">Disconnect Serial Port</button>
<button class="transmit-button" onclick="transmit433()">Transmit Data</button><br>
<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>';
// Scroll to the bottom for new data
//serialDataDiv.scrollTop = serialDataDiv.scrollHeight;
});
</script>
<script>
function promptUser433() {
Swal.fire({
title: 'Serial Port:',
input: 'text',
inputAttributes: {
autocapitalize: 'off'
},
showCancelButton: true,
confirmButtonText: 'Submit',
cancelButtonText: 'Cancel',
showLoaderOnConfirm: true,
preConfirm: (value) => {
// Make an AJAX request to Flask
fetch(`/attach_serial_433?user_input=${encodeURIComponent(value)}`)
.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.', 'error');
});
},
allowOutsideClick: () => !Swal.isLoading()
});
}
</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>
function transmit433() {
Swal.fire({
title: 'Enter data to transmit:',
input: 'text',
inputAttributes: {
autocapitalize: 'off'
},
showCancelButton: true,
confirmButtonText: 'Submit',
cancelButtonText: 'Cancel',
showLoaderOnConfirm: true,
preConfirm: (value) => {
// Make an HTTP POST request to Flask
return fetch('/transmit433', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ user_input: value })
})
.then(response => response.json())
.catch(error => {
console.error('Error:', error);
Swal.fire('Oops!', 'Something went wrong. Maybe the serial port is disconnected?', 'error');
});
},
allowOutsideClick: () => !Swal.isLoading()
}).then((result) => {
if (result.isConfirmed) {
Swal.fire({
title: 'Data Transmitted',
icon: 'info'
});
}
});
}
</script>
</section>
<hr class="m-0" />
<!-- 868 -->
<section class="resume-section" id="868">
<div class="resume-section-content">
<h2 class="mb-5">868 MHz</h2>
<div class="d-flex flex-column flex-md-row justify-content-between mb-5">
<div class="flex-grow-1">
<h3 class="mb-0">LoRa Transceiver</h3><br>
<div class="serial-data" id="serial-data-port2">
</div>
<div style="text-align:center;">
<button class="styled-button" onclick="promptUser868()">Connect Serial Port</button>
<button class="disconnect-button" onclick="deleteSerial868()">Disconnect Serial Port</button>
<button class="transmit-button" onclick="transmit868()">Transmit Data</button><br>
<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 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>';
// Scroll to the bottom for new data
//serialDataDiv.scrollTop = serialDataDiv.scrollHeight;
});
</script>
<script>
// For port2
socket.on('initial_serial_data_port2', function(data) {
var serialDataDiv = document.getElementById('serial-data-port2');
data.data.forEach(function(line) {
serialDataDiv.innerHTML += line + '<br>';
});
// Scroll to the bottom for new data
//serialDataDiv.scrollTop = serialDataDiv.scrollHeight;
});
socket.on('serial_data_port2', function(data) {
var serialDataDiv = document.getElementById('serial-data-port2');
serialDataDiv.innerHTML += data.data + '<br>';
// Scroll to the bottom for new data
//serialDataDiv.scrollTop = serialDataDiv.scrollHeight;
});
</script>
<script>
function promptUser868() {
Swal.fire({
title: 'Serial Port:',
input: 'text',
inputAttributes: {
autocapitalize: 'off'
},
showCancelButton: true,
confirmButtonText: 'Submit',
cancelButtonText: 'Cancel',
showLoaderOnConfirm: true,
preConfirm: (value) => {
// Make an AJAX request to Flask
fetch(`/attach_serial_868?user_input=${encodeURIComponent(value)}`)
.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.', 'error');
});
},
allowOutsideClick: () => !Swal.isLoading()
});
}
</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>
function transmit868() {
Swal.fire({
title: 'Enter data to transmit:',
input: 'text',
inputAttributes: {
autocapitalize: 'off'
},
showCancelButton: true,
confirmButtonText: 'Submit',
cancelButtonText: 'Cancel',
showLoaderOnConfirm: true,
preConfirm: (value) => {
// Make an HTTP POST request to Flask
return fetch('/transmit868', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ user_input: value })
})
.then(response => response.json())
.catch(error => {
console.error('Error:', error);
Swal.fire('Oops!', 'Something went wrong. Maybe the serial port is disconnected?', 'error');
});
},
allowOutsideClick: () => !Swal.isLoading()
}).then((result) => {
if (result.isConfirmed) {
Swal.fire({
title: 'Data Transmitted',
icon: 'info'
});
}
});
}
</script>
</section>
<hr class="m-0" />
<!-- 915-->
<section class="resume-section" id="915">
<div class="resume-section-content">
<h2 class="mb-5">915 MHz</h2><br>
<div class="d-flex flex-column flex-md-row justify-content-between mb-5">
<div class="flex-grow-1">
<h3 class="mb-0">LoRa Transceiver</h3><br>
<div class="serial-data" id="serial-data-port3">
</div>
<div style="text-align:center;">
<button class="styled-button" onclick="promptUser915()">Connect Serial Port</button>
<button class="disconnect-button" onclick="deleteSerial915()">Disconnect Serial Port</button>
<button class="transmit-button" onclick="transmit915()">Transmit Data</button><br>
<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
socket.on('initial_serial_data_port3', function(data) {
var serialDataDiv = document.getElementById('serial-data-port3');
data.data.forEach(function(line) {
serialDataDiv.innerHTML += line + '<br>';
});
// Scroll to the bottom for new data
//serialDataDiv.scrollTop = serialDataDiv.scrollHeight;
});
socket.on('serial_data_port3', function(data) {
var serialDataDiv = document.getElementById('serial-data-port3');
serialDataDiv.innerHTML += data.data + '<br>';
// Scroll to the bottom for new data
//serialDataDiv.scrollTop = serialDataDiv.scrollHeight;
});
</script>
<script>
function promptUser915() {
Swal.fire({
title: 'Serial Port:',
input: 'text',
inputAttributes: {
autocapitalize: 'off'
},
showCancelButton: true,
confirmButtonText: 'Submit',
cancelButtonText: 'Cancel',
showLoaderOnConfirm: true,
preConfirm: (value) => {
// Make an AJAX request to Flask
fetch(`/attach_serial_915?user_input=${encodeURIComponent(value)}`)
.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.', 'error');
});
},
allowOutsideClick: () => !Swal.isLoading()
});
}
</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>
function transmit915() {
Swal.fire({
title: 'Enter data to transmit:',
input: 'text',
inputAttributes: {
autocapitalize: 'off'
},
showCancelButton: true,
confirmButtonText: 'Submit',
cancelButtonText: 'Cancel',
showLoaderOnConfirm: true,
preConfirm: (value) => {
// Make an HTTP POST request to Flask
return fetch('/transmit915', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ user_input: value })
})
.then(response => response.json())
.catch(error => {
console.error('Error:', error);
Swal.fire('Oops!', 'Something went wrong. Maybe the serial port is disconnected?', 'error');
});
},
allowOutsideClick: () => !Swal.isLoading()
}).then((result) => {
if (result.isConfirmed) {
Swal.fire({
title: 'Data Transmitted',
icon: 'info'
});
}
});
}
</script>
</section>
</div>
<!-- Bootstrap core JS-->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
<!-- Core theme JS-->
<script src="static/js/scripts.js"></script>
</body>
</html>
+70
View File
@@ -0,0 +1,70 @@
<!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="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.1.2/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="https://use.fontawesome.com/releases/v6.3.0/js/all.js" crossorigin="anonymous"></script>
<!-- Google fonts-->
<link href="https://fonts.googleapis.com/css?family=Saira+Extra+Condensed:500,700" rel="stylesheet" type="text/css" />
<link href="https://fonts.googleapis.com/css?family=Muli:400,400i,800,800i" rel="stylesheet" type="text/css" />
<!-- Core theme CSS (includes Bootstrap)-->
<link href="static/css/styles.css" rel="stylesheet" />
<!-- Include SweetAlert2 CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@10">
<!-- Include SweetAlert2 JS -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@10"></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="#about">About</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">
LoRa Scanner
</h1>
<h2 class="lead mb-5">Skinny Research and Development</h2>
<p>LoRa, short for Long Range, is a wireless communication technology designed for long-range, low-power communication between devices in the Internet of Things (IoT) and machine-to-machine (M2M) applications. Developed to address the specific needs of IoT devices, LoRa technology enables efficient, low-cost, and long-range communication in various scenarios.
<br><br>LoRa operates on unlicensed radio frequencies, such as those in the Industrial, Scientific, and Medical (ISM) bands, providing the flexibility for deployment without the need for a dedicated spectrum license. It utilizes a modulation technique called Chirp Spread Spectrum (CSS), which allows for long-range communication with minimal power consumption.
<br><br>One of the key features of LoRa technology is its ability to provide extended communication ranges, often reaching several kilometers in open environments. This makes it suitable for applications where devices need to communicate over long distances while conserving battery life, such as in agriculture, smart cities, asset tracking, and environmental monitoring.
<br><br>LoRa devices typically consist of two main components: LoRa nodes (sensors or devices) and LoRa gateways. The nodes collect and transmit data, while gateways receive and forward this data to the central server or cloud infrastructure. The open LoRaWAN (Long Range Wide Area Network) protocol standardizes communication between devices and gateways, ensuring interoperability and facilitating the deployment of large-scale IoT networks.
<br><br>Due to its low power consumption, long-range capabilities, and suitability for diverse IoT applications, LoRa technology has gained popularity as a reliable and cost-effective solution for connecting a wide range of devices and sensors in the evolving landscape of the Internet of Things.
</p>
</div>
</section>
</div>
<!-- Bootstrap core JS-->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
<!-- Core theme JS-->
<script src="static/js/scripts.js"></script>
</body>
</html>
+98
View File
@@ -0,0 +1,98 @@
<!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="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.1.2/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="https://use.fontawesome.com/releases/v6.3.0/js/all.js" crossorigin="anonymous"></script>
<!-- Google fonts-->
<link href="https://fonts.googleapis.com/css?family=Saira+Extra+Condensed:500,700" rel="stylesheet" type="text/css" />
<link href="https://fonts.googleapis.com/css?family=Muli:400,400i,800,800i" rel="stylesheet" type="text/css" />
<!-- Core theme CSS (includes Bootstrap)-->
<link href="static/css/styles.css" rel="stylesheet" />
<!-- Include SweetAlert2 CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@10">
<!-- Include SweetAlert2 JS -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@10"></script>
<script src="https://code.jquery.com/jquery-3.6.0.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="/analysis">Analysis Mode</a></li>
<li class="nav-item"><a class="nav-link js-scroll-trigger" href="#">Survey Mode</a></li>
<li class="nav-item"><a class="nav-link js-scroll-trigger" href="/tracking">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">
Survey Mode
</h1>
<h2 class="lead mb-5">Skinny Research and Development</h2>
</div>
<!DOCTYPE html>
<html>
<head>
<title>DataFrame Table</title>
<style>
table {
border-collapse: collapse;
width: 80%;
margin: auto;
}
th, td {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
th {
background-color: #f2f2f2;
}
</style>
<table>
<thead>
<tr>
<th>Device Name</th>
<th>Frequency</th>
<th>Signal Strength</th>
<th>Plaintext</th>
</tr>
</thead>
<tbody>
{% for index, row in data.iterrows() %}
<tr>
<td>{{ row['Device Name'] }}</td>
<td>{{ row['Frequency'] }}</td>
<td>{{ row['Signal Strength'] }}</td>
<td>{{ row['Plaintext'] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</section>
<hr class="m-0" />
</body>
</html>
+57
View File
@@ -0,0 +1,57 @@
<!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="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.1.2/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="https://use.fontawesome.com/releases/v6.3.0/js/all.js" crossorigin="anonymous"></script>
<!-- Google fonts-->
<link href="https://fonts.googleapis.com/css?family=Saira+Extra+Condensed:500,700" rel="stylesheet" type="text/css" />
<link href="https://fonts.googleapis.com/css?family=Muli:400,400i,800,800i" rel="stylesheet" type="text/css" />
<!-- Core theme CSS (includes Bootstrap)-->
<link href="static/css/styles.css" rel="stylesheet" />
<!-- Include SweetAlert2 CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@10">
<!-- Include SweetAlert2 JS -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@10"></script>
<script src="https://code.jquery.com/jquery-3.6.0.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="/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">
Tracking Mode
</h1>
<h2 class="lead mb-5">Skinny Research and Development</h2>
</div>
</section>
<hr class="m-0" />
</body>
</html>