aprsd 4.1.1__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/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 = "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"
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 == "compact":
30
+ if CONF.log_packet_format == 'compact':
31
31
  return
32
32
 
33
33
  # asdict(packet)
34
- logit = ["\n"]
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"<{TX_COLOR}>TX</{TX_COLOR}>"
44
+ header_str = f'<{TX_COLOR}>TX</{TX_COLOR}>'
45
45
  logit.append(
46
- f"{header_str}________(<{PACKET_COLOR}>{name}</{PACKET_COLOR}> "
47
- f"TX:{packet.send_count + 1} of {pkt_max_send_count}",
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"<{RX_COLOR}>RX</{RX_COLOR}>"
50
+ header_str = f'<{RX_COLOR}>RX</{RX_COLOR}>'
51
51
  logit.append(
52
- f"{header_str}________(<{PACKET_COLOR}>{name}</{PACKET_COLOR}>)",
52
+ f'{header_str}________(<{PACKET_COLOR}>{name}</{PACKET_COLOR}>)',
53
53
  )
54
54
 
55
55
  else:
56
- header_str = ""
57
- logit.append(f"__________(<{PACKET_COLOR}>{name}</{PACKET_COLOR}>)")
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" Msg # : {packet.msgNo}")
60
+ logit.append(f' Msg # : {packet.msgNo}')
61
61
  if packet.from_call:
62
- logit.append(f" From : <{FROM_COLOR}>{packet.from_call}</{FROM_COLOR}>")
62
+ logit.append(f' From : <{FROM_COLOR}>{packet.from_call}</{FROM_COLOR}>')
63
63
  if packet.to_call:
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}")
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" Info : <light-yellow><b>{msg}</b></light-yellow>")
74
+ msg = msg.replace('<', '\\<')
75
+ logit.append(f' Info : <light-yellow><b>{msg}</b></light-yellow>')
76
76
 
77
- if hasattr(packet, "comment") and packet.comment:
78
- logit.append(f" Comment : {packet.comment}")
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" Raw : <fg #828282>{raw}</fg #828282>")
82
- logit.append(f"{header_str}________(<{PACKET_COLOR}>{name}</{PACKET_COLOR}>)")
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("\n".join(logit))
84
+ LOGU.opt(colors=True).info('\n'.join(logit))
85
85
  LOG.debug(repr(packet))
86
86
 
87
87
 
88
- def log(packet, tx: Optional[bool] = False, header: Optional[bool] = True) -> None:
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 == "multiline":
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 = "red"
105
- arrow = f"<{via_color}>\u2192</{via_color}>"
114
+ via_color = 'red'
115
+ arrow = f'<{via_color}>\u2192</{via_color}>'
106
116
  logit.append(
107
- f"<red>TX\u2191</red> "
108
- f"<cyan>{name}</cyan>"
109
- f":{packet.msgNo}"
110
- f" ({packet.send_count + 1} of {pkt_max_send_count})",
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 = "fg #1AA730"
114
- arrow = f"<{via_color}>\u2192</{via_color}>"
115
- f"<{via_color}><-</{via_color}>"
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"<fg #1AA730>RX\u2193</fg #1AA730> "
118
- f"<cyan>{name}</cyan>"
119
- f":{packet.msgNo}",
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 = "green"
123
- arrow = f"<{via_color}>-></{via_color}>"
132
+ via_color = 'green'
133
+ arrow = f'<{via_color}>-></{via_color}>'
124
134
  logit.append(
125
- f"<cyan>{name}</cyan>" f":{packet.msgNo}",
135
+ f'<cyan>{name}</cyan>:{packet.msgNo}',
126
136
  )
127
137
 
128
138
  tmp = None
129
139
  if packet.path:
130
- tmp = f"{arrow}".join(packet.path) + f"{arrow} "
140
+ tmp = f'{arrow}'.join(packet.path) + f'{arrow} '
131
141
 
132
142
  logit.append(
133
- f"<{FROM_COLOR}>{packet.from_call}</{FROM_COLOR}> {arrow}"
134
- f"{tmp if tmp else ' '}"
135
- f"<{TO_COLOR}>{packet.to_call}</{TO_COLOR}>",
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"<light-yellow><b>{msg}</b></light-yellow>")
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"Failed to calculate bearing: {e}")
163
+ LOG.error(f'Failed to calculate bearing: {e}')
154
164
  bearing = 0
155
165
  logit.append(
156
- f" : <{DEGREES_COLOR}>{utils.degrees_to_cardinal(bearing, full_string=True)}</{DEGREES_COLOR}>"
157
- f"<{DISTANCE_COLOR}>@{haversine(my_coords, packet_coords, unit=Unit.MILES):.2f}miles</{DISTANCE_COLOR}>",
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(" ".join(logit))
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 client, packets, threads
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 = client.client_factory.create().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
- 'https://api.openweathermap.org/data/2.5/onecall?'
70
- 'lat={}&lon={}&appid={}&units={}&exclude={}'.format(
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
- else:
327
- return True
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("APRSD")
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"Error in producer {name} (stats): {e}")
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"Producer {producer_name} is not a StatsProducer")
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"Producer {producer_name} is not a StatsProducer")
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 client_factory
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.stop()
44
+ self._client.close()
43
45
 
44
46
  def loop(self):
45
47
  if not self._client:
46
- self._client = client_factory.create()
48
+ self._client = APRSDClient()
47
49
  time.sleep(1)
48
50
  return True
49
51
 
50
- if not self._client.is_connected:
51
- self._client = client_factory.create()
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
- # LOG.exception(ex)
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
- packet_log.log(packet)
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 client_factory
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("APRSD")
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("Sending ack packets is disabled. Not sending AckPacket.")
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 = client_factory.create()
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"Failed to send packet: {packet}")
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"TX-{packet.to_call}-{self.packet.msgNo}")
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"{self.packet.__class__.__name__}"
123
- f"({self.packet.msgNo}) "
124
- "Message Send Complete via Ack.",
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"{packet.__class__.__name__} "
134
- f"({packet.msgNo}) "
135
- "Message Send Complete. Max attempts reached"
136
- f" {packet.retry_count}",
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"Failed to send packet: {packet}")
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"TXAck-{packet.to_call}-{self.packet.msgNo}")
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"{self.packet.__class__.__name__}"
192
- f"({self.packet.msgNo}) "
193
- "Send Complete. Max attempts reached"
194
- f" {self.max_retries}",
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"Still wating. {delta}")
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"Failed to send packet: {self.packet}")
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__("BeaconSendThread")
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
- "Latitude and Longitude are not set in the config file."
249
- "Beacon will not be sent and thread is STOPPED.",
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
- "Beacon thread is running and will send "
254
- f"beacons every {CONF.beacon_interval} seconds.",
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="APRS",
263
+ to_call='APRS',
263
264
  latitude=float(CONF.latitude),
264
265
  longitude=float(CONF.longitude),
265
- comment="APRSD GPS Beacon",
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"Failed to send beacon: {e}")
274
- client_factory.create().reset()
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("APRSD")
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"Error in producer {name} (check): {e}")
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"Error in producer {name} (check): {e}")
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"Producer {producer_name} is not a KeepAliveProducer")
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"Producer {producer_name} is not a KeepAliveProducer")
56
+ raise TypeError(f'Producer {producer_name} is not a KeepAliveProducer')
55
57
  self.producers.remove(producer_name)