updated dataclasses

This commit is contained in:
DJ2LS 2023-04-27 21:43:56 +02:00
parent d2c5c934d5
commit 69749d30ae
18 changed files with 988 additions and 1038 deletions

View file

@ -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)

View file

@ -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

View file

@ -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))

View file

@ -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))

View file

@ -21,9 +21,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(
@ -46,21 +46,21 @@ 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")
Station.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()
@ -149,8 +149,8 @@ def t_datac13_1(
time.sleep(0.5)
if "stop" in data["command"]:
log.debug("t_datac13_1: STOP test, setting TNC state")
static.TNC_STATE = "BUSY"
static.ARQ_STATE = True
TNC.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))
@ -169,7 +169,7 @@ def t_datac13_1(
time.sleep(0.1)
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)

View file

@ -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,21 +40,21 @@ 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")
Station.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()
@ -140,18 +140,18 @@ def t_datac13_1(
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_datac13_1: STOP test, setting TNC state",
mycall=static.MYCALLSIGN,
dxcall=static.DXCALLSIGN,
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,10 +172,10 @@ def t_datac13_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)
@ -266,7 +266,7 @@ def t_datac13_2(
log.info("t_datac13_2:", RXCHANNEL=modem.RXCHANNEL)
log.info("t_datac13_2:", TXCHANNEL=modem.TXCHANNEL)
log.info("t_datac13_2:", mycall=static.MYCALLSIGN)
log.info("t_datac13_2:", mycall=Station.mycallsign)
if "cq" in data:
t_data = {"type": "arq", "command": "stop_transmission"}

View file

@ -26,8 +26,7 @@ import crcengine
import log_handler
import serial.tools.list_ports
import sock
import static
from static import ARQ, Audio, Beacon, Channel, Daemon, Hamlib, Modem, Station, TCI, TNC
from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC
import structlog
import ujson as json
@ -84,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(
@ -114,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(
@ -319,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
@ -369,7 +368,7 @@ if __name__ == "__main__":
# https://stackoverflow.com/a/16641793
socketserver.TCPServer.allow_reuse_address = True
cmdserver = sock.ThreadedTCPServer(
(static.HOST, DAEMON.port), sock.ThreadedTCPRequestHandler
(TNC.host, DAEMON.port), sock.ThreadedTCPRequestHandler
)
server_thread = threading.Thread(target=cmdserver.serve_forever)
server_thread.daemon = True

File diff suppressed because it is too large Load diff

View file

@ -13,7 +13,7 @@ import time
import ujson as json
import structlog
import static
from static import ARQ, Audio, Beacon, Channel, Daemon, Hamlib, Modem, Station, TCI, TNC
from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC
log = structlog.get_logger("explorer")
@ -34,21 +34,21 @@ 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.mycall, "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")

View file

@ -8,7 +8,7 @@ import time
from datetime import datetime,timezone
import crcengine
import static
from static import ARQ, Audio, Beacon, Channel, Daemon, Hamlib, Modem, Station, TCI, TNC
from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC
import structlog
import numpy as np
import threading
@ -131,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()),
@ -151,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,
@ -166,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:
@ -306,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"))

View file

@ -29,7 +29,7 @@ import helpers
import log_handler
import modem
import static
from static import ARQ, Audio, Beacon, Channel, Daemon, Hamlib, Modem, Station, TCI, TNC
from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC
import structlog
import explorer
import json
@ -256,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:
@ -267,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
TNC.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
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)
@ -321,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')
TNC.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'))
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
@ -405,8 +405,8 @@ 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

View file

@ -23,7 +23,7 @@ import numpy as np
import sock
import sounddevice as sd
import static
from static import ARQ, Audio, Beacon, Channel, Daemon, Hamlib, Modem, Station, TCI, TNC
from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC
from static import FRAME_TYPE
import structlog
import ujson as json
@ -35,7 +35,7 @@ TESTMODE = False
RXCHANNEL = ""
TXCHANNEL = ""
static.TRANSMITTING = False
TNC.transmitting = False
# Receive only specific modes to reduce CPU load
RECEIVE_SIG0 = True
@ -73,7 +73,7 @@ class RF:
self.AUDIO_FRAMES_PER_BUFFER_RX = 2400 * 2 # 8192
# 8192 Let's do some tests with very small chunks for TX
self.AUDIO_FRAMES_PER_BUFFER_TX = 1200 if static.AUDIO_ENABLE_TCI else 2400 * 2
self.AUDIO_FRAMES_PER_BUFFER_TX = 1200 if AudioParam.audio_enable_tci else 2400 * 2
# 8 * (self.AUDIO_SAMPLE_RATE_RX/self.MODEM_SAMPLE_RATE) == 48
self.AUDIO_CHANNELS = 1
self.MODE = 0
@ -178,13 +178,13 @@ class RF:
self.freedv_ldpc1_tx = open_codec2_instance(codec2.FREEDV_MODE.fsk_ldpc_1.value)
# --------------------------------------------CREATE PORTAUDIO INSTANCE
if not TESTMODE and not static.AUDIO_ENABLE_TCI:
if not TESTMODE and not AudioParam.audio_enable_tci:
try:
self.stream = sd.RawStream(
channels=1,
dtype="int16",
callback=self.callback,
device=(static.AUDIO_INPUT_DEVICE, static.AUDIO_OUTPUT_DEVICE),
device=(AudioParam.audio_input_device, AudioParam.audio_output_device),
samplerate=self.AUDIO_SAMPLE_RATE_RX,
blocksize=4800,
)
@ -204,7 +204,7 @@ class RF:
elif not TESTMODE:
# placeholder area for processing audio via TCI
# https://github.com/maksimus1210/TCI
self.log.warning("[MDM] [TCI] Not yet fully implemented", ip=static.TCI_IP, port=static.TCI_PORT)
self.log.warning("[MDM] [TCI] Not yet fully implemented", ip=TCIParam.tci_ip, port=TCIParam.tci_port)
# we are trying this by simulating an audio stream Object like with mkfifo
class Object:
@ -214,7 +214,7 @@ class RF:
self.stream = Object()
# lets init TCI module
self.tci_module = tci.TCI()
self.tci_module = tci.TCICtrl()
tci_rx_callback_thread = threading.Thread(
target=self.tci_rx_callback,
@ -264,28 +264,28 @@ class RF:
# --------------------------------------------INIT AND OPEN HAMLIB
# Check how we want to control the radio
if static.HAMLIB_RADIOCONTROL == "rigctld":
if HamlibParam.hamlib_radiocontrol == "rigctld":
import rigctld as rig
elif static.AUDIO_ENABLE_TCI:
elif AudioParam.audio_enable_tci:
self.radio = self.tci_module
else:
import rigdummy as rig
if not static.AUDIO_ENABLE_TCI:
if not AudioParam.audio_enable_tci:
self.radio = rig.radio()
self.radio.open_rig(
rigctld_ip=static.HAMLIB_RIGCTLD_IP,
rigctld_port=static.HAMLIB_RIGCTLD_PORT,
rigctld_ip=HamlibParam.hamlib_rigctld_ip,
rigctld_port=HamlibParam.hamlib_rigctld_port,
)
# --------------------------------------------START DECODER THREAD
if static.ENABLE_FFT:
if AudioParam.enable_fft:
fft_thread = threading.Thread(
target=self.calculate_fft, name="FFT_THREAD", daemon=True
)
fft_thread.start()
if static.ENABLE_FSK:
if TNC.enable_fsk:
audio_thread_fsk_ldpc0 = threading.Thread(
target=self.audio_fsk_ldpc_0, name="AUDIO_THREAD FSK LDPC0", daemon=True
)
@ -352,7 +352,7 @@ class RF:
threading.Event().wait(0.01)
if len(self.modoutqueue) > 0 and not self.mod_out_locked:
static.PTT_STATE = self.radio.set_ptt(True)
HamlibParam.ptt_state = self.radio.set_ptt(True)
jsondata = {"ptt": "True"}
data_out = json.dumps(jsondata)
sock.SOCKET_QUEUE.put(data_out)
@ -384,8 +384,8 @@ class RF:
(self.dat0_datac1_buffer, RECEIVE_DATAC1),
(self.dat0_datac3_buffer, RECEIVE_DATAC3),
(self.dat0_datac4_buffer, RECEIVE_DATAC4),
(self.fsk_ldpc_buffer_0, static.ENABLE_FSK),
(self.fsk_ldpc_buffer_1, static.ENABLE_FSK),
(self.fsk_ldpc_buffer_0, TNC.enable_fsk),
(self.fsk_ldpc_buffer_1, TNC.enable_fsk),
]:
if (
not (data_buffer.nbuffer + length_x) > data_buffer.size
@ -418,8 +418,8 @@ class RF:
(self.dat0_datac1_buffer, RECEIVE_DATAC1),
(self.dat0_datac3_buffer, RECEIVE_DATAC3),
(self.dat0_datac4_buffer, RECEIVE_DATAC4),
(self.fsk_ldpc_buffer_0, static.ENABLE_FSK),
(self.fsk_ldpc_buffer_1, static.ENABLE_FSK),
(self.fsk_ldpc_buffer_0, TNC.enable_fsk),
(self.fsk_ldpc_buffer_1, TNC.enable_fsk),
]:
if (
not (data_buffer.nbuffer + length_x) > data_buffer.size
@ -460,13 +460,13 @@ class RF:
x = self.resampler.resample48_to_8(x)
# audio recording for debugging purposes
if static.AUDIO_RECORD:
# static.AUDIO_RECORD_FILE.write(x)
static.AUDIO_RECORD_FILE.writeframes(x)
if AudioParam.audio_record:
# AudioParam.audio_record_file.write(x)
AudioParam.audio_record_file.writeframes(x)
# Avoid decoding when transmitting to reduce CPU
# TODO: Overriding this for testing purposes
# if not static.TRANSMITTING:
# if not TNC.transmitting:
length_x = len(x)
# Avoid buffer overflow by filling only if buffer for
# selected datachannel mode is not full
@ -476,23 +476,23 @@ class RF:
(self.dat0_datac1_buffer, RECEIVE_DATAC1, 2),
(self.dat0_datac3_buffer, RECEIVE_DATAC3, 3),
(self.dat0_datac4_buffer, RECEIVE_DATAC4, 4),
(self.fsk_ldpc_buffer_0, static.ENABLE_FSK, 5),
(self.fsk_ldpc_buffer_1, static.ENABLE_FSK, 6),
(self.fsk_ldpc_buffer_0, TNC.enable_fsk, 5),
(self.fsk_ldpc_buffer_1, TNC.enable_fsk, 6),
]:
if (audiobuffer.nbuffer + length_x) > audiobuffer.size:
static.BUFFER_OVERFLOW_COUNTER[index] += 1
AudioParam.buffer_overflow_counter[index] += 1
elif receive:
audiobuffer.push(x)
# end of "not static.TRANSMITTING" if block
# end of "not TNC.transmitting" if block
if not self.modoutqueue or self.mod_out_locked:
data_out48k = np.zeros(frames, dtype=np.int16)
self.fft_data = x
else:
if not static.PTT_STATE:
if not HamlibParam.ptt_state:
# TODO: Moved to this place for testing
# Maybe we can avoid moments of silence before transmitting
static.PTT_STATE = self.radio.set_ptt(True)
HamlibParam.ptt_state = self.radio.set_ptt(True)
jsondata = {"ptt": "True"}
data_out = json.dumps(jsondata)
sock.SOCKET_QUEUE.put(data_out)
@ -539,14 +539,14 @@ class RF:
else:
return False
static.TRANSMITTING = True
TNC.transmitting = True
# if we're transmitting FreeDATA signals, reset channel busy state
static.CHANNEL_BUSY = False
ModemParam.channel_busy = False
start_of_transmission = time.time()
# TODO: Moved ptt toggle some steps before audio is ready for testing
# Toggle ptt early to save some time and send ptt state via socket
# static.PTT_STATE = self.radio.set_ptt(True)
# HamlibParam.ptt_state = self.radio.set_ptt(True)
# jsondata = {"ptt": "True"}
# data_out = json.dumps(jsondata)
# sock.SOCKET_QUEUE.put(data_out)
@ -577,15 +577,15 @@ class RF:
)
# Add empty data to handle ptt toggle time
if static.TX_DELAY > 0:
data_delay = int(self.MODEM_SAMPLE_RATE * (static.TX_DELAY / 1000)) # type: ignore
if ModemParam.tx_delay > 0:
data_delay = int(self.MODEM_SAMPLE_RATE * (ModemParam.tx_delay / 1000)) # type: ignore
mod_out_silence = ctypes.create_string_buffer(data_delay * 2)
txbuffer = bytes(mod_out_silence)
else:
txbuffer = bytes()
self.log.debug(
"[MDM] TRANSMIT", mode=self.MODE, payload=payload_bytes_per_frame, delay=static.TX_DELAY
"[MDM] TRANSMIT", mode=self.MODE, payload=payload_bytes_per_frame, delay=ModemParam.tx_delay
)
for _ in range(repeats):
@ -646,35 +646,35 @@ class RF:
x = np.frombuffer(txbuffer, dtype=np.int16)
# enable / disable AUDIO TUNE Feature / ALC correction
if static.AUDIO_AUTO_TUNE:
if static.HAMLIB_ALC == 0.0:
static.TX_AUDIO_LEVEL = static.TX_AUDIO_LEVEL + 20
elif 0.0 < static.HAMLIB_ALC <= 0.1:
print("0.0 < static.HAMLIB_ALC <= 0.1")
static.TX_AUDIO_LEVEL = static.TX_AUDIO_LEVEL + 2
self.log.debug("[MDM] AUDIO TUNE", audio_level=str(static.TX_AUDIO_LEVEL),
alc_level=str(static.HAMLIB_ALC))
elif 0.1 < static.HAMLIB_ALC < 0.2:
print("0.1 < static.HAMLIB_ALC < 0.2")
static.TX_AUDIO_LEVEL = static.TX_AUDIO_LEVEL
self.log.debug("[MDM] AUDIO TUNE", audio_level=str(static.TX_AUDIO_LEVEL),
alc_level=str(static.HAMLIB_ALC))
elif 0.2 < static.HAMLIB_ALC < 0.99:
print("0.2 < static.HAMLIB_ALC < 0.99")
static.TX_AUDIO_LEVEL = static.TX_AUDIO_LEVEL - 20
self.log.debug("[MDM] AUDIO TUNE", audio_level=str(static.TX_AUDIO_LEVEL),
alc_level=str(static.HAMLIB_ALC))
elif 1.0 >= static.HAMLIB_ALC:
print("1.0 >= static.HAMLIB_ALC")
static.TX_AUDIO_LEVEL = static.TX_AUDIO_LEVEL - 40
self.log.debug("[MDM] AUDIO TUNE", audio_level=str(static.TX_AUDIO_LEVEL),
alc_level=str(static.HAMLIB_ALC))
if AudioParam.audio_auto_tune:
if HamlibParam.alc == 0.0:
AudioParam.tx_audio_level = AudioParam.tx_audio_level + 20
elif 0.0 < HamlibParam.alc <= 0.1:
print("0.0 < HamlibParam.alc <= 0.1")
AudioParam.tx_audio_level = AudioParam.tx_audio_level + 2
self.log.debug("[MDM] AUDIO TUNE", audio_level=str(AudioParam.tx_audio_level),
alc_level=str(HamlibParam.alc))
elif 0.1 < HamlibParam.alc < 0.2:
print("0.1 < HamlibParam.alc < 0.2")
AudioParam.tx_audio_level = AudioParam.tx_audio_level
self.log.debug("[MDM] AUDIO TUNE", audio_level=str(AudioParam.tx_audio_level),
alc_level=str(HamlibParam.alc))
elif 0.2 < HamlibParam.alc < 0.99:
print("0.2 < HamlibParam.alc < 0.99")
AudioParam.tx_audio_level = AudioParam.tx_audio_level - 20
self.log.debug("[MDM] AUDIO TUNE", audio_level=str(AudioParam.tx_audio_level),
alc_level=str(HamlibParam.alc))
elif 1.0 >= HamlibParam.alc:
print("1.0 >= HamlibParam.alc")
AudioParam.tx_audio_level = AudioParam.tx_audio_level - 40
self.log.debug("[MDM] AUDIO TUNE", audio_level=str(AudioParam.tx_audio_level),
alc_level=str(HamlibParam.alc))
else:
self.log.debug("[MDM] AUDIO TUNE", audio_level=str(static.TX_AUDIO_LEVEL),
alc_level=str(static.HAMLIB_ALC))
x = set_audio_volume(x, static.TX_AUDIO_LEVEL)
self.log.debug("[MDM] AUDIO TUNE", audio_level=str(AudioParam.tx_audio_level),
alc_level=str(HamlibParam.alc))
x = set_audio_volume(x, AudioParam.tx_audio_level)
if not static.AUDIO_ENABLE_TCI:
if not AudioParam.audio_enable_tci:
txbuffer_out = self.resampler.resample8_to_48(x)
else:
txbuffer_out = x
@ -704,7 +704,7 @@ class RF:
self.mod_out_locked = False
# we need to wait manually for tci processing
if static.AUDIO_ENABLE_TCI:
if AudioParam.audio_enable_tci:
duration = len(txbuffer_out) / 8000
timestamp_to_sleep = time.time() + duration
self.log.debug("[MDM] TCI calculated duration", duration=duration)
@ -717,7 +717,7 @@ class RF:
tci_timeout_reached = True
while self.modoutqueue or not tci_timeout_reached:
if static.AUDIO_ENABLE_TCI:
if AudioParam.audio_enable_tci:
if time.time() < timestamp_to_sleep:
tci_timeout_reached = False
else:
@ -725,9 +725,9 @@ class RF:
threading.Event().wait(0.01)
# if we're transmitting FreeDATA signals, reset channel busy state
static.CHANNEL_BUSY = False
ModemParam.channel_busy = False
static.PTT_STATE = self.radio.set_ptt(False)
HamlibParam.ptt_state = self.radio.set_ptt(False)
# Push ptt state to socket stream
jsondata = {"ptt": "False"}
@ -738,7 +738,7 @@ class RF:
self.mod_out_locked = True
self.modem_transmit_queue.task_done()
static.TRANSMITTING = False
TNC.transmitting = False
threading.Event().set()
end_of_transmission = time.time()
@ -796,14 +796,14 @@ class RF:
if rx_status != 0:
# we need to disable this if in testmode as its causing problems with FIFO it seems
if not TESTMODE:
static.IS_CODEC2_TRAFFIC = True
ModemParam.is_codec2_traffic = True
self.log.debug(
"[MDM] [demod_audio] modem state", mode=mode_name, rx_status=rx_status,
sync_flag=codec2.api.rx_sync_flags_to_text[rx_status]
)
else:
static.IS_CODEC2_TRAFFIC = False
ModemParam.is_codec2_traffic = False
if rx_status == 10:
state_buffer.append(rx_status)
@ -812,8 +812,8 @@ class RF:
nin = codec2.api.freedv_nin(freedv)
if nbytes == bytes_per_frame:
# process commands only if static.LISTEN = True
if static.LISTEN:
# process commands only if TNC.listen = True
if TNC.listen:
# ignore data channel opener frames for avoiding toggle states
@ -839,7 +839,7 @@ class RF:
else:
self.log.warning(
"[MDM] [demod_audio] received frame but ignored processing",
listen=static.LISTEN
listen=TNC.listen
)
except Exception as e:
self.log.warning("[MDM] [demod_audio] Stream not active anymore", e=e)
@ -876,8 +876,8 @@ class RF:
# set tuning range
codec2.api.freedv_set_tuning_range(
c2instance,
ctypes.c_float(static.TUNING_RANGE_FMIN),
ctypes.c_float(static.TUNING_RANGE_FMAX),
ctypes.c_float(ModemParam.tuning_range_fmin),
ctypes.c_float(ModemParam.tuning_range_fmax),
)
# get bytes per frame
@ -1029,7 +1029,7 @@ class RF:
def get_frequency_offset(self, freedv: ctypes.c_void_p) -> float:
"""
Ask codec2 for the calculated (audio) frequency offset of the received signal.
Side-effect: sets static.FREQ_OFFSET
Side-effect: sets ModemParam.frequency_offset
:param freedv: codec2 instance to query
:type freedv: ctypes.c_void_p
@ -1039,18 +1039,18 @@ class RF:
modemStats = codec2.MODEMSTATS()
codec2.api.freedv_get_modem_extended_stats(freedv, ctypes.byref(modemStats))
offset = round(modemStats.foff) * (-1)
static.FREQ_OFFSET = offset
ModemParam.frequency_offset = offset
return offset
def get_scatter(self, freedv: ctypes.c_void_p) -> None:
"""
Ask codec2 for data about the received signal and calculate the scatter plot.
Side-effect: sets static.SCATTER
Side-effect: sets ModemParam.scatter
:param freedv: codec2 instance to query
:type freedv: ctypes.c_void_p
"""
if not static.ENABLE_SCATTER:
if not ModemParam.enable_scatter:
return
modemStats = codec2.MODEMSTATS()
@ -1078,16 +1078,16 @@ class RF:
# Send all the data if we have too-few samples, otherwise send a sampling
if 150 > len(scatterdata) > 0:
static.SCATTER = scatterdata
ModemParam.scatter = scatterdata
else:
# only take every tenth data point
static.SCATTER = scatterdata[::10]
ModemParam.scatter = scatterdata[::10]
def calculate_snr(self, freedv: ctypes.c_void_p) -> float:
"""
Ask codec2 for data about the received signal and calculate
the signal-to-noise ratio.
Side-effect: sets static.SNR
Side-effect: sets ModemParam.snr
:param freedv: codec2 instance to query
:type freedv: ctypes.c_void_p
@ -1106,15 +1106,15 @@ class RF:
snr = round(modem_stats_snr, 1)
self.log.info("[MDM] calculate_snr: ", snr=snr)
static.SNR = snr
# static.SNR = np.clip(
ModemParam.snr = snr
# ModemParam.snr = np.clip(
# snr, -127, 127
# ) # limit to max value of -128/128 as a possible fix of #188
return static.SNR
return ModemParam.snr
except Exception as err:
self.log.error(f"[MDM] calculate_snr: Exception: {err}")
static.SNR = 0
return static.SNR
ModemParam.snr = 0
return ModemParam.snr
def set_rig_data(self) -> None:
"""
@ -1134,29 +1134,29 @@ class RF:
"""
Request information about the current state of the radio via hamlib
Side-effect: sets
- static.HAMLIB_FREQUENCY
- static.HAMLIB_MODE
- static.HAMLIB_BANDWIDTH
- HamlibParam.hamlib_frequency
- HamlibParam.hamlib_mode
- HamlibParam.hamlib_bandwidth
"""
while True:
# this looks weird, but is necessary for avoiding rigctld packet colission sock
threading.Event().wait(0.25)
static.HAMLIB_FREQUENCY = self.radio.get_frequency()
HamlibParam.hamlib_frequency = self.radio.get_frequency()
threading.Event().wait(0.1)
static.HAMLIB_MODE = self.radio.get_mode()
HamlibParam.hamlib_mode = self.radio.get_mode()
threading.Event().wait(0.1)
static.HAMLIB_BANDWIDTH = self.radio.get_bandwidth()
HamlibParam.hamlib_bandwidth = self.radio.get_bandwidth()
threading.Event().wait(0.1)
static.HAMLIB_STATUS = self.radio.get_status()
HamlibParam.hamlib_status = self.radio.get_status()
threading.Event().wait(0.1)
if static.TRANSMITTING:
static.HAMLIB_ALC = self.radio.get_alc()
if TNC.transmitting:
HamlibParam.alc = self.radio.get_alc()
threading.Event().wait(0.1)
# static.HAMLIB_RF = self.radio.get_level()
# HamlibParam.hamlib_rf = self.radio.get_level()
# threading.Event().wait(0.1)
static.HAMLIB_STRENGTH = self.radio.get_strength()
HamlibParam.hamlib_strength = self.radio.get_strength()
# print(f"ALC: {static.HAMLIB_ALC}, RF: {static.HAMLIB_RF}, STRENGTH: {static.HAMLIB_STRENGTH}")
# print(f"ALC: {HamlibParam.alc}, RF: {HamlibParam.hamlib_rf}, STRENGTH: {HamlibParam.hamlib_strength}")
def calculate_fft(self) -> None:
"""
@ -1195,7 +1195,7 @@ class RF:
# Therefore we are setting it to 100 so it will be highlighted
# Have to do this when we are not transmitting so our
# own sending data will not affect this too much
if not static.TRANSMITTING:
if not TNC.transmitting:
dfft[dfft > avg + 15] = 100
# Calculate audio dbfs
@ -1211,20 +1211,20 @@ class RF:
rms = int(np.sqrt(np.max(d ** 2)))
if rms == 0:
raise ZeroDivisionError
static.AUDIO_DBFS = 20 * np.log10(rms / 32768)
AudioParam.audio_dbfs = 20 * np.log10(rms / 32768)
except Exception as e:
self.log.warning(
"[MDM] fft calculation error - please check your audio setup",
e=e,
)
static.AUDIO_DBFS = -100
AudioParam.audio_dbfs = -100
rms_counter = 0
# Convert data to int to decrease size
dfft = dfft.astype(int)
# Create list of dfft for later pushing to static.FFT
# Create list of dfft for later pushing to AudioParam.fft
dfftlist = dfft.tolist()
# Reduce area where the busy detection is enabled
@ -1250,14 +1250,14 @@ class RF:
range_start = range[0]
range_end = range[1]
# define the area, we are detecting busy state
#dfft = dfft[120:176] if static.LOW_BANDWIDTH_MODE else dfft[65:231]
#dfft = dfft[120:176] if TNC.low_bandwidth_mode else dfft[65:231]
dfft = dfft[range_start:range_end]
# Check for signals higher than average by checking for "100"
# If we have a signal, increment our channel_busy delay counter
# so we have a smoother state toggle
if np.sum(dfft[dfft > avg + 15]) >= 400 and not static.TRANSMITTING:
static.CHANNEL_BUSY = True
static.CHANNEL_BUSY_SLOT[slot] = True
if np.sum(dfft[dfft > avg + 15]) >= 400 and not TNC.transmitting:
ModemParam.channel_busy = True
ModemParam.channel_busy_slot[slot] = True
# Limit delay counter to a maximum of 200. The higher this value,
# the longer we will wait until releasing state
channel_busy_delay = min(channel_busy_delay + 10, 200)
@ -1266,18 +1266,18 @@ class RF:
channel_busy_delay = max(channel_busy_delay - 1, 0)
# When our channel busy counter reaches 0, toggle state to False
if channel_busy_delay == 0:
static.CHANNEL_BUSY = False
static.CHANNEL_BUSY_SLOT[slot] = False
ModemParam.channel_busy = False
ModemParam.channel_busy_slot[slot] = False
# increment slot
slot += 1
static.FFT = dfftlist[:315] # 315 --> bandwidth 3200
AudioParam.fft = dfftlist[:315] # 315 --> bandwidth 3200
except Exception as err:
self.log.error(f"[MDM] calculate_fft: Exception: {err}")
self.log.debug("[MDM] Setting fft=0")
# else 0
static.FFT = [0]
AudioParam.fft = [0]
def set_frames_per_burst(self, frames_per_burst: int) -> None:
"""

View file

@ -3,7 +3,7 @@ Hold queues used by more than one module to eliminate cyclic imports.
"""
import queue
import static
from static import ARQ, Audio, Beacon, Channel, Daemon, Hamlib, Modem, Station, TCI, TNC
from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, TCIParam, TNC
DATA_QUEUE_TRANSMIT = queue.Queue()
DATA_QUEUE_RECEIVED = queue.Queue()
@ -17,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()

View file

@ -10,10 +10,7 @@ import time
import structlog
import threading
import static
from static import ARQ, Audio, Beacon, Channel, Daemon, Hamlib, Modem, Station, TCI, TNC
# set global hamlib version
hamlib_version = 0
from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, TCIParam
class radio:
@ -244,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

View file

@ -27,7 +27,7 @@ import time
import wave
import helpers
import static
from static import ARQ, Audio, Beacon, Channel, Daemon, Hamlib, Modem, Station, TCI, TNC
from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC
import structlog
from random import randrange
import ujson as json
@ -68,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] == TNC.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
@ -99,9 +99,9 @@ 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 = []
ModemParam.scatter = []
# we want to display INFO messages only once
static.INFO = []
#static.INFO = []
# self.request.sendall(sock_data)
threading.Event().wait(0.15)
@ -355,14 +355,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:
@ -373,15 +373,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)
@ -393,7 +393,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:
@ -404,7 +404,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:
@ -415,7 +415,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:
@ -482,7 +482,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)
@ -497,7 +497,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:
@ -528,7 +528,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)
@ -544,7 +544,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:
@ -562,7 +562,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
@ -570,11 +570,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:
@ -594,24 +594,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:
@ -623,13 +623,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",
@ -639,19 +639,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"])
@ -664,7 +664,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:
@ -698,11 +698,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)
@ -804,7 +804,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)
@ -822,18 +822,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)
@ -847,8 +847,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)
@ -929,12 +929,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)
@ -973,15 +973,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"})
@ -999,53 +999,53 @@ def send_tnc_state():
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),
"channel_busy_slot": str(static.CHANNEL_BUSY_SLOT),
"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],

View file

@ -5,143 +5,144 @@ 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
CHANNEL_BUSY_SLOT = [False] * 5
ENABLE_EXPLORER = False
ENABLE_STATS = False
# DAEMON
TNCSTARTED: bool = False
TNCPROCESS: subprocess.Popen
# Operator Defaults
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: list = [] # ssid list we are responding to
LOW_BANDWIDTH_MODE: bool = False
# ---------------------------------
# Server Defaults
# ---------------------------------
SERIAL_DEVICES: list = []
# ---------------------------------
LISTEN: bool = True
PTT_STATE: bool = False
TRANSMITTING: bool = False
HAMLIB_RADIOCONTROL: str = "disabled"
HAMLIB_RIGCTLD_IP: str = "127.0.0.1"
HAMLIB_RIGCTLD_PORT: str = "4532"
HAMLIB_STATUS: str = "unknown/disconnected"
HAMLIB_FREQUENCY: int = 0
HAMLIB_MODE: str = ""
HAMLIB_BANDWIDTH: int = 0
HAMLIB_RF: int = 0
HAMLIB_ALC: int = 0
HAMLIB_STRENGTH: int = 0
# -------------------------
# FreeDV Defaults
SNR: float = 0
FREQ_OFFSET: float = 0
SCATTER: list = []
ENABLE_SCATTER: bool = False
ENABLE_FSK: bool = False
RESPOND_TO_CQ: bool = False
RESPOND_TO_CALL: bool = True # respond to cq, ping, connection request, file request if not in session
TX_DELAY: int = 0 # delay in ms before sending modulation for triggering VOX for example or slow PTT radios
# ---------------------------------
# Audio Defaults
TX_AUDIO_LEVEL: int = 50
AUDIO_INPUT_DEVICES: list = []
AUDIO_OUTPUT_DEVICES: list = []
AUDIO_INPUT_DEVICE: int = -2
AUDIO_OUTPUT_DEVICE: int = -2
AUDIO_RECORD: bool = False
AUDIO_RECORD_FILE = ''
BUFFER_OVERFLOW_COUNTER: list = [0, 0, 0, 0, 0]
AUDIO_AUTO_TUNE: bool = False
# Audio TCI Support
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
# v.5 - signalling frame uses datac0
# v.6 - signalling frame uses datac13
ARQ_PROTOCOL_VERSION: int = 6
# ARQ statistics
SPEED_LIST: list = []
ARQ_BYTES_PER_MINUTE_BURST: int = 0
ARQ_BYTES_PER_MINUTE: int = 0
ARQ_BITS_PER_SECOND_BURST: int = 0
ARQ_BITS_PER_SECOND: int = 0
ARQ_COMPRESSION_FACTOR: int = 0
ARQ_TRANSMISSION_PERCENT: int = 0
ARQ_SECONDS_UNTIL_FINISH: int = 0
ARQ_SPEED_LEVEL: int = 0
TOTAL_BYTES: int = 0
# set save to folder state for allowing downloading files to local file system
ARQ_SAVE_TO_FOLDER: bool = False
# CHANNEL_STATE = 'RECEIVING_SIGNALLING'
TNC_STATE: str = "IDLE"
ARQ_STATE: bool = False
ARQ_SESSION: bool = False
# disconnected, connecting, connected, disconnecting, failed
ARQ_SESSION_STATE: str = "disconnected"
# BEACON STATE
BEACON_STATE: bool = False
BEACON_PAUSE: bool = False
# ------- RX BUFFER
RX_MSG_BUFFER: list = []
RX_BURST_BUFFER: list = []
RX_FRAME_BUFFER: bytes = b""
RX_BUFFER_SIZE: int = 16
# ------- HEARD STATIONS BUFFER
HEARD_STATIONS: list = []
@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 = []
# ------- INFO MESSAGE BUFFER
# TODO: This can be removed?
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
@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.5"
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 = False
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):
@ -176,50 +177,3 @@ class FRAME_TYPE(Enum):
IDENT = 254
TEST_FRAME = 255
# TODO: Move settings above to dataclasses
@dataclass
class ARQ:
pass
@dataclass
class Audio:
pass
@dataclass
class Beacon:
pass
@dataclass
class Channel:
pass
@dataclass
class Daemon:
port: int = 3001
@dataclass
class Hamlib:
pass
@dataclass
class Modem:
pass
@dataclass
class Station:
pass
@dataclass
class TCI:
pass
@dataclass
class TNC:
version = "0.9.0-alpha-exp.5"
host: str = "0.0.0.0"
port: int = 3000
SOCKET_TIMEOUT: int = 1 # seconds

View file

@ -13,7 +13,7 @@ import time
import ujson as json
import structlog
import static
from static import ARQ, Audio, Beacon, Channel, Daemon, Hamlib, Modem, Station, TCI, TNC
from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, TCIParam, TNC
log = structlog.get_logger("stats")
@ -26,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)

View file

@ -7,9 +7,9 @@ import websocket
import numpy as np
import time
from queues import AUDIO_TRANSMIT_QUEUE, AUDIO_RECEIVED_QUEUE
from static import ARQ, Audio, Beacon, Channel, Daemon, Hamlib, Modem, Station, TCI, TNC
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")