mirror of
https://github.com/craigerl/aprsd.git
synced 2024-12-22 01:20:59 -05:00
Allow stats collector to serialize upon creation
This does some cleanup with the stats collector and usage of the stats. The patch adds a new optional param to the collector's collect() method to tell the object to provide serializable stats. This is used for the webchat app that sends stats to the browser.
This commit is contained in:
parent
e2e58530b2
commit
71d72adf06
@ -28,7 +28,7 @@ factory = None
|
|||||||
|
|
||||||
@singleton
|
@singleton
|
||||||
class APRSClientStats:
|
class APRSClientStats:
|
||||||
def stats(self):
|
def stats(self, serializable=False):
|
||||||
client = factory.create()
|
client = factory.create()
|
||||||
stats = {
|
stats = {
|
||||||
"transport": client.transport(),
|
"transport": client.transport(),
|
||||||
@ -38,7 +38,10 @@ class APRSClientStats:
|
|||||||
|
|
||||||
if client.transport() == TRANSPORT_APRSIS:
|
if client.transport() == TRANSPORT_APRSIS:
|
||||||
stats["server_string"] = client.client.server_string
|
stats["server_string"] = client.client.server_string
|
||||||
stats["sever_keepalive"] = client.client.aprsd_keepalive
|
keepalive = client.client.aprsd_keepalive
|
||||||
|
if keepalive:
|
||||||
|
keepalive = keepalive.isoformat()
|
||||||
|
stats["sever_keepalive"] = keepalive
|
||||||
elif client.transport() == TRANSPORT_TCPKISS:
|
elif client.transport() == TRANSPORT_TCPKISS:
|
||||||
stats["host"] = CONF.kiss_tcp.host
|
stats["host"] = CONF.kiss_tcp.host
|
||||||
stats["port"] = CONF.kiss_tcp.port
|
stats["port"] = CONF.kiss_tcp.port
|
||||||
@ -96,7 +99,9 @@ class Client:
|
|||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
"""Call this to force a rebuild/reconnect."""
|
"""Call this to force a rebuild/reconnect."""
|
||||||
|
LOG.info("Resetting client connection.")
|
||||||
if self._client:
|
if self._client:
|
||||||
|
self._client.close()
|
||||||
del self._client
|
del self._client
|
||||||
self._create_client()
|
self._create_client()
|
||||||
else:
|
else:
|
||||||
@ -131,6 +136,10 @@ class Client:
|
|||||||
def is_alive(self):
|
def is_alive(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def close(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class APRSISClient(Client):
|
class APRSISClient(Client):
|
||||||
|
|
||||||
@ -195,6 +204,11 @@ class APRSISClient(Client):
|
|||||||
LOG.warning(f"APRS_CLIENT {self._client} alive? NO!!!")
|
LOG.warning(f"APRS_CLIENT {self._client} alive? NO!!!")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
if self._client:
|
||||||
|
self._client.stop()
|
||||||
|
self._client.close()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def transport():
|
def transport():
|
||||||
return TRANSPORT_APRSIS
|
return TRANSPORT_APRSIS
|
||||||
@ -239,11 +253,10 @@ class APRSISClient(Client):
|
|||||||
return aprs_client
|
return aprs_client
|
||||||
|
|
||||||
def consumer(self, callback, blocking=False, immortal=False, raw=False):
|
def consumer(self, callback, blocking=False, immortal=False, raw=False):
|
||||||
if self.is_alive():
|
self._client.consumer(
|
||||||
self._client.consumer(
|
callback, blocking=blocking,
|
||||||
callback, blocking=blocking,
|
immortal=immortal, raw=raw,
|
||||||
immortal=immortal, raw=raw,
|
)
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class KISSClient(Client):
|
class KISSClient(Client):
|
||||||
@ -296,6 +309,10 @@ class KISSClient(Client):
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
if self._client:
|
||||||
|
self._client.stop()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def transport():
|
def transport():
|
||||||
if CONF.kiss_serial.enabled:
|
if CONF.kiss_serial.enabled:
|
||||||
@ -350,6 +367,9 @@ class APRSDFakeClient(Client, metaclass=trace.TraceWrapperMetaclass):
|
|||||||
def is_alive(self):
|
def is_alive(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
pass
|
||||||
|
|
||||||
def setup_connection(self):
|
def setup_connection(self):
|
||||||
self.connected = True
|
self.connected = True
|
||||||
return fake.APRSDFakeClient()
|
return fake.APRSDFakeClient()
|
||||||
|
@ -63,7 +63,7 @@ def signal_handler(sig, frame):
|
|||||||
time.sleep(1.5)
|
time.sleep(1.5)
|
||||||
# packets.WatchList().save()
|
# packets.WatchList().save()
|
||||||
# packets.SeenList().save()
|
# packets.SeenList().save()
|
||||||
LOG.info(stats.APRSDStats())
|
LOG.info(stats.stats_collector.collect())
|
||||||
LOG.info("Telling flask to bail.")
|
LOG.info("Telling flask to bail.")
|
||||||
signal.signal(signal.SIGTERM, sys.exit(0))
|
signal.signal(signal.SIGTERM, sys.exit(0))
|
||||||
|
|
||||||
@ -378,7 +378,7 @@ def _get_transport(stats):
|
|||||||
transport = "aprs-is"
|
transport = "aprs-is"
|
||||||
aprs_connection = (
|
aprs_connection = (
|
||||||
"APRS-IS Server: <a href='http://status.aprs2.net' >"
|
"APRS-IS Server: <a href='http://status.aprs2.net' >"
|
||||||
"{}</a>".format(stats["stats"]["aprs-is"]["server"])
|
"{}</a>".format(stats["APRSClientStats"]["server_string"])
|
||||||
)
|
)
|
||||||
elif client.KISSClient.is_enabled():
|
elif client.KISSClient.is_enabled():
|
||||||
transport = client.KISSClient.transport()
|
transport = client.KISSClient.transport()
|
||||||
@ -414,12 +414,13 @@ def location(callsign):
|
|||||||
@flask_app.route("/")
|
@flask_app.route("/")
|
||||||
def index():
|
def index():
|
||||||
stats = _stats()
|
stats = _stats()
|
||||||
|
LOG.error(stats)
|
||||||
|
|
||||||
# For development
|
# For development
|
||||||
html_template = "index.html"
|
html_template = "index.html"
|
||||||
LOG.debug(f"Template {html_template}")
|
LOG.debug(f"Template {html_template}")
|
||||||
|
|
||||||
transport, aprs_connection = _get_transport(stats)
|
transport, aprs_connection = _get_transport(stats["stats"])
|
||||||
LOG.debug(f"transport {transport} aprs_connection {aprs_connection}")
|
LOG.debug(f"transport {transport} aprs_connection {aprs_connection}")
|
||||||
|
|
||||||
stats["transport"] = transport
|
stats["transport"] = transport
|
||||||
@ -454,18 +455,17 @@ def send_message_status():
|
|||||||
|
|
||||||
|
|
||||||
def _stats():
|
def _stats():
|
||||||
stats_obj = stats.APRSDStats()
|
|
||||||
now = datetime.datetime.now()
|
now = datetime.datetime.now()
|
||||||
|
|
||||||
time_format = "%m-%d-%Y %H:%M:%S"
|
time_format = "%m-%d-%Y %H:%M:%S"
|
||||||
stats_dict = stats_obj.stats()
|
stats_dict = stats.stats_collector.collect(serializable=True)
|
||||||
# Webchat doesnt need these
|
# Webchat doesnt need these
|
||||||
if "watch_list" in stats_dict["aprsd"]:
|
if "WatchList" in stats_dict:
|
||||||
del stats_dict["aprsd"]["watch_list"]
|
del stats_dict["WatchList"]
|
||||||
if "seen_list" in stats_dict["aprsd"]:
|
if "seen_list" in stats_dict:
|
||||||
del stats_dict["aprsd"]["seen_list"]
|
del stats_dict["seen_list"]
|
||||||
if "threads" in stats_dict["aprsd"]:
|
if "APRSDThreadList" in stats_dict:
|
||||||
del stats_dict["aprsd"]["threads"]
|
del stats_dict["APRSDThreadList"]
|
||||||
# del stats_dict["email"]
|
# del stats_dict["email"]
|
||||||
# del stats_dict["plugins"]
|
# del stats_dict["plugins"]
|
||||||
# del stats_dict["messages"]
|
# del stats_dict["messages"]
|
||||||
@ -544,7 +544,7 @@ class SendMessageNamespace(Namespace):
|
|||||||
LOG.debug(f"Long {long}")
|
LOG.debug(f"Long {long}")
|
||||||
|
|
||||||
tx.send(
|
tx.send(
|
||||||
packets.GPSPacket(
|
packets.BeaconPacket(
|
||||||
from_call=CONF.callsign,
|
from_call=CONF.callsign,
|
||||||
to_call="APDW16",
|
to_call="APDW16",
|
||||||
latitude=lat,
|
latitude=lat,
|
||||||
|
@ -218,6 +218,11 @@ class BulletinPacket(Packet):
|
|||||||
bid: Optional[str] = field(default="1")
|
bid: Optional[str] = field(default="1")
|
||||||
message_text: Optional[str] = field(default=None)
|
message_text: Optional[str] = field(default=None)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def key(self) -> str:
|
||||||
|
"""Build a key for finding this packet in a dict."""
|
||||||
|
return f"{self.from_call}:BLN{self.bid}"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def human_info(self) -> str:
|
def human_info(self) -> str:
|
||||||
return f"BLN{self.bid} {self.message_text}"
|
return f"BLN{self.bid} {self.message_text}"
|
||||||
@ -385,6 +390,14 @@ class BeaconPacket(GPSPacket):
|
|||||||
f"{self.payload}"
|
f"{self.payload}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def key(self) -> str:
|
||||||
|
"""Build a key for finding this packet in a dict."""
|
||||||
|
if self.raw_timestamp:
|
||||||
|
return f"{self.from_call}:{self.raw_timestamp}"
|
||||||
|
else:
|
||||||
|
return f"{self.from_call}:{self.human_info.replace(' ','')}"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def human_info(self) -> str:
|
def human_info(self) -> str:
|
||||||
h_str = []
|
h_str = []
|
||||||
@ -407,6 +420,11 @@ class MicEPacket(GPSPacket):
|
|||||||
# 0 to 360
|
# 0 to 360
|
||||||
course: int = 0
|
course: int = 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def key(self) -> str:
|
||||||
|
"""Build a key for finding this packet in a dict."""
|
||||||
|
return f"{self.from_call}:{self.human_info.replace(' ', '')}"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def human_info(self) -> str:
|
def human_info(self) -> str:
|
||||||
h_info = super().human_info
|
h_info = super().human_info
|
||||||
@ -428,6 +446,14 @@ class TelemetryPacket(GPSPacket):
|
|||||||
# 0 to 360
|
# 0 to 360
|
||||||
course: int = 0
|
course: int = 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def key(self) -> str:
|
||||||
|
"""Build a key for finding this packet in a dict."""
|
||||||
|
if self.raw_timestamp:
|
||||||
|
return f"{self.from_call}:{self.raw_timestamp}"
|
||||||
|
else:
|
||||||
|
return f"{self.from_call}:{self.human_info.replace(' ','')}"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def human_info(self) -> str:
|
def human_info(self) -> str:
|
||||||
h_info = super().human_info
|
h_info = super().human_info
|
||||||
@ -548,6 +574,14 @@ class WeatherPacket(GPSPacket, DataClassJsonMixin):
|
|||||||
raw = cls._translate(cls, kvs) # type: ignore
|
raw = cls._translate(cls, kvs) # type: ignore
|
||||||
return super().from_dict(raw)
|
return super().from_dict(raw)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def key(self) -> str:
|
||||||
|
"""Build a key for finding this packet in a dict."""
|
||||||
|
if self.raw_timestamp:
|
||||||
|
return f"{self.from_call}:{self.raw_timestamp}"
|
||||||
|
elif self.wx_raw_timestamp:
|
||||||
|
return f"{self.from_call}:{self.wx_raw_timestamp}"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def human_info(self) -> str:
|
def human_info(self) -> str:
|
||||||
h_str = []
|
h_str = []
|
||||||
@ -643,6 +677,11 @@ class ThirdPartyPacket(Packet, DataClassJsonMixin):
|
|||||||
obj.subpacket = factory(obj.subpacket) # type: ignore
|
obj.subpacket = factory(obj.subpacket) # type: ignore
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
@property
|
||||||
|
def key(self) -> str:
|
||||||
|
"""Build a key for finding this packet in a dict."""
|
||||||
|
return f"{self.from_call}:{self.subpacket.key}"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def human_info(self) -> str:
|
def human_info(self) -> str:
|
||||||
sub_info = self.subpacket.human_info
|
sub_info = self.subpacket.human_info
|
||||||
@ -772,8 +811,7 @@ def factory(raw_packet: dict[Any, Any]) -> type[Packet]:
|
|||||||
if "latitude" in raw:
|
if "latitude" in raw:
|
||||||
packet_class = GPSPacket
|
packet_class = GPSPacket
|
||||||
else:
|
else:
|
||||||
LOG.warning(f"Unknown packet type {packet_type}")
|
# LOG.warning(raw)
|
||||||
LOG.warning(raw)
|
|
||||||
packet_class = UnknownPacket
|
packet_class = UnknownPacket
|
||||||
|
|
||||||
raw.get("addresse", raw.get("to_call"))
|
raw.get("addresse", raw.get("to_call"))
|
||||||
|
@ -95,7 +95,7 @@ class PacketList(MutableMapping):
|
|||||||
def total_tx(self):
|
def total_tx(self):
|
||||||
return self._total_tx
|
return self._total_tx
|
||||||
|
|
||||||
def stats(self) -> dict:
|
def stats(self, serializable=False) -> dict:
|
||||||
stats = {
|
stats = {
|
||||||
"total_tracked": self.total_tx() + self.total_rx(),
|
"total_tracked": self.total_tx() + self.total_rx(),
|
||||||
"rx": self.total_rx(),
|
"rx": self.total_rx(),
|
||||||
|
@ -58,15 +58,17 @@ class PacketTrack(objectstore.ObjectStoreMixin):
|
|||||||
return self.data.values()
|
return self.data.values()
|
||||||
|
|
||||||
@wrapt.synchronized(lock)
|
@wrapt.synchronized(lock)
|
||||||
def stats(self):
|
def stats(self, serializable=False):
|
||||||
stats = {
|
stats = {
|
||||||
"total_tracked": self.total_tracked,
|
"total_tracked": self.total_tracked,
|
||||||
}
|
}
|
||||||
pkts = {}
|
pkts = {}
|
||||||
for key in self.data:
|
for key in self.data:
|
||||||
|
last_send_time = self.data[key].last_send_time
|
||||||
|
last_send_attempt = self.data[key]._last_send_attempt
|
||||||
pkts[key] = {
|
pkts[key] = {
|
||||||
"last_send_time": self.data[key].last_send_time,
|
"last_send_time": last_send_time,
|
||||||
"last_send_attempt": self.data[key]._last_send_attempt,
|
"last_send_attempt": last_send_attempt,
|
||||||
"retry_count": self.data[key].retry_count,
|
"retry_count": self.data[key].retry_count,
|
||||||
"message": self.data[key].raw,
|
"message": self.data[key].raw,
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ class WatchList(objectstore.ObjectStoreMixin):
|
|||||||
}
|
}
|
||||||
|
|
||||||
@wrapt.synchronized(lock)
|
@wrapt.synchronized(lock)
|
||||||
def stats(self) -> dict:
|
def stats(self, serializable=False) -> dict:
|
||||||
stats = {}
|
stats = {}
|
||||||
for callsign in self.data:
|
for callsign in self.data:
|
||||||
stats[callsign] = {
|
stats[callsign] = {
|
||||||
|
@ -344,7 +344,7 @@ class PluginManager:
|
|||||||
self._watchlist_pm = pluggy.PluginManager("aprsd")
|
self._watchlist_pm = pluggy.PluginManager("aprsd")
|
||||||
self._watchlist_pm.add_hookspecs(APRSDPluginSpec)
|
self._watchlist_pm.add_hookspecs(APRSDPluginSpec)
|
||||||
|
|
||||||
def stats(self) -> dict:
|
def stats(self, serializable=False) -> dict:
|
||||||
"""Collect and return stats for all plugins."""
|
"""Collect and return stats for all plugins."""
|
||||||
def full_name_with_qualname(obj):
|
def full_name_with_qualname(obj):
|
||||||
return "{}.{}".format(
|
return "{}.{}".format(
|
||||||
|
@ -68,12 +68,15 @@ class EmailStats:
|
|||||||
rx = 0
|
rx = 0
|
||||||
email_thread_last_time = None
|
email_thread_last_time = None
|
||||||
|
|
||||||
def stats(self):
|
def stats(self, serializable=False):
|
||||||
if CONF.email_plugin.enabled:
|
if CONF.email_plugin.enabled:
|
||||||
|
last_check_time = self.email_thread_last_time
|
||||||
|
if serializable and last_check_time:
|
||||||
|
last_check_time = last_check_time.isoformat()
|
||||||
stats = {
|
stats = {
|
||||||
"tx": self.tx,
|
"tx": self.tx,
|
||||||
"rx": self.rx,
|
"rx": self.rx,
|
||||||
"last_check_time": self.email_thread_last_time,
|
"last_check_time": last_check_time,
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
stats = {}
|
stats = {}
|
||||||
|
@ -30,11 +30,14 @@ class APRSDStats:
|
|||||||
def uptime(self):
|
def uptime(self):
|
||||||
return datetime.datetime.now() - self.start_time
|
return datetime.datetime.now() - self.start_time
|
||||||
|
|
||||||
def stats(self) -> dict:
|
def stats(self, serializable=False) -> dict:
|
||||||
current, peak = tracemalloc.get_traced_memory()
|
current, peak = tracemalloc.get_traced_memory()
|
||||||
|
uptime = self.uptime()
|
||||||
|
if serializable:
|
||||||
|
uptime = str(uptime)
|
||||||
stats = {
|
stats = {
|
||||||
"version": aprsd.__version__,
|
"version": aprsd.__version__,
|
||||||
"uptime": self.uptime(),
|
"uptime": uptime,
|
||||||
"callsign": CONF.callsign,
|
"callsign": CONF.callsign,
|
||||||
"memory_current": int(current),
|
"memory_current": int(current),
|
||||||
"memory_current_str": utils.human_size(current),
|
"memory_current_str": utils.human_size(current),
|
||||||
|
@ -5,7 +5,8 @@ from aprsd.utils import singleton
|
|||||||
|
|
||||||
class StatsProducer(Protocol):
|
class StatsProducer(Protocol):
|
||||||
"""The StatsProducer protocol is used to define the interface for collecting stats."""
|
"""The StatsProducer protocol is used to define the interface for collecting stats."""
|
||||||
def stats(self) -> dict:
|
def stats(self, serializeable=False) -> dict:
|
||||||
|
"""provide stats in a dictionary format."""
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
@ -15,11 +16,11 @@ class Collector:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.producers: dict[str, StatsProducer] = {}
|
self.producers: dict[str, StatsProducer] = {}
|
||||||
|
|
||||||
def collect(self):
|
def collect(self, serializable=False) -> dict:
|
||||||
stats = {}
|
stats = {}
|
||||||
for name, producer in self.producers.items():
|
for name, producer in self.producers.items():
|
||||||
# No need to put in empty stats
|
# No need to put in empty stats
|
||||||
tmp_stats = producer.stats()
|
tmp_stats = producer.stats(serializable=serializable)
|
||||||
if tmp_stats:
|
if tmp_stats:
|
||||||
stats[name] = tmp_stats
|
stats[name] = tmp_stats
|
||||||
return stats
|
return stats
|
||||||
|
@ -13,7 +13,7 @@ LOG = logging.getLogger("APRSD")
|
|||||||
class APRSDThread(threading.Thread, metaclass=abc.ABCMeta):
|
class APRSDThread(threading.Thread, metaclass=abc.ABCMeta):
|
||||||
"""Base class for all threads in APRSD."""
|
"""Base class for all threads in APRSD."""
|
||||||
|
|
||||||
loop_interval = 1
|
loop_count = 1
|
||||||
|
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
super().__init__(name=name)
|
super().__init__(name=name)
|
||||||
@ -49,7 +49,6 @@ class APRSDThread(threading.Thread, metaclass=abc.ABCMeta):
|
|||||||
while not self._should_quit():
|
while not self._should_quit():
|
||||||
self.loop_count += 1
|
self.loop_count += 1
|
||||||
can_loop = self.loop()
|
can_loop = self.loop()
|
||||||
self.loop_interval += 1
|
|
||||||
self._last_loop = datetime.datetime.now()
|
self._last_loop = datetime.datetime.now()
|
||||||
if not can_loop:
|
if not can_loop:
|
||||||
self.stop()
|
self.stop()
|
||||||
@ -72,9 +71,12 @@ class APRSDThreadList:
|
|||||||
cls.threads_list = []
|
cls.threads_list = []
|
||||||
return cls._instance
|
return cls._instance
|
||||||
|
|
||||||
def stats(self) -> dict:
|
def stats(self, serializable=False) -> dict:
|
||||||
stats = {}
|
stats = {}
|
||||||
for th in self.threads_list:
|
for th in self.threads_list:
|
||||||
|
age = th.loop_age()
|
||||||
|
if serializable:
|
||||||
|
age = str(age)
|
||||||
stats[th.__class__.__name__] = {
|
stats[th.__class__.__name__] = {
|
||||||
"name": th.name,
|
"name": th.name,
|
||||||
"alive": th.is_alive(),
|
"alive": th.is_alive(),
|
||||||
|
@ -116,5 +116,6 @@ class KeepAliveThread(APRSDThread):
|
|||||||
level, msg = utils._check_version()
|
level, msg = utils._check_version()
|
||||||
if level:
|
if level:
|
||||||
LOG.warning(msg)
|
LOG.warning(msg)
|
||||||
|
self.cntr += 1
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
return True
|
return True
|
||||||
|
@ -6,7 +6,7 @@ import time
|
|||||||
import aprslib
|
import aprslib
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
|
||||||
from aprsd import client, packets, plugin, stats
|
from aprsd import client, packets, plugin
|
||||||
from aprsd.packets import log as packet_log
|
from aprsd.packets import log as packet_log
|
||||||
from aprsd.threads import APRSDThread, tx
|
from aprsd.threads import APRSDThread, tx
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ class APRSDRXThread(APRSDThread):
|
|||||||
self._client.stop()
|
self._client.stop()
|
||||||
|
|
||||||
def loop(self):
|
def loop(self):
|
||||||
LOG.debug(f"RX_MSG-LOOP {self.loop_interval}")
|
LOG.debug(f"RX_MSG-LOOP {self.loop_count}")
|
||||||
if not self._client:
|
if not self._client:
|
||||||
self._client = client.factory.create()
|
self._client = client.factory.create()
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
@ -53,21 +53,21 @@ class APRSDRXThread(APRSDThread):
|
|||||||
aprslib.exceptions.ConnectionError,
|
aprslib.exceptions.ConnectionError,
|
||||||
):
|
):
|
||||||
LOG.error("Connection dropped, reconnecting")
|
LOG.error("Connection dropped, reconnecting")
|
||||||
time.sleep(5)
|
|
||||||
# Force the deletion of the client object connected to aprs
|
# Force the deletion of the client object connected to aprs
|
||||||
# This will cause a reconnect, next time client.get_client()
|
# This will cause a reconnect, next time client.get_client()
|
||||||
# is called
|
# is called
|
||||||
self._client.reset()
|
self._client.reset()
|
||||||
except Exception as ex:
|
time.sleep(5)
|
||||||
LOG.error("Something bad happened!!!")
|
except Exception:
|
||||||
LOG.exception(ex)
|
# LOG.exception(ex)
|
||||||
return False
|
LOG.error("Resetting connection and trying again.")
|
||||||
|
self._client.reset()
|
||||||
|
time.sleep(5)
|
||||||
# Continue to loop
|
# Continue to loop
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _process_packet(self, *args, **kwargs):
|
def _process_packet(self, *args, **kwargs):
|
||||||
"""Intermediate callback so we can update the keepalive time."""
|
"""Intermediate callback so we can update the keepalive time."""
|
||||||
stats.APRSDStats().set_aprsis_keepalive()
|
|
||||||
# Now call the 'real' packet processing for a RX'x packet
|
# Now call the 'real' packet processing for a RX'x packet
|
||||||
self.process_packet(*args, **kwargs)
|
self.process_packet(*args, **kwargs)
|
||||||
|
|
||||||
|
@ -77,7 +77,11 @@ def _send_direct(packet, aprs_client=None):
|
|||||||
|
|
||||||
packet.update_timestamp()
|
packet.update_timestamp()
|
||||||
packet_log.log(packet, tx=True)
|
packet_log.log(packet, tx=True)
|
||||||
cl.send(packet)
|
try:
|
||||||
|
cl.send(packet)
|
||||||
|
except Exception as e:
|
||||||
|
LOG.error(f"Failed to send packet: {packet}")
|
||||||
|
LOG.error(e)
|
||||||
|
|
||||||
|
|
||||||
class SendPacketThread(aprsd_threads.APRSDThread):
|
class SendPacketThread(aprsd_threads.APRSDThread):
|
||||||
@ -232,7 +236,15 @@ class BeaconSendThread(aprsd_threads.APRSDThread):
|
|||||||
comment="APRSD GPS Beacon",
|
comment="APRSD GPS Beacon",
|
||||||
symbol=CONF.beacon_symbol,
|
symbol=CONF.beacon_symbol,
|
||||||
)
|
)
|
||||||
send(pkt, direct=True)
|
try:
|
||||||
|
# Only send it once
|
||||||
|
pkt.retry_count = 1
|
||||||
|
send(pkt, direct=True)
|
||||||
|
except Exception as e:
|
||||||
|
LOG.error(f"Failed to send beacon: {e}")
|
||||||
|
client.factory.create().reset()
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
self._loop_cnt += 1
|
self._loop_cnt += 1
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
return True
|
return True
|
||||||
|
@ -19,9 +19,10 @@ function show_aprs_icon(item, symbol) {
|
|||||||
function ord(str){return str.charCodeAt(0);}
|
function ord(str){return str.charCodeAt(0);}
|
||||||
|
|
||||||
function update_stats( data ) {
|
function update_stats( data ) {
|
||||||
$("#version").text( data["stats"]["aprsd"]["version"] );
|
console.log(data);
|
||||||
|
$("#version").text( data["stats"]["APRSDStats"]["version"] );
|
||||||
$("#aprs_connection").html( data["aprs_connection"] );
|
$("#aprs_connection").html( data["aprs_connection"] );
|
||||||
$("#uptime").text( "uptime: " + data["stats"]["aprsd"]["uptime"] );
|
$("#uptime").text( "uptime: " + data["stats"]["APRSDStats"]["uptime"] );
|
||||||
short_time = data["time"].split(/\s(.+)/)[1];
|
short_time = data["time"].split(/\s(.+)/)[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user