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!
Fill grid with common 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"
>
-
-
-
+
-
+
- Clear grid
-
+ 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 @@
- {{ btnText}}
+
+ {{ btnText }}
+
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