diff --git a/modem/arq_session.py b/modem/arq_session.py index 52fc129c..76b33189 100644 --- a/modem/arq_session.py +++ b/modem/arq_session.py @@ -45,10 +45,8 @@ class ARQSession(): self.id = None - self.final = False # class wide final state for stopping transmissions on command - def log(self, message, isWarning = False): - msg = f"[{type(self).__name__}][{self.state}]: {message}" + msg = f"[{type(self).__name__}][state={self.state}]: {message}" logger = self.logger.warn if isWarning else self.logger.info logger(msg) diff --git a/modem/arq_session_irs.py b/modem/arq_session_irs.py index bd40559b..770d84bc 100644 --- a/modem/arq_session_irs.py +++ b/modem/arq_session_irs.py @@ -68,6 +68,7 @@ class ARQSessionIRS(arq_session.ARQSession): self.received_crc = None self.transmitted_acks = 0 + self.final = False def set_decode_mode(self): self.modem.demodulator.set_decode_mode(self.get_mode_by_speed_level(self.speed_level)) @@ -204,7 +205,7 @@ class ARQSessionIRS(arq_session.ARQSession): self.speed_level = new_speed_level def stop_transmission(self): - self.log(f"Stopping transmission...., setting final flag") + self.log(f"Stopping transmission... setting final flag") self.final = True def send_stop_ack(self, stop_frame): diff --git a/modem/arq_session_iss.py b/modem/arq_session_iss.py index fc0b81c9..1ad7084b 100644 --- a/modem/arq_session_iss.py +++ b/modem/arq_session_iss.py @@ -15,7 +15,9 @@ class ISS_State(Enum): BURST_SENT = 3 ENDED = 4 FAILED = 5 - ABORTED = 6 + ABORT = 6 + ABORTING = 7 + ABORTED = 8 class ARQSessionISS(arq_session.ARQSession): @@ -41,6 +43,20 @@ class ARQSessionISS(arq_session.ARQSession): }, ISS_State.FAILED:{ FRAME_TYPE.ARQ_STOP_ACK.value: 'transmission_failed' + }, + ISS_State.ABORT: { + FRAME_TYPE.ARQ_BURST_ACK.value: 'abort_transmission', + FRAME_TYPE.ARQ_SESSION_OPEN_ACK.value: 'abort_transmission', + FRAME_TYPE.ARQ_SESSION_INFO_ACK.value: 'abort_transmission', + }, + ISS_State.ABORTING: { + FRAME_TYPE.ARQ_STOP_ACK.value: 'aborted', + FRAME_TYPE.ARQ_BURST_ACK.value: 'abort_transmission', + FRAME_TYPE.ARQ_SESSION_OPEN_ACK.value: 'abort_transmission', + FRAME_TYPE.ARQ_SESSION_INFO_ACK.value: 'abort_transmission', + }, + ISS_State.ABORTED: { + FRAME_TYPE.ARQ_STOP_ACK.value: 'aborted', } } @@ -54,13 +70,15 @@ class ARQSessionISS(arq_session.ARQSession): self.state = ISS_State.NEW self.id = self.generate_id() + self.retry = True + self.frame_factory = data_frame_factory.DataFrameFactory(self.config) def generate_id(self): return random.randint(1,255) def transmit_wait_and_retry(self, frame_or_burst, timeout, retries, mode): - while retries > 0 and not self.final: + while retries > 0 and self.state not in [ISS_State.ABORT, ISS_State.ABORTED]: self.event_frame_received = threading.Event() if isinstance(frame_or_burst, list): burst = frame_or_burst else: burst = [frame_or_burst] @@ -72,10 +90,13 @@ class ARQSessionISS(arq_session.ARQSession): return self.log("Timeout!") retries = retries - 1 + + if self.state == ISS_State.ABORTED: + self.log("session aborted initiated...") + return + self.set_state(ISS_State.FAILED) self.transmission_failed() - if self.final: - self.send_stop() def launch_twr(self, frame_or_burst, timeout, retries, mode): twr = threading.Thread(target = self.transmit_wait_and_retry, args=[frame_or_burst, timeout, retries, mode]) @@ -101,6 +122,7 @@ class ARQSessionISS(arq_session.ARQSession): self.set_state(ISS_State.INFO_SENT) def send_data(self, irs_frame): + self.set_speed_and_frames_per_burst(irs_frame) if 'offset' in irs_frame: @@ -114,7 +136,7 @@ class ARQSessionISS(arq_session.ARQSession): self.transmission_ended(irs_frame) return else: - self.transmission_failed(irs_frame) + self.transmission_failed() return payload_size = self.get_data_payload_size() @@ -136,16 +158,21 @@ class ARQSessionISS(arq_session.ARQSession): def transmission_failed(self, irs_frame): self.set_state(ISS_State.FAILED) - self.log(f"Transmission failed! flag_final={irs_frame['flag']['FINAL']}, flag_checksum={irs_frame['flag']['CHECKSUM']}") + self.log(f"Transmission failed!") self.event_manager.send_arq_session_finished(True, self.id, self.dxcall, len(self.data),False) - def stop_transmission(self): + def abort_transmission(self, irs_frame=None): self.log(f"Stopping transmission...") - self.set_state(ISS_State.FAILED) - self.final = True - + self.set_state(ISS_State.ABORTING) + # interrupt possible pending retries + self.retry = False + self.retry = True + self.send_stop() def send_stop(self): - self.final = False stop_frame = self.frame_factory.build_arq_stop(self.id) - self.launch_twr(stop_frame, self.TIMEOUT_CONNECT_ACK, self.RETRIES_CONNECT, mode=FREEDV_MODE.signalling) + self.launch_twr(stop_frame, 15, self.RETRIES_CONNECT, mode=FREEDV_MODE.signalling) + + def aborted(self, irs_frame): + self.log("session aborted") + self.set_state(ISS_State.ABORTED) \ No newline at end of file diff --git a/modem/frame_handler_arq_session.py b/modem/frame_handler_arq_session.py index 6e18a2de..c0bbef95 100644 --- a/modem/frame_handler_arq_session.py +++ b/modem/frame_handler_arq_session.py @@ -31,14 +31,14 @@ class ARQFrameHandler(frame_handler.FrameHandler): elif frame['frame_type_int'] in [ FR.ARQ_SESSION_INFO.value, FR.ARQ_BURST_FRAME.value, - ]: + FR.ARQ_STOP.value, + ]: session = self.states.get_arq_irs_session(session_id) elif frame['frame_type_int'] in [ FR.ARQ_SESSION_OPEN_ACK.value, FR.ARQ_SESSION_INFO_ACK.value, FR.ARQ_BURST_ACK.value, - FR.ARQ_STOP.value, FR.ARQ_STOP_ACK.value ]: session = self.states.get_arq_iss_session(session_id) diff --git a/modem/state_manager.py b/modem/state_manager.py index 3f692c56..6e4d89a0 100644 --- a/modem/state_manager.py +++ b/modem/state_manager.py @@ -146,9 +146,9 @@ class StateManager: def set_final_to_arq_transmissions(self): for id in self.arq_irs_sessions: - self.arq_irs_sessions[id].stop_transmission() + self.arq_irs_sessions[id].abort_transmission() for id in self.arq_iss_sessions: - self.arq_iss_sessions[id].stop_transmission() + self.arq_iss_sessions[id].abort_transmission() def add_activity(self, activity_data): # Generate a random 8-byte string as hex