aprsd 4.0.2__py3-none-any.whl → 4.1.1__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/cli_helper.py +36 -35
- aprsd/client/base.py +14 -11
- aprsd/client/drivers/aprsis.py +87 -35
- aprsd/client/drivers/kiss.py +28 -5
- aprsd/client/kiss.py +1 -0
- aprsd/cmds/listen.py +84 -91
- aprsd/cmds/send_message.py +30 -28
- aprsd/cmds/server.py +29 -64
- aprsd/conf/common.py +100 -101
- aprsd/conf/log.py +32 -22
- aprsd/log/log.py +31 -18
- aprsd/main.py +22 -22
- aprsd/packets/__init__.py +6 -0
- aprsd/packets/core.py +5 -2
- aprsd/packets/filter.py +58 -0
- aprsd/packets/filters/__init__.py +0 -0
- aprsd/packets/filters/dupe_filter.py +68 -0
- aprsd/packets/filters/packet_type.py +53 -0
- aprsd/packets/packet_list.py +33 -27
- aprsd/plugin.py +52 -52
- aprsd/plugin_utils.py +20 -21
- aprsd/plugins/weather.py +110 -109
- aprsd/threads/__init__.py +1 -2
- aprsd/threads/rx.py +83 -75
- aprsd/threads/service.py +42 -0
- aprsd/threads/stats.py +4 -9
- aprsd/utils/objectstore.py +12 -13
- {aprsd-4.0.2.dist-info → aprsd-4.1.1.dist-info}/METADATA +22 -20
- {aprsd-4.0.2.dist-info → aprsd-4.1.1.dist-info}/RECORD +34 -29
- {aprsd-4.0.2.dist-info → aprsd-4.1.1.dist-info}/WHEEL +1 -1
- {aprsd-4.0.2.dist-info → aprsd-4.1.1.dist-info}/AUTHORS +0 -0
- {aprsd-4.0.2.dist-info → aprsd-4.1.1.dist-info}/LICENSE +0 -0
- {aprsd-4.0.2.dist-info → aprsd-4.1.1.dist-info}/entry_points.txt +0 -0
- {aprsd-4.0.2.dist-info → aprsd-4.1.1.dist-info}/top_level.txt +0 -0
aprsd/cmds/listen.py
CHANGED
@@ -20,8 +20,10 @@ from aprsd import cli_helper, packets, plugin, threads, utils
|
|
20
20
|
from aprsd.client import client_factory
|
21
21
|
from aprsd.main import cli
|
22
22
|
from aprsd.packets import collector as packet_collector
|
23
|
+
from aprsd.packets import core, seen_list
|
23
24
|
from aprsd.packets import log as packet_log
|
24
|
-
from aprsd.packets import
|
25
|
+
from aprsd.packets.filter import PacketFilter
|
26
|
+
from aprsd.packets.filters import dupe_filter, packet_type
|
25
27
|
from aprsd.stats import collector
|
26
28
|
from aprsd.threads import keepalive, rx
|
27
29
|
from aprsd.threads import stats as stats_thread
|
@@ -29,7 +31,7 @@ from aprsd.threads.aprsd import APRSDThread
|
|
29
31
|
|
30
32
|
# setup the global logger
|
31
33
|
# log.basicConfig(level=log.DEBUG) # level=10
|
32
|
-
LOG = logging.getLogger(
|
34
|
+
LOG = logging.getLogger('APRSD')
|
33
35
|
CONF = cfg.CONF
|
34
36
|
LOGU = logger
|
35
37
|
console = Console()
|
@@ -37,9 +39,9 @@ console = Console()
|
|
37
39
|
|
38
40
|
def signal_handler(sig, frame):
|
39
41
|
threads.APRSDThreadList().stop_all()
|
40
|
-
if
|
42
|
+
if 'subprocess' not in str(frame):
|
41
43
|
LOG.info(
|
42
|
-
|
44
|
+
'Ctrl+C, Sending all threads exit! Can take up to 10 seconds {}'.format(
|
43
45
|
datetime.datetime.now(),
|
44
46
|
),
|
45
47
|
)
|
@@ -48,90 +50,66 @@ def signal_handler(sig, frame):
|
|
48
50
|
collector.Collector().collect()
|
49
51
|
|
50
52
|
|
51
|
-
class
|
53
|
+
class APRSDListenProcessThread(rx.APRSDFilterThread):
|
52
54
|
def __init__(
|
53
55
|
self,
|
54
56
|
packet_queue,
|
55
57
|
packet_filter=None,
|
56
58
|
plugin_manager=None,
|
57
|
-
enabled_plugins=
|
59
|
+
enabled_plugins=None,
|
58
60
|
log_packets=False,
|
59
61
|
):
|
60
|
-
super().__init__(packet_queue)
|
62
|
+
super().__init__('ListenProcThread', packet_queue)
|
61
63
|
self.packet_filter = packet_filter
|
62
64
|
self.plugin_manager = plugin_manager
|
63
65
|
if self.plugin_manager:
|
64
|
-
LOG.info(f
|
66
|
+
LOG.info(f'Plugins {self.plugin_manager.get_message_plugins()}')
|
65
67
|
self.log_packets = log_packets
|
66
68
|
|
67
|
-
def
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
packets.ObjectPacket.__name__: packets.ObjectPacket,
|
77
|
-
packets.StatusPacket.__name__: packets.StatusPacket,
|
78
|
-
packets.ThirdPartyPacket.__name__: packets.ThirdPartyPacket,
|
79
|
-
packets.WeatherPacket.__name__: packets.WeatherPacket,
|
80
|
-
packets.UnknownPacket.__name__: packets.UnknownPacket,
|
81
|
-
}
|
82
|
-
|
83
|
-
if self.packet_filter:
|
84
|
-
filter_class = filters[self.packet_filter]
|
85
|
-
if isinstance(packet, filter_class):
|
86
|
-
if self.log_packets:
|
87
|
-
packet_log.log(packet)
|
88
|
-
if self.plugin_manager:
|
89
|
-
# Don't do anything with the reply
|
90
|
-
# This is the listen only command.
|
91
|
-
self.plugin_manager.run(packet)
|
92
|
-
else:
|
93
|
-
if self.log_packets:
|
94
|
-
packet_log.log(packet)
|
95
|
-
if self.plugin_manager:
|
96
|
-
# Don't do anything with the reply.
|
97
|
-
# This is the listen only command.
|
98
|
-
self.plugin_manager.run(packet)
|
99
|
-
|
100
|
-
packet_collector.PacketCollector().rx(packet)
|
69
|
+
def print_packet(self, packet):
|
70
|
+
if self.log_packets:
|
71
|
+
packet_log.log(packet)
|
72
|
+
|
73
|
+
def process_packet(self, packet: type[core.Packet]):
|
74
|
+
if self.plugin_manager:
|
75
|
+
# Don't do anything with the reply.
|
76
|
+
# This is the listen only command.
|
77
|
+
self.plugin_manager.run(packet)
|
101
78
|
|
102
79
|
|
103
80
|
class ListenStatsThread(APRSDThread):
|
104
81
|
"""Log the stats from the PacketList."""
|
105
82
|
|
106
83
|
def __init__(self):
|
107
|
-
super().__init__(
|
84
|
+
super().__init__('PacketStatsLog')
|
108
85
|
self._last_total_rx = 0
|
86
|
+
self.period = 31
|
109
87
|
|
110
88
|
def loop(self):
|
111
|
-
if self.loop_count %
|
89
|
+
if self.loop_count % self.period == 0:
|
112
90
|
# log the stats every 10 seconds
|
113
91
|
stats_json = collector.Collector().collect()
|
114
|
-
stats = stats_json[
|
115
|
-
total_rx = stats[
|
116
|
-
packet_count = len(stats[
|
92
|
+
stats = stats_json['PacketList']
|
93
|
+
total_rx = stats['rx']
|
94
|
+
packet_count = len(stats['packets'])
|
117
95
|
rx_delta = total_rx - self._last_total_rx
|
118
|
-
rate = rx_delta /
|
96
|
+
rate = rx_delta / self.period
|
119
97
|
|
120
98
|
# Log summary stats
|
121
99
|
LOGU.opt(colors=True).info(
|
122
|
-
f
|
123
|
-
f
|
124
|
-
f
|
125
|
-
f
|
100
|
+
f'<green>RX Rate: {rate:.2f} pps</green> '
|
101
|
+
f'<yellow>Total RX: {total_rx}</yellow> '
|
102
|
+
f'<red>RX Last {self.period} secs: {rx_delta}</red> '
|
103
|
+
f'<white>Packets in PacketListStats: {packet_count}</white>',
|
126
104
|
)
|
127
105
|
self._last_total_rx = total_rx
|
128
106
|
|
129
107
|
# Log individual type stats
|
130
|
-
for k, v in stats[
|
131
|
-
thread_hex = f
|
108
|
+
for k, v in stats['types'].items():
|
109
|
+
thread_hex = f'fg {utils.hex_from_name(k)}'
|
132
110
|
LOGU.opt(colors=True).info(
|
133
|
-
f
|
134
|
-
f
|
111
|
+
f'<{thread_hex}>{k:<15}</{thread_hex}> '
|
112
|
+
f'<blue>RX: {v["rx"]}</blue> <red>TX: {v["tx"]}</red>',
|
135
113
|
)
|
136
114
|
|
137
115
|
time.sleep(1)
|
@@ -141,19 +119,19 @@ class ListenStatsThread(APRSDThread):
|
|
141
119
|
@cli.command()
|
142
120
|
@cli_helper.add_options(cli_helper.common_options)
|
143
121
|
@click.option(
|
144
|
-
|
145
|
-
envvar=
|
122
|
+
'--aprs-login',
|
123
|
+
envvar='APRS_LOGIN',
|
146
124
|
show_envvar=True,
|
147
|
-
help=
|
125
|
+
help='What callsign to send the message from.',
|
148
126
|
)
|
149
127
|
@click.option(
|
150
|
-
|
151
|
-
envvar=
|
128
|
+
'--aprs-password',
|
129
|
+
envvar='APRS_PASSWORD',
|
152
130
|
show_envvar=True,
|
153
|
-
help=
|
131
|
+
help='the APRS-IS password for APRS_LOGIN',
|
154
132
|
)
|
155
133
|
@click.option(
|
156
|
-
|
134
|
+
'--packet-filter',
|
157
135
|
type=click.Choice(
|
158
136
|
[
|
159
137
|
packets.AckPacket.__name__,
|
@@ -170,35 +148,37 @@ class ListenStatsThread(APRSDThread):
|
|
170
148
|
],
|
171
149
|
case_sensitive=False,
|
172
150
|
),
|
173
|
-
|
151
|
+
multiple=True,
|
152
|
+
default=[],
|
153
|
+
help='Filter by packet type',
|
174
154
|
)
|
175
155
|
@click.option(
|
176
|
-
|
156
|
+
'--enable-plugin',
|
177
157
|
multiple=True,
|
178
|
-
help=
|
158
|
+
help='Enable a plugin. This is the name of the file in the plugins directory.',
|
179
159
|
)
|
180
160
|
@click.option(
|
181
|
-
|
161
|
+
'--load-plugins',
|
182
162
|
default=False,
|
183
163
|
is_flag=True,
|
184
|
-
help=
|
164
|
+
help='Load plugins as enabled in aprsd.conf ?',
|
185
165
|
)
|
186
166
|
@click.argument(
|
187
|
-
|
167
|
+
'filter',
|
188
168
|
nargs=-1,
|
189
169
|
required=True,
|
190
170
|
)
|
191
171
|
@click.option(
|
192
|
-
|
172
|
+
'--log-packets',
|
193
173
|
default=False,
|
194
174
|
is_flag=True,
|
195
|
-
help=
|
175
|
+
help='Log incoming packets.',
|
196
176
|
)
|
197
177
|
@click.option(
|
198
|
-
|
178
|
+
'--enable-packet-stats',
|
199
179
|
default=False,
|
200
180
|
is_flag=True,
|
201
|
-
help=
|
181
|
+
help='Enable packet stats periodic logging.',
|
202
182
|
)
|
203
183
|
@click.pass_context
|
204
184
|
@cli_helper.process_standard_options
|
@@ -228,46 +208,46 @@ def listen(
|
|
228
208
|
|
229
209
|
if not aprs_login:
|
230
210
|
click.echo(ctx.get_help())
|
231
|
-
click.echo(
|
232
|
-
ctx.fail(
|
211
|
+
click.echo('')
|
212
|
+
ctx.fail('Must set --aprs-login or APRS_LOGIN')
|
233
213
|
ctx.exit()
|
234
214
|
|
235
215
|
if not aprs_password:
|
236
216
|
click.echo(ctx.get_help())
|
237
|
-
click.echo(
|
238
|
-
ctx.fail(
|
217
|
+
click.echo('')
|
218
|
+
ctx.fail('Must set --aprs-password or APRS_PASSWORD')
|
239
219
|
ctx.exit()
|
240
220
|
|
241
221
|
# CONF.aprs_network.login = aprs_login
|
242
222
|
# config["aprs"]["password"] = aprs_password
|
243
223
|
|
244
|
-
LOG.info(f
|
224
|
+
LOG.info(f'APRSD Listen Started version: {aprsd.__version__}')
|
245
225
|
|
246
226
|
CONF.log_opt_values(LOG, logging.DEBUG)
|
247
227
|
collector.Collector()
|
248
228
|
|
249
229
|
# Try and load saved MsgTrack list
|
250
|
-
LOG.debug(
|
230
|
+
LOG.debug('Loading saved MsgTrack object.')
|
251
231
|
|
252
232
|
# Initialize the client factory and create
|
253
233
|
# The correct client object ready for use
|
254
234
|
# Make sure we have 1 client transport enabled
|
255
235
|
if not client_factory.is_client_enabled():
|
256
|
-
LOG.error(
|
236
|
+
LOG.error('No Clients are enabled in config.')
|
257
237
|
sys.exit(-1)
|
258
238
|
|
259
239
|
# Creates the client object
|
260
|
-
LOG.info(
|
240
|
+
LOG.info('Creating client connection')
|
261
241
|
aprs_client = client_factory.create()
|
262
242
|
LOG.info(aprs_client)
|
263
243
|
if not aprs_client.login_success:
|
264
244
|
# We failed to login, will just quit!
|
265
|
-
msg = f
|
245
|
+
msg = f'Login Failure: {aprs_client.login_failure}'
|
266
246
|
LOG.error(msg)
|
267
247
|
print(msg)
|
268
248
|
sys.exit(-1)
|
269
249
|
|
270
|
-
LOG.debug(f"Filter by '{filter}'")
|
250
|
+
LOG.debug(f"Filter messages on aprsis server by '{filter}'")
|
271
251
|
aprs_client.set_filter(filter)
|
272
252
|
|
273
253
|
keepalive_thread = keepalive.KeepAliveThread()
|
@@ -276,10 +256,19 @@ def listen(
|
|
276
256
|
# just deregister the class from the packet collector
|
277
257
|
packet_collector.PacketCollector().unregister(seen_list.SeenList)
|
278
258
|
|
259
|
+
# we don't want the dupe filter to run here.
|
260
|
+
PacketFilter().unregister(dupe_filter.DupePacketFilter)
|
261
|
+
if packet_filter:
|
262
|
+
LOG.info('Enabling packet filtering for {packet_filter}')
|
263
|
+
packet_type.PacketTypeFilter().set_allow_list(packet_filter)
|
264
|
+
PacketFilter().register(packet_type.PacketTypeFilter)
|
265
|
+
else:
|
266
|
+
LOG.info('No packet filtering enabled.')
|
267
|
+
|
279
268
|
pm = None
|
280
269
|
if load_plugins:
|
281
270
|
pm = plugin.PluginManager()
|
282
|
-
LOG.info(
|
271
|
+
LOG.info('Loading plugins')
|
283
272
|
pm.setup_plugins(load_help_plugin=False)
|
284
273
|
elif enable_plugin:
|
285
274
|
pm = plugin.PluginManager()
|
@@ -290,33 +279,37 @@ def listen(
|
|
290
279
|
else:
|
291
280
|
LOG.warning(
|
292
281
|
"Not Loading any plugins use --load-plugins to load what's "
|
293
|
-
|
282
|
+
'defined in the config file.',
|
294
283
|
)
|
295
284
|
|
296
285
|
if pm:
|
297
286
|
for p in pm.get_plugins():
|
298
|
-
LOG.info(
|
287
|
+
LOG.info('Loaded plugin %s', p.__class__.__name__)
|
299
288
|
|
300
289
|
stats = stats_thread.APRSDStatsStoreThread()
|
301
290
|
stats.start()
|
302
291
|
|
303
|
-
LOG.debug(
|
304
|
-
|
292
|
+
LOG.debug('Start APRSDRxThread')
|
293
|
+
rx_thread = rx.APRSDRXThread(packet_queue=threads.packet_queue)
|
294
|
+
rx_thread.start()
|
295
|
+
|
296
|
+
LOG.debug('Create APRSDListenProcessThread')
|
297
|
+
listen_thread = APRSDListenProcessThread(
|
305
298
|
packet_queue=threads.packet_queue,
|
306
299
|
packet_filter=packet_filter,
|
307
300
|
plugin_manager=pm,
|
308
301
|
enabled_plugins=enable_plugin,
|
309
302
|
log_packets=log_packets,
|
310
303
|
)
|
311
|
-
LOG.debug(
|
304
|
+
LOG.debug('Start APRSDListenProcessThread')
|
312
305
|
listen_thread.start()
|
313
306
|
if enable_packet_stats:
|
314
307
|
listen_stats = ListenStatsThread()
|
315
308
|
listen_stats.start()
|
316
309
|
|
317
310
|
keepalive_thread.start()
|
318
|
-
LOG.debug(
|
311
|
+
LOG.debug('keepalive Join')
|
319
312
|
keepalive_thread.join()
|
320
|
-
|
313
|
+
rx_thread.join()
|
321
314
|
listen_thread.join()
|
322
315
|
stats.join()
|
aprsd/cmds/send_message.py
CHANGED
@@ -3,58 +3,60 @@ import sys
|
|
3
3
|
import time
|
4
4
|
|
5
5
|
import aprslib
|
6
|
-
from aprslib.exceptions import LoginError
|
7
6
|
import click
|
7
|
+
from aprslib.exceptions import LoginError
|
8
8
|
from oslo_config import cfg
|
9
9
|
|
10
10
|
import aprsd
|
11
|
-
|
12
|
-
from aprsd import
|
11
|
+
import aprsd.packets # noqa : F401
|
12
|
+
from aprsd import (
|
13
|
+
cli_helper,
|
14
|
+
conf, # noqa : F401
|
15
|
+
packets,
|
16
|
+
)
|
13
17
|
from aprsd.client import client_factory
|
14
18
|
from aprsd.main import cli
|
15
|
-
import aprsd.packets # noqa : F401
|
16
19
|
from aprsd.packets import collector
|
17
20
|
from aprsd.packets import log as packet_log
|
18
21
|
from aprsd.threads import tx
|
19
22
|
|
20
|
-
|
21
23
|
CONF = cfg.CONF
|
22
|
-
LOG = logging.getLogger(
|
24
|
+
LOG = logging.getLogger('APRSD')
|
23
25
|
|
24
26
|
|
25
27
|
@cli.command()
|
26
28
|
@cli_helper.add_options(cli_helper.common_options)
|
27
29
|
@click.option(
|
28
|
-
|
29
|
-
envvar=
|
30
|
+
'--aprs-login',
|
31
|
+
envvar='APRS_LOGIN',
|
30
32
|
show_envvar=True,
|
31
|
-
help=
|
33
|
+
help='What callsign to send the message from. Defaults to config entry.',
|
32
34
|
)
|
33
35
|
@click.option(
|
34
|
-
|
35
|
-
envvar=
|
36
|
+
'--aprs-password',
|
37
|
+
envvar='APRS_PASSWORD',
|
36
38
|
show_envvar=True,
|
37
|
-
help=
|
39
|
+
help='the APRS-IS password for APRS_LOGIN. Defaults to config entry.',
|
38
40
|
)
|
39
41
|
@click.option(
|
40
|
-
|
41
|
-
|
42
|
+
'--no-ack',
|
43
|
+
'-n',
|
42
44
|
is_flag=True,
|
43
45
|
show_default=True,
|
44
46
|
default=False,
|
45
47
|
help="Don't wait for an ack, just sent it to APRS-IS and bail.",
|
46
48
|
)
|
47
49
|
@click.option(
|
48
|
-
|
49
|
-
|
50
|
+
'--wait-response',
|
51
|
+
'-w',
|
50
52
|
is_flag=True,
|
51
53
|
show_default=True,
|
52
54
|
default=False,
|
53
|
-
help=
|
55
|
+
help='Wait for a response to the message?',
|
54
56
|
)
|
55
|
-
@click.option(
|
56
|
-
@click.argument(
|
57
|
-
@click.argument(
|
57
|
+
@click.option('--raw', default=None, help='Send a raw message. Implies --no-ack')
|
58
|
+
@click.argument('tocallsign', required=True)
|
59
|
+
@click.argument('command', nargs=-1, required=True)
|
58
60
|
@click.pass_context
|
59
61
|
@cli_helper.process_standard_options
|
60
62
|
def send_message(
|
@@ -69,11 +71,11 @@ def send_message(
|
|
69
71
|
):
|
70
72
|
"""Send a message to a callsign via APRS_IS."""
|
71
73
|
global got_ack, got_response
|
72
|
-
quiet = ctx.obj[
|
74
|
+
quiet = ctx.obj['quiet']
|
73
75
|
|
74
76
|
if not aprs_login:
|
75
77
|
if CONF.aprs_network.login == conf.client.DEFAULT_LOGIN:
|
76
|
-
click.echo(
|
78
|
+
click.echo('Must set --aprs_login or APRS_LOGIN')
|
77
79
|
ctx.exit(-1)
|
78
80
|
return
|
79
81
|
else:
|
@@ -81,15 +83,15 @@ def send_message(
|
|
81
83
|
|
82
84
|
if not aprs_password:
|
83
85
|
if not CONF.aprs_network.password:
|
84
|
-
click.echo(
|
86
|
+
click.echo('Must set --aprs-password or APRS_PASSWORD')
|
85
87
|
ctx.exit(-1)
|
86
88
|
return
|
87
89
|
else:
|
88
90
|
aprs_password = CONF.aprs_network.password
|
89
91
|
|
90
|
-
LOG.info(f
|
92
|
+
LOG.info(f'APRSD LISTEN Started version: {aprsd.__version__}')
|
91
93
|
if type(command) is tuple:
|
92
|
-
command =
|
94
|
+
command = ' '.join(command)
|
93
95
|
if not quiet:
|
94
96
|
if raw:
|
95
97
|
LOG.info(f"L'{aprs_login}' R'{raw}'")
|
@@ -129,7 +131,7 @@ def send_message(
|
|
129
131
|
sys.exit(0)
|
130
132
|
|
131
133
|
try:
|
132
|
-
client_factory.create().client
|
134
|
+
client_factory.create().client # noqa: B018
|
133
135
|
except LoginError:
|
134
136
|
sys.exit(-1)
|
135
137
|
|
@@ -140,7 +142,7 @@ def send_message(
|
|
140
142
|
# message
|
141
143
|
if raw:
|
142
144
|
tx.send(
|
143
|
-
packets.Packet(from_call=
|
145
|
+
packets.Packet(from_call='', to_call='', raw=raw),
|
144
146
|
direct=True,
|
145
147
|
)
|
146
148
|
sys.exit(0)
|
@@ -164,7 +166,7 @@ def send_message(
|
|
164
166
|
aprs_client = client_factory.create().client
|
165
167
|
aprs_client.consumer(rx_packet, raw=False)
|
166
168
|
except aprslib.exceptions.ConnectionDrop:
|
167
|
-
LOG.error(
|
169
|
+
LOG.error('Connection dropped, reconnecting')
|
168
170
|
time.sleep(5)
|
169
171
|
# Force the deletion of the client object connected to aprs
|
170
172
|
# This will cause a reconnect, next time client.get_client()
|
aprsd/cmds/server.py
CHANGED
@@ -12,59 +12,24 @@ from aprsd.client import client_factory
|
|
12
12
|
from aprsd.main import cli
|
13
13
|
from aprsd.packets import collector as packet_collector
|
14
14
|
from aprsd.packets import seen_list
|
15
|
-
from aprsd.threads import
|
16
|
-
from aprsd.threads import keepalive, registry, rx, tx
|
15
|
+
from aprsd.threads import keepalive, registry, rx, service, tx
|
17
16
|
from aprsd.threads import stats as stats_thread
|
18
|
-
from aprsd.utils import singleton
|
19
17
|
|
20
18
|
CONF = cfg.CONF
|
21
|
-
LOG = logging.getLogger(
|
22
|
-
|
23
|
-
|
24
|
-
@singleton
|
25
|
-
class ServerThreads:
|
26
|
-
"""Registry for threads that the server command runs.
|
27
|
-
|
28
|
-
This enables extensions to register a thread to run during
|
29
|
-
the server command.
|
30
|
-
|
31
|
-
"""
|
32
|
-
|
33
|
-
def __init__(self):
|
34
|
-
self.threads: list[aprsd_threads.APRSDThread] = []
|
35
|
-
|
36
|
-
def register(self, thread: aprsd_threads.APRSDThread):
|
37
|
-
if not isinstance(thread, aprsd_threads.APRSDThread):
|
38
|
-
raise TypeError(f"Thread {thread} is not an APRSDThread")
|
39
|
-
self.threads.append(thread)
|
40
|
-
|
41
|
-
def unregister(self, thread: aprsd_threads.APRSDThread):
|
42
|
-
if not isinstance(thread, aprsd_threads.APRSDThread):
|
43
|
-
raise TypeError(f"Thread {thread} is not an APRSDThread")
|
44
|
-
self.threads.remove(thread)
|
45
|
-
|
46
|
-
def start(self):
|
47
|
-
"""Start all threads in the list."""
|
48
|
-
for thread in self.threads:
|
49
|
-
thread.start()
|
50
|
-
|
51
|
-
def join(self):
|
52
|
-
"""Join all the threads in the list"""
|
53
|
-
for thread in self.threads:
|
54
|
-
thread.join()
|
19
|
+
LOG = logging.getLogger('APRSD')
|
55
20
|
|
56
21
|
|
57
22
|
# main() ###
|
58
23
|
@cli.command()
|
59
24
|
@cli_helper.add_options(cli_helper.common_options)
|
60
25
|
@click.option(
|
61
|
-
|
62
|
-
|
63
|
-
|
26
|
+
'-f',
|
27
|
+
'--flush',
|
28
|
+
'flush',
|
64
29
|
is_flag=True,
|
65
30
|
show_default=True,
|
66
31
|
default=False,
|
67
|
-
help=
|
32
|
+
help='Flush out all old aged messages on disk.',
|
68
33
|
)
|
69
34
|
@click.pass_context
|
70
35
|
@cli_helper.process_standard_options
|
@@ -73,37 +38,37 @@ def server(ctx, flush):
|
|
73
38
|
signal.signal(signal.SIGINT, aprsd_main.signal_handler)
|
74
39
|
signal.signal(signal.SIGTERM, aprsd_main.signal_handler)
|
75
40
|
|
76
|
-
|
41
|
+
service_threads = service.ServiceThreads()
|
77
42
|
|
78
43
|
level, msg = utils._check_version()
|
79
44
|
if level:
|
80
45
|
LOG.warning(msg)
|
81
46
|
else:
|
82
47
|
LOG.info(msg)
|
83
|
-
LOG.info(f
|
48
|
+
LOG.info(f'APRSD Started version: {aprsd.__version__}')
|
84
49
|
|
85
50
|
# Initialize the client factory and create
|
86
51
|
# The correct client object ready for use
|
87
52
|
if not client_factory.is_client_enabled():
|
88
|
-
LOG.error(
|
53
|
+
LOG.error('No Clients are enabled in config.')
|
89
54
|
sys.exit(-1)
|
90
55
|
|
91
56
|
# Make sure we have 1 client transport enabled
|
92
57
|
if not client_factory.is_client_enabled():
|
93
|
-
LOG.error(
|
58
|
+
LOG.error('No Clients are enabled in config.')
|
94
59
|
sys.exit(-1)
|
95
60
|
|
96
61
|
if not client_factory.is_client_configured():
|
97
|
-
LOG.error(
|
62
|
+
LOG.error('APRS client is not properly configured in config file.')
|
98
63
|
sys.exit(-1)
|
99
64
|
|
100
65
|
# Creates the client object
|
101
|
-
LOG.info(
|
66
|
+
LOG.info('Creating client connection')
|
102
67
|
aprs_client = client_factory.create()
|
103
68
|
LOG.info(aprs_client)
|
104
69
|
if not aprs_client.login_success:
|
105
70
|
# We failed to login, will just quit!
|
106
|
-
msg = f
|
71
|
+
msg = f'Login Failure: {aprs_client.login_failure}'
|
107
72
|
LOG.error(msg)
|
108
73
|
print(msg)
|
109
74
|
sys.exit(-1)
|
@@ -114,7 +79,7 @@ def server(ctx, flush):
|
|
114
79
|
# We register plugins first here so we can register each
|
115
80
|
# plugins config options, so we can dump them all in the
|
116
81
|
# log file output.
|
117
|
-
LOG.info(
|
82
|
+
LOG.info('Loading Plugin Manager and registering plugins')
|
118
83
|
plugin_manager = plugin.PluginManager()
|
119
84
|
plugin_manager.setup_plugins(load_help_plugin=CONF.load_help_plugin)
|
120
85
|
|
@@ -122,10 +87,10 @@ def server(ctx, flush):
|
|
122
87
|
CONF.log_opt_values(LOG, logging.DEBUG)
|
123
88
|
message_plugins = plugin_manager.get_message_plugins()
|
124
89
|
watchlist_plugins = plugin_manager.get_watchlist_plugins()
|
125
|
-
LOG.info(
|
90
|
+
LOG.info('Message Plugins enabled and running:')
|
126
91
|
for p in message_plugins:
|
127
92
|
LOG.info(p)
|
128
|
-
LOG.info(
|
93
|
+
LOG.info('Watchlist Plugins enabled and running:')
|
129
94
|
for p in watchlist_plugins:
|
130
95
|
LOG.info(p)
|
131
96
|
|
@@ -135,37 +100,37 @@ def server(ctx, flush):
|
|
135
100
|
|
136
101
|
# Now load the msgTrack from disk if any
|
137
102
|
if flush:
|
138
|
-
LOG.debug(
|
103
|
+
LOG.debug('Flushing All packet tracking objects.')
|
139
104
|
packet_collector.PacketCollector().flush()
|
140
105
|
else:
|
141
106
|
# Try and load saved MsgTrack list
|
142
|
-
LOG.debug(
|
107
|
+
LOG.debug('Loading saved packet tracking data.')
|
143
108
|
packet_collector.PacketCollector().load()
|
144
109
|
|
145
110
|
# Now start all the main processing threads.
|
146
111
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
rx.
|
112
|
+
service_threads.register(keepalive.KeepAliveThread())
|
113
|
+
service_threads.register(stats_thread.APRSDStatsStoreThread())
|
114
|
+
service_threads.register(
|
115
|
+
rx.APRSDRXThread(
|
151
116
|
packet_queue=threads.packet_queue,
|
152
117
|
),
|
153
118
|
)
|
154
|
-
|
119
|
+
service_threads.register(
|
155
120
|
rx.APRSDPluginProcessPacketThread(
|
156
121
|
packet_queue=threads.packet_queue,
|
157
122
|
),
|
158
123
|
)
|
159
124
|
|
160
125
|
if CONF.enable_beacon:
|
161
|
-
LOG.info(
|
162
|
-
|
126
|
+
LOG.info('Beacon Enabled. Starting Beacon thread.')
|
127
|
+
service_threads.register(tx.BeaconSendThread())
|
163
128
|
|
164
129
|
if CONF.aprs_registry.enabled:
|
165
|
-
LOG.info(
|
166
|
-
|
130
|
+
LOG.info('Registry Enabled. Starting Registry thread.')
|
131
|
+
service_threads.register(registry.APRSRegistryThread())
|
167
132
|
|
168
|
-
|
169
|
-
|
133
|
+
service_threads.start()
|
134
|
+
service_threads.join()
|
170
135
|
|
171
136
|
return 0
|