aprsd 4.2.0__py3-none-any.whl → 4.2.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/client/client.py CHANGED
@@ -38,15 +38,16 @@ class APRSDClient:
38
38
  keepalive_collector.KeepAliveCollector().register(cls)
39
39
  return cls._instance
40
40
 
41
- def __init__(self):
41
+ def __init__(self, auto_connect: bool = True):
42
+ self.auto_connect = auto_connect
42
43
  self.connected = False
43
44
  self.login_status = {
44
45
  'success': False,
45
46
  'message': None,
46
47
  }
47
- if not self.driver:
48
- self.driver = DriverRegistry().get_driver()
49
- self.driver.setup_connection()
48
+ self.driver = DriverRegistry().get_driver()
49
+ if self.auto_connect:
50
+ self.connect()
50
51
 
51
52
  def stats(self, serializable=False) -> dict:
52
53
  stats = {}
@@ -54,17 +55,20 @@ class APRSDClient:
54
55
  stats = self.driver.stats(serializable=serializable)
55
56
  return stats
56
57
 
57
- @property
58
- def is_enabled(self):
59
- if not self.driver:
60
- return False
61
- return self.driver.is_enabled()
62
-
63
- @property
64
- def is_configured(self):
65
- if not self.driver:
66
- return False
67
- return self.driver.is_configured()
58
+ @staticmethod
59
+ def is_enabled():
60
+ for driver in DriverRegistry().drivers:
61
+ if driver.is_enabled():
62
+ return True
63
+ return False
64
+
65
+ @staticmethod
66
+ def is_configured():
67
+ """Check if ANY driver is configured."""
68
+ for driver in DriverRegistry().drivers:
69
+ if driver.is_configured():
70
+ return True
71
+ return False
68
72
 
69
73
  # @property
70
74
  # def is_connected(self):
@@ -98,6 +102,11 @@ class APRSDClient:
98
102
  def is_alive(self):
99
103
  return self.driver.is_alive()
100
104
 
105
+ def connect(self):
106
+ if not self.driver:
107
+ self.driver = DriverRegistry().get_driver()
108
+ self.driver.setup_connection()
109
+
101
110
  def close(self):
102
111
  if not self.driver:
103
112
  return
@@ -109,7 +118,8 @@ class APRSDClient:
109
118
  LOG.info('Resetting client connection.')
110
119
  if self.driver:
111
120
  self.driver.close()
112
- self.driver.setup_connection()
121
+ if not self.delay_connect:
122
+ self.driver.setup_connection()
113
123
  if self.filter:
114
124
  self.driver.set_filter(self.filter)
115
125
  else:
@@ -138,4 +148,9 @@ class APRSDClient:
138
148
  return self.driver.consumer(callback=callback, raw=raw)
139
149
 
140
150
  def decode_packet(self, *args, **kwargs) -> core.Packet:
141
- return self.driver.decode_packet(*args, **kwargs)
151
+ try:
152
+ packet = self.driver.decode_packet(*args, **kwargs)
153
+ except Exception as e:
154
+ LOG.error(f'Error decoding packet: {e}')
155
+ return None
156
+ return packet
@@ -26,6 +26,7 @@ class APRSISDriver:
26
26
 
27
27
  _client = None
28
28
  _checks = False
29
+ connected = False
29
30
 
30
31
  def __init__(self):
31
32
  max_timeout = {'hours': 0.0, 'minutes': 2, 'seconds': 0}
@@ -164,7 +165,7 @@ class APRSISDriver:
164
165
  return core.factory(args[0])
165
166
 
166
167
  def consumer(self, callback: Callable, raw: bool = False):
167
- if self._client:
168
+ if self._client and self.connected:
168
169
  try:
169
170
  self._client.consumer(
170
171
  callback,
@@ -177,10 +178,9 @@ class APRSISDriver:
177
178
  LOG.info(e.__cause__)
178
179
  raise e
179
180
  else:
180
- LOG.warning('client is None, might be resetting.')
181
181
  self.connected = False
182
182
 
183
- def stats(self, serializable=False) -> dict:
183
+ def stats(self, serializable: bool = False) -> dict:
184
184
  stats = {}
185
185
  if self.is_configured():
186
186
  if self._client:
@@ -79,8 +79,8 @@ class TCPKISSDriver:
79
79
  def transport(self) -> str:
80
80
  return client.TRANSPORT_TCPKISS
81
81
 
82
- @classmethod
83
- def is_enabled(cls) -> bool:
82
+ @staticmethod
83
+ def is_enabled() -> bool:
84
84
  """Check if KISS is enabled in configuration.
85
85
 
86
86
  Returns:
@@ -248,7 +248,11 @@ class TCPKISSDriver:
248
248
  LOG.warning(f'FRAME: {str(frame)}')
249
249
  try:
250
250
  aprslib_frame = aprslib.parse(str(frame))
251
- return core.factory(aprslib_frame)
251
+ packet = core.factory(aprslib_frame)
252
+ if isinstance(packet, core.ThirdPartyPacket):
253
+ return packet.subpacket
254
+ else:
255
+ return packet
252
256
  except Exception as e:
253
257
  LOG.error(f'Error decoding packet: {e}')
254
258
  return None
@@ -271,8 +275,19 @@ class TCPKISSDriver:
271
275
  """
272
276
  if serializable:
273
277
  keepalive = self.keepalive.isoformat()
278
+ if self.last_packet_sent:
279
+ last_packet_sent = self.last_packet_sent.isoformat()
280
+ else:
281
+ last_packet_sent = 'None'
282
+ if self.last_packet_received:
283
+ last_packet_received = self.last_packet_received.isoformat()
284
+ else:
285
+ last_packet_received = 'None'
274
286
  else:
275
287
  keepalive = self.keepalive
288
+ last_packet_sent = self.last_packet_sent
289
+ last_packet_received = self.last_packet_received
290
+
276
291
  stats = {
277
292
  'client': self.__class__.__name__,
278
293
  'transport': self.transport,
@@ -280,8 +295,8 @@ class TCPKISSDriver:
280
295
  'path': self.path,
281
296
  'packets_sent': self.packets_sent,
282
297
  'packets_received': self.packets_received,
283
- 'last_packet_sent': self.last_packet_sent,
284
- 'last_packet_received': self.last_packet_received,
298
+ 'last_packet_sent': last_packet_sent,
299
+ 'last_packet_received': last_packet_received,
285
300
  'connection_keepalive': keepalive,
286
301
  'host': CONF.kiss_tcp.host,
287
302
  'port': CONF.kiss_tcp.port,
aprsd/cmds/dev.py CHANGED
@@ -4,11 +4,13 @@
4
4
  #
5
5
  # python included libs
6
6
  import logging
7
+ import sys
7
8
 
8
9
  import click
9
10
  from oslo_config import cfg
10
11
 
11
- from aprsd import cli_helper, conf, packets, plugin
12
+ import aprsd
13
+ from aprsd import cli_helper, conf, packets, plugin, utils
12
14
 
13
15
  # local imports here
14
16
  from aprsd.main import cli
@@ -71,6 +73,9 @@ def test_plugin(
71
73
  ):
72
74
  """Test an individual APRSD plugin given a python path."""
73
75
 
76
+ LOG.info(f'Python version: {sys.version}')
77
+ LOG.info(f'APRSD DEV Started version: {aprsd.__version__}')
78
+ utils.package.log_installed_extensions_and_plugins()
74
79
  CONF.log_opt_values(LOG, logging.DEBUG)
75
80
 
76
81
  if not aprs_login:
aprsd/cmds/fetch_stats.py CHANGED
@@ -1,5 +1,6 @@
1
1
  # Fetch active stats from a remote running instance of aprsd admin web interface.
2
2
  import logging
3
+ import sys
3
4
 
4
5
  import click
5
6
  import requests
@@ -38,6 +39,7 @@ CONF = cfg.CONF
38
39
  def fetch_stats(ctx, host, port):
39
40
  """Fetch stats from a APRSD admin web interface."""
40
41
  console = Console()
42
+ console.print(f'Python version: {sys.version}')
41
43
  console.print(f'APRSD Fetch-Stats started version: {aprsd.__version__}')
42
44
 
43
45
  CONF.log_opt_values(LOG, logging.DEBUG)
@@ -1,119 +1,18 @@
1
- import fnmatch
2
- import importlib
3
1
  import inspect
4
2
  import logging
5
- import os
6
- import pkgutil
7
- import sys
8
- from traceback import print_tb
9
3
 
10
4
  import click
11
- import requests
12
5
  from rich.console import Console
13
6
  from rich.table import Table
14
7
  from rich.text import Text
15
- from thesmuggler import smuggle
16
8
 
17
9
  from aprsd import cli_helper
18
10
  from aprsd import plugin as aprsd_plugin
19
11
  from aprsd.main import cli
20
12
  from aprsd.plugins import fortune, notify, ping, time, version, weather
13
+ from aprsd.utils import package as aprsd_package
21
14
 
22
15
  LOG = logging.getLogger('APRSD')
23
- PYPI_URL = 'https://pypi.org/search/'
24
-
25
-
26
- def onerror(name):
27
- print(f'Error importing module {name}')
28
- type, value, traceback = sys.exc_info()
29
- print_tb(traceback)
30
-
31
-
32
- def is_plugin(obj):
33
- for c in inspect.getmro(obj):
34
- if issubclass(c, aprsd_plugin.APRSDPluginBase):
35
- return True
36
-
37
- return False
38
-
39
-
40
- def plugin_type(obj):
41
- for c in inspect.getmro(obj):
42
- if issubclass(c, aprsd_plugin.APRSDRegexCommandPluginBase):
43
- return 'RegexCommand'
44
- if issubclass(c, aprsd_plugin.APRSDWatchListPluginBase):
45
- return 'WatchList'
46
- if issubclass(c, aprsd_plugin.APRSDPluginBase):
47
- return 'APRSDPluginBase'
48
-
49
- return 'Unknown'
50
-
51
-
52
- def walk_package(package):
53
- return pkgutil.walk_packages(
54
- package.__path__,
55
- package.__name__ + '.',
56
- onerror=onerror,
57
- )
58
-
59
-
60
- def get_module_info(package_name, module_name, module_path):
61
- if not os.path.exists(module_path):
62
- return None
63
-
64
- dir_path = os.path.realpath(module_path)
65
- pattern = '*.py'
66
-
67
- obj_list = []
68
-
69
- for path, _subdirs, files in os.walk(dir_path):
70
- for name in files:
71
- if fnmatch.fnmatch(name, pattern):
72
- module = smuggle(f'{path}/{name}')
73
- for mem_name, obj in inspect.getmembers(module):
74
- if inspect.isclass(obj) and is_plugin(obj):
75
- obj_list.append(
76
- {
77
- 'package': package_name,
78
- 'name': mem_name,
79
- 'obj': obj,
80
- 'version': obj.version,
81
- 'path': f'{".".join([module_name, obj.__name__])}',
82
- },
83
- )
84
-
85
- return obj_list
86
-
87
-
88
- def _get_installed_aprsd_items():
89
- # installed plugins
90
- plugins = {}
91
- extensions = {}
92
- for _finder, name, ispkg in pkgutil.iter_modules():
93
- if ispkg and name.startswith('aprsd_'):
94
- module = importlib.import_module(name)
95
- pkgs = walk_package(module)
96
- for pkg in pkgs:
97
- pkg_info = get_module_info(
98
- module.__name__, pkg.name, module.__path__[0]
99
- )
100
- if 'plugin' in name:
101
- plugins[name] = pkg_info
102
- elif 'extension' in name:
103
- extensions[name] = pkg_info
104
- return plugins, extensions
105
-
106
-
107
- def get_installed_plugins():
108
- # installed plugins
109
- plugins, extensions = _get_installed_aprsd_items()
110
- return plugins
111
-
112
-
113
- def get_installed_extensions():
114
- # installed plugins
115
- plugins, extensions = _get_installed_aprsd_items()
116
- return extensions
117
16
 
118
17
 
119
18
  def show_built_in_plugins(console):
@@ -157,34 +56,8 @@ def show_built_in_plugins(console):
157
56
  console.print(table)
158
57
 
159
58
 
160
- def _get_pypi_packages():
161
- if simple_r := requests.get(
162
- 'https://pypi.org/simple',
163
- headers={'Accept': 'application/vnd.pypi.simple.v1+json'},
164
- ):
165
- simple_response = simple_r.json()
166
- else:
167
- simple_response = {}
168
-
169
- key = 'aprsd'
170
- matches = [
171
- p['name'] for p in simple_response['projects'] if p['name'].startswith(key)
172
- ]
173
-
174
- packages = []
175
- for pkg in matches:
176
- # Get info for first match
177
- if r := requests.get(
178
- f'https://pypi.org/pypi/{pkg}/json',
179
- headers={'Accept': 'application/json'},
180
- ):
181
- packages.append(r.json())
182
-
183
- return packages
184
-
185
-
186
59
  def show_pypi_plugins(installed_plugins, console):
187
- packages = _get_pypi_packages()
60
+ packages = aprsd_package.get_pypi_packages()
188
61
 
189
62
  title = Text.assemble(
190
63
  ('Pypi.org APRSD Installable Plugin Packages\n\n', 'bold magenta'),
@@ -225,7 +98,7 @@ def show_pypi_plugins(installed_plugins, console):
225
98
 
226
99
 
227
100
  def show_pypi_extensions(installed_extensions, console):
228
- packages = _get_pypi_packages()
101
+ packages = aprsd_package.get_pypi_packages()
229
102
 
230
103
  title = Text.assemble(
231
104
  ('Pypi.org APRSD Installable Extension Packages\n\n', 'bold magenta'),
@@ -282,7 +155,7 @@ def show_installed_plugins(installed_plugins, console):
282
155
  name.replace('_', '-'),
283
156
  plugin['name'],
284
157
  plugin['version'],
285
- plugin_type(plugin['obj']),
158
+ aprsd_package.plugin_type(plugin['obj']),
286
159
  plugin['path'],
287
160
  )
288
161
 
@@ -302,7 +175,7 @@ def list_plugins(ctx):
302
175
  show_built_in_plugins(console)
303
176
 
304
177
  status.update('Fetching pypi.org plugins')
305
- installed_plugins = get_installed_plugins()
178
+ installed_plugins = aprsd_package.get_installed_plugins()
306
179
  show_pypi_plugins(installed_plugins, console)
307
180
 
308
181
  status.update('Looking for installed APRSD plugins')
@@ -321,5 +194,5 @@ def list_extensions(ctx):
321
194
  status.update('Fetching pypi.org APRSD Extensions')
322
195
 
323
196
  status.update('Looking for installed APRSD Extensions')
324
- installed_extensions = get_installed_extensions()
197
+ installed_extensions = aprsd_package.get_installed_extensions()
325
198
  show_pypi_extensions(installed_extensions, console)
aprsd/cmds/listen.py CHANGED
@@ -221,7 +221,9 @@ def listen(
221
221
  # CONF.aprs_network.login = aprs_login
222
222
  # config["aprs"]["password"] = aprs_password
223
223
 
224
+ LOG.info(f'Python version: {sys.version}')
224
225
  LOG.info(f'APRSD Listen Started version: {aprsd.__version__}')
226
+ utils.package.log_installed_extensions_and_plugins()
225
227
 
226
228
  CONF.log_opt_values(LOG, logging.DEBUG)
227
229
  collector.Collector()
@@ -13,6 +13,7 @@ from aprsd import (
13
13
  cli_helper,
14
14
  conf, # noqa : F401
15
15
  packets,
16
+ utils,
16
17
  )
17
18
  from aprsd.client.client import APRSDClient
18
19
  from aprsd.main import cli
@@ -89,7 +90,9 @@ def send_message(
89
90
  else:
90
91
  aprs_password = CONF.aprs_network.password
91
92
 
92
- LOG.info(f'APRSD LISTEN Started version: {aprsd.__version__}')
93
+ LOG.info(f'Python version: {sys.version}')
94
+ LOG.info(f'APRSD SEND_MESSAGE Started version: {aprsd.__version__}')
95
+ utils.package.log_installed_extensions_and_plugins()
93
96
  if type(command) is tuple:
94
97
  command = ' '.join(command)
95
98
  if not quiet:
aprsd/cmds/server.py CHANGED
@@ -40,12 +40,14 @@ def server(ctx, flush):
40
40
 
41
41
  service_threads = service.ServiceThreads()
42
42
 
43
+ LOG.info(f'Python version: {sys.version}')
44
+ LOG.info(f'APRSD Started version: {aprsd.__version__}')
43
45
  level, msg = utils._check_version()
44
46
  if level:
45
47
  LOG.warning(msg)
46
48
  else:
47
49
  LOG.info(msg)
48
- LOG.info(f'APRSD Started version: {aprsd.__version__}')
50
+ utils.package.log_installed_extensions_and_plugins()
49
51
 
50
52
  # Make sure we have 1 client transport enabled
51
53
  if not APRSDClient().is_enabled:
aprsd/conf/common.py CHANGED
@@ -19,7 +19,7 @@ registry_group = cfg.OptGroup(
19
19
  aprsd_opts = [
20
20
  cfg.StrOpt(
21
21
  'callsign',
22
- required=True,
22
+ default='NOCALL',
23
23
  help='Callsign to use for messages sent by APRSD',
24
24
  ),
25
25
  cfg.BoolOpt(
@@ -137,6 +137,12 @@ aprsd_opts = [
137
137
  help='Set this to False, to disable sending of ack packets. This will entirely stop'
138
138
  'APRSD from sending ack packets.',
139
139
  ),
140
+ cfg.BoolOpt(
141
+ 'is_digipi',
142
+ default=False,
143
+ help='Set this to True, if APRSD is running on a Digipi.'
144
+ 'This is useful for changing the behavior of APRSD to work with Digipi.',
145
+ ),
140
146
  ]
141
147
 
142
148
  watch_list_opts = [
aprsd/exception.py CHANGED
@@ -13,3 +13,10 @@ class ConfigOptionBogusDefaultException(Exception):
13
13
  f"Config file option '{config_option}' needs to be "
14
14
  f"changed from provided default of '{default_fail}'"
15
15
  )
16
+
17
+
18
+ class APRSClientNotConfiguredException(Exception):
19
+ """APRS client is not configured."""
20
+
21
+ def __init__(self):
22
+ self.message = 'APRS client is not configured.'
aprsd/threads/rx.py CHANGED
@@ -275,7 +275,7 @@ class APRSDProcessPacketThread(APRSDFilterThread):
275
275
  def process_other_packet(self, packet, for_us=False):
276
276
  """Process an APRS Packet that isn't a message or ack"""
277
277
  if not for_us:
278
- LOG.info("Got a packet meant for someone else '{packet.to_call}'")
278
+ LOG.info(f"Got a packet meant for someone else '{packet.to_call}'")
279
279
  else:
280
280
  LOG.info('Got a non AckPacket/MessagePacket')
281
281
 
aprsd/utils/package.py ADDED
@@ -0,0 +1,176 @@
1
+ import fnmatch
2
+ import importlib
3
+ import inspect
4
+ import logging
5
+ import os
6
+ import pkgutil
7
+ import sys
8
+ from traceback import print_tb
9
+
10
+ import requests
11
+ from thesmuggler import smuggle
12
+
13
+ from aprsd import plugin as aprsd_plugin
14
+
15
+ LOG = logging.getLogger()
16
+
17
+
18
+ def onerror(name):
19
+ type, value, traceback = sys.exc_info()
20
+ print_tb(traceback)
21
+
22
+
23
+ def plugin_type(obj):
24
+ for c in inspect.getmro(obj):
25
+ if issubclass(c, aprsd_plugin.APRSDRegexCommandPluginBase):
26
+ return 'RegexCommand'
27
+ if issubclass(c, aprsd_plugin.APRSDWatchListPluginBase):
28
+ return 'WatchList'
29
+ if issubclass(c, aprsd_plugin.APRSDPluginBase):
30
+ return 'APRSDPluginBase'
31
+
32
+ return 'Unknown'
33
+
34
+
35
+ def is_plugin(obj):
36
+ for c in inspect.getmro(obj):
37
+ if issubclass(c, aprsd_plugin.APRSDPluginBase):
38
+ return True
39
+
40
+ return False
41
+
42
+
43
+ def walk_package(package):
44
+ return pkgutil.walk_packages(
45
+ package.__path__,
46
+ package.__name__ + '.',
47
+ onerror=onerror,
48
+ )
49
+
50
+
51
+ def get_module_info(package_name, module_name, module_path):
52
+ if not os.path.exists(module_path):
53
+ return None
54
+
55
+ dir_path = os.path.realpath(module_path)
56
+ pattern = '*.py'
57
+
58
+ obj_list = []
59
+
60
+ for path, _subdirs, files in os.walk(dir_path):
61
+ for name in files:
62
+ if fnmatch.fnmatch(name, pattern):
63
+ module = smuggle(f'{path}/{name}')
64
+ for mem_name, obj in inspect.getmembers(module):
65
+ if inspect.isclass(obj) and is_plugin(obj):
66
+ obj_list.append(
67
+ {
68
+ 'package': package_name,
69
+ 'name': mem_name,
70
+ 'obj': obj,
71
+ 'version': obj.version,
72
+ 'path': f'{".".join([module_name, obj.__name__])}',
73
+ },
74
+ )
75
+
76
+ return obj_list
77
+
78
+
79
+ def is_aprsd_package(name):
80
+ if name.startswith('aprsd_'):
81
+ return True
82
+
83
+
84
+ def is_aprsd_extension(name):
85
+ if name.startswith('aprsd_') and 'extension' in name:
86
+ # This is an installed package that is an extension of
87
+ # APRSD
88
+ return True
89
+ else:
90
+ # We might have an editable install of an extension
91
+ # of APRSD.
92
+ return '__editable__' in name and 'aprsd_' in name and 'extension' in name
93
+
94
+
95
+ def get_installed_aprsd_items():
96
+ # installed plugins
97
+ plugins = {}
98
+ extensions = {}
99
+ for _finder, name, ispkg in pkgutil.iter_modules():
100
+ if ispkg and is_aprsd_package(name):
101
+ module = importlib.import_module(name)
102
+ pkgs = walk_package(module)
103
+ for pkg in pkgs:
104
+ pkg_info = get_module_info(
105
+ module.__name__, pkg.name, module.__path__[0]
106
+ )
107
+ if 'plugin' in name:
108
+ plugins[name] = pkg_info
109
+ elif 'extension' in name:
110
+ mod = importlib.import_module(name)
111
+ extensions[name] = mod
112
+ elif is_aprsd_extension(name):
113
+ # This isn't a package, so it could be an editable install
114
+ module = importlib.import_module(name)
115
+ key_name = next(iter(module.MAPPING.keys()))
116
+ module = importlib.import_module(key_name)
117
+ pkg_info = get_module_info(module.__name__, key_name, module.__path__[0])
118
+ extensions[key_name] = module
119
+ return plugins, extensions
120
+
121
+
122
+ def get_installed_plugins():
123
+ # installed plugins
124
+ plugins, _ = get_installed_aprsd_items()
125
+ return plugins
126
+
127
+
128
+ def get_installed_extensions():
129
+ # installed plugins
130
+ _, extensions = get_installed_aprsd_items()
131
+ return extensions
132
+
133
+
134
+ def get_pypi_packages():
135
+ if simple_r := requests.get(
136
+ 'https://pypi.org/simple',
137
+ headers={'Accept': 'application/vnd.pypi.simple.v1+json'},
138
+ ):
139
+ simple_response = simple_r.json()
140
+ else:
141
+ simple_response = {}
142
+
143
+ key = 'aprsd'
144
+ matches = [
145
+ p['name'] for p in simple_response['projects'] if p['name'].startswith(key)
146
+ ]
147
+
148
+ packages = []
149
+ for pkg in matches:
150
+ # Get info for first match
151
+ if r := requests.get(
152
+ f'https://pypi.org/pypi/{pkg}/json',
153
+ headers={'Accept': 'application/json'},
154
+ ):
155
+ packages.append(r.json())
156
+
157
+ return packages
158
+
159
+
160
+ def log_installed_extensions_and_plugins():
161
+ plugins, extensions = get_installed_aprsd_items()
162
+
163
+ for name in extensions:
164
+ ext = extensions[name]
165
+ # print(f"Extension: {ext}")
166
+ # print(f"Extension: {ext.__dict__}")
167
+ if hasattr(ext, '__version__'):
168
+ version = ext.__version__
169
+ elif hasattr(ext, 'version'):
170
+ version = ext.version
171
+ else:
172
+ version = ext['version']
173
+ LOG.info(f'Extension: {name} version: {version}')
174
+
175
+ for plugin in plugins:
176
+ LOG.info(f'Plugin: {plugin} version: {plugins[plugin][0]["version"]}')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aprsd
3
- Version: 4.2.0
3
+ Version: 4.2.1
4
4
  Summary: APRSd is a APRS-IS server that can be used to connect to APRS-IS and send and receive APRS packets.
5
5
  Author-email: Craig Lamparter <craig@craiger.org>, "Walter A. Boring IV" <waboring@hemna.com>, Emre Saglam <emresaglam@gmail.com>, Jason Martin <jhmartin@toger.us>, John <johng42@users.noreply.github.com>, Martiros Shakhzadyan <vrzh@vrzh.net>, Zoe Moore <zoenb@mailbox.org>, ranguli <hello@joshmurphy.ca>
6
6
  Maintainer-email: Craig Lamparter <craig@craiger.org>, "Walter A. Boring IV" <waboring@hemna.com>
@@ -1,31 +1,31 @@
1
1
  aprsd/__init__.py,sha256=ci_49KK2a4GXyxcM2lFZfNAOsBfXzh0yayIGQazw56I,687
2
2
  aprsd/cli_helper.py,sha256=mKHww_cStwFBThjntFylrSnF6n9jOPHlR8r9SsrCxdY,4605
3
- aprsd/exception.py,sha256=Oi6w0ISPemX0UpLB40BYnZBT1YOU-Pnpj8yf-A0E4-E,504
3
+ aprsd/exception.py,sha256=bzln7sP9USQ67tz5nQh6e4KMaS8X2uhPJMNVmCkKV30,679
4
4
  aprsd/main.py,sha256=sOzG4tKtm7FGxwvYWIwiPujzo5TV3F0cSkR7IWHlb8M,4719
5
5
  aprsd/plugin.py,sha256=pdyvKhSugFo4vRy7VflnaZ-BKozGa3GTTAHErskW3WU,17848
6
6
  aprsd/plugin_utils.py,sha256=beXQ1n_YI38rqDwswtE8NjFwFzjpaeve9W_JotX1n1A,2544
7
7
  aprsd/client/__init__.py,sha256=lh7mKBoSo2Tt82QoqlAARGm4LY6ffsn7d8x6M4B7n9g,154
8
- aprsd/client/client.py,sha256=i4KBGT_-6btH9e3X2moyGYz7OGHLHgbS8qqYMmlsH_o,3912
8
+ aprsd/client/client.py,sha256=7Y79BDaD0S28lziTgD6xl9C4f6rRrOgLJXNx_c__Wa8,4430
9
9
  aprsd/client/stats.py,sha256=dUqRZao04B2TTj9TGMSygdLHa3if3pEy86eK-fK4sj4,353
10
10
  aprsd/client/drivers/__init__.py,sha256=IWSSrAEMrJQzulCIAx-N7Du0HK9sQOXIh98aJRCtfdg,421
11
- aprsd/client/drivers/aprsis.py,sha256=upUqCYDVVvOfbX43h5ncXq7CdlMrJsnO2ghbA88RKAk,6665
11
+ aprsd/client/drivers/aprsis.py,sha256=8VhKjnfAfxaXdBLKvC4guTU2WQsdHAvIogoxHX57gxc,6651
12
12
  aprsd/client/drivers/fake.py,sha256=b3q9-4O9Gtd7XnEzgZ2NzR5Zv6szxKBe07nsXJXmSHw,3249
13
13
  aprsd/client/drivers/registry.py,sha256=AWDWqxjOYHDz8ow4fNSSJ7JR6Tgy1axG6r0I9Yk2nJ8,2213
14
- aprsd/client/drivers/tcpkiss.py,sha256=PIiBaj0j4KDcXKRi3gUYDp10tC6qLmUlGfTbkQKPN1M,12926
14
+ aprsd/client/drivers/tcpkiss.py,sha256=cjdVL88aeOst7tlxZ15ti5EBJNiXqvWHWFVrZMrk23Y,13527
15
15
  aprsd/client/drivers/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  aprsd/client/drivers/lib/aprslib.py,sha256=9KTEKlivGT1f1js-u-w1WNLhOs1kQxkr3COa1CI95oE,9439
17
17
  aprsd/cmds/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
18
  aprsd/cmds/completion.py,sha256=BMM8dSYUihYmj2fSsefo6LzgJZKbxHnNfRIhwVZW_U8,816
19
- aprsd/cmds/dev.py,sha256=iXjO0WBrEPE8wnuQU-7BpKOHsPLqyNZZ-67FvWiWOko,4097
20
- aprsd/cmds/fetch_stats.py,sha256=rE99ir67udprRLxOhWkZ1btgF5Vs8UX74S4ssjYi4lM,9621
19
+ aprsd/cmds/dev.py,sha256=9znqGv8qUd1hRV_-Iit8ktxFhYFIIB4rOnluhurrv28,4296
20
+ aprsd/cmds/fetch_stats.py,sha256=L8l-43GfZiWu9c9BgxpUV1PdrB8IG8z1FlsryAvPeAI,9684
21
21
  aprsd/cmds/healthcheck.py,sha256=swXb4LE1qdr3Z-417fv4LhWvscE4WUrqF9So1sWXiCU,2635
22
- aprsd/cmds/list_plugins.py,sha256=ongeK7gy_IxzLw_EfhclKMVHptyzIubV4PYxCxDMIqs,10415
23
- aprsd/cmds/listen.py,sha256=t_EOfy-qNRox6YwaeXHtynk_F5mShyDSjv2GZA9ca3I,9415
24
- aprsd/cmds/send_message.py,sha256=iJEteEWTPj3gQhSyBj8BvQr4WQzjrVbHWxaHgvIcpQM,4709
25
- aprsd/cmds/server.py,sha256=uZQawLzL5IKUPUHRleligJqlIokRwujcovhcivixY1g,4034
22
+ aprsd/cmds/list_plugins.py,sha256=PzvoyXfV26xAiTHtgSiJyWAmdPd2BEua5ta5fGuspVQ,7010
23
+ aprsd/cmds/listen.py,sha256=3M8eXIneEuM5wfskAFFYUZSfHTQveTAFSmnRZAfe9WY,9519
24
+ aprsd/cmds/send_message.py,sha256=EVJ-VayxcSNYAJ8dM8-LM9HLbsanC2mOWA6bfZwcLn4,4830
25
+ aprsd/cmds/server.py,sha256=hB3Tu0MbzEvg4XkoCFomvfMZqIitDKdIejQ6uwHDm0o,4138
26
26
  aprsd/conf/__init__.py,sha256=2ikrZahcS2EULQEJ5xErnzMVR2vcsDdMvixEPuNE-xE,1678
27
27
  aprsd/conf/client.py,sha256=9oheIUnotnbHmpKtxlw-00quW0o-3pZYtFmaim9bsjs,3013
28
- aprsd/conf/common.py,sha256=6bYna2bn0js6cq3c0h3KzbzgOWcpqeui5JEijx5rDj8,7386
28
+ aprsd/conf/common.py,sha256=l5tUw6G5CNOiFMZQPoStkpsNa3d9xr4BunzZK0FNgV8,7605
29
29
  aprsd/conf/log.py,sha256=qBoF8ptGHK7G6NPHNZCE2PBH7S-L587wFkT-9ikUtfE,1656
30
30
  aprsd/conf/opts.py,sha256=kbZELePpBDoQrKbowbWHgmLksbREARU8T8UhX9FIhq8,2725
31
31
  aprsd/conf/plugin_common.py,sha256=H7LxiJL0Sl1D_dpAmJHEHSbPxaOK938M1WCOcTpOYN8,1990
@@ -57,7 +57,7 @@ aprsd/threads/__init__.py,sha256=KPqAOhS4q995NCEWDnPCHiuu3guyuMZlyDUGx_h50z8,259
57
57
  aprsd/threads/aprsd.py,sha256=13AS7jAhcQBmTervBiADaC1Ins9C-6TrMDYjW1fQJkg,4794
58
58
  aprsd/threads/keepalive.py,sha256=E48_erNnqik5AAllMGx5gexAwPIaznCp0HCG45NltFw,3939
59
59
  aprsd/threads/registry.py,sha256=zWG4-SMBSx46NY93__Bt_F8vFrljxQvMHbi80WP5kY8,1690
60
- aprsd/threads/rx.py,sha256=u7SZ-YqINrnetusV7qFRWKVVoDMfj8-Z1bnSby3w3bI,14936
60
+ aprsd/threads/rx.py,sha256=u0W3YgU83OaZcKyw60C3B-Chb6LXYXpDv9RsXKSKHcg,14937
61
61
  aprsd/threads/service.py,sha256=fGjyr34i2-CJdBynxachNaBrBsULwmAnewLHdTujfmk,1375
62
62
  aprsd/threads/stats.py,sha256=drKqHV2WxgXhyWXGrmRHQx7oKlrJ9bwEMtCInCzulPY,884
63
63
  aprsd/threads/tx.py,sha256=spuWk4E5HvTWYNyhKB1kxqVbVvxNapzYvi9tNScTAHs,9264
@@ -67,12 +67,13 @@ aprsd/utils/fuzzyclock.py,sha256=qKV8SYZhQGOHG9biF8TeueLb6RMppspx1Zg4IOy1Z10,326
67
67
  aprsd/utils/json.py,sha256=eHoBfXGcchO4Q1MXj6uKK9YU-H8HKPJ2cThLZ1dM_vo,2578
68
68
  aprsd/utils/keepalive_collector.py,sha256=r0oKCpKPGsivOKTQkTfwcJRESqMfbNawCyqrcHoJo8M,1807
69
69
  aprsd/utils/objectstore.py,sha256=0OivUeagncWGH7eWjTwZhauf-etweTabp8Oykt0hoF4,3541
70
+ aprsd/utils/package.py,sha256=BtyIT6F5tPTFIATy5zDtYnB2k-rSFey5K2t9RPGenck,5025
70
71
  aprsd/utils/ring_buffer.py,sha256=lWWuw7lEbc2URhqAJfRLjpXBDLiK6UUWzk3j2VFnERQ,1111
71
72
  aprsd/utils/trace.py,sha256=lIuDZHOjvWbL2IMJ2tN_XW4Ch8oe4uQ7uLGylUByli0,5687
72
- aprsd-4.2.0.dist-info/licenses/AUTHORS,sha256=fGZhgXFMCfDPbp0hHllwmPyfiKPobLNA3sJA3BMIJVE,22
73
- aprsd-4.2.0.dist-info/licenses/LICENSE,sha256=CeipvOyAZxBGUsFoaFqwkx54aPnIKEtm9a5u2uXxEws,10142
74
- aprsd-4.2.0.dist-info/METADATA,sha256=eky_cPS4yV2IcaRxoiHCOc95g4UzL8pmMbnfzI5cxpU,45583
75
- aprsd-4.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
76
- aprsd-4.2.0.dist-info/entry_points.txt,sha256=4fReoJUB-bFqOUK6eeXYYCvTdVLprL7KVH0hWQRP9eM,171
77
- aprsd-4.2.0.dist-info/top_level.txt,sha256=v1O96niUcJOTMh9aQnFRknbScJ6mMOwqurdbxeaeSjs,6
78
- aprsd-4.2.0.dist-info/RECORD,,
73
+ aprsd-4.2.1.dist-info/licenses/AUTHORS,sha256=fGZhgXFMCfDPbp0hHllwmPyfiKPobLNA3sJA3BMIJVE,22
74
+ aprsd-4.2.1.dist-info/licenses/LICENSE,sha256=CeipvOyAZxBGUsFoaFqwkx54aPnIKEtm9a5u2uXxEws,10142
75
+ aprsd-4.2.1.dist-info/METADATA,sha256=TKX8daOdMLu42sayX71q88zaAZfCBy_e3gyjsBOsBeg,45583
76
+ aprsd-4.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
77
+ aprsd-4.2.1.dist-info/entry_points.txt,sha256=4fReoJUB-bFqOUK6eeXYYCvTdVLprL7KVH0hWQRP9eM,171
78
+ aprsd-4.2.1.dist-info/top_level.txt,sha256=v1O96niUcJOTMh9aQnFRknbScJ6mMOwqurdbxeaeSjs,6
79
+ aprsd-4.2.1.dist-info/RECORD,,
File without changes