aprsd 1.0.0__py3-none-any.whl → 3.4.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aprsd/__init__.py +6 -4
- aprsd/cli_helper.py +151 -0
- aprsd/client/__init__.py +13 -0
- aprsd/client/aprsis.py +132 -0
- aprsd/client/base.py +105 -0
- aprsd/client/drivers/__init__.py +0 -0
- aprsd/client/drivers/aprsis.py +228 -0
- aprsd/client/drivers/fake.py +73 -0
- aprsd/client/drivers/kiss.py +119 -0
- aprsd/client/factory.py +88 -0
- aprsd/client/fake.py +48 -0
- aprsd/client/kiss.py +103 -0
- aprsd/client/stats.py +38 -0
- aprsd/cmds/__init__.py +0 -0
- aprsd/cmds/completion.py +22 -0
- aprsd/cmds/dev.py +162 -0
- aprsd/cmds/fetch_stats.py +156 -0
- aprsd/cmds/healthcheck.py +86 -0
- aprsd/cmds/list_plugins.py +319 -0
- aprsd/cmds/listen.py +231 -0
- aprsd/cmds/send_message.py +171 -0
- aprsd/cmds/server.py +137 -0
- aprsd/cmds/webchat.py +674 -0
- aprsd/conf/__init__.py +56 -0
- aprsd/conf/client.py +131 -0
- aprsd/conf/common.py +301 -0
- aprsd/conf/log.py +65 -0
- aprsd/conf/opts.py +80 -0
- aprsd/conf/plugin_common.py +182 -0
- aprsd/conf/plugin_email.py +105 -0
- aprsd/exception.py +13 -0
- aprsd/log/__init__.py +0 -0
- aprsd/log/log.py +138 -0
- aprsd/main.py +104 -867
- aprsd/packets/__init__.py +20 -0
- aprsd/packets/collector.py +79 -0
- aprsd/packets/core.py +823 -0
- aprsd/packets/log.py +161 -0
- aprsd/packets/packet_list.py +110 -0
- aprsd/packets/seen_list.py +49 -0
- aprsd/packets/tracker.py +103 -0
- aprsd/packets/watch_list.py +119 -0
- aprsd/plugin.py +474 -284
- aprsd/plugin_utils.py +86 -0
- aprsd/plugins/__init__.py +0 -0
- aprsd/plugins/email.py +709 -0
- aprsd/plugins/fortune.py +61 -0
- aprsd/plugins/location.py +179 -0
- aprsd/plugins/notify.py +61 -0
- aprsd/plugins/ping.py +31 -0
- aprsd/plugins/time.py +115 -0
- aprsd/plugins/version.py +31 -0
- aprsd/plugins/weather.py +405 -0
- aprsd/stats/__init__.py +20 -0
- aprsd/stats/app.py +49 -0
- aprsd/stats/collector.py +37 -0
- aprsd/threads/__init__.py +11 -0
- aprsd/threads/aprsd.py +119 -0
- aprsd/threads/keep_alive.py +131 -0
- aprsd/threads/log_monitor.py +121 -0
- aprsd/threads/registry.py +56 -0
- aprsd/threads/rx.py +354 -0
- aprsd/threads/stats.py +44 -0
- aprsd/threads/tx.py +255 -0
- aprsd/utils/__init__.py +218 -0
- aprsd/utils/counter.py +51 -0
- aprsd/utils/json.py +80 -0
- aprsd/utils/objectstore.py +123 -0
- aprsd/utils/ring_buffer.py +40 -0
- aprsd/utils/trace.py +180 -0
- aprsd/web/__init__.py +0 -0
- aprsd/web/admin/__init__.py +0 -0
- aprsd/web/admin/static/css/index.css +84 -0
- aprsd/web/admin/static/css/prism.css +4 -0
- aprsd/web/admin/static/css/tabs.css +35 -0
- aprsd/web/admin/static/images/Untitled.png +0 -0
- aprsd/web/admin/static/images/aprs-symbols-16-0.png +0 -0
- aprsd/web/admin/static/images/aprs-symbols-16-1.png +0 -0
- aprsd/web/admin/static/images/aprs-symbols-64-0.png +0 -0
- aprsd/web/admin/static/images/aprs-symbols-64-1.png +0 -0
- aprsd/web/admin/static/images/aprs-symbols-64-2.png +0 -0
- aprsd/web/admin/static/js/charts.js +235 -0
- aprsd/web/admin/static/js/echarts.js +465 -0
- aprsd/web/admin/static/js/logs.js +26 -0
- aprsd/web/admin/static/js/main.js +231 -0
- aprsd/web/admin/static/js/prism.js +12 -0
- aprsd/web/admin/static/js/send-message.js +114 -0
- aprsd/web/admin/static/js/tabs.js +28 -0
- aprsd/web/admin/templates/index.html +196 -0
- aprsd/web/chat/static/css/chat.css +115 -0
- aprsd/web/chat/static/css/index.css +66 -0
- aprsd/web/chat/static/css/style.css.map +1 -0
- aprsd/web/chat/static/css/tabs.css +41 -0
- aprsd/web/chat/static/css/upstream/bootstrap.min.css +6 -0
- aprsd/web/chat/static/css/upstream/font.woff2 +0 -0
- aprsd/web/chat/static/css/upstream/google-fonts.css +23 -0
- aprsd/web/chat/static/css/upstream/jquery-ui.css +1311 -0
- aprsd/web/chat/static/css/upstream/jquery.toast.css +28 -0
- aprsd/web/chat/static/css/upstream/themes/default/assets/fonts/LatoLatin-Bold.woff +0 -0
- aprsd/web/chat/static/css/upstream/themes/default/assets/fonts/LatoLatin-Bold.woff2 +0 -0
- aprsd/web/chat/static/css/upstream/themes/default/assets/fonts/LatoLatin-Regular.woff +0 -0
- aprsd/web/chat/static/css/upstream/themes/default/assets/fonts/LatoLatin-Regular.woff2 +0 -0
- aprsd/web/chat/static/css/upstream/themes/default/assets/fonts/icons.woff +0 -0
- aprsd/web/chat/static/css/upstream/themes/default/assets/fonts/icons.woff2 +0 -0
- aprsd/web/chat/static/css/upstream/themes/default/assets/fonts/outline-icons.woff +0 -0
- aprsd/web/chat/static/css/upstream/themes/default/assets/fonts/outline-icons.woff2 +0 -0
- aprsd/web/chat/static/images/Untitled.png +0 -0
- aprsd/web/chat/static/images/aprs-symbols-16-0.png +0 -0
- aprsd/web/chat/static/images/aprs-symbols-16-1.png +0 -0
- aprsd/web/chat/static/images/aprs-symbols-64-0.png +0 -0
- aprsd/web/chat/static/images/aprs-symbols-64-1.png +0 -0
- aprsd/web/chat/static/images/aprs-symbols-64-2.png +0 -0
- aprsd/web/chat/static/images/globe.svg +3 -0
- aprsd/web/chat/static/js/gps.js +84 -0
- aprsd/web/chat/static/js/main.js +45 -0
- aprsd/web/chat/static/js/send-message.js +585 -0
- aprsd/web/chat/static/js/tabs.js +28 -0
- aprsd/web/chat/static/js/upstream/bootstrap.bundle.min.js +7 -0
- aprsd/web/chat/static/js/upstream/jquery-3.7.1.min.js +2 -0
- aprsd/web/chat/static/js/upstream/jquery-ui.min.js +13 -0
- aprsd/web/chat/static/js/upstream/jquery.toast.js +374 -0
- aprsd/web/chat/static/js/upstream/semantic.min.js +11 -0
- aprsd/web/chat/static/js/upstream/socket.io.min.js +7 -0
- aprsd/web/chat/templates/index.html +139 -0
- aprsd/wsgi.py +315 -0
- aprsd-3.4.2.dist-info/AUTHORS +13 -0
- aprsd-3.4.2.dist-info/LICENSE +175 -0
- aprsd-3.4.2.dist-info/METADATA +793 -0
- aprsd-3.4.2.dist-info/RECORD +133 -0
- {aprsd-1.0.0.dist-info → aprsd-3.4.2.dist-info}/WHEEL +1 -1
- aprsd-3.4.2.dist-info/entry_points.txt +8 -0
- aprsd/fake_aprs.py +0 -83
- aprsd/utils.py +0 -166
- aprsd-1.0.0.dist-info/AUTHORS +0 -6
- aprsd-1.0.0.dist-info/METADATA +0 -181
- aprsd-1.0.0.dist-info/RECORD +0 -13
- aprsd-1.0.0.dist-info/entry_points.txt +0 -4
- aprsd-1.0.0.dist-info/pbr.json +0 -1
- /aprsd/{fuzzyclock.py → utils/fuzzyclock.py} +0 -0
- {aprsd-1.0.0.dist-info → aprsd-3.4.2.dist-info}/top_level.txt +0 -0
aprsd/cmds/listen.py
ADDED
@@ -0,0 +1,231 @@
|
|
1
|
+
#
|
2
|
+
# License GPLv2
|
3
|
+
#
|
4
|
+
|
5
|
+
# python included libs
|
6
|
+
import datetime
|
7
|
+
import logging
|
8
|
+
import signal
|
9
|
+
import sys
|
10
|
+
import time
|
11
|
+
|
12
|
+
import click
|
13
|
+
from oslo_config import cfg
|
14
|
+
from rich.console import Console
|
15
|
+
|
16
|
+
# local imports here
|
17
|
+
import aprsd
|
18
|
+
from aprsd import cli_helper, packets, plugin, threads
|
19
|
+
from aprsd.client import client_factory
|
20
|
+
from aprsd.main import cli
|
21
|
+
from aprsd.packets import collector as packet_collector
|
22
|
+
from aprsd.packets import log as packet_log
|
23
|
+
from aprsd.packets import seen_list
|
24
|
+
from aprsd.stats import collector
|
25
|
+
from aprsd.threads import keep_alive, rx
|
26
|
+
from aprsd.threads import stats as stats_thread
|
27
|
+
|
28
|
+
|
29
|
+
# setup the global logger
|
30
|
+
# log.basicConfig(level=log.DEBUG) # level=10
|
31
|
+
LOG = logging.getLogger("APRSD")
|
32
|
+
CONF = cfg.CONF
|
33
|
+
console = Console()
|
34
|
+
|
35
|
+
|
36
|
+
def signal_handler(sig, frame):
|
37
|
+
threads.APRSDThreadList().stop_all()
|
38
|
+
if "subprocess" not in str(frame):
|
39
|
+
LOG.info(
|
40
|
+
"Ctrl+C, Sending all threads exit! Can take up to 10 seconds {}".format(
|
41
|
+
datetime.datetime.now(),
|
42
|
+
),
|
43
|
+
)
|
44
|
+
time.sleep(5)
|
45
|
+
# Last save to disk
|
46
|
+
collector.Collector().collect()
|
47
|
+
|
48
|
+
|
49
|
+
class APRSDListenThread(rx.APRSDRXThread):
|
50
|
+
def __init__(self, packet_queue, packet_filter=None, plugin_manager=None):
|
51
|
+
super().__init__(packet_queue)
|
52
|
+
self.packet_filter = packet_filter
|
53
|
+
self.plugin_manager = plugin_manager
|
54
|
+
if self.plugin_manager:
|
55
|
+
LOG.info(f"Plugins {self.plugin_manager.get_message_plugins()}")
|
56
|
+
|
57
|
+
def process_packet(self, *args, **kwargs):
|
58
|
+
packet = self._client.decode_packet(*args, **kwargs)
|
59
|
+
filters = {
|
60
|
+
packets.Packet.__name__: packets.Packet,
|
61
|
+
packets.AckPacket.__name__: packets.AckPacket,
|
62
|
+
packets.BeaconPacket.__name__: packets.BeaconPacket,
|
63
|
+
packets.GPSPacket.__name__: packets.GPSPacket,
|
64
|
+
packets.MessagePacket.__name__: packets.MessagePacket,
|
65
|
+
packets.MicEPacket.__name__: packets.MicEPacket,
|
66
|
+
packets.ObjectPacket.__name__: packets.ObjectPacket,
|
67
|
+
packets.StatusPacket.__name__: packets.StatusPacket,
|
68
|
+
packets.ThirdPartyPacket.__name__: packets.ThirdPartyPacket,
|
69
|
+
packets.WeatherPacket.__name__: packets.WeatherPacket,
|
70
|
+
packets.UnknownPacket.__name__: packets.UnknownPacket,
|
71
|
+
}
|
72
|
+
|
73
|
+
if self.packet_filter:
|
74
|
+
filter_class = filters[self.packet_filter]
|
75
|
+
if isinstance(packet, filter_class):
|
76
|
+
packet_log.log(packet)
|
77
|
+
if self.plugin_manager:
|
78
|
+
# Don't do anything with the reply
|
79
|
+
# This is the listen only command.
|
80
|
+
self.plugin_manager.run(packet)
|
81
|
+
else:
|
82
|
+
packet_log.log(packet)
|
83
|
+
if self.plugin_manager:
|
84
|
+
# Don't do anything with the reply.
|
85
|
+
# This is the listen only command.
|
86
|
+
self.plugin_manager.run(packet)
|
87
|
+
|
88
|
+
packet_collector.PacketCollector().rx(packet)
|
89
|
+
|
90
|
+
|
91
|
+
@cli.command()
|
92
|
+
@cli_helper.add_options(cli_helper.common_options)
|
93
|
+
@click.option(
|
94
|
+
"--aprs-login",
|
95
|
+
envvar="APRS_LOGIN",
|
96
|
+
show_envvar=True,
|
97
|
+
help="What callsign to send the message from.",
|
98
|
+
)
|
99
|
+
@click.option(
|
100
|
+
"--aprs-password",
|
101
|
+
envvar="APRS_PASSWORD",
|
102
|
+
show_envvar=True,
|
103
|
+
help="the APRS-IS password for APRS_LOGIN",
|
104
|
+
)
|
105
|
+
@click.option(
|
106
|
+
"--packet-filter",
|
107
|
+
type=click.Choice(
|
108
|
+
[
|
109
|
+
packets.AckPacket.__name__,
|
110
|
+
packets.BeaconPacket.__name__,
|
111
|
+
packets.GPSPacket.__name__,
|
112
|
+
packets.MicEPacket.__name__,
|
113
|
+
packets.MessagePacket.__name__,
|
114
|
+
packets.ObjectPacket.__name__,
|
115
|
+
packets.RejectPacket.__name__,
|
116
|
+
packets.StatusPacket.__name__,
|
117
|
+
packets.ThirdPartyPacket.__name__,
|
118
|
+
packets.UnknownPacket.__name__,
|
119
|
+
packets.WeatherPacket.__name__,
|
120
|
+
],
|
121
|
+
case_sensitive=False,
|
122
|
+
),
|
123
|
+
help="Filter by packet type",
|
124
|
+
)
|
125
|
+
@click.option(
|
126
|
+
"--load-plugins",
|
127
|
+
default=False,
|
128
|
+
is_flag=True,
|
129
|
+
help="Load plugins as enabled in aprsd.conf ?",
|
130
|
+
)
|
131
|
+
@click.argument(
|
132
|
+
"filter",
|
133
|
+
nargs=-1,
|
134
|
+
required=True,
|
135
|
+
)
|
136
|
+
@click.pass_context
|
137
|
+
@cli_helper.process_standard_options
|
138
|
+
def listen(
|
139
|
+
ctx,
|
140
|
+
aprs_login,
|
141
|
+
aprs_password,
|
142
|
+
packet_filter,
|
143
|
+
load_plugins,
|
144
|
+
filter,
|
145
|
+
):
|
146
|
+
"""Listen to packets on the APRS-IS Network based on FILTER.
|
147
|
+
|
148
|
+
FILTER is the APRS Filter to use.\n
|
149
|
+
see http://www.aprs-is.net/javAPRSFilter.aspx\n
|
150
|
+
r/lat/lon/dist - Range Filter Pass posits and objects within dist km from lat/lon.\n
|
151
|
+
p/aa/bb/cc... - Prefix Filter Pass traffic with fromCall that start with aa or bb or cc.\n
|
152
|
+
b/call1/call2... - Budlist Filter Pass all traffic from exact call: call1, call2, ... (* wild card allowed) \n
|
153
|
+
o/obj1/obj2... - Object Filter Pass all objects with the exact name of obj1, obj2, ... (* wild card allowed)\n
|
154
|
+
|
155
|
+
"""
|
156
|
+
signal.signal(signal.SIGINT, signal_handler)
|
157
|
+
signal.signal(signal.SIGTERM, signal_handler)
|
158
|
+
|
159
|
+
if not aprs_login:
|
160
|
+
click.echo(ctx.get_help())
|
161
|
+
click.echo("")
|
162
|
+
ctx.fail("Must set --aprs-login or APRS_LOGIN")
|
163
|
+
ctx.exit()
|
164
|
+
|
165
|
+
if not aprs_password:
|
166
|
+
click.echo(ctx.get_help())
|
167
|
+
click.echo("")
|
168
|
+
ctx.fail("Must set --aprs-password or APRS_PASSWORD")
|
169
|
+
ctx.exit()
|
170
|
+
|
171
|
+
# CONF.aprs_network.login = aprs_login
|
172
|
+
# config["aprs"]["password"] = aprs_password
|
173
|
+
|
174
|
+
LOG.info(f"APRSD Listen Started version: {aprsd.__version__}")
|
175
|
+
|
176
|
+
CONF.log_opt_values(LOG, logging.DEBUG)
|
177
|
+
collector.Collector()
|
178
|
+
|
179
|
+
# Try and load saved MsgTrack list
|
180
|
+
LOG.debug("Loading saved MsgTrack object.")
|
181
|
+
|
182
|
+
# Initialize the client factory and create
|
183
|
+
# The correct client object ready for use
|
184
|
+
# Make sure we have 1 client transport enabled
|
185
|
+
if not client_factory.is_client_enabled():
|
186
|
+
LOG.error("No Clients are enabled in config.")
|
187
|
+
sys.exit(-1)
|
188
|
+
|
189
|
+
# Creates the client object
|
190
|
+
LOG.info("Creating client connection")
|
191
|
+
aprs_client = client_factory.create()
|
192
|
+
LOG.info(aprs_client)
|
193
|
+
|
194
|
+
LOG.debug(f"Filter by '{filter}'")
|
195
|
+
aprs_client.set_filter(filter)
|
196
|
+
|
197
|
+
keepalive = keep_alive.KeepAliveThread()
|
198
|
+
# keepalive.start()
|
199
|
+
|
200
|
+
if not CONF.enable_seen_list:
|
201
|
+
# just deregister the class from the packet collector
|
202
|
+
packet_collector.PacketCollector().unregister(seen_list.SeenList)
|
203
|
+
|
204
|
+
pm = None
|
205
|
+
pm = plugin.PluginManager()
|
206
|
+
if load_plugins:
|
207
|
+
LOG.info("Loading plugins")
|
208
|
+
pm.setup_plugins(load_help_plugin=False)
|
209
|
+
else:
|
210
|
+
LOG.warning(
|
211
|
+
"Not Loading any plugins use --load-plugins to load what's "
|
212
|
+
"defined in the config file.",
|
213
|
+
)
|
214
|
+
stats = stats_thread.APRSDStatsStoreThread()
|
215
|
+
stats.start()
|
216
|
+
|
217
|
+
LOG.debug("Create APRSDListenThread")
|
218
|
+
listen_thread = APRSDListenThread(
|
219
|
+
packet_queue=threads.packet_queue,
|
220
|
+
packet_filter=packet_filter,
|
221
|
+
plugin_manager=pm,
|
222
|
+
)
|
223
|
+
LOG.debug("Start APRSDListenThread")
|
224
|
+
listen_thread.start()
|
225
|
+
|
226
|
+
keepalive.start()
|
227
|
+
LOG.debug("keepalive Join")
|
228
|
+
keepalive.join()
|
229
|
+
LOG.debug("listen_thread Join")
|
230
|
+
listen_thread.join()
|
231
|
+
stats.join()
|
@@ -0,0 +1,171 @@
|
|
1
|
+
import logging
|
2
|
+
import sys
|
3
|
+
import time
|
4
|
+
|
5
|
+
import aprslib
|
6
|
+
from aprslib.exceptions import LoginError
|
7
|
+
import click
|
8
|
+
from oslo_config import cfg
|
9
|
+
|
10
|
+
import aprsd
|
11
|
+
from aprsd import cli_helper, packets
|
12
|
+
from aprsd import conf # noqa : F401
|
13
|
+
from aprsd.client import client_factory
|
14
|
+
from aprsd.main import cli
|
15
|
+
import aprsd.packets # noqa : F401
|
16
|
+
from aprsd.packets import collector
|
17
|
+
from aprsd.threads import tx
|
18
|
+
|
19
|
+
|
20
|
+
CONF = cfg.CONF
|
21
|
+
LOG = logging.getLogger("APRSD")
|
22
|
+
|
23
|
+
|
24
|
+
@cli.command()
|
25
|
+
@cli_helper.add_options(cli_helper.common_options)
|
26
|
+
@click.option(
|
27
|
+
"--aprs-login",
|
28
|
+
envvar="APRS_LOGIN",
|
29
|
+
show_envvar=True,
|
30
|
+
help="What callsign to send the message from. Defaults to config entry.",
|
31
|
+
)
|
32
|
+
@click.option(
|
33
|
+
"--aprs-password",
|
34
|
+
envvar="APRS_PASSWORD",
|
35
|
+
show_envvar=True,
|
36
|
+
help="the APRS-IS password for APRS_LOGIN. Defaults to config entry.",
|
37
|
+
)
|
38
|
+
@click.option(
|
39
|
+
"--no-ack",
|
40
|
+
"-n",
|
41
|
+
is_flag=True,
|
42
|
+
show_default=True,
|
43
|
+
default=False,
|
44
|
+
help="Don't wait for an ack, just sent it to APRS-IS and bail.",
|
45
|
+
)
|
46
|
+
@click.option(
|
47
|
+
"--wait-response",
|
48
|
+
"-w",
|
49
|
+
is_flag=True,
|
50
|
+
show_default=True,
|
51
|
+
default=False,
|
52
|
+
help="Wait for a response to the message?",
|
53
|
+
)
|
54
|
+
@click.option("--raw", default=None, help="Send a raw message. Implies --no-ack")
|
55
|
+
@click.argument("tocallsign", required=True)
|
56
|
+
@click.argument("command", nargs=-1, required=True)
|
57
|
+
@click.pass_context
|
58
|
+
@cli_helper.process_standard_options
|
59
|
+
def send_message(
|
60
|
+
ctx,
|
61
|
+
aprs_login,
|
62
|
+
aprs_password,
|
63
|
+
no_ack,
|
64
|
+
wait_response,
|
65
|
+
raw,
|
66
|
+
tocallsign,
|
67
|
+
command,
|
68
|
+
):
|
69
|
+
"""Send a message to a callsign via APRS_IS."""
|
70
|
+
global got_ack, got_response
|
71
|
+
quiet = ctx.obj["quiet"]
|
72
|
+
|
73
|
+
if not aprs_login:
|
74
|
+
if CONF.aprs_network.login == conf.client.DEFAULT_LOGIN:
|
75
|
+
click.echo("Must set --aprs_login or APRS_LOGIN")
|
76
|
+
ctx.exit(-1)
|
77
|
+
return
|
78
|
+
else:
|
79
|
+
aprs_login = CONF.aprs_network.login
|
80
|
+
|
81
|
+
if not aprs_password:
|
82
|
+
if not CONF.aprs_network.password:
|
83
|
+
click.echo("Must set --aprs-password or APRS_PASSWORD")
|
84
|
+
ctx.exit(-1)
|
85
|
+
return
|
86
|
+
else:
|
87
|
+
aprs_password = CONF.aprs_network.password
|
88
|
+
|
89
|
+
LOG.info(f"APRSD LISTEN Started version: {aprsd.__version__}")
|
90
|
+
if type(command) is tuple:
|
91
|
+
command = " ".join(command)
|
92
|
+
if not quiet:
|
93
|
+
if raw:
|
94
|
+
LOG.info(f"L'{aprs_login}' R'{raw}'")
|
95
|
+
else:
|
96
|
+
LOG.info(f"L'{aprs_login}' To'{tocallsign}' C'{command}'")
|
97
|
+
|
98
|
+
got_ack = False
|
99
|
+
got_response = False
|
100
|
+
|
101
|
+
def rx_packet(packet):
|
102
|
+
global got_ack, got_response
|
103
|
+
cl = client_factory.create()
|
104
|
+
packet = cl.decode_packet(packet)
|
105
|
+
collector.PacketCollector().rx(packet)
|
106
|
+
packet.log("RX")
|
107
|
+
# LOG.debug("Got packet back {}".format(packet))
|
108
|
+
if isinstance(packet, packets.AckPacket):
|
109
|
+
got_ack = True
|
110
|
+
else:
|
111
|
+
got_response = True
|
112
|
+
from_call = packet.from_call
|
113
|
+
our_call = CONF.callsign.lower()
|
114
|
+
tx.send(
|
115
|
+
packets.AckPacket(
|
116
|
+
from_call=our_call,
|
117
|
+
to_call=from_call,
|
118
|
+
msgNo=packet.msgNo,
|
119
|
+
),
|
120
|
+
direct=True,
|
121
|
+
)
|
122
|
+
|
123
|
+
if got_ack:
|
124
|
+
if wait_response:
|
125
|
+
if got_response:
|
126
|
+
sys.exit(0)
|
127
|
+
else:
|
128
|
+
sys.exit(0)
|
129
|
+
|
130
|
+
try:
|
131
|
+
client_factory.create().client
|
132
|
+
except LoginError:
|
133
|
+
sys.exit(-1)
|
134
|
+
|
135
|
+
# Send a message
|
136
|
+
# then we setup a consumer to rx messages
|
137
|
+
# We should get an ack back as well as a new message
|
138
|
+
# we should bail after we get the ack and send an ack back for the
|
139
|
+
# message
|
140
|
+
if raw:
|
141
|
+
tx.send(
|
142
|
+
packets.Packet(from_call="", to_call="", raw=raw),
|
143
|
+
direct=True,
|
144
|
+
)
|
145
|
+
sys.exit(0)
|
146
|
+
else:
|
147
|
+
tx.send(
|
148
|
+
packets.MessagePacket(
|
149
|
+
from_call=aprs_login,
|
150
|
+
to_call=tocallsign,
|
151
|
+
message_text=command,
|
152
|
+
),
|
153
|
+
direct=True,
|
154
|
+
)
|
155
|
+
|
156
|
+
if no_ack:
|
157
|
+
sys.exit(0)
|
158
|
+
|
159
|
+
try:
|
160
|
+
# This will register a packet consumer with aprslib
|
161
|
+
# When new packets come in the consumer will process
|
162
|
+
# the packet
|
163
|
+
aprs_client = client_factory.create().client
|
164
|
+
aprs_client.consumer(rx_packet, raw=False)
|
165
|
+
except aprslib.exceptions.ConnectionDrop:
|
166
|
+
LOG.error("Connection dropped, reconnecting")
|
167
|
+
time.sleep(5)
|
168
|
+
# Force the deletion of the client object connected to aprs
|
169
|
+
# This will cause a reconnect, next time client.get_client()
|
170
|
+
# is called
|
171
|
+
aprs_client.reset()
|
aprsd/cmds/server.py
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
import logging
|
2
|
+
import signal
|
3
|
+
import sys
|
4
|
+
|
5
|
+
import click
|
6
|
+
from oslo_config import cfg
|
7
|
+
|
8
|
+
import aprsd
|
9
|
+
from aprsd import cli_helper
|
10
|
+
from aprsd import main as aprsd_main
|
11
|
+
from aprsd import plugin, threads, utils
|
12
|
+
from aprsd.client import client_factory
|
13
|
+
from aprsd.main import cli
|
14
|
+
from aprsd.packets import collector as packet_collector
|
15
|
+
from aprsd.packets import seen_list
|
16
|
+
from aprsd.threads import keep_alive, log_monitor, registry, rx
|
17
|
+
from aprsd.threads import stats as stats_thread
|
18
|
+
from aprsd.threads import tx
|
19
|
+
|
20
|
+
|
21
|
+
CONF = cfg.CONF
|
22
|
+
LOG = logging.getLogger("APRSD")
|
23
|
+
|
24
|
+
|
25
|
+
# main() ###
|
26
|
+
@cli.command()
|
27
|
+
@cli_helper.add_options(cli_helper.common_options)
|
28
|
+
@click.option(
|
29
|
+
"-f",
|
30
|
+
"--flush",
|
31
|
+
"flush",
|
32
|
+
is_flag=True,
|
33
|
+
show_default=True,
|
34
|
+
default=False,
|
35
|
+
help="Flush out all old aged messages on disk.",
|
36
|
+
)
|
37
|
+
@click.pass_context
|
38
|
+
@cli_helper.process_standard_options
|
39
|
+
def server(ctx, flush):
|
40
|
+
"""Start the aprsd server gateway process."""
|
41
|
+
signal.signal(signal.SIGINT, aprsd_main.signal_handler)
|
42
|
+
signal.signal(signal.SIGTERM, aprsd_main.signal_handler)
|
43
|
+
|
44
|
+
level, msg = utils._check_version()
|
45
|
+
if level:
|
46
|
+
LOG.warning(msg)
|
47
|
+
else:
|
48
|
+
LOG.info(msg)
|
49
|
+
LOG.info(f"APRSD Started version: {aprsd.__version__}")
|
50
|
+
|
51
|
+
# Initialize the client factory and create
|
52
|
+
# The correct client object ready for use
|
53
|
+
if not client_factory.is_client_enabled():
|
54
|
+
LOG.error("No Clients are enabled in config.")
|
55
|
+
sys.exit(-1)
|
56
|
+
|
57
|
+
# Creates the client object
|
58
|
+
LOG.info("Creating client connection")
|
59
|
+
aprs_client = client_factory.create()
|
60
|
+
LOG.info(aprs_client)
|
61
|
+
|
62
|
+
# Create the initial PM singleton and Register plugins
|
63
|
+
# We register plugins first here so we can register each
|
64
|
+
# plugins config options, so we can dump them all in the
|
65
|
+
# log file output.
|
66
|
+
LOG.info("Loading Plugin Manager and registering plugins")
|
67
|
+
plugin_manager = plugin.PluginManager()
|
68
|
+
plugin_manager.setup_plugins()
|
69
|
+
|
70
|
+
# Dump all the config options now.
|
71
|
+
CONF.log_opt_values(LOG, logging.DEBUG)
|
72
|
+
message_plugins = plugin_manager.get_message_plugins()
|
73
|
+
watchlist_plugins = plugin_manager.get_watchlist_plugins()
|
74
|
+
LOG.info("Message Plugins enabled and running:")
|
75
|
+
for p in message_plugins:
|
76
|
+
LOG.info(p)
|
77
|
+
LOG.info("Watchlist Plugins enabled and running:")
|
78
|
+
for p in watchlist_plugins:
|
79
|
+
LOG.info(p)
|
80
|
+
|
81
|
+
# Make sure we have 1 client transport enabled
|
82
|
+
if not client_factory.is_client_enabled():
|
83
|
+
LOG.error("No Clients are enabled in config.")
|
84
|
+
sys.exit(-1)
|
85
|
+
|
86
|
+
if not client_factory.is_client_configured():
|
87
|
+
LOG.error("APRS client is not properly configured in config file.")
|
88
|
+
sys.exit(-1)
|
89
|
+
|
90
|
+
if not CONF.enable_seen_list:
|
91
|
+
# just deregister the class from the packet collector
|
92
|
+
packet_collector.PacketCollector().unregister(seen_list.SeenList)
|
93
|
+
|
94
|
+
# Now load the msgTrack from disk if any
|
95
|
+
if flush:
|
96
|
+
LOG.debug("Flushing All packet tracking objects.")
|
97
|
+
packet_collector.PacketCollector().flush()
|
98
|
+
else:
|
99
|
+
# Try and load saved MsgTrack list
|
100
|
+
LOG.debug("Loading saved packet tracking data.")
|
101
|
+
packet_collector.PacketCollector().load()
|
102
|
+
|
103
|
+
# Now start all the main processing threads.
|
104
|
+
|
105
|
+
keepalive = keep_alive.KeepAliveThread()
|
106
|
+
keepalive.start()
|
107
|
+
|
108
|
+
stats_store_thread = stats_thread.APRSDStatsStoreThread()
|
109
|
+
stats_store_thread.start()
|
110
|
+
|
111
|
+
rx_thread = rx.APRSDPluginRXThread(
|
112
|
+
packet_queue=threads.packet_queue,
|
113
|
+
)
|
114
|
+
process_thread = rx.APRSDPluginProcessPacketThread(
|
115
|
+
packet_queue=threads.packet_queue,
|
116
|
+
)
|
117
|
+
rx_thread.start()
|
118
|
+
process_thread.start()
|
119
|
+
|
120
|
+
if CONF.enable_beacon:
|
121
|
+
LOG.info("Beacon Enabled. Starting Beacon thread.")
|
122
|
+
bcn_thread = tx.BeaconSendThread()
|
123
|
+
bcn_thread.start()
|
124
|
+
|
125
|
+
if CONF.aprs_registry.enabled:
|
126
|
+
LOG.info("Registry Enabled. Starting Registry thread.")
|
127
|
+
registry_thread = registry.APRSRegistryThread()
|
128
|
+
registry_thread.start()
|
129
|
+
|
130
|
+
if CONF.admin.web_enabled:
|
131
|
+
log_monitor_thread = log_monitor.LogMonitorThread()
|
132
|
+
log_monitor_thread.start()
|
133
|
+
|
134
|
+
rx_thread.join()
|
135
|
+
process_thread.join()
|
136
|
+
|
137
|
+
return 0
|