mirror of
https://github.com/DJ2LS/FreeDATA
synced 2024-05-14 08:04:33 +00:00
Add PingFrameHandler
This commit is contained in:
parent
f4b00ce68a
commit
63273b7f02
|
@ -68,6 +68,15 @@ class DataFrameFactory:
|
||||||
"origin": 6
|
"origin": 6
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ping ack
|
||||||
|
self.template_list[FR_TYPE.PING_ACK.value] = {
|
||||||
|
"frame_length": self.LENGTH_SIG0_FRAME,
|
||||||
|
"destination_crc": 3,
|
||||||
|
"origin_crc": 3,
|
||||||
|
"gridsquare": 4,
|
||||||
|
"snr": 1,
|
||||||
|
}
|
||||||
|
|
||||||
def _load_fec_templates(self):
|
def _load_fec_templates(self):
|
||||||
# fec wakeup frame
|
# fec wakeup frame
|
||||||
self.template_list[FR_TYPE.FEC_WAKEUP.value] = {
|
self.template_list[FR_TYPE.FEC_WAKEUP.value] = {
|
||||||
|
@ -207,7 +216,16 @@ class DataFrameFactory:
|
||||||
"origin": helpers.callsign_to_bytes(self.myfullcall),
|
"origin": helpers.callsign_to_bytes(self.myfullcall),
|
||||||
}
|
}
|
||||||
return self.construct(FR_TYPE.PING, payload)
|
return self.construct(FR_TYPE.PING, payload)
|
||||||
|
|
||||||
|
def build_ping_ack(self, destination, snr):
|
||||||
|
payload = {
|
||||||
|
"destination_crc": helpers.get_crc_24(destination),
|
||||||
|
"origin_crc": helpers.get_crc_24(self.myfullcall),
|
||||||
|
"gridsquare": helpers.encode_grid(self.mygrid),
|
||||||
|
"snr": helpers.snr_to_bytes(snr)
|
||||||
|
}
|
||||||
|
return self.construct(FR_TYPE.PING_ACK, payload)
|
||||||
|
|
||||||
def build_cq(self):
|
def build_cq(self):
|
||||||
payload = {
|
payload = {
|
||||||
"origin": helpers.callsign_to_bytes(self.myfullcall),
|
"origin": helpers.callsign_to_bytes(self.myfullcall),
|
||||||
|
|
|
@ -21,6 +21,7 @@ from protocol_arq import ARQ
|
||||||
from protocol_arq_session import SESSION
|
from protocol_arq_session import SESSION
|
||||||
|
|
||||||
from frame_handler import FrameHandler
|
from frame_handler import FrameHandler
|
||||||
|
from frame_handler_ping import PingFrameHandler
|
||||||
|
|
||||||
class DISPATCHER():
|
class DISPATCHER():
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ class DISPATCHER():
|
||||||
FR_TYPE.FR_NACK.value: {"class": FrameHandler, "name": "FRAME NACK"},
|
FR_TYPE.FR_NACK.value: {"class": FrameHandler, "name": "FRAME NACK"},
|
||||||
FR_TYPE.FR_REPEAT.value: {"class": FrameHandler, "name": "REPEAT REQUEST"},
|
FR_TYPE.FR_REPEAT.value: {"class": FrameHandler, "name": "REPEAT REQUEST"},
|
||||||
FR_TYPE.PING_ACK.value: {"class": FrameHandler, "name": "PING ACK"},
|
FR_TYPE.PING_ACK.value: {"class": FrameHandler, "name": "PING ACK"},
|
||||||
FR_TYPE.PING.value: {"class": FrameHandler, "name": "PING"},
|
FR_TYPE.PING.value: {"class": PingFrameHandler, "name": "PING"},
|
||||||
FR_TYPE.QRV.value: {"class": FrameHandler, "name": "QRV"},
|
FR_TYPE.QRV.value: {"class": FrameHandler, "name": "QRV"},
|
||||||
FR_TYPE.IS_WRITING.value: {"class": FrameHandler, "name": "IS_WRITING"},
|
FR_TYPE.IS_WRITING.value: {"class": FrameHandler, "name": "IS_WRITING"},
|
||||||
FR_TYPE.FEC.value: {"class": FrameHandler, "name": "FEC"},
|
FR_TYPE.FEC.value: {"class": FrameHandler, "name": "FEC"},
|
||||||
|
@ -169,6 +170,7 @@ class DISPATCHER():
|
||||||
# instantiate handler
|
# instantiate handler
|
||||||
handler_class = self.FRAME_HANDLER[frametype]['class']
|
handler_class = self.FRAME_HANDLER[frametype]['class']
|
||||||
handler = handler_class(self.FRAME_HANDLER[frametype]['name'],
|
handler = handler_class(self.FRAME_HANDLER[frametype]['name'],
|
||||||
|
self.config,
|
||||||
self.states,
|
self.states,
|
||||||
self.event_manager,
|
self.event_manager,
|
||||||
MODEM_TRANSMIT_QUEUE,
|
MODEM_TRANSMIT_QUEUE,
|
||||||
|
|
|
@ -3,41 +3,75 @@ from event_manager import EventManager
|
||||||
from state_manager import StateManager
|
from state_manager import StateManager
|
||||||
from queue import Queue
|
from queue import Queue
|
||||||
import structlog
|
import structlog
|
||||||
|
import time, uuid
|
||||||
|
from codec2 import FREEDV_MODE
|
||||||
|
|
||||||
class FrameHandler():
|
class FrameHandler():
|
||||||
|
|
||||||
def __init__(self, name: str, states: StateManager, event_manager: EventManager,
|
def __init__(self, name: str, config, states: StateManager, event_manager: EventManager,
|
||||||
tx_frame_queue: Queue,
|
tx_frame_queue: Queue,
|
||||||
arq_sessions: list) -> None:
|
arq_sessions: list) -> None:
|
||||||
|
|
||||||
self.name = name
|
self.name = name
|
||||||
|
self.config = config
|
||||||
self.states = states
|
self.states = states
|
||||||
self.event_manager = event_manager
|
self.event_manager = event_manager
|
||||||
self.tx_trame_queue = tx_frame_queue
|
self.tx_frame_queue = tx_frame_queue
|
||||||
self.arq_sessions = arq_sessions
|
self.arq_sessions = arq_sessions
|
||||||
self.logger = structlog.get_logger("Frame Handler")
|
self.logger = structlog.get_logger("Frame Handler")
|
||||||
|
|
||||||
def add_to_heard_stations(self):
|
self.details = {
|
||||||
pass
|
'frame' : None,
|
||||||
|
'snr' : 0,
|
||||||
def make_event(self, frame):
|
'freq_offset': 0,
|
||||||
return {
|
'freedv_inst': None,
|
||||||
"freedata": "generic frame handler",
|
'bytes_per_frame': 0
|
||||||
"frame": frame,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def emit_event(self, frame):
|
def add_to_heard_stations(self):
|
||||||
event_data = self.make_event(frame)
|
frame = self.details['frame']
|
||||||
|
dxgrid = frame['gridsquare'] if 'gridsquare' in frame else "------"
|
||||||
|
helpers.add_to_heard_stations(
|
||||||
|
frame['origin'],
|
||||||
|
dxgrid,
|
||||||
|
self.name,
|
||||||
|
self.details['snr'],
|
||||||
|
self.details['freq_offset'],
|
||||||
|
self.states.radio_frequency,
|
||||||
|
self.states.heard_stations,
|
||||||
|
)
|
||||||
|
|
||||||
|
def make_event(self):
|
||||||
|
event = {
|
||||||
|
"freedata": "modem-message",
|
||||||
|
"uuid": str(uuid.uuid4()),
|
||||||
|
"timestamp": int(time.time()),
|
||||||
|
"mycallsign": self.config['STATION']['mycall'],
|
||||||
|
"snr": str(self.details['snr']),
|
||||||
|
}
|
||||||
|
if 'origin' in self.details['frame']:
|
||||||
|
event['dxcallsign'] = self.details['frame']['origin']
|
||||||
|
return event
|
||||||
|
|
||||||
|
def emit_event(self):
|
||||||
|
event_data = self.make_event()
|
||||||
self.event_manager.broadcast(event_data)
|
self.event_manager.broadcast(event_data)
|
||||||
|
|
||||||
def make_modem_queue_item(self, mode, repeat, repeat_delay, frame):
|
def make_modem_queue_item(self, mode, repeat, repeat_delay, frame):
|
||||||
return {
|
return {
|
||||||
'mode': self.get_tx_mode(),
|
'mode': self.get_tx_mode(),
|
||||||
'repeat': 1,
|
'repeat': repeat,
|
||||||
'repeat_delay': 0,
|
'repeat_delay': repeat_delay,
|
||||||
'frame': frame,
|
'frame': frame,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def get_tx_mode(self):
|
||||||
|
return (
|
||||||
|
FREEDV_MODE.fsk_ldpc_0.value
|
||||||
|
if self.config['MODEM']['enable_fsk']
|
||||||
|
else FREEDV_MODE.sig0.value
|
||||||
|
)
|
||||||
|
|
||||||
def transmit(self, frame):
|
def transmit(self, frame):
|
||||||
tx_queue_item = self.make_modem_queue_item(self.get_tx_mode(), 1, 0, frame)
|
tx_queue_item = self.make_modem_queue_item(self.get_tx_mode(), 1, 0, frame)
|
||||||
self.tx_frame_queue.put(tx_queue_item)
|
self.tx_frame_queue.put(tx_queue_item)
|
||||||
|
@ -45,12 +79,18 @@ class FrameHandler():
|
||||||
def follow_protocol(self):
|
def follow_protocol(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def log(self, frame):
|
def log(self):
|
||||||
self.logger.info(f"[Frame Handler] Handling frame {frame}")
|
self.logger.info(f"[Frame Handler] Handling frame {self.details['frame']}")
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def handle(self, frame, snr, freq_offset, freedv_inst, bytes_per_frame):
|
def handle(self, frame, snr, freq_offset, freedv_inst, bytes_per_frame):
|
||||||
self.log(frame)
|
self.details['frame'] = frame
|
||||||
|
self.details['snr'] = snr
|
||||||
|
self.details['freq_offset'] = freq_offset
|
||||||
|
self.details['freedv_inst'] = freedv_inst
|
||||||
|
self.details['bytes_per_frame'] = bytes_per_frame
|
||||||
|
|
||||||
|
self.log()
|
||||||
self.add_to_heard_stations()
|
self.add_to_heard_stations()
|
||||||
self.emit_event(frame)
|
self.emit_event()
|
||||||
self.follow_protocol()
|
self.follow_protocol()
|
||||||
|
|
42
modem/frame_handler_ping.py
Normal file
42
modem/frame_handler_ping.py
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
import frame_handler
|
||||||
|
import helpers
|
||||||
|
import data_frame_factory
|
||||||
|
|
||||||
|
class PingFrameHandler(frame_handler.FrameHandler):
|
||||||
|
|
||||||
|
def make_event(self):
|
||||||
|
event = super().make_event()
|
||||||
|
event['ping'] = "received"
|
||||||
|
return event
|
||||||
|
|
||||||
|
def follow_protocol(self):
|
||||||
|
deconstructed_frame = self.details['frame']
|
||||||
|
origin = deconstructed_frame["origin"]
|
||||||
|
|
||||||
|
# check if callsign ssid override
|
||||||
|
valid, mycallsign = helpers.check_callsign(
|
||||||
|
self.config['STATION']['mycall'],
|
||||||
|
deconstructed_frame["destination_crc"],
|
||||||
|
self.config['STATION']['ssid_list'])
|
||||||
|
|
||||||
|
if not valid:
|
||||||
|
# PING packet not for me.
|
||||||
|
self.logger.debug("[Modem] received_ping: ping not for this station.")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.dxcallsign_crc = deconstructed_frame["origin_crc"]
|
||||||
|
self.dxcallsign = origin
|
||||||
|
self.logger.info(
|
||||||
|
f"[Modem] PING REQ from [{origin}] to [{mycallsign}]",
|
||||||
|
snr=self.details['snr'],
|
||||||
|
)
|
||||||
|
|
||||||
|
self.send_ack()
|
||||||
|
|
||||||
|
def send_ack(self):
|
||||||
|
factory = data_frame_factory.DataFrameFactory(self.config)
|
||||||
|
ping_ack_frame = factory.build_ping_ack(
|
||||||
|
self.details['frame']['origin_crc'],
|
||||||
|
self.details['snr']
|
||||||
|
)
|
||||||
|
self.transmit(ping_ack_frame)
|
Loading…
Reference in a new issue