mirror of
https://github.com/craigerl/aprsd.git
synced 2024-10-31 15:07:13 -04:00
Admin UI working again
This commit is contained in:
parent
333feee805
commit
0ca9072c97
@ -96,12 +96,14 @@ def server(ctx, flush):
|
||||
packets.PacketTrack().flush()
|
||||
packets.WatchList().flush()
|
||||
packets.SeenList().flush()
|
||||
packets.PacketList().flush()
|
||||
else:
|
||||
# Try and load saved MsgTrack list
|
||||
LOG.debug("Loading saved MsgTrack object.")
|
||||
packets.PacketTrack().load()
|
||||
packets.WatchList().load()
|
||||
packets.SeenList().load()
|
||||
packets.PacketList().load()
|
||||
|
||||
keepalive = keep_alive.KeepAliveThread()
|
||||
keepalive.start()
|
||||
|
@ -96,6 +96,7 @@ def signal_handler(sig, frame):
|
||||
packets.PacketTrack().save()
|
||||
packets.WatchList().save()
|
||||
packets.SeenList().save()
|
||||
packets.PacketList().save()
|
||||
LOG.info(collector.Collector().collect())
|
||||
# signal.signal(signal.SIGTERM, sys.exit(0))
|
||||
# sys.exit(0)
|
||||
|
@ -7,24 +7,27 @@ from oslo_config import cfg
|
||||
import wrapt
|
||||
|
||||
from aprsd.packets import seen_list
|
||||
from aprsd.utils import objectstore
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
LOG = logging.getLogger("APRSD")
|
||||
|
||||
|
||||
class PacketList(MutableMapping):
|
||||
class PacketList(MutableMapping, objectstore.ObjectStoreMixin):
|
||||
_instance = None
|
||||
lock = threading.Lock()
|
||||
_total_rx: int = 0
|
||||
_total_tx: int = 0
|
||||
types = {}
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
if cls._instance is None:
|
||||
cls._instance = super().__new__(cls)
|
||||
cls._maxlen = 100
|
||||
cls.d = OrderedDict()
|
||||
cls.data = {
|
||||
"types": {},
|
||||
"packets": OrderedDict(),
|
||||
}
|
||||
return cls._instance
|
||||
|
||||
@wrapt.synchronized(lock)
|
||||
@ -33,9 +36,9 @@ class PacketList(MutableMapping):
|
||||
self._total_rx += 1
|
||||
self._add(packet)
|
||||
ptype = packet.__class__.__name__
|
||||
if not ptype in self.types:
|
||||
self.types[ptype] = {"tx": 0, "rx": 0}
|
||||
self.types[ptype]["rx"] += 1
|
||||
if not ptype in self.data["types"]:
|
||||
self.data["types"][ptype] = {"tx": 0, "rx": 0}
|
||||
self.data["types"][ptype]["rx"] += 1
|
||||
seen_list.SeenList().update_seen(packet)
|
||||
|
||||
@wrapt.synchronized(lock)
|
||||
@ -44,9 +47,9 @@ class PacketList(MutableMapping):
|
||||
self._total_tx += 1
|
||||
self._add(packet)
|
||||
ptype = packet.__class__.__name__
|
||||
if not ptype in self.types:
|
||||
self.types[ptype] = {"tx": 0, "rx": 0}
|
||||
self.types[ptype]["tx"] += 1
|
||||
if not ptype in self.data["types"]:
|
||||
self.data["types"][ptype] = {"tx": 0, "rx": 0}
|
||||
self.data["types"][ptype]["tx"] += 1
|
||||
seen_list.SeenList().update_seen(packet)
|
||||
|
||||
@wrapt.synchronized(lock)
|
||||
@ -54,7 +57,7 @@ class PacketList(MutableMapping):
|
||||
self._add(packet)
|
||||
|
||||
def _add(self, packet):
|
||||
self[packet.key] = packet
|
||||
self.data["packets"][packet.key] = packet
|
||||
|
||||
def copy(self):
|
||||
return self.d.copy()
|
||||
@ -69,23 +72,23 @@ class PacketList(MutableMapping):
|
||||
|
||||
def __getitem__(self, key):
|
||||
# self.d.move_to_end(key)
|
||||
return self.d[key]
|
||||
return self.data["packets"][key]
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
if key in self.d:
|
||||
self.d.move_to_end(key)
|
||||
elif len(self.d) == self.maxlen:
|
||||
self.d.popitem(last=False)
|
||||
self.d[key] = value
|
||||
if key in self.data["packets"]:
|
||||
self.data["packets"].move_to_end(key)
|
||||
elif len(self.data["packets"]) == self.maxlen:
|
||||
self.data["packets"].popitem(last=False)
|
||||
self.data["packets"][key] = value
|
||||
|
||||
def __delitem__(self, key):
|
||||
del self.d[key]
|
||||
del self.data["packets"][key]
|
||||
|
||||
def __iter__(self):
|
||||
return self.d.__iter__()
|
||||
return self.data["packets"].__iter__()
|
||||
|
||||
def __len__(self):
|
||||
return len(self.d)
|
||||
return len(self.data["packets"])
|
||||
|
||||
@wrapt.synchronized(lock)
|
||||
def total_rx(self):
|
||||
@ -100,7 +103,8 @@ class PacketList(MutableMapping):
|
||||
"total_tracked": self.total_tx() + self.total_rx(),
|
||||
"rx": self.total_rx(),
|
||||
"tx": self.total_tx(),
|
||||
"packets": self.types,
|
||||
"types": self.data["types"],
|
||||
"packets": self.data["packets"],
|
||||
}
|
||||
|
||||
return stats
|
||||
|
@ -28,11 +28,7 @@ class SeenList(objectstore.ObjectStoreMixin):
|
||||
|
||||
def stats(self, serializable=False):
|
||||
"""Return the stats for the PacketTrack class."""
|
||||
stats = self.data
|
||||
# if serializable:
|
||||
# for call in self.data:
|
||||
# stats[call]["last"] = stats[call]["last"].isoformat()
|
||||
return stats
|
||||
return self.data
|
||||
|
||||
@wrapt.synchronized(lock)
|
||||
def update_seen(self, packet):
|
||||
|
@ -3,6 +3,8 @@ import decimal
|
||||
import json
|
||||
import sys
|
||||
|
||||
from aprsd.packets import core
|
||||
|
||||
|
||||
class EnhancedJSONEncoder(json.JSONEncoder):
|
||||
def default(self, obj):
|
||||
@ -54,6 +56,8 @@ class SimpleJSONEncoder(json.JSONEncoder):
|
||||
return str(obj)
|
||||
elif isinstance(obj, decimal.Decimal):
|
||||
return str(obj)
|
||||
elif isinstance(obj, core.Packet):
|
||||
return obj.to_dict()
|
||||
else:
|
||||
return super().default(obj)
|
||||
|
||||
|
@ -327,7 +327,6 @@ function updatePacketTypesChart() {
|
||||
option = {
|
||||
series: series
|
||||
}
|
||||
console.log(option)
|
||||
packet_types_chart.setOption(option);
|
||||
}
|
||||
|
||||
@ -381,22 +380,23 @@ function updateAcksChart() {
|
||||
}
|
||||
|
||||
function update_stats( data ) {
|
||||
console.log(data);
|
||||
our_callsign = data["APRSDStats"]["callsign"];
|
||||
$("#version").text( data["APRSDStats"]["version"] );
|
||||
$("#aprs_connection").html( data["aprs_connection"] );
|
||||
$("#uptime").text( "uptime: " + data["APRSDStats"]["uptime"] );
|
||||
console.log("update_stats() echarts.js called")
|
||||
stats = data["stats"];
|
||||
our_callsign = stats["APRSDStats"]["callsign"];
|
||||
$("#version").text( stats["APRSDStats"]["version"] );
|
||||
$("#aprs_connection").html( stats["aprs_connection"] );
|
||||
$("#uptime").text( "uptime: " + stats["APRSDStats"]["uptime"] );
|
||||
const html_pretty = Prism.highlight(JSON.stringify(data, null, '\t'), Prism.languages.json, 'json');
|
||||
$("#jsonstats").html(html_pretty);
|
||||
|
||||
t = Date.parse(data["time"]);
|
||||
ts = new Date(t);
|
||||
updatePacketData(packets_chart, ts, data["PacketList"]["tx"], data["PacketList"]["rx"]);
|
||||
updatePacketTypesData(ts, data["PacketList"]["packets"]);
|
||||
updatePacketData(packets_chart, ts, stats["PacketList"]["tx"], stats["PacketList"]["rx"]);
|
||||
updatePacketTypesData(ts, stats["PacketList"]["types"]);
|
||||
updatePacketTypesChart();
|
||||
updateMessagesChart();
|
||||
updateAcksChart();
|
||||
updateMemChart(ts, data["APRSDStats"]["memory_current"], data["APRSDStats"]["memory_peak"]);
|
||||
updateMemChart(ts, stats["APRSDStats"]["memory_current"], stats["APRSDStats"]["memory_peak"]);
|
||||
//updateQuadData(message_chart, short_time, data["stats"]["messages"]["sent"], data["stats"]["messages"]["received"], data["stats"]["messages"]["ack_sent"], data["stats"]["messages"]["ack_recieved"]);
|
||||
//updateDualData(email_chart, short_time, data["stats"]["email"]["sent"], data["stats"]["email"]["recieved"]);
|
||||
//updateDualData(memory_chart, short_time, data["stats"]["aprsd"]["memory_peak"], data["stats"]["aprsd"]["memory_current"]);
|
||||
|
@ -24,11 +24,12 @@ function ord(str){return str.charCodeAt(0);}
|
||||
|
||||
|
||||
function update_watchlist( data ) {
|
||||
// Update the watch list
|
||||
// Update the watch list
|
||||
stats = data["stats"];
|
||||
var watchdiv = $("#watchDiv");
|
||||
var html_str = '<table class="ui celled striped table"><thead><tr><th>HAM Callsign</th><th>Age since last seen by APRSD</th></tr></thead><tbody>'
|
||||
watchdiv.html('')
|
||||
jQuery.each(data["WatchList"], function(i, val) {
|
||||
jQuery.each(stats["WatchList"], function(i, val) {
|
||||
html_str += '<tr><td class="collapsing"><img id="callsign_'+i+'" class="aprsd_1"></img>' + i + '</td><td>' + val["last"] + '</td></tr>'
|
||||
});
|
||||
html_str += "</tbody></table>";
|
||||
@ -60,12 +61,13 @@ function update_watchlist_from_packet(callsign, val) {
|
||||
}
|
||||
|
||||
function update_seenlist( data ) {
|
||||
stats = data["stats"];
|
||||
var seendiv = $("#seenDiv");
|
||||
var html_str = '<table class="ui celled striped table">'
|
||||
html_str += '<thead><tr><th>HAM Callsign</th><th>Age since last seen by APRSD</th>'
|
||||
html_str += '<th>Number of packets RX</th></tr></thead><tbody>'
|
||||
seendiv.html('')
|
||||
var seen_list = data["SeenList"]
|
||||
var seen_list = stats["SeenList"]
|
||||
var len = Object.keys(seen_list).length
|
||||
$('#seen_count').html(len)
|
||||
jQuery.each(seen_list, function(i, val) {
|
||||
@ -79,6 +81,7 @@ function update_seenlist( data ) {
|
||||
}
|
||||
|
||||
function update_plugins( data ) {
|
||||
stats = data["stats"];
|
||||
var plugindiv = $("#pluginDiv");
|
||||
var html_str = '<table class="ui celled striped table"><thead><tr>'
|
||||
html_str += '<th>Plugin Name</th><th>Plugin Enabled?</th>'
|
||||
@ -87,7 +90,7 @@ function update_plugins( data ) {
|
||||
html_str += '</tr></thead><tbody>'
|
||||
plugindiv.html('')
|
||||
|
||||
var plugins = data["PluginManager"];
|
||||
var plugins = stats["PluginManager"];
|
||||
var keys = Object.keys(plugins);
|
||||
keys.sort();
|
||||
for (var i=0; i<keys.length; i++) { // now lets iterate in sort order
|
||||
@ -107,8 +110,8 @@ function update_packets( data ) {
|
||||
if (size_dict(packet_list) == 0 && size_dict(data) > 0) {
|
||||
packetsdiv.html('')
|
||||
}
|
||||
jQuery.each(data, function(i, val) {
|
||||
pkt = JSON.parse(val);
|
||||
jQuery.each(data.packets, function(i, val) {
|
||||
pkt = val;
|
||||
|
||||
update_watchlist_from_packet(pkt['from_call'], pkt);
|
||||
if ( packet_list.hasOwnProperty(pkt['timestamp']) == false ) {
|
||||
|
@ -30,7 +30,6 @@
|
||||
var color = Chart.helpers.color;
|
||||
|
||||
$(document).ready(function() {
|
||||
console.log(initial_stats);
|
||||
start_update();
|
||||
start_charts();
|
||||
init_messages();
|
||||
|
@ -1,3 +1,4 @@
|
||||
import datetime
|
||||
import importlib.metadata as imp
|
||||
import io
|
||||
import json
|
||||
@ -48,10 +49,13 @@ def verify_password(username, password):
|
||||
def _stats():
|
||||
stats_obj = stats_threads.StatsStore()
|
||||
stats_obj.load()
|
||||
# now = datetime.datetime.now()
|
||||
# time_format = "%m-%d-%Y %H:%M:%S"
|
||||
stats_dict = stats_obj.data
|
||||
return stats_dict
|
||||
now = datetime.datetime.now()
|
||||
time_format = "%m-%d-%Y %H:%M:%S"
|
||||
stats = {
|
||||
"time": now.strftime(time_format),
|
||||
"stats": stats_obj.data,
|
||||
}
|
||||
return stats
|
||||
|
||||
|
||||
@app.route("/stats")
|
||||
@ -71,7 +75,7 @@ def index():
|
||||
transport = "aprs-is"
|
||||
aprs_connection = (
|
||||
"APRS-IS Server: <a href='http://status.aprs2.net' >"
|
||||
"{}</a>".format(stats["APRSClientStats"]["server_string"])
|
||||
"{}</a>".format(stats["stats"]["APRSClientStats"]["server_string"])
|
||||
)
|
||||
else:
|
||||
# We might be connected to a KISS socket?
|
||||
@ -92,8 +96,8 @@ def index():
|
||||
)
|
||||
)
|
||||
|
||||
stats["transport"] = transport
|
||||
stats["aprs_connection"] = aprs_connection
|
||||
stats["stats"]["APRSClientStats"]["transport"] = transport
|
||||
stats["stats"]["APRSClientStats"]["aprs_connection"] = aprs_connection
|
||||
entries = conf.conf_to_dict()
|
||||
|
||||
return flask.render_template(
|
||||
@ -113,7 +117,6 @@ def index():
|
||||
|
||||
@auth.login_required
|
||||
def messages():
|
||||
_stats()
|
||||
track = packets.PacketTrack()
|
||||
msgs = []
|
||||
for id in track:
|
||||
@ -126,9 +129,10 @@ def messages():
|
||||
@auth.login_required
|
||||
@app.route("/packets")
|
||||
def get_packets():
|
||||
LOG.debug("/packets called")
|
||||
stats_dict = _stats()
|
||||
return json.dumps(stats_dict.get("PacketList", {}))
|
||||
stats = _stats()
|
||||
stats_dict = stats["stats"]
|
||||
packets = stats_dict.get("PacketList", {})
|
||||
return json.dumps(packets, cls=aprsd_json.SimpleJSONEncoder)
|
||||
|
||||
|
||||
@auth.login_required
|
||||
|
Loading…
Reference in New Issue
Block a user