diff --git a/gui/src/components/dynamic_components2.vue b/gui/src/components/dynamic_components2.vue index af051179..149b9400 100644 --- a/gui/src/components/dynamic_components2.vue +++ b/gui/src/components/dynamic_components2.vue @@ -51,7 +51,8 @@ const gridWidgets = [ { x: 0, y: 0, w: 16, h: 40 }, "Detailed heard stations list", true, - true,"Activity" + true, + "Activity", ), new gridWidget( active_stats, @@ -59,7 +60,7 @@ const gridWidgets = [ "Stats (waterfall, etc)", true, true, - "Stats" + "Stats", ), new gridWidget( active_audio_level, @@ -75,7 +76,7 @@ const gridWidgets = [ "Rig control main", true, true, - "Rig" + "Rig", ), new gridWidget( active_broadcats, @@ -83,7 +84,7 @@ const gridWidgets = [ "Broadcats main", true, true, - "Broadcasts" + "Broadcasts", ), new gridWidget( mini_heard_stations, @@ -91,16 +92,23 @@ const gridWidgets = [ "Mini heard stations list", false, true, - "Activity" + "Activity", + ), + new gridWidget( + s_meter, + { x: 1, y: 1, w: 4, h: 8 }, + "S-Meter", + false, + true, + "Rig", ), - new gridWidget(s_meter, { x: 1, y: 1, w: 4, h: 8 }, "S-Meter", false, true, "Rig"), new gridWidget( dbfs_meter, { x: 1, y: 1, w: 4, h: 8 }, "Dbfs Meter", false, true, - "Audio" + "Audio", ), new gridWidget( grid_activities, @@ -110,7 +118,6 @@ const gridWidgets = [ true, "Activity", ), - ]; onMounted(() => { grid = GridStack.init({ @@ -137,23 +144,23 @@ onMounted(() => { grid.on("change", onChange); - gridWidgets.forEach((gw) =>{ + gridWidgets.forEach((gw) => { //Dynamically add widgets to widget menu let dom = document.getElementById("otherBod"); switch (gw.category) { case "Activity": dom = document.getElementById("actBody"); break; - case "Stats": + case "Stats": dom = document.getElementById("statsBody"); break; - case "Audio": + case "Audio": dom = document.getElementById("audioBody"); break; - case "Rig": + case "Rig": dom = document.getElementById("rigBody"); break; - case "Broadcasts": + case "Broadcasts": dom = document.getElementById("bcBody"); break; default: @@ -161,7 +168,7 @@ onMounted(() => { break; } var index = gridWidgets.findIndex((w) => gw.text == w.text); - dom.insertAdjacentHTML("beforeend",`
`); + dom.insertAdjacentHTML("beforeend", `
`); let dom2 = document.getElementById(`gridbtn-${index}`); let vueComponent = h(grid_button,{btnText: gw.text,btnID:index}); render(vueComponent,dom2); @@ -274,7 +281,7 @@ function quickfill() {
Manage grid widgets
- +
-

Grid widgets allow you to customize the display for your own usage. Here you may add additional widgets to fit your needs. - You can move and resize the individual widgets! +

+ Grid widgets allow you to customize the display for your own usage. Here + you may add additional widgets to fit your needs. You can move and + resize the individual widgets!

- -
-
+
@@ -320,9 +327,7 @@ function quickfill() { aria-labelledby="headingHeardStations" data-bs-parent="#accordionExample" > -
- -
+
@@ -346,9 +351,7 @@ function quickfill() { aria-labelledby="headingActivities" data-bs-parent="#accordionExample" > -
- -
+
@@ -371,9 +374,7 @@ function quickfill() { aria-labelledby="headingBroadcasts" data-bs-parent="#accordionExample" > -
- -
+
@@ -396,9 +397,7 @@ function quickfill() { aria-labelledby="headingRadioControl" data-bs-parent="#accordionExample" > -
- -
+
@@ -422,9 +421,7 @@ function quickfill() { aria-labelledby="headingAudioControl" data-bs-parent="#accordionExample" > -
- -
+
@@ -448,20 +445,18 @@ function quickfill() { aria-labelledby="headingStatistics" data-bs-parent="#accordionExample" > -
- -
+
-
+
+ class="btn btn-sm btn-outline-warning" + type="button" + @click="clearAllItems" + > + Clear grid + diff --git a/gui/src/components/grid/button.vue b/gui/src/components/grid/button.vue index 5a6ef5a8..265c4ff3 100644 --- a/gui/src/components/grid/button.vue +++ b/gui/src/components/grid/button.vue @@ -1,12 +1,13 @@ diff --git a/modem/arq_session_irs.py b/modem/arq_session_irs.py index 677fb79d..99ff6dcd 100644 --- a/modem/arq_session_irs.py +++ b/modem/arq_session_irs.py @@ -13,7 +13,7 @@ class ARQSessionIRS(arq_session.ARQSession): RETRIES_CONNECT = 3 RETRIES_TRANSFER = 3 - TIMEOUT_DATA = 2 + TIMEOUT_DATA = 6 def __init__(self, config: dict, tx_frame_queue: queue.Queue, dxcall: str, session_id: int): super().__init__(config, tx_frame_queue, dxcall) @@ -35,7 +35,7 @@ class ARQSessionIRS(arq_session.ARQSession): pass def set_state(self, state): - self.log(f"ARQ Session {self.id} state {self.state}") + self.log(f"ARQ Session IRS {self.id} state {self.state}") self.state = state def set_modem_decode_modes(self, modes): @@ -50,24 +50,25 @@ class ARQSessionIRS(arq_session.ARQSession): self.transmit_frame(ack_frame) self.set_modem_decode_modes(None) - self.state = self.STATE_WAITING_DATA while self.state == self.STATE_WAITING_DATA: if not self.event_data_received.wait(self.TIMEOUT_DATA): self.log("Timeout waiting for data") self.state = self.STATE_FAILED return - + self.log("Finished ARQ IRS session") def run(self): self.thread = threading.Thread(target=self.runner, name=f"ARQ IRS Session {self.id}", daemon=True) - self.thread.run() + self.thread.start() + def on_data_received(self, data_frame): if self.state != self.STATE_WAITING_DATA: - raise RuntimeError(f"ARQ Session: Received data while in state {self.state}") + raise RuntimeError(f"ARQ Session: Received data while in state {self.state}, expected {self.STATE_WAITING_DATA}") + self.received_data = data_frame["data"] self.event_data_received.set() @@ -87,3 +88,4 @@ class ARQSessionIRS(arq_session.ARQSession): self.event_connection_ack_received.clear() self.event_transfer_feedback.set() self.event_transfer_feedback.clear() + self.received_data = b'' diff --git a/modem/arq_session_iss.py b/modem/arq_session_iss.py index 544d5457..39a6cd73 100644 --- a/modem/arq_session_iss.py +++ b/modem/arq_session_iss.py @@ -35,7 +35,7 @@ class ARQSessionISS(arq_session.ARQSession): return random.randint(1,255) def set_state(self, state): - self.logger.info(f"ARQ Session {self.id} state {self.state}") + self.logger.info(f"ARQ Session ISS {self.id} state {self.state}") self.state = state def runner(self): @@ -49,7 +49,7 @@ class ARQSessionISS(arq_session.ARQSession): self.thread.run() def connect(self): - self.state = self.STATE_CONNECTING + self.state = self.STATE_CONNECTING connect_frame = self.frame_factory.build_arq_session_connect(True, self.dxcall, self.id) @@ -69,9 +69,10 @@ class ARQSessionISS(arq_session.ARQSession): if self.state != self.STATE_CONNECTING: raise RuntimeError(f"ARQ Session: Received connection ACK while in state {self.state}") - self.speed_level = ack['speed_level'] + self.build_arq_data_framespeed_level = ack['speed_level'] self.event_connection_ack_received.set() + # Sends the full payload in multiple frames def send_data(self): # Todo make this n frames per burst stuff part of the protocol again @@ -84,6 +85,7 @@ class ARQSessionISS(arq_session.ARQSession): max_size = self.get_payload_size(self.speed_level) end_offset = min(len(self.data), max_size) frame_payload = self.data[offset:end_offset] + print(self.id) data_frame = self.frame_factory.build_arq_data_frame(self.id, n_frames_per_burst, max_size, n_frame, frame_payload) self.set_state(self.STATE_SENDING) if not self.send_arq(data_frame): diff --git a/modem/data_frame_factory.py b/modem/data_frame_factory.py index 365206b5..50e9e5f0 100644 --- a/modem/data_frame_factory.py +++ b/modem/data_frame_factory.py @@ -127,12 +127,12 @@ class DataFrameFactory: # arq data frame # register n frames - for n_frame in range(0,50): - self.template_list[FR_TYPE.BURST_01.value + n_frame] = { + for n_frame in range(1,5): + self.template_list[FR_TYPE.BURST_01.value + (n_frame-1)] = { "frame_length": "dynamic", "n_frames_per_burst": 1, "session_id": 1, - "payload": "dynamic", + "data": "dynamic", } # arq burst ack @@ -175,18 +175,19 @@ class DataFrameFactory: def construct(self, frametype, content, frame_length=LENGTH_SIG1_FRAME): # frame_length: can be set manually for data frames, whose length can be dynamic regarding corresponding mode - # data bursts have a frame type range of 01-50 if frametype in range(1, 50): - frame_template = self.template_list[frametype.value] + frame_template = self.template_list[frametype] frame = bytearray(frame_length) # override "dynamic" value of payload length - self.template_list[frame_template].payload = frame_length - 3 + self.template_list[frametype]["data"] = frame_length - 3 + frame[:1] = bytes([frametype]) else: frame_template = self.template_list[frametype.value] frame_length = frame_template["frame_length"] frame = bytearray(frame_length) + frame[:1] = bytes([frametype.value]) buffer_position = 1 for key, item_length in frame_template.items(): @@ -194,7 +195,6 @@ class DataFrameFactory: frame[buffer_position: buffer_position + item_length] = content[key] buffer_position += item_length - frame[:1] = bytes([frametype.value]) return frame def deconstruct(self, frame): @@ -212,16 +212,24 @@ class DataFrameFactory: for key, item_length in frame_template.items(): if key != "frame_length": - data = frame[buffer_position: buffer_position + item_length] + # data is always on the last payload slots + if item_length in ["dynamic"] and key in["data"]: + data = frame[buffer_position:] + item_length = len(data) + else: + data = frame[buffer_position: buffer_position + item_length] # Process the data based on the key if key in ["origin", "destination"]: extracted_data[key] = helpers.bytes_to_callsign(data).decode() + if key in ["origin_crc", "destination_crc"]: + extracted_data[key] = data.hex() + elif key == "gridsquare": extracted_data[key] = helpers.decode_grid(data) - elif key in ["session_id", "speed_level"]: + elif key in ["session_id", "speed_level", "n_frames_per_burst"]: extracted_data[key] = int.from_bytes(data, 'big') else: @@ -319,9 +327,7 @@ class DataFrameFactory: return test_frame def build_arq_session_connect(self, isWideband, destination, session_id): - print(isWideband) - print(destination) - print(session_id) + payload = { "destination_crc": helpers.get_crc_24(destination), "origin_crc": helpers.get_crc_24(self.myfullcall), @@ -351,11 +357,11 @@ class DataFrameFactory: def build_arq_data_frame(self, session_id: bytes, n_frames_per_burst: int, max_size: int, n_frame: int, frame_payload: bytes): payload = { "n_frames_per_burst": bytes([n_frames_per_burst]), - "session_id": session_id, + "session_id": session_id.to_bytes(1, 'big'), "data": frame_payload } - return self.construct(FR_TYPE.FR_TYPE.BURST_01.value + n_frame, payload, frame_length=max_size) + return self.construct(FR_TYPE.BURST_01.value + (n_frame-1), payload, frame_length=max_size) def build_arq_burst_ack(self, session_id: bytes, snr: int, speed_level: int, len_arq_rx_frame_buffer: int): diff --git a/modem/frame_dispatcher.py b/modem/frame_dispatcher.py index b3a1a04f..f43b8a16 100644 --- a/modem/frame_dispatcher.py +++ b/modem/frame_dispatcher.py @@ -35,6 +35,7 @@ class DISPATCHER(): FR_TYPE.ARQ_CONNECTION_OPEN.value: {"class": ARQFrameHandler, "name": "ARQ OPEN SESSION"}, FR_TYPE.ARQ_STOP.value: {"class": ARQFrameHandler, "name": "ARQ STOP TX"}, FR_TYPE.BEACON.value: {"class": FrameHandler, "name": "BEACON"}, + FR_TYPE.BURST_01.value:{"class": ARQFrameHandler, "name": "BURST_01"}, FR_TYPE.BURST_ACK.value: {"class": FrameHandler, "name": "BURST ACK"}, FR_TYPE.BURST_NACK.value: {"class": FrameHandler, "name": "BURST NACK"}, FR_TYPE.CQ.value: {"class": CQFrameHandler, "name": "CQ"}, diff --git a/modem/frame_handler_arq_session.py b/modem/frame_handler_arq_session.py index f929763a..d6a37eec 100644 --- a/modem/frame_handler_arq_session.py +++ b/modem/frame_handler_arq_session.py @@ -23,3 +23,9 @@ class ARQFrameHandler(frame_handler.FrameHandler): if frame['frame_type_int'] in [FR.ARQ_SESSION_OPEN_ACK_N.value, FR.ARQ_SESSION_OPEN_ACK_W.value]: iss_session:ARQSessionISS = self.states.get_arq_iss_session(frame['session_id']) iss_session.on_connection_ack_received(frame) + + # ARQ session data frame received + if frame['frame_type_int'] in [FR.BURST_01.value, FR.BURST_02.value, FR.BURST_03.value, FR.BURST_04.value, FR.BURST_05.value]: + print("received data frame....") + irs_session:ARQSessionIRS = self.states.get_arq_irs_session(frame['session_id']) + irs_session.on_data_received(frame) \ No newline at end of file diff --git a/modem/modem_frametypes.py b/modem/modem_frametypes.py index ce315c9e..23e07c4f 100644 --- a/modem/modem_frametypes.py +++ b/modem/modem_frametypes.py @@ -11,8 +11,7 @@ class FRAME_TYPE(Enum): BURST_02 = 2 BURST_03 = 3 BURST_04 = 4 - # ... - BURST_50 = 50 + BURST_05 = 5 BURST_ACK = 60 FR_ACK = 61 FR_REPEAT = 62