mirror of
https://github.com/DJ2LS/FreeDATA
synced 2024-05-14 08:04:33 +00:00
Merge pull request #399 from DJ2LS/ls-modem
Work on datac4, datac5, datac13, selective repeat ARQ
This commit is contained in:
commit
3cfaaec3da
2
.github/workflows/build_multiplatform.yml
vendored
2
.github/workflows/build_multiplatform.yml
vendored
|
@ -112,6 +112,8 @@ jobs:
|
|||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.head_ref }}
|
||||
- uses: uraimo/run-on-arch-action@v2
|
||||
name: Build artifact
|
||||
id: build
|
||||
|
|
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
|
@ -40,6 +40,8 @@ jobs:
|
|||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.head_ref }}
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
|
|
2
.github/workflows/ctest.yml
vendored
2
.github/workflows/ctest.yml
vendored
|
@ -44,7 +44,7 @@ jobs:
|
|||
shell: bash
|
||||
run: |
|
||||
git clone https://github.com/drowe67/codec2.git
|
||||
cd codec2 && git checkout master # This should be pinned to a release
|
||||
cd codec2
|
||||
mkdir -p build_linux && cd build_linux && cmake .. && make
|
||||
|
||||
- name: run ctests
|
||||
|
|
|
@ -58,19 +58,19 @@ add_test(NAME tnc_irs_iss
|
|||
# python3 test_chat_text.py")
|
||||
# set_tests_properties(chat_text PROPERTIES PASS_REGULAR_EXPRESSION "errors: 0")
|
||||
|
||||
add_test(NAME datac0_frames
|
||||
add_test(NAME datac13_frames
|
||||
COMMAND sh -c "export LD_LIBRARY_PATH=${CODEC2_BUILD_DIR}/src;
|
||||
export PYTHONPATH=../tnc;
|
||||
cd ${CMAKE_CURRENT_SOURCE_DIR}/test;
|
||||
python3 test_datac0.py")
|
||||
set_tests_properties(datac0_frames PROPERTIES PASS_REGULAR_EXPRESSION "errors: 0")
|
||||
python3 test_datac13.py")
|
||||
set_tests_properties(datac13_frames PROPERTIES PASS_REGULAR_EXPRESSION "errors: 0")
|
||||
|
||||
add_test(NAME datac0_frames_negative
|
||||
add_test(NAME datac13_frames_negative
|
||||
COMMAND sh -c "export LD_LIBRARY_PATH=${CODEC2_BUILD_DIR}/src;
|
||||
export PYTHONPATH=../tnc;
|
||||
cd ${CMAKE_CURRENT_SOURCE_DIR}/test;
|
||||
python3 test_datac0_negative.py")
|
||||
set_tests_properties(datac0_frames_negative PROPERTIES PASS_REGULAR_EXPRESSION "errors: 0")
|
||||
python3 test_datac13_negative.py")
|
||||
set_tests_properties(datac13_frames_negative PROPERTIES PASS_REGULAR_EXPRESSION "errors: 0")
|
||||
|
||||
add_test(NAME helper_routines
|
||||
COMMAND sh -c "export LD_LIBRARY_PATH=${CODEC2_BUILD_DIR}/src;
|
||||
|
@ -87,7 +87,7 @@ add_test(NAME py_highsnr_stdio_P_P_multi
|
|||
PATH=$PATH:${CODEC2_BUILD_DIR}/src;
|
||||
cd ${CMAKE_CURRENT_SOURCE_DIR}/test;
|
||||
python3 test_highsnr_stdio_P_P_multi.py")
|
||||
set_tests_properties(py_highsnr_stdio_P_P_multi PROPERTIES PASS_REGULAR_EXPRESSION "DATAC0: ${BURSTS}/${FRAMESPERBURST} DATAC1: ${BURSTS}/${FRAMESPERBURST} DATAC3: ${BURSTS}/${FRAMESPERBURST}")
|
||||
set_tests_properties(py_highsnr_stdio_P_P_multi PROPERTIES PASS_REGULAR_EXPRESSION "DATAC13: ${BURSTS}/${FRAMESPERBURST} DATAC1: ${BURSTS}/${FRAMESPERBURST} DATAC3: ${BURSTS}/${FRAMESPERBURST}")
|
||||
|
||||
add_test(NAME py_highsnr_stdio_P_P_datacx
|
||||
COMMAND sh -c "export LD_LIBRARY_PATH=${CODEC2_BUILD_DIR}/src;
|
||||
|
@ -124,26 +124,26 @@ add_test(NAME highsnr_stdio_P_C_single
|
|||
COMMAND sh -c "export LD_LIBRARY_PATH=${CODEC2_BUILD_DIR}/src;
|
||||
PATH=$PATH:${CODEC2_BUILD_DIR}/src;
|
||||
cd ${CMAKE_CURRENT_SOURCE_DIR}/test;
|
||||
python3 util_tx.py --mode datac0 --delay 500 --framesperburst ${FRAMESPERBURST} --bursts ${BURSTS} |
|
||||
python3 util_tx.py --mode datac13 --delay 500 --framesperburst ${FRAMESPERBURST} --bursts ${BURSTS} |
|
||||
sox -t .s16 -r 48000 -c 1 - -t .s16 -r 8000 -c 1 - |
|
||||
freedv_data_raw_rx datac0 - - --framesperburst ${FRAMESPERBURST} | hexdump -C")
|
||||
freedv_data_raw_rx datac13 - - --framesperburst ${FRAMESPERBURST} | hexdump -C")
|
||||
set_tests_properties(highsnr_stdio_P_C_single PROPERTIES PASS_REGULAR_EXPRESSION "HELLO WORLD")
|
||||
|
||||
add_test(NAME highsnr_stdio_C_P_single
|
||||
COMMAND sh -c "export LD_LIBRARY_PATH=${CODEC2_BUILD_DIR}/src;
|
||||
PATH=$PATH:${CODEC2_BUILD_DIR}/src;
|
||||
cd ${CMAKE_CURRENT_SOURCE_DIR}/test;
|
||||
freedv_data_raw_tx datac0 --testframes ${TESTFRAMES} --bursts ${BURSTS} --framesperburst ${FRAMESPERBURST} /dev/zero - |
|
||||
freedv_data_raw_tx datac13 --testframes ${TESTFRAMES} --bursts ${BURSTS} --framesperburst ${FRAMESPERBURST} /dev/zero - |
|
||||
sox -t .s16 -r 8000 -c 1 - -t .s16 -r 48000 -c 1 - |
|
||||
python3 util_rx.py --mode datac0 --framesperburst ${FRAMESPERBURST} --bursts ${BURSTS}")
|
||||
python3 util_rx.py --mode datac13 --framesperburst ${FRAMESPERBURST} --bursts ${BURSTS}")
|
||||
set_tests_properties(highsnr_stdio_C_P_single PROPERTIES PASS_REGULAR_EXPRESSION "RECEIVED BURSTS: ${BURSTS} RECEIVED FRAMES: ${FRAMESPERBURST}")
|
||||
|
||||
add_test(NAME highsnr_stdio_P_P_single
|
||||
COMMAND sh -c "export LD_LIBRARY_PATH=${CODEC2_BUILD_DIR}/src;
|
||||
PATH=$PATH:${CODEC2_BUILD_DIR}/src;
|
||||
cd ${CMAKE_CURRENT_SOURCE_DIR}/test;
|
||||
python3 util_tx.py --mode datac0 --delay 500 --framesperburst ${FRAMESPERBURST} --bursts ${BURSTS} |
|
||||
python3 util_rx.py --debug --mode datac0 --framesperburst ${FRAMESPERBURST} --bursts ${BURSTS}")
|
||||
python3 util_tx.py --mode datac13 --delay 500 --framesperburst ${FRAMESPERBURST} --bursts ${BURSTS} |
|
||||
python3 util_rx.py --debug --mode datac13 --framesperburst ${FRAMESPERBURST} --bursts ${BURSTS}")
|
||||
set_tests_properties(highsnr_stdio_P_P_single PROPERTIES PASS_REGULAR_EXPRESSION "RECEIVED BURSTS: ${BURSTS} RECEIVED FRAMES: ${FRAMESPERBURST}")
|
||||
|
||||
add_test(NAME highsnr_stdio_P_P_multi
|
||||
|
@ -151,8 +151,8 @@ add_test(NAME highsnr_stdio_P_P_multi
|
|||
PATH=$PATH:${CODEC2_BUILD_DIR}/src;
|
||||
cd ${CMAKE_CURRENT_SOURCE_DIR}/test;
|
||||
python3 util_multimode_tx.py --delay 500 --framesperburst ${FRAMESPERBURST} --bursts ${BURSTS} |
|
||||
python3 util_multimode_rx.py --framesperburst ${FRAMESPERBURST} --bursts ${BURSTS} --timeout 20")
|
||||
set_tests_properties(highsnr_stdio_P_P_multi PROPERTIES PASS_REGULAR_EXPRESSION "DATAC0: ${BURSTS}/${FRAMESPERBURST} DATAC1: ${BURSTS}/${FRAMESPERBURST} DATAC3: ${BURSTS}/${FRAMESPERBURST}")
|
||||
python3 util_multimode_rx.py --framesperburst ${FRAMESPERBURST} --bursts ${BURSTS} --timeout 60")
|
||||
set_tests_properties(highsnr_stdio_P_P_multi PROPERTIES PASS_REGULAR_EXPRESSION "DATAC13: ${BURSTS}/${FRAMESPERBURST} DATAC1: ${BURSTS}/${FRAMESPERBURST} DATAC3: ${BURSTS}/${FRAMESPERBURST}")
|
||||
|
||||
# These tests can't run on GitHub actions as we don't have a virtual sound card
|
||||
if(NOT DEFINED ENV{GITHUB_RUN_ID})
|
||||
|
@ -179,7 +179,7 @@ add_test(NAME highsnr_virtual3_P_P_multi
|
|||
PATH=$PATH:${CODEC2_BUILD_DIR}/src;
|
||||
cd ${CMAKE_CURRENT_SOURCE_DIR}/test;
|
||||
./test_virtual_mm.sh")
|
||||
set_tests_properties(highsnr_virtual3_P_P_multi PROPERTIES PASS_REGULAR_EXPRESSION "DATAC0: 2/4 DATAC1: 2/4 DATAC3: 2/4")
|
||||
set_tests_properties(highsnr_virtual3_P_P_multi PROPERTIES PASS_REGULAR_EXPRESSION "DATAC13: 2/4 DATAC1: 2/4 DATAC3: 2/4")
|
||||
|
||||
# let Python do audio I/O via pyaudio callback mode
|
||||
add_test(NAME highsnr_virtual4_P_P_single_callback
|
||||
|
@ -203,7 +203,7 @@ add_test(NAME highsnr_virtual5_P_P_multi_callback
|
|||
PATH=$PATH:${CODEC2_BUILD_DIR}/src;
|
||||
cd ${CMAKE_CURRENT_SOURCE_DIR}/test;
|
||||
./test_virtual4a.sh")
|
||||
set_tests_properties(highsnr_virtual5_P_P_multi_callback PROPERTIES PASS_REGULAR_EXPRESSION "DATAC0: 2/4 DATAC1: 2/4 DATAC3: 2/4")
|
||||
set_tests_properties(highsnr_virtual5_P_P_multi_callback PROPERTIES PASS_REGULAR_EXPRESSION "DATAC13: 2/4 DATAC1: 2/4 DATAC3: 2/4")
|
||||
|
||||
# let Python do audio I/O via pyaudio callback mode with code outside of callback
|
||||
add_test(NAME highsnr_virtual5_P_P_multi_callback_outside
|
||||
|
@ -211,7 +211,7 @@ add_test(NAME highsnr_virtual5_P_P_multi_callback_outside
|
|||
PATH=$PATH:${CODEC2_BUILD_DIR}/src;
|
||||
cd ${CMAKE_CURRENT_SOURCE_DIR}/test;
|
||||
./test_virtual4b.sh")
|
||||
set_tests_properties(highsnr_virtual5_P_P_multi_callback_outside PROPERTIES PASS_REGULAR_EXPRESSION "DATAC0: 2/4 DATAC1: 2/4 DATAC3: 2/4")
|
||||
set_tests_properties(highsnr_virtual5_P_P_multi_callback_outside PROPERTIES PASS_REGULAR_EXPRESSION "DATAC13: 2/4 DATAC1: 2/4 DATAC3: 2/4")
|
||||
|
||||
endif()
|
||||
|
||||
|
|
|
@ -483,7 +483,7 @@ window.addEventListener("DOMContentLoaded", () => {
|
|||
command: "msg",
|
||||
dxcallsign: dxcallsign,
|
||||
mode: 255,
|
||||
frames: 1,
|
||||
frames: 5,
|
||||
data: data_with_attachment,
|
||||
checksum: file_checksum,
|
||||
uuid: uuid,
|
||||
|
@ -1443,7 +1443,7 @@ update_chat = function (obj) {
|
|||
command: "msg",
|
||||
dxcallsign: doc.dxcallsign,
|
||||
mode: 255,
|
||||
frames: 1,
|
||||
frames: 5,
|
||||
data: data_with_attachment,
|
||||
checksum: doc.checksum,
|
||||
uuid: doc.uuid,
|
||||
|
|
|
@ -1634,6 +1634,7 @@ ipcRenderer.on("action-update-reception-status", (event, arg) => {
|
|||
var time_left = "<strong>" + time_left + " || Speed/min: ";
|
||||
|
||||
// SET BYTES PER MINUTE
|
||||
|
||||
if (typeof data.bytesperminute == "undefined") {
|
||||
var arq_bytes_per_minute = 0;
|
||||
} else {
|
||||
|
@ -1648,7 +1649,7 @@ ipcRenderer.on("action-update-reception-status", (event, arg) => {
|
|||
var arq_bytes_per_minute_compressed = Math.round(
|
||||
arq_bytes_per_minute * compress
|
||||
);
|
||||
|
||||
console.log(arq_bytes_per_minute);
|
||||
time_left +=
|
||||
formatBytes(arq_bytes_per_minute, 1) +
|
||||
" (comp: " +
|
||||
|
@ -2210,11 +2211,14 @@ function updateHeardStations(arg) {
|
|||
|
||||
//https://stackoverflow.com/a/847196
|
||||
timestampRaw = arg.stations[i]["timestamp"];
|
||||
var date = new Date(timestampRaw * 1000);
|
||||
var hours = date.getHours();
|
||||
var minutes = "0" + date.getMinutes();
|
||||
var seconds = "0" + date.getSeconds();
|
||||
var datetime = hours + ":" + minutes.substr(-2) + ":" + seconds.substr(-2);
|
||||
|
||||
var datetime = new Date(timestampRaw * 1000).toLocaleString(
|
||||
navigator.language
|
||||
);
|
||||
//var hours = date.getHours();
|
||||
//var minutes = "0" + date.getMinutes();
|
||||
//var seconds = "0" + date.getSeconds();
|
||||
//var datetime = hours + ":" + minutes.substr(-2) + ":" + seconds.substr(-2);
|
||||
|
||||
var timestamp = document.createElement("td");
|
||||
var timestampText = document.createElement("span");
|
||||
|
|
|
@ -198,6 +198,7 @@ client.on("data", function (socketdata) {
|
|||
dbfs_level: data["audio_dbfs"],
|
||||
fft: data["fft"],
|
||||
channel_busy: data["channel_busy"],
|
||||
channel_busy_slot: data["channel_busy_slot"],
|
||||
scatter: data["scatter"],
|
||||
info: data["info"],
|
||||
rx_buffer_length: data["rx_buffer_length"],
|
||||
|
|
|
@ -16,8 +16,8 @@ check_alsa_loopback
|
|||
# make sure all child processes are killed when we exit
|
||||
trap 'jobs -p | xargs -r kill' EXIT
|
||||
|
||||
python3 util_callback_rx.py --mode datac0 --frames 2 --bursts 3 --audiodev -2 --debug &
|
||||
python3 util_callback_rx.py --mode datac13 --frames 2 --bursts 3 --audiodev -2 --debug &
|
||||
rx_pid=$!
|
||||
#sleep 1
|
||||
python3 util_tx.py --mode datac0 --frames 2 --bursts 3 --audiodev -2
|
||||
python3 util_tx.py --mode datac13 --frames 2 --bursts 3 --audiodev -2
|
||||
wait ${rx_pid}
|
||||
|
|
|
@ -204,7 +204,7 @@ for i in range(N_BURSTS):
|
|||
|
||||
# time.sleep(DELAY_BETWEEN_BURSTS)
|
||||
|
||||
# WAIT UNTIL WE RECEIVD AN ACK/DATAC0 FRAME
|
||||
# WAIT UNTIL WE RECEIVD AN ACK/datac13 FRAME
|
||||
while ACK_TIMEOUT >= time.time():
|
||||
time.sleep(0.01)
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ queue used by the daemon process into and out of the TNC.
|
|||
|
||||
Can be invoked from CMake, pytest, coverage or directly.
|
||||
|
||||
Uses util_datac0.py in separate process to perform the data transfer.
|
||||
Uses util_datac13.py in separate process to perform the data transfer.
|
||||
|
||||
@author: N2KIQ
|
||||
"""
|
||||
|
@ -28,9 +28,9 @@ import pytest
|
|||
import structlog
|
||||
|
||||
try:
|
||||
import test.util_datac0 as util
|
||||
import test.util_datac13 as util
|
||||
except ImportError:
|
||||
import util_datac0 as util
|
||||
import util_datac13 as util
|
||||
|
||||
|
||||
STATIONS = ["AA2BB", "ZZ9YY"]
|
||||
|
@ -48,11 +48,11 @@ def parameters() -> dict:
|
|||
connect_data = {"type": "arq", "command": "connect", "dxcallsign": "ZZ9YY-0"}
|
||||
stop_data = {"type": "arq", "command": "stop_transmission", "dxcallsign": "ZZ9YY-0"}
|
||||
|
||||
beacon_timeout = 6
|
||||
cq_timeout = 8
|
||||
ping_timeout = 5
|
||||
connect_timeout = 10
|
||||
stop_timeout = 5
|
||||
beacon_timeout = 1
|
||||
ping_timeout = 1
|
||||
cq_timeout = 1
|
||||
connect_timeout = 1
|
||||
stop_timeout = 1
|
||||
|
||||
beacon_tx_check = '"beacon":"transmitting"'
|
||||
cq_tx_check = '"qrv":"received"'
|
||||
|
@ -192,13 +192,13 @@ def analyze_results(station1: list, station2: list, call_list: list):
|
|||
pytest.param("beacon", marks=pytest.mark.flaky(reruns=2)),
|
||||
pytest.param("ping", marks=pytest.mark.flaky(reruns=2)),
|
||||
pytest.param("cq", marks=pytest.mark.flaky(reruns=20)),
|
||||
# pytest.param("cq", marks=pytest.mark.xfail(reason="Too unstable for CI")),
|
||||
pytest.param("stop", marks=pytest.mark.flaky(reruns=0)),
|
||||
#pytest.param("cq", marks=pytest.mark.xfail(reason="Too unstable for CI")),
|
||||
pytest.param("stop", marks=pytest.mark.flaky(reruns=2)),
|
||||
],
|
||||
)
|
||||
def test_datac0(frame_type: str, tmp_path):
|
||||
log_handler.setup_logging(filename=tmp_path / "test_datac0", level="DEBUG")
|
||||
log = structlog.get_logger("test_datac0")
|
||||
def test_datac13(frame_type: str, tmp_path):
|
||||
log_handler.setup_logging(filename=tmp_path / "test_datac13", level="DEBUG")
|
||||
log = structlog.get_logger("test_datac13")
|
||||
|
||||
s1_data = []
|
||||
s2_data = []
|
||||
|
@ -227,7 +227,7 @@ def test_datac0(frame_type: str, tmp_path):
|
|||
from_s2, s2_send = multiprocessing.Pipe()
|
||||
proc = [
|
||||
multiprocessing.Process(
|
||||
target=util.t_datac0_1,
|
||||
target=util.t_datac13_1,
|
||||
args=(
|
||||
s1_send,
|
||||
STATIONS[0],
|
||||
|
@ -238,7 +238,7 @@ def test_datac0(frame_type: str, tmp_path):
|
|||
daemon=True,
|
||||
),
|
||||
multiprocessing.Process(
|
||||
target=util.t_datac0_2,
|
||||
target=util.t_datac13_2,
|
||||
args=(
|
||||
s2_send,
|
||||
STATIONS[1],
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Negative tests for datac0 frames.
|
||||
Negative tests for datac13 frames.
|
||||
|
||||
@author: kronenpj
|
||||
"""
|
||||
|
@ -20,9 +20,9 @@ import pytest
|
|||
import structlog
|
||||
|
||||
try:
|
||||
import test.util_datac0_negative as util
|
||||
import test.util_datac13_negative as util
|
||||
except ImportError:
|
||||
import util_datac0_negative as util
|
||||
import util_datac13_negative as util
|
||||
|
||||
|
||||
STATIONS = ["AA2BB", "ZZ9YY"]
|
||||
|
@ -162,10 +162,13 @@ def analyze_results(station1: list, station2: list, call_list: list):
|
|||
|
||||
|
||||
# @pytest.mark.parametrize("frame_type", ["beacon", "connect", "ping"])
|
||||
@pytest.mark.parametrize("frame_type", ["ping", "stop"])
|
||||
def test_datac0_negative(frame_type: str, tmp_path):
|
||||
log_handler.setup_logging(filename=tmp_path / "test_datac0", level="DEBUG")
|
||||
log = structlog.get_logger("test_datac0")
|
||||
@pytest.mark.parametrize("frame_type", [
|
||||
"ping",
|
||||
pytest.param("stop", marks=pytest.mark.flaky(reruns=10))
|
||||
])
|
||||
def test_datac13_negative(frame_type: str, tmp_path):
|
||||
log_handler.setup_logging(filename=tmp_path / "test_datac13", level="DEBUG")
|
||||
log = structlog.get_logger("test_datac13")
|
||||
|
||||
s1_data = []
|
||||
s2_data = []
|
||||
|
@ -194,7 +197,7 @@ def test_datac0_negative(frame_type: str, tmp_path):
|
|||
from_s2, s2_send = multiprocessing.Pipe()
|
||||
proc = [
|
||||
multiprocessing.Process(
|
||||
target=util.t_datac0_1,
|
||||
target=util.t_datac13_1,
|
||||
args=(
|
||||
s1_send,
|
||||
STATIONS[0],
|
||||
|
@ -205,7 +208,7 @@ def test_datac0_negative(frame_type: str, tmp_path):
|
|||
daemon=True,
|
||||
),
|
||||
multiprocessing.Process(
|
||||
target=util.t_datac0_2,
|
||||
target=util.t_datac13_2,
|
||||
args=(
|
||||
s2_send,
|
||||
STATIONS[1],
|
|
@ -14,7 +14,7 @@ import sys
|
|||
|
||||
import helpers
|
||||
import pytest
|
||||
import static
|
||||
from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC
|
||||
|
||||
|
||||
@pytest.mark.parametrize("callsign", ["AA1AA", "DE2DE", "E4AWQ-4"])
|
||||
|
@ -22,7 +22,7 @@ def test_check_callsign(callsign: str):
|
|||
"""
|
||||
Execute test to demonstrate how to create and verify callsign checksums.
|
||||
"""
|
||||
static.SSID_LIST = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
|
||||
Station.ssid_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
|
||||
|
||||
t_callsign_bytes = helpers.callsign_to_bytes(callsign)
|
||||
t_callsign = helpers.bytes_to_callsign(t_callsign_bytes)
|
||||
|
@ -41,7 +41,7 @@ def test_callsign_to_bytes(callsign: str):
|
|||
"""
|
||||
Execute test to demonsrate symmetry when converting callsigns to and from byte arrays.
|
||||
"""
|
||||
static.SSID_LIST = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
|
||||
Station.ssid_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
|
||||
|
||||
t_callsign_crc = helpers.get_crc_24(bytes(callsign, "UTF-8"))
|
||||
t_callsign_bytes = helpers.callsign_to_bytes(callsign)
|
||||
|
|
|
@ -49,7 +49,7 @@ def t_HighSNR_C_P_DATACx(
|
|||
bursts: int, frames_per_burst: int, testframes: int, mode: str
|
||||
):
|
||||
"""
|
||||
Test a high signal-to-noise ratio path with DATAC0.
|
||||
Test a high signal-to-noise ratio path with datac13.
|
||||
|
||||
:param bursts: Number of bursts
|
||||
:type bursts: str
|
||||
|
@ -152,7 +152,7 @@ def t_HighSNR_C_P_DATACx(
|
|||
@pytest.mark.parametrize("bursts", [BURSTS])
|
||||
@pytest.mark.parametrize("frames_per_burst", [FRAMESPERBURST])
|
||||
@pytest.mark.parametrize("testframes", [TESTFRAMES])
|
||||
@pytest.mark.parametrize("mode", ["datac0", "datac1", "datac3"])
|
||||
@pytest.mark.parametrize("mode", ["datac13", "datac1", "datac3"])
|
||||
def test_HighSNR_C_P_DATACx(
|
||||
bursts: int, frames_per_burst: int, testframes: int, mode: str
|
||||
):
|
||||
|
|
|
@ -47,7 +47,7 @@ if os.path.exists("test"):
|
|||
|
||||
def t_HighSNR_P_C_DATACx(bursts: int, frames_per_burst: int, mode: str):
|
||||
"""
|
||||
Test a high signal-to-noise ratio path with DATAC0.
|
||||
Test a high signal-to-noise ratio path with datac13.
|
||||
|
||||
:param bursts: Number of bursts
|
||||
:type bursts: str
|
||||
|
@ -154,7 +154,7 @@ def t_HighSNR_P_C_DATACx(bursts: int, frames_per_burst: int, mode: str):
|
|||
# @pytest.mark.parametrize("frames_per_burst", [FRAMESPERBURST, 2, 3])
|
||||
@pytest.mark.parametrize("bursts", [BURSTS])
|
||||
@pytest.mark.parametrize("frames_per_burst", [FRAMESPERBURST])
|
||||
@pytest.mark.parametrize("mode", ["datac0", "datac1", "datac3"])
|
||||
@pytest.mark.parametrize("mode", ["datac13", "datac1", "datac3"])
|
||||
def test_HighSNR_P_C_DATACx(bursts: int, frames_per_burst: int, mode: str):
|
||||
proc = multiprocessing.Process(
|
||||
target=t_HighSNR_P_C_DATACx,
|
||||
|
|
|
@ -115,7 +115,7 @@ def t_HighSNR_P_P_DATACx(bursts: int, frames_per_burst: int, mode: str):
|
|||
# @pytest.mark.parametrize("frames_per_burst", [FRAMESPERBURST, 2, 3])
|
||||
@pytest.mark.parametrize("bursts", [BURSTS])
|
||||
@pytest.mark.parametrize("frames_per_burst", [FRAMESPERBURST])
|
||||
@pytest.mark.parametrize("mode", ["datac0", "datac1", "datac3"])
|
||||
@pytest.mark.parametrize("mode", ["datac13", "datac1", "datac3"])
|
||||
def test_HighSNR_P_P_DATACx(bursts: int, frames_per_burst: int, mode: str):
|
||||
proc = multiprocessing.Process(
|
||||
target=t_HighSNR_P_P_DATACx,
|
||||
|
|
|
@ -46,7 +46,7 @@ if os.path.exists("test"):
|
|||
|
||||
def t_HighSNR_P_P_Multi(bursts: int, frames_per_burst: int):
|
||||
"""
|
||||
Test a high signal-to-noise ratio path with DATAC0, DATAC1 and DATAC3.
|
||||
Test a high signal-to-noise ratio path with datac13, DATAC1 and DATAC3.
|
||||
|
||||
:param bursts: Number of bursts
|
||||
:type bursts: int
|
||||
|
@ -101,7 +101,7 @@ def t_HighSNR_P_P_Multi(bursts: int, frames_per_burst: int):
|
|||
if "DATAC" in str(line, "UTF-8")
|
||||
]
|
||||
)
|
||||
assert f"DATAC0: {bursts}/{frames_per_burst * bursts}" in lastline
|
||||
assert f"DATAC13: {bursts}/{frames_per_burst * bursts}" in lastline
|
||||
assert f"DATAC1: {bursts}/{frames_per_burst * bursts}" in lastline
|
||||
assert f"DATAC3: {bursts}/{frames_per_burst * bursts}" in lastline
|
||||
print(lastline)
|
||||
|
|
|
@ -9,7 +9,7 @@ queue used by the daemon process into and out of the TNC.
|
|||
|
||||
Can be invoked from CMake, pytest, coverage or directly.
|
||||
|
||||
Uses util_datac0.py in separate process to perform the data transfer.
|
||||
Uses util_datac13.py in separate process to perform the data transfer.
|
||||
|
||||
@author: N2KIQ
|
||||
"""
|
||||
|
@ -26,7 +26,7 @@ sys.path.insert(0, "..")
|
|||
sys.path.insert(0, "../tnc")
|
||||
import data_handler
|
||||
import helpers
|
||||
import static
|
||||
from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC
|
||||
|
||||
|
||||
def print_frame(data: bytearray):
|
||||
|
@ -148,18 +148,18 @@ def t_foreign_disconnect(mycall: str, dxcall: str):
|
|||
:rtype: bytearray
|
||||
"""
|
||||
# Set the SSIDs we'll use for this test.
|
||||
static.SSID_LIST = [0, 1, 2, 3, 4]
|
||||
Station.ssid_list = [0, 1, 2, 3, 4]
|
||||
|
||||
# Setup the static parameters for the connection.
|
||||
mycallsign_bytes = helpers.callsign_to_bytes(mycall)
|
||||
mycallsign = helpers.bytes_to_callsign(mycallsign_bytes)
|
||||
static.MYCALLSIGN = mycallsign
|
||||
static.MYCALLSIGN_CRC = helpers.get_crc_24(mycallsign)
|
||||
Station.mycallsign = mycallsign
|
||||
Station.mycallsign_crc = helpers.get_crc_24(mycallsign)
|
||||
|
||||
dxcallsign_bytes = helpers.callsign_to_bytes(dxcall)
|
||||
dxcallsign = helpers.bytes_to_callsign(dxcallsign_bytes)
|
||||
static.DXCALLSIGN = dxcallsign
|
||||
static.DXCALLSIGN_CRC = helpers.get_crc_24(dxcallsign)
|
||||
Station.dxcallsign = dxcallsign
|
||||
Station.dxcallsign_crc = helpers.get_crc_24(dxcallsign)
|
||||
|
||||
# Create the TNC
|
||||
tnc = data_handler.DATA()
|
||||
|
@ -173,12 +173,12 @@ def t_foreign_disconnect(mycall: str, dxcall: str):
|
|||
print_frame(create_frame)
|
||||
tnc.received_session_opener(create_frame)
|
||||
|
||||
assert helpers.callsign_to_bytes(static.MYCALLSIGN) == mycallsign_bytes
|
||||
assert helpers.callsign_to_bytes(static.DXCALLSIGN) == dxcallsign_bytes
|
||||
assert helpers.callsign_to_bytes(Station.mycallsign) == mycallsign_bytes
|
||||
assert helpers.callsign_to_bytes(Station.dxcallsign) == dxcallsign_bytes
|
||||
|
||||
assert static.ARQ_SESSION is True
|
||||
assert static.TNC_STATE == "BUSY"
|
||||
assert static.ARQ_SESSION_STATE == "connecting"
|
||||
assert ARQ.arq_session is True
|
||||
assert TNC.tnc_state == "BUSY"
|
||||
assert ARQ.arq_session_state == "connecting"
|
||||
|
||||
# Set up a frame from a non-associated station.
|
||||
# foreigncall_bytes = helpers.callsign_to_bytes("ZZ0ZZ-0")
|
||||
|
@ -193,8 +193,8 @@ def t_foreign_disconnect(mycall: str, dxcall: str):
|
|||
print_frame(close_frame)
|
||||
|
||||
# assert (
|
||||
# helpers.check_callsign(static.DXCALLSIGN, bytes(close_frame[4:7]))[0] is False
|
||||
# ), f"{helpers.get_crc_24(static.DXCALLSIGN)} == {bytes(close_frame[4:7])} but should be not equal."
|
||||
# helpers.check_callsign(Station.dxcallsign, bytes(close_frame[4:7]))[0] is False
|
||||
# ), f"{helpers.get_crc_24(Station.dxcallsign)} == {bytes(close_frame[4:7])} but should be not equal."
|
||||
|
||||
# assert (
|
||||
# helpers.check_callsign(foreigncall, bytes(close_frame[4:7]))[0] is True
|
||||
|
@ -203,16 +203,16 @@ def t_foreign_disconnect(mycall: str, dxcall: str):
|
|||
# Send the non-associated session close frame to the TNC
|
||||
tnc.received_session_close(close_frame)
|
||||
|
||||
assert helpers.callsign_to_bytes(static.MYCALLSIGN) == helpers.callsign_to_bytes(
|
||||
assert helpers.callsign_to_bytes(Station.mycallsign) == helpers.callsign_to_bytes(
|
||||
mycall
|
||||
), f"{static.MYCALLSIGN} != {mycall} but should equal."
|
||||
assert helpers.callsign_to_bytes(static.DXCALLSIGN) == helpers.callsign_to_bytes(
|
||||
), f"{Station.mycallsign} != {mycall} but should equal."
|
||||
assert helpers.callsign_to_bytes(Station.dxcallsign) == helpers.callsign_to_bytes(
|
||||
dxcall
|
||||
), f"{static.DXCALLSIGN} != {dxcall} but should equal."
|
||||
), f"{Station.dxcallsign} != {dxcall} but should equal."
|
||||
|
||||
assert static.ARQ_SESSION is True
|
||||
assert static.TNC_STATE == "BUSY"
|
||||
assert static.ARQ_SESSION_STATE == "connecting"
|
||||
assert ARQ.arq_session is True
|
||||
assert TNC.tnc_state == "BUSY"
|
||||
assert ARQ.arq_session_state == "connecting"
|
||||
|
||||
|
||||
def t_valid_disconnect(mycall: str, dxcall: str):
|
||||
|
@ -228,18 +228,18 @@ def t_valid_disconnect(mycall: str, dxcall: str):
|
|||
:rtype: bytearray
|
||||
"""
|
||||
# Set the SSIDs we'll use for this test.
|
||||
static.SSID_LIST = [0, 1, 2, 3, 4]
|
||||
Station.ssid_list = [0, 1, 2, 3, 4]
|
||||
|
||||
# Setup the static parameters for the connection.
|
||||
mycallsign_bytes = helpers.callsign_to_bytes(mycall)
|
||||
mycallsign = helpers.bytes_to_callsign(mycallsign_bytes)
|
||||
static.MYCALLSIGN = mycallsign
|
||||
static.MYCALLSIGN_CRC = helpers.get_crc_24(mycallsign)
|
||||
Station.mycallsign = mycallsign
|
||||
Station.mycallsign_crc = helpers.get_crc_24(mycallsign)
|
||||
|
||||
dxcallsign_bytes = helpers.callsign_to_bytes(dxcall)
|
||||
dxcallsign = helpers.bytes_to_callsign(dxcallsign_bytes)
|
||||
static.DXCALLSIGN = dxcallsign
|
||||
static.DXCALLSIGN_CRC = helpers.get_crc_24(dxcallsign)
|
||||
Station.dxcallsign = dxcallsign
|
||||
Station.dxcallsign_crc = helpers.get_crc_24(dxcallsign)
|
||||
|
||||
# Create the TNC
|
||||
tnc = data_handler.DATA()
|
||||
|
@ -253,9 +253,9 @@ def t_valid_disconnect(mycall: str, dxcall: str):
|
|||
print_frame(create_frame)
|
||||
tnc.received_session_opener(create_frame)
|
||||
|
||||
assert static.ARQ_SESSION is True
|
||||
assert static.TNC_STATE == "BUSY"
|
||||
assert static.ARQ_SESSION_STATE == "connecting"
|
||||
assert ARQ.arq_session is True
|
||||
assert TNC.tnc_state == "BUSY"
|
||||
assert ARQ.arq_session_state == "connecting"
|
||||
|
||||
# Create packet to be 'received' by this station.
|
||||
# close_frame = t_create_session_close_old(mycall=dxcall, dxcall=mycall)
|
||||
|
@ -267,12 +267,12 @@ def t_valid_disconnect(mycall: str, dxcall: str):
|
|||
print_frame(close_frame)
|
||||
tnc.received_session_close(close_frame)
|
||||
|
||||
assert helpers.callsign_to_bytes(static.MYCALLSIGN) == mycallsign_bytes
|
||||
assert helpers.callsign_to_bytes(static.DXCALLSIGN) == dxcallsign_bytes
|
||||
assert helpers.callsign_to_bytes(Station.mycallsign) == mycallsign_bytes
|
||||
assert helpers.callsign_to_bytes(Station.dxcallsign) == dxcallsign_bytes
|
||||
|
||||
assert static.ARQ_SESSION is False
|
||||
assert static.TNC_STATE == "IDLE"
|
||||
assert static.ARQ_SESSION_STATE == "disconnected"
|
||||
assert ARQ.arq_session is False
|
||||
assert TNC.tnc_state == "IDLE"
|
||||
assert ARQ.arq_session_state == "disconnected"
|
||||
|
||||
|
||||
# These tests are pushed into separate processes as a workaround. These tests
|
||||
|
|
|
@ -15,13 +15,13 @@ function check_alsa_loopback {
|
|||
check_alsa_loopback
|
||||
|
||||
RX_LOG=$(mktemp)
|
||||
MAX_RUN_TIME=2600
|
||||
MAX_RUN_TIME=2700
|
||||
|
||||
# make sure all child processes are killed when we exit
|
||||
trap 'jobs -p | xargs -r kill' EXIT
|
||||
|
||||
arecord --device="plughw:CARD=CHAT2,DEV=0" -r 48000 -f S16_LE -d $MAX_RUN_TIME | python3 util_rx.py --mode datac0 --frames 2 --bursts 5 --debug &
|
||||
arecord --device="plughw:CARD=CHAT2,DEV=0" -r 48000 -f S16_LE -d $MAX_RUN_TIME | python3 util_rx.py --mode datac13 --frames 2 --bursts 5 --debug &
|
||||
rx_pid=$!
|
||||
sleep 1
|
||||
python3 util_tx.py --mode datac0 --frames 2 --bursts 5 --delay 500 | aplay --device="plughw:CARD=CHAT2,DEV=1" -r 48000 -f S16_LE
|
||||
python3 util_tx.py --mode datac13 --frames 2 --bursts 5 --delay 500 | aplay --device="plughw:CARD=CHAT2,DEV=1" -r 48000 -f S16_LE
|
||||
wait ${rx_pid}
|
||||
|
|
|
@ -8,9 +8,9 @@ MAX_RUN_TIME=2600
|
|||
trap 'jobs -p | xargs -r kill' EXIT
|
||||
|
||||
arecord -r 48000 --device="plughw:CARD=CHAT1,DEV=0" -f S16_LE -d $MAX_RUN_TIME | \
|
||||
python3 util_rx.py --mode datac0 --frames 2 --bursts 5 --debug &
|
||||
python3 util_rx.py --mode datac13 --frames 2 --bursts 5 --debug &
|
||||
rx_pid=$!
|
||||
sleep 1
|
||||
python3 util_tx.py --mode datac0 --frames 2 --bursts 5 --delay 500 | \
|
||||
python3 util_tx.py --mode datac13 --frames 2 --bursts 5 --delay 500 | \
|
||||
aplay -r 48000 --device="plughw:CARD=CHAT1,DEV=1" -f S16_LE
|
||||
wait ${rx_pid}
|
||||
|
|
|
@ -8,8 +8,8 @@ MAX_RUN_TIME=2600
|
|||
trap 'jobs -p | xargs -r kill' EXIT
|
||||
|
||||
arecord -r 48000 --device="plughw:CARD=CHAT1,DEV=0" -f S16_LE -d $MAX_RUN_TIME | \
|
||||
python3 util_rx.py --mode datac0 --frames 2 --bursts 5 --debug --timeout 20 &
|
||||
python3 util_rx.py --mode datac13 --frames 2 --bursts 5 --debug --timeout 20 &
|
||||
rx_pid=$!
|
||||
sleep 1
|
||||
python3 util_tx.py --mode datac0 --frames 2 --bursts 5 --delay 2000 --audiodev -2
|
||||
python3 util_tx.py --mode datac13 --frames 2 --bursts 5 --delay 2000 --audiodev -2
|
||||
wait ${rx_pid}
|
||||
|
|
|
@ -7,9 +7,9 @@ MAX_RUN_TIME=2600
|
|||
# make sure all child processes are killed when we exit
|
||||
trap 'jobs -p | xargs -r kill' EXIT
|
||||
|
||||
python3 util_rx.py --mode datac0 --frames 2 --bursts 5 --debug --audiodev -2 &
|
||||
python3 util_rx.py --mode datac13 --frames 2 --bursts 5 --debug --audiodev -2 &
|
||||
rx_pid=$!
|
||||
sleep 1
|
||||
python3 util_tx.py --mode datac0 --frames 2 --bursts 5 | \
|
||||
python3 util_tx.py --mode datac13 --frames 2 --bursts 5 | \
|
||||
aplay -r 48000 --device="plughw:CARD=CHAT1,DEV=1" -f S16_LE
|
||||
wait ${rx_pid}
|
||||
|
|
|
@ -16,8 +16,8 @@ check_alsa_loopback
|
|||
# make sure all child processes are killed when we exit
|
||||
trap 'jobs -p | xargs -r kill' EXIT
|
||||
|
||||
python3 util_callback_rx.py --mode datac0 --frames 2 --bursts 3 --audiodev -2 --debug &
|
||||
python3 util_callback_rx.py --mode datac13 --frames 2 --bursts 3 --audiodev -2 --debug &
|
||||
rx_pid=$!
|
||||
sleep 1
|
||||
python3 util_tx.py --mode datac0 --frames 2 --bursts 3 --audiodev -2
|
||||
python3 util_tx.py --mode datac13 --frames 2 --bursts 3 --audiodev -2
|
||||
wait ${rx_pid}
|
||||
|
|
|
@ -16,8 +16,8 @@ check_alsa_loopback
|
|||
# make sure all child processes are killed when we exit
|
||||
trap 'jobs -p | xargs -r kill' EXIT
|
||||
|
||||
python3 util_callback_rx.py --mode datac0 --frames 2 --bursts 3 --audiodev -2 --debug &
|
||||
python3 util_callback_rx.py --mode datac13 --frames 2 --bursts 3 --audiodev -2 --debug &
|
||||
rx_pid=$!
|
||||
#sleep 1
|
||||
python3 util_tx.py --mode datac0 --frames 2 --bursts 3 --audiodev -2
|
||||
python3 util_tx.py --mode datac13 --frames 2 --bursts 3 --audiodev -2
|
||||
wait ${rx_pid}
|
||||
|
|
|
@ -16,8 +16,8 @@ check_alsa_loopback
|
|||
# make sure all child processes are killed when we exit
|
||||
trap 'jobs -p | xargs -r kill' EXIT
|
||||
|
||||
python3 util_callback_rx_outside.py --mode datac0 --frames 2 --bursts 3 --audiodev -2 --debug &
|
||||
python3 util_callback_rx_outside.py --mode datac13 --frames 2 --bursts 3 --audiodev -2 --debug &
|
||||
rx_pid=$!
|
||||
#sleep 1
|
||||
python3 util_tx.py --mode datac0 --frames 2 --bursts 3 --audiodev -2
|
||||
python3 util_tx.py --mode datac13 --frames 2 --bursts 3 --audiodev -2
|
||||
wait ${rx_pid}
|
||||
|
|
|
@ -112,20 +112,20 @@ class Test:
|
|||
sys.exit()
|
||||
|
||||
# open codec2 instance
|
||||
self.datac0_freedv = ctypes.cast(
|
||||
codec2.api.freedv_open(codec2.api.FREEDV_MODE_DATAC0), ctypes.c_void_p
|
||||
self.datac13_freedv = ctypes.cast(
|
||||
codec2.api.freedv_open(codec2.FREEDV_MODE.datac13.value), ctypes.c_void_p
|
||||
)
|
||||
self.datac0_bytes_per_frame = int(
|
||||
codec2.api.freedv_get_bits_per_modem_frame(self.datac0_freedv) / 8
|
||||
self.datac13_bytes_per_frame = int(
|
||||
codec2.api.freedv_get_bits_per_modem_frame(self.datac13_freedv) / 8
|
||||
)
|
||||
self.datac0_bytes_out = ctypes.create_string_buffer(self.datac0_bytes_per_frame)
|
||||
self.datac13_bytes_out = ctypes.create_string_buffer(self.datac13_bytes_per_frame)
|
||||
codec2.api.freedv_set_frames_per_burst(
|
||||
self.datac0_freedv, self.N_FRAMES_PER_BURST
|
||||
self.datac13_freedv, self.N_FRAMES_PER_BURST
|
||||
)
|
||||
self.datac0_buffer = codec2.audio_buffer(2 * self.AUDIO_FRAMES_PER_BUFFER)
|
||||
self.datac13_buffer = codec2.audio_buffer(2 * self.AUDIO_FRAMES_PER_BUFFER)
|
||||
|
||||
self.datac1_freedv = ctypes.cast(
|
||||
codec2.api.freedv_open(codec2.api.FREEDV_MODE_DATAC1), ctypes.c_void_p
|
||||
codec2.api.freedv_open(codec2.FREEDV_MODE.datac1.value), ctypes.c_void_p
|
||||
)
|
||||
self.datac1_bytes_per_frame = int(
|
||||
codec2.api.freedv_get_bits_per_modem_frame(self.datac1_freedv) / 8
|
||||
|
@ -137,7 +137,7 @@ class Test:
|
|||
self.datac1_buffer = codec2.audio_buffer(2 * self.AUDIO_FRAMES_PER_BUFFER)
|
||||
|
||||
self.datac3_freedv = ctypes.cast(
|
||||
codec2.api.freedv_open(codec2.api.FREEDV_MODE_DATAC3), ctypes.c_void_p
|
||||
codec2.api.freedv_open(codec2.FREEDV_MODE.datac3.value), ctypes.c_void_p
|
||||
)
|
||||
self.datac3_bytes_per_frame = int(
|
||||
codec2.api.freedv_get_bits_per_modem_frame(self.datac3_freedv) / 8
|
||||
|
@ -149,9 +149,9 @@ class Test:
|
|||
self.datac3_buffer = codec2.audio_buffer(2 * self.AUDIO_FRAMES_PER_BUFFER)
|
||||
|
||||
# SET COUNTERS
|
||||
self.rx_total_frames_datac0 = 0
|
||||
self.rx_frames_datac0 = 0
|
||||
self.rx_bursts_datac0 = 0
|
||||
self.rx_total_frames_datac13 = 0
|
||||
self.rx_frames_datac13 = 0
|
||||
self.rx_bursts_datac13 = 0
|
||||
|
||||
self.rx_total_frames_datac1 = 0
|
||||
self.rx_frames_datac1 = 0
|
||||
|
@ -173,7 +173,7 @@ class Test:
|
|||
self.frx = open("rx48_callback_multimode.raw", mode="wb")
|
||||
|
||||
# initial nin values
|
||||
self.datac0_nin = codec2.api.freedv_nin(self.datac0_freedv)
|
||||
self.datac13_nin = codec2.api.freedv_nin(self.datac13_freedv)
|
||||
self.datac1_nin = codec2.api.freedv_nin(self.datac1_freedv)
|
||||
self.datac3_nin = codec2.api.freedv_nin(self.datac3_freedv)
|
||||
|
||||
|
@ -187,26 +187,26 @@ class Test:
|
|||
x.tofile(self.frx)
|
||||
x = self.resampler.resample48_to_8(x)
|
||||
|
||||
self.datac0_buffer.push(x)
|
||||
self.datac13_buffer.push(x)
|
||||
self.datac1_buffer.push(x)
|
||||
self.datac3_buffer.push(x)
|
||||
|
||||
while self.datac0_buffer.nbuffer >= self.datac0_nin:
|
||||
while self.datac13_buffer.nbuffer >= self.datac13_nin:
|
||||
# demodulate audio
|
||||
nbytes = codec2.api.freedv_rawdatarx(
|
||||
self.datac0_freedv,
|
||||
self.datac0_bytes_out,
|
||||
self.datac0_buffer.buffer.ctypes,
|
||||
self.datac13_freedv,
|
||||
self.datac13_bytes_out,
|
||||
self.datac13_buffer.buffer.ctypes,
|
||||
)
|
||||
self.datac0_buffer.pop(self.datac0_nin)
|
||||
self.datac0_nin = codec2.api.freedv_nin(self.datac0_freedv)
|
||||
if nbytes == self.datac0_bytes_per_frame:
|
||||
self.rx_total_frames_datac0 = self.rx_total_frames_datac0 + 1
|
||||
self.rx_frames_datac0 = self.rx_frames_datac0 + 1
|
||||
self.datac13_buffer.pop(self.datac13_nin)
|
||||
self.datac13_nin = codec2.api.freedv_nin(self.datac13_freedv)
|
||||
if nbytes == self.datac13_bytes_per_frame:
|
||||
self.rx_total_frames_datac13 = self.rx_total_frames_datac13 + 1
|
||||
self.rx_frames_datac13 = self.rx_frames_datac13 + 1
|
||||
|
||||
if self.rx_frames_datac0 == self.N_FRAMES_PER_BURST:
|
||||
self.rx_frames_datac0 = 0
|
||||
self.rx_bursts_datac0 = self.rx_bursts_datac0 + 1
|
||||
if self.rx_frames_datac13 == self.N_FRAMES_PER_BURST:
|
||||
self.rx_frames_datac13 = 0
|
||||
self.rx_bursts_datac13 = self.rx_bursts_datac13 + 1
|
||||
|
||||
while self.datac1_buffer.nbuffer >= self.datac1_nin:
|
||||
# demodulate audio
|
||||
|
@ -243,7 +243,7 @@ class Test:
|
|||
self.rx_bursts_datac3 = self.rx_bursts_datac3 + 1
|
||||
|
||||
if (
|
||||
self.rx_bursts_datac0 and self.rx_bursts_datac1 and self.rx_bursts_datac3
|
||||
self.rx_bursts_datac13 and self.rx_bursts_datac1 and self.rx_bursts_datac3
|
||||
) == self.N_BURSTS:
|
||||
self.receive = False
|
||||
|
||||
|
@ -253,11 +253,11 @@ class Test:
|
|||
while self.receive:
|
||||
time.sleep(0.01)
|
||||
if self.DEBUGGING_MODE:
|
||||
self.datac0_rxstatus = codec2.api.freedv_get_rx_status(
|
||||
self.datac0_freedv
|
||||
self.datac13_rxstatus = codec2.api.freedv_get_rx_status(
|
||||
self.datac13_freedv
|
||||
)
|
||||
self.datac0_rxstatus = codec2.api.rx_sync_flags_to_text[
|
||||
self.datac0_rxstatus
|
||||
self.datac13_rxstatus = codec2.api.rx_sync_flags_to_text[
|
||||
self.datac13_rxstatus
|
||||
]
|
||||
|
||||
self.datac1_rxstatus = codec2.api.freedv_get_rx_status(
|
||||
|
@ -277,8 +277,8 @@ class Test:
|
|||
print(
|
||||
"NIN0: %5d RX_STATUS0: %4s NIN1: %5d RX_STATUS1: %4s NIN3: %5d RX_STATUS3: %4s"
|
||||
% (
|
||||
self.datac0_nin,
|
||||
self.datac0_rxstatus,
|
||||
self.datac13_nin,
|
||||
self.datac13_rxstatus,
|
||||
self.datac1_nin,
|
||||
self.datac1_rxstatus,
|
||||
self.datac3_nin,
|
||||
|
@ -309,7 +309,7 @@ class Test:
|
|||
)
|
||||
|
||||
print(
|
||||
f"DATAC0: {self.rx_bursts_datac0}/{self.rx_total_frames_datac0} DATAC1: {self.rx_bursts_datac1}/{self.rx_total_frames_datac1} DATAC3: {self.rx_bursts_datac3}/{self.rx_total_frames_datac3}",
|
||||
f"datac13: {self.rx_bursts_datac13}/{self.rx_total_frames_datac13} DATAC1: {self.rx_bursts_datac1}/{self.rx_total_frames_datac1} DATAC3: {self.rx_bursts_datac3}/{self.rx_total_frames_datac3}",
|
||||
file=sys.stderr,
|
||||
)
|
||||
self.frx.close()
|
||||
|
|
|
@ -110,20 +110,20 @@ class Test:
|
|||
sys.exit()
|
||||
|
||||
# open codec2 instance
|
||||
self.datac0_freedv = ctypes.cast(
|
||||
codec2.api.freedv_open(codec2.api.FREEDV_MODE_DATAC0), ctypes.c_void_p
|
||||
self.datac13_freedv = ctypes.cast(
|
||||
codec2.api.freedv_open(codec2.FREEDV_MODE.datac13.value), ctypes.c_void_p
|
||||
)
|
||||
self.datac0_bytes_per_frame = int(
|
||||
codec2.api.freedv_get_bits_per_modem_frame(self.datac0_freedv) / 8
|
||||
self.datac13_bytes_per_frame = int(
|
||||
codec2.api.freedv_get_bits_per_modem_frame(self.datac13_freedv) / 8
|
||||
)
|
||||
self.datac0_bytes_out = ctypes.create_string_buffer(self.datac0_bytes_per_frame)
|
||||
self.datac13_bytes_out = ctypes.create_string_buffer(self.datac13_bytes_per_frame)
|
||||
codec2.api.freedv_set_frames_per_burst(
|
||||
self.datac0_freedv, self.N_FRAMES_PER_BURST
|
||||
self.datac13_freedv, self.N_FRAMES_PER_BURST
|
||||
)
|
||||
self.datac0_buffer = codec2.audio_buffer(2 * self.AUDIO_FRAMES_PER_BUFFER)
|
||||
self.datac13_buffer = codec2.audio_buffer(2 * self.AUDIO_FRAMES_PER_BUFFER)
|
||||
|
||||
self.datac1_freedv = ctypes.cast(
|
||||
codec2.api.freedv_open(codec2.api.FREEDV_MODE_DATAC1), ctypes.c_void_p
|
||||
codec2.api.freedv_open(codec2.FREEDV_MODE.datac1.value), ctypes.c_void_p
|
||||
)
|
||||
self.datac1_bytes_per_frame = int(
|
||||
codec2.api.freedv_get_bits_per_modem_frame(self.datac1_freedv) / 8
|
||||
|
@ -135,7 +135,7 @@ class Test:
|
|||
self.datac1_buffer = codec2.audio_buffer(2 * self.AUDIO_FRAMES_PER_BUFFER)
|
||||
|
||||
self.datac3_freedv = ctypes.cast(
|
||||
codec2.api.freedv_open(codec2.api.FREEDV_MODE_DATAC3), ctypes.c_void_p
|
||||
codec2.api.freedv_open(codec2.FREEDV_MODE.datac3.value), ctypes.c_void_p
|
||||
)
|
||||
self.datac3_bytes_per_frame = int(
|
||||
codec2.api.freedv_get_bits_per_modem_frame(self.datac3_freedv) / 8
|
||||
|
@ -147,9 +147,9 @@ class Test:
|
|||
self.datac3_buffer = codec2.audio_buffer(2 * self.AUDIO_FRAMES_PER_BUFFER)
|
||||
|
||||
# SET COUNTERS
|
||||
self.rx_total_frames_datac0 = 0
|
||||
self.rx_frames_datac0 = 0
|
||||
self.rx_bursts_datac0 = 0
|
||||
self.rx_total_frames_datac13 = 0
|
||||
self.rx_frames_datac13 = 0
|
||||
self.rx_bursts_datac13 = 0
|
||||
|
||||
self.rx_total_frames_datac1 = 0
|
||||
self.rx_frames_datac1 = 0
|
||||
|
@ -171,7 +171,7 @@ class Test:
|
|||
self.frx = open("rx48_callback_multimode.raw", mode="wb")
|
||||
|
||||
# initial nin values
|
||||
self.datac0_nin = codec2.api.freedv_nin(self.datac0_freedv)
|
||||
self.datac13_nin = codec2.api.freedv_nin(self.datac13_freedv)
|
||||
self.datac1_nin = codec2.api.freedv_nin(self.datac1_freedv)
|
||||
self.datac3_nin = codec2.api.freedv_nin(self.datac3_freedv)
|
||||
|
||||
|
@ -181,7 +181,7 @@ class Test:
|
|||
x.tofile(self.frx)
|
||||
x = self.resampler.resample48_to_8(x)
|
||||
|
||||
self.datac0_buffer.push(x)
|
||||
self.datac13_buffer.push(x)
|
||||
self.datac1_buffer.push(x)
|
||||
self.datac3_buffer.push(x)
|
||||
|
||||
|
@ -189,9 +189,9 @@ class Test:
|
|||
|
||||
def print_stats(self):
|
||||
if self.DEBUGGING_MODE:
|
||||
self.datac0_rxstatus = codec2.api.freedv_get_rx_status(self.datac0_freedv)
|
||||
self.datac0_rxstatus = codec2.api.rx_sync_flags_to_text[
|
||||
self.datac0_rxstatus
|
||||
self.datac13_rxstatus = codec2.api.freedv_get_rx_status(self.datac13_freedv)
|
||||
self.datac13_rxstatus = codec2.api.rx_sync_flags_to_text[
|
||||
self.datac13_rxstatus
|
||||
]
|
||||
|
||||
self.datac1_rxstatus = codec2.api.freedv_get_rx_status(self.datac1_freedv)
|
||||
|
@ -207,8 +207,8 @@ class Test:
|
|||
print(
|
||||
"NIN0: %5d RX_STATUS0: %4s NIN1: %5d RX_STATUS1: %4s NIN3: %5d RX_STATUS3: %4s"
|
||||
% (
|
||||
self.datac0_nin,
|
||||
self.datac0_rxstatus,
|
||||
self.datac13_nin,
|
||||
self.datac13_rxstatus,
|
||||
self.datac1_nin,
|
||||
self.datac1_rxstatus,
|
||||
self.datac3_nin,
|
||||
|
@ -225,22 +225,22 @@ class Test:
|
|||
print(f"pyAudio error: {e}", file=sys.stderr)
|
||||
|
||||
while self.receive and time.time() < self.timeout:
|
||||
while self.datac0_buffer.nbuffer >= self.datac0_nin:
|
||||
while self.datac13_buffer.nbuffer >= self.datac13_nin:
|
||||
# demodulate audio
|
||||
nbytes = codec2.api.freedv_rawdatarx(
|
||||
self.datac0_freedv,
|
||||
self.datac0_bytes_out,
|
||||
self.datac0_buffer.buffer.ctypes,
|
||||
self.datac13_freedv,
|
||||
self.datac13_bytes_out,
|
||||
self.datac13_buffer.buffer.ctypes,
|
||||
)
|
||||
self.datac0_buffer.pop(self.datac0_nin)
|
||||
self.datac0_nin = codec2.api.freedv_nin(self.datac0_freedv)
|
||||
if nbytes == self.datac0_bytes_per_frame:
|
||||
self.rx_total_frames_datac0 = self.rx_total_frames_datac0 + 1
|
||||
self.rx_frames_datac0 = self.rx_frames_datac0 + 1
|
||||
self.datac13_buffer.pop(self.datac13_nin)
|
||||
self.datac13_nin = codec2.api.freedv_nin(self.datac13_freedv)
|
||||
if nbytes == self.datac13_bytes_per_frame:
|
||||
self.rx_total_frames_datac13 = self.rx_total_frames_datac13 + 1
|
||||
self.rx_frames_datac13 = self.rx_frames_datac13 + 1
|
||||
|
||||
if self.rx_frames_datac0 == self.N_FRAMES_PER_BURST:
|
||||
self.rx_frames_datac0 = 0
|
||||
self.rx_bursts_datac0 = self.rx_bursts_datac0 + 1
|
||||
if self.rx_frames_datac13 == self.N_FRAMES_PER_BURST:
|
||||
self.rx_frames_datac13 = 0
|
||||
self.rx_bursts_datac13 = self.rx_bursts_datac13 + 1
|
||||
self.print_stats()
|
||||
|
||||
while self.datac1_buffer.nbuffer >= self.datac1_nin:
|
||||
|
@ -280,7 +280,7 @@ class Test:
|
|||
self.print_stats()
|
||||
|
||||
if (
|
||||
self.rx_bursts_datac0
|
||||
self.rx_bursts_datac13
|
||||
and self.rx_bursts_datac1
|
||||
and self.rx_bursts_datac3
|
||||
) == self.N_BURSTS:
|
||||
|
@ -297,7 +297,7 @@ class Test:
|
|||
)
|
||||
|
||||
print(
|
||||
f"DATAC0: {self.rx_bursts_datac0}/{self.rx_total_frames_datac0} DATAC1: {self.rx_bursts_datac1}/{self.rx_total_frames_datac1} DATAC3: {self.rx_bursts_datac3}/{self.rx_total_frames_datac3}",
|
||||
f"datac13: {self.rx_bursts_datac13}/{self.rx_total_frames_datac13} DATAC1: {self.rx_bursts_datac1}/{self.rx_total_frames_datac1} DATAC3: {self.rx_bursts_datac3}/{self.rx_total_frames_datac3}",
|
||||
file=sys.stderr,
|
||||
)
|
||||
self.frx.close()
|
||||
|
|
|
@ -158,9 +158,9 @@ class Test:
|
|||
def create_modulation(self):
|
||||
|
||||
modes = [
|
||||
codec2.api.FREEDV_MODE_DATAC0,
|
||||
codec2.api.FREEDV_MODE_DATAC1,
|
||||
codec2.api.FREEDV_MODE_DATAC3,
|
||||
codec2.FREEDV_MODE.datac13.value,
|
||||
codec2.FREEDV_MODE.datac1.value,
|
||||
codec2.FREEDV_MODE.datac3.value,
|
||||
]
|
||||
for m in modes:
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ parser = argparse.ArgumentParser(description="FreeDATA audio test")
|
|||
parser.add_argument("--bursts", dest="N_BURSTS", default=1, type=int)
|
||||
parser.add_argument("--framesperburst", dest="N_FRAMES_PER_BURST", default=1, type=int)
|
||||
parser.add_argument(
|
||||
"--mode", dest="FREEDV_MODE", type=str, choices=["datac0", "datac1", "datac3"]
|
||||
"--mode", dest="FREEDV_MODE", type=str, choices=["datac13", "datac1", "datac3"]
|
||||
)
|
||||
parser.add_argument(
|
||||
"--audiodev",
|
||||
|
@ -35,7 +35,7 @@ parser.add_argument("--debug", dest="DEBUGGING_MODE", action="store_true")
|
|||
parser.add_argument(
|
||||
"--timeout",
|
||||
dest="TIMEOUT",
|
||||
default=10,
|
||||
default=60,
|
||||
type=int,
|
||||
help="Timeout (seconds) before test ends",
|
||||
)
|
||||
|
|
|
@ -22,7 +22,7 @@ parser = argparse.ArgumentParser(description="FreeDATA audio test")
|
|||
parser.add_argument("--bursts", dest="N_BURSTS", default=1, type=int)
|
||||
parser.add_argument("--framesperburst", dest="N_FRAMES_PER_BURST", default=1, type=int)
|
||||
parser.add_argument(
|
||||
"--mode", dest="FREEDV_MODE", type=str, choices=["datac0", "datac1", "datac3"]
|
||||
"--mode", dest="FREEDV_MODE", type=str, choices=["datac13", "datac1", "datac3"]
|
||||
)
|
||||
parser.add_argument(
|
||||
"--audiodev",
|
||||
|
|
|
@ -25,7 +25,7 @@ parser.add_argument("--bursts", dest="N_BURSTS", default=1, type=int)
|
|||
parser.add_argument("--framesperburst", dest="N_FRAMES_PER_BURST", default=1, type=int)
|
||||
parser.add_argument("--delay", dest="DELAY_BETWEEN_BURSTS", default=500, type=int)
|
||||
parser.add_argument(
|
||||
"--mode", dest="FREEDV_MODE", type=str, choices=["datac0", "datac1", "datac3"]
|
||||
"--mode", dest="FREEDV_MODE", type=str, choices=["datac13", "datac1", "datac3"]
|
||||
)
|
||||
parser.add_argument(
|
||||
"--audiodev",
|
||||
|
|
|
@ -22,7 +22,7 @@ import data_handler
|
|||
import helpers
|
||||
import modem
|
||||
import sock
|
||||
import static
|
||||
from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC
|
||||
import structlog
|
||||
|
||||
|
||||
|
@ -39,23 +39,23 @@ def t_setup(
|
|||
modem.RXCHANNEL = tmp_path / "hfchannel1"
|
||||
modem.TESTMODE = True
|
||||
modem.TXCHANNEL = tmp_path / "hfchannel2"
|
||||
static.HAMLIB_RADIOCONTROL = "disabled"
|
||||
static.LOW_BANDWIDTH_MODE = lowbwmode
|
||||
static.MYGRID = bytes("AA12aa", "utf-8")
|
||||
static.RESPOND_TO_CQ = True
|
||||
static.SSID_LIST = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
HamlibParam.hamlib_radiocontrol = "disabled"
|
||||
TNC.low_bandwidth_mode = lowbwmode
|
||||
Station.mygrid = bytes("AA12aa", "utf-8")
|
||||
TNC.respond_to_cq = True
|
||||
Station.ssid_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
# override ARQ SESSION STATE for allowing disconnect command
|
||||
static.ARQ_SESSION_STATE = "connected"
|
||||
ARQ.arq_session_state = "connected"
|
||||
|
||||
mycallsign = helpers.callsign_to_bytes(mycall)
|
||||
mycallsign = helpers.bytes_to_callsign(mycallsign)
|
||||
static.MYCALLSIGN = mycallsign
|
||||
static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN)
|
||||
Station.mycallsign = mycallsign
|
||||
Station.mycallsign_crc = helpers.get_crc_24(Station.mycallsign)
|
||||
|
||||
dxcallsign = helpers.callsign_to_bytes(dxcall)
|
||||
dxcallsign = helpers.bytes_to_callsign(dxcallsign)
|
||||
static.DXCALLSIGN = dxcallsign
|
||||
static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN)
|
||||
Station.dxcallsign = dxcallsign
|
||||
Station.dxcallsign_crc = helpers.get_crc_24(Station.dxcallsign)
|
||||
|
||||
# Create the TNC
|
||||
tnc = data_handler.DATA()
|
||||
|
@ -105,7 +105,7 @@ def t_highsnr_arq_short_station1(
|
|||
log.info("S1 TX: ", mode=static.FRAME_TYPE(frametype).name)
|
||||
|
||||
if (
|
||||
static.LOW_BANDWIDTH_MODE
|
||||
TNC.low_bandwidth_mode
|
||||
and frametype == static.FRAME_TYPE.ARQ_DC_OPEN_W.value
|
||||
):
|
||||
mesg = (
|
||||
|
@ -116,7 +116,7 @@ def t_highsnr_arq_short_station1(
|
|||
log.error(mesg)
|
||||
assert False, mesg
|
||||
if (
|
||||
not static.LOW_BANDWIDTH_MODE
|
||||
not TNC.low_bandwidth_mode
|
||||
and frametype == static.FRAME_TYPE.ARQ_DC_OPEN_N.value
|
||||
):
|
||||
mesg = (
|
||||
|
@ -184,23 +184,23 @@ def t_highsnr_arq_short_station1(
|
|||
log.warning("station1 TIMEOUT", first=True)
|
||||
break
|
||||
time.sleep(0.1)
|
||||
log.info("station1, first", arq_state=pformat(static.ARQ_STATE))
|
||||
log.info("station1, first", arq_state=pformat(ARQ.arq_state))
|
||||
|
||||
data = {"type": "arq", "command": "disconnect", "dxcallsign": dxcall}
|
||||
sock.process_tnc_commands(json.dumps(data, indent=None))
|
||||
time.sleep(0.5)
|
||||
# override ARQ SESSION STATE for allowing disconnect command
|
||||
static.ARQ_SESSION_STATE = "connected"
|
||||
ARQ.arq_session_state = "connected"
|
||||
sock.process_tnc_commands(json.dumps(data, indent=None))
|
||||
|
||||
# Allow enough time for this side to process the disconnect frame.
|
||||
timeout = time.time() + 20
|
||||
while static.ARQ_STATE or tnc.data_queue_transmit.queue:
|
||||
while ARQ.arq_state or tnc.data_queue_transmit.queue:
|
||||
if time.time() > timeout:
|
||||
log.error("station1", TIMEOUT=True)
|
||||
break
|
||||
time.sleep(0.5)
|
||||
log.info("station1", arq_state=pformat(static.ARQ_STATE))
|
||||
log.info("station1", arq_state=pformat(ARQ.arq_state))
|
||||
|
||||
# log.info("S1 DQT: ", DQ_Tx=pformat(tnc.data_queue_transmit.queue))
|
||||
# log.info("S1 DQR: ", DQ_Rx=pformat(tnc.data_queue_received.queue))
|
||||
|
|
|
@ -19,7 +19,7 @@ import data_handler
|
|||
import helpers
|
||||
import modem
|
||||
import sock
|
||||
import static
|
||||
from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC
|
||||
import structlog
|
||||
|
||||
|
||||
|
@ -36,23 +36,23 @@ def t_setup(
|
|||
modem.RXCHANNEL = tmp_path / "hfchannel2"
|
||||
modem.TESTMODE = True
|
||||
modem.TXCHANNEL = tmp_path / "hfchannel1"
|
||||
static.HAMLIB_RADIOCONTROL = "disabled"
|
||||
static.LOW_BANDWIDTH_MODE = lowbwmode
|
||||
static.MYGRID = bytes("AA12aa", "utf-8")
|
||||
static.RESPOND_TO_CQ = True
|
||||
static.SSID_LIST = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
HamlibParam.hamlib_radiocontrol = "disabled"
|
||||
TNC.low_bandwidth_mode = lowbwmode
|
||||
Station.mygrid = bytes("AA12aa", "utf-8")
|
||||
TNC.respond_to_cq = True
|
||||
Station.ssid_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
# override ARQ SESSION STATE for allowing disconnect command
|
||||
static.ARQ_SESSION_STATE = "connected"
|
||||
ARQ.arq_session_state = "connected"
|
||||
|
||||
mycallsign = helpers.callsign_to_bytes(mycall)
|
||||
mycallsign = helpers.bytes_to_callsign(mycallsign)
|
||||
static.MYCALLSIGN = mycallsign
|
||||
static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN)
|
||||
Station.mycallsign = mycallsign
|
||||
Station.mycallsign_crc = helpers.get_crc_24(Station.mycallsign)
|
||||
|
||||
dxcallsign = helpers.callsign_to_bytes(dxcall)
|
||||
dxcallsign = helpers.bytes_to_callsign(dxcallsign)
|
||||
static.DXCALLSIGN = dxcallsign
|
||||
static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN)
|
||||
Station.dxcallsign = dxcallsign
|
||||
Station.dxcallsign_crc = helpers.get_crc_24(Station.dxcallsign)
|
||||
|
||||
# Create the TNC
|
||||
tnc = data_handler.DATA()
|
||||
|
@ -136,13 +136,13 @@ def t_highsnr_arq_short_station2(
|
|||
# the queue to an object for comparisons.
|
||||
while (
|
||||
'"arq":"transmission","status":"received"' not in str(sock.SOCKET_QUEUE.queue)
|
||||
or static.ARQ_STATE
|
||||
or ARQ.arq_state
|
||||
):
|
||||
if time.time() > timeout:
|
||||
log.warning("station2 TIMEOUT", first=True)
|
||||
break
|
||||
time.sleep(0.5)
|
||||
log.info("station2, first", arq_state=pformat(static.ARQ_STATE))
|
||||
log.info("station2, first", arq_state=pformat(ARQ.arq_state))
|
||||
|
||||
# Allow enough time for this side to receive the disconnect frame.
|
||||
timeout = time.time() + 20
|
||||
|
@ -151,7 +151,7 @@ def t_highsnr_arq_short_station2(
|
|||
log.warning("station2", TIMEOUT=True)
|
||||
break
|
||||
time.sleep(0.5)
|
||||
log.info("station2", arq_state=pformat(static.ARQ_STATE))
|
||||
log.info("station2", arq_state=pformat(ARQ.arq_state))
|
||||
|
||||
# log.info("S2 DQT: ", DQ_Tx=pformat(tnc.data_queue_transmit.queue))
|
||||
# log.info("S2 DQR: ", DQ_Rx=pformat(tnc.data_queue_received.queue))
|
||||
|
|
|
@ -5,9 +5,9 @@ simulated audio channel.
|
|||
|
||||
Near end-to-end test for sending / receiving control frames through the TNC and modem
|
||||
and back through on the other station. Data injection initiates from the queue used
|
||||
by the daemon process into and out of the TNC.
|
||||
by the daemon process into and out of the TNCParam.
|
||||
|
||||
Invoked from test_datac0.py.
|
||||
Invoked from test_datac13.py.
|
||||
|
||||
@author: N2KIQ
|
||||
"""
|
||||
|
@ -21,9 +21,10 @@ import data_handler
|
|||
import helpers
|
||||
import modem
|
||||
import sock
|
||||
import static
|
||||
import structlog
|
||||
from static import ARQ, HamlibParam, ModemParam, Station, TNC as TNCParam
|
||||
from static import FRAME_TYPE as FR_TYPE
|
||||
import structlog
|
||||
#from static import FRAME_TYPE as FR_TYPE
|
||||
|
||||
|
||||
def t_setup(
|
||||
|
@ -46,33 +47,35 @@ def t_setup(
|
|||
modem.RXCHANNEL = tmp_path / rx_channel
|
||||
modem.TESTMODE = True
|
||||
modem.TXCHANNEL = tmp_path / tx_channel
|
||||
static.HAMLIB_RADIOCONTROL = "disabled"
|
||||
static.LOW_BANDWIDTH_MODE = lowbwmode or True
|
||||
static.MYGRID = bytes("AA12aa", "utf-8")
|
||||
static.RESPOND_TO_CQ = True
|
||||
static.SSID_LIST = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
HamlibParam.hamlib_radiocontrol = "disabled"
|
||||
TNCParam.low_bandwidth_mode = lowbwmode or True
|
||||
Station.mygrid = bytes("AA12aa", "utf-8")
|
||||
TNCParam.respond_to_cq = True
|
||||
Station.ssid_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
|
||||
mycallsign = helpers.callsign_to_bytes(mycall)
|
||||
mycallsign = helpers.bytes_to_callsign(mycallsign)
|
||||
static.MYCALLSIGN = mycallsign
|
||||
static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN)
|
||||
Station.mycallsign = mycallsign
|
||||
Station.mycallsign_crc = helpers.get_crc_24(Station.mycallsign)
|
||||
|
||||
dxcallsign = helpers.callsign_to_bytes(dxcall)
|
||||
dxcallsign = helpers.bytes_to_callsign(dxcallsign)
|
||||
static.DXCALLSIGN = dxcallsign
|
||||
static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN)
|
||||
Station.dxcallsign = dxcallsign
|
||||
Station.dxcallsign_crc = helpers.get_crc_24(Station.dxcallsign)
|
||||
|
||||
# Create the TNC
|
||||
tnc = data_handler.DATA()
|
||||
tnc_data_handler = data_handler.DATA()
|
||||
orig_rx_func = data_handler.DATA.process_data
|
||||
data_handler.DATA.process_data = t_process_data
|
||||
tnc.log = structlog.get_logger(f"station{station}_DATA")
|
||||
tnc_data_handler.log = structlog.get_logger(f"station{station}_DATA")
|
||||
# Limit the frame-ack timeout
|
||||
tnc.time_list_low_bw = [3, 1, 1]
|
||||
tnc.time_list_high_bw = [3, 1, 1]
|
||||
tnc.time_list = [3, 1, 1]
|
||||
tnc_data_handler.time_list_low_bw = [8, 8, 8]
|
||||
tnc_data_handler.time_list_high_bw = [8, 8, 8]
|
||||
tnc_data_handler.time_list = [8, 8, 8]
|
||||
# Limit number of retries
|
||||
tnc.rx_n_max_retries_per_burst = 4
|
||||
tnc_data_handler.rx_n_max_retries_per_burst = 4
|
||||
ModemParam.tx_delay = 50 # add additional delay time for passing test
|
||||
|
||||
|
||||
# Create the modem
|
||||
t_modem = modem.RF()
|
||||
|
@ -80,10 +83,10 @@ def t_setup(
|
|||
modem.RF.transmit = t_transmit
|
||||
t_modem.log = structlog.get_logger(f"station{station}_RF")
|
||||
|
||||
return tnc, orig_rx_func, orig_tx_func
|
||||
return tnc_data_handler, orig_rx_func, orig_tx_func
|
||||
|
||||
|
||||
def t_datac0_1(
|
||||
def t_datac13_1(
|
||||
parent_pipe,
|
||||
mycall: str,
|
||||
dxcall: str,
|
||||
|
@ -93,7 +96,7 @@ def t_datac0_1(
|
|||
log = structlog.get_logger("station1")
|
||||
orig_tx_func: Callable
|
||||
orig_rx_func: Callable
|
||||
log.debug("t_datac0_1:", TMP_PATH=tmp_path)
|
||||
log.debug("t_datac13_1:", TMP_PATH=tmp_path)
|
||||
|
||||
# Unpack tuple
|
||||
data, timeout_duration, tx_check, _, final_tx_check, _ = config
|
||||
|
@ -131,7 +134,7 @@ def t_datac0_1(
|
|||
# original function captured before this one was put in place.
|
||||
orig_rx_func(self, bytes_out, freedv, bytes_per_frame) # type: ignore
|
||||
|
||||
tnc, orig_rx_func, orig_tx_func = t_setup(
|
||||
tnc_data_handler, orig_rx_func, orig_tx_func = t_setup(
|
||||
1,
|
||||
mycall,
|
||||
dxcall,
|
||||
|
@ -143,20 +146,20 @@ def t_datac0_1(
|
|||
tmp_path,
|
||||
)
|
||||
|
||||
log.info("t_datac0_1:", RXCHANNEL=modem.RXCHANNEL)
|
||||
log.info("t_datac0_1:", TXCHANNEL=modem.TXCHANNEL)
|
||||
log.info("t_datac13_1:", RXCHANNEL=modem.RXCHANNEL)
|
||||
log.info("t_datac13_1:", TXCHANNEL=modem.TXCHANNEL)
|
||||
|
||||
time.sleep(0.5)
|
||||
if "stop" in data["command"]:
|
||||
log.debug("t_datac0_1: STOP test, setting TNC state")
|
||||
static.TNC_STATE = "BUSY"
|
||||
static.ARQ_STATE = True
|
||||
log.debug("t_datac13_1: STOP test, setting TNC state")
|
||||
TNCParam.tnc_state = "BUSY"
|
||||
ARQ.arq_state = True
|
||||
sock.ThreadedTCPRequestHandler.process_tnc_commands(None,json.dumps(data, indent=None))
|
||||
time.sleep(0.5)
|
||||
sock.ThreadedTCPRequestHandler.process_tnc_commands(None,json.dumps(data, indent=None))
|
||||
|
||||
# Assure the test completes.
|
||||
timeout = time.time() + timeout_duration
|
||||
timeout = time.time() + timeout_duration
|
||||
while tx_check not in str(sock.SOCKET_QUEUE.queue):
|
||||
if time.time() > timeout:
|
||||
log.warning(
|
||||
|
@ -166,25 +169,25 @@ def t_datac0_1(
|
|||
tx_check=tx_check,
|
||||
)
|
||||
break
|
||||
time.sleep(0.1)
|
||||
time.sleep(0.5)
|
||||
log.info("station1, first")
|
||||
# override ARQ SESSION STATE for allowing disconnect command
|
||||
static.ARQ_SESSION_STATE = "connected"
|
||||
ARQ.arq_session_state = "connected"
|
||||
data = {"type": "arq", "command": "disconnect", "dxcallsign": dxcall}
|
||||
sock.ThreadedTCPRequestHandler.process_tnc_commands(None,json.dumps(data, indent=None))
|
||||
time.sleep(0.5)
|
||||
|
||||
# Allow enough time for this side to process the disconnect frame.
|
||||
timeout = time.time() + timeout_duration
|
||||
while tnc.data_queue_transmit.queue:
|
||||
timeout = time.time() + timeout_duration
|
||||
while tnc_data_handler.data_queue_transmit.queue:
|
||||
if time.time() > timeout:
|
||||
log.warning("station1", TIMEOUT=True, dq_tx=tnc.data_queue_transmit.queue)
|
||||
log.warning("station1", TIMEOUT=True, dq_tx=tnc_data_handler.data_queue_transmit.queue)
|
||||
break
|
||||
time.sleep(0.5)
|
||||
log.info("station1, final")
|
||||
|
||||
# log.info("S1 DQT: ", DQ_Tx=pformat(tnc.data_queue_transmit.queue))
|
||||
# log.info("S1 DQR: ", DQ_Rx=pformat(tnc.data_queue_received.queue))
|
||||
# log.info("S1 DQT: ", DQ_Tx=pformat(TNCParam.data_queue_transmit.queue))
|
||||
# log.info("S1 DQR: ", DQ_Rx=pformat(TNCParam.data_queue_received.queue))
|
||||
log.debug("S1 Socket: ", socket_queue=pformat(sock.SOCKET_QUEUE.queue))
|
||||
|
||||
for item in final_tx_check:
|
||||
|
@ -199,7 +202,7 @@ def t_datac0_1(
|
|||
log.warning("station1: Exiting!")
|
||||
|
||||
|
||||
def t_datac0_2(
|
||||
def t_datac13_2(
|
||||
parent_pipe,
|
||||
mycall: str,
|
||||
dxcall: str,
|
||||
|
@ -209,7 +212,7 @@ def t_datac0_2(
|
|||
log = structlog.get_logger("station2")
|
||||
orig_tx_func: Callable
|
||||
orig_rx_func: Callable
|
||||
log.debug("t_datac0_2:", TMP_PATH=tmp_path)
|
||||
log.debug("t_datac13_2:", TMP_PATH=tmp_path)
|
||||
|
||||
# Unpack tuple
|
||||
data, timeout_duration, _, rx_check, _, final_rx_check = config
|
||||
|
@ -259,8 +262,8 @@ def t_datac0_2(
|
|||
tmp_path,
|
||||
)
|
||||
|
||||
log.info("t_datac0_2:", RXCHANNEL=modem.RXCHANNEL)
|
||||
log.info("t_datac0_2:", TXCHANNEL=modem.TXCHANNEL)
|
||||
log.info("t_datac13_2:", RXCHANNEL=modem.RXCHANNEL)
|
||||
log.info("t_datac13_2:", TXCHANNEL=modem.TXCHANNEL)
|
||||
|
||||
if "cq" in data:
|
||||
t_data = {"type": "arq", "command": "stop_transmission"}
|
||||
|
@ -268,7 +271,7 @@ def t_datac0_2(
|
|||
sock.ThreadedTCPRequestHandler.process_tnc_commands(None,json.dumps(t_data, indent=None))
|
||||
|
||||
# Assure the test completes.
|
||||
timeout = time.time() + timeout_duration
|
||||
timeout = time.time() + timeout_duration
|
||||
# Compare with the string conversion instead of repeatedly dumping
|
||||
# the queue to an object for comparisons.
|
||||
while rx_check not in str(sock.SOCKET_QUEUE.queue):
|
||||
|
@ -284,7 +287,7 @@ def t_datac0_2(
|
|||
log.info("station2, first")
|
||||
|
||||
# Allow enough time for this side to receive the disconnect frame.
|
||||
timeout = time.time() + timeout_duration
|
||||
timeout = time.time() + timeout_duration
|
||||
while '"arq":"session","status":"close"' not in str(sock.SOCKET_QUEUE.queue):
|
||||
if time.time() > timeout:
|
||||
log.warning("station2", TIMEOUT=True, queue=str(sock.SOCKET_QUEUE.queue))
|
||||
|
@ -292,8 +295,8 @@ def t_datac0_2(
|
|||
time.sleep(0.5)
|
||||
log.info("station2, final")
|
||||
|
||||
# log.info("S2 DQT: ", DQ_Tx=pformat(tnc.data_queue_transmit.queue))
|
||||
# log.info("S2 DQR: ", DQ_Rx=pformat(tnc.data_queue_received.queue))
|
||||
# log.info("S2 DQT: ", DQ_Tx=pformat(TNCParam.data_queue_transmit.queue))
|
||||
# log.info("S2 DQR: ", DQ_Rx=pformat(TNCParam.data_queue_received.queue))
|
||||
log.debug("S2 Socket: ", socket_queue=pformat(sock.SOCKET_QUEUE.queue))
|
||||
|
||||
for item in final_rx_check:
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Negative test utilities for datac0 frames.
|
||||
Negative test utilities for datac13 frames.
|
||||
|
||||
@author: kronenpj
|
||||
"""
|
||||
|
@ -15,9 +15,9 @@ import data_handler
|
|||
import helpers
|
||||
import modem
|
||||
import sock
|
||||
import static
|
||||
from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC, FRAME_TYPE as FR_TYPE
|
||||
import structlog
|
||||
from static import FRAME_TYPE as FR_TYPE
|
||||
#from static import FRAME_TYPE as FR_TYPE
|
||||
|
||||
|
||||
def t_setup(
|
||||
|
@ -40,44 +40,44 @@ def t_setup(
|
|||
modem.RXCHANNEL = tmp_path / rx_channel
|
||||
modem.TESTMODE = True
|
||||
modem.TXCHANNEL = tmp_path / tx_channel
|
||||
static.HAMLIB_RADIOCONTROL = "disabled"
|
||||
static.LOW_BANDWIDTH_MODE = lowbwmode or True
|
||||
static.MYGRID = bytes("AA12aa", "utf-8")
|
||||
static.RESPOND_TO_CQ = True
|
||||
static.SSID_LIST = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
HamlibParam.hamlib_radiocontrol = "disabled"
|
||||
TNC.low_bandwidth_mode = lowbwmode or True
|
||||
Station.mygrid = bytes("AA12aa", "utf-8")
|
||||
TNC.respond_to_cq = True
|
||||
Station.ssid_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
|
||||
mycallsign_bytes = helpers.callsign_to_bytes(mycall)
|
||||
mycallsign = helpers.bytes_to_callsign(mycallsign_bytes)
|
||||
Station.mycallsign = mycallsign
|
||||
Station.mycallsign_crc = helpers.get_crc_24(mycallsign)
|
||||
|
||||
mycallsign = helpers.callsign_to_bytes(mycall)
|
||||
mycallsign = helpers.bytes_to_callsign(mycallsign)
|
||||
static.MYCALLSIGN = mycallsign
|
||||
static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN)
|
||||
|
||||
dxcallsign = helpers.callsign_to_bytes(dxcall)
|
||||
dxcallsign = helpers.bytes_to_callsign(dxcallsign)
|
||||
static.DXCALLSIGN = dxcallsign
|
||||
static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN)
|
||||
dxcallsign_bytes = helpers.callsign_to_bytes(dxcall)
|
||||
dxcallsign = helpers.bytes_to_callsign(dxcallsign_bytes)
|
||||
Station.dxcallsign = dxcallsign
|
||||
Station.dxcallsign_crc = helpers.get_crc_24(dxcallsign)
|
||||
|
||||
# Create the TNC
|
||||
tnc = data_handler.DATA()
|
||||
tnc_data_handler = data_handler.DATA()
|
||||
orig_rx_func = data_handler.DATA.process_data
|
||||
data_handler.DATA.process_data = t_process_data
|
||||
tnc.log = structlog.get_logger(f"station{station}_DATA")
|
||||
tnc_data_handler.log = structlog.get_logger(f"station{station}_DATA")
|
||||
# Limit the frame-ack timeout
|
||||
tnc.time_list_low_bw = [3, 1, 1]
|
||||
tnc.time_list_high_bw = [3, 1, 1]
|
||||
tnc.time_list = [3, 1, 1]
|
||||
tnc_data_handler.time_list_low_bw = [8, 8, 8]
|
||||
tnc_data_handler.time_list_high_bw = [8, 8, 8]
|
||||
tnc_data_handler.time_list = [8, 8, 8]
|
||||
# Limit number of retries
|
||||
tnc.rx_n_max_retries_per_burst = 4
|
||||
|
||||
tnc_data_handler.rx_n_max_retries_per_burst = 4
|
||||
ModemParam.tx_delay = 50 # add additional delay time for passing test
|
||||
# Create the modem
|
||||
t_modem = modem.RF()
|
||||
orig_tx_func = modem.RF.transmit
|
||||
modem.RF.transmit = t_transmit
|
||||
t_modem.log = structlog.get_logger(f"station{station}_RF")
|
||||
|
||||
return tnc, orig_rx_func, orig_tx_func
|
||||
return tnc_data_handler, orig_rx_func, orig_tx_func
|
||||
|
||||
|
||||
def t_datac0_1(
|
||||
def t_datac13_1(
|
||||
parent_pipe,
|
||||
mycall: str,
|
||||
dxcall: str,
|
||||
|
@ -87,7 +87,7 @@ def t_datac0_1(
|
|||
log = structlog.get_logger("station1")
|
||||
orig_tx_func: Callable
|
||||
orig_rx_func: Callable
|
||||
log.debug("t_datac0_1:", TMP_PATH=tmp_path)
|
||||
log.debug("t_datac13_1:", TMP_PATH=tmp_path)
|
||||
|
||||
# Unpack tuple
|
||||
data, timeout_duration, tx_check, _, final_tx_check, _ = config
|
||||
|
@ -125,7 +125,7 @@ def t_datac0_1(
|
|||
# original function captured before this one was put in place.
|
||||
orig_rx_func(self, bytes_out, freedv, bytes_per_frame) # type: ignore
|
||||
|
||||
tnc, orig_rx_func, orig_tx_func = t_setup(
|
||||
tnc_data_handler, orig_rx_func, orig_tx_func = t_setup(
|
||||
1,
|
||||
mycall,
|
||||
dxcall,
|
||||
|
@ -137,21 +137,21 @@ def t_datac0_1(
|
|||
tmp_path,
|
||||
)
|
||||
|
||||
log.info("t_datac0_1:", RXCHANNEL=modem.RXCHANNEL)
|
||||
log.info("t_datac0_1:", TXCHANNEL=modem.TXCHANNEL)
|
||||
log.info("t_datac13_1:", RXCHANNEL=modem.RXCHANNEL)
|
||||
log.info("t_datac13_1:", TXCHANNEL=modem.TXCHANNEL)
|
||||
|
||||
orig_dxcall = static.DXCALLSIGN
|
||||
orig_dxcall = Station.dxcallsign
|
||||
if "stop" in data["command"]:
|
||||
time.sleep(0.5)
|
||||
log.debug(
|
||||
"t_datac0_1: STOP test, setting TNC state",
|
||||
mycall=static.MYCALLSIGN,
|
||||
dxcall=static.DXCALLSIGN,
|
||||
"t_datac13_1: STOP test, setting TNC state",
|
||||
mycall=Station.mycallsign,
|
||||
dxcall=Station.dxcallsign,
|
||||
)
|
||||
static.DXCALLSIGN = helpers.callsign_to_bytes(data["dxcallsign"])
|
||||
static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN)
|
||||
static.TNC_STATE = "BUSY"
|
||||
static.ARQ_STATE = True
|
||||
Station.dxcallsign = helpers.callsign_to_bytes(data["dxcallsign"])
|
||||
Station.dxcallsign_CRC = helpers.get_crc_24(Station.dxcallsign)
|
||||
TNC.tnc_state = "BUSY"
|
||||
ARQ.arq_state = True
|
||||
sock.ThreadedTCPRequestHandler.process_tnc_commands(None,json.dumps(data, indent=None))
|
||||
sock.ThreadedTCPRequestHandler.process_tnc_commands(None,json.dumps(data, indent=None))
|
||||
|
||||
|
@ -172,19 +172,19 @@ def t_datac0_1(
|
|||
if "stop" in data["command"]:
|
||||
time.sleep(0.5)
|
||||
log.debug("STOP test, resetting DX callsign")
|
||||
static.DXCALLSIGN = orig_dxcall
|
||||
static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN)
|
||||
Station.dxcallsign = orig_dxcall
|
||||
Station.dxcallsign_CRC = helpers.get_crc_24(Station.dxcallsign)
|
||||
# override ARQ SESSION STATE for allowing disconnect command
|
||||
static.ARQ_SESSION_STATE = "connected"
|
||||
ARQ.arq_session_state = "connected"
|
||||
data = {"type": "arq", "command": "disconnect", "dxcallsign": dxcall}
|
||||
sock.ThreadedTCPRequestHandler.process_tnc_commands(None,json.dumps(data, indent=None))
|
||||
time.sleep(0.5)
|
||||
|
||||
# Allow enough time for this side to process the disconnect frame.
|
||||
timeout = time.time() + timeout_duration
|
||||
while tnc.data_queue_transmit.queue:
|
||||
while tnc_data_handler.data_queue_transmit.queue:
|
||||
if time.time() > timeout:
|
||||
log.warning("station1", TIMEOUT=True, dq_tx=tnc.data_queue_transmit.queue)
|
||||
log.warning("station1", TIMEOUT=True, dq_tx=tnc_data_handler.data_queue_transmit.queue)
|
||||
break
|
||||
time.sleep(0.5)
|
||||
log.info("station1, final")
|
||||
|
@ -204,7 +204,7 @@ def t_datac0_1(
|
|||
log.warning("station1: Exiting!")
|
||||
|
||||
|
||||
def t_datac0_2(
|
||||
def t_datac13_2(
|
||||
parent_pipe,
|
||||
mycall: str,
|
||||
dxcall: str,
|
||||
|
@ -214,7 +214,7 @@ def t_datac0_2(
|
|||
log = structlog.get_logger("station2")
|
||||
orig_tx_func: Callable
|
||||
orig_rx_func: Callable
|
||||
log.debug("t_datac0_2:", TMP_PATH=tmp_path)
|
||||
log.debug("t_datac13_2:", TMP_PATH=tmp_path)
|
||||
|
||||
# Unpack tuple
|
||||
data, timeout_duration, _, rx_check, _, final_rx_check = config
|
||||
|
@ -264,9 +264,9 @@ def t_datac0_2(
|
|||
tmp_path,
|
||||
)
|
||||
|
||||
log.info("t_datac0_2:", RXCHANNEL=modem.RXCHANNEL)
|
||||
log.info("t_datac0_2:", TXCHANNEL=modem.TXCHANNEL)
|
||||
log.info("t_datac0_2:", mycall=static.MYCALLSIGN)
|
||||
log.info("t_datac13_2:", RXCHANNEL=modem.RXCHANNEL)
|
||||
log.info("t_datac13_2:", TXCHANNEL=modem.TXCHANNEL)
|
||||
log.info("t_datac13_2:", mycall=Station.mycallsign)
|
||||
|
||||
if "cq" in data:
|
||||
t_data = {"type": "arq", "command": "stop_transmission"}
|
||||
|
@ -292,9 +292,6 @@ def t_datac0_2(
|
|||
# Allow enough time for this side to receive the disconnect frame.
|
||||
timeout = time.time() + timeout_duration
|
||||
while '"arq":"session", "status":"close"' not in str(sock.SOCKET_QUEUE.queue):
|
||||
|
||||
|
||||
|
||||
if time.time() > timeout:
|
||||
log.warning("station2", TIMEOUT=True, queue=str(sock.SOCKET_QUEUE.queue))
|
||||
break
|
|
@ -67,7 +67,7 @@ def test_mm_rx():
|
|||
for idx in range(3):
|
||||
datac_freedv.append(
|
||||
ctypes.cast(
|
||||
codec2.api.freedv_open(codec2.api.FREEDV_MODE_DATAC0), ctypes.c_void_p
|
||||
codec2.api.freedv_open(codec2.FREEDV_MODE.datac13.value), ctypes.c_void_p
|
||||
)
|
||||
)
|
||||
datac_bytes_per_frame.append(
|
||||
|
@ -121,11 +121,11 @@ def test_mm_rx():
|
|||
for idx in range(3):
|
||||
datac_nin[idx] = codec2.api.freedv_nin(datac_freedv[idx])
|
||||
|
||||
def print_stats(time_datac0, time_datac1, time_datac3):
|
||||
def print_stats(time_datac13, time_datac1, time_datac3):
|
||||
if not DEBUGGING_MODE:
|
||||
return
|
||||
|
||||
time_datac = [time_datac0, time_datac1, time_datac3]
|
||||
time_datac = [time_datac13, time_datac1, time_datac3]
|
||||
datac_rxstatus = ["", "", ""]
|
||||
for idx in range(3):
|
||||
datac_rxstatus[idx] = codec2.api.rx_sync_flags_to_text[
|
||||
|
@ -206,7 +206,7 @@ def test_mm_rx():
|
|||
print("TIMEOUT REACHED", file=sys.stderr)
|
||||
|
||||
print(
|
||||
f"DATAC0: {rx_bursts_datac[0]}/{rx_total_frames_datac[0]} "
|
||||
f"DATAC13: {rx_bursts_datac[0]}/{rx_total_frames_datac[0]} "
|
||||
f"DATAC1: {rx_bursts_datac[1]}/{rx_total_frames_datac[1]} "
|
||||
f"DATAC3: {rx_bursts_datac[2]}/{rx_total_frames_datac[2]}",
|
||||
file=sys.stderr,
|
||||
|
@ -241,7 +241,7 @@ def parse_arguments():
|
|||
parser.add_argument(
|
||||
"--timeout",
|
||||
dest="TIMEOUT",
|
||||
default=10,
|
||||
default=60,
|
||||
type=int,
|
||||
help="Timeout (seconds) before test ends",
|
||||
)
|
||||
|
|
|
@ -49,9 +49,9 @@ def test_mm_tx():
|
|||
data_out = b"HELLO WORLD!"
|
||||
|
||||
modes = [
|
||||
codec2.api.FREEDV_MODE_DATAC0,
|
||||
codec2.api.FREEDV_MODE_DATAC1,
|
||||
codec2.api.FREEDV_MODE_DATAC3,
|
||||
codec2.FREEDV_MODE.datac13.value,
|
||||
codec2.FREEDV_MODE.datac1.value,
|
||||
codec2.FREEDV_MODE.datac3.value,
|
||||
]
|
||||
|
||||
if AUDIO_OUTPUT_DEVICE != -1:
|
||||
|
|
|
@ -221,7 +221,7 @@ def parse_arguments():
|
|||
"--framesperburst", dest="N_FRAMES_PER_BURST", default=1, type=int
|
||||
)
|
||||
parser.add_argument(
|
||||
"--mode", dest="FREEDV_MODE", type=str, choices=["datac0", "datac1", "datac3"]
|
||||
"--mode", dest="FREEDV_MODE", type=str, choices=["datac13", "datac1", "datac3"]
|
||||
)
|
||||
parser.add_argument(
|
||||
"--audiodev",
|
||||
|
@ -234,7 +234,7 @@ def parse_arguments():
|
|||
parser.add_argument(
|
||||
"--timeout",
|
||||
dest="TIMEOUT",
|
||||
default=10,
|
||||
default=60,
|
||||
type=int,
|
||||
help="Timeout (seconds) before test ends",
|
||||
)
|
||||
|
|
|
@ -122,18 +122,18 @@ def t_arq_iss(*args):
|
|||
else:
|
||||
assert not MESSAGE, f"{MESSAGE} not known to test."
|
||||
|
||||
time.sleep(0.5)
|
||||
time.sleep(2.5)
|
||||
|
||||
sock.ThreadedTCPRequestHandler.process_tnc_commands(None,json.dumps(data, indent=None))
|
||||
sock.ThreadedTCPRequestHandler.process_tnc_commands(None,json.dumps(data, indent=None))
|
||||
sock.ThreadedTCPRequestHandler.process_tnc_commands(None,json.dumps(data, indent=None))
|
||||
|
||||
time.sleep(1.5)
|
||||
time.sleep(7.5)
|
||||
|
||||
data = {"type": "arq", "command": "stop_transmission"}
|
||||
sock.ThreadedTCPRequestHandler.process_tnc_commands(None,json.dumps(data, indent=None))
|
||||
|
||||
time.sleep(0.5)
|
||||
time.sleep(2.5)
|
||||
sock.ThreadedTCPRequestHandler.process_tnc_commands(None,json.dumps(data, indent=None))
|
||||
|
||||
# Set timeout
|
||||
|
|
|
@ -198,7 +198,7 @@ def parse_arguments():
|
|||
help="delay between bursts in ms",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--mode", dest="FREEDV_MODE", type=str, choices=["datac0", "datac1", "datac3"]
|
||||
"--mode", dest="FREEDV_MODE", type=str, choices=["datac13", "datac1", "datac3"]
|
||||
)
|
||||
parser.add_argument(
|
||||
"--audiodev",
|
||||
|
|
|
@ -18,20 +18,38 @@ import structlog
|
|||
|
||||
log = structlog.get_logger("codec2")
|
||||
|
||||
|
||||
# Enum for codec2 modes
|
||||
class FREEDV_MODE(Enum):
|
||||
"""
|
||||
Enumeration for codec2 modes and names
|
||||
"""
|
||||
sig0 = 14
|
||||
sig1 = 14
|
||||
sig0 = 19
|
||||
sig1 = 19
|
||||
datac0 = 14
|
||||
datac1 = 10
|
||||
datac3 = 12
|
||||
datac4 = 18
|
||||
datac13 = 19
|
||||
fsk_ldpc = 9
|
||||
fsk_ldpc_0 = 200
|
||||
fsk_ldpc_1 = 201
|
||||
|
||||
class FREEDV_MODE_USED_SLOTS(Enum):
|
||||
"""
|
||||
Enumeration for codec2 used slots
|
||||
"""
|
||||
sig0 = [False, False, True, False, False]
|
||||
sig1 = [False, False, True, False, False]
|
||||
datac0 = [False, False, True, False, False]
|
||||
datac1 = [False, True, True, True, False]
|
||||
datac3 = [False, False, True, False, False]
|
||||
datac4 = [False, False, True, False, False]
|
||||
datac13 = [False, False, True, False, False]
|
||||
fsk_ldpc = [False, False, True, False, False]
|
||||
fsk_ldpc_0 = [False, False, True, False, False]
|
||||
fsk_ldpc_1 = [False, False, True, False, False]
|
||||
|
||||
# Function for returning the mode value
|
||||
def freedv_get_mode_value_by_name(mode: str) -> int:
|
||||
"""
|
||||
|
@ -101,6 +119,9 @@ if api is None or "api" not in locals():
|
|||
api.freedv_open.argype = [ctypes.c_int] # type: ignore
|
||||
api.freedv_open.restype = ctypes.c_void_p
|
||||
|
||||
api.freedv_set_sync.argype = [ctypes.c_void_p, ctypes.c_int] # type: ignore
|
||||
api.freedv_set_sync.restype = ctypes.c_void_p
|
||||
|
||||
api.freedv_open_advanced.argtype = [ctypes.c_int, ctypes.c_void_p] # type: ignore
|
||||
api.freedv_open_advanced.restype = ctypes.c_void_p
|
||||
|
||||
|
@ -150,10 +171,6 @@ api.freedv_get_n_max_modem_samples.argtype = [ctypes.c_void_p] # type: ignore
|
|||
api.freedv_get_n_max_modem_samples.restype = ctypes.c_int
|
||||
|
||||
api.FREEDV_FS_8000 = 8000 # type: ignore
|
||||
api.FREEDV_MODE_DATAC1 = 10 # type: ignore
|
||||
api.FREEDV_MODE_DATAC3 = 12 # type: ignore
|
||||
api.FREEDV_MODE_DATAC0 = 14 # type: ignore
|
||||
api.FREEDV_MODE_FSK_LDPC = 9 # type: ignore
|
||||
|
||||
# -------------------------------- FSK LDPC MODE SETTINGS
|
||||
|
||||
|
@ -216,7 +233,7 @@ api.FREEDV_MODE_FSK_LDPC_1_ADV.codename = "H_4096_8192_3d".encode("utf-8") # co
|
|||
|
||||
# ------- MODEM STATS STRUCTURES
|
||||
MODEM_STATS_NC_MAX = 50 + 1 * 2
|
||||
MODEM_STATS_NR_MAX = 160 * 2
|
||||
MODEM_STATS_NR_MAX = 320 * 2
|
||||
MODEM_STATS_ET_MAX = 8
|
||||
MODEM_STATS_EYE_IND_MAX = 160
|
||||
MODEM_STATS_NSPEC = 512
|
||||
|
|
|
@ -4,20 +4,20 @@ tncport = 3000
|
|||
|
||||
[STATION]
|
||||
#station settings
|
||||
mycall = DJ2LS-9
|
||||
mygrid = JN12AA
|
||||
mycall = DN2LS-0
|
||||
mygrid = JN48cs
|
||||
ssid_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
|
||||
[AUDIO]
|
||||
#audio settings
|
||||
rx = 0
|
||||
tx = 1
|
||||
txaudiolevel = 78
|
||||
tx = 0
|
||||
txaudiolevel = 250
|
||||
auto_tune = False
|
||||
|
||||
[RADIO]
|
||||
#radio settings
|
||||
radiocontrol = rigctld
|
||||
radiocontrol = disabled
|
||||
rigctld_ip = 127.0.0.1
|
||||
rigctld_port = 4532
|
||||
|
||||
|
@ -26,12 +26,12 @@ rigctld_port = 4532
|
|||
scatter = True
|
||||
fft = True
|
||||
narrowband = False
|
||||
fmin = -250.0
|
||||
fmax = 250.0
|
||||
fmin = -150.0
|
||||
fmax = 150.0
|
||||
qrv = True
|
||||
rxbuffersize = 16
|
||||
explorer = False
|
||||
stats = False
|
||||
fsk = False
|
||||
tx_delay = 0
|
||||
tx_delay = 800
|
||||
|
||||
|
|
|
@ -26,7 +26,8 @@ import crcengine
|
|||
import log_handler
|
||||
import serial.tools.list_ports
|
||||
import sock
|
||||
import static
|
||||
from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC
|
||||
|
||||
import structlog
|
||||
import ujson as json
|
||||
import config
|
||||
|
@ -82,10 +83,10 @@ class DAEMON:
|
|||
"""
|
||||
while True:
|
||||
try:
|
||||
if not static.TNCSTARTED:
|
||||
if not Daemon.tncstarted:
|
||||
(
|
||||
static.AUDIO_INPUT_DEVICES,
|
||||
static.AUDIO_OUTPUT_DEVICES,
|
||||
AudioParam.audio_input_devices,
|
||||
AudioParam.audio_output_devices,
|
||||
) = audio.get_audio_devices()
|
||||
except Exception as err1:
|
||||
self.log.error(
|
||||
|
@ -112,7 +113,7 @@ class DAEMON:
|
|||
{"port": str(port), "description": str(description)}
|
||||
)
|
||||
|
||||
static.SERIAL_DEVICES = serial_devices
|
||||
Daemon.serial_devices = serial_devices
|
||||
threading.Event().wait(1)
|
||||
except Exception as err1:
|
||||
self.log.error(
|
||||
|
@ -210,10 +211,10 @@ class DAEMON:
|
|||
self.log.warning("[DMN] Starting TNC", rig=data[5], port=data[6])
|
||||
|
||||
# list of parameters, necessary for running subprocess command as a list
|
||||
options = ["--port", str(static.DAEMONPORT - 1)]
|
||||
options = ["--port", str(DAEMON.port - 1)]
|
||||
|
||||
# create an additional list entry for parameters not covered by gui
|
||||
data[50] = int(static.DAEMONPORT - 1)
|
||||
data[50] = int(DAEMON.port - 1)
|
||||
|
||||
options.append("--mycall")
|
||||
options.extend((data[1], "--mygrid"))
|
||||
|
@ -317,8 +318,8 @@ class DAEMON:
|
|||
|
||||
self.log.info("[DMN] TNC started", path="source")
|
||||
|
||||
static.TNCPROCESS = proc
|
||||
static.TNCSTARTED = True
|
||||
Daemon.tncprocess = proc
|
||||
Daemon.tncstarted = True
|
||||
if __name__ == "__main__":
|
||||
mainlog = structlog.get_logger(__file__)
|
||||
# we need to run this on Windows for multiprocessing support
|
||||
|
@ -335,7 +336,7 @@ if __name__ == "__main__":
|
|||
)
|
||||
ARGS = PARSER.parse_args()
|
||||
|
||||
static.DAEMONPORT = ARGS.socket_port
|
||||
DAEMON.port = ARGS.socket_port
|
||||
|
||||
try:
|
||||
if sys.platform == "linux":
|
||||
|
@ -363,11 +364,11 @@ if __name__ == "__main__":
|
|||
config = config.CONFIG("config.ini")
|
||||
|
||||
try:
|
||||
mainlog.info("[DMN] Starting TCP/IP socket", port=static.DAEMONPORT)
|
||||
mainlog.info("[DMN] Starting TCP/IP socket", port=DAEMON.port)
|
||||
# https://stackoverflow.com/a/16641793
|
||||
socketserver.TCPServer.allow_reuse_address = True
|
||||
cmdserver = sock.ThreadedTCPServer(
|
||||
(static.HOST, static.DAEMONPORT), sock.ThreadedTCPRequestHandler
|
||||
(TNC.host, DAEMON.port), sock.ThreadedTCPRequestHandler
|
||||
)
|
||||
server_thread = threading.Thread(target=cmdserver.serve_forever)
|
||||
server_thread.daemon = True
|
||||
|
@ -375,7 +376,7 @@ if __name__ == "__main__":
|
|||
|
||||
except Exception as err:
|
||||
mainlog.error(
|
||||
"[DMN] Starting TCP/IP socket failed", port=static.DAEMONPORT, e=err
|
||||
"[DMN] Starting TCP/IP socket failed", port=DAEMON.port, e=err
|
||||
)
|
||||
sys.exit(1)
|
||||
daemon = DAEMON()
|
||||
|
@ -384,7 +385,7 @@ if __name__ == "__main__":
|
|||
"[DMN] Starting FreeDATA Daemon",
|
||||
author="DJ2LS",
|
||||
year="2023",
|
||||
version=static.VERSION,
|
||||
version=TNC.version,
|
||||
)
|
||||
while True:
|
||||
threading.Event().wait(1)
|
||||
|
|
1576
tnc/data_handler.py
1576
tnc/data_handler.py
File diff suppressed because it is too large
Load diff
|
@ -13,6 +13,8 @@ import time
|
|||
import ujson as json
|
||||
import structlog
|
||||
import static
|
||||
from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC
|
||||
|
||||
|
||||
log = structlog.get_logger("explorer")
|
||||
|
||||
|
@ -32,30 +34,31 @@ class explorer():
|
|||
|
||||
def push(self):
|
||||
|
||||
frequency = 0 if static.HAMLIB_FREQUENCY is None else static.HAMLIB_FREQUENCY
|
||||
frequency = 0 if HamlibParam.hamlib_frequency is None else HamlibParam.hamlib_frequency
|
||||
band = "USB"
|
||||
callsign = str(static.MYCALLSIGN, "utf-8")
|
||||
gridsquare = str(static.MYGRID, "utf-8")
|
||||
version = str(static.VERSION)
|
||||
bandwidth = str(static.LOW_BANDWIDTH_MODE)
|
||||
beacon = str(static.BEACON_STATE)
|
||||
strength = str(static.HAMLIB_STRENGTH)
|
||||
callsign = str(Station.mycallsign, "utf-8")
|
||||
gridsquare = str(Station.mygrid, "utf-8")
|
||||
version = str(TNC.version)
|
||||
bandwidth = str(TNC.low_bandwidth_mode)
|
||||
beacon = str(Beacon.beacon_state)
|
||||
strength = str(HamlibParam.hamlib_strength)
|
||||
|
||||
log.info("[EXPLORER] publish", frequency=frequency, band=band, callsign=callsign, gridsquare=gridsquare, version=version, bandwidth=bandwidth)
|
||||
|
||||
headers = {"Content-Type": "application/json"}
|
||||
station_data = {'callsign': callsign, 'gridsquare': gridsquare, 'frequency': frequency, 'strength': strength, 'band': band, 'version': version, 'bandwidth': bandwidth, 'beacon': beacon, "lastheard": []}
|
||||
|
||||
for i in static.HEARD_STATIONS:
|
||||
for i in TNC.heard_stations:
|
||||
try:
|
||||
callsign = str(i[0], "UTF-8")
|
||||
grid = str(i[1], "UTF-8")
|
||||
timestamp = i[2]
|
||||
frequency = i[6]
|
||||
try:
|
||||
snr = i[4].split("/")[1]
|
||||
except AttributeError:
|
||||
snr = str(i[4])
|
||||
station_data["lastheard"].append({"callsign": callsign, "grid": grid, "snr": snr, "timestamp": timestamp})
|
||||
station_data["lastheard"].append({"callsign": callsign, "grid": grid, "snr": snr, "timestamp": timestamp, "frequency": frequency})
|
||||
except Exception as e:
|
||||
log.debug("[EXPLORER] not publishing station", e=e)
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import time
|
|||
from datetime import datetime,timezone
|
||||
import crcengine
|
||||
import static
|
||||
from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC
|
||||
import structlog
|
||||
import numpy as np
|
||||
import threading
|
||||
|
@ -130,16 +131,16 @@ def add_to_heard_stations(dxcallsign, dxgrid, datatype, snr, offset, frequency):
|
|||
Nothing
|
||||
"""
|
||||
# check if buffer empty
|
||||
if len(static.HEARD_STATIONS) == 0:
|
||||
static.HEARD_STATIONS.append(
|
||||
if len(TNC.heard_stations) == 0:
|
||||
TNC.heard_stations.append(
|
||||
[dxcallsign, dxgrid, int(datetime.now(timezone.utc).timestamp()), datatype, snr, offset, frequency]
|
||||
)
|
||||
# if not, we search and update
|
||||
else:
|
||||
for i in range(len(static.HEARD_STATIONS)):
|
||||
for i in range(len(TNC.heard_stations)):
|
||||
# Update callsign with new timestamp
|
||||
if static.HEARD_STATIONS[i].count(dxcallsign) > 0:
|
||||
static.HEARD_STATIONS[i] = [
|
||||
if TNC.heard_stations[i].count(dxcallsign) > 0:
|
||||
TNC.heard_stations[i] = [
|
||||
dxcallsign,
|
||||
dxgrid,
|
||||
int(time.time()),
|
||||
|
@ -150,8 +151,8 @@ def add_to_heard_stations(dxcallsign, dxgrid, datatype, snr, offset, frequency):
|
|||
]
|
||||
break
|
||||
# Insert if nothing found
|
||||
if i == len(static.HEARD_STATIONS) - 1:
|
||||
static.HEARD_STATIONS.append(
|
||||
if i == len(TNC.heard_stations) - 1:
|
||||
TNC.heard_stations.append(
|
||||
[
|
||||
dxcallsign,
|
||||
dxgrid,
|
||||
|
@ -165,10 +166,10 @@ def add_to_heard_stations(dxcallsign, dxgrid, datatype, snr, offset, frequency):
|
|||
break
|
||||
|
||||
|
||||
# for idx, item in enumerate(static.HEARD_STATIONS):
|
||||
# for idx, item in enumerate(TNC.heard_stations):
|
||||
# if dxcallsign in item:
|
||||
# item = [dxcallsign, int(time.time())]
|
||||
# static.HEARD_STATIONS[idx] = item
|
||||
# TNC.heard_stations[idx] = item
|
||||
|
||||
|
||||
def callsign_to_bytes(callsign) -> bytes:
|
||||
|
@ -305,7 +306,7 @@ def check_callsign(callsign: bytes, crc_to_check: bytes):
|
|||
except Exception as err:
|
||||
log.debug("[HLP] check_callsign: Error callsign SSID to integer:", e=err)
|
||||
|
||||
for ssid in static.SSID_LIST:
|
||||
for ssid in Station.ssid_list:
|
||||
call_with_ssid = bytearray(callsign)
|
||||
call_with_ssid.extend("-".encode("utf-8"))
|
||||
call_with_ssid.extend(str(ssid).encode("utf-8"))
|
||||
|
|
141
tnc/main.py
141
tnc/main.py
|
@ -29,6 +29,7 @@ import helpers
|
|||
import log_handler
|
||||
import modem
|
||||
import static
|
||||
from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC
|
||||
import structlog
|
||||
import explorer
|
||||
import json
|
||||
|
@ -255,7 +256,7 @@ if __name__ == "__main__":
|
|||
ARGS = PARSER.parse_args()
|
||||
|
||||
# set save to folder state for allowing downloading files to local file system
|
||||
static.ARQ_SAVE_TO_FOLDER = ARGS.savetofolder
|
||||
ARQ.arq_save_to_folder = ARGS.savetofolder
|
||||
|
||||
if not ARGS.configfile:
|
||||
|
||||
|
@ -266,46 +267,46 @@ if __name__ == "__main__":
|
|||
try:
|
||||
mycallsign = bytes(ARGS.mycall.upper(), "utf-8")
|
||||
mycallsign = helpers.callsign_to_bytes(mycallsign)
|
||||
static.MYCALLSIGN = helpers.bytes_to_callsign(mycallsign)
|
||||
static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN)
|
||||
static.SSID_LIST = ARGS.ssid_list
|
||||
Station.mycallsign = helpers.bytes_to_callsign(mycallsign)
|
||||
Station.mycallsign_crc = helpers.get_crc_24(Station.mycallsign)
|
||||
Station.ssid_list = ARGS.ssid_list
|
||||
# check if own ssid is always part of ssid list
|
||||
own_ssid = int(static.MYCALLSIGN.split(b"-")[1])
|
||||
if own_ssid not in static.SSID_LIST:
|
||||
static.SSID_LIST.append(own_ssid)
|
||||
own_ssid = int(Station.mycallsign.split(b"-")[1])
|
||||
if own_ssid not in Station.ssid_list:
|
||||
Station.ssid_list.append(own_ssid)
|
||||
|
||||
static.MYGRID = bytes(ARGS.mygrid, "utf-8")
|
||||
Station.mygrid = bytes(ARGS.mygrid, "utf-8")
|
||||
|
||||
# check if we have an int or str as device name
|
||||
try:
|
||||
static.AUDIO_INPUT_DEVICE = int(ARGS.audio_input_device)
|
||||
AudioParam.audio_input_device = int(ARGS.audio_input_device)
|
||||
except ValueError:
|
||||
static.AUDIO_INPUT_DEVICE = ARGS.audio_input_device
|
||||
AudioParam.audio_input_device = ARGS.audio_input_device
|
||||
try:
|
||||
static.AUDIO_OUTPUT_DEVICE = int(ARGS.audio_output_device)
|
||||
AudioParam.audio_output_device = int(ARGS.audio_output_device)
|
||||
except ValueError:
|
||||
static.AUDIO_OUTPUT_DEVICE = ARGS.audio_output_device
|
||||
AudioParam.audio_output_device = ARGS.audio_output_device
|
||||
|
||||
static.PORT = ARGS.socket_port
|
||||
static.HAMLIB_RADIOCONTROL = ARGS.hamlib_radiocontrol
|
||||
static.HAMLIB_RIGCTLD_IP = ARGS.rigctld_ip
|
||||
static.HAMLIB_RIGCTLD_PORT = str(ARGS.rigctld_port)
|
||||
static.ENABLE_SCATTER = ARGS.send_scatter
|
||||
static.ENABLE_FFT = ARGS.send_fft
|
||||
static.ENABLE_FSK = ARGS.enable_fsk
|
||||
static.LOW_BANDWIDTH_MODE = ARGS.low_bandwidth_mode
|
||||
static.TUNING_RANGE_FMIN = ARGS.tuning_range_fmin
|
||||
static.TUNING_RANGE_FMAX = ARGS.tuning_range_fmax
|
||||
static.TX_AUDIO_LEVEL = ARGS.tx_audio_level
|
||||
static.RESPOND_TO_CQ = ARGS.enable_respond_to_cq
|
||||
static.RX_BUFFER_SIZE = ARGS.rx_buffer_size
|
||||
static.ENABLE_EXPLORER = ARGS.enable_explorer
|
||||
static.AUDIO_AUTO_TUNE = ARGS.enable_audio_auto_tune
|
||||
static.ENABLE_STATS = ARGS.enable_stats
|
||||
static.AUDIO_ENABLE_TCI = ARGS.audio_enable_tci
|
||||
static.TCI_IP = ARGS.tci_ip
|
||||
static.TCI_PORT = ARGS.tci_port
|
||||
static.TX_DELAY = ARGS.tx_delay
|
||||
TNC.port = ARGS.socket_port
|
||||
HamlibParam.hamlib_radiocontrol = ARGS.hamlib_radiocontrol
|
||||
HamlibParam.hamlib_rigctld_ip = ARGS.rigctld_ip
|
||||
HamlibParam.hamlib_rigctld_port = str(ARGS.rigctld_port)
|
||||
ModemParam.enable_scatter = ARGS.send_scatter
|
||||
AudioParam.enable_fft = ARGS.send_fft
|
||||
TNC.enable_fsk = ARGS.enable_fsk
|
||||
TNC.low_bandwidth_mode = ARGS.low_bandwidth_mode
|
||||
ModemParam.tuning_range_fmin = ARGS.tuning_range_fmin
|
||||
ModemParam.tuning_range_fmax = ARGS.tuning_range_fmax
|
||||
AudioParam.tx_audio_level = ARGS.tx_audio_level
|
||||
TNC.respond_to_cq = ARGS.enable_respond_to_cq
|
||||
ARQ.rx_buffer_size = ARGS.rx_buffer_size
|
||||
TNC.enable_explorer = ARGS.enable_explorer
|
||||
AudioParam.audio_auto_tune = ARGS.enable_audio_auto_tune
|
||||
TNC.enable_stats = ARGS.enable_stats
|
||||
AudioParam.audio_enable_tci = ARGS.audio_enable_tci
|
||||
TCIParam.ip = ARGS.tci_ip
|
||||
TCIParam.port = ARGS.tci_port
|
||||
ModemParam.tx_delay = ARGS.tx_delay
|
||||
|
||||
except Exception as e:
|
||||
log.error("[DMN] Error reading config file", exception=e)
|
||||
|
@ -320,52 +321,52 @@ if __name__ == "__main__":
|
|||
# then we are forcing a station ssid = 0
|
||||
mycallsign = bytes(conf.get('STATION', 'mycall', 'AA0AA'), "utf-8")
|
||||
mycallsign = helpers.callsign_to_bytes(mycallsign)
|
||||
static.MYCALLSIGN = helpers.bytes_to_callsign(mycallsign)
|
||||
static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN)
|
||||
Station.mycallsign = helpers.bytes_to_callsign(mycallsign)
|
||||
Station.mycallsign_crc = helpers.get_crc_24(Station.mycallsign)
|
||||
|
||||
#json.loads = for converting str list to list
|
||||
static.SSID_LIST = json.loads(conf.get('STATION', 'ssid_list', '[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]'))
|
||||
Station.ssid_list = json.loads(conf.get('STATION', 'ssid_list', '[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]'))
|
||||
|
||||
static.MYGRID = bytes(conf.get('STATION', 'mygrid', 'JN12aa'), "utf-8")
|
||||
Station.mygrid = bytes(conf.get('STATION', 'mygrid', 'JN12aa'), "utf-8")
|
||||
# check if we have an int or str as device name
|
||||
try:
|
||||
static.AUDIO_INPUT_DEVICE = int(conf.get('AUDIO', 'rx', '0'))
|
||||
AudioParam.audio_input_device = int(conf.get('AUDIO', 'rx', '0'))
|
||||
except ValueError:
|
||||
static.AUDIO_INPUT_DEVICE = conf.get('AUDIO', 'rx', '0')
|
||||
AudioParam.audio_input_device = conf.get('AUDIO', 'rx', '0')
|
||||
try:
|
||||
static.AUDIO_OUTPUT_DEVICE = int(conf.get('AUDIO', 'tx', '0'))
|
||||
AudioParam.audio_output_device = int(conf.get('AUDIO', 'tx', '0'))
|
||||
except ValueError:
|
||||
static.AUDIO_OUTPUT_DEVICE = conf.get('AUDIO', 'tx', '0')
|
||||
AudioParam.audio_output_device = conf.get('AUDIO', 'tx', '0')
|
||||
|
||||
static.PORT = int(conf.get('NETWORK', 'tncport', '3000'))
|
||||
static.HAMLIB_RADIOCONTROL = conf.get('RADIO', 'radiocontrol', 'rigctld')
|
||||
static.HAMLIB_RIGCTLD_IP = conf.get('RADIO', 'rigctld_ip', '127.0.0.1')
|
||||
static.HAMLIB_RIGCTLD_PORT = str(conf.get('RADIO', 'rigctld_port', '4532'))
|
||||
static.ENABLE_SCATTER = conf.get('TNC', 'scatter', 'True')
|
||||
static.ENABLE_FFT = conf.get('TNC', 'fft', 'True')
|
||||
static.ENABLE_FSK = conf.get('TNC', 'fsk', 'False')
|
||||
static.LOW_BANDWIDTH_MODE = conf.get('TNC', 'narrowband', 'False')
|
||||
static.TUNING_RANGE_FMIN = float(conf.get('TNC', 'fmin', '-50.0'))
|
||||
static.TUNING_RANGE_FMAX = float(conf.get('TNC', 'fmax', '50.0'))
|
||||
static.TX_AUDIO_LEVEL = int(conf.get('AUDIO', 'txaudiolevel', '100'))
|
||||
static.RESPOND_TO_CQ = conf.get('TNC', 'qrv', 'True')
|
||||
static.RX_BUFFER_SIZE = int(conf.get('TNC', 'rxbuffersize', '16'))
|
||||
static.ENABLE_EXPLORER = conf.get('TNC', 'explorer', 'False')
|
||||
static.AUDIO_AUTO_TUNE = conf.get('AUDIO', 'auto_tune', 'False')
|
||||
static.ENABLE_STATS = conf.get('TNC', 'stats', 'False')
|
||||
static.AUDIO_ENABLE_TCI = conf.get('AUDIO', 'enable_tci', 'False')
|
||||
static.TCI_IP = str(conf.get('AUDIO', 'tci_ip', 'localhost'))
|
||||
static.TCI_PORT = int(conf.get('AUDIO', 'tci_port', '50001'))
|
||||
static.TX_DELAY = int(conf.get('TNC', 'tx_delay', '0'))
|
||||
TNC.port = int(conf.get('NETWORK', 'tncport', '3000'))
|
||||
HamlibParam.hamlib_radiocontrol = conf.get('RADIO', 'radiocontrol', 'rigctld')
|
||||
HamlibParam.hamlib_rigctld_ip = conf.get('RADIO', 'rigctld_ip', '127.0.0.1')
|
||||
HamlibParam.hamlib_rigctld_port = str(conf.get('RADIO', 'rigctld_port', '4532'))
|
||||
ModemParam.enable_scatter = conf.get('TNC', 'scatter', 'True')
|
||||
AudioParam.enable_fft = conf.get('TNC', 'fft', 'True')
|
||||
TNC.enable_fsk = conf.get('TNC', 'fsk', 'False')
|
||||
TNC.low_bandwidth_mode = conf.get('TNC', 'narrowband', 'False')
|
||||
ModemParam.tuning_range_fmin = float(conf.get('TNC', 'fmin', '-50.0'))
|
||||
ModemParam.tuning_range_fmax = float(conf.get('TNC', 'fmax', '50.0'))
|
||||
AudioParam.tx_audio_level = int(conf.get('AUDIO', 'txaudiolevel', '100'))
|
||||
TNC.respond_to_cq = conf.get('TNC', 'qrv', 'True')
|
||||
ARQ.rx_buffer_size = int(conf.get('TNC', 'rxbuffersize', '16'))
|
||||
TNC.enable_explorer = conf.get('TNC', 'explorer', 'False')
|
||||
AudioParam.audio_auto_tune = conf.get('AUDIO', 'auto_tune', 'False')
|
||||
TNC.enable_stats = conf.get('TNC', 'stats', 'False')
|
||||
AudioParam.audio_enable_tci = conf.get('AUDIO', 'enable_tci', 'False')
|
||||
TCIParam.ip = str(conf.get('AUDIO', 'tci_ip', 'localhost'))
|
||||
TCIParam.port = int(conf.get('AUDIO', 'tci_port', '50001'))
|
||||
ModemParam.tx_delay = int(conf.get('TNC', 'tx_delay', '0'))
|
||||
except KeyError as e:
|
||||
log.warning("[CFG] Error reading config file near", key=str(e))
|
||||
except Exception as e:
|
||||
log.warning("[CFG] Error", e=e)
|
||||
|
||||
# make sure the own ssid is always part of the ssid list
|
||||
my_ssid = int(static.MYCALLSIGN.split(b'-')[1])
|
||||
if my_ssid not in static.SSID_LIST:
|
||||
static.SSID_LIST.append(my_ssid)
|
||||
my_ssid = int(Station.mycallsign.split(b'-')[1])
|
||||
if my_ssid not in Station.ssid_list:
|
||||
Station.ssid_list.append(my_ssid)
|
||||
|
||||
# we need to wait until we got all parameters from argparse first before we can load the other modules
|
||||
import sock
|
||||
|
@ -394,7 +395,7 @@ if __name__ == "__main__":
|
|||
log.error("[DMN] logger init error", exception=err)
|
||||
|
||||
log.info(
|
||||
"[TNC] Starting FreeDATA", author="DJ2LS", version=static.VERSION
|
||||
"[TNC] Starting FreeDATA", author="DJ2LS", version=TNC.version
|
||||
)
|
||||
|
||||
# start data handler
|
||||
|
@ -404,17 +405,17 @@ if __name__ == "__main__":
|
|||
modem = modem.RF()
|
||||
|
||||
# optionally start explorer module
|
||||
if static.ENABLE_EXPLORER:
|
||||
log.info("[EXPLORER] Publishing to https://explorer.freedata.app", state=static.ENABLE_EXPLORER)
|
||||
if TNC.enable_explorer:
|
||||
log.info("[EXPLORER] Publishing to https://explorer.freedata.app", state=TNC.enable_explorer)
|
||||
explorer = explorer.explorer()
|
||||
|
||||
# --------------------------------------------START CMD SERVER
|
||||
try:
|
||||
log.info("[TNC] Starting TCP/IP socket", port=static.PORT)
|
||||
log.info("[TNC] Starting TCP/IP socket", port=TNC.port)
|
||||
# https://stackoverflow.com/a/16641793
|
||||
socketserver.TCPServer.allow_reuse_address = True
|
||||
cmdserver = sock.ThreadedTCPServer(
|
||||
(static.HOST, static.PORT), sock.ThreadedTCPRequestHandler
|
||||
(TNC.host, TNC.port), sock.ThreadedTCPRequestHandler
|
||||
)
|
||||
server_thread = threading.Thread(target=cmdserver.serve_forever)
|
||||
|
||||
|
@ -422,7 +423,7 @@ if __name__ == "__main__":
|
|||
server_thread.start()
|
||||
|
||||
except Exception as err:
|
||||
log.error("[TNC] Starting TCP/IP socket failed", port=static.PORT, e=err)
|
||||
log.error("[TNC] Starting TCP/IP socket failed", port=TNC.port, e=err)
|
||||
sys.exit(1)
|
||||
while True:
|
||||
threading.Event().wait(1)
|
||||
threading.Event().wait(1)
|
567
tnc/modem.py
567
tnc/modem.py
File diff suppressed because it is too large
Load diff
|
@ -3,6 +3,7 @@ Hold queues used by more than one module to eliminate cyclic imports.
|
|||
"""
|
||||
import queue
|
||||
import static
|
||||
from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, TCIParam, TNC
|
||||
|
||||
DATA_QUEUE_TRANSMIT = queue.Queue()
|
||||
DATA_QUEUE_RECEIVED = queue.Queue()
|
||||
|
@ -16,7 +17,7 @@ AUDIO_RECEIVED_QUEUE = queue.Queue()
|
|||
AUDIO_TRANSMIT_QUEUE = queue.Queue()
|
||||
|
||||
# Initialize FIFO queue to finally store received data
|
||||
RX_BUFFER = queue.Queue(maxsize=static.RX_BUFFER_SIZE)
|
||||
RX_BUFFER = queue.Queue(maxsize=ARQ.rx_buffer_size)
|
||||
|
||||
# Commands we want to send to rigctld
|
||||
RIGCTLD_COMMAND_QUEUE = queue.Queue()
|
|
@ -10,9 +10,7 @@ import time
|
|||
import structlog
|
||||
import threading
|
||||
import static
|
||||
|
||||
# set global hamlib version
|
||||
hamlib_version = 0
|
||||
from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, TCIParam
|
||||
|
||||
|
||||
class radio:
|
||||
|
@ -243,7 +241,7 @@ class radio:
|
|||
if 'RPRT' not in alc:
|
||||
try:
|
||||
alc = float(alc)
|
||||
self.alc = alc if alc != 0.0 else static.HAMLIB_ALC
|
||||
self.alc = alc if alc != 0.0 else HamlibParam.alc
|
||||
except ValueError:
|
||||
self.alc = 0.0
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@ simple TNC self tests
|
|||
# pylint: disable=import-outside-toplevel, attribute-defined-outside-init
|
||||
import sys
|
||||
import structlog
|
||||
from static import ARQ, Audio, Beacon, Channel, Daemon, Hamlib, Modem, Station, TCI, TNC
|
||||
|
||||
log = structlog.get_logger("selftest")
|
||||
|
||||
|
||||
|
|
197
tnc/sock.py
197
tnc/sock.py
|
@ -27,6 +27,7 @@ import time
|
|||
import wave
|
||||
import helpers
|
||||
import static
|
||||
from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC
|
||||
import structlog
|
||||
from random import randrange
|
||||
import ujson as json
|
||||
|
@ -67,7 +68,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
|||
while self.connection_alive and not CLOSE_SIGNAL:
|
||||
# send tnc state as network stream
|
||||
# check server port against daemon port and send corresponding data
|
||||
if self.server.server_address[1] == static.PORT and not static.TNCSTARTED:
|
||||
if self.server.server_address[1] == TNC.port and not Daemon.tncstarted:
|
||||
data = send_tnc_state()
|
||||
if data != tempdata:
|
||||
tempdata = data
|
||||
|
@ -98,9 +99,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
|||
self.log.debug("[SCK] catch harmless RuntimeError: Set changed size during iteration", e=err)
|
||||
|
||||
# we want to transmit scatter data only once to reduce network traffic
|
||||
static.SCATTER = []
|
||||
# we want to display INFO messages only once
|
||||
static.INFO = []
|
||||
ModemParam.scatter = []
|
||||
# self.request.sendall(sock_data)
|
||||
threading.Event().wait(0.15)
|
||||
|
||||
|
@ -127,7 +126,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
|||
|
||||
# iterate thorugh data list
|
||||
for commands in data:
|
||||
if self.server.server_address[1] == static.PORT:
|
||||
if self.server.server_address[1] == TNC.port:
|
||||
self.process_tnc_commands(commands)
|
||||
else:
|
||||
self.process_daemon_commands(commands)
|
||||
|
@ -354,14 +353,14 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
|||
|
||||
def tnc_set_listen(self, received_json):
|
||||
try:
|
||||
static.LISTEN = received_json["state"] in ['true', 'True', True, "ON", "on"]
|
||||
TNC.listen = received_json["state"] in ['true', 'True', True, "ON", "on"]
|
||||
command_response("listen", True)
|
||||
|
||||
# if tnc is connected, force disconnect when static.LISTEN == False
|
||||
if not static.LISTEN and static.ARQ_SESSION_STATE not in ["disconnecting", "disconnected", "failed"]:
|
||||
# if tnc is connected, force disconnect when TNC.listen == False
|
||||
if not TNC.listen and ARQ.arq_session_state not in ["disconnecting", "disconnected", "failed"]:
|
||||
DATA_QUEUE_TRANSMIT.put(["DISCONNECT"])
|
||||
# set early disconnecting state so we can interrupt connection attempts
|
||||
static.ARQ_SESSION_STATE = "disconnecting"
|
||||
ARQ.arq_session_state = "disconnecting"
|
||||
command_response("disconnect", True)
|
||||
|
||||
except Exception as err:
|
||||
|
@ -372,15 +371,15 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
|||
|
||||
def tnc_set_record_audio(self, received_json):
|
||||
try:
|
||||
if not static.AUDIO_RECORD:
|
||||
static.AUDIO_RECORD_FILE = wave.open(f"{int(time.time())}_audio_recording.wav", 'w')
|
||||
static.AUDIO_RECORD_FILE.setnchannels(1)
|
||||
static.AUDIO_RECORD_FILE.setsampwidth(2)
|
||||
static.AUDIO_RECORD_FILE.setframerate(8000)
|
||||
static.AUDIO_RECORD = True
|
||||
if not AudioParam.audio_record:
|
||||
AudioParam.audio_record_FILE = wave.open(f"{int(time.time())}_audio_recording.wav", 'w')
|
||||
AudioParam.audio_record_FILE.setnchannels(1)
|
||||
AudioParam.audio_record_FILE.setsampwidth(2)
|
||||
AudioParam.audio_record_FILE.setframerate(8000)
|
||||
AudioParam.audio_record = True
|
||||
else:
|
||||
static.AUDIO_RECORD = False
|
||||
static.AUDIO_RECORD_FILE.close()
|
||||
AudioParam.audio_record = False
|
||||
AudioParam.audio_record_FILE.close()
|
||||
|
||||
command_response("respond_to_call", True)
|
||||
|
||||
|
@ -392,7 +391,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
|||
|
||||
def tnc_set_respond_to_call(self, received_json):
|
||||
try:
|
||||
static.RESPOND_TO_CALL = received_json["state"] in ['true', 'True', True]
|
||||
TNC.respond_to_call = received_json["state"] in ['true', 'True', True]
|
||||
command_response("respond_to_call", True)
|
||||
|
||||
except Exception as err:
|
||||
|
@ -403,7 +402,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
|||
|
||||
def tnc_set_respond_to_cq(self, received_json):
|
||||
try:
|
||||
static.RESPOND_TO_CQ = received_json["state"] in ['true', 'True', True]
|
||||
TNC.respond_to_cq = received_json["state"] in ['true', 'True', True]
|
||||
command_response("respond_to_cq", True)
|
||||
|
||||
except Exception as err:
|
||||
|
@ -414,7 +413,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
|||
|
||||
def tnc_set_tx_audio_level(self, received_json):
|
||||
try:
|
||||
static.TX_AUDIO_LEVEL = int(received_json["value"])
|
||||
AudioParam.tx_audio_level = int(received_json["value"])
|
||||
command_response("tx_audio_level", True)
|
||||
|
||||
except Exception as err:
|
||||
|
@ -481,7 +480,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
|||
|
||||
def tnc_start_beacon(self, received_json):
|
||||
try:
|
||||
static.BEACON_STATE = True
|
||||
Beacon.beacon_state = True
|
||||
interval = int(received_json["parameter"])
|
||||
DATA_QUEUE_TRANSMIT.put(["BEACON", interval, True])
|
||||
command_response("start_beacon", True)
|
||||
|
@ -496,7 +495,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
|||
def tnc_stop_beacon(self, received_json):
|
||||
try:
|
||||
log.warning("[SCK] Stopping beacon!")
|
||||
static.BEACON_STATE = False
|
||||
Beacon.beacon_state = False
|
||||
DATA_QUEUE_TRANSMIT.put(["BEACON", None, False])
|
||||
command_response("stop_beacon", True)
|
||||
except Exception as err:
|
||||
|
@ -527,7 +526,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
|||
mycallsign = helpers.bytes_to_callsign(mycallsign)
|
||||
|
||||
except Exception:
|
||||
mycallsign = static.MYCALLSIGN
|
||||
mycallsign = Station.mycallsign
|
||||
|
||||
DATA_QUEUE_TRANSMIT.put(["PING", mycallsign, dxcallsign])
|
||||
command_response("ping", True)
|
||||
|
@ -543,7 +542,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
|||
def tnc_arq_connect(self, received_json):
|
||||
|
||||
# pause our beacon first
|
||||
static.BEACON_PAUSE = True
|
||||
Beacon.beacon_pause = True
|
||||
|
||||
# check for connection attempts key
|
||||
try:
|
||||
|
@ -561,7 +560,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
|||
mycallsign = helpers.bytes_to_callsign(mycallsign)
|
||||
|
||||
except Exception:
|
||||
mycallsign = static.MYCALLSIGN
|
||||
mycallsign = Station.mycallsign
|
||||
|
||||
# additional step for being sure our callsign is correctly
|
||||
# in case we are not getting a station ssid
|
||||
|
@ -569,11 +568,11 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
|||
dxcallsign = helpers.callsign_to_bytes(dxcallsign)
|
||||
dxcallsign = helpers.bytes_to_callsign(dxcallsign)
|
||||
|
||||
if static.ARQ_SESSION_STATE not in ["disconnected", "failed"]:
|
||||
if ARQ.arq_session_state not in ["disconnected", "failed"]:
|
||||
command_response("connect", False)
|
||||
log.warning(
|
||||
"[SCK] Connect command execution error",
|
||||
e=f"already connected to station:{static.DXCALLSIGN}",
|
||||
e=f"already connected to station:{Station.dxcallsign}",
|
||||
command=received_json,
|
||||
)
|
||||
else:
|
||||
|
@ -593,24 +592,24 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
|||
command=received_json,
|
||||
)
|
||||
# allow beacon transmission again
|
||||
static.BEACON_PAUSE = False
|
||||
Beacon.beacon_pause = False
|
||||
|
||||
# allow beacon transmission again
|
||||
static.BEACON_PAUSE = False
|
||||
Beacon.beacon_pause = False
|
||||
|
||||
def tnc_arq_disconnect(self, received_json):
|
||||
try:
|
||||
if static.ARQ_SESSION_STATE not in ["disconnecting", "disconnected", "failed"]:
|
||||
if ARQ.arq_session_state not in ["disconnecting", "disconnected", "failed"]:
|
||||
DATA_QUEUE_TRANSMIT.put(["DISCONNECT"])
|
||||
|
||||
# set early disconnecting state so we can interrupt connection attempts
|
||||
static.ARQ_SESSION_STATE = "disconnecting"
|
||||
ARQ.arq_session_state = "disconnecting"
|
||||
command_response("disconnect", True)
|
||||
else:
|
||||
command_response("disconnect", False)
|
||||
log.warning(
|
||||
"[SCK] Disconnect command not possible",
|
||||
state=static.ARQ_SESSION_STATE,
|
||||
state=ARQ.arq_session_state,
|
||||
command=received_json,
|
||||
)
|
||||
except Exception as err:
|
||||
|
@ -622,13 +621,13 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
|||
)
|
||||
|
||||
def tnc_arq_send_raw(self, received_json):
|
||||
static.BEACON_PAUSE = True
|
||||
Beacon.beacon_pause = True
|
||||
|
||||
# wait some random time
|
||||
helpers.wait(randrange(5, 25, 5) / 10.0)
|
||||
|
||||
# we need to warn if already in arq state
|
||||
if static.ARQ_STATE:
|
||||
if ARQ.arq_state:
|
||||
command_response("send_raw", False)
|
||||
log.warning(
|
||||
"[SCK] Send raw command execution warning",
|
||||
|
@ -638,19 +637,19 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
|||
)
|
||||
|
||||
try:
|
||||
if not static.ARQ_SESSION:
|
||||
if not ARQ.arq_session:
|
||||
dxcallsign = received_json["parameter"][0]["dxcallsign"]
|
||||
# additional step for being sure our callsign is correctly
|
||||
# in case we are not getting a station ssid
|
||||
# then we are forcing a station ssid = 0
|
||||
dxcallsign = helpers.callsign_to_bytes(dxcallsign)
|
||||
dxcallsign = helpers.bytes_to_callsign(dxcallsign)
|
||||
static.DXCALLSIGN = dxcallsign
|
||||
static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN)
|
||||
Station.dxcallsign = dxcallsign
|
||||
Station.dxcallsign_crc = helpers.get_crc_24(Station.dxcallsign)
|
||||
command_response("send_raw", True)
|
||||
else:
|
||||
dxcallsign = static.DXCALLSIGN
|
||||
static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN)
|
||||
dxcallsign = Station.dxcallsign
|
||||
Station.dxcallsign_crc = helpers.get_crc_24(Station.dxcallsign)
|
||||
|
||||
mode = int(received_json["parameter"][0]["mode"])
|
||||
n_frames = int(received_json["parameter"][0]["n_frames"])
|
||||
|
@ -663,7 +662,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
|||
mycallsign = helpers.bytes_to_callsign(mycallsign)
|
||||
|
||||
except Exception:
|
||||
mycallsign = static.MYCALLSIGN
|
||||
mycallsign = Station.mycallsign
|
||||
|
||||
# check for connection attempts key
|
||||
try:
|
||||
|
@ -697,11 +696,11 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
|||
|
||||
def tnc_arq_stop_transmission(self, received_json):
|
||||
try:
|
||||
if static.TNC_STATE == "BUSY" or static.ARQ_STATE:
|
||||
if TNC.tnc_state == "BUSY" or ARQ.arq_state:
|
||||
DATA_QUEUE_TRANSMIT.put(["STOP"])
|
||||
log.warning("[SCK] Stopping transmission!")
|
||||
static.TNC_STATE = "IDLE"
|
||||
static.ARQ_STATE = False
|
||||
TNC.tnc_state = "IDLE"
|
||||
ARQ.arq_state = False
|
||||
command_response("stop_transmission", True)
|
||||
except Exception as err:
|
||||
command_response("stop_transmission", False)
|
||||
|
@ -803,7 +802,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
|||
if (
|
||||
received_json["type"] == "set"
|
||||
and received_json["command"] == "start_tnc"
|
||||
and not static.TNCSTARTED
|
||||
and not Daemon.tncstarted
|
||||
):
|
||||
self.daemon_start_tnc(received_json)
|
||||
|
||||
|
@ -821,18 +820,18 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
|||
self.request.sendall(b"INVALID CALLSIGN")
|
||||
log.warning(
|
||||
"[SCK] SET MYCALL FAILED",
|
||||
call=static.MYCALLSIGN,
|
||||
crc=static.MYCALLSIGN_CRC.hex(),
|
||||
call=Station.mycallsign,
|
||||
crc=Station.mycallsign_crc.hex(),
|
||||
)
|
||||
else:
|
||||
static.MYCALLSIGN = bytes(callsign, "utf-8")
|
||||
static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN)
|
||||
Station.mycallsign = bytes(callsign, "utf-8")
|
||||
Station.mycallsign_crc = helpers.get_crc_24(Station.mycallsign)
|
||||
|
||||
command_response("mycallsign", True)
|
||||
log.info(
|
||||
"[SCK] SET MYCALL",
|
||||
call=static.MYCALLSIGN,
|
||||
crc=static.MYCALLSIGN_CRC.hex(),
|
||||
call=Station.mycallsign,
|
||||
crc=Station.mycallsign_crc.hex(),
|
||||
)
|
||||
except Exception as err:
|
||||
command_response("mycallsign", False)
|
||||
|
@ -846,8 +845,8 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
|||
self.request.sendall(b"INVALID GRID")
|
||||
command_response("mygrid", False)
|
||||
else:
|
||||
static.MYGRID = bytes(mygrid, "utf-8")
|
||||
log.info("[SCK] SET MYGRID", grid=static.MYGRID)
|
||||
Station.mygrid = bytes(mygrid, "utf-8")
|
||||
log.info("[SCK] SET MYGRID", grid=Station.mygrid)
|
||||
command_response("mygrid", True)
|
||||
except Exception as err:
|
||||
command_response("mygrid", False)
|
||||
|
@ -928,12 +927,12 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
|||
|
||||
def daemon_stop_tnc(self, received_json):
|
||||
try:
|
||||
static.TNCPROCESS.kill()
|
||||
Daemon.tncprocess.kill()
|
||||
# unregister process from atexit to avoid process zombies
|
||||
atexit.unregister(static.TNCPROCESS.kill)
|
||||
atexit.unregister(Daemon.tncprocess.kill)
|
||||
|
||||
log.warning("[SCK] Stopping TNC")
|
||||
static.TNCSTARTED = False
|
||||
Daemon.tncstarted = False
|
||||
command_response("stop_tnc", True)
|
||||
except Exception as err:
|
||||
command_response("stop_tnc", False)
|
||||
|
@ -972,15 +971,15 @@ def send_daemon_state():
|
|||
"command": "daemon_state",
|
||||
"daemon_state": [],
|
||||
"python_version": str(python_version),
|
||||
"input_devices": static.AUDIO_INPUT_DEVICES,
|
||||
"output_devices": static.AUDIO_OUTPUT_DEVICES,
|
||||
"serial_devices": static.SERIAL_DEVICES,
|
||||
"input_devices": AudioParam.audio_input_devices,
|
||||
"output_devices": AudioParam.audio_output_devices,
|
||||
"serial_devices": Daemon.serial_devices,
|
||||
# 'cpu': str(psutil.cpu_percent()),
|
||||
# 'ram': str(psutil.virtual_memory().percent),
|
||||
"version": "0.1",
|
||||
}
|
||||
|
||||
if static.TNCSTARTED:
|
||||
if Daemon.tncstarted:
|
||||
output["daemon_state"].append({"status": "running"})
|
||||
else:
|
||||
output["daemon_state"].append({"status": "stopped"})
|
||||
|
@ -996,55 +995,55 @@ def send_tnc_state():
|
|||
send the tnc state to network
|
||||
"""
|
||||
encoding = "utf-8"
|
||||
|
||||
output = {
|
||||
"command": "tnc_state",
|
||||
"ptt_state": str(static.PTT_STATE),
|
||||
"tnc_state": str(static.TNC_STATE),
|
||||
"arq_state": str(static.ARQ_STATE),
|
||||
"arq_session": str(static.ARQ_SESSION),
|
||||
"arq_session_state": str(static.ARQ_SESSION_STATE),
|
||||
"audio_dbfs": str(static.AUDIO_DBFS),
|
||||
"snr": str(static.SNR),
|
||||
"frequency": str(static.HAMLIB_FREQUENCY),
|
||||
"rf_level": str(static.HAMLIB_RF),
|
||||
"strength": str(static.HAMLIB_STRENGTH),
|
||||
"alc": str(static.HAMLIB_ALC),
|
||||
"audio_level": str(static.TX_AUDIO_LEVEL),
|
||||
"audio_auto_tune": str(static.AUDIO_AUTO_TUNE),
|
||||
"speed_level": str(static.ARQ_SPEED_LEVEL),
|
||||
"mode": str(static.HAMLIB_MODE),
|
||||
"bandwidth": str(static.HAMLIB_BANDWIDTH),
|
||||
"fft": str(static.FFT),
|
||||
"channel_busy": str(static.CHANNEL_BUSY),
|
||||
"is_codec2_traffic": str(static.IS_CODEC2_TRAFFIC),
|
||||
"scatter": static.SCATTER,
|
||||
"ptt_state": str(HamlibParam.ptt_state),
|
||||
"tnc_state": str(TNC.tnc_state),
|
||||
"arq_state": str(ARQ.arq_state),
|
||||
"arq_session": str(ARQ.arq_session),
|
||||
"arq_session_state": str(ARQ.arq_session_state),
|
||||
"audio_dbfs": str(AudioParam.audio_dbfs),
|
||||
"snr": str(ModemParam.snr),
|
||||
"frequency": str(HamlibParam.hamlib_frequency),
|
||||
"rf_level": str(HamlibParam.hamlib_rf),
|
||||
"strength": str(HamlibParam.hamlib_strength),
|
||||
"alc": str(HamlibParam.alc),
|
||||
"audio_level": str(AudioParam.tx_audio_level),
|
||||
"audio_auto_tune": str(AudioParam.audio_auto_tune),
|
||||
"speed_level": str(ARQ.arq_speed_level),
|
||||
"mode": str(HamlibParam.hamlib_mode),
|
||||
"bandwidth": str(HamlibParam.hamlib_bandwidth),
|
||||
"fft": str(AudioParam.fft),
|
||||
"channel_busy": str(ModemParam.channel_busy),
|
||||
"channel_busy_slot": str(ModemParam.channel_busy_slot),
|
||||
"is_codec2_traffic": str(ModemParam.is_codec2_traffic),
|
||||
"scatter": ModemParam.scatter,
|
||||
"rx_buffer_length": str(RX_BUFFER.qsize()),
|
||||
"rx_msg_buffer_length": str(len(static.RX_MSG_BUFFER)),
|
||||
"arq_bytes_per_minute": str(static.ARQ_BYTES_PER_MINUTE),
|
||||
"arq_bytes_per_minute_burst": str(static.ARQ_BYTES_PER_MINUTE_BURST),
|
||||
"arq_seconds_until_finish": str(static.ARQ_SECONDS_UNTIL_FINISH),
|
||||
"arq_compression_factor": str(static.ARQ_COMPRESSION_FACTOR),
|
||||
"arq_transmission_percent": str(static.ARQ_TRANSMISSION_PERCENT),
|
||||
"speed_list": static.SPEED_LIST,
|
||||
"total_bytes": str(static.TOTAL_BYTES),
|
||||
"beacon_state": str(static.BEACON_STATE),
|
||||
"rx_msg_buffer_length": str(len(ARQ.rx_msg_buffer)),
|
||||
"arq_bytes_per_minute": str(ARQ.bytes_per_minute),
|
||||
"arq_bytes_per_minute_burst": str(ARQ.bytes_per_minute_burst),
|
||||
"arq_seconds_until_finish": str(ARQ.arq_seconds_until_finish),
|
||||
"arq_compression_factor": str(ARQ.arq_compression_factor),
|
||||
"arq_transmission_percent": str(ARQ.arq_transmission_percent),
|
||||
"speed_list": ARQ.speed_list,
|
||||
"total_bytes": str(ARQ.total_bytes),
|
||||
"beacon_state": str(Beacon.beacon_state),
|
||||
"stations": [],
|
||||
"mycallsign": str(static.MYCALLSIGN, encoding),
|
||||
"mygrid": str(static.MYGRID, encoding),
|
||||
"dxcallsign": str(static.DXCALLSIGN, encoding),
|
||||
"dxgrid": str(static.DXGRID, encoding),
|
||||
"hamlib_status": static.HAMLIB_STATUS,
|
||||
"listen": str(static.LISTEN),
|
||||
"audio_recording": str(static.AUDIO_RECORD),
|
||||
"mycallsign": str(Station.mycallsign, encoding),
|
||||
"mygrid": str(Station.mygrid, encoding),
|
||||
"dxcallsign": str(Station.dxcallsign, encoding),
|
||||
"dxgrid": str(Station.dxgrid, encoding),
|
||||
"hamlib_status": HamlibParam.hamlib_status,
|
||||
"listen": str(TNC.listen),
|
||||
"audio_recording": str(AudioParam.audio_record),
|
||||
}
|
||||
|
||||
# add heard stations to heard stations object
|
||||
for heard in static.HEARD_STATIONS:
|
||||
for heard in TNC.heard_stations:
|
||||
output["stations"].append(
|
||||
{
|
||||
"dxcallsign": str(heard[0], "utf-8"),
|
||||
"dxgrid": str(heard[1], "utf-8"),
|
||||
"dxcallsign": str(heard[0], encoding),
|
||||
"dxgrid": str(heard[1], encoding),
|
||||
"timestamp": heard[2],
|
||||
"datatype": heard[3],
|
||||
"snr": heard[4],
|
||||
|
|
216
tnc/static.py
216
tnc/static.py
|
@ -5,13 +5,188 @@ Created on Wed Dec 23 11:13:57 2020
|
|||
|
||||
@author: DJ2LS
|
||||
Here we are saving application wide variables and stats, which have to be accessed everywhere.
|
||||
Not nice, suggestions are appreciated :-)
|
||||
"""
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List
|
||||
import subprocess
|
||||
from enum import Enum
|
||||
|
||||
VERSION = "0.8.1-alpha"
|
||||
|
||||
# CHANNEL_STATE = 'RECEIVING_SIGNALLING'
|
||||
# disconnected, connecting, connected, disconnecting, failed
|
||||
# ------- RX BUFFER
|
||||
|
||||
@dataclass
|
||||
class ARQ:
|
||||
bytes_per_minute: int = 0
|
||||
arq_transmission_percent: int = 0
|
||||
arq_compression_factor: int = 0
|
||||
arq_speed_level: int = 0
|
||||
arq_bits_per_second_burst: int = 0
|
||||
arq_bits_per_second: int = 0
|
||||
arq_seconds_until_finish: int = 0
|
||||
rx_buffer_size: int = 16
|
||||
rx_frame_buffer: bytes = b""
|
||||
rx_burst_buffer =[]
|
||||
arq_session_state: str = "disconnected"
|
||||
arq_session: bool = False
|
||||
arq_state: bool = False
|
||||
# ARQ PROTOCOL VERSION
|
||||
# v.5 - signalling frame uses datac0
|
||||
# v.6 - signalling frame uses datac13
|
||||
arq_protocol_version: int = 6
|
||||
total_bytes: int = 0
|
||||
speed_list = []
|
||||
# set save to folder state for allowing downloading files to local file system
|
||||
arq_save_to_folder: bool = False
|
||||
bytes_per_minute_burst: int = 0
|
||||
rx_msg_buffer = []
|
||||
|
||||
|
||||
@dataclass
|
||||
class AudioParam:
|
||||
tx_audio_level: int = 50
|
||||
audio_input_devices = []
|
||||
audio_output_devices = []
|
||||
audio_input_device: int = -2
|
||||
audio_output_device: int = -2
|
||||
audio_record: bool = False
|
||||
audio_record_file = ''
|
||||
buffer_overflow_counter = []
|
||||
audio_auto_tune: bool = False
|
||||
# Audio TCI Support
|
||||
audio_enable_tci: bool = False
|
||||
audio_dbfs: int = 0
|
||||
fft = []
|
||||
enable_fft: bool = True
|
||||
|
||||
|
||||
@dataclass
|
||||
class Beacon:
|
||||
beacon_state: bool = False
|
||||
beacon_pause: bool = False
|
||||
|
||||
@dataclass
|
||||
class Channel:
|
||||
pass
|
||||
|
||||
@dataclass
|
||||
class Daemon:
|
||||
tncprocess: subprocess.Popen
|
||||
tncstarted: bool = False
|
||||
port: int = 3001
|
||||
serial_devices = []
|
||||
|
||||
@dataclass
|
||||
class HamlibParam:
|
||||
alc: int = 0
|
||||
hamlib_frequency: int = 0
|
||||
hamlib_strength: int = 0
|
||||
hamlib_radiocontrol: str = "disabled"
|
||||
hamlib_rigctld_ip: str = "127.0.0.1"
|
||||
hamlib_rigctld_port: str = "4532"
|
||||
ptt_state: bool = False
|
||||
hamlib_bandwidth: int = 0
|
||||
hamlib_status: str = "unknown/disconnected"
|
||||
hamlib_mode: str = ""
|
||||
hamlib_rf: int = 0
|
||||
|
||||
@dataclass
|
||||
class ModemParam:
|
||||
tuning_range_fmin: float = -50.0
|
||||
tuning_range_fmax: float = 50.0
|
||||
channel_busy: bool = False
|
||||
channel_busy_slot = [False] * 5
|
||||
snr: float = 0
|
||||
is_codec2_traffic: bool = False # true if we have codec2 signalling mode traffic on channel
|
||||
frequency_offset: float = 0
|
||||
tx_delay: int = 0 # delay in ms before sending modulation for triggering VOX for example or slow PTT radios
|
||||
enable_scatter: bool = False
|
||||
scatter = []
|
||||
|
||||
@dataclass
|
||||
class Station:
|
||||
mycallsign: bytes = b"AA0AA"
|
||||
mycallsign_crc: bytes = b"A"
|
||||
dxcallsign: bytes = b"ZZ9YY"
|
||||
dxcallsign_crc: bytes = b"A"
|
||||
mygrid: bytes = b""
|
||||
dxgrid: bytes = b""
|
||||
ssid_list = [] # ssid list we are responding to
|
||||
|
||||
|
||||
@dataclass
|
||||
class Statistics:
|
||||
pass
|
||||
|
||||
@dataclass
|
||||
class TCIParam:
|
||||
ip: str = '127.0.0.1'
|
||||
port: int = '9000'
|
||||
|
||||
@dataclass
|
||||
class TNC:
|
||||
version = "0.9.0-alpha-exp.6"
|
||||
host: str = "0.0.0.0"
|
||||
port: int = 3000
|
||||
SOCKET_TIMEOUT: int = 1 # seconds
|
||||
tnc_state: str = "IDLE"
|
||||
enable_explorer = False
|
||||
enable_stats = False
|
||||
transmitting: bool = False
|
||||
low_bandwidth_mode: bool = False
|
||||
enable_fsk: bool = False
|
||||
respond_to_cq: bool = True
|
||||
respond_to_call: bool = True # respond to cq, ping, connection request, file request if not in session
|
||||
heard_stations = []
|
||||
listen: bool = True
|
||||
|
||||
# ------------
|
||||
|
||||
|
||||
class FRAME_TYPE(Enum):
|
||||
"""Lookup for frame types"""
|
||||
|
||||
BURST_01 = 10
|
||||
BURST_02 = 11
|
||||
BURST_03 = 12
|
||||
BURST_04 = 13
|
||||
# ...
|
||||
BURST_51 = 50
|
||||
BURST_ACK = 60
|
||||
FR_ACK = 61
|
||||
FR_REPEAT = 62
|
||||
FR_NACK = 63
|
||||
BURST_NACK = 64
|
||||
CQ = 200
|
||||
QRV = 201
|
||||
PING = 210
|
||||
PING_ACK = 211
|
||||
IS_WRITING = 215
|
||||
ARQ_SESSION_OPEN = 221
|
||||
ARQ_SESSION_HB = 222
|
||||
ARQ_SESSION_CLOSE = 223
|
||||
ARQ_DC_OPEN_W = 225
|
||||
ARQ_DC_OPEN_ACK_W = 226
|
||||
ARQ_DC_OPEN_N = 227
|
||||
ARQ_DC_OPEN_ACK_N = 228
|
||||
ARQ_STOP = 249
|
||||
BEACON = 250
|
||||
FEC = 251
|
||||
IDENT = 254
|
||||
TEST_FRAME = 255
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# DON'T USE THESE SETTINGS ANYMORE
|
||||
# ---------------------------------------------------------------
|
||||
# Fixme: REMOVE THESE OLD SETTINGS!
|
||||
# REASON: For some reason ctests are failing when using dataclasses.
|
||||
# We need to figure out whats happening and why the tests are failing.
|
||||
|
||||
|
||||
CHANNEL_BUSY_SLOT = [False] * 5
|
||||
|
||||
|
||||
ENABLE_EXPLORER = False
|
||||
ENABLE_STATS = False
|
||||
|
@ -87,15 +262,15 @@ AUDIO_ENABLE_TCI: bool = False
|
|||
TCI_IP: str = '127.0.0.1'
|
||||
TCI_PORT: int = '9000'
|
||||
|
||||
|
||||
|
||||
AUDIO_DBFS: int = 0
|
||||
FFT: list = [0]
|
||||
ENABLE_FFT: bool = True
|
||||
CHANNEL_BUSY: bool = False
|
||||
|
||||
# ARQ PROTOCOL VERSION
|
||||
ARQ_PROTOCOL_VERSION: int = 5
|
||||
# v.5 - signalling frame uses datac0
|
||||
# v.6 - signalling frame uses datac13
|
||||
ARQ_PROTOCOL_VERSION: int = 6
|
||||
|
||||
# ARQ statistics
|
||||
SPEED_LIST: list = []
|
||||
|
@ -138,33 +313,4 @@ INFO: list = []
|
|||
# ------- CODEC2 SETTINGS
|
||||
TUNING_RANGE_FMIN: float = -50.0
|
||||
TUNING_RANGE_FMAX: float = 50.0
|
||||
IS_CODEC2_TRAFFIC: bool = False # true if we have codec2 signalling mode traffic on channel
|
||||
|
||||
class FRAME_TYPE(Enum):
|
||||
"""Lookup for frame types"""
|
||||
|
||||
BURST_01 = 10
|
||||
# ...
|
||||
BURST_51 = 50
|
||||
BURST_ACK = 60
|
||||
FR_ACK = 61
|
||||
FR_REPEAT = 62
|
||||
FR_NACK = 63
|
||||
BURST_NACK = 64
|
||||
CQ = 200
|
||||
QRV = 201
|
||||
PING = 210
|
||||
PING_ACK = 211
|
||||
IS_WRITING = 215
|
||||
ARQ_SESSION_OPEN = 221
|
||||
ARQ_SESSION_HB = 222
|
||||
ARQ_SESSION_CLOSE = 223
|
||||
ARQ_DC_OPEN_W = 225
|
||||
ARQ_DC_OPEN_ACK_W = 226
|
||||
ARQ_DC_OPEN_N = 227
|
||||
ARQ_DC_OPEN_ACK_N = 228
|
||||
ARQ_STOP = 249
|
||||
BEACON = 250
|
||||
FEC = 251
|
||||
IDENT = 254
|
||||
TEST_FRAME = 255
|
||||
IS_CODEC2_TRAFFIC: bool = False # true if we have codec2 signalling mode traffic on channel
|
||||
|
|
23
tnc/stats.py
23
tnc/stats.py
|
@ -13,6 +13,7 @@ import time
|
|||
import ujson as json
|
||||
import structlog
|
||||
import static
|
||||
from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, TCIParam, TNC
|
||||
|
||||
log = structlog.get_logger("stats")
|
||||
|
||||
|
@ -25,29 +26,29 @@ class stats():
|
|||
crcerror = status in ["crc_error", "wrong_crc"]
|
||||
# get avg snr
|
||||
try:
|
||||
snr_raw = [item["snr"] for item in static.SPEED_LIST]
|
||||
snr_raw = [item["snr"] for item in ARQ.speed_list]
|
||||
avg_snr = round(sum(snr_raw) / len(snr_raw), 2 )
|
||||
except Exception:
|
||||
avg_snr = 0
|
||||
|
||||
headers = {"Content-Type": "application/json"}
|
||||
station_data = {
|
||||
'callsign': str(static.MYCALLSIGN, "utf-8"),
|
||||
'dxcallsign': str(static.DXCALLSIGN, "utf-8"),
|
||||
'gridsquare': str(static.MYGRID, "utf-8"),
|
||||
'dxgridsquare': str(static.DXGRID, "utf-8"),
|
||||
'frequency': 0 if static.HAMLIB_FREQUENCY is None else static.HAMLIB_FREQUENCY,
|
||||
'callsign': str(Station.mycallsign, "utf-8"),
|
||||
'dxcallsign': str(Station.dxcallsign, "utf-8"),
|
||||
'gridsquare': str(Station.mygrid, "utf-8"),
|
||||
'dxgridsquare': str(Station.dxgrid, "utf-8"),
|
||||
'frequency': 0 if HamlibParam.hamlib_frequency is None else HamlibParam.hamlib_frequency,
|
||||
'avgstrength': 0,
|
||||
'avgsnr': avg_snr,
|
||||
'bytesperminute': static.ARQ_BYTES_PER_MINUTE,
|
||||
'filesize': static.TOTAL_BYTES,
|
||||
'compressionfactor': static.ARQ_COMPRESSION_FACTOR,
|
||||
'bytesperminute': ARQ.bytes_per_minute,
|
||||
'filesize': ARQ.total_bytes,
|
||||
'compressionfactor': ARQ.arq_compression_factor,
|
||||
'nacks': frame_nack_counter,
|
||||
'crcerror': crcerror,
|
||||
'duration': duration,
|
||||
'percentage': static.ARQ_TRANSMISSION_PERCENT,
|
||||
'percentage': ARQ.arq_transmission_percent,
|
||||
'status': status,
|
||||
'version': static.VERSION
|
||||
'version': TNC.version
|
||||
}
|
||||
|
||||
station_data = json.dumps(station_data)
|
||||
|
|
|
@ -7,8 +7,9 @@ import websocket
|
|||
import numpy as np
|
||||
import time
|
||||
from queues import AUDIO_TRANSMIT_QUEUE, AUDIO_RECEIVED_QUEUE
|
||||
from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, TCIParam, TNC
|
||||
|
||||
class TCI:
|
||||
class TCICtrl:
|
||||
def __init__(self, hostname='127.0.0.1', port=50001):
|
||||
# websocket.enableTrace(True)
|
||||
self.log = structlog.get_logger("TCI")
|
||||
|
|
Loading…
Reference in a new issue