FreeDATA/modem/frame_dispatcher.py

140 lines
4.5 KiB
Python
Raw Normal View History

"""
FRAME DISPATCHER - We are dispatching the received frames to the needed functions
2023-11-23 09:14:11 +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
from data_frame_factory import DataFrameFactory
from frame_handler import FrameHandler
2023-11-29 23:15:16 +00:00
from frame_handler_ping import PingFrameHandler
from frame_handler_cq import CQFrameHandler
from frame_handler_arq_session import ARQFrameHandler
2023-11-23 09:14:11 +00:00
class DISPATCHER():
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"},
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-05 17:50:39 +00:00
FR_TYPE.ARQ_STOP.value: {"class": ARQFrameHandler, "name": "ARQ STOP TX"},
FR_TYPE.BEACON.value: {"class": FrameHandler, "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.ARQ_BURST_NACK.value: {"class": ARQFrameHandler, "name": "BURST NACK"},
FR_TYPE.ARQ_DATA_ACK_NACK.value: {"class": ARQFrameHandler, "name": "DATA ACK NACK"},
FR_TYPE.CQ.value: {"class": CQFrameHandler, "name": "CQ"},
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"},
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_queue, 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.event_queue = event_queue
self.states = states
self._initialize_handlers(config, event_queue, states)
2023-11-29 16:35:23 +00:00
self.modem = modem
self.data_queue_received = modem.data_queue_received
2023-11-23 09:14:11 +00:00
self.arq_sessions = []
2023-11-23 09:14:11 +00:00
def _initialize_handlers(self, config, event_queue, states):
"""Initializes various data handlers."""
self.frame_factory = DataFrameFactory(config)
2023-11-23 09:14:11 +00:00
self.event_manager = event_manager.EventManager([event_queue])
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()
self.new_process_data(
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:
# 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 = handler_class(self.FRAME_HANDLER[frametype]['name'],
2023-11-29 23:15:16 +00:00
self.config,
self.states,
self.event_manager,
self.modem)
2023-12-13 15:56:11 +00:00
handler.handle(deconstructed_frame, snr, frequency_offset, freedv, bytes_per_frame)
def get_id_from_frame(self, data):
2023-12-12 19:22:34 +00:00
if data[:1] == FR_TYPE.ARQ_SESSION_OPEN:
return data[13:14]
return None
2023-11-23 09:14:11 +00:00