mirror of
https://git.ianrenton.com/ian/spothole.git
synced 2025-10-27 08:49:27 +00:00
Start of web interface
This commit is contained in:
@@ -38,6 +38,9 @@ Suggested names so far:
|
||||
* (s)pothole
|
||||
* Spot on API
|
||||
* API on Spot
|
||||
* frankenspot
|
||||
* spot(t)sammler
|
||||
* On the Air
|
||||
|
||||
### TODO - Setup instructions - checkout, config.yml, pip
|
||||
### TODO - systemd
|
||||
|
||||
19
main.py
19
main.py
@@ -33,6 +33,11 @@ if __name__ == '__main__':
|
||||
# Set up logging
|
||||
root = logging.getLogger()
|
||||
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...")
|
||||
|
||||
# Shut down gracefully on SIGINT
|
||||
@@ -40,13 +45,13 @@ if __name__ == '__main__':
|
||||
|
||||
# Create providers
|
||||
providers = [
|
||||
# POTA(),
|
||||
# SOTA(),
|
||||
# WWFF(),
|
||||
# WWBOTA(),
|
||||
# GMA(),
|
||||
# HEMA(),
|
||||
# ParksNPeaks(),
|
||||
POTA(),
|
||||
SOTA(),
|
||||
WWFF(),
|
||||
WWBOTA(),
|
||||
GMA(),
|
||||
HEMA(),
|
||||
ParksNPeaks(),
|
||||
DXCluster("hrd.wa9pie.net", 8000),
|
||||
# DXCluster("dxc.w3lpl.net", 22)
|
||||
]
|
||||
|
||||
@@ -49,8 +49,8 @@ class DXCluster(Provider):
|
||||
self.status = "Connecting"
|
||||
logging.info("DX Cluster " + self.hostname + " connecting...")
|
||||
self.telnet = telnetlib3.Telnet(self.hostname, self.port)
|
||||
self.telnet.read_until("login: ".encode("utf-8"))
|
||||
self.telnet.write((config["server-owner-callsign"] + "\n").encode("utf-8"))
|
||||
self.telnet.read_until("login: ".encode("latin-1"))
|
||||
self.telnet.write((config["server-owner-callsign"] + "\n").encode("latin-1"))
|
||||
connected = True
|
||||
logging.info("DX Cluster " + self.hostname + " connected.")
|
||||
except Exception as e:
|
||||
@@ -62,8 +62,8 @@ class DXCluster(Provider):
|
||||
while connected and self.run:
|
||||
try:
|
||||
# Check new telnet info against regular expression
|
||||
telnet_output = self.telnet.read_until("\n".encode("utf-8"))
|
||||
match = self.LINE_PATTERN.match(telnet_output.decode("utf-8"))
|
||||
telnet_output = self.telnet.read_until("\n".encode("latin-1"))
|
||||
match = self.LINE_PATTERN.match(telnet_output.decode("latin-1"))
|
||||
if match:
|
||||
spot_time = datetime.strptime(match.group(5), "%H%MZ")
|
||||
spot_datetime = datetime.combine(datetime.today(), spot_time.time()).replace(tzinfo=pytz.UTC)
|
||||
|
||||
@@ -20,6 +20,8 @@ class WebServer:
|
||||
|
||||
# Set up routing
|
||||
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
|
||||
def start(self):
|
||||
@@ -36,8 +38,16 @@ class WebServer:
|
||||
response.content_type = 'application/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 apidocs
|
||||
# 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