2022-07-20 08:43:57 -04:00
|
|
|
import datetime
|
|
|
|
import json
|
|
|
|
import logging
|
|
|
|
from logging.handlers import RotatingFileHandler
|
|
|
|
import signal
|
|
|
|
import sys
|
|
|
|
import threading
|
|
|
|
import time
|
|
|
|
|
2022-11-24 11:27:58 -05:00
|
|
|
from aprslib import util as aprslib_util
|
2022-07-20 08:43:57 -04:00
|
|
|
import click
|
|
|
|
import flask
|
|
|
|
from flask import request
|
|
|
|
from flask.logging import default_handler
|
|
|
|
import flask_classful
|
|
|
|
from flask_httpauth import HTTPBasicAuth
|
|
|
|
from flask_socketio import Namespace, SocketIO
|
2022-12-07 13:40:08 -05:00
|
|
|
from user_agents import parse as ua_parse
|
2022-07-20 08:43:57 -04:00
|
|
|
from werkzeug.security import check_password_hash, generate_password_hash
|
|
|
|
import wrapt
|
|
|
|
|
|
|
|
import aprsd
|
|
|
|
from aprsd import cli_helper, client
|
|
|
|
from aprsd import config as aprsd_config
|
2022-12-15 17:23:54 -05:00
|
|
|
from aprsd import packets, stats, threads, utils
|
2022-07-20 08:43:57 -04:00
|
|
|
from aprsd.aprsd import cli
|
|
|
|
from aprsd.logging import rich as aprsd_logging
|
2022-12-21 16:26:36 -05:00
|
|
|
from aprsd.threads import rx, tx
|
2022-07-20 08:43:57 -04:00
|
|
|
from aprsd.utils import objectstore, trace
|
|
|
|
|
|
|
|
|
|
|
|
LOG = logging.getLogger("APRSD")
|
|
|
|
auth = HTTPBasicAuth()
|
|
|
|
users = None
|
|
|
|
|
|
|
|
|
2022-11-22 13:32:19 -05:00
|
|
|
def signal_handler(sig, frame):
|
|
|
|
|
|
|
|
click.echo("signal_handler: called")
|
|
|
|
LOG.info(
|
|
|
|
f"Ctrl+C, Sending all threads({len(threads.APRSDThreadList())}) exit! "
|
|
|
|
f"Can take up to 10 seconds {datetime.datetime.now()}",
|
|
|
|
)
|
|
|
|
threads.APRSDThreadList().stop_all()
|
|
|
|
if "subprocess" not in str(frame):
|
|
|
|
time.sleep(1.5)
|
|
|
|
# packets.WatchList().save()
|
|
|
|
# packets.SeenList().save()
|
|
|
|
LOG.info(stats.APRSDStats())
|
|
|
|
LOG.info("Telling flask to bail.")
|
|
|
|
signal.signal(signal.SIGTERM, sys.exit(0))
|
|
|
|
|
|
|
|
|
2022-07-20 08:43:57 -04:00
|
|
|
class SentMessages(objectstore.ObjectStoreMixin):
|
|
|
|
_instance = None
|
|
|
|
lock = threading.Lock()
|
|
|
|
|
|
|
|
data = {}
|
|
|
|
|
|
|
|
def __new__(cls, *args, **kwargs):
|
|
|
|
"""This magic turns this into a singleton."""
|
|
|
|
if cls._instance is None:
|
|
|
|
cls._instance = super().__new__(cls)
|
|
|
|
return cls._instance
|
|
|
|
|
2022-12-18 08:52:58 -05:00
|
|
|
def is_initialized(self):
|
|
|
|
return True
|
|
|
|
|
2022-07-20 08:43:57 -04:00
|
|
|
@wrapt.synchronized(lock)
|
|
|
|
def add(self, msg):
|
2022-12-15 17:23:54 -05:00
|
|
|
self.data[msg.msgNo] = self.create(msg.msgNo)
|
|
|
|
self.data[msg.msgNo]["from"] = msg.from_call
|
|
|
|
self.data[msg.msgNo]["to"] = msg.to_call
|
|
|
|
self.data[msg.msgNo]["message"] = msg.message_text.rstrip("\n")
|
|
|
|
self.data[msg.msgNo]["raw"] = msg.message_text.rstrip("\n")
|
2022-07-20 08:43:57 -04:00
|
|
|
|
|
|
|
def create(self, id):
|
|
|
|
return {
|
|
|
|
"id": id,
|
|
|
|
"ts": time.time(),
|
|
|
|
"ack": False,
|
|
|
|
"from": None,
|
|
|
|
"to": None,
|
|
|
|
"raw": None,
|
|
|
|
"message": None,
|
|
|
|
"status": None,
|
|
|
|
"last_update": None,
|
|
|
|
"reply": None,
|
|
|
|
}
|
|
|
|
|
|
|
|
@wrapt.synchronized(lock)
|
|
|
|
def __len__(self):
|
|
|
|
return len(self.data.keys())
|
|
|
|
|
|
|
|
@wrapt.synchronized(lock)
|
|
|
|
def get(self, id):
|
|
|
|
if id in self.data:
|
|
|
|
return self.data[id]
|
|
|
|
|
|
|
|
@wrapt.synchronized(lock)
|
|
|
|
def get_all(self):
|
|
|
|
return self.data
|
|
|
|
|
|
|
|
@wrapt.synchronized(lock)
|
|
|
|
def set_status(self, id, status):
|
2022-07-28 16:24:25 -04:00
|
|
|
if id in self.data:
|
|
|
|
self.data[id]["last_update"] = str(datetime.datetime.now())
|
|
|
|
self.data[id]["status"] = status
|
2022-07-20 08:43:57 -04:00
|
|
|
|
|
|
|
@wrapt.synchronized(lock)
|
|
|
|
def ack(self, id):
|
|
|
|
"""The message got an ack!"""
|
2022-07-28 16:24:25 -04:00
|
|
|
if id in self.data:
|
|
|
|
self.data[id]["last_update"] = str(datetime.datetime.now())
|
|
|
|
self.data[id]["ack"] = True
|
2022-07-20 08:43:57 -04:00
|
|
|
|
|
|
|
@wrapt.synchronized(lock)
|
|
|
|
def reply(self, id, packet):
|
|
|
|
"""We got a packet back from the sent message."""
|
2022-07-28 16:24:25 -04:00
|
|
|
if id in self.data:
|
|
|
|
self.data[id]["reply"] = packet
|
2022-07-20 08:43:57 -04:00
|
|
|
|
|
|
|
|
|
|
|
# HTTPBasicAuth doesn't work on a class method.
|
|
|
|
# This has to be out here. Rely on the APRSDFlask
|
|
|
|
# class to initialize the users from the config
|
|
|
|
@auth.verify_password
|
|
|
|
def verify_password(username, password):
|
|
|
|
global users
|
|
|
|
|
|
|
|
if username in users and check_password_hash(users.get(username), password):
|
|
|
|
return username
|
|
|
|
|
|
|
|
|
2022-12-02 16:26:48 -05:00
|
|
|
class WebChatProcessPacketThread(rx.APRSDProcessPacketThread):
|
|
|
|
"""Class that handles packets being sent to us."""
|
2022-12-19 10:28:22 -05:00
|
|
|
def __init__(self, config, packet_queue, socketio):
|
2022-07-20 08:43:57 -04:00
|
|
|
self.socketio = socketio
|
|
|
|
self.connected = False
|
2022-12-19 10:28:22 -05:00
|
|
|
super().__init__(config, packet_queue)
|
2022-07-20 08:43:57 -04:00
|
|
|
|
2022-12-14 22:03:21 -05:00
|
|
|
def process_ack_packet(self, packet: packets.AckPacket):
|
2022-12-02 16:26:48 -05:00
|
|
|
super().process_ack_packet(packet)
|
2022-07-20 08:43:57 -04:00
|
|
|
ack_num = packet.get("msgNo")
|
|
|
|
SentMessages().ack(int(ack_num))
|
|
|
|
self.socketio.emit(
|
|
|
|
"ack", SentMessages().get(int(ack_num)),
|
|
|
|
namespace="/sendmsg",
|
|
|
|
)
|
|
|
|
self.got_ack = True
|
|
|
|
|
2022-12-14 22:03:21 -05:00
|
|
|
def process_our_message_packet(self, packet: packets.MessagePacket):
|
2022-12-21 16:26:36 -05:00
|
|
|
LOG.info(f"process MessagePacket {repr(packet)}")
|
2022-12-02 16:26:48 -05:00
|
|
|
packet.get("addresse", None)
|
2022-12-14 22:03:21 -05:00
|
|
|
fromcall = packet.from_call
|
2022-12-02 16:26:48 -05:00
|
|
|
|
|
|
|
message = packet.get("message_text", None)
|
|
|
|
msg = {
|
|
|
|
"id": 0,
|
2022-12-14 22:03:21 -05:00
|
|
|
"ts": packet.get("timestamp", time.time()),
|
2022-12-02 16:26:48 -05:00
|
|
|
"ack": False,
|
|
|
|
"from": fromcall,
|
2022-12-14 22:03:21 -05:00
|
|
|
"to": packet.to_call,
|
|
|
|
"raw": packet.raw,
|
2022-12-02 16:26:48 -05:00
|
|
|
"message": message,
|
|
|
|
"status": None,
|
|
|
|
"last_update": None,
|
|
|
|
"reply": None,
|
|
|
|
}
|
|
|
|
self.socketio.emit(
|
|
|
|
"new", msg,
|
|
|
|
namespace="/sendmsg",
|
|
|
|
)
|
2022-07-20 08:43:57 -04:00
|
|
|
|
|
|
|
|
|
|
|
class WebChatFlask(flask_classful.FlaskView):
|
|
|
|
config = None
|
|
|
|
|
|
|
|
def set_config(self, config):
|
|
|
|
global users
|
|
|
|
self.config = config
|
|
|
|
self.users = {}
|
|
|
|
for user in self.config["aprsd"]["web"]["users"]:
|
|
|
|
self.users[user] = generate_password_hash(
|
|
|
|
self.config["aprsd"]["web"]["users"][user],
|
|
|
|
)
|
|
|
|
|
|
|
|
users = self.users
|
|
|
|
|
2022-11-30 14:07:16 -05:00
|
|
|
def _get_transport(self, stats):
|
2022-07-20 08:43:57 -04:00
|
|
|
if self.config["aprs"].get("enabled", True):
|
|
|
|
transport = "aprs-is"
|
|
|
|
aprs_connection = (
|
|
|
|
"APRS-IS Server: <a href='http://status.aprs2.net' >"
|
|
|
|
"{}</a>".format(stats["stats"]["aprs-is"]["server"])
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
# We might be connected to a KISS socket?
|
2022-07-28 16:24:25 -04:00
|
|
|
if client.KISSClient.is_enabled(self.config):
|
2022-07-20 08:43:57 -04:00
|
|
|
transport = client.KISSClient.transport(self.config)
|
|
|
|
if transport == client.TRANSPORT_TCPKISS:
|
|
|
|
aprs_connection = (
|
|
|
|
"TCPKISS://{}:{}".format(
|
|
|
|
self.config["kiss"]["tcp"]["host"],
|
|
|
|
self.config["kiss"]["tcp"]["port"],
|
|
|
|
)
|
|
|
|
)
|
|
|
|
elif transport == client.TRANSPORT_SERIALKISS:
|
2022-12-07 13:40:08 -05:00
|
|
|
# for pep8 violation
|
|
|
|
kiss_default = aprsd_config.DEFAULT_DATE_FORMAT["kiss"]
|
|
|
|
default_baudrate = kiss_default["serial"]["baudrate"]
|
2022-07-20 08:43:57 -04:00
|
|
|
aprs_connection = (
|
|
|
|
"SerialKISS://{}@{} baud".format(
|
|
|
|
self.config["kiss"]["serial"]["device"],
|
2022-12-07 13:40:08 -05:00
|
|
|
self.config["kiss"]["serial"].get(
|
|
|
|
"baudrate",
|
|
|
|
default_baudrate,
|
|
|
|
),
|
2022-07-20 08:43:57 -04:00
|
|
|
)
|
|
|
|
)
|
|
|
|
|
2022-11-30 14:07:16 -05:00
|
|
|
return transport, aprs_connection
|
|
|
|
|
|
|
|
@auth.login_required
|
|
|
|
def index(self):
|
2022-12-07 13:40:08 -05:00
|
|
|
ua_str = request.headers.get("User-Agent")
|
|
|
|
# this takes about 2 seconds :(
|
|
|
|
user_agent = ua_parse(ua_str)
|
|
|
|
LOG.debug(f"Is mobile? {user_agent.is_mobile}")
|
2022-11-30 14:07:16 -05:00
|
|
|
stats = self._stats()
|
|
|
|
|
2022-12-07 13:40:08 -05:00
|
|
|
if user_agent.is_mobile:
|
2022-11-30 14:07:16 -05:00
|
|
|
html_template = "mobile.html"
|
|
|
|
else:
|
|
|
|
html_template = "index.html"
|
|
|
|
|
|
|
|
# For development
|
2022-12-02 14:20:52 -05:00
|
|
|
# html_template = "mobile.html"
|
2022-11-30 14:07:16 -05:00
|
|
|
|
|
|
|
LOG.debug(f"Template {html_template}")
|
|
|
|
|
|
|
|
transport, aprs_connection = self._get_transport(stats)
|
|
|
|
LOG.debug(f"transport {transport} aprs_connection {aprs_connection}")
|
|
|
|
|
2022-07-20 08:43:57 -04:00
|
|
|
stats["transport"] = transport
|
|
|
|
stats["aprs_connection"] = aprs_connection
|
|
|
|
LOG.debug(f"initial stats = {stats}")
|
|
|
|
|
|
|
|
return flask.render_template(
|
2022-11-30 14:07:16 -05:00
|
|
|
html_template,
|
2022-07-20 08:43:57 -04:00
|
|
|
initial_stats=stats,
|
|
|
|
aprs_connection=aprs_connection,
|
2022-07-28 16:24:25 -04:00
|
|
|
callsign=self.config["aprsd"]["callsign"],
|
2022-07-20 08:43:57 -04:00
|
|
|
version=aprsd.__version__,
|
|
|
|
)
|
|
|
|
|
|
|
|
@auth.login_required
|
|
|
|
def send_message_status(self):
|
|
|
|
LOG.debug(request)
|
|
|
|
msgs = SentMessages()
|
|
|
|
info = msgs.get_all()
|
|
|
|
return json.dumps(info)
|
|
|
|
|
|
|
|
def _stats(self):
|
|
|
|
stats_obj = stats.APRSDStats()
|
|
|
|
now = datetime.datetime.now()
|
|
|
|
|
|
|
|
time_format = "%m-%d-%Y %H:%M:%S"
|
|
|
|
stats_dict = stats_obj.stats()
|
|
|
|
# Webchat doesnt need these
|
|
|
|
del stats_dict["aprsd"]["watch_list"]
|
|
|
|
del stats_dict["aprsd"]["seen_list"]
|
|
|
|
# del stats_dict["email"]
|
|
|
|
# del stats_dict["plugins"]
|
|
|
|
# del stats_dict["messages"]
|
|
|
|
|
|
|
|
result = {
|
|
|
|
"time": now.strftime(time_format),
|
|
|
|
"stats": stats_dict,
|
|
|
|
}
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
def stats(self):
|
|
|
|
return json.dumps(self._stats())
|
|
|
|
|
|
|
|
|
|
|
|
class SendMessageNamespace(Namespace):
|
|
|
|
"""Class to handle the socketio interactions."""
|
|
|
|
_config = None
|
|
|
|
got_ack = False
|
|
|
|
reply_sent = False
|
|
|
|
msg = None
|
|
|
|
request = None
|
|
|
|
|
2022-12-02 16:26:48 -05:00
|
|
|
def __init__(self, namespace=None, config=None):
|
2022-07-20 08:43:57 -04:00
|
|
|
self._config = config
|
|
|
|
super().__init__(namespace)
|
|
|
|
|
|
|
|
def on_connect(self):
|
|
|
|
global socketio
|
|
|
|
LOG.debug("Web socket connected")
|
|
|
|
socketio.emit(
|
|
|
|
"connected", {"data": "/sendmsg Connected"},
|
|
|
|
namespace="/sendmsg",
|
|
|
|
)
|
|
|
|
|
|
|
|
def on_disconnect(self):
|
|
|
|
LOG.debug("WS Disconnected")
|
|
|
|
|
|
|
|
def on_send(self, data):
|
|
|
|
global socketio
|
|
|
|
LOG.debug(f"WS: on_send {data}")
|
|
|
|
self.request = data
|
|
|
|
data["from"] = self._config["aprs"]["login"]
|
2022-12-15 17:23:54 -05:00
|
|
|
pkt = packets.MessagePacket(
|
|
|
|
from_call=data["from"],
|
|
|
|
to_call=data["to"].upper(),
|
|
|
|
message_text=data["message"],
|
2022-07-20 08:43:57 -04:00
|
|
|
)
|
2022-12-15 17:23:54 -05:00
|
|
|
self.msg = pkt
|
2022-07-20 08:43:57 -04:00
|
|
|
msgs = SentMessages()
|
2022-12-15 17:23:54 -05:00
|
|
|
msgs.add(pkt)
|
2022-12-21 16:26:36 -05:00
|
|
|
tx.send(pkt)
|
2022-12-15 17:23:54 -05:00
|
|
|
msgs.set_status(pkt.msgNo, "Sending")
|
|
|
|
obj = msgs.get(pkt.msgNo)
|
2022-07-20 08:43:57 -04:00
|
|
|
socketio.emit(
|
2022-11-22 13:32:19 -05:00
|
|
|
"sent", obj,
|
2022-07-20 08:43:57 -04:00
|
|
|
namespace="/sendmsg",
|
|
|
|
)
|
|
|
|
|
2022-11-24 11:27:58 -05:00
|
|
|
def on_gps(self, data):
|
|
|
|
LOG.debug(f"WS on_GPS: {data}")
|
|
|
|
lat = aprslib_util.latitude_to_ddm(data["latitude"])
|
|
|
|
long = aprslib_util.longitude_to_ddm(data["longitude"])
|
|
|
|
LOG.debug(f"Lat DDM {lat}")
|
|
|
|
LOG.debug(f"Long DDM {long}")
|
|
|
|
|
2022-12-21 16:26:36 -05:00
|
|
|
tx.send(
|
|
|
|
packets.GPSPacket(
|
|
|
|
from_call=self._config["aprs"]["login"],
|
|
|
|
to_call="APDW16",
|
|
|
|
latitude=lat,
|
|
|
|
longitude=long,
|
|
|
|
comment="APRSD WebChat Beacon",
|
|
|
|
),
|
|
|
|
direct=True,
|
2022-12-15 17:23:54 -05:00
|
|
|
)
|
2022-11-24 11:27:58 -05:00
|
|
|
|
2022-07-20 08:43:57 -04:00
|
|
|
def handle_message(self, data):
|
|
|
|
LOG.debug(f"WS Data {data}")
|
|
|
|
|
|
|
|
def handle_json(self, data):
|
|
|
|
LOG.debug(f"WS json {data}")
|
|
|
|
|
|
|
|
|
|
|
|
def setup_logging(config, flask_app, loglevel, quiet):
|
|
|
|
flask_log = logging.getLogger("werkzeug")
|
|
|
|
flask_app.logger.removeHandler(default_handler)
|
|
|
|
flask_log.removeHandler(default_handler)
|
|
|
|
|
|
|
|
log_level = aprsd_config.LOG_LEVELS[loglevel]
|
|
|
|
flask_log.setLevel(log_level)
|
|
|
|
date_format = config["aprsd"].get(
|
|
|
|
"dateformat",
|
|
|
|
aprsd_config.DEFAULT_DATE_FORMAT,
|
|
|
|
)
|
|
|
|
|
|
|
|
if not config["aprsd"]["web"].get("logging_enabled", False):
|
|
|
|
# disable web logging
|
|
|
|
flask_log.disabled = True
|
|
|
|
flask_app.logger.disabled = True
|
|
|
|
# return
|
|
|
|
|
|
|
|
if config["aprsd"].get("rich_logging", False) and not quiet:
|
|
|
|
log_format = "%(message)s"
|
|
|
|
log_formatter = logging.Formatter(fmt=log_format, datefmt=date_format)
|
|
|
|
rh = aprsd_logging.APRSDRichHandler(
|
|
|
|
show_thread=True, thread_width=15,
|
|
|
|
rich_tracebacks=True, omit_repeated_times=False,
|
|
|
|
)
|
|
|
|
rh.setFormatter(log_formatter)
|
|
|
|
flask_log.addHandler(rh)
|
|
|
|
|
|
|
|
log_file = config["aprsd"].get("logfile", None)
|
|
|
|
|
|
|
|
if log_file:
|
|
|
|
log_format = config["aprsd"].get(
|
|
|
|
"logformat",
|
|
|
|
aprsd_config.DEFAULT_LOG_FORMAT,
|
|
|
|
)
|
|
|
|
log_formatter = logging.Formatter(fmt=log_format, datefmt=date_format)
|
|
|
|
fh = RotatingFileHandler(
|
|
|
|
log_file, maxBytes=(10248576 * 5),
|
|
|
|
backupCount=4,
|
|
|
|
)
|
|
|
|
fh.setFormatter(log_formatter)
|
|
|
|
flask_log.addHandler(fh)
|
|
|
|
|
|
|
|
|
|
|
|
@trace.trace
|
|
|
|
def init_flask(config, loglevel, quiet):
|
|
|
|
global socketio
|
|
|
|
|
|
|
|
flask_app = flask.Flask(
|
|
|
|
"aprsd",
|
|
|
|
static_url_path="/static",
|
|
|
|
static_folder="web/chat/static",
|
|
|
|
template_folder="web/chat/templates",
|
|
|
|
)
|
|
|
|
setup_logging(config, flask_app, loglevel, quiet)
|
|
|
|
server = WebChatFlask()
|
|
|
|
server.set_config(config)
|
|
|
|
flask_app.route("/", methods=["GET"])(server.index)
|
|
|
|
flask_app.route("/stats", methods=["GET"])(server.stats)
|
|
|
|
# flask_app.route("/send-message", methods=["GET"])(server.send_message)
|
|
|
|
flask_app.route("/send-message-status", methods=["GET"])(server.send_message_status)
|
|
|
|
|
|
|
|
socketio = SocketIO(
|
|
|
|
flask_app, logger=False, engineio_logger=False,
|
|
|
|
async_mode="threading",
|
|
|
|
)
|
|
|
|
# async_mode="gevent",
|
|
|
|
# async_mode="eventlet",
|
|
|
|
# import eventlet
|
|
|
|
# eventlet.monkey_patch()
|
|
|
|
|
|
|
|
socketio.on_namespace(
|
|
|
|
SendMessageNamespace(
|
|
|
|
"/sendmsg", config=config,
|
|
|
|
),
|
|
|
|
)
|
|
|
|
return socketio, flask_app
|
|
|
|
|
|
|
|
|
|
|
|
# main() ###
|
|
|
|
@cli.command()
|
|
|
|
@cli_helper.add_options(cli_helper.common_options)
|
|
|
|
@click.option(
|
|
|
|
"-f",
|
|
|
|
"--flush",
|
|
|
|
"flush",
|
|
|
|
is_flag=True,
|
|
|
|
show_default=True,
|
|
|
|
default=False,
|
|
|
|
help="Flush out all old aged messages on disk.",
|
|
|
|
)
|
|
|
|
@click.option(
|
|
|
|
"-p",
|
|
|
|
"--port",
|
|
|
|
"port",
|
|
|
|
show_default=True,
|
|
|
|
default=80,
|
|
|
|
help="Port to listen to web requests",
|
|
|
|
)
|
|
|
|
@click.pass_context
|
|
|
|
@cli_helper.process_standard_options
|
|
|
|
def webchat(ctx, flush, port):
|
|
|
|
"""Web based HAM Radio chat program!"""
|
|
|
|
ctx.obj["config_file"]
|
|
|
|
loglevel = ctx.obj["loglevel"]
|
|
|
|
quiet = ctx.obj["quiet"]
|
|
|
|
config = ctx.obj["config"]
|
|
|
|
|
2022-11-22 13:32:19 -05:00
|
|
|
signal.signal(signal.SIGINT, signal_handler)
|
|
|
|
signal.signal(signal.SIGTERM, signal_handler)
|
2022-07-20 08:43:57 -04:00
|
|
|
|
|
|
|
if not quiet:
|
|
|
|
click.echo("Load config")
|
|
|
|
|
|
|
|
level, msg = utils._check_version()
|
|
|
|
if level:
|
|
|
|
LOG.warning(msg)
|
|
|
|
else:
|
|
|
|
LOG.info(msg)
|
|
|
|
LOG.info(f"APRSD Started version: {aprsd.__version__}")
|
|
|
|
|
|
|
|
flat_config = utils.flatten_dict(config)
|
|
|
|
LOG.info("Using CONFIG values:")
|
|
|
|
for x in flat_config:
|
|
|
|
if "password" in x or "aprsd.web.users.admin" in x:
|
|
|
|
LOG.info(f"{x} = XXXXXXXXXXXXXXXXXXX")
|
|
|
|
else:
|
|
|
|
LOG.info(f"{x} = {flat_config[x]}")
|
|
|
|
|
|
|
|
stats.APRSDStats(config)
|
|
|
|
|
|
|
|
# Initialize the client factory and create
|
|
|
|
# The correct client object ready for use
|
|
|
|
client.ClientFactory.setup(config)
|
|
|
|
# Make sure we have 1 client transport enabled
|
|
|
|
if not client.factory.is_client_enabled():
|
|
|
|
LOG.error("No Clients are enabled in config.")
|
|
|
|
sys.exit(-1)
|
|
|
|
|
|
|
|
if not client.factory.is_client_configured():
|
|
|
|
LOG.error("APRS client is not properly configured in config file.")
|
|
|
|
sys.exit(-1)
|
|
|
|
|
|
|
|
packets.PacketList(config=config)
|
2022-12-15 17:23:54 -05:00
|
|
|
packets.PacketTrack(config=config)
|
2022-07-20 08:43:57 -04:00
|
|
|
packets.WatchList(config=config)
|
|
|
|
packets.SeenList(config=config)
|
|
|
|
|
|
|
|
(socketio, app) = init_flask(config, loglevel, quiet)
|
2022-12-19 10:28:22 -05:00
|
|
|
rx_thread = rx.APRSDPluginRXThread(
|
2022-07-20 08:43:57 -04:00
|
|
|
config=config,
|
2022-12-19 10:28:22 -05:00
|
|
|
packet_queue=threads.packet_queue,
|
2022-07-20 08:43:57 -04:00
|
|
|
)
|
|
|
|
rx_thread.start()
|
2022-12-19 10:28:22 -05:00
|
|
|
process_thread = WebChatProcessPacketThread(
|
|
|
|
config=config,
|
|
|
|
packet_queue=threads.packet_queue,
|
|
|
|
socketio=socketio,
|
|
|
|
)
|
|
|
|
process_thread.start()
|
2022-07-20 08:43:57 -04:00
|
|
|
|
|
|
|
keepalive = threads.KeepAliveThread(config=config)
|
2022-11-22 13:32:19 -05:00
|
|
|
LOG.info("Start KeepAliveThread")
|
2022-07-20 08:43:57 -04:00
|
|
|
keepalive.start()
|
2022-11-22 13:32:19 -05:00
|
|
|
LOG.info("Start socketio.run()")
|
2022-07-20 08:43:57 -04:00
|
|
|
socketio.run(
|
|
|
|
app,
|
2022-12-07 13:40:08 -05:00
|
|
|
ssl_context="adhoc",
|
2022-07-20 08:43:57 -04:00
|
|
|
host=config["aprsd"]["web"]["host"],
|
|
|
|
port=port,
|
|
|
|
)
|
2022-11-22 13:32:19 -05:00
|
|
|
|
|
|
|
LOG.info("WebChat exiting!!!! Bye.")
|