mirror of
https://github.com/DJ2LS/FreeDATA
synced 2024-05-14 08:04:33 +00:00
ARQ progress
This commit is contained in:
parent
c98b37db96
commit
9bbdaa055a
5 changed files with 30 additions and 21 deletions
|
@ -24,11 +24,6 @@ class ARQSession():
|
||||||
|
|
||||||
self.id = None
|
self.id = None
|
||||||
|
|
||||||
# 3 bytes for the BOF Beginning of File indicator in a data frame
|
|
||||||
self.data_frame_bof = b"BOF"
|
|
||||||
# 3 bytes for the EOF End of File indicator in a data frame
|
|
||||||
self.data_frame_eof = b"EOF"
|
|
||||||
|
|
||||||
def log(self, message, isWarning = False):
|
def log(self, message, isWarning = False):
|
||||||
msg = f"[{type(self).__name__}]: {message}"
|
msg = f"[{type(self).__name__}]: {message}"
|
||||||
logger = self.logger.warn if isWarning else self.logger.info
|
logger = self.logger.warn if isWarning else self.logger.info
|
||||||
|
|
|
@ -94,7 +94,8 @@ class ARQSessionIRS(arq_session.ARQSession):
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
self.set_state(self.STATE_WAITING_DATA)
|
self.set_state(self.STATE_WAITING_DATA)
|
||||||
self.thread = threading.Thread(target=self.runner, name=f"ARQ IRS Session {self.id}", daemon=False)
|
self.thread = threading.Thread(target=self.runner,
|
||||||
|
name=f"ARQ IRS Session {self.id}", daemon=False)
|
||||||
self.thread.start()
|
self.thread.start()
|
||||||
|
|
||||||
def send_open_ack(self):
|
def send_open_ack(self):
|
||||||
|
@ -123,6 +124,10 @@ class ARQSessionIRS(arq_session.ARQSession):
|
||||||
self.frames_per_burst = self.frames_per_burst
|
self.frames_per_burst = self.frames_per_burst
|
||||||
|
|
||||||
def on_info_received(self, frame):
|
def on_info_received(self, frame):
|
||||||
|
if self.state != self.STATE_CONN_REQ_RECEIVED:
|
||||||
|
self.logger.warning("Discarding received INFO.")
|
||||||
|
return
|
||||||
|
|
||||||
self.received_data = bytearray(frame['total_length'])
|
self.received_data = bytearray(frame['total_length'])
|
||||||
self.received_crc = frame['total_crc']
|
self.received_crc = frame['total_crc']
|
||||||
self.dx_snr = frame['snr']
|
self.dx_snr = frame['snr']
|
||||||
|
@ -134,7 +139,8 @@ class ARQSessionIRS(arq_session.ARQSession):
|
||||||
|
|
||||||
def on_data_received(self, frame):
|
def on_data_received(self, frame):
|
||||||
if self.state != self.STATE_WAITING_DATA:
|
if self.state != self.STATE_WAITING_DATA:
|
||||||
raise RuntimeError(f"ARQ Session: Received data while in state {self.state}, expected {self.STATE_WAITING_DATA}")
|
self.logger.warning(f"ARQ Session: Received data while in state {self.state}. Ignoring.")
|
||||||
|
return
|
||||||
|
|
||||||
self.received_frame = frame
|
self.received_frame = frame
|
||||||
self.event_data_received.set()
|
self.event_data_received.set()
|
||||||
|
@ -144,10 +150,10 @@ class ARQSessionIRS(arq_session.ARQSession):
|
||||||
self.logger.info(f"Discarding data frame due to wrong offset", frame=self.frame_received)
|
self.logger.info(f"Discarding data frame due to wrong offset", frame=self.frame_received)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
remaining_data_length = len(self.receive_data) - self.received_bytes
|
remaining_data_length = len(self.received_data) - self.received_bytes
|
||||||
|
|
||||||
# Is this the last data part?
|
# Is this the last data part?
|
||||||
if len(self.received_frame['data']) <= remaining_data_length:
|
if remaining_data_length <= len(self.received_frame['data']):
|
||||||
# we only want the remaining length, not the entire frame data
|
# we only want the remaining length, not the entire frame data
|
||||||
data_part = self.received_frame['data'][:remaining_data_length]
|
data_part = self.received_frame['data'][:remaining_data_length]
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -199,7 +199,7 @@ class DataFrameFactory:
|
||||||
if key in ["origin", "destination"]:
|
if key in ["origin", "destination"]:
|
||||||
extracted_data[key] = helpers.bytes_to_callsign(data).decode()
|
extracted_data[key] = helpers.bytes_to_callsign(data).decode()
|
||||||
|
|
||||||
elif key in ["origin_crc", "destination_crc"]:
|
elif key in ["origin_crc", "destination_crc", "total_crc"]:
|
||||||
extracted_data[key] = data.hex()
|
extracted_data[key] = data.hex()
|
||||||
|
|
||||||
elif key == "gridsquare":
|
elif key == "gridsquare":
|
||||||
|
@ -207,7 +207,7 @@ class DataFrameFactory:
|
||||||
|
|
||||||
elif key in ["session_id", "speed_level",
|
elif key in ["session_id", "speed_level",
|
||||||
"frames_per_burst", "version",
|
"frames_per_burst", "version",
|
||||||
"snr", "offset"]:
|
"snr", "offset", "total_length"]:
|
||||||
extracted_data[key] = int.from_bytes(data, 'big')
|
extracted_data[key] = int.from_bytes(data, 'big')
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -333,7 +333,7 @@ class DataFrameFactory:
|
||||||
payload = {
|
payload = {
|
||||||
"frame_length": self.LENGTH_SIG0_FRAME,
|
"frame_length": self.LENGTH_SIG0_FRAME,
|
||||||
"session_id": session_id.to_bytes(1, 'big'),
|
"session_id": session_id.to_bytes(1, 'big'),
|
||||||
"total_crc": total_crc,
|
"total_crc": bytes.fromhex(total_crc),
|
||||||
"snr": snr.to_bytes(1, 'big'),
|
"snr": snr.to_bytes(1, 'big'),
|
||||||
"speed_level": speed_level.to_bytes(1, 'big'),
|
"speed_level": speed_level.to_bytes(1, 'big'),
|
||||||
"frames_per_burst": frames_per_burst.to_bytes(1, 'big'),
|
"frames_per_burst": frames_per_burst.to_bytes(1, 'big'),
|
||||||
|
|
|
@ -9,19 +9,27 @@ from arq_session_iss import ARQSessionISS
|
||||||
class ARQFrameHandler(frame_handler.FrameHandler):
|
class ARQFrameHandler(frame_handler.FrameHandler):
|
||||||
|
|
||||||
def follow_protocol(self):
|
def follow_protocol(self):
|
||||||
# self.details == {'frame': {'frame_type': 'BURST_01', 'frame_type_int': 1, 'n_frames_per_burst': 1, 'session_id': 31, 'data': b'Hello world!'}, 'snr': 0, 'frequency_offset': 0, 'freedv_inst': None, 'bytes_per_frame': 15}
|
|
||||||
frame = self.details['frame']
|
frame = self.details['frame']
|
||||||
snr = self.details["snr"]
|
snr = self.details["snr"]
|
||||||
frequency_offset = self.details["frequency_offset"]
|
frequency_offset = self.details["frequency_offset"]
|
||||||
|
|
||||||
if frame['frame_type_int'] == FR.ARQ_SESSION_OPEN.value:
|
if frame['frame_type_int'] == FR.ARQ_SESSION_OPEN.value:
|
||||||
session = ARQSessionIRS(self.config,
|
# Lost OPEN_ACK case .. ISS will retry opening a session
|
||||||
self.tx_frame_queue,
|
if frame['session_id'] in self.states.arq_irs_sessions:
|
||||||
frame['origin'],
|
session = self.states.arq_irs_sessions[frame['session_id']]
|
||||||
frame['session_id'])
|
if session.state == ARQSessionIRS.STATE_CONN_REQ_RECEIVED:
|
||||||
self.states.register_arq_irs_session(session)
|
session.set_details(snr, frequency_offset)
|
||||||
session.set_details(snr, frequency_offset)
|
else:
|
||||||
session.run()
|
self.logger.warning(f"IRS Session conflict for session {session.id}")
|
||||||
|
# Normal case when receiving a SESSION_OPEN for the first time
|
||||||
|
else:
|
||||||
|
session = ARQSessionIRS(self.config,
|
||||||
|
self.tx_frame_queue,
|
||||||
|
frame['origin'],
|
||||||
|
frame['session_id'])
|
||||||
|
self.states.register_arq_irs_session(session)
|
||||||
|
session.set_details(snr, frequency_offset)
|
||||||
|
session.run()
|
||||||
|
|
||||||
elif frame['frame_type_int'] == FR.ARQ_SESSION_OPEN_ACK.value:
|
elif frame['frame_type_int'] == FR.ARQ_SESSION_OPEN_ACK.value:
|
||||||
session:ARQSessionISS = self.states.get_arq_iss_session(frame['session_id'])
|
session:ARQSessionISS = self.states.get_arq_iss_session(frame['session_id'])
|
||||||
|
|
|
@ -72,7 +72,7 @@ class TestARQSession(unittest.TestCase):
|
||||||
def testARQSession(self):
|
def testARQSession(self):
|
||||||
|
|
||||||
# set Packet Error Rate (PER) / frame loss probability
|
# set Packet Error Rate (PER) / frame loss probability
|
||||||
self.loss_probability = 50
|
self.loss_probability = 20
|
||||||
|
|
||||||
self.establishChannels()
|
self.establishChannels()
|
||||||
params = {
|
params = {
|
||||||
|
|
Loading…
Reference in a new issue