aprsd 4.1.2__py3-none-any.whl → 4.2.0__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/client/__init__.py +5 -13
- aprsd/client/client.py +141 -0
- aprsd/client/drivers/__init__.py +10 -0
- aprsd/client/drivers/aprsis.py +174 -255
- aprsd/client/drivers/fake.py +59 -11
- aprsd/client/drivers/lib/__init__.py +0 -0
- aprsd/client/drivers/lib/aprslib.py +296 -0
- aprsd/client/drivers/registry.py +86 -0
- aprsd/client/drivers/tcpkiss.py +408 -0
- aprsd/client/stats.py +2 -2
- aprsd/cmds/dev.py +0 -3
- aprsd/cmds/listen.py +3 -3
- aprsd/cmds/send_message.py +4 -4
- aprsd/cmds/server.py +4 -10
- aprsd/log/log.py +1 -1
- aprsd/main.py +0 -7
- aprsd/packets/core.py +168 -169
- aprsd/packets/log.py +69 -59
- aprsd/plugin.py +3 -2
- aprsd/plugin_utils.py +2 -2
- aprsd/plugins/weather.py +2 -2
- aprsd/stats/collector.py +5 -4
- aprsd/threads/rx.py +12 -10
- aprsd/threads/tx.py +32 -31
- aprsd/utils/keepalive_collector.py +7 -5
- {aprsd-4.1.2.dist-info → aprsd-4.2.0.dist-info}/METADATA +48 -48
- {aprsd-4.1.2.dist-info → aprsd-4.2.0.dist-info}/RECORD +32 -33
- {aprsd-4.1.2.dist-info → aprsd-4.2.0.dist-info}/WHEEL +1 -1
- aprsd/client/aprsis.py +0 -183
- aprsd/client/base.py +0 -156
- aprsd/client/drivers/kiss.py +0 -144
- aprsd/client/factory.py +0 -91
- aprsd/client/fake.py +0 -49
- aprsd/client/kiss.py +0 -143
- {aprsd-4.1.2.dist-info → aprsd-4.2.0.dist-info}/entry_points.txt +0 -0
- {aprsd-4.1.2.dist-info → aprsd-4.2.0.dist-info/licenses}/AUTHORS +0 -0
- {aprsd-4.1.2.dist-info → aprsd-4.2.0.dist-info/licenses}/LICENSE +0 -0
- {aprsd-4.1.2.dist-info → aprsd-4.2.0.dist-info}/top_level.txt +0 -0
aprsd/packets/log.py
CHANGED
@@ -12,13 +12,13 @@ LOG = logging.getLogger()
|
|
12
12
|
LOGU = logger
|
13
13
|
CONF = cfg.CONF
|
14
14
|
|
15
|
-
FROM_COLOR =
|
16
|
-
TO_COLOR =
|
17
|
-
TX_COLOR =
|
18
|
-
RX_COLOR =
|
19
|
-
PACKET_COLOR =
|
20
|
-
DISTANCE_COLOR =
|
21
|
-
DEGREES_COLOR =
|
15
|
+
FROM_COLOR = 'fg #C70039'
|
16
|
+
TO_COLOR = 'fg #D033FF'
|
17
|
+
TX_COLOR = 'red'
|
18
|
+
RX_COLOR = 'green'
|
19
|
+
PACKET_COLOR = 'cyan'
|
20
|
+
DISTANCE_COLOR = 'fg #FF5733'
|
21
|
+
DEGREES_COLOR = 'fg #FFA900'
|
22
22
|
|
23
23
|
|
24
24
|
def log_multiline(
|
@@ -27,11 +27,11 @@ def log_multiline(
|
|
27
27
|
"""LOG a packet to the logfile."""
|
28
28
|
if not CONF.enable_packet_logging:
|
29
29
|
return
|
30
|
-
if CONF.log_packet_format ==
|
30
|
+
if CONF.log_packet_format == 'compact':
|
31
31
|
return
|
32
32
|
|
33
33
|
# asdict(packet)
|
34
|
-
logit = [
|
34
|
+
logit = ['\n']
|
35
35
|
name = packet.__class__.__name__
|
36
36
|
|
37
37
|
if isinstance(packet, AckPacket):
|
@@ -41,57 +41,67 @@ def log_multiline(
|
|
41
41
|
|
42
42
|
if header:
|
43
43
|
if tx:
|
44
|
-
header_str = f
|
44
|
+
header_str = f'<{TX_COLOR}>TX</{TX_COLOR}>'
|
45
45
|
logit.append(
|
46
|
-
f
|
47
|
-
f
|
46
|
+
f'{header_str}________(<{PACKET_COLOR}>{name}</{PACKET_COLOR}> '
|
47
|
+
f'TX:{packet.send_count + 1} of {pkt_max_send_count}',
|
48
48
|
)
|
49
49
|
else:
|
50
|
-
header_str = f
|
50
|
+
header_str = f'<{RX_COLOR}>RX</{RX_COLOR}>'
|
51
51
|
logit.append(
|
52
|
-
f
|
52
|
+
f'{header_str}________(<{PACKET_COLOR}>{name}</{PACKET_COLOR}>)',
|
53
53
|
)
|
54
54
|
|
55
55
|
else:
|
56
|
-
header_str =
|
57
|
-
logit.append(f
|
56
|
+
header_str = ''
|
57
|
+
logit.append(f'__________(<{PACKET_COLOR}>{name}</{PACKET_COLOR}>)')
|
58
58
|
# log_list.append(f" Packet : {packet.__class__.__name__}")
|
59
59
|
if packet.msgNo:
|
60
|
-
logit.append(f
|
60
|
+
logit.append(f' Msg # : {packet.msgNo}')
|
61
61
|
if packet.from_call:
|
62
|
-
logit.append(f
|
62
|
+
logit.append(f' From : <{FROM_COLOR}>{packet.from_call}</{FROM_COLOR}>')
|
63
63
|
if packet.to_call:
|
64
|
-
logit.append(f
|
65
|
-
if hasattr(packet,
|
66
|
-
logit.append(f
|
67
|
-
if hasattr(packet,
|
68
|
-
logit.append(f
|
64
|
+
logit.append(f' To : <{TO_COLOR}>{packet.to_call}</{TO_COLOR}>')
|
65
|
+
if hasattr(packet, 'path') and packet.path:
|
66
|
+
logit.append(f' Path : {"=>".join(packet.path)}')
|
67
|
+
if hasattr(packet, 'via') and packet.via:
|
68
|
+
logit.append(f' VIA : {packet.via}')
|
69
69
|
|
70
70
|
if not isinstance(packet, AckPacket) and not isinstance(packet, RejectPacket):
|
71
71
|
msg = packet.human_info
|
72
72
|
|
73
73
|
if msg:
|
74
|
-
msg = msg.replace(
|
75
|
-
logit.append(f
|
74
|
+
msg = msg.replace('<', '\\<')
|
75
|
+
logit.append(f' Info : <light-yellow><b>{msg}</b></light-yellow>')
|
76
76
|
|
77
|
-
if hasattr(packet,
|
78
|
-
logit.append(f
|
77
|
+
if hasattr(packet, 'comment') and packet.comment:
|
78
|
+
logit.append(f' Comment : {packet.comment}')
|
79
79
|
|
80
|
-
raw = packet.raw.replace(
|
81
|
-
logit.append(f
|
82
|
-
logit.append(f
|
80
|
+
raw = packet.raw.replace('<', '\\<')
|
81
|
+
logit.append(f' Raw : <fg #828282>{raw}</fg #828282>')
|
82
|
+
logit.append(f'{header_str}________(<{PACKET_COLOR}>{name}</{PACKET_COLOR}>)')
|
83
83
|
|
84
|
-
LOGU.opt(colors=True).info(
|
84
|
+
LOGU.opt(colors=True).info('\n'.join(logit))
|
85
85
|
LOG.debug(repr(packet))
|
86
86
|
|
87
87
|
|
88
|
-
def log(
|
88
|
+
def log(
|
89
|
+
packet,
|
90
|
+
tx: Optional[bool] = False,
|
91
|
+
header: Optional[bool] = True,
|
92
|
+
packet_count: Optional[int] = None,
|
93
|
+
) -> None:
|
89
94
|
if not CONF.enable_packet_logging:
|
90
95
|
return
|
91
|
-
if CONF.log_packet_format ==
|
96
|
+
if CONF.log_packet_format == 'multiline':
|
92
97
|
log_multiline(packet, tx, header)
|
93
98
|
return
|
94
99
|
|
100
|
+
if not packet_count:
|
101
|
+
packet_count = ''
|
102
|
+
else:
|
103
|
+
packet_count = f'({packet_count:d})'
|
104
|
+
|
95
105
|
logit = []
|
96
106
|
name = packet.__class__.__name__
|
97
107
|
if isinstance(packet, AckPacket):
|
@@ -101,47 +111,47 @@ def log(packet, tx: Optional[bool] = False, header: Optional[bool] = True) -> No
|
|
101
111
|
|
102
112
|
if header:
|
103
113
|
if tx:
|
104
|
-
via_color =
|
105
|
-
arrow = f
|
114
|
+
via_color = 'red'
|
115
|
+
arrow = f'<{via_color}>\u2192</{via_color}>'
|
106
116
|
logit.append(
|
107
|
-
f
|
108
|
-
f
|
109
|
-
f
|
110
|
-
f
|
117
|
+
f'<red>TX{packet_count}\u2191</red> '
|
118
|
+
f'<cyan>{name}</cyan>'
|
119
|
+
f':{packet.msgNo}'
|
120
|
+
f' ({packet.send_count + 1} of {pkt_max_send_count})',
|
111
121
|
)
|
112
122
|
else:
|
113
|
-
via_color =
|
114
|
-
arrow = f
|
115
|
-
f
|
123
|
+
via_color = 'fg #1AA730'
|
124
|
+
arrow = f'<{via_color}>\u2192</{via_color}>'
|
125
|
+
f'<{via_color}><-</{via_color}>'
|
116
126
|
logit.append(
|
117
|
-
f
|
118
|
-
f
|
119
|
-
f
|
127
|
+
f'<fg #1AA730>RX{packet_count}\u2193</fg #1AA730> '
|
128
|
+
f'<cyan>{name}</cyan>'
|
129
|
+
f':{packet.msgNo}',
|
120
130
|
)
|
121
131
|
else:
|
122
|
-
via_color =
|
123
|
-
arrow = f
|
132
|
+
via_color = 'green'
|
133
|
+
arrow = f'<{via_color}>-></{via_color}>'
|
124
134
|
logit.append(
|
125
|
-
f
|
135
|
+
f'<cyan>{name}</cyan>:{packet.msgNo}',
|
126
136
|
)
|
127
137
|
|
128
138
|
tmp = None
|
129
139
|
if packet.path:
|
130
|
-
tmp = f
|
140
|
+
tmp = f'{arrow}'.join(packet.path) + f'{arrow} '
|
131
141
|
|
132
142
|
logit.append(
|
133
|
-
f
|
134
|
-
f
|
135
|
-
f
|
143
|
+
f'<{FROM_COLOR}>{packet.from_call}</{FROM_COLOR}> {arrow}'
|
144
|
+
f'{tmp if tmp else " "}'
|
145
|
+
f'<{TO_COLOR}>{packet.to_call}</{TO_COLOR}>',
|
136
146
|
)
|
137
147
|
|
138
148
|
if not isinstance(packet, AckPacket) and not isinstance(packet, RejectPacket):
|
139
|
-
logit.append(
|
149
|
+
logit.append(':')
|
140
150
|
msg = packet.human_info
|
141
151
|
|
142
152
|
if msg:
|
143
|
-
msg = msg.replace(
|
144
|
-
logit.append(f
|
153
|
+
msg = msg.replace('<', '\\<')
|
154
|
+
logit.append(f'<light-yellow><b>{msg}</b></light-yellow>')
|
145
155
|
|
146
156
|
# is there distance information?
|
147
157
|
if isinstance(packet, GPSPacket) and CONF.latitude and CONF.longitude:
|
@@ -150,12 +160,12 @@ def log(packet, tx: Optional[bool] = False, header: Optional[bool] = True) -> No
|
|
150
160
|
try:
|
151
161
|
bearing = utils.calculate_initial_compass_bearing(my_coords, packet_coords)
|
152
162
|
except Exception as e:
|
153
|
-
LOG.error(f
|
163
|
+
LOG.error(f'Failed to calculate bearing: {e}')
|
154
164
|
bearing = 0
|
155
165
|
logit.append(
|
156
|
-
f
|
157
|
-
f
|
166
|
+
f' : <{DEGREES_COLOR}>{utils.degrees_to_cardinal(bearing, full_string=True)}</{DEGREES_COLOR}>'
|
167
|
+
f'<{DISTANCE_COLOR}>@{haversine(my_coords, packet_coords, unit=Unit.MILES):.2f}miles</{DISTANCE_COLOR}>',
|
158
168
|
)
|
159
169
|
|
160
|
-
LOGU.opt(colors=True).info(
|
170
|
+
LOGU.opt(colors=True).info(' '.join(logit))
|
161
171
|
log_multiline(packet, tx, header)
|
aprsd/plugin.py
CHANGED
@@ -12,7 +12,8 @@ import pluggy
|
|
12
12
|
from oslo_config import cfg
|
13
13
|
|
14
14
|
import aprsd
|
15
|
-
from aprsd import
|
15
|
+
from aprsd import packets, threads
|
16
|
+
from aprsd.client.client import APRSDClient
|
16
17
|
from aprsd.packets import watch_list
|
17
18
|
|
18
19
|
# setup the global logger
|
@@ -146,7 +147,7 @@ class APRSDWatchListPluginBase(APRSDPluginBase, metaclass=abc.ABCMeta):
|
|
146
147
|
watch_list = CONF.watch_list.callsigns
|
147
148
|
# make sure the timeout is set or this doesn't work
|
148
149
|
if watch_list:
|
149
|
-
aprs_client =
|
150
|
+
aprs_client = APRSDClient()
|
150
151
|
filter_str = 'b/{}'.format('/'.join(watch_list))
|
151
152
|
aprs_client.set_filter(filter_str)
|
152
153
|
else:
|
aprsd/plugin_utils.py
CHANGED
@@ -66,8 +66,8 @@ def fetch_openweathermap(api_key, lat, lon, units='metric', exclude=None):
|
|
66
66
|
exclude = 'minutely,hourly,daily,alerts'
|
67
67
|
try:
|
68
68
|
url = (
|
69
|
-
|
70
|
-
|
69
|
+
"https://api.openweathermap.org/data/3.0/onecall?"
|
70
|
+
"lat={}&lon={}&appid={}&units={}&exclude={}".format(
|
71
71
|
lat,
|
72
72
|
lon,
|
73
73
|
api_key,
|
aprsd/plugins/weather.py
CHANGED
@@ -323,8 +323,8 @@ class AVWXWeatherPlugin(plugin.APRSDRegexCommandPluginBase):
|
|
323
323
|
elif not CONF.avwx_plugin.apiKey:
|
324
324
|
LOG.error('Config avwx_plugin.apiKey not specified. Disabling')
|
325
325
|
return False
|
326
|
-
|
327
|
-
|
326
|
+
|
327
|
+
self.enabled = True
|
328
328
|
|
329
329
|
def help(self):
|
330
330
|
_help = [
|
aprsd/stats/collector.py
CHANGED
@@ -3,7 +3,7 @@ from typing import Callable, Protocol, runtime_checkable
|
|
3
3
|
|
4
4
|
from aprsd.utils import singleton
|
5
5
|
|
6
|
-
LOG = logging.getLogger(
|
6
|
+
LOG = logging.getLogger('APRSD')
|
7
7
|
|
8
8
|
|
9
9
|
@runtime_checkable
|
@@ -31,15 +31,16 @@ class Collector:
|
|
31
31
|
serializable=serializable
|
32
32
|
).copy()
|
33
33
|
except Exception as e:
|
34
|
-
LOG.error(f
|
34
|
+
LOG.error(f'Error in producer {name} (stats): {e}')
|
35
|
+
raise e
|
35
36
|
return stats
|
36
37
|
|
37
38
|
def register_producer(self, producer_name: Callable):
|
38
39
|
if not isinstance(producer_name, StatsProducer):
|
39
|
-
raise TypeError(f
|
40
|
+
raise TypeError(f'Producer {producer_name} is not a StatsProducer')
|
40
41
|
self.producers.append(producer_name)
|
41
42
|
|
42
43
|
def unregister_producer(self, producer_name: Callable):
|
43
44
|
if not isinstance(producer_name, StatsProducer):
|
44
|
-
raise TypeError(f
|
45
|
+
raise TypeError(f'Producer {producer_name} is not a StatsProducer')
|
45
46
|
self.producers.remove(producer_name)
|
aprsd/threads/rx.py
CHANGED
@@ -7,7 +7,7 @@ import aprslib
|
|
7
7
|
from oslo_config import cfg
|
8
8
|
|
9
9
|
from aprsd import packets, plugin
|
10
|
-
from aprsd.client import
|
10
|
+
from aprsd.client.client import APRSDClient
|
11
11
|
from aprsd.packets import collector, filter
|
12
12
|
from aprsd.packets import log as packet_log
|
13
13
|
from aprsd.threads import APRSDThread, tx
|
@@ -32,6 +32,8 @@ class APRSDRXThread(APRSDThread):
|
|
32
32
|
# getting blocked by the APRS server trying to send us packets.
|
33
33
|
packet_queue = None
|
34
34
|
|
35
|
+
pkt_count = 0
|
36
|
+
|
35
37
|
def __init__(self, packet_queue):
|
36
38
|
super().__init__('RX_PKT')
|
37
39
|
self.packet_queue = packet_queue
|
@@ -39,16 +41,16 @@ class APRSDRXThread(APRSDThread):
|
|
39
41
|
def stop(self):
|
40
42
|
self.thread_stop = True
|
41
43
|
if self._client:
|
42
|
-
self._client.
|
44
|
+
self._client.close()
|
43
45
|
|
44
46
|
def loop(self):
|
45
47
|
if not self._client:
|
46
|
-
self._client =
|
48
|
+
self._client = APRSDClient()
|
47
49
|
time.sleep(1)
|
48
50
|
return True
|
49
51
|
|
50
|
-
if not self._client.
|
51
|
-
self._client =
|
52
|
+
if not self._client.is_alive:
|
53
|
+
self._client = APRSDClient()
|
52
54
|
time.sleep(1)
|
53
55
|
return True
|
54
56
|
|
@@ -66,7 +68,6 @@ class APRSDRXThread(APRSDThread):
|
|
66
68
|
self._client.consumer(
|
67
69
|
self.process_packet,
|
68
70
|
raw=False,
|
69
|
-
blocking=False,
|
70
71
|
)
|
71
72
|
except (
|
72
73
|
aprslib.exceptions.ConnectionDrop,
|
@@ -78,8 +79,8 @@ class APRSDRXThread(APRSDThread):
|
|
78
79
|
# is called
|
79
80
|
self._client.reset()
|
80
81
|
time.sleep(5)
|
81
|
-
except Exception:
|
82
|
-
|
82
|
+
except Exception as ex:
|
83
|
+
LOG.exception(ex)
|
83
84
|
LOG.error('Resetting connection and trying again.')
|
84
85
|
self._client.reset()
|
85
86
|
time.sleep(5)
|
@@ -92,7 +93,8 @@ class APRSDRXThread(APRSDThread):
|
|
92
93
|
'No packet received from decode_packet. Most likely a failure to parse'
|
93
94
|
)
|
94
95
|
return
|
95
|
-
|
96
|
+
self.pkt_count += 1
|
97
|
+
packet_log.log(packet, packet_count=self.pkt_count)
|
96
98
|
pkt_list = packets.PacketList()
|
97
99
|
|
98
100
|
if isinstance(packet, packets.AckPacket):
|
@@ -216,7 +218,7 @@ class APRSDProcessPacketThread(APRSDFilterThread):
|
|
216
218
|
our_call = CONF.callsign.lower()
|
217
219
|
|
218
220
|
from_call = packet.from_call
|
219
|
-
if packet.addresse:
|
221
|
+
if hasattr(packet, 'addresse') and packet.addresse:
|
220
222
|
to_call = packet.addresse
|
221
223
|
else:
|
222
224
|
to_call = packet.to_call
|
aprsd/threads/tx.py
CHANGED
@@ -11,12 +11,12 @@ from rush.stores import dictionary
|
|
11
11
|
|
12
12
|
from aprsd import conf # noqa
|
13
13
|
from aprsd import threads as aprsd_threads
|
14
|
-
from aprsd.client import
|
14
|
+
from aprsd.client.client import APRSDClient
|
15
15
|
from aprsd.packets import collector, core, tracker
|
16
16
|
from aprsd.packets import log as packet_log
|
17
17
|
|
18
18
|
CONF = cfg.CONF
|
19
|
-
LOG = logging.getLogger(
|
19
|
+
LOG = logging.getLogger('APRSD')
|
20
20
|
|
21
21
|
msg_t = throttle.Throttle(
|
22
22
|
limiter=periodic.PeriodicLimiter(
|
@@ -54,7 +54,7 @@ def send(packet: core.Packet, direct=False, aprs_client=None):
|
|
54
54
|
if CONF.enable_sending_ack_packets:
|
55
55
|
_send_ack(packet, direct=direct, aprs_client=aprs_client)
|
56
56
|
else:
|
57
|
-
LOG.info(
|
57
|
+
LOG.info('Sending ack packets is disabled. Not sending AckPacket.')
|
58
58
|
else:
|
59
59
|
_send_packet(packet, direct=direct, aprs_client=aprs_client)
|
60
60
|
|
@@ -81,14 +81,14 @@ def _send_direct(packet, aprs_client=None):
|
|
81
81
|
if aprs_client:
|
82
82
|
cl = aprs_client
|
83
83
|
else:
|
84
|
-
cl =
|
84
|
+
cl = APRSDClient()
|
85
85
|
|
86
86
|
packet.update_timestamp()
|
87
87
|
packet_log.log(packet, tx=True)
|
88
88
|
try:
|
89
89
|
cl.send(packet)
|
90
90
|
except Exception as e:
|
91
|
-
LOG.error(f
|
91
|
+
LOG.error(f'Failed to send packet: {packet}')
|
92
92
|
LOG.error(e)
|
93
93
|
return False
|
94
94
|
else:
|
@@ -100,7 +100,7 @@ class SendPacketThread(aprsd_threads.APRSDThread):
|
|
100
100
|
|
101
101
|
def __init__(self, packet):
|
102
102
|
self.packet = packet
|
103
|
-
super().__init__(f
|
103
|
+
super().__init__(f'TX-{packet.to_call}-{self.packet.msgNo}')
|
104
104
|
|
105
105
|
def loop(self):
|
106
106
|
"""Loop until a message is acked or it gets delayed.
|
@@ -119,9 +119,9 @@ class SendPacketThread(aprsd_threads.APRSDThread):
|
|
119
119
|
# The message has been removed from the tracking queue
|
120
120
|
# So it got acked and we are done.
|
121
121
|
LOG.info(
|
122
|
-
f
|
123
|
-
f
|
124
|
-
|
122
|
+
f'{self.packet.__class__.__name__}'
|
123
|
+
f'({self.packet.msgNo}) '
|
124
|
+
'Message Send Complete via Ack.',
|
125
125
|
)
|
126
126
|
return False
|
127
127
|
else:
|
@@ -130,10 +130,10 @@ class SendPacketThread(aprsd_threads.APRSDThread):
|
|
130
130
|
# we reached the send limit, don't send again
|
131
131
|
# TODO(hemna) - Need to put this in a delayed queue?
|
132
132
|
LOG.info(
|
133
|
-
f
|
134
|
-
f
|
135
|
-
|
136
|
-
f
|
133
|
+
f'{packet.__class__.__name__} '
|
134
|
+
f'({packet.msgNo}) '
|
135
|
+
'Message Send Complete. Max attempts reached'
|
136
|
+
f' {packet.retry_count}',
|
137
137
|
)
|
138
138
|
pkt_tracker.remove(packet.msgNo)
|
139
139
|
return False
|
@@ -157,8 +157,9 @@ class SendPacketThread(aprsd_threads.APRSDThread):
|
|
157
157
|
sent = False
|
158
158
|
try:
|
159
159
|
sent = _send_direct(packet)
|
160
|
-
except Exception:
|
161
|
-
LOG.error(f
|
160
|
+
except Exception as ex:
|
161
|
+
LOG.error(f'Failed to send packet: {packet}')
|
162
|
+
LOG.error(ex)
|
162
163
|
else:
|
163
164
|
# If an exception happens while sending
|
164
165
|
# we don't want this attempt to count
|
@@ -178,7 +179,7 @@ class SendAckThread(aprsd_threads.APRSDThread):
|
|
178
179
|
|
179
180
|
def __init__(self, packet):
|
180
181
|
self.packet = packet
|
181
|
-
super().__init__(f
|
182
|
+
super().__init__(f'TXAck-{packet.to_call}-{self.packet.msgNo}')
|
182
183
|
self.max_retries = CONF.default_ack_send_count
|
183
184
|
|
184
185
|
def loop(self):
|
@@ -188,10 +189,10 @@ class SendAckThread(aprsd_threads.APRSDThread):
|
|
188
189
|
# we reached the send limit, don't send again
|
189
190
|
# TODO(hemna) - Need to put this in a delayed queue?
|
190
191
|
LOG.debug(
|
191
|
-
f
|
192
|
-
f
|
193
|
-
|
194
|
-
f
|
192
|
+
f'{self.packet.__class__.__name__}'
|
193
|
+
f'({self.packet.msgNo}) '
|
194
|
+
'Send Complete. Max attempts reached'
|
195
|
+
f' {self.max_retries}',
|
195
196
|
)
|
196
197
|
return False
|
197
198
|
|
@@ -207,7 +208,7 @@ class SendAckThread(aprsd_threads.APRSDThread):
|
|
207
208
|
# It's time to try to send it again
|
208
209
|
send_now = True
|
209
210
|
elif self.loop_count % 10 == 0:
|
210
|
-
LOG.debug(f
|
211
|
+
LOG.debug(f'Still wating. {delta}')
|
211
212
|
else:
|
212
213
|
send_now = True
|
213
214
|
|
@@ -216,7 +217,7 @@ class SendAckThread(aprsd_threads.APRSDThread):
|
|
216
217
|
try:
|
217
218
|
sent = _send_direct(self.packet)
|
218
219
|
except Exception:
|
219
|
-
LOG.error(f
|
220
|
+
LOG.error(f'Failed to send packet: {self.packet}')
|
220
221
|
else:
|
221
222
|
# If an exception happens while sending
|
222
223
|
# we don't want this attempt to count
|
@@ -240,18 +241,18 @@ class BeaconSendThread(aprsd_threads.APRSDThread):
|
|
240
241
|
_loop_cnt: int = 1
|
241
242
|
|
242
243
|
def __init__(self):
|
243
|
-
super().__init__(
|
244
|
+
super().__init__('BeaconSendThread')
|
244
245
|
self._loop_cnt = 1
|
245
246
|
# Make sure Latitude and Longitude are set.
|
246
247
|
if not CONF.latitude or not CONF.longitude:
|
247
248
|
LOG.error(
|
248
|
-
|
249
|
-
|
249
|
+
'Latitude and Longitude are not set in the config file.'
|
250
|
+
'Beacon will not be sent and thread is STOPPED.',
|
250
251
|
)
|
251
252
|
self.stop()
|
252
253
|
LOG.info(
|
253
|
-
|
254
|
-
f
|
254
|
+
'Beacon thread is running and will send '
|
255
|
+
f'beacons every {CONF.beacon_interval} seconds.',
|
255
256
|
)
|
256
257
|
|
257
258
|
def loop(self):
|
@@ -259,10 +260,10 @@ class BeaconSendThread(aprsd_threads.APRSDThread):
|
|
259
260
|
if self._loop_cnt % CONF.beacon_interval == 0:
|
260
261
|
pkt = core.BeaconPacket(
|
261
262
|
from_call=CONF.callsign,
|
262
|
-
to_call=
|
263
|
+
to_call='APRS',
|
263
264
|
latitude=float(CONF.latitude),
|
264
265
|
longitude=float(CONF.longitude),
|
265
|
-
comment=
|
266
|
+
comment='APRSD GPS Beacon',
|
266
267
|
symbol=CONF.beacon_symbol,
|
267
268
|
)
|
268
269
|
try:
|
@@ -270,8 +271,8 @@ class BeaconSendThread(aprsd_threads.APRSDThread):
|
|
270
271
|
pkt.retry_count = 1
|
271
272
|
send(pkt, direct=True)
|
272
273
|
except Exception as e:
|
273
|
-
LOG.error(f
|
274
|
-
|
274
|
+
LOG.error(f'Failed to send beacon: {e}')
|
275
|
+
APRSDClient().reset()
|
275
276
|
time.sleep(5)
|
276
277
|
|
277
278
|
self._loop_cnt += 1
|
@@ -3,7 +3,7 @@ from typing import Callable, Protocol, runtime_checkable
|
|
3
3
|
|
4
4
|
from aprsd.utils import singleton
|
5
5
|
|
6
|
-
LOG = logging.getLogger(
|
6
|
+
LOG = logging.getLogger('APRSD')
|
7
7
|
|
8
8
|
|
9
9
|
@runtime_checkable
|
@@ -33,7 +33,8 @@ class KeepAliveCollector:
|
|
33
33
|
try:
|
34
34
|
cls.keepalive_check()
|
35
35
|
except Exception as e:
|
36
|
-
LOG.error(f
|
36
|
+
LOG.error(f'Error in producer {name} (check): {e}')
|
37
|
+
raise e
|
37
38
|
|
38
39
|
def log(self) -> None:
|
39
40
|
"""Log any relevant information during a KeepAlive check"""
|
@@ -42,14 +43,15 @@ class KeepAliveCollector:
|
|
42
43
|
try:
|
43
44
|
cls.keepalive_log()
|
44
45
|
except Exception as e:
|
45
|
-
LOG.error(f
|
46
|
+
LOG.error(f'Error in producer {name} (check): {e}')
|
47
|
+
raise e
|
46
48
|
|
47
49
|
def register(self, producer_name: Callable):
|
48
50
|
if not isinstance(producer_name, KeepAliveProducer):
|
49
|
-
raise TypeError(f
|
51
|
+
raise TypeError(f'Producer {producer_name} is not a KeepAliveProducer')
|
50
52
|
self.producers.append(producer_name)
|
51
53
|
|
52
54
|
def unregister(self, producer_name: Callable):
|
53
55
|
if not isinstance(producer_name, KeepAliveProducer):
|
54
|
-
raise TypeError(f
|
56
|
+
raise TypeError(f'Producer {producer_name} is not a KeepAliveProducer')
|
55
57
|
self.producers.remove(producer_name)
|