""" FRAME DISPATCHER - We are dispatching the received frames to the needed functions """ import threading import structlog from modem_frametypes import FRAME_TYPE as FR_TYPE import event_manager from data_frame_factory import DataFrameFactory from frame_handler import FrameHandler from frame_handler_ping import PingFrameHandler from frame_handler_cq import CQFrameHandler from frame_handler_arq_session import ARQFrameHandler from frame_handler_beacon import BeaconFrameHandler class DISPATCHER(): FRAME_HANDLER = { 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"}, 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"}, 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"}, FR_TYPE.ARQ_STOP.value: {"class": ARQFrameHandler, "name": "ARQ STOP"}, FR_TYPE.ARQ_STOP_ACK.value: {"class": ARQFrameHandler, "name": "ARQ STOP ACK"}, FR_TYPE.BEACON.value: {"class": BeaconFrameHandler, "name": "BEACON"}, FR_TYPE.ARQ_BURST_FRAME.value:{"class": ARQFrameHandler, "name": "BURST FRAME"}, FR_TYPE.ARQ_BURST_ACK.value: {"class": ARQFrameHandler, "name": "BURST ACK"}, FR_TYPE.CQ.value: {"class": CQFrameHandler, "name": "CQ"}, FR_TYPE.PING_ACK.value: {"class": FrameHandler, "name": "PING ACK"}, FR_TYPE.PING.value: {"class": PingFrameHandler, "name": "PING"}, 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"}, } def __init__(self, config, event_manager, states, modem): self.log = structlog.get_logger("frame_dispatcher") self.log.info("loading frame dispatcher.....\n") self.config = config self.states = states self.event_manager = event_manager self._initialize_handlers(config, states) self.modem = modem self.data_queue_received = modem.data_queue_received self.arq_sessions = [] def _initialize_handlers(self, config, states): """Initializes various data handlers.""" self.frame_factory = DataFrameFactory(config) def start(self): """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() self.new_process_data( data['payload'], data['freedv'], data['bytes_per_frame'], data['snr'], data['frequency_offset'], ) def new_process_data(self, bytes_out, freedv, bytes_per_frame: int, snr, frequency_offset) -> None: # 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'] handler: FrameHandler = handler_class(self.FRAME_HANDLER[frametype]['name'], self.config, self.states, self.event_manager, self.modem) handler.handle(deconstructed_frame, snr, frequency_offset, freedv, bytes_per_frame) def get_id_from_frame(self, data): if data[:1] == FR_TYPE.ARQ_SESSION_OPEN: return data[13:14] return None