Merge pull request #5 from skinnyrad/feat/two_gateways

Feat/two gateways
This commit is contained in:
Halcy0nic
2024-03-29 14:25:42 -06:00
committed by GitHub
13 changed files with 11328 additions and 109 deletions
+83 -36
View File
@@ -9,6 +9,7 @@ from collections import deque
import re
import requests
from bs4 import BeautifulSoup
import ipaddress
app = Flask(__name__)
socketio = SocketIO(app)
@@ -20,6 +21,9 @@ port3_status = True
global ser1
global ser2
global ser3
gateway_ips = {'gateway1': '192.168.0.101',
'gateway2': '192.168.0.102',
'gateway3': '192.168.0.103'}
frequency = lambda port: {'port1': 433, 'port2': 868,'port3': 915}.get(port, None)
surveydata = {}
parsed_entries = set()
@@ -79,61 +83,104 @@ def read_serial_data(port, ser, buffer):
#print(f"Error: {e}")
pass
@app.route('/set_gateways', methods=['POST'])
def set_gateways():
global gateway_ips
data = request.form
for key in ['gateway1', 'gateway2', 'gateway3']:
input_ip = data.get(key, '').strip()
if input_ip: # Proceed only if the input is not empty
try:
# Validate the IP address
ipaddress.ip_address(input_ip)
# Update the IP address if valid
gateway_ips[key] = input_ip
except ValueError:
# Return an error if the IP address is invalid
return jsonify({"error": f"Invalid IP address provided for {key}"}), 400
for gateway, ip_address in gateway_ips.items():
print(f"Gateway {gateway} has IP address: {ip_address}")
return jsonify({"message": "Gateway IPs updated successfully"}), 200
def parse_and_store_data():
global surveydata
url = "http://10.130.1.1/cgi-bin/log-traffic.has" # Your target URL
global parsed_entries
global gateway_ips
# Include the port number (8000) in your gateway URLs
gateway_urls = [
f"http://{gateway_ips['gateway1']}:8000/cgi-bin/log-traffic.has", # Gateway 1
f"http://{gateway_ips['gateway2']}:8000/cgi-bin/log-traffic.has", # Gateway 2
f"http://{gateway_ips['gateway3']}:8000/cgi-bin/log-traffic.has" # Gateway 3
]
headers = {
"Host": "10.130.1.1",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:122.0) Gecko/20100101 Firefox/122.0",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.5",
"Accept-Encoding": "gzip, deflate",
"DNT": "1",
"Sec-GPC": "1",
"Authorization": "Basic cm9vdDpkcmFnaW5v",
"Authorization": "Basic cm9vdDpkcmFnaW5v", # Assumes the same credentials for both gateways
"Connection": "keep-alive",
"Referer": "http://10.130.1.1/cgi-bin/log-lora.has",
"Upgrade-Insecure-Requests": "1"
}
response = requests.get(url, headers=headers)
for url in gateway_urls:
try:
response = requests.get(url, headers=headers, timeout=10)
if response.status_code == 200:
soup = BeautifulSoup(response.text, 'html.parser')
table = soup.find('table')
if table:
rows = table.find_all('tr')[1:] # Skip the header row
for row in rows:
# Skip hidden rows in this iteration
if row.get('style') == 'display: none;':
continue
cells = row.find_all('td')
if not cells:
continue
# Prepare formatted_row from visible cells, skipping the first cell for Chevron icon
formatted_row = ' | '.join(cell.text.strip() for cell in cells[1:])
# Extract dev_id and freq from the visible row
dev_id = extract_dev_id(formatted_row)
freq = extract_freq(formatted_row)
if response.status_code == 200:
soup = BeautifulSoup(response.text, 'html.parser')
table = soup.find('table')
rows = table.find_all('tr')
headers = [header.text.strip() for header in rows[0].find_all('th')][1:]
# Extract RSSI from the next hidden row
hidden_row = row.find_next_sibling('tr')
if hidden_row and 'display: none;' in hidden_row.get('style', ''):
hidden_data = hidden_row.td.text.strip()
rssi_match = re.search(r'"Rssi":(-?\d+)', hidden_data)
if rssi_match:
rssi = int(rssi_match.group(1))
else:
rssi = None
else:
rssi = None
for row in rows[1:]:
cells = row.find_all('td')
cell_data = [cell.text.strip() for cell in cells[1:] if cells.index(cell) < len(headers) + 1]
formatted_row = ' | '.join(cell_data)
# Save data into the surveydata structure
if dev_id and freq is not None:
entry_identifier = f"{dev_id}_{freq}_{formatted_row}"
if entry_identifier not in parsed_entries:
parsed_entries.add(entry_identifier)
if dev_id not in surveydata:
surveydata[dev_id] = []
surveydata[dev_id].append([freq, rssi, formatted_row])
dev_id = extract_dev_id(formatted_row) # Your existing function to extract DevEui or DevAddr
freq = extract_freq(formatted_row) # Your existing function to extract frequency
if dev_id and freq:
entry_identifier = f"{dev_id}_{formatted_row}" # Create a unique identifier for the entry
# Only process the entry if we haven't seen this identifier before
if entry_identifier not in parsed_entries:
parsed_entries.add(entry_identifier) # Add the identifier to the set
# Initialize dictionary for dev_id if not present
if dev_id not in surveydata:
surveydata[dev_id] = []
# Append new data to the list associated with the DevEui or DevAddr
surveydata[dev_id].append([freq, 0, formatted_row])
print("Data parsed and stored.")
else:
print(f"Request failed with status code: {response.status_code}")
print(f"Data parsed and stored from {url}.")
else:
print(f"Request to {url} failed with status code: {response.status_code}")
except Exception as e:
print(f"An error occurred while processing {url}: {e}")
# Schedule the next call to this function
Timer(60, parse_and_store_data).start() # Call this function every 60 seconds
Timer(30, parse_and_store_data).start() # Call this function every 30 seconds
def extract_dev_id(formatted_row):
@@ -346,5 +393,5 @@ def get_table_data():
if __name__ == '__main__':
Timer(60, parse_and_store_data).start()
Timer(30, parse_and_store_data).start()
socketio.run(app, debug=True)
+41 -42
View File
@@ -1,10 +1,35 @@
import requests
from bs4 import BeautifulSoup
# Define the URL and headers
url = "http://10.130.1.1/cgi-bin/log-traffic.has"
def get_gateway_data(url, headers):
"""
Makes a request to the specified gateway URL and parses the HTML table content.
Returns a list of formatted strings for each row in the table.
"""
formatted_rows = []
response = requests.get(url, headers=headers)
if response.status_code == 200:
soup = BeautifulSoup(response.text, 'html.parser')
table = soup.find('table')
if table:
rows = table.find_all('tr')
headers = [header.text.strip() for header in rows[0].find_all('th')][1:]
for row in rows[1:]:
cells = row.find_all('td')
cell_data = [cell.text.strip() for cell in cells[1:] if cells.index(cell) < len(headers) + 1]
formatted_row = ' | '.join(cell_data)
formatted_rows.append(formatted_row)
else:
print(f"Request to {url} failed with status code:", response.status_code)
return formatted_rows
# Define URLs and headers for both gateways
gateway_1 = "http://192.168.1.23/cgi-bin/log-traffic.has"
gateway_2 = "http://192.168.1.24/cgi-bin/log-traffic.has"
headers = {
"Host": "10.130.1.1",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:122.0) Gecko/20100101 Firefox/122.0",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.5",
@@ -13,46 +38,20 @@ headers = {
"Sec-GPC": "1",
"Authorization": "Basic cm9vdDpkcmFnaW5v",
"Connection": "keep-alive",
"Referer": "http://10.130.1.1/cgi-bin/log-lora.has",
"Upgrade-Insecure-Requests": "1"
}
# Send the GET request
response = requests.get(url, headers=headers)
# Fetch and print data from both gateways
print("Fetching data from Gateway 1 (192.168.1.23)...")
data_1 = get_gateway_data(gateway_1, headers)
for row in data_1:
print(row)
print("\nFetching data from Gateway 2 (192.168.1.24)...")
# Update the 'Host' header for the second gateway if necessary
headers["Host"] = "192.168.1.24"
data_2 = get_gateway_data(gateway_2, headers)
for row in data_2:
print(row)
if response.status_code == 200:
# Parse the HTML content using BeautifulSoup
soup = BeautifulSoup(response.text, 'html.parser')
# Find the table
table = soup.find('table')
# Initialize an empty list to store formatted strings for each row
formatted_rows = []
# Find all table rows
rows = table.find_all('tr')
# Get column headers from the first row
# Using .text.strip() to clean the text and [1:] to skip the empty first column
headers = [header.text.strip() for header in rows[0].find_all('th')][1:]
# Iterate through each row (skipping the first row with the headers)
for row in rows[1:]:
# Find all data cells (td tags) in the row
cells = row.find_all('td')
# Extract text from each cell
# Using [1:] to skip the first cell with the arrow icon
cell_data = [cell.text.strip() for cell in cells[1:] if cells.index(cell) < len(headers) + 1]
# Format the row data into a neat line
formatted_row = ' | '.join(cell_data)
# Append the formatted string to the list
formatted_rows.append(formatted_row)
# Print the formatted string to display the row
print(formatted_row)
else:
print("Request failed with status code:", response.status_code)
Binary file not shown.

After

Width:  |  Height:  |  Size: 775 KiB

File diff suppressed because it is too large Load Diff
+6
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2
View File
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+7 -8
View File
@@ -5,22 +5,21 @@
<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>
<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="https://use.fontawesome.com/releases/v6.3.0/js/all.js" crossorigin="anonymous"></script>
<script src="static/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">
<link rel="stylesheet" href="static/css/sweetalert2.css">
<!-- 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>
<script src="static/js/sweetalert2.js"></script>
<script src="static/js/jquery.min.js"></script>
</head>
<body id="page-top">
@@ -637,7 +636,7 @@
</div>
<!-- Bootstrap core JS-->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="static/js/bootstrap.bundle.min.js"></script>
<!-- Core theme JS-->
<script src="static/js/scripts.js"></script>
</body>
+75 -8
View File
@@ -5,21 +5,20 @@
<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>
<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="https://use.fontawesome.com/releases/v6.3.0/js/all.js" crossorigin="anonymous"></script>
<script src="static/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">
<link rel="stylesheet" href="static/css/sweetalert2.css">
<!-- Include SweetAlert2 JS -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@10"></script>
<script src="static/js/sweetalert2.js"></script>
</head>
@@ -33,7 +32,7 @@
<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="#about">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">Tracking Mode</a></li>
@@ -61,9 +60,77 @@
</p>
</div>
</section>
<!-- Add this form within the body where it fits best, possibly under the About section -->
<section class="resume-section">
<div class="resume-section-content">
<h2 class="mb-0" style="text-align: center;">LoRaWAN Gateway Configuration</h2><br>
<img src="static/assets/img/lorawan.webp" style="width:100%; "><br><br>
<div style="display: flex; justify-content: center; margin-top: 20px;"><button class="transmit-button" id="configureGatewayBtn">Configure Gateway</button></div>
</div>
</section>
</div>
<script>
document.getElementById('configureGatewayBtn').addEventListener('click', function() {
let gatewayIPs = {};
const ipPrompt = (title) => {
return Swal.fire({
title: title,
input: 'text',
inputPlaceholder: 'Leave empty to keep current IP',
inputValidator: (value) => {
if (value && !value.match(/^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/)) {
return 'Please enter a valid IP address or leave it empty';
}
}
});
};
ipPrompt('Enter Gateway 1 IP Address').then((result) => {
if (result.value) gatewayIPs.gateway1 = result.value;
ipPrompt('Enter Gateway 2 IP Address').then((result) => {
if (result.value) gatewayIPs.gateway2 = result.value;
ipPrompt('Enter Gateway 3 IP Address').then((result) => {
if (result.value) gatewayIPs.gateway3 = result.value;
// Now send the IPs to the server only if they are not undefined
let queryString = Object.keys(gatewayIPs).reduce((acc, key) => {
if (gatewayIPs[key] !== undefined) {
acc.push(`${key}=${encodeURIComponent(gatewayIPs[key])}`);
}
return acc;
}, []).join('&');
if (queryString) {
fetch('/set_gateways', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: queryString
})
.then(response => response.json())
.then(data => Swal.fire('Success', 'Gateway IPs updated successfully', 'success'))
.catch(error => Swal.fire('Error', 'There was an issue updating the Gateway IPs', 'error'));
} else {
Swal.fire('No Changes', 'No IP addresses were changed.', 'info');
}
});
});
});
});
</script>
<!-- Bootstrap core JS-->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="static/js/bootstrap.bundle.min.js"></script>
<!-- Core theme JS-->
<script src="static/js/scripts.js"></script>
</body>
+6 -7
View File
@@ -5,22 +5,21 @@
<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>
<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="https://use.fontawesome.com/releases/v6.3.0/js/all.js" crossorigin="anonymous"></script>
<script src="static/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">
<link rel="stylesheet" href="static/css/sweetalert2.css">
<!-- Include SweetAlert2 JS -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@10"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="static/js/sweetalert2.js"></script>
<script src="static/js/jquery.min.js"></script>
</head>
<body id="page-top">
+7 -8
View File
@@ -5,22 +5,21 @@
<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>
<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="https://use.fontawesome.com/releases/v6.3.0/js/all.js" crossorigin="anonymous"></script>
<script src="static/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">
<link rel="stylesheet" href="static/css/sweetalert2.css">
<!-- 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>
<script src="static/js/sweetalert2.js"></script>
<script src="static/js/jquery.min.js"></script>
</head>
<body id="page-top">
@@ -946,7 +945,7 @@
</div>
<!-- Bootstrap core JS-->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="static/js/bootstrap.bundle.min.js"></script>
<!-- Core theme JS-->
<script src="static/js/scripts.js"></script>
</body>