From 30710fbb7e64aadd00a2a34492fa4a9efd8c697a Mon Sep 17 00:00:00 2001 From: codefactor-io Date: Sat, 9 Dec 2023 10:22:14 +0000 Subject: [PATCH 1/5] [CodeFactor] Apply fixes to commit bdc21d1 --- gui/src/components/dynamic_components2.vue | 105 ++++++++++----------- gui/src/components/grid/button.vue | 11 ++- 2 files changed, 56 insertions(+), 60 deletions(-) diff --git a/gui/src/components/dynamic_components2.vue b/gui/src/components/dynamic_components2.vue index d00de417..13097005 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,19 +168,19 @@ 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); - }) + let vueComponent = h(grid_button, { btnText: gw.text, btnID: index }); + render(vueComponent, dom2); + }); window.addEventListener( - "add-widget", - function (eventdata) { - let data = eventdata.detail; - addNewWidget2(gridWidgets[data]); - }, - false, - ); + "add-widget", + function (eventdata) { + let data = eventdata.detail; + addNewWidget2(gridWidgets[data]); + }, + false, + ); }); function onChange(event, changeItems) { // update item position @@ -273,7 +280,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!

- -
-
+
@@ -319,9 +326,7 @@ function quickfill() { aria-labelledby="headingHeardStations" data-bs-parent="#accordionExample" > -
- -
+
@@ -345,9 +350,7 @@ function quickfill() { aria-labelledby="headingActivities" data-bs-parent="#accordionExample" > -
- -
+
@@ -370,9 +373,7 @@ function quickfill() { aria-labelledby="headingBroadcasts" data-bs-parent="#accordionExample" > -
- -
+
@@ -395,9 +396,7 @@ function quickfill() { aria-labelledby="headingRadioControl" data-bs-parent="#accordionExample" > -
- -
+
@@ -421,9 +420,7 @@ function quickfill() { aria-labelledby="headingAudioControl" data-bs-parent="#accordionExample" > -
- -
+
@@ -447,20 +444,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 @@ From 9b820f65624d43c81572717e04c47c30179ddd74 Mon Sep 17 00:00:00 2001 From: DJ2LS Date: Sat, 9 Dec 2023 12:31:08 +0100 Subject: [PATCH 2/5] WIP adding arq data frame --- gui/package.json | 56 ++++++++++++++++++------------------- modem/arq_session_iss.py | 5 ++-- modem/data_frame_factory.py | 25 +++++++++-------- modem/frame_dispatcher.py | 1 + 4 files changed, 46 insertions(+), 41 deletions(-) diff --git a/gui/package.json b/gui/package.json index 4e2761a1..726620fc 100644 --- a/gui/package.json +++ b/gui/package.json @@ -32,57 +32,57 @@ }, "homepage": "https://freedata.app", "dependencies": { - "@electron/asar": "^3.2.7", - "@electron/notarize": "^2.1.0", - "@electron/universal": "^2.0.0", + "@electron/asar": "^3.2.8", + "@electron/notarize": "^2.2.0", + "@electron/universal": "^2.0.1", "@popperjs/core": "^2.11.8", - "@vueuse/electron": "^10.4.1", + "@vueuse/electron": "^10.7.0", "blob-util": "^2.0.2", - "bootstrap": "^5.3.1", - "bootstrap-icons": "^1.10.5", - "bootswatch": "^5.3.1", + "bootstrap": "^5.3.2", + "bootstrap-icons": "^1.11.2", + "bootswatch": "^5.3.2", "browser-image-compression": "^2.0.2", - "chart.js": "^4.3.3", + "chart.js": "^4.4.1", "chartjs-plugin-annotation": "^3.0.1", - "electron-log": "^5.0.0", - "electron-updater": "^6.1.6", - "emoji-picker-element": "^1.18.3", - "emoji-picker-element-data": "^1.4.0", + "electron-log": "^5.0.1", + "electron-updater": "^6.1.7", + "emoji-picker-element": "^1.20.1", + "emoji-picker-element-data": "^1.6.0", "file-saver": "^2.0.5", "gridstack": "^10.0.0", "mime": "^4.0.0", - "pinia": "^2.1.6", + "pinia": "^2.1.7", "pouchdb": "^8.0.1", "pouchdb-browser": "^8.0.1", "pouchdb-find": "^8.0.1", "pouchdb-upsert": "^2.2.0", "qth-locator": "^2.1.0", - "sass": "^1.66.1", + "sass": "^1.69.5", "socket.io": "^4.7.2", - "uuid": "^9.0.0", + "uuid": "^9.0.1", "vue": "^3.3.4", "vue-chartjs": "^5.2.0", "vuemoji-picker": "^0.2.0" }, "devDependencies": { - "@typescript-eslint/eslint-plugin": "^6.7.4", - "@vitejs/plugin-vue": "^4.4.0", - "electron": "^27.0.0", - "electron-builder": "^24.6.3", - "eslint": "^8.50.0", - "eslint-config-prettier": "^9.0.0", + "@typescript-eslint/eslint-plugin": "^6.13.2", + "@vitejs/plugin-vue": "^4.5.2", + "electron": "^27.1.3", + "electron-builder": "^24.9.1", + "eslint": "^8.55.0", + "eslint-config-prettier": "^9.1.0", "eslint-config-standard-with-typescript": "^40.0.0", - "eslint-plugin-import": "^2.28.1", - "eslint-plugin-n": "^16.1.0", - "eslint-plugin-prettier": "^5.0.0", + "eslint-plugin-import": "^2.29.0", + "eslint-plugin-n": "^16.3.1", + "eslint-plugin-prettier": "^5.0.1", "eslint-plugin-promise": "^6.1.1", - "eslint-plugin-vue": "^9.17.0", - "typescript": "^5.2.2", - "vite": "^5.0.4", + "eslint-plugin-vue": "^9.19.2", + "typescript": "^5.3.3", + "vite": "^5.0.7", "vite-plugin-electron": "^0.15.4", "vite-plugin-electron-renderer": "^0.14.5", "vitest": "^0.34.6", "vue": "^3.3.4", - "vue-tsc": "^1.4.2" + "vue-tsc": "^1.8.25" } } diff --git a/modem/arq_session_iss.py b/modem/arq_session_iss.py index 544d5457..ffa33259 100644 --- a/modem/arq_session_iss.py +++ b/modem/arq_session_iss.py @@ -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,7 +69,7 @@ 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 @@ -84,6 +84,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..3a18db3d 100644 --- a/modem/data_frame_factory.py +++ b/modem/data_frame_factory.py @@ -132,7 +132,7 @@ class DataFrameFactory: "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,7 +212,12 @@ 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"]: @@ -319,9 +324,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 +354,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"}, From f28e47f44155c32cb5f65e5959f34947b652dead Mon Sep 17 00:00:00 2001 From: DJ2LS Date: Sat, 9 Dec 2023 13:28:32 +0100 Subject: [PATCH 3/5] WIP adding arq data frame --- modem/arq_session_irs.py | 12 ++++++++---- modem/arq_session_iss.py | 3 ++- modem/data_frame_factory.py | 4 ++-- modem/frame_handler_arq_session.py | 7 +++++++ modem/modem_frametypes.py | 3 +-- 5 files changed, 20 insertions(+), 9 deletions(-) diff --git a/modem/arq_session_irs.py b/modem/arq_session_irs.py index 677fb79d..4a2cfe3e 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,13 +50,15 @@ 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 + else: + print("data received") + print(self.frame) self.log("Finished ARQ IRS session") @@ -66,8 +68,9 @@ class ARQSessionIRS(arq_session.ARQSession): 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 +90,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 ffa33259..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): @@ -72,6 +72,7 @@ class ARQSessionISS(arq_session.ARQSession): 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 diff --git a/modem/data_frame_factory.py b/modem/data_frame_factory.py index 3a18db3d..1d2b96b7 100644 --- a/modem/data_frame_factory.py +++ b/modem/data_frame_factory.py @@ -127,8 +127,8 @@ 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, diff --git a/modem/frame_handler_arq_session.py b/modem/frame_handler_arq_session.py index f929763a..df5e41d7 100644 --- a/modem/frame_handler_arq_session.py +++ b/modem/frame_handler_arq_session.py @@ -23,3 +23,10 @@ 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 From 73f6bba63018ce9584eae5f19479ce947025f90d Mon Sep 17 00:00:00 2001 From: DJ2LS Date: Sat, 9 Dec 2023 13:31:19 +0100 Subject: [PATCH 4/5] WIP adding arq data frame --- modem/data_frame_factory.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modem/data_frame_factory.py b/modem/data_frame_factory.py index 1d2b96b7..50e9e5f0 100644 --- a/modem/data_frame_factory.py +++ b/modem/data_frame_factory.py @@ -223,10 +223,13 @@ class DataFrameFactory: 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: From e3bca5bdc7e85170acd1c33e7fb446bd406834ec Mon Sep 17 00:00:00 2001 From: DJ2LS Date: Sat, 9 Dec 2023 14:16:53 +0100 Subject: [PATCH 5/5] WIP adding arq data frame --- modem/arq_session_irs.py | 8 +++----- modem/frame_handler_arq_session.py | 1 - 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/modem/arq_session_irs.py b/modem/arq_session_irs.py index 4a2cfe3e..99ff6dcd 100644 --- a/modem/arq_session_irs.py +++ b/modem/arq_session_irs.py @@ -56,15 +56,13 @@ class ARQSessionIRS(arq_session.ARQSession): self.log("Timeout waiting for data") self.state = self.STATE_FAILED return - else: - print("data received") - print(self.frame) - + 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: diff --git a/modem/frame_handler_arq_session.py b/modem/frame_handler_arq_session.py index df5e41d7..d6a37eec 100644 --- a/modem/frame_handler_arq_session.py +++ b/modem/frame_handler_arq_session.py @@ -24,7 +24,6 @@ class ARQFrameHandler(frame_handler.FrameHandler): 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....")