aprsd 4.0.0__py3-none-any.whl → 4.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aprsd/client/drivers/fake.py +5 -0
- aprsd/client/drivers/kiss.py +17 -15
- aprsd/client/kiss.py +28 -25
- aprsd/plugins/fortune.py +21 -15
- aprsd-4.0.2.dist-info/METADATA +748 -0
- {aprsd-4.0.0.dist-info → aprsd-4.0.2.dist-info}/RECORD +11 -11
- aprsd-4.0.0.dist-info/METADATA +0 -293
- {aprsd-4.0.0.dist-info → aprsd-4.0.2.dist-info}/AUTHORS +0 -0
- {aprsd-4.0.0.dist-info → aprsd-4.0.2.dist-info}/LICENSE +0 -0
- {aprsd-4.0.0.dist-info → aprsd-4.0.2.dist-info}/WHEEL +0 -0
- {aprsd-4.0.0.dist-info → aprsd-4.0.2.dist-info}/entry_points.txt +0 -0
- {aprsd-4.0.0.dist-info → aprsd-4.0.2.dist-info}/top_level.txt +0 -0
aprsd/client/drivers/fake.py
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
import datetime
|
1
2
|
import logging
|
2
3
|
import threading
|
3
4
|
import time
|
@@ -20,6 +21,9 @@ class APRSDFakeClient(metaclass=trace.TraceWrapperMetaclass):
|
|
20
21
|
# flag to tell us to stop
|
21
22
|
thread_stop = False
|
22
23
|
|
24
|
+
# date for last time we heard from the server
|
25
|
+
aprsd_keepalive = datetime.datetime.now()
|
26
|
+
|
23
27
|
lock = threading.Lock()
|
24
28
|
path = []
|
25
29
|
|
@@ -63,6 +67,7 @@ class APRSDFakeClient(metaclass=trace.TraceWrapperMetaclass):
|
|
63
67
|
raw = 'GTOWN>APDW16,WIDE1-1,WIDE2-1:}KM6LYW-9>APZ100,TCPIP,GTOWN*::KM6LYW :KM6LYW: 19 Miles SW'
|
64
68
|
pkt_raw = aprslib.parse(raw)
|
65
69
|
pkt = core.factory(pkt_raw)
|
70
|
+
self.aprsd_keepalive = datetime.datetime.now()
|
66
71
|
callback(packet=pkt)
|
67
72
|
LOG.debug(f'END blocking FAKE consumer {self}')
|
68
73
|
time.sleep(8)
|
aprsd/client/drivers/kiss.py
CHANGED
@@ -1,21 +1,24 @@
|
|
1
|
+
import datetime
|
1
2
|
import logging
|
2
3
|
|
3
|
-
from ax253 import Frame
|
4
4
|
import kiss
|
5
|
+
from ax253 import Frame
|
5
6
|
from oslo_config import cfg
|
6
7
|
|
7
8
|
from aprsd import conf # noqa
|
8
9
|
from aprsd.packets import core
|
9
10
|
from aprsd.utils import trace
|
10
11
|
|
11
|
-
|
12
12
|
CONF = cfg.CONF
|
13
|
-
LOG = logging.getLogger(
|
13
|
+
LOG = logging.getLogger('APRSD')
|
14
14
|
|
15
15
|
|
16
16
|
class KISS3Client:
|
17
17
|
path = []
|
18
18
|
|
19
|
+
# date for last time we heard from the server
|
20
|
+
aprsd_keepalive = datetime.datetime.now()
|
21
|
+
|
19
22
|
def __init__(self):
|
20
23
|
self.setup()
|
21
24
|
|
@@ -26,7 +29,7 @@ class KISS3Client:
|
|
26
29
|
# we can be TCP kiss or Serial kiss
|
27
30
|
if CONF.kiss_serial.enabled:
|
28
31
|
LOG.debug(
|
29
|
-
|
32
|
+
'KISS({}) Serial connection to {}'.format(
|
30
33
|
kiss.__version__,
|
31
34
|
CONF.kiss_serial.device,
|
32
35
|
),
|
@@ -39,7 +42,7 @@ class KISS3Client:
|
|
39
42
|
self.path = CONF.kiss_serial.path
|
40
43
|
elif CONF.kiss_tcp.enabled:
|
41
44
|
LOG.debug(
|
42
|
-
|
45
|
+
'KISS({}) TCP Connection to {}:{}'.format(
|
43
46
|
kiss.__version__,
|
44
47
|
CONF.kiss_tcp.host,
|
45
48
|
CONF.kiss_tcp.port,
|
@@ -52,7 +55,7 @@ class KISS3Client:
|
|
52
55
|
)
|
53
56
|
self.path = CONF.kiss_tcp.path
|
54
57
|
|
55
|
-
LOG.debug(
|
58
|
+
LOG.debug('Starting KISS interface connection')
|
56
59
|
self.kiss.start()
|
57
60
|
|
58
61
|
@trace.trace
|
@@ -74,18 +77,17 @@ class KISS3Client:
|
|
74
77
|
frame = Frame.from_bytes(frame_bytes)
|
75
78
|
# Now parse it with aprslib
|
76
79
|
kwargs = {
|
77
|
-
|
80
|
+
'frame': frame,
|
78
81
|
}
|
79
82
|
self._parse_callback(**kwargs)
|
83
|
+
self.aprsd_keepalive = datetime.datetime.now()
|
80
84
|
except Exception as ex:
|
81
|
-
LOG.error(
|
85
|
+
LOG.error('Failed to parse bytes received from KISS interface.')
|
82
86
|
LOG.exception(ex)
|
83
87
|
|
84
88
|
def consumer(self, callback):
|
85
|
-
LOG.debug("Start blocking KISS consumer")
|
86
89
|
self._parse_callback = callback
|
87
90
|
self.kiss.read(callback=self.parse_frame, min_frames=None)
|
88
|
-
LOG.debug(f"END blocking KISS consumer {self.kiss}")
|
89
91
|
|
90
92
|
def send(self, packet):
|
91
93
|
"""Send an APRS Message object."""
|
@@ -94,24 +96,24 @@ class KISS3Client:
|
|
94
96
|
path = self.path
|
95
97
|
if isinstance(packet, core.Packet):
|
96
98
|
packet.prepare()
|
97
|
-
payload = packet.payload.encode(
|
99
|
+
payload = packet.payload.encode('US-ASCII')
|
98
100
|
if packet.path:
|
99
101
|
path = packet.path
|
100
102
|
else:
|
101
|
-
msg_payload = f
|
103
|
+
msg_payload = f'{packet.raw}{{{str(packet.msgNo)}'
|
102
104
|
payload = (
|
103
|
-
|
105
|
+
':{:<9}:{}'.format(
|
104
106
|
packet.to_call,
|
105
107
|
msg_payload,
|
106
108
|
)
|
107
|
-
).encode(
|
109
|
+
).encode('US-ASCII')
|
108
110
|
|
109
111
|
LOG.debug(
|
110
112
|
f"KISS Send '{payload}' TO '{packet.to_call}' From "
|
111
113
|
f"'{packet.from_call}' with PATH '{path}'",
|
112
114
|
)
|
113
115
|
frame = Frame.ui(
|
114
|
-
destination=
|
116
|
+
destination='APZ100',
|
115
117
|
source=packet.from_call,
|
116
118
|
path=path,
|
117
119
|
info=payload,
|
aprsd/client/kiss.py
CHANGED
@@ -12,7 +12,7 @@ from aprsd.client.drivers import kiss
|
|
12
12
|
from aprsd.packets import core
|
13
13
|
|
14
14
|
CONF = cfg.CONF
|
15
|
-
LOG = logging.getLogger(
|
15
|
+
LOG = logging.getLogger('APRSD')
|
16
16
|
LOGU = logger
|
17
17
|
|
18
18
|
|
@@ -27,15 +27,15 @@ class KISSClient(base.APRSClient):
|
|
27
27
|
if serializable:
|
28
28
|
keepalive = keepalive.isoformat()
|
29
29
|
stats = {
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
'connected': self.is_connected,
|
31
|
+
'connection_keepalive': keepalive,
|
32
|
+
'transport': self.transport(),
|
33
33
|
}
|
34
34
|
if self.transport() == client.TRANSPORT_TCPKISS:
|
35
|
-
stats[
|
36
|
-
stats[
|
35
|
+
stats['host'] = CONF.kiss_tcp.host
|
36
|
+
stats['port'] = CONF.kiss_tcp.port
|
37
37
|
elif self.transport() == client.TRANSPORT_SERIALKISS:
|
38
|
-
stats[
|
38
|
+
stats['device'] = CONF.kiss_serial.device
|
39
39
|
return stats
|
40
40
|
|
41
41
|
@staticmethod
|
@@ -56,15 +56,15 @@ class KISSClient(base.APRSClient):
|
|
56
56
|
transport = KISSClient.transport()
|
57
57
|
if transport == client.TRANSPORT_SERIALKISS:
|
58
58
|
if not CONF.kiss_serial.device:
|
59
|
-
LOG.error(
|
59
|
+
LOG.error('KISS serial enabled, but no device is set.')
|
60
60
|
raise exception.MissingConfigOptionException(
|
61
|
-
|
61
|
+
'kiss_serial.device is not set.',
|
62
62
|
)
|
63
63
|
elif transport == client.TRANSPORT_TCPKISS:
|
64
64
|
if not CONF.kiss_tcp.host:
|
65
|
-
LOG.error(
|
65
|
+
LOG.error('KISS TCP enabled, but no host is set.')
|
66
66
|
raise exception.MissingConfigOptionException(
|
67
|
-
|
67
|
+
'kiss_tcp.host is not set.',
|
68
68
|
)
|
69
69
|
|
70
70
|
return True
|
@@ -91,8 +91,8 @@ class KISSClient(base.APRSClient):
|
|
91
91
|
if ka := self._client.aprsd_keepalive:
|
92
92
|
keepalive = timeago.format(ka)
|
93
93
|
else:
|
94
|
-
keepalive =
|
95
|
-
LOGU.opt(colors=True).info(f
|
94
|
+
keepalive = 'N/A'
|
95
|
+
LOGU.opt(colors=True).info(f'<green>Client keepalive {keepalive}</green>')
|
96
96
|
|
97
97
|
@staticmethod
|
98
98
|
def transport():
|
@@ -104,8 +104,8 @@ class KISSClient(base.APRSClient):
|
|
104
104
|
|
105
105
|
def decode_packet(self, *args, **kwargs):
|
106
106
|
"""We get a frame, which has to be decoded."""
|
107
|
-
LOG.debug(f
|
108
|
-
frame = kwargs[
|
107
|
+
LOG.debug(f'kwargs {kwargs}')
|
108
|
+
frame = kwargs['frame']
|
109
109
|
LOG.debug(f"Got an APRS Frame '{frame}'")
|
110
110
|
# try and nuke the * from the fromcall sign.
|
111
111
|
# frame.header._source._ch = False
|
@@ -114,20 +114,23 @@ class KISSClient(base.APRSClient):
|
|
114
114
|
# msg = frame.tnc2
|
115
115
|
# LOG.debug(f"Decoding {msg}")
|
116
116
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
117
|
+
try:
|
118
|
+
raw = aprslib.parse(str(frame))
|
119
|
+
packet = core.factory(raw)
|
120
|
+
if isinstance(packet, core.ThirdPartyPacket):
|
121
|
+
return packet.subpacket
|
122
|
+
else:
|
123
|
+
return packet
|
124
|
+
except Exception as ex:
|
125
|
+
LOG.error(f'Error decoding packet: {ex}')
|
123
126
|
|
124
127
|
def setup_connection(self):
|
125
128
|
try:
|
126
129
|
self._client = kiss.KISS3Client()
|
127
|
-
self.connected = self.login_status[
|
130
|
+
self.connected = self.login_status['success'] = True
|
128
131
|
except Exception as ex:
|
129
|
-
self.connected = self.login_status[
|
130
|
-
self.login_status[
|
132
|
+
self.connected = self.login_status['success'] = False
|
133
|
+
self.login_status['message'] = str(ex)
|
131
134
|
return self._client
|
132
135
|
|
133
136
|
def consumer(self, callback, blocking=False, immortal=False, raw=False):
|
@@ -135,5 +138,5 @@ class KISSClient(base.APRSClient):
|
|
135
138
|
self._client.consumer(callback)
|
136
139
|
self.keepalive = datetime.datetime.now()
|
137
140
|
except Exception as ex:
|
138
|
-
LOG.error(f
|
141
|
+
LOG.error(f'Consumer failed {ex}')
|
139
142
|
LOG.error(ex)
|
aprsd/plugins/fortune.py
CHANGED
@@ -5,24 +5,30 @@ import subprocess
|
|
5
5
|
from aprsd import packets, plugin
|
6
6
|
from aprsd.utils import trace
|
7
7
|
|
8
|
+
LOG = logging.getLogger('APRSD')
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
FORTUNE_PATHS = [
|
11
|
+
'/usr/games/fortune',
|
12
|
+
'/usr/local/bin/fortune',
|
13
|
+
'/usr/bin/fortune',
|
14
|
+
]
|
12
15
|
|
13
16
|
|
14
17
|
class FortunePlugin(plugin.APRSDRegexCommandPluginBase):
|
15
18
|
"""Fortune."""
|
16
19
|
|
17
|
-
command_regex = r
|
18
|
-
command_name =
|
19
|
-
short_description =
|
20
|
+
command_regex = r'^([f]|[f]\s|fortune)'
|
21
|
+
command_name = 'fortune'
|
22
|
+
short_description = 'Give me a fortune'
|
20
23
|
|
21
24
|
fortune_path = None
|
22
25
|
|
23
26
|
def setup(self):
|
24
|
-
|
25
|
-
|
27
|
+
for path in FORTUNE_PATHS:
|
28
|
+
self.fortune_path = shutil.which(path)
|
29
|
+
LOG.info(f'Fortune path {self.fortune_path}')
|
30
|
+
if self.fortune_path:
|
31
|
+
break
|
26
32
|
if not self.fortune_path:
|
27
33
|
self.enabled = False
|
28
34
|
else:
|
@@ -30,7 +36,7 @@ class FortunePlugin(plugin.APRSDRegexCommandPluginBase):
|
|
30
36
|
|
31
37
|
@trace.trace
|
32
38
|
def process(self, packet: packets.MessagePacket):
|
33
|
-
LOG.info(
|
39
|
+
LOG.info('FortunePlugin')
|
34
40
|
|
35
41
|
# fromcall = packet.get("from")
|
36
42
|
# message = packet.get("message_text", None)
|
@@ -39,8 +45,8 @@ class FortunePlugin(plugin.APRSDRegexCommandPluginBase):
|
|
39
45
|
reply = None
|
40
46
|
|
41
47
|
try:
|
42
|
-
cmnd = [self.fortune_path,
|
43
|
-
command =
|
48
|
+
cmnd = [self.fortune_path, '-s', '-n 60']
|
49
|
+
command = ' '.join(cmnd)
|
44
50
|
output = subprocess.check_output(
|
45
51
|
command,
|
46
52
|
shell=True,
|
@@ -48,10 +54,10 @@ class FortunePlugin(plugin.APRSDRegexCommandPluginBase):
|
|
48
54
|
text=True,
|
49
55
|
)
|
50
56
|
output = (
|
51
|
-
output.replace(
|
52
|
-
.replace(
|
53
|
-
.replace(
|
54
|
-
.replace(
|
57
|
+
output.replace('\r', '')
|
58
|
+
.replace('\n', '')
|
59
|
+
.replace(' ', '')
|
60
|
+
.replace('\t', ' ')
|
55
61
|
)
|
56
62
|
except subprocess.CalledProcessError as ex:
|
57
63
|
reply = f"Fortune command failed '{ex.output}'"
|