diff --git a/aprsd/cmds/server.py b/aprsd/cmds/server.py
index 174e024..4edaff3 100644
--- a/aprsd/cmds/server.py
+++ b/aprsd/cmds/server.py
@@ -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()
diff --git a/aprsd/main.py b/aprsd/main.py
index cdb88dd..96d2249 100644
--- a/aprsd/main.py
+++ b/aprsd/main.py
@@ -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)
diff --git a/aprsd/packets/packet_list.py b/aprsd/packets/packet_list.py
index 11ec7fe..0813a49 100644
--- a/aprsd/packets/packet_list.py
+++ b/aprsd/packets/packet_list.py
@@ -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
diff --git a/aprsd/packets/seen_list.py b/aprsd/packets/seen_list.py
index 5c7774f..9b81831 100644
--- a/aprsd/packets/seen_list.py
+++ b/aprsd/packets/seen_list.py
@@ -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):
diff --git a/aprsd/utils/json.py b/aprsd/utils/json.py
index 29f6565..648238a 100644
--- a/aprsd/utils/json.py
+++ b/aprsd/utils/json.py
@@ -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)
diff --git a/aprsd/web/admin/static/js/echarts.js b/aprsd/web/admin/static/js/echarts.js
index 607d88b..8d67a73 100644
--- a/aprsd/web/admin/static/js/echarts.js
+++ b/aprsd/web/admin/static/js/echarts.js
@@ -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"]);
diff --git a/aprsd/web/admin/static/js/main.js b/aprsd/web/admin/static/js/main.js
index 0b6389f..99c956a 100644
--- a/aprsd/web/admin/static/js/main.js
+++ b/aprsd/web/admin/static/js/main.js
@@ -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 = '
HAM Callsign | Age since last seen by APRSD |
'
watchdiv.html('')
- jQuery.each(data["WatchList"], function(i, val) {
+ jQuery.each(stats["WatchList"], function(i, val) {
html_str += '' + i + ' | ' + val["last"] + ' |
'
});
html_str += "
";
@@ -60,12 +61,13 @@ function update_watchlist_from_packet(callsign, val) {
}
function update_seenlist( data ) {
+ stats = data["stats"];
var seendiv = $("#seenDiv");
var html_str = ''
html_str += 'HAM Callsign | Age since last seen by APRSD | '
html_str += 'Number of packets RX |
'
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 = ''
html_str += 'Plugin Name | Plugin Enabled? | '
@@ -87,7 +90,7 @@ function update_plugins( data ) {
html_str += '
'
plugindiv.html('')
- var plugins = data["PluginManager"];
+ var plugins = stats["PluginManager"];
var keys = Object.keys(plugins);
keys.sort();
for (var i=0; i 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 ) {
diff --git a/aprsd/web/admin/templates/index.html b/aprsd/web/admin/templates/index.html
index fe992c7..4fe1194 100644
--- a/aprsd/web/admin/templates/index.html
+++ b/aprsd/web/admin/templates/index.html
@@ -30,7 +30,6 @@
var color = Chart.helpers.color;
$(document).ready(function() {
- console.log(initial_stats);
start_update();
start_charts();
init_messages();
diff --git a/aprsd/wsgi.py b/aprsd/wsgi.py
index 8386e33..93eab5c 100644
--- a/aprsd/wsgi.py
+++ b/aprsd/wsgi.py
@@ -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: "
- "{}".format(stats["APRSClientStats"]["server_string"])
+ "{}".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