1
0
mirror of https://github.com/craigerl/aprsd.git synced 2026-02-24 10:10:50 -05:00

make consumer call signature consistent.

This commit is contained in:
Walter Boring 2026-02-18 14:11:25 -05:00
parent 2b7e42802b
commit 6ea9889369
6 changed files with 87 additions and 14 deletions

View File

@ -131,10 +131,19 @@ class KISSDriver(metaclass=trace.TraceWrapperMetaclass):
"""Start consuming frames with the given callback.
Args:
callback: Function to call with received packets
callback: Function to call with received packets.
Called with frame=<frame> keyword argument to match
the signature used by other drivers (packet=<packet>).
raw: If True, callback receives raw frame data.
If False, callback receives decoded packet.
Raises:
Exception: If not connected to KISS TNC
Note:
The callback signature should accept keyword arguments:
- For raw frames: callback(frame=frame_obj)
- For decoded packets: callback(packet=packet_obj)
"""
# Ensure connection
if not self._connected:
@ -144,7 +153,14 @@ class KISSDriver(metaclass=trace.TraceWrapperMetaclass):
frame = self.read_frame()
if frame:
LOG.info(f'GOT FRAME: {frame} calling {callback}')
callback(frame)
if raw:
# Pass raw frame with keyword argument for consistency
callback(frame=frame)
else:
# Decode frame to packet and pass with keyword argument
packet = self.decode_packet(frame)
if packet:
callback(packet=packet)
def read_frame(self):
"""Read a frame from the KISS interface.

View File

@ -89,7 +89,16 @@ class SerialKISSDriver(KISSDriver):
pass
def setup_connection(self):
"""Set up the KISS interface."""
"""Set up the KISS interface.
This is the Protocol-defined method that initializes the connection.
It internally calls connect() to establish the actual serial connection.
Note:
This method follows the ClientDriver Protocol. Use this method
for standard connection setup. The connect() method is an internal
KISS-specific helper for establishing the serial port connection.
"""
if not self.is_enabled():
LOG.error('KISS is not enabled in configuration')
return
@ -99,7 +108,7 @@ class SerialKISSDriver(KISSDriver):
return
try:
# Configure for TCP KISS
# Configure for Serial KISS
if self.is_enabled():
LOG.info(
f'Serial KISS Connection to {CONF.kiss_serial.device}:{CONF.kiss_serial.baudrate}'
@ -116,7 +125,16 @@ class SerialKISSDriver(KISSDriver):
self._connected = False
def connect(self):
"""Connect to the KISS interface."""
"""Establish serial connection to the KISS device.
This is a KISS-specific internal method that handles the low-level
serial port connection. It is called by setup_connection().
Note:
This method is NOT part of the ClientDriver Protocol. It is specific
to KISS drivers and handles serial port establishment and configuration.
External code should use setup_connection() instead.
"""
if not self.is_enabled():
LOG.error('KISS is not enabled in configuration')
return

View File

@ -145,7 +145,16 @@ class TCPKISSDriver(KISSDriver):
return True
def setup_connection(self):
"""Set up the KISS interface."""
"""Set up the KISS interface.
This is the Protocol-defined method that initializes the connection.
It internally calls connect() to establish the actual TCP connection.
Note:
This method follows the ClientDriver Protocol. Use this method
for standard connection setup. The connect() method is an internal
KISS-specific helper for establishing the TCP socket connection.
"""
if not self.is_enabled():
LOG.error('KISS is not enabled in configuration')
return
@ -186,6 +195,14 @@ class TCPKISSDriver(KISSDriver):
def connect(self) -> bool:
"""Establish TCP connection to the KISS host.
This is a KISS-specific internal method that handles the low-level
socket connection. It is called by setup_connection().
Note:
This method is NOT part of the ClientDriver Protocol. It is specific
to KISS drivers and handles TCP socket establishment and configuration.
External code should use setup_connection() instead.
Returns:
bool: True if connection successful, False otherwise
"""

View File

@ -94,12 +94,26 @@ class APRSDRXThread(APRSDThread):
"""Put the raw packet on the queue.
The processing of the packet will happen in a separate thread.
Accepts packets/frames as either:
- Positional arg: process_packet(frame)
- Keyword args: process_packet(raw=frame), process_packet(frame=frame), or process_packet(packet=pkt)
"""
if not args:
# Extract the packet/frame from either args or kwargs
if args:
data = args[0]
elif 'raw' in kwargs:
data = kwargs['raw']
elif 'frame' in kwargs:
data = kwargs['frame']
elif 'packet' in kwargs:
data = kwargs['packet']
else:
LOG.warning('No frame received to process?!?!')
return
self.pkt_count += 1
self.packet_queue.put(args[0])
self.packet_queue.put(data)
class APRSDFilterThread(APRSDThread):

View File

@ -175,11 +175,15 @@ class TestKISSDriver(unittest.TestCase):
self.driver._connected = True
callback = mock.MagicMock()
mock_frame = b'test_frame'
mock_packet = mock.MagicMock()
with mock.patch.object(self.driver, 'read_frame', return_value=mock_frame):
with mock.patch('aprsd.client.drivers.kiss_common.LOG'):
self.driver.consumer(callback)
callback.assert_called()
with mock.patch.object(
self.driver, 'decode_packet', return_value=mock_packet
):
with mock.patch('aprsd.client.drivers.kiss_common.LOG'):
self.driver.consumer(callback)
callback.assert_called_once_with(packet=mock_packet)
def test_read_frame_not_implemented(self):
"""Test read_frame() raises NotImplementedError."""

View File

@ -373,6 +373,7 @@ class TestTCPKISSDriver(unittest.TestCase):
"""Test consumer processes frames and calls callback."""
mock_callback = mock.MagicMock()
mock_frame = mock.MagicMock()
mock_packet = mock.MagicMock()
# Configure driver for test
self.driver._connected = True
@ -386,10 +387,13 @@ class TestTCPKISSDriver(unittest.TestCase):
with mock.patch.object(
self.driver, 'read_frame', side_effect=side_effect
) as mock_read_frame:
self.driver.consumer(mock_callback)
with mock.patch.object(
self.driver, 'decode_packet', return_value=mock_packet
):
self.driver.consumer(mock_callback)
mock_read_frame.assert_called_once()
mock_callback.assert_called_once_with(mock_frame)
mock_read_frame.assert_called_once()
mock_callback.assert_called_once_with(packet=mock_packet)
@mock.patch('aprsd.client.drivers.tcpkiss.LOG')
def test_read_frame_success(self, mock_log):