mirror of
https://github.com/DJ2LS/FreeDATA
synced 2024-05-14 08:04:33 +00:00
Merge branch 'develop' of github.com:DJ2LS/FreeDATA into develop
This commit is contained in:
commit
5f1597c27f
15 changed files with 96 additions and 68 deletions
|
@ -2,7 +2,7 @@
|
||||||
"name": "FreeDATA",
|
"name": "FreeDATA",
|
||||||
"description": "FreeDATA Client application for connecting to FreeDATA server",
|
"description": "FreeDATA Client application for connecting to FreeDATA server",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.14.4-alpha",
|
"version": "0.14.5-alpha",
|
||||||
"main": "dist-electron/main/index.js",
|
"main": "dist-electron/main/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "vite",
|
"start": "vite",
|
||||||
|
@ -77,7 +77,7 @@
|
||||||
"vite": "5.1.3",
|
"vite": "5.1.3",
|
||||||
"vite-plugin-electron": "0.28.2",
|
"vite-plugin-electron": "0.28.2",
|
||||||
"vite-plugin-electron-renderer": "0.14.5",
|
"vite-plugin-electron-renderer": "0.14.5",
|
||||||
"vitest": "1.2.2",
|
"vitest": "1.3.1",
|
||||||
"vue": "3.4.21",
|
"vue": "3.4.21",
|
||||||
"vue-tsc": "1.8.27"
|
"vue-tsc": "1.8.27"
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,7 +124,6 @@ import { loadAllData } from "../js/eventHandler";
|
||||||
<!-------------------------------- MAIN AREA ---------------->
|
<!-------------------------------- MAIN AREA ---------------->
|
||||||
|
|
||||||
<!------------------------------------------------------------------------------------------>
|
<!------------------------------------------------------------------------------------------>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -165,20 +165,20 @@ const audioStore = useAudioStore();
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="input-group input-group-sm mb-1">
|
<div class="input-group input-group-sm mb-1">
|
||||||
<label class="input-group-text w-50">Enable 250Hz bandwidth mode</label>
|
<label class="input-group-text w-50">Maximum used bandwidth</label>
|
||||||
<label class="input-group-text w-50">
|
<select
|
||||||
<div class="form-check form-switch form-check-inline">
|
class="form-select form-select-sm"
|
||||||
<input
|
id="maximum_bandwidth"
|
||||||
class="form-check-input"
|
@change="onChange"
|
||||||
type="checkbox"
|
v-model.number="settings.remote.MODEM.maximum_bandwidth"
|
||||||
id="250HzModeSwitch"
|
>
|
||||||
v-model="settings.remote.MODEM.enable_low_bandwidth_mode"
|
<option value="250">250 Hz</option>
|
||||||
@change="onChange"
|
<option value="563">563 Hz</option>
|
||||||
/>
|
<option value="1700">1700 Hz</option>
|
||||||
<label class="form-check-label" for="250HzModeSwitch">250Hz</label>
|
</select>
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="input-group input-group-sm mb-1">
|
<div class="input-group input-group-sm mb-1">
|
||||||
<label class="input-group-text w-50">Respond to CQ</label>
|
<label class="input-group-text w-50">Respond to CQ</label>
|
||||||
<label class="input-group-text w-50">
|
<label class="input-group-text w-50">
|
||||||
|
|
|
@ -54,11 +54,11 @@ const defaultConfig = {
|
||||||
enable_protocol: false,
|
enable_protocol: false,
|
||||||
},
|
},
|
||||||
MODEM: {
|
MODEM: {
|
||||||
enable_low_bandwidth_mode: false,
|
|
||||||
respond_to_cq: false,
|
respond_to_cq: false,
|
||||||
tx_delay: 0,
|
tx_delay: 0,
|
||||||
enable_hamc: false,
|
enable_hamc: false,
|
||||||
enable_morse_identifier: false,
|
enable_morse_identifier: false,
|
||||||
|
maximum_bandwidth: 3000,
|
||||||
},
|
},
|
||||||
RADIO: {
|
RADIO: {
|
||||||
control: "disabled",
|
control: "disabled",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import datetime
|
import datetime
|
||||||
import queue, threading
|
import threading
|
||||||
import codec2
|
import codec2
|
||||||
import data_frame_factory
|
import data_frame_factory
|
||||||
import structlog
|
import structlog
|
||||||
|
@ -9,23 +9,26 @@ import time
|
||||||
from arq_data_type_handler import ARQDataTypeHandler
|
from arq_data_type_handler import ARQDataTypeHandler
|
||||||
|
|
||||||
|
|
||||||
class ARQSession():
|
class ARQSession:
|
||||||
|
|
||||||
SPEED_LEVEL_DICT = {
|
SPEED_LEVEL_DICT = {
|
||||||
0: {
|
0: {
|
||||||
'mode': codec2.FREEDV_MODE.datac4,
|
'mode': codec2.FREEDV_MODE.datac4,
|
||||||
'min_snr': -10,
|
'min_snr': -10,
|
||||||
'duration_per_frame': 5.17,
|
'duration_per_frame': 5.17,
|
||||||
|
'bandwidth': 250,
|
||||||
},
|
},
|
||||||
1: {
|
1: {
|
||||||
'mode': codec2.FREEDV_MODE.datac3,
|
'mode': codec2.FREEDV_MODE.datac3,
|
||||||
'min_snr': 0,
|
'min_snr': 0,
|
||||||
'duration_per_frame': 3.19,
|
'duration_per_frame': 3.19,
|
||||||
|
'bandwidth': 563,
|
||||||
},
|
},
|
||||||
2: {
|
2: {
|
||||||
'mode': codec2.FREEDV_MODE.datac1,
|
'mode': codec2.FREEDV_MODE.datac1,
|
||||||
'min_snr': 3,
|
'min_snr': 3,
|
||||||
'duration_per_frame': 4.18,
|
'duration_per_frame': 4.18,
|
||||||
|
'bandwidth': 1700,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +66,7 @@ class ARQSession():
|
||||||
self.bpm_histogram = []
|
self.bpm_histogram = []
|
||||||
self.time_histogram = []
|
self.time_histogram = []
|
||||||
|
|
||||||
def log(self, message, isWarning = False):
|
def log(self, message, isWarning=False):
|
||||||
msg = f"[{type(self).__name__}][id={self.id}][state={self.state}]: {message}"
|
msg = f"[{type(self).__name__}][id={self.id}][state={self.state}]: {message}"
|
||||||
logger = self.logger.warn if isWarning else self.logger.info
|
logger = self.logger.warn if isWarning else self.logger.info
|
||||||
logger(msg)
|
logger(msg)
|
||||||
|
@ -99,21 +102,22 @@ class ARQSession():
|
||||||
self.event_frame_received.set()
|
self.event_frame_received.set()
|
||||||
self.log(f"Received {frame['frame_type']}")
|
self.log(f"Received {frame['frame_type']}")
|
||||||
frame_type = frame['frame_type_int']
|
frame_type = frame['frame_type_int']
|
||||||
if self.state in self.STATE_TRANSITION:
|
if self.state in self.STATE_TRANSITION and frame_type in self.STATE_TRANSITION[self.state]:
|
||||||
if frame_type in self.STATE_TRANSITION[self.state]:
|
action_name = self.STATE_TRANSITION[self.state][frame_type]
|
||||||
action_name = self.STATE_TRANSITION[self.state][frame_type]
|
received_data, type_byte = getattr(self, action_name)(frame)
|
||||||
received_data, type_byte = getattr(self, action_name)(frame)
|
if isinstance(received_data, bytearray) and isinstance(type_byte, int):
|
||||||
if isinstance(received_data, bytearray) and isinstance(type_byte, int):
|
self.arq_data_type_handler.dispatch(type_byte, received_data, self.update_histograms(len(received_data), len(received_data)))
|
||||||
self.arq_data_type_handler.dispatch(type_byte, received_data, self.update_histograms(len(received_data), len(received_data)))
|
return
|
||||||
return
|
|
||||||
|
|
||||||
self.log(f"Ignoring unknown transition from state {self.state.name} with frame {frame['frame_type']}")
|
self.log(f"Ignoring unknown transition from state {self.state.name} with frame {frame['frame_type']}")
|
||||||
|
|
||||||
def is_session_outdated(self):
|
def is_session_outdated(self):
|
||||||
session_alivetime = time.time() - self.session_max_age
|
session_alivetime = time.time() - self.session_max_age
|
||||||
if self.session_ended < session_alivetime and self.state.name in ['FAILED', 'ENDED', 'ABORTED']:
|
return self.session_ended < session_alivetime and self.state.name in [
|
||||||
return True
|
'FAILED',
|
||||||
return False
|
'ENDED',
|
||||||
|
'ABORTED',
|
||||||
|
]
|
||||||
|
|
||||||
def calculate_session_duration(self):
|
def calculate_session_duration(self):
|
||||||
if self.session_ended == 0:
|
if self.session_ended == 0:
|
||||||
|
@ -123,7 +127,7 @@ class ARQSession():
|
||||||
|
|
||||||
def calculate_session_statistics(self, confirmed_bytes, total_bytes):
|
def calculate_session_statistics(self, confirmed_bytes, total_bytes):
|
||||||
duration = self.calculate_session_duration()
|
duration = self.calculate_session_duration()
|
||||||
#total_bytes = self.total_length
|
# total_bytes = self.total_length
|
||||||
# self.total_length
|
# self.total_length
|
||||||
duration_in_minutes = duration / 60 # Convert duration from seconds to minutes
|
duration_in_minutes = duration / 60 # Convert duration from seconds to minutes
|
||||||
|
|
||||||
|
@ -134,9 +138,9 @@ class ARQSession():
|
||||||
bytes_per_minute = 0
|
bytes_per_minute = 0
|
||||||
|
|
||||||
# Convert histograms lists to dictionaries
|
# Convert histograms lists to dictionaries
|
||||||
time_histogram_dict = {i: timestamp for i, timestamp in enumerate(self.time_histogram)}
|
time_histogram_dict = dict(enumerate(self.time_histogram))
|
||||||
snr_histogram_dict = {i: snr for i, snr in enumerate(self.snr_histogram)}
|
snr_histogram_dict = dict(enumerate(self.snr_histogram))
|
||||||
bpm_histogram_dict = {i: bpm for i, bpm in enumerate(self.bpm_histogram)}
|
bpm_histogram_dict = dict(enumerate(self.bpm_histogram))
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'total_bytes': total_bytes,
|
'total_bytes': total_bytes,
|
||||||
|
@ -160,11 +164,20 @@ class ARQSession():
|
||||||
|
|
||||||
return stats
|
return stats
|
||||||
|
|
||||||
def get_appropriate_speed_level(self, snr):
|
def get_appropriate_speed_level(self, snr, maximum_bandwidth=None):
|
||||||
# Start with the lowest speed level as default
|
if maximum_bandwidth is None:
|
||||||
# In case of a not fitting SNR, we return the lowest speed level
|
maximum_bandwidth = self.config['MODEM']['maximum_bandwidth']
|
||||||
|
|
||||||
|
# Adjust maximum_bandwidth based on special conditions or invalid configurations
|
||||||
|
if maximum_bandwidth == 0:
|
||||||
|
# Use the maximum available bandwidth from the speed level dictionary
|
||||||
|
maximum_bandwidth = max(details['bandwidth'] for details in self.SPEED_LEVEL_DICT.values())
|
||||||
|
|
||||||
|
# Initialize appropriate_speed_level to the lowest level that meets the minimum criteria
|
||||||
appropriate_speed_level = min(self.SPEED_LEVEL_DICT.keys())
|
appropriate_speed_level = min(self.SPEED_LEVEL_DICT.keys())
|
||||||
|
|
||||||
for level, details in self.SPEED_LEVEL_DICT.items():
|
for level, details in self.SPEED_LEVEL_DICT.items():
|
||||||
if snr >= details['min_snr'] and level > appropriate_speed_level:
|
if snr >= details['min_snr'] and details['bandwidth'] <= maximum_bandwidth and level > appropriate_speed_level:
|
||||||
appropriate_speed_level = level
|
appropriate_speed_level = level
|
||||||
|
|
||||||
return appropriate_speed_level
|
return appropriate_speed_level
|
|
@ -18,7 +18,7 @@ class IRS_State(Enum):
|
||||||
class ARQSessionIRS(arq_session.ARQSession):
|
class ARQSessionIRS(arq_session.ARQSession):
|
||||||
|
|
||||||
TIMEOUT_CONNECT = 55 #14.2
|
TIMEOUT_CONNECT = 55 #14.2
|
||||||
TIMEOUT_DATA = 60
|
TIMEOUT_DATA = 120
|
||||||
|
|
||||||
STATE_TRANSITION = {
|
STATE_TRANSITION = {
|
||||||
IRS_State.NEW: {
|
IRS_State.NEW: {
|
||||||
|
@ -76,14 +76,15 @@ class ARQSessionIRS(arq_session.ARQSession):
|
||||||
self.received_bytes = 0
|
self.received_bytes = 0
|
||||||
self.received_crc = None
|
self.received_crc = None
|
||||||
|
|
||||||
|
self.maximum_bandwidth = 0
|
||||||
|
|
||||||
self.abort = False
|
self.abort = False
|
||||||
|
|
||||||
def all_data_received(self):
|
def all_data_received(self):
|
||||||
return self.total_length == self.received_bytes
|
return self.total_length == self.received_bytes
|
||||||
|
|
||||||
def final_crc_matches(self) -> bool:
|
def final_crc_matches(self) -> bool:
|
||||||
match = self.total_crc == helpers.get_crc_32(bytes(self.received_data)).hex()
|
return self.total_crc == helpers.get_crc_32(bytes(self.received_data)).hex()
|
||||||
return match
|
|
||||||
|
|
||||||
def transmit_and_wait(self, frame, timeout, mode):
|
def transmit_and_wait(self, frame, timeout, mode):
|
||||||
self.event_frame_received.clear()
|
self.event_frame_received.clear()
|
||||||
|
@ -99,6 +100,12 @@ class ARQSessionIRS(arq_session.ARQSession):
|
||||||
thread_wait.start()
|
thread_wait.start()
|
||||||
|
|
||||||
def send_open_ack(self, open_frame):
|
def send_open_ack(self, open_frame):
|
||||||
|
self.maximum_bandwidth = open_frame['maximum_bandwidth']
|
||||||
|
# check for maximum bandwidth. If ISS bandwidth is higher than own, then use own
|
||||||
|
if open_frame['maximum_bandwidth'] > self.config['MODEM']['maximum_bandwidth']:
|
||||||
|
self.maximum_bandwidth = self.config['MODEM']['maximum_bandwidth']
|
||||||
|
|
||||||
|
|
||||||
self.event_manager.send_arq_session_new(
|
self.event_manager.send_arq_session_new(
|
||||||
False, self.id, self.dxcall, 0, self.state.name)
|
False, self.id, self.dxcall, 0, self.state.name)
|
||||||
ack_frame = self.frame_factory.build_arq_session_open_ack(
|
ack_frame = self.frame_factory.build_arq_session_open_ack(
|
||||||
|
@ -212,7 +219,7 @@ class ARQSessionIRS(arq_session.ARQSession):
|
||||||
received_speed_level = 0
|
received_speed_level = 0
|
||||||
|
|
||||||
latest_snr = self.snr if self.snr else -10
|
latest_snr = self.snr if self.snr else -10
|
||||||
appropriate_speed_level = self.get_appropriate_speed_level(latest_snr)
|
appropriate_speed_level = self.get_appropriate_speed_level(latest_snr, self.maximum_bandwidth)
|
||||||
modes_to_decode = {}
|
modes_to_decode = {}
|
||||||
|
|
||||||
# Log the latest SNR, current, appropriate speed levels, and the previous speed level
|
# Log the latest SNR, current, appropriate speed levels, and the previous speed level
|
||||||
|
@ -247,7 +254,7 @@ class ARQSessionIRS(arq_session.ARQSession):
|
||||||
return self.speed_level
|
return self.speed_level
|
||||||
|
|
||||||
def abort_transmission(self):
|
def abort_transmission(self):
|
||||||
self.log(f"Aborting transmission... setting abort flag")
|
self.log("Aborting transmission... setting abort flag")
|
||||||
self.abort = True
|
self.abort = True
|
||||||
|
|
||||||
def send_stop_ack(self, stop_frame):
|
def send_stop_ack(self, stop_frame):
|
||||||
|
@ -263,7 +270,7 @@ class ARQSessionIRS(arq_session.ARQSession):
|
||||||
# final function for failed transmissions
|
# final function for failed transmissions
|
||||||
self.session_ended = time.time()
|
self.session_ended = time.time()
|
||||||
self.set_state(IRS_State.FAILED)
|
self.set_state(IRS_State.FAILED)
|
||||||
self.log(f"Transmission failed!")
|
self.log("Transmission failed!")
|
||||||
self.event_manager.send_arq_session_finished(True, self.id, self.dxcall,False, self.state.name, statistics=self.calculate_session_statistics(self.received_bytes, self.total_length))
|
self.event_manager.send_arq_session_finished(True, self.id, self.dxcall,False, self.state.name, statistics=self.calculate_session_statistics(self.received_bytes, self.total_length))
|
||||||
self.states.setARQ(False)
|
self.states.setARQ(False)
|
||||||
return None, None
|
return None, None
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import threading
|
import threading
|
||||||
import data_frame_factory
|
import data_frame_factory
|
||||||
import queue
|
|
||||||
import random
|
import random
|
||||||
from codec2 import FREEDV_MODE
|
from codec2 import FREEDV_MODE
|
||||||
from modem_frametypes import FRAME_TYPE
|
from modem_frametypes import FRAME_TYPE
|
||||||
|
@ -105,9 +104,10 @@ class ARQSessionISS(arq_session.ARQSession):
|
||||||
twr.start()
|
twr.start()
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
|
maximum_bandwidth = self.config['MODEM']['maximum_bandwidth']
|
||||||
self.event_manager.send_arq_session_new(
|
self.event_manager.send_arq_session_new(
|
||||||
True, self.id, self.dxcall, self.total_length, self.state.name)
|
True, self.id, self.dxcall, self.total_length, self.state.name)
|
||||||
session_open_frame = self.frame_factory.build_arq_session_open(self.dxcall, self.id)
|
session_open_frame = self.frame_factory.build_arq_session_open(self.dxcall, self.id, maximum_bandwidth)
|
||||||
self.launch_twr(session_open_frame, self.TIMEOUT_CONNECT_ACK, self.RETRIES_CONNECT, mode=FREEDV_MODE.signalling)
|
self.launch_twr(session_open_frame, self.TIMEOUT_CONNECT_ACK, self.RETRIES_CONNECT, mode=FREEDV_MODE.signalling)
|
||||||
self.set_state(ISS_State.OPEN_SENT)
|
self.set_state(ISS_State.OPEN_SENT)
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ class ARQSessionISS(arq_session.ARQSession):
|
||||||
|
|
||||||
payload_size = self.get_data_payload_size()
|
payload_size = self.get_data_payload_size()
|
||||||
burst = []
|
burst = []
|
||||||
for f in range(0, self.frames_per_burst):
|
for _ in range(0, self.frames_per_burst):
|
||||||
offset = self.confirmed_bytes
|
offset = self.confirmed_bytes
|
||||||
payload = self.data[offset : offset + payload_size]
|
payload = self.data[offset : offset + payload_size]
|
||||||
data_frame = self.frame_factory.build_arq_burst_frame(
|
data_frame = self.frame_factory.build_arq_burst_frame(
|
||||||
|
@ -200,7 +200,7 @@ class ARQSessionISS(arq_session.ARQSession):
|
||||||
# final function for failed transmissions
|
# final function for failed transmissions
|
||||||
self.session_ended = time.time()
|
self.session_ended = time.time()
|
||||||
self.set_state(ISS_State.FAILED)
|
self.set_state(ISS_State.FAILED)
|
||||||
self.log(f"Transmission failed!")
|
self.log("Transmission failed!")
|
||||||
self.event_manager.send_arq_session_finished(True, self.id, self.dxcall,False, self.state.name, statistics=self.calculate_session_statistics(self.confirmed_bytes, self.total_length))
|
self.event_manager.send_arq_session_finished(True, self.id, self.dxcall,False, self.state.name, statistics=self.calculate_session_statistics(self.confirmed_bytes, self.total_length))
|
||||||
self.states.setARQ(False)
|
self.states.setARQ(False)
|
||||||
|
|
||||||
|
@ -209,7 +209,7 @@ class ARQSessionISS(arq_session.ARQSession):
|
||||||
|
|
||||||
def abort_transmission(self, irs_frame=None):
|
def abort_transmission(self, irs_frame=None):
|
||||||
# function for starting the abort sequence
|
# function for starting the abort sequence
|
||||||
self.log(f"aborting transmission...")
|
self.log("aborting transmission...")
|
||||||
self.set_state(ISS_State.ABORTING)
|
self.set_state(ISS_State.ABORTING)
|
||||||
|
|
||||||
self.event_manager.send_arq_session_finished(
|
self.event_manager.send_arq_session_finished(
|
||||||
|
|
|
@ -45,10 +45,10 @@ enable_protocol = False
|
||||||
|
|
||||||
[MODEM]
|
[MODEM]
|
||||||
enable_hmac = False
|
enable_hmac = False
|
||||||
enable_low_bandwidth_mode = False
|
|
||||||
enable_morse_identifier = False
|
enable_morse_identifier = False
|
||||||
respond_to_cq = True
|
respond_to_cq = True
|
||||||
tx_delay = 200
|
tx_delay = 50
|
||||||
|
maximum_bandwidth = 1700
|
||||||
|
|
||||||
[MESSAGES]
|
[MESSAGES]
|
||||||
enable_auto_repeat = False
|
enable_auto_repeat = False
|
||||||
|
|
|
@ -57,7 +57,7 @@ class CONFIG:
|
||||||
'MODEM': {
|
'MODEM': {
|
||||||
'enable_hmac': bool,
|
'enable_hmac': bool,
|
||||||
'enable_morse_identifier': bool,
|
'enable_morse_identifier': bool,
|
||||||
'enable_low_bandwidth_mode': bool,
|
'maximum_bandwidth': int,
|
||||||
'respond_to_cq': bool,
|
'respond_to_cq': bool,
|
||||||
'tx_delay': int
|
'tx_delay': int
|
||||||
},
|
},
|
||||||
|
|
|
@ -98,6 +98,7 @@ class DataFrameFactory:
|
||||||
"destination_crc": 3,
|
"destination_crc": 3,
|
||||||
"origin": 6,
|
"origin": 6,
|
||||||
"session_id": 1,
|
"session_id": 1,
|
||||||
|
"maximum_bandwidth": 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
self.template_list[FR_TYPE.ARQ_SESSION_OPEN_ACK.value] = {
|
self.template_list[FR_TYPE.ARQ_SESSION_OPEN_ACK.value] = {
|
||||||
|
@ -219,7 +220,7 @@ class DataFrameFactory:
|
||||||
|
|
||||||
elif key in ["session_id", "speed_level",
|
elif key in ["session_id", "speed_level",
|
||||||
"frames_per_burst", "version",
|
"frames_per_burst", "version",
|
||||||
"offset", "total_length", "state", "type"]:
|
"offset", "total_length", "state", "type", "maximum_bandwidth"]:
|
||||||
extracted_data[key] = int.from_bytes(data, 'big')
|
extracted_data[key] = int.from_bytes(data, 'big')
|
||||||
|
|
||||||
elif key in ["snr"]:
|
elif key in ["snr"]:
|
||||||
|
@ -328,11 +329,12 @@ class DataFrameFactory:
|
||||||
test_frame[:1] = bytes([FR_TYPE.TEST_FRAME.value])
|
test_frame[:1] = bytes([FR_TYPE.TEST_FRAME.value])
|
||||||
return test_frame
|
return test_frame
|
||||||
|
|
||||||
def build_arq_session_open(self, destination, session_id):
|
def build_arq_session_open(self, destination, session_id, maximum_bandwidth):
|
||||||
payload = {
|
payload = {
|
||||||
"destination_crc": helpers.get_crc_24(destination),
|
"destination_crc": helpers.get_crc_24(destination),
|
||||||
"origin": helpers.callsign_to_bytes(self.myfullcall),
|
"origin": helpers.callsign_to_bytes(self.myfullcall),
|
||||||
"session_id": session_id.to_bytes(1, 'big'),
|
"session_id": session_id.to_bytes(1, 'big'),
|
||||||
|
"maximum_bandwidth": maximum_bandwidth.to_bytes(2, 'big'),
|
||||||
}
|
}
|
||||||
return self.construct(FR_TYPE.ARQ_SESSION_OPEN, payload)
|
return self.construct(FR_TYPE.ARQ_SESSION_OPEN, payload)
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ class explorer():
|
||||||
callsign = str(self.config['STATION']['mycall']) + "-" + str(self.config["STATION"]['myssid'])
|
callsign = str(self.config['STATION']['mycall']) + "-" + str(self.config["STATION"]['myssid'])
|
||||||
gridsquare = str(self.config['STATION']['mygrid'])
|
gridsquare = str(self.config['STATION']['mygrid'])
|
||||||
version = str(self.modem_version)
|
version = str(self.modem_version)
|
||||||
bandwidth = str(self.config['MODEM']['enable_low_bandwidth_mode'])
|
bandwidth = str(self.config['MODEM']['maximum_bandwidth'])
|
||||||
beacon = str(self.states.is_beacon_running)
|
beacon = str(self.states.is_beacon_running)
|
||||||
strength = str(self.states.s_meter_strength)
|
strength = str(self.states.s_meter_strength)
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,22 @@ import frame_handler
|
||||||
from message_system_db_messages import DatabaseManagerMessages
|
from message_system_db_messages import DatabaseManagerMessages
|
||||||
|
|
||||||
|
|
||||||
class CQFrameHandler(frame_handler_ping.PingFrameHandler):
|
class CQFrameHandler(frame_handler.FrameHandler):
|
||||||
|
|
||||||
def should_respond(self):
|
#def should_respond(self):
|
||||||
self.logger.debug(f"Respond to CQ: {self.config['MODEM']['respond_to_cq']}")
|
# self.logger.debug(f"Respond to CQ: {self.config['MODEM']['respond_to_cq']}")
|
||||||
return self.config['MODEM']['respond_to_cq']
|
# return bool(self.config['MODEM']['respond_to_cq'] and not self.states.getARQ())
|
||||||
|
|
||||||
|
def follow_protocol(self):
|
||||||
|
if self.states.getARQ():
|
||||||
|
return
|
||||||
|
|
||||||
|
self.logger.debug(
|
||||||
|
f"[Modem] Responding to request from [{self.details['frame']['origin']}]",
|
||||||
|
snr=self.details['snr'],
|
||||||
|
)
|
||||||
|
|
||||||
|
self.send_ack()
|
||||||
|
|
||||||
def send_ack(self):
|
def send_ack(self):
|
||||||
factory = data_frame_factory.DataFrameFactory(self.config)
|
factory = data_frame_factory.DataFrameFactory(self.config)
|
||||||
|
|
|
@ -16,12 +16,8 @@ class PingFrameHandler(frame_handler.FrameHandler):
|
||||||
# self.logger.info(f"[Modem] {ft} received but not for us.")
|
# self.logger.info(f"[Modem] {ft} received but not for us.")
|
||||||
# return valid
|
# return valid
|
||||||
|
|
||||||
#def should_respond(self):
|
|
||||||
# return self.is_frame_for_me()
|
|
||||||
|
|
||||||
def follow_protocol(self):
|
def follow_protocol(self):
|
||||||
|
if not bool(self.is_frame_for_me() and not self.states.getARQ()):
|
||||||
if not self.should_respond():
|
|
||||||
return
|
return
|
||||||
|
|
||||||
self.logger.debug(
|
self.logger.debug(
|
||||||
|
|
|
@ -33,7 +33,7 @@ from schedule_manager import ScheduleManager
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
CORS(app, resources={r"/*": {"origins": "*"}})
|
CORS(app, resources={r"/*": {"origins": "*"}})
|
||||||
sock = Sock(app)
|
sock = Sock(app)
|
||||||
MODEM_VERSION = "0.14.4-alpha"
|
MODEM_VERSION = "0.14.5-alpha"
|
||||||
|
|
||||||
# set config file to use
|
# set config file to use
|
||||||
def set_config():
|
def set_config():
|
||||||
|
|
|
@ -32,7 +32,7 @@ class TestDataFrameFactory(unittest.TestCase):
|
||||||
def testARQConnect(self):
|
def testARQConnect(self):
|
||||||
dxcall = "DJ2LS-4"
|
dxcall = "DJ2LS-4"
|
||||||
session_id = 123
|
session_id = 123
|
||||||
frame = self.factory.build_arq_session_open(dxcall, session_id)
|
frame = self.factory.build_arq_session_open(dxcall, session_id, 1700)
|
||||||
frame_data = self.factory.deconstruct(frame)
|
frame_data = self.factory.deconstruct(frame)
|
||||||
|
|
||||||
self.assertEqual(frame_data['origin'], self.factory.myfullcall)
|
self.assertEqual(frame_data['origin'], self.factory.myfullcall)
|
||||||
|
|
Loading…
Reference in a new issue