2023-11-23 22:10:53 +00:00
|
|
|
"""
|
|
|
|
FRAME DISPATCHER - We are dispatching the received frames to the needed functions
|
2023-11-23 09:14:11 +00:00
|
|
|
|
2023-11-23 22:10:53 +00:00
|
|
|
|
|
|
|
"""
|
2023-11-23 09:14:11 +00:00
|
|
|
import threading
|
2023-11-28 19:00:39 +00:00
|
|
|
import structlog
|
2023-11-23 09:14:11 +00:00
|
|
|
from modem_frametypes import FRAME_TYPE as FR_TYPE
|
|
|
|
import event_manager
|
2023-11-26 10:41:37 +00:00
|
|
|
from data_frame_factory import DataFrameFactory
|
|
|
|
|
2023-11-29 21:53:50 +00:00
|
|
|
from frame_handler import FrameHandler
|
2023-11-29 23:15:16 +00:00
|
|
|
from frame_handler_ping import PingFrameHandler
|
2023-11-30 08:24:36 +00:00
|
|
|
from frame_handler_cq import CQFrameHandler
|
2023-12-08 09:25:26 +00:00
|
|
|
from frame_handler_arq_session import ARQFrameHandler
|
2024-02-03 09:57:56 +00:00
|
|
|
from frame_handler_beacon import BeaconFrameHandler
|
2023-11-23 09:14:11 +00:00
|
|
|
|
|
|
|
class DISPATCHER():
|
|
|
|
|
2023-11-29 21:53:50 +00:00
|
|
|
FRAME_HANDLER = {
|
2023-12-12 19:22:34 +00:00
|
|
|
FR_TYPE.ARQ_SESSION_OPEN_ACK.value: {"class": ARQFrameHandler, "name": "ARQ OPEN ACK"},
|
|
|
|
FR_TYPE.ARQ_SESSION_OPEN.value: {"class": ARQFrameHandler, "name": "ARQ Data Channel Open"},
|
2023-12-12 19:46:22 +00:00
|
|
|
FR_TYPE.ARQ_SESSION_INFO_ACK.value: {"class": ARQFrameHandler, "name": "ARQ INFO ACK"},
|
|
|
|
FR_TYPE.ARQ_SESSION_INFO.value: {"class": ARQFrameHandler, "name": "ARQ Data Channel Info"},
|
2023-12-08 09:25:26 +00:00
|
|
|
FR_TYPE.ARQ_CONNECTION_CLOSE.value: {"class": ARQFrameHandler, "name": "ARQ CLOSE SESSION"},
|
|
|
|
FR_TYPE.ARQ_CONNECTION_HB.value: {"class": ARQFrameHandler, "name": "ARQ HEARTBEAT"},
|
|
|
|
FR_TYPE.ARQ_CONNECTION_OPEN.value: {"class": ARQFrameHandler, "name": "ARQ OPEN SESSION"},
|
2023-12-21 14:05:22 +00:00
|
|
|
FR_TYPE.ARQ_STOP.value: {"class": ARQFrameHandler, "name": "ARQ STOP"},
|
|
|
|
FR_TYPE.ARQ_STOP_ACK.value: {"class": ARQFrameHandler, "name": "ARQ STOP ACK"},
|
2024-02-03 09:57:56 +00:00
|
|
|
FR_TYPE.BEACON.value: {"class": BeaconFrameHandler, "name": "BEACON"},
|
2023-12-14 08:07:46 +00:00
|
|
|
FR_TYPE.ARQ_BURST_FRAME.value:{"class": ARQFrameHandler, "name": "BURST FRAME"},
|
|
|
|
FR_TYPE.ARQ_BURST_ACK.value: {"class": ARQFrameHandler, "name": "BURST ACK"},
|
2023-11-30 08:24:36 +00:00
|
|
|
FR_TYPE.CQ.value: {"class": CQFrameHandler, "name": "CQ"},
|
2023-11-29 21:53:50 +00:00
|
|
|
FR_TYPE.PING_ACK.value: {"class": FrameHandler, "name": "PING ACK"},
|
2023-11-29 23:15:16 +00:00
|
|
|
FR_TYPE.PING.value: {"class": PingFrameHandler, "name": "PING"},
|
2023-11-29 21:53:50 +00:00
|
|
|
FR_TYPE.QRV.value: {"class": FrameHandler, "name": "QRV"},
|
|
|
|
FR_TYPE.IS_WRITING.value: {"class": FrameHandler, "name": "IS_WRITING"},
|
|
|
|
FR_TYPE.FEC.value: {"class": FrameHandler, "name": "FEC"},
|
|
|
|
FR_TYPE.FEC_WAKEUP.value: {"class": FrameHandler, "name": "FEC WAKEUP"},
|
|
|
|
}
|
|
|
|
|
2024-01-04 14:46:58 +00:00
|
|
|
def __init__(self, config, event_manager, states, modem):
|
2023-11-28 19:00:39 +00:00
|
|
|
self.log = structlog.get_logger("frame_dispatcher")
|
|
|
|
|
|
|
|
self.log.info("loading frame dispatcher.....\n")
|
2023-11-23 09:14:11 +00:00
|
|
|
self.config = config
|
|
|
|
self.states = states
|
2024-01-04 14:46:58 +00:00
|
|
|
self.event_manager = event_manager
|
2023-11-23 09:14:11 +00:00
|
|
|
|
2024-01-04 14:46:58 +00:00
|
|
|
self._initialize_handlers(config, states)
|
2023-11-29 16:35:23 +00:00
|
|
|
|
2023-12-15 23:51:57 +00:00
|
|
|
self.modem = modem
|
|
|
|
self.data_queue_received = modem.data_queue_received
|
2023-11-23 09:14:11 +00:00
|
|
|
|
2023-11-29 21:53:50 +00:00
|
|
|
self.arq_sessions = []
|
|
|
|
|
2024-01-04 14:46:58 +00:00
|
|
|
def _initialize_handlers(self, config, states):
|
2023-11-23 09:14:11 +00:00
|
|
|
"""Initializes various data handlers."""
|
2023-11-26 10:41:37 +00:00
|
|
|
|
2023-11-26 11:45:51 +00:00
|
|
|
self.frame_factory = DataFrameFactory(config)
|
2023-11-23 09:14:11 +00:00
|
|
|
|
2023-11-26 13:51:58 +00:00
|
|
|
def start(self):
|
2023-11-23 09:14:11 +00:00
|
|
|
"""Starts worker threads for transmit and receive operations."""
|
|
|
|
threading.Thread(target=self.worker_receive, name="Receive Worker", daemon=True).start()
|
|
|
|
|
|
|
|
def worker_receive(self) -> None:
|
|
|
|
"""Queue received data for processing"""
|
|
|
|
while True:
|
|
|
|
data = self.data_queue_received.get()
|
2023-11-29 21:53:50 +00:00
|
|
|
self.new_process_data(
|
2023-11-30 09:54:37 +00:00
|
|
|
data['payload'],
|
|
|
|
data['freedv'],
|
|
|
|
data['bytes_per_frame'],
|
|
|
|
data['snr'],
|
|
|
|
data['frequency_offset'],
|
2023-11-23 09:14:11 +00:00
|
|
|
)
|
|
|
|
|
2023-12-13 15:56:11 +00:00
|
|
|
def new_process_data(self, bytes_out, freedv, bytes_per_frame: int, snr, frequency_offset) -> None:
|
2023-11-29 21:53:50 +00:00
|
|
|
# get frame as dictionary
|
|
|
|
deconstructed_frame = self.frame_factory.deconstruct(bytes_out)
|
|
|
|
frametype = deconstructed_frame["frame_type_int"]
|
|
|
|
|
|
|
|
if frametype not in self.FRAME_HANDLER:
|
|
|
|
self.log.warning(
|
|
|
|
"[Modem] ARQ - other frame type", frametype=FR_TYPE(frametype).name)
|
|
|
|
return
|
|
|
|
|
|
|
|
# instantiate handler
|
|
|
|
handler_class = self.FRAME_HANDLER[frametype]['class']
|
2023-12-20 11:26:28 +00:00
|
|
|
handler: FrameHandler = handler_class(self.FRAME_HANDLER[frametype]['name'],
|
2023-11-29 23:15:16 +00:00
|
|
|
self.config,
|
2023-11-29 21:53:50 +00:00
|
|
|
self.states,
|
|
|
|
self.event_manager,
|
2023-12-15 23:51:57 +00:00
|
|
|
self.modem)
|
2023-12-13 15:56:11 +00:00
|
|
|
handler.handle(deconstructed_frame, snr, frequency_offset, freedv, bytes_per_frame)
|
2023-12-03 13:11:43 +00:00
|
|
|
|
|
|
|
def get_id_from_frame(self, data):
|
2023-12-12 19:22:34 +00:00
|
|
|
if data[:1] == FR_TYPE.ARQ_SESSION_OPEN:
|
2023-12-03 13:11:43 +00:00
|
|
|
return data[13:14]
|
|
|
|
return None
|