diff --git a/modem/deprecated_daemon.py b/modem/data cemetery/deprecated_daemon.py similarity index 100% rename from modem/deprecated_daemon.py rename to modem/data cemetery/deprecated_daemon.py diff --git a/modem/deprecated_main.py b/modem/data cemetery/deprecated_main.py similarity index 100% rename from modem/deprecated_main.py rename to modem/data cemetery/deprecated_main.py diff --git a/modem/deprecated_sock.py b/modem/data cemetery/deprecated_sock.py similarity index 100% rename from modem/deprecated_sock.py rename to modem/data cemetery/deprecated_sock.py diff --git a/modem/data_frame_factory.py b/modem/data_frame_factory.py index 0910f570..29ce8da0 100644 --- a/modem/data_frame_factory.py +++ b/modem/data_frame_factory.py @@ -99,9 +99,9 @@ class DataFrameFactory: } def _load_arq_templates(self): - # same structure for narrow and wide types - arq_dc_open_ack = { + + arq_dc_open = { "frame_length": self.LENGTH_SIG0_FRAME, "destination_crc": 3, "origin_crc": 3, @@ -109,9 +109,22 @@ class DataFrameFactory: "session_id": 1, } # arq connect frames + self.template_list[FR_TYPE.ARQ_DC_OPEN_N.value] = arq_dc_open + self.template_list[FR_TYPE.ARQ_DC_OPEN_W.value] = arq_dc_open + + # same structure for narrow and wide types + arq_dc_open_ack = { + "frame_length": self.LENGTH_SIG0_FRAME, + "session_id": 1, + "speed_level": 1, + "arq_protocol_version": 1 + } + # arq connect ack frames self.template_list[FR_TYPE.ARQ_DC_OPEN_ACK_N.value] = arq_dc_open_ack self.template_list[FR_TYPE.ARQ_DC_OPEN_ACK_W.value] = arq_dc_open_ack + + # arq burst ack self.template_list[FR_TYPE.BURST_ACK.value] = { "frame_length": self.LENGTH_SIG1_FRAME, @@ -288,9 +301,36 @@ class DataFrameFactory: "session_id": session_id.to_bytes(1, 'big'), } + channel_type = FR_TYPE.ARQ_DC_OPEN_W if isWideband else FR_TYPE.ARQ_DC_OPEN_N + return self.construct(channel_type, payload) + + def build_arq_connect_ack(self, isWideband, session_id, speed_level,arq_protocol_version): + + #connection_frame = bytearray(self.length_sig0_frame) + #connection_frame[:1] = frametype + #connection_frame[1:2] = self.session_id + #connection_frame[8:9] = bytes([self.speed_level]) + #connection_frame[13:14] = bytes([self.arq_protocol_version]) + + payload = { + "session_id": session_id.to_bytes(1, 'big'), + "speed_level": bytes([speed_level]), + "arq_protocol_version": bytes([arq_protocol_version]), + } + channel_type = FR_TYPE.ARQ_DC_OPEN_ACK_W if isWideband else FR_TYPE.ARQ_DC_OPEN_ACK_N return self.construct(channel_type, payload) + def build_arq_session_connect(self, isWideband, destination, session_id): + + payload = { + "destination_crc": helpers.get_crc_24(destination), + "origin_crc": helpers.get_crc_24(self.myfullcall), + "origin": helpers.callsign_to_bytes(self.myfullcall), + "session_id": session_id.to_bytes(1, 'big'), + } + return self.construct(FR_TYPE.ARQ_SESSION_OPEN, payload) + def build_arq_burst_ack(self, session_id: bytes, snr: int, speed_level: int, len_arq_rx_frame_buffer: int): # ack_frame = bytearray(self.length_sig1_frame) # ack_frame[:1] = bytes([FR_TYPE.BURST_ACK.value]) diff --git a/modem/protocol_arq_irs.py b/modem/protocol_arq_irs.py index 03910598..9f16e8bb 100644 --- a/modem/protocol_arq_irs.py +++ b/modem/protocol_arq_irs.py @@ -329,13 +329,14 @@ class IRS(ARQ): frametype = bytes([FR_TYPE.ARQ_DC_OPEN_ACK_W.value]) self.log.debug("[Modem] Responding with high bandwidth mode") - connection_frame = bytearray(self.length_sig0_frame) - connection_frame[:1] = frametype - connection_frame[1:2] = self.session_id - connection_frame[8:9] = bytes([self.speed_level]) - connection_frame[13:14] = bytes([self.arq_protocol_version]) - self.enqueue_frame_for_tx([connection_frame], c2_mode=FREEDV_MODE.sig0.value, copies=1, repeat_delay=0) + connection_ack_frame = self.frame_factory.build_arq_connect_ack( + session_id=self.session_id, + speed_level=self.speed_level, + arq_protocol_version=self.arq_protocol_version + ) + + self.enqueue_frame_for_tx([connection_ack_frame], c2_mode=FREEDV_MODE.sig0.value, copies=1, repeat_delay=0) self.event_manager.send_custom_event( freedata="modem-message", diff --git a/modem/protocol_arq_iss.py b/modem/protocol_arq_iss.py index 7a1b7fe7..17377c8e 100644 --- a/modem/protocol_arq_iss.py +++ b/modem/protocol_arq_iss.py @@ -626,83 +626,6 @@ class ISS(ARQ): ) return False - def open_session(self) -> bool: - """ - Create and send the frame to request a connection. - - Returns: - True if the session was opened successfully - False if the session open request failed - """ - self.IS_ARQ_SESSION_MASTER = True - self.states.set("arq_session_state", "connecting") - - # create a random session id - self.session_id = np.random.bytes(1) - - connection_frame = bytearray(self.length_sig0_frame) - connection_frame[:1] = bytes([FR_TYPE.ARQ_SESSION_OPEN.value]) - connection_frame[1:2] = self.session_id - connection_frame[2:5] = self.dxcallsign_crc - connection_frame[5:8] = self.mycallsign_crc - connection_frame[8:14] = helpers.callsign_to_bytes(self.mycallsign) - - while not self.states.is_arq_session: - threading.Event().wait(0.01) - for attempt in range(self.session_connect_max_retries): - self.log.info( - "[Modem] SESSION [" - + str(self.mycallsign, "UTF-8") - + "]>>?<<[" - + str(self.dxcallsign, "UTF-8") - + "]", - a=f"{str(attempt + 1)}/{str(self.session_connect_max_retries)}", - state=self.states.arq_session_state, - ) - - self.event_manager.send_custom_event( - freedata="modem-message", - arq="session", - status="connecting", - attempt=attempt + 1, - maxattempts=self.session_connect_max_retries, - mycallsign=str(self.mycallsign, 'UTF-8'), - dxcallsign=str(self.dxcallsign, 'UTF-8'), - ) - - self.enqueue_frame_for_tx([connection_frame], c2_mode=FREEDV_MODE.sig0.value, copies=1, repeat_delay=0) - - # Wait for a time, looking to see if `self.states.is_arq_session` - # indicates we've received a positive response from the far station. - timeout = time.time() + 3 - while time.time() < timeout: - threading.Event().wait(0.01) - # Stop waiting if data channel is opened - if self.states.is_arq_session: - return True - - # Stop waiting and interrupt if data channel is getting closed while opening - if self.states.arq_session_state == "disconnecting": - # disabled this session close as its called twice - # self.close_session() - return False - - # Session connect timeout, send close_session frame to - # attempt to clean up the far-side, if it received the - # open_session frame and can still hear us. - if not self.states.is_arq_session: - self.close_session() - return False - - # Given the while condition, it will only exit when `self.states.is_arq_session` is True - self.event_manager.send_custom_event( - freedata="modem-message", - arq="session", - status="connected", - mycallsign=str(self.mycallsign, 'UTF-8'), - dxcallsign=str(self.dxcallsign, 'UTF-8'), - ) - return True def open_dc_and_transmit( self, @@ -838,13 +761,11 @@ class ISS(ARQ): frametype = bytes([FR_TYPE.ARQ_DC_OPEN_W.value]) self.log.debug("[Modem] Requesting high bandwidth mode") - connection_frame = bytearray(self.length_sig0_frame) - connection_frame[:1] = frametype - connection_frame[1:4] = self.dxcallsign_crc - connection_frame[4:7] = self.mycallsign_crc - connection_frame[7:13] = helpers.callsign_to_bytes(mycallsign) - connection_frame[13:14] = self.session_id - + # build connection frame + connection_frame = self.frame_factory.build_arq_connect( + session_id=self.session_id, + destination_crc=self.dxcallsign_crc, + ) for attempt in range(self.data_channel_max_retries): self.event_manager.send_custom_event( diff --git a/modem/protocol_arq_session.py b/modem/protocol_arq_session.py index 332b5956..d0d9dcda 100644 --- a/modem/protocol_arq_session.py +++ b/modem/protocol_arq_session.py @@ -169,6 +169,82 @@ class SESSION(ARQ): MODEM_TRANSMIT_QUEUE.put(["morse", 1, 0, self.mycallsign]) self.arq_cleanup() + def open_session(self) -> bool: + """ + Create and send the frame to request a connection. + + Returns: + True if the session was opened successfully + False if the session open request failed + """ + self.IS_ARQ_SESSION_MASTER = True + self.states.set("arq_session_state", "connecting") + + # create a random session id + self.session_id = np.random.bytes(1) + + # build connection frame + connection_frame = self.frame_factory.build_arq_session_connect( + session_id=self.session_id, + destination_crc=self.dxcallsign_crc, + ) + while not self.states.is_arq_session: + threading.Event().wait(0.01) + for attempt in range(self.session_connect_max_retries): + self.log.info( + "[Modem] SESSION [" + + str(self.mycallsign, "UTF-8") + + "]>>?<<[" + + str(self.dxcallsign, "UTF-8") + + "]", + a=f"{str(attempt + 1)}/{str(self.session_connect_max_retries)}", + state=self.states.arq_session_state, + ) + + self.event_manager.send_custom_event( + freedata="modem-message", + arq="session", + status="connecting", + attempt=attempt + 1, + maxattempts=self.session_connect_max_retries, + mycallsign=str(self.mycallsign, 'UTF-8'), + dxcallsign=str(self.dxcallsign, 'UTF-8'), + ) + + self.enqueue_frame_for_tx([connection_frame], c2_mode=FREEDV_MODE.sig0.value, copies=1, repeat_delay=0) + + # Wait for a time, looking to see if `self.states.is_arq_session` + # indicates we've received a positive response from the far station. + timeout = time.time() + 3 + while time.time() < timeout: + threading.Event().wait(0.01) + # Stop waiting if data channel is opened + if self.states.is_arq_session: + return True + + # Stop waiting and interrupt if data channel is getting closed while opening + if self.states.arq_session_state == "disconnecting": + # disabled this session close as its called twice + # self.close_session() + return False + + # Session connect timeout, send close_session frame to + # attempt to clean up the far-side, if it received the + # open_session frame and can still hear us. + if not self.states.is_arq_session: + self.close_session() + return False + + # Given the while condition, it will only exit when `self.states.is_arq_session` is True + self.event_manager.send_custom_event( + freedata="modem-message", + arq="session", + status="connected", + mycallsign=str(self.mycallsign, 'UTF-8'), + dxcallsign=str(self.dxcallsign, 'UTF-8'), + ) + return True + def received_session_opener(self, data_in: bytes, snr) -> None: """ Received a session open request packet.