mirror of
https://git.ianrenton.com/ian/spothole.git
synced 2025-10-27 16:59:25 +00:00
Start of web interface
This commit is contained in:
@@ -38,6 +38,9 @@ Suggested names so far:
|
|||||||
* (s)pothole
|
* (s)pothole
|
||||||
* Spot on API
|
* Spot on API
|
||||||
* API on Spot
|
* API on Spot
|
||||||
|
* frankenspot
|
||||||
|
* spot(t)sammler
|
||||||
|
* On the Air
|
||||||
|
|
||||||
### TODO - Setup instructions - checkout, config.yml, pip
|
### TODO - Setup instructions - checkout, config.yml, pip
|
||||||
### TODO - systemd
|
### TODO - systemd
|
||||||
|
|||||||
19
main.py
19
main.py
@@ -33,6 +33,11 @@ if __name__ == '__main__':
|
|||||||
# Set up logging
|
# Set up logging
|
||||||
root = logging.getLogger()
|
root = logging.getLogger()
|
||||||
root.setLevel(logging.INFO)
|
root.setLevel(logging.INFO)
|
||||||
|
handler = logging.StreamHandler(sys.stdout)
|
||||||
|
handler.setLevel(logging.INFO)
|
||||||
|
formatter = logging.Formatter("%(message)s")
|
||||||
|
handler.setFormatter(formatter)
|
||||||
|
root.addHandler(handler)
|
||||||
logging.info("Starting...")
|
logging.info("Starting...")
|
||||||
|
|
||||||
# Shut down gracefully on SIGINT
|
# Shut down gracefully on SIGINT
|
||||||
@@ -40,13 +45,13 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
# Create providers
|
# Create providers
|
||||||
providers = [
|
providers = [
|
||||||
# POTA(),
|
POTA(),
|
||||||
# SOTA(),
|
SOTA(),
|
||||||
# WWFF(),
|
WWFF(),
|
||||||
# WWBOTA(),
|
WWBOTA(),
|
||||||
# GMA(),
|
GMA(),
|
||||||
# HEMA(),
|
HEMA(),
|
||||||
# ParksNPeaks(),
|
ParksNPeaks(),
|
||||||
DXCluster("hrd.wa9pie.net", 8000),
|
DXCluster("hrd.wa9pie.net", 8000),
|
||||||
# DXCluster("dxc.w3lpl.net", 22)
|
# DXCluster("dxc.w3lpl.net", 22)
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ class DXCluster(Provider):
|
|||||||
self.status = "Connecting"
|
self.status = "Connecting"
|
||||||
logging.info("DX Cluster " + self.hostname + " connecting...")
|
logging.info("DX Cluster " + self.hostname + " connecting...")
|
||||||
self.telnet = telnetlib3.Telnet(self.hostname, self.port)
|
self.telnet = telnetlib3.Telnet(self.hostname, self.port)
|
||||||
self.telnet.read_until("login: ".encode("utf-8"))
|
self.telnet.read_until("login: ".encode("latin-1"))
|
||||||
self.telnet.write((config["server-owner-callsign"] + "\n").encode("utf-8"))
|
self.telnet.write((config["server-owner-callsign"] + "\n").encode("latin-1"))
|
||||||
connected = True
|
connected = True
|
||||||
logging.info("DX Cluster " + self.hostname + " connected.")
|
logging.info("DX Cluster " + self.hostname + " connected.")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -62,8 +62,8 @@ class DXCluster(Provider):
|
|||||||
while connected and self.run:
|
while connected and self.run:
|
||||||
try:
|
try:
|
||||||
# Check new telnet info against regular expression
|
# Check new telnet info against regular expression
|
||||||
telnet_output = self.telnet.read_until("\n".encode("utf-8"))
|
telnet_output = self.telnet.read_until("\n".encode("latin-1"))
|
||||||
match = self.LINE_PATTERN.match(telnet_output.decode("utf-8"))
|
match = self.LINE_PATTERN.match(telnet_output.decode("latin-1"))
|
||||||
if match:
|
if match:
|
||||||
spot_time = datetime.strptime(match.group(5), "%H%MZ")
|
spot_time = datetime.strptime(match.group(5), "%H%MZ")
|
||||||
spot_datetime = datetime.combine(datetime.today(), spot_time.time()).replace(tzinfo=pytz.UTC)
|
spot_datetime = datetime.combine(datetime.today(), spot_time.time()).replace(tzinfo=pytz.UTC)
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ class WebServer:
|
|||||||
|
|
||||||
# Set up routing
|
# Set up routing
|
||||||
bottle.get("/api/spots")(self.serve_api_spots)
|
bottle.get("/api/spots")(self.serve_api_spots)
|
||||||
|
bottle.get("/")(self.serve_index)
|
||||||
|
bottle.get("/<filepath:path>")(self.serve_static_file)
|
||||||
|
|
||||||
# Start the web server
|
# Start the web server
|
||||||
def start(self):
|
def start(self):
|
||||||
@@ -36,8 +38,16 @@ class WebServer:
|
|||||||
response.content_type = 'application/json'
|
response.content_type = 'application/json'
|
||||||
return spots_json
|
return spots_json
|
||||||
|
|
||||||
|
# Serve the home page. This would be accessible as /index.html but we need this workaround to make it available as /
|
||||||
|
def serve_index(self):
|
||||||
|
return bottle.static_file("index.html", root="webassets")
|
||||||
|
|
||||||
# Todo spot API arguments e.g. "since" based on received_time of spots, sources, sigs, dx cont, dxcc, de cont, band, mode, filter out qrt, filter pre-qsy
|
# Serve general static files from "webassets" directory
|
||||||
|
def serve_static_file(self, filepath):
|
||||||
|
return bottle.static_file(filepath, root="webassets")
|
||||||
|
|
||||||
|
|
||||||
|
# Todo spot API arguments e.g. "since" based on received_time of spots, sources, sigs, dx cont, dxcc, de cont, band, mode, filter out qrt, filter pre-qsy, sort order, list of fields
|
||||||
# Todo serve status API
|
# Todo serve status API
|
||||||
# Todo serve apidocs
|
# Todo serve apidocs
|
||||||
# Todo serve website
|
# Todo serve website
|
||||||
|
|||||||
16
webassets/index.html
Normal file
16
webassets/index.html
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>Spot tool</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="css/style.css" type="text/css">
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/jquery-ui@1.13.2/dist/jquery-ui.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/moment@2.29.4/moment.min.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="table-container"></div>
|
||||||
|
<script src="js/code.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
13
webassets/js/code.js
Normal file
13
webassets/js/code.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
$.getJSON('/api/spots', function(jsonData) {
|
||||||
|
let headers = Object.keys(jsonData[0]);
|
||||||
|
let table = $('<table>').append('<thead><tr></tr></thead><tbody></tbody>');
|
||||||
|
headers.forEach(header => table.find('thead tr').append(`<th>${header}</th>`));
|
||||||
|
|
||||||
|
jsonData.forEach(row => {
|
||||||
|
let $tr = $('<tr>');
|
||||||
|
headers.forEach(header => $tr.append(`<td>${row[header]}</td>`));
|
||||||
|
table.find('tbody').append($tr);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#table-container').html(table);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user