Admin UI working again

This commit is contained in:
Hemna 2024-04-05 15:02:26 -04:00
parent 333feee805
commit 0ca9072c97
9 changed files with 65 additions and 52 deletions

View File

@ -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()

View File

@ -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)

View File

@ -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

View File

@ -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):

View File

@ -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)

View File

@ -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"]);

View File

@ -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 ) {

View File

@ -30,7 +30,6 @@
var color = Chart.helpers.color;
$(document).ready(function() {
console.log(initial_stats);
start_update();
start_charts();
init_messages();

View File

@ -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