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 helpers
import pytest 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"]) @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. 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_bytes = helpers.callsign_to_bytes(callsign)
t_callsign = helpers.bytes_to_callsign(t_callsign_bytes) 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. 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_crc = helpers.get_crc_24(bytes(callsign, "UTF-8"))
t_callsign_bytes = helpers.callsign_to_bytes(callsign) t_callsign_bytes = helpers.callsign_to_bytes(callsign)

View file

@ -26,7 +26,7 @@ sys.path.insert(0, "..")
sys.path.insert(0, "../tnc") sys.path.insert(0, "../tnc")
import data_handler import data_handler
import helpers import helpers
import static from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC
def print_frame(data: bytearray): def print_frame(data: bytearray):
@ -148,18 +148,18 @@ def t_foreign_disconnect(mycall: str, dxcall: str):
:rtype: bytearray :rtype: bytearray
""" """
# Set the SSIDs we'll use for this test. # 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. # Setup the static parameters for the connection.
mycallsign_bytes = helpers.callsign_to_bytes(mycall) mycallsign_bytes = helpers.callsign_to_bytes(mycall)
mycallsign = helpers.bytes_to_callsign(mycallsign_bytes) mycallsign = helpers.bytes_to_callsign(mycallsign_bytes)
static.MYCALLSIGN = mycallsign Station.mycallsign = mycallsign
static.MYCALLSIGN_CRC = helpers.get_crc_24(mycallsign) Station.mycallsign_crc = helpers.get_crc_24(mycallsign)
dxcallsign_bytes = helpers.callsign_to_bytes(dxcall) dxcallsign_bytes = helpers.callsign_to_bytes(dxcall)
dxcallsign = helpers.bytes_to_callsign(dxcallsign_bytes) dxcallsign = helpers.bytes_to_callsign(dxcallsign_bytes)
static.DXCALLSIGN = dxcallsign Station.dxcallsign = dxcallsign
static.DXCALLSIGN_CRC = helpers.get_crc_24(dxcallsign) Station.dxcallsign_crc = helpers.get_crc_24(dxcallsign)
# Create the TNC # Create the TNC
tnc = data_handler.DATA() tnc = data_handler.DATA()
@ -173,12 +173,12 @@ def t_foreign_disconnect(mycall: str, dxcall: str):
print_frame(create_frame) print_frame(create_frame)
tnc.received_session_opener(create_frame) tnc.received_session_opener(create_frame)
assert helpers.callsign_to_bytes(static.MYCALLSIGN) == mycallsign_bytes assert helpers.callsign_to_bytes(Station.mycallsign) == mycallsign_bytes
assert helpers.callsign_to_bytes(static.DXCALLSIGN) == dxcallsign_bytes assert helpers.callsign_to_bytes(Station.dxcallsign) == dxcallsign_bytes
assert static.ARQ_SESSION is True assert ARQ.arq_session is True
assert static.TNC_STATE == "BUSY" assert TNC.tnc_state == "BUSY"
assert static.ARQ_SESSION_STATE == "connecting" assert ARQ.arq_session_state == "connecting"
# Set up a frame from a non-associated station. # Set up a frame from a non-associated station.
# foreigncall_bytes = helpers.callsign_to_bytes("ZZ0ZZ-0") # foreigncall_bytes = helpers.callsign_to_bytes("ZZ0ZZ-0")
@ -193,8 +193,8 @@ def t_foreign_disconnect(mycall: str, dxcall: str):
print_frame(close_frame) print_frame(close_frame)
# assert ( # assert (
# helpers.check_callsign(static.DXCALLSIGN, bytes(close_frame[4:7]))[0] is False # helpers.check_callsign(Station.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." # ), f"{helpers.get_crc_24(Station.dxcallsign)} == {bytes(close_frame[4:7])} but should be not equal."
# assert ( # assert (
# helpers.check_callsign(foreigncall, bytes(close_frame[4:7]))[0] is True # 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 # Send the non-associated session close frame to the TNC
tnc.received_session_close(close_frame) 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 mycall
), f"{static.MYCALLSIGN} != {mycall} but should equal." ), f"{Station.mycallsign} != {mycall} but should equal."
assert helpers.callsign_to_bytes(static.DXCALLSIGN) == helpers.callsign_to_bytes( assert helpers.callsign_to_bytes(Station.dxcallsign) == helpers.callsign_to_bytes(
dxcall dxcall
), f"{static.DXCALLSIGN} != {dxcall} but should equal." ), f"{Station.dxcallsign} != {dxcall} but should equal."
assert static.ARQ_SESSION is True assert ARQ.arq_session is True
assert static.TNC_STATE == "BUSY" assert TNC.tnc_state == "BUSY"
assert static.ARQ_SESSION_STATE == "connecting" assert ARQ.arq_session_state == "connecting"
def t_valid_disconnect(mycall: str, dxcall: str): def t_valid_disconnect(mycall: str, dxcall: str):
@ -228,18 +228,18 @@ def t_valid_disconnect(mycall: str, dxcall: str):
:rtype: bytearray :rtype: bytearray
""" """
# Set the SSIDs we'll use for this test. # 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. # Setup the static parameters for the connection.
mycallsign_bytes = helpers.callsign_to_bytes(mycall) mycallsign_bytes = helpers.callsign_to_bytes(mycall)
mycallsign = helpers.bytes_to_callsign(mycallsign_bytes) mycallsign = helpers.bytes_to_callsign(mycallsign_bytes)
static.MYCALLSIGN = mycallsign Station.mycallsign = mycallsign
static.MYCALLSIGN_CRC = helpers.get_crc_24(mycallsign) Station.mycallsign_crc = helpers.get_crc_24(mycallsign)
dxcallsign_bytes = helpers.callsign_to_bytes(dxcall) dxcallsign_bytes = helpers.callsign_to_bytes(dxcall)
dxcallsign = helpers.bytes_to_callsign(dxcallsign_bytes) dxcallsign = helpers.bytes_to_callsign(dxcallsign_bytes)
static.DXCALLSIGN = dxcallsign Station.dxcallsign = dxcallsign
static.DXCALLSIGN_CRC = helpers.get_crc_24(dxcallsign) Station.dxcallsign_crc = helpers.get_crc_24(dxcallsign)
# Create the TNC # Create the TNC
tnc = data_handler.DATA() tnc = data_handler.DATA()
@ -253,9 +253,9 @@ def t_valid_disconnect(mycall: str, dxcall: str):
print_frame(create_frame) print_frame(create_frame)
tnc.received_session_opener(create_frame) tnc.received_session_opener(create_frame)
assert static.ARQ_SESSION is True assert ARQ.arq_session is True
assert static.TNC_STATE == "BUSY" assert TNC.tnc_state == "BUSY"
assert static.ARQ_SESSION_STATE == "connecting" assert ARQ.arq_session_state == "connecting"
# Create packet to be 'received' by this station. # Create packet to be 'received' by this station.
# close_frame = t_create_session_close_old(mycall=dxcall, dxcall=mycall) # 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) print_frame(close_frame)
tnc.received_session_close(close_frame) tnc.received_session_close(close_frame)
assert helpers.callsign_to_bytes(static.MYCALLSIGN) == mycallsign_bytes assert helpers.callsign_to_bytes(Station.mycallsign) == mycallsign_bytes
assert helpers.callsign_to_bytes(static.DXCALLSIGN) == dxcallsign_bytes assert helpers.callsign_to_bytes(Station.dxcallsign) == dxcallsign_bytes
assert static.ARQ_SESSION is False assert ARQ.arq_session is False
assert static.TNC_STATE == "IDLE" assert TNC.tnc_state == "IDLE"
assert static.ARQ_SESSION_STATE == "disconnected" assert ARQ.arq_session_state == "disconnected"
# These tests are pushed into separate processes as a workaround. These tests # These tests are pushed into separate processes as a workaround. These tests

View file

@ -22,7 +22,7 @@ import data_handler
import helpers import helpers
import modem import modem
import sock import sock
import static from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC
import structlog import structlog
@ -39,23 +39,23 @@ def t_setup(
modem.RXCHANNEL = tmp_path / "hfchannel1" modem.RXCHANNEL = tmp_path / "hfchannel1"
modem.TESTMODE = True modem.TESTMODE = True
modem.TXCHANNEL = tmp_path / "hfchannel2" modem.TXCHANNEL = tmp_path / "hfchannel2"
static.HAMLIB_RADIOCONTROL = "disabled" HamlibParam.hamlib_radiocontrol = "disabled"
static.LOW_BANDWIDTH_MODE = lowbwmode TNC.low_bandwidth_mode = lowbwmode
static.MYGRID = bytes("AA12aa", "utf-8") Station.mygrid = bytes("AA12aa", "utf-8")
static.RESPOND_TO_CQ = True TNC.respond_to_cq = True
static.SSID_LIST = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] Station.ssid_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# override ARQ SESSION STATE for allowing disconnect command # 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.callsign_to_bytes(mycall)
mycallsign = helpers.bytes_to_callsign(mycallsign) mycallsign = helpers.bytes_to_callsign(mycallsign)
static.MYCALLSIGN = mycallsign Station.mycallsign = mycallsign
static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN) Station.mycallsign_crc = helpers.get_crc_24(Station.mycallsign)
dxcallsign = helpers.callsign_to_bytes(dxcall) dxcallsign = helpers.callsign_to_bytes(dxcall)
dxcallsign = helpers.bytes_to_callsign(dxcallsign) dxcallsign = helpers.bytes_to_callsign(dxcallsign)
static.DXCALLSIGN = dxcallsign Station.dxcallsign = dxcallsign
static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN) Station.dxcallsign_crc = helpers.get_crc_24(Station.dxcallsign)
# Create the TNC # Create the TNC
tnc = data_handler.DATA() tnc = data_handler.DATA()
@ -105,7 +105,7 @@ def t_highsnr_arq_short_station1(
log.info("S1 TX: ", mode=static.FRAME_TYPE(frametype).name) log.info("S1 TX: ", mode=static.FRAME_TYPE(frametype).name)
if ( if (
static.LOW_BANDWIDTH_MODE TNC.low_bandwidth_mode
and frametype == static.FRAME_TYPE.ARQ_DC_OPEN_W.value and frametype == static.FRAME_TYPE.ARQ_DC_OPEN_W.value
): ):
mesg = ( mesg = (
@ -116,7 +116,7 @@ def t_highsnr_arq_short_station1(
log.error(mesg) log.error(mesg)
assert False, mesg assert False, mesg
if ( if (
not static.LOW_BANDWIDTH_MODE not TNC.low_bandwidth_mode
and frametype == static.FRAME_TYPE.ARQ_DC_OPEN_N.value and frametype == static.FRAME_TYPE.ARQ_DC_OPEN_N.value
): ):
mesg = ( mesg = (
@ -184,23 +184,23 @@ def t_highsnr_arq_short_station1(
log.warning("station1 TIMEOUT", first=True) log.warning("station1 TIMEOUT", first=True)
break break
time.sleep(0.1) 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} data = {"type": "arq", "command": "disconnect", "dxcallsign": dxcall}
sock.process_tnc_commands(json.dumps(data, indent=None)) sock.process_tnc_commands(json.dumps(data, indent=None))
time.sleep(0.5) time.sleep(0.5)
# override ARQ SESSION STATE for allowing disconnect command # 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)) sock.process_tnc_commands(json.dumps(data, indent=None))
# Allow enough time for this side to process the disconnect frame. # Allow enough time for this side to process the disconnect frame.
timeout = time.time() + 20 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: if time.time() > timeout:
log.error("station1", TIMEOUT=True) log.error("station1", TIMEOUT=True)
break break
time.sleep(0.5) 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 DQT: ", DQ_Tx=pformat(tnc.data_queue_transmit.queue))
# log.info("S1 DQR: ", DQ_Rx=pformat(tnc.data_queue_received.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 helpers
import modem import modem
import sock import sock
import static from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC
import structlog import structlog
@ -36,23 +36,23 @@ def t_setup(
modem.RXCHANNEL = tmp_path / "hfchannel2" modem.RXCHANNEL = tmp_path / "hfchannel2"
modem.TESTMODE = True modem.TESTMODE = True
modem.TXCHANNEL = tmp_path / "hfchannel1" modem.TXCHANNEL = tmp_path / "hfchannel1"
static.HAMLIB_RADIOCONTROL = "disabled" HamlibParam.hamlib_radiocontrol = "disabled"
static.LOW_BANDWIDTH_MODE = lowbwmode TNC.low_bandwidth_mode = lowbwmode
static.MYGRID = bytes("AA12aa", "utf-8") Station.mygrid = bytes("AA12aa", "utf-8")
static.RESPOND_TO_CQ = True TNC.respond_to_cq = True
static.SSID_LIST = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] Station.ssid_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# override ARQ SESSION STATE for allowing disconnect command # 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.callsign_to_bytes(mycall)
mycallsign = helpers.bytes_to_callsign(mycallsign) mycallsign = helpers.bytes_to_callsign(mycallsign)
static.MYCALLSIGN = mycallsign Station.mycallsign = mycallsign
static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN) Station.mycallsign_crc = helpers.get_crc_24(Station.mycallsign)
dxcallsign = helpers.callsign_to_bytes(dxcall) dxcallsign = helpers.callsign_to_bytes(dxcall)
dxcallsign = helpers.bytes_to_callsign(dxcallsign) dxcallsign = helpers.bytes_to_callsign(dxcallsign)
static.DXCALLSIGN = dxcallsign Station.dxcallsign = dxcallsign
static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN) Station.dxcallsign_crc = helpers.get_crc_24(Station.dxcallsign)
# Create the TNC # Create the TNC
tnc = data_handler.DATA() tnc = data_handler.DATA()
@ -136,13 +136,13 @@ def t_highsnr_arq_short_station2(
# the queue to an object for comparisons. # the queue to an object for comparisons.
while ( while (
'"arq":"transmission","status":"received"' not in str(sock.SOCKET_QUEUE.queue) '"arq":"transmission","status":"received"' not in str(sock.SOCKET_QUEUE.queue)
or static.ARQ_STATE or ARQ.arq_state
): ):
if time.time() > timeout: if time.time() > timeout:
log.warning("station2 TIMEOUT", first=True) log.warning("station2 TIMEOUT", first=True)
break break
time.sleep(0.5) 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. # Allow enough time for this side to receive the disconnect frame.
timeout = time.time() + 20 timeout = time.time() + 20
@ -151,7 +151,7 @@ def t_highsnr_arq_short_station2(
log.warning("station2", TIMEOUT=True) log.warning("station2", TIMEOUT=True)
break break
time.sleep(0.5) 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 DQT: ", DQ_Tx=pformat(tnc.data_queue_transmit.queue))
# log.info("S2 DQR: ", DQ_Rx=pformat(tnc.data_queue_received.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 helpers
import modem import modem
import sock 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 import structlog
from static import FRAME_TYPE as FR_TYPE #from static import FRAME_TYPE as FR_TYPE
def t_setup( def t_setup(
@ -46,21 +46,21 @@ def t_setup(
modem.RXCHANNEL = tmp_path / rx_channel modem.RXCHANNEL = tmp_path / rx_channel
modem.TESTMODE = True modem.TESTMODE = True
modem.TXCHANNEL = tmp_path / tx_channel modem.TXCHANNEL = tmp_path / tx_channel
static.HAMLIB_RADIOCONTROL = "disabled" HamlibParam.hamlib_radiocontrol = "disabled"
static.LOW_BANDWIDTH_MODE = lowbwmode or True TNC.low_bandwidth_mode = lowbwmode or True
static.MYGRID = bytes("AA12aa", "utf-8") Station.mygrid = bytes("AA12aa", "utf-8")
static.RESPOND_TO_CQ = True Station.respond_to_cq = True
static.SSID_LIST = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] Station.ssid_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
mycallsign = helpers.callsign_to_bytes(mycall) mycallsign = helpers.callsign_to_bytes(mycall)
mycallsign = helpers.bytes_to_callsign(mycallsign) mycallsign = helpers.bytes_to_callsign(mycallsign)
static.MYCALLSIGN = mycallsign Station.mycallsign = mycallsign
static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN) Station.mycallsign_crc = helpers.get_crc_24(Station.mycallsign)
dxcallsign = helpers.callsign_to_bytes(dxcall) dxcallsign = helpers.callsign_to_bytes(dxcall)
dxcallsign = helpers.bytes_to_callsign(dxcallsign) dxcallsign = helpers.bytes_to_callsign(dxcallsign)
static.DXCALLSIGN = dxcallsign Station.dxcallsign = dxcallsign
static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN) Station.dxcallsign_crc = helpers.get_crc_24(Station.dxcallsign)
# Create the TNC # Create the TNC
tnc = data_handler.DATA() tnc = data_handler.DATA()
@ -149,8 +149,8 @@ def t_datac13_1(
time.sleep(0.5) time.sleep(0.5)
if "stop" in data["command"]: if "stop" in data["command"]:
log.debug("t_datac13_1: STOP test, setting TNC state") log.debug("t_datac13_1: STOP test, setting TNC state")
static.TNC_STATE = "BUSY" TNC.tnc_state = "BUSY"
static.ARQ_STATE = True 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))
time.sleep(0.5) time.sleep(0.5)
sock.ThreadedTCPRequestHandler.process_tnc_commands(None,json.dumps(data, indent=None)) sock.ThreadedTCPRequestHandler.process_tnc_commands(None,json.dumps(data, indent=None))
@ -169,7 +169,7 @@ def t_datac13_1(
time.sleep(0.1) time.sleep(0.1)
log.info("station1, first") log.info("station1, first")
# override ARQ SESSION STATE for allowing disconnect command # 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} data = {"type": "arq", "command": "disconnect", "dxcallsign": dxcall}
sock.ThreadedTCPRequestHandler.process_tnc_commands(None,json.dumps(data, indent=None)) sock.ThreadedTCPRequestHandler.process_tnc_commands(None,json.dumps(data, indent=None))
time.sleep(0.5) time.sleep(0.5)

View file

@ -15,9 +15,9 @@ import data_handler
import helpers import helpers
import modem import modem
import sock 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 import structlog
from static import FRAME_TYPE as FR_TYPE #from static import FRAME_TYPE as FR_TYPE
def t_setup( def t_setup(
@ -40,21 +40,21 @@ def t_setup(
modem.RXCHANNEL = tmp_path / rx_channel modem.RXCHANNEL = tmp_path / rx_channel
modem.TESTMODE = True modem.TESTMODE = True
modem.TXCHANNEL = tmp_path / tx_channel modem.TXCHANNEL = tmp_path / tx_channel
static.HAMLIB_RADIOCONTROL = "disabled" HamlibParam.hamlib_radiocontrol = "disabled"
static.LOW_BANDWIDTH_MODE = lowbwmode or True TNC.low_bandwidth_mode = lowbwmode or True
static.MYGRID = bytes("AA12aa", "utf-8") Station.mygrid = bytes("AA12aa", "utf-8")
static.RESPOND_TO_CQ = True Station.respond_to_cq = True
static.SSID_LIST = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 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) dxcallsign_bytes = helpers.callsign_to_bytes(dxcall)
mycallsign = helpers.bytes_to_callsign(mycallsign) dxcallsign = helpers.bytes_to_callsign(dxcallsign_bytes)
static.MYCALLSIGN = mycallsign Station.dxcallsign = dxcallsign
static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN) Station.dxcallsign_crc = helpers.get_crc_24(dxcallsign)
dxcallsign = helpers.callsign_to_bytes(dxcall)
dxcallsign = helpers.bytes_to_callsign(dxcallsign)
static.DXCALLSIGN = dxcallsign
static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN)
# Create the TNC # Create the TNC
tnc = data_handler.DATA() 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:", RXCHANNEL=modem.RXCHANNEL)
log.info("t_datac13_1:", TXCHANNEL=modem.TXCHANNEL) log.info("t_datac13_1:", TXCHANNEL=modem.TXCHANNEL)
orig_dxcall = static.DXCALLSIGN orig_dxcall = Station.dxcallsign
if "stop" in data["command"]: if "stop" in data["command"]:
time.sleep(0.5) time.sleep(0.5)
log.debug( log.debug(
"t_datac13_1: STOP test, setting TNC state", "t_datac13_1: STOP test, setting TNC state",
mycall=static.MYCALLSIGN, mycall=Station.mycallsign,
dxcall=static.DXCALLSIGN, dxcall=Station.dxcallsign,
) )
static.DXCALLSIGN = helpers.callsign_to_bytes(data["dxcallsign"]) Station.dxcallsign = helpers.callsign_to_bytes(data["dxcallsign"])
static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN) Station.dxcallsign_CRC = helpers.get_crc_24(Station.dxcallsign)
static.TNC_STATE = "BUSY" TNC.tnc_state = "BUSY"
static.ARQ_STATE = True 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))
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"]: if "stop" in data["command"]:
time.sleep(0.5) time.sleep(0.5)
log.debug("STOP test, resetting DX callsign") log.debug("STOP test, resetting DX callsign")
static.DXCALLSIGN = orig_dxcall Station.dxcallsign = orig_dxcall
static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN) Station.dxcallsign_CRC = helpers.get_crc_24(Station.dxcallsign)
# override ARQ SESSION STATE for allowing disconnect command # 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} data = {"type": "arq", "command": "disconnect", "dxcallsign": dxcall}
sock.ThreadedTCPRequestHandler.process_tnc_commands(None,json.dumps(data, indent=None)) sock.ThreadedTCPRequestHandler.process_tnc_commands(None,json.dumps(data, indent=None))
time.sleep(0.5) 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:", RXCHANNEL=modem.RXCHANNEL)
log.info("t_datac13_2:", TXCHANNEL=modem.TXCHANNEL) 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: if "cq" in data:
t_data = {"type": "arq", "command": "stop_transmission"} t_data = {"type": "arq", "command": "stop_transmission"}

View file

@ -26,8 +26,7 @@ import crcengine
import log_handler import log_handler
import serial.tools.list_ports import serial.tools.list_ports
import sock import sock
import static from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC
from static import ARQ, Audio, Beacon, Channel, Daemon, Hamlib, Modem, Station, TCI, TNC
import structlog import structlog
import ujson as json import ujson as json
@ -84,10 +83,10 @@ class DAEMON:
""" """
while True: while True:
try: try:
if not static.TNCSTARTED: if not Daemon.tncstarted:
( (
static.AUDIO_INPUT_DEVICES, AudioParam.audio_input_devices,
static.AUDIO_OUTPUT_DEVICES, AudioParam.audio_output_devices,
) = audio.get_audio_devices() ) = audio.get_audio_devices()
except Exception as err1: except Exception as err1:
self.log.error( self.log.error(
@ -114,7 +113,7 @@ class DAEMON:
{"port": str(port), "description": str(description)} {"port": str(port), "description": str(description)}
) )
static.SERIAL_DEVICES = serial_devices Daemon.serial_devices = serial_devices
threading.Event().wait(1) threading.Event().wait(1)
except Exception as err1: except Exception as err1:
self.log.error( self.log.error(
@ -319,8 +318,8 @@ class DAEMON:
self.log.info("[DMN] TNC started", path="source") self.log.info("[DMN] TNC started", path="source")
static.TNCPROCESS = proc Daemon.tncprocess = proc
static.TNCSTARTED = True Daemon.tncstarted = True
if __name__ == "__main__": if __name__ == "__main__":
mainlog = structlog.get_logger(__file__) mainlog = structlog.get_logger(__file__)
# we need to run this on Windows for multiprocessing support # we need to run this on Windows for multiprocessing support
@ -369,7 +368,7 @@ if __name__ == "__main__":
# https://stackoverflow.com/a/16641793 # https://stackoverflow.com/a/16641793
socketserver.TCPServer.allow_reuse_address = True socketserver.TCPServer.allow_reuse_address = True
cmdserver = sock.ThreadedTCPServer( 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 = threading.Thread(target=cmdserver.serve_forever)
server_thread.daemon = True 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 ujson as json
import structlog import structlog
import static 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") log = structlog.get_logger("explorer")
@ -34,21 +34,21 @@ class explorer():
def push(self): 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" band = "USB"
callsign = str(static.MYCALLSIGN, "utf-8") callsign = str(Station.mycall, "utf-8")
gridsquare = str(static.MYGRID, "utf-8") gridsquare = str(Station.mygrid, "utf-8")
version = str(static.VERSION) version = str(TNC.version)
bandwidth = str(static.LOW_BANDWIDTH_MODE) bandwidth = str(TNC.low_bandwidth_mode)
beacon = str(static.BEACON_STATE) beacon = str(Beacon.beacon_state)
strength = str(static.HAMLIB_STRENGTH) strength = str(HamlibParam.hamlib_strength)
log.info("[EXPLORER] publish", frequency=frequency, band=band, callsign=callsign, gridsquare=gridsquare, version=version, bandwidth=bandwidth) log.info("[EXPLORER] publish", frequency=frequency, band=band, callsign=callsign, gridsquare=gridsquare, version=version, bandwidth=bandwidth)
headers = {"Content-Type": "application/json"} headers = {"Content-Type": "application/json"}
station_data = {'callsign': callsign, 'gridsquare': gridsquare, 'frequency': frequency, 'strength': strength, 'band': band, 'version': version, 'bandwidth': bandwidth, 'beacon': beacon, "lastheard": []} 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: try:
callsign = str(i[0], "UTF-8") callsign = str(i[0], "UTF-8")
grid = str(i[1], "UTF-8") grid = str(i[1], "UTF-8")

View file

@ -8,7 +8,7 @@ import time
from datetime import datetime,timezone from datetime import datetime,timezone
import crcengine import crcengine
import static 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 structlog
import numpy as np import numpy as np
import threading import threading
@ -131,16 +131,16 @@ def add_to_heard_stations(dxcallsign, dxgrid, datatype, snr, offset, frequency):
Nothing Nothing
""" """
# check if buffer empty # check if buffer empty
if len(static.HEARD_STATIONS) == 0: if len(TNC.heard_stations) == 0:
static.HEARD_STATIONS.append( TNC.heard_stations.append(
[dxcallsign, dxgrid, int(datetime.now(timezone.utc).timestamp()), datatype, snr, offset, frequency] [dxcallsign, dxgrid, int(datetime.now(timezone.utc).timestamp()), datatype, snr, offset, frequency]
) )
# if not, we search and update # if not, we search and update
else: else:
for i in range(len(static.HEARD_STATIONS)): for i in range(len(TNC.heard_stations)):
# Update callsign with new timestamp # Update callsign with new timestamp
if static.HEARD_STATIONS[i].count(dxcallsign) > 0: if TNC.heard_stations[i].count(dxcallsign) > 0:
static.HEARD_STATIONS[i] = [ TNC.heard_stations[i] = [
dxcallsign, dxcallsign,
dxgrid, dxgrid,
int(time.time()), int(time.time()),
@ -151,8 +151,8 @@ def add_to_heard_stations(dxcallsign, dxgrid, datatype, snr, offset, frequency):
] ]
break break
# Insert if nothing found # Insert if nothing found
if i == len(static.HEARD_STATIONS) - 1: if i == len(TNC.heard_stations) - 1:
static.HEARD_STATIONS.append( TNC.heard_stations.append(
[ [
dxcallsign, dxcallsign,
dxgrid, dxgrid,
@ -166,10 +166,10 @@ def add_to_heard_stations(dxcallsign, dxgrid, datatype, snr, offset, frequency):
break break
# for idx, item in enumerate(static.HEARD_STATIONS): # for idx, item in enumerate(TNC.heard_stations):
# if dxcallsign in item: # if dxcallsign in item:
# item = [dxcallsign, int(time.time())] # item = [dxcallsign, int(time.time())]
# static.HEARD_STATIONS[idx] = item # TNC.heard_stations[idx] = item
def callsign_to_bytes(callsign) -> bytes: def callsign_to_bytes(callsign) -> bytes:
@ -306,7 +306,7 @@ def check_callsign(callsign: bytes, crc_to_check: bytes):
except Exception as err: except Exception as err:
log.debug("[HLP] check_callsign: Error callsign SSID to integer:", e=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 = bytearray(callsign)
call_with_ssid.extend("-".encode("utf-8")) call_with_ssid.extend("-".encode("utf-8"))
call_with_ssid.extend(str(ssid).encode("utf-8")) call_with_ssid.extend(str(ssid).encode("utf-8"))

View file

@ -29,7 +29,7 @@ import helpers
import log_handler import log_handler
import modem import modem
import static 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 structlog
import explorer import explorer
import json import json
@ -256,7 +256,7 @@ if __name__ == "__main__":
ARGS = PARSER.parse_args() ARGS = PARSER.parse_args()
# set save to folder state for allowing downloading files to local file system # 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: if not ARGS.configfile:
@ -267,46 +267,46 @@ if __name__ == "__main__":
try: try:
mycallsign = bytes(ARGS.mycall.upper(), "utf-8") mycallsign = bytes(ARGS.mycall.upper(), "utf-8")
mycallsign = helpers.callsign_to_bytes(mycallsign) mycallsign = helpers.callsign_to_bytes(mycallsign)
static.MYCALLSIGN = helpers.bytes_to_callsign(mycallsign) Station.mycallsign = helpers.bytes_to_callsign(mycallsign)
static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN) Station.mycallsign_crc = helpers.get_crc_24(Station.mycallsign)
static.SSID_LIST = ARGS.ssid_list Station.ssid_list = ARGS.ssid_list
# check if own ssid is always part of ssid list # check if own ssid is always part of ssid list
own_ssid = int(static.MYCALLSIGN.split(b"-")[1]) own_ssid = int(Station.mycallsign.split(b"-")[1])
if own_ssid not in static.SSID_LIST: if own_ssid not in Station.ssid_list:
static.SSID_LIST.append(own_ssid) 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 # check if we have an int or str as device name
try: try:
static.AUDIO_INPUT_DEVICE = int(ARGS.audio_input_device) AudioParam.audio_input_device = int(ARGS.audio_input_device)
except ValueError: except ValueError:
static.AUDIO_INPUT_DEVICE = ARGS.audio_input_device AudioParam.audio_input_device = ARGS.audio_input_device
try: try:
static.AUDIO_OUTPUT_DEVICE = int(ARGS.audio_output_device) AudioParam.audio_output_device = int(ARGS.audio_output_device)
except ValueError: except ValueError:
static.AUDIO_OUTPUT_DEVICE = ARGS.audio_output_device AudioParam.audio_output_device = ARGS.audio_output_device
TNC.port = ARGS.socket_port TNC.port = ARGS.socket_port
static.HAMLIB_RADIOCONTROL = ARGS.hamlib_radiocontrol HamlibParam.hamlib_radiocontrol = ARGS.hamlib_radiocontrol
static.HAMLIB_RIGCTLD_IP = ARGS.rigctld_ip HamlibParam.hamlib_rigctld_ip = ARGS.rigctld_ip
static.HAMLIB_RIGCTLD_PORT = str(ARGS.rigctld_port) HamlibParam.hamlib_rigctld_port = str(ARGS.rigctld_port)
static.ENABLE_SCATTER = ARGS.send_scatter ModemParam.enable_scatter = ARGS.send_scatter
static.ENABLE_FFT = ARGS.send_fft AudioParam.enable_fft = ARGS.send_fft
static.ENABLE_FSK = ARGS.enable_fsk TNC.enable_fsk = ARGS.enable_fsk
static.LOW_BANDWIDTH_MODE = ARGS.low_bandwidth_mode TNC.low_bandwidth_mode = ARGS.low_bandwidth_mode
static.TUNING_RANGE_FMIN = ARGS.tuning_range_fmin ModemParam.tuning_range_fmin = ARGS.tuning_range_fmin
static.TUNING_RANGE_FMAX = ARGS.tuning_range_fmax ModemParam.tuning_range_fmax = ARGS.tuning_range_fmax
static.TX_AUDIO_LEVEL = ARGS.tx_audio_level AudioParam.tx_audio_level = ARGS.tx_audio_level
static.RESPOND_TO_CQ = ARGS.enable_respond_to_cq TNC.respond_to_cq = ARGS.enable_respond_to_cq
static.RX_BUFFER_SIZE = ARGS.rx_buffer_size ARQ.rx_buffer_size = ARGS.rx_buffer_size
static.ENABLE_EXPLORER = ARGS.enable_explorer TNC.enable_explorer = ARGS.enable_explorer
static.AUDIO_AUTO_TUNE = ARGS.enable_audio_auto_tune AudioParam.audio_auto_tune = ARGS.enable_audio_auto_tune
static.ENABLE_STATS = ARGS.enable_stats TNC.enable_stats = ARGS.enable_stats
static.AUDIO_ENABLE_TCI = ARGS.audio_enable_tci AudioParam.audio_enable_tci = ARGS.audio_enable_tci
static.TCI_IP = ARGS.tci_ip TCIParam.ip = ARGS.tci_ip
static.TCI_PORT = ARGS.tci_port TCIParam.port = ARGS.tci_port
static.TX_DELAY = ARGS.tx_delay ModemParam.tx_delay = ARGS.tx_delay
except Exception as e: except Exception as e:
log.error("[DMN] Error reading config file", exception=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 # then we are forcing a station ssid = 0
mycallsign = bytes(conf.get('STATION', 'mycall', 'AA0AA'), "utf-8") mycallsign = bytes(conf.get('STATION', 'mycall', 'AA0AA'), "utf-8")
mycallsign = helpers.callsign_to_bytes(mycallsign) mycallsign = helpers.callsign_to_bytes(mycallsign)
static.MYCALLSIGN = helpers.bytes_to_callsign(mycallsign) Station.mycallsign = helpers.bytes_to_callsign(mycallsign)
static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN) Station.mycallsign_crc = helpers.get_crc_24(Station.mycallsign)
#json.loads = for converting str list to list #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 # check if we have an int or str as device name
try: try:
static.AUDIO_INPUT_DEVICE = int(conf.get('AUDIO', 'rx', '0')) AudioParam.audio_input_device = int(conf.get('AUDIO', 'rx', '0'))
except ValueError: except ValueError:
static.AUDIO_INPUT_DEVICE = conf.get('AUDIO', 'rx', '0') AudioParam.audio_input_device = conf.get('AUDIO', 'rx', '0')
try: try:
static.AUDIO_OUTPUT_DEVICE = int(conf.get('AUDIO', 'tx', '0')) AudioParam.audio_output_device = int(conf.get('AUDIO', 'tx', '0'))
except ValueError: 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')) TNC.port = int(conf.get('NETWORK', 'tncport', '3000'))
static.HAMLIB_RADIOCONTROL = conf.get('RADIO', 'radiocontrol', 'rigctld') HamlibParam.hamlib_radiocontrol = conf.get('RADIO', 'radiocontrol', 'rigctld')
static.HAMLIB_RIGCTLD_IP = conf.get('RADIO', 'rigctld_ip', '127.0.0.1') HamlibParam.hamlib_rigctld_ip = conf.get('RADIO', 'rigctld_ip', '127.0.0.1')
static.HAMLIB_RIGCTLD_PORT = str(conf.get('RADIO', 'rigctld_port', '4532')) HamlibParam.hamlib_rigctld_port = str(conf.get('RADIO', 'rigctld_port', '4532'))
static.ENABLE_SCATTER = conf.get('TNC', 'scatter', 'True') ModemParam.enable_scatter = conf.get('TNC', 'scatter', 'True')
static.ENABLE_FFT = conf.get('TNC', 'fft', 'True') AudioParam.enable_fft = conf.get('TNC', 'fft', 'True')
static.ENABLE_FSK = conf.get('TNC', 'fsk', 'False') TNC.enable_fsk = conf.get('TNC', 'fsk', 'False')
static.LOW_BANDWIDTH_MODE = conf.get('TNC', 'narrowband', 'False') TNC.low_bandwidth_mode = conf.get('TNC', 'narrowband', 'False')
static.TUNING_RANGE_FMIN = float(conf.get('TNC', 'fmin', '-50.0')) ModemParam.tuning_range_fmin = float(conf.get('TNC', 'fmin', '-50.0'))
static.TUNING_RANGE_FMAX = float(conf.get('TNC', 'fmax', '50.0')) ModemParam.tuning_range_fmax = float(conf.get('TNC', 'fmax', '50.0'))
static.TX_AUDIO_LEVEL = int(conf.get('AUDIO', 'txaudiolevel', '100')) AudioParam.tx_audio_level = int(conf.get('AUDIO', 'txaudiolevel', '100'))
static.RESPOND_TO_CQ = conf.get('TNC', 'qrv', 'True') TNC.respond_to_cq = conf.get('TNC', 'qrv', 'True')
static.RX_BUFFER_SIZE = int(conf.get('TNC', 'rxbuffersize', '16')) ARQ.rx_buffer_size = int(conf.get('TNC', 'rxbuffersize', '16'))
static.ENABLE_EXPLORER = conf.get('TNC', 'explorer', 'False') TNC.enable_explorer = conf.get('TNC', 'explorer', 'False')
static.AUDIO_AUTO_TUNE = conf.get('AUDIO', 'auto_tune', 'False') AudioParam.audio_auto_tune = conf.get('AUDIO', 'auto_tune', 'False')
static.ENABLE_STATS = conf.get('TNC', 'stats', 'False') TNC.enable_stats = conf.get('TNC', 'stats', 'False')
static.AUDIO_ENABLE_TCI = conf.get('AUDIO', 'enable_tci', 'False') AudioParam.audio_enable_tci = conf.get('AUDIO', 'enable_tci', 'False')
static.TCI_IP = str(conf.get('AUDIO', 'tci_ip', 'localhost')) TCIParam.ip = str(conf.get('AUDIO', 'tci_ip', 'localhost'))
static.TCI_PORT = int(conf.get('AUDIO', 'tci_port', '50001')) TCIParam.port = int(conf.get('AUDIO', 'tci_port', '50001'))
static.TX_DELAY = int(conf.get('TNC', 'tx_delay', '0')) ModemParam.tx_delay = int(conf.get('TNC', 'tx_delay', '0'))
except KeyError as e: except KeyError as e:
log.warning("[CFG] Error reading config file near", key=str(e)) log.warning("[CFG] Error reading config file near", key=str(e))
except Exception as e: except Exception as e:
log.warning("[CFG] Error", e=e) log.warning("[CFG] Error", e=e)
# make sure the own ssid is always part of the ssid list # make sure the own ssid is always part of the ssid list
my_ssid = int(static.MYCALLSIGN.split(b'-')[1]) my_ssid = int(Station.mycallsign.split(b'-')[1])
if my_ssid not in static.SSID_LIST: if my_ssid not in Station.ssid_list:
static.SSID_LIST.append(my_ssid) 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 # we need to wait until we got all parameters from argparse first before we can load the other modules
import sock import sock
@ -405,8 +405,8 @@ if __name__ == "__main__":
modem = modem.RF() modem = modem.RF()
# optionally start explorer module # optionally start explorer module
if static.ENABLE_EXPLORER: if TNC.enable_explorer:
log.info("[EXPLORER] Publishing to https://explorer.freedata.app", state=static.ENABLE_EXPLORER) log.info("[EXPLORER] Publishing to https://explorer.freedata.app", state=TNC.enable_explorer)
explorer = explorer.explorer() explorer = explorer.explorer()
# --------------------------------------------START CMD SERVER # --------------------------------------------START CMD SERVER

View file

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

View file

@ -10,10 +10,7 @@ import time
import structlog import structlog
import threading import threading
import static 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
# set global hamlib version
hamlib_version = 0
class radio: class radio:
@ -244,7 +241,7 @@ class radio:
if 'RPRT' not in alc: if 'RPRT' not in alc:
try: try:
alc = float(alc) 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: except ValueError:
self.alc = 0.0 self.alc = 0.0

View file

@ -27,7 +27,7 @@ import time
import wave import wave
import helpers import helpers
import static 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 structlog
from random import randrange from random import randrange
import ujson as json import ujson as json
@ -68,7 +68,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
while self.connection_alive and not CLOSE_SIGNAL: while self.connection_alive and not CLOSE_SIGNAL:
# send tnc state as network stream # send tnc state as network stream
# check server port against daemon port and send corresponding data # 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() data = send_tnc_state()
if data != tempdata: if data != tempdata:
tempdata = data tempdata = data
@ -99,9 +99,9 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
self.log.debug("[SCK] catch harmless RuntimeError: Set changed size during iteration", e=err) 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 # we want to transmit scatter data only once to reduce network traffic
static.SCATTER = [] ModemParam.scatter = []
# we want to display INFO messages only once # we want to display INFO messages only once
static.INFO = [] #static.INFO = []
# self.request.sendall(sock_data) # self.request.sendall(sock_data)
threading.Event().wait(0.15) threading.Event().wait(0.15)
@ -355,14 +355,14 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
def tnc_set_listen(self, received_json): def tnc_set_listen(self, received_json):
try: 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) command_response("listen", True)
# if tnc is connected, force disconnect when static.LISTEN == False # if tnc is connected, force disconnect when TNC.listen == False
if not static.LISTEN and static.ARQ_SESSION_STATE not in ["disconnecting", "disconnected", "failed"]: if not TNC.listen and ARQ.arq_session_state not in ["disconnecting", "disconnected", "failed"]:
DATA_QUEUE_TRANSMIT.put(["DISCONNECT"]) DATA_QUEUE_TRANSMIT.put(["DISCONNECT"])
# set early disconnecting state so we can interrupt connection attempts # set early disconnecting state so we can interrupt connection attempts
static.ARQ_SESSION_STATE = "disconnecting" ARQ.arq_session_state = "disconnecting"
command_response("disconnect", True) command_response("disconnect", True)
except Exception as err: except Exception as err:
@ -373,15 +373,15 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
def tnc_set_record_audio(self, received_json): def tnc_set_record_audio(self, received_json):
try: try:
if not static.AUDIO_RECORD: if not AudioParam.audio_record:
static.AUDIO_RECORD_FILE = wave.open(f"{int(time.time())}_audio_recording.wav", 'w') AudioParam.audio_record_FILE = wave.open(f"{int(time.time())}_audio_recording.wav", 'w')
static.AUDIO_RECORD_FILE.setnchannels(1) AudioParam.audio_record_FILE.setnchannels(1)
static.AUDIO_RECORD_FILE.setsampwidth(2) AudioParam.audio_record_FILE.setsampwidth(2)
static.AUDIO_RECORD_FILE.setframerate(8000) AudioParam.audio_record_FILE.setframerate(8000)
static.AUDIO_RECORD = True AudioParam.audio_record = True
else: else:
static.AUDIO_RECORD = False AudioParam.audio_record = False
static.AUDIO_RECORD_FILE.close() AudioParam.audio_record_FILE.close()
command_response("respond_to_call", True) command_response("respond_to_call", True)
@ -393,7 +393,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
def tnc_set_respond_to_call(self, received_json): def tnc_set_respond_to_call(self, received_json):
try: 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) command_response("respond_to_call", True)
except Exception as err: except Exception as err:
@ -404,7 +404,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
def tnc_set_respond_to_cq(self, received_json): def tnc_set_respond_to_cq(self, received_json):
try: 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) command_response("respond_to_cq", True)
except Exception as err: except Exception as err:
@ -415,7 +415,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
def tnc_set_tx_audio_level(self, received_json): def tnc_set_tx_audio_level(self, received_json):
try: try:
static.TX_AUDIO_LEVEL = int(received_json["value"]) AudioParam.tx_audio_level = int(received_json["value"])
command_response("tx_audio_level", True) command_response("tx_audio_level", True)
except Exception as err: except Exception as err:
@ -482,7 +482,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
def tnc_start_beacon(self, received_json): def tnc_start_beacon(self, received_json):
try: try:
static.BEACON_STATE = True Beacon.beacon_state = True
interval = int(received_json["parameter"]) interval = int(received_json["parameter"])
DATA_QUEUE_TRANSMIT.put(["BEACON", interval, True]) DATA_QUEUE_TRANSMIT.put(["BEACON", interval, True])
command_response("start_beacon", True) command_response("start_beacon", True)
@ -497,7 +497,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
def tnc_stop_beacon(self, received_json): def tnc_stop_beacon(self, received_json):
try: try:
log.warning("[SCK] Stopping beacon!") log.warning("[SCK] Stopping beacon!")
static.BEACON_STATE = False Beacon.beacon_state = False
DATA_QUEUE_TRANSMIT.put(["BEACON", None, False]) DATA_QUEUE_TRANSMIT.put(["BEACON", None, False])
command_response("stop_beacon", True) command_response("stop_beacon", True)
except Exception as err: except Exception as err:
@ -528,7 +528,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
mycallsign = helpers.bytes_to_callsign(mycallsign) mycallsign = helpers.bytes_to_callsign(mycallsign)
except Exception: except Exception:
mycallsign = static.MYCALLSIGN mycallsign = Station.mycallsign
DATA_QUEUE_TRANSMIT.put(["PING", mycallsign, dxcallsign]) DATA_QUEUE_TRANSMIT.put(["PING", mycallsign, dxcallsign])
command_response("ping", True) command_response("ping", True)
@ -544,7 +544,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
def tnc_arq_connect(self, received_json): def tnc_arq_connect(self, received_json):
# pause our beacon first # pause our beacon first
static.BEACON_PAUSE = True Beacon.beacon_pause = True
# check for connection attempts key # check for connection attempts key
try: try:
@ -562,7 +562,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
mycallsign = helpers.bytes_to_callsign(mycallsign) mycallsign = helpers.bytes_to_callsign(mycallsign)
except Exception: except Exception:
mycallsign = static.MYCALLSIGN mycallsign = Station.mycallsign
# additional step for being sure our callsign is correctly # additional step for being sure our callsign is correctly
# in case we are not getting a station ssid # 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.callsign_to_bytes(dxcallsign)
dxcallsign = helpers.bytes_to_callsign(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) command_response("connect", False)
log.warning( log.warning(
"[SCK] Connect command execution error", "[SCK] Connect command execution error",
e=f"already connected to station:{static.DXCALLSIGN}", e=f"already connected to station:{Station.dxcallsign}",
command=received_json, command=received_json,
) )
else: else:
@ -594,24 +594,24 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
command=received_json, command=received_json,
) )
# allow beacon transmission again # allow beacon transmission again
static.BEACON_PAUSE = False Beacon.beacon_pause = False
# allow beacon transmission again # allow beacon transmission again
static.BEACON_PAUSE = False Beacon.beacon_pause = False
def tnc_arq_disconnect(self, received_json): def tnc_arq_disconnect(self, received_json):
try: 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"]) DATA_QUEUE_TRANSMIT.put(["DISCONNECT"])
# set early disconnecting state so we can interrupt connection attempts # set early disconnecting state so we can interrupt connection attempts
static.ARQ_SESSION_STATE = "disconnecting" ARQ.arq_session_state = "disconnecting"
command_response("disconnect", True) command_response("disconnect", True)
else: else:
command_response("disconnect", False) command_response("disconnect", False)
log.warning( log.warning(
"[SCK] Disconnect command not possible", "[SCK] Disconnect command not possible",
state=static.ARQ_SESSION_STATE, state=ARQ.arq_session_state,
command=received_json, command=received_json,
) )
except Exception as err: except Exception as err:
@ -623,13 +623,13 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
) )
def tnc_arq_send_raw(self, received_json): def tnc_arq_send_raw(self, received_json):
static.BEACON_PAUSE = True Beacon.beacon_pause = True
# wait some random time # wait some random time
helpers.wait(randrange(5, 25, 5) / 10.0) helpers.wait(randrange(5, 25, 5) / 10.0)
# we need to warn if already in arq state # we need to warn if already in arq state
if static.ARQ_STATE: if ARQ.arq_state:
command_response("send_raw", False) command_response("send_raw", False)
log.warning( log.warning(
"[SCK] Send raw command execution warning", "[SCK] Send raw command execution warning",
@ -639,19 +639,19 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
) )
try: try:
if not static.ARQ_SESSION: if not ARQ.arq_session:
dxcallsign = received_json["parameter"][0]["dxcallsign"] dxcallsign = received_json["parameter"][0]["dxcallsign"]
# additional step for being sure our callsign is correctly # additional step for being sure our callsign is correctly
# in case we are not getting a station ssid # in case we are not getting a station ssid
# then we are forcing a station ssid = 0 # then we are forcing a station ssid = 0
dxcallsign = helpers.callsign_to_bytes(dxcallsign) dxcallsign = helpers.callsign_to_bytes(dxcallsign)
dxcallsign = helpers.bytes_to_callsign(dxcallsign) dxcallsign = helpers.bytes_to_callsign(dxcallsign)
static.DXCALLSIGN = dxcallsign Station.dxcallsign = dxcallsign
static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN) Station.dxcallsign_crc = helpers.get_crc_24(Station.dxcallsign)
command_response("send_raw", True) command_response("send_raw", True)
else: else:
dxcallsign = static.DXCALLSIGN dxcallsign = Station.dxcallsign
static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN) Station.dxcallsign_crc = helpers.get_crc_24(Station.dxcallsign)
mode = int(received_json["parameter"][0]["mode"]) mode = int(received_json["parameter"][0]["mode"])
n_frames = int(received_json["parameter"][0]["n_frames"]) n_frames = int(received_json["parameter"][0]["n_frames"])
@ -664,7 +664,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
mycallsign = helpers.bytes_to_callsign(mycallsign) mycallsign = helpers.bytes_to_callsign(mycallsign)
except Exception: except Exception:
mycallsign = static.MYCALLSIGN mycallsign = Station.mycallsign
# check for connection attempts key # check for connection attempts key
try: try:
@ -698,11 +698,11 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
def tnc_arq_stop_transmission(self, received_json): def tnc_arq_stop_transmission(self, received_json):
try: try:
if static.TNC_STATE == "BUSY" or static.ARQ_STATE: if TNC.tnc_state == "BUSY" or ARQ.arq_state:
DATA_QUEUE_TRANSMIT.put(["STOP"]) DATA_QUEUE_TRANSMIT.put(["STOP"])
log.warning("[SCK] Stopping transmission!") log.warning("[SCK] Stopping transmission!")
static.TNC_STATE = "IDLE" TNC.tnc_state = "IDLE"
static.ARQ_STATE = False ARQ.arq_state = False
command_response("stop_transmission", True) command_response("stop_transmission", True)
except Exception as err: except Exception as err:
command_response("stop_transmission", False) command_response("stop_transmission", False)
@ -804,7 +804,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
if ( if (
received_json["type"] == "set" received_json["type"] == "set"
and received_json["command"] == "start_tnc" and received_json["command"] == "start_tnc"
and not static.TNCSTARTED and not Daemon.tncstarted
): ):
self.daemon_start_tnc(received_json) self.daemon_start_tnc(received_json)
@ -822,18 +822,18 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
self.request.sendall(b"INVALID CALLSIGN") self.request.sendall(b"INVALID CALLSIGN")
log.warning( log.warning(
"[SCK] SET MYCALL FAILED", "[SCK] SET MYCALL FAILED",
call=static.MYCALLSIGN, call=Station.mycallsign,
crc=static.MYCALLSIGN_CRC.hex(), crc=Station.mycallsign_crc.hex(),
) )
else: else:
static.MYCALLSIGN = bytes(callsign, "utf-8") Station.mycallsign = bytes(callsign, "utf-8")
static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN) Station.mycallsign_crc = helpers.get_crc_24(Station.mycallsign)
command_response("mycallsign", True) command_response("mycallsign", True)
log.info( log.info(
"[SCK] SET MYCALL", "[SCK] SET MYCALL",
call=static.MYCALLSIGN, call=Station.mycallsign,
crc=static.MYCALLSIGN_CRC.hex(), crc=Station.mycallsign_crc.hex(),
) )
except Exception as err: except Exception as err:
command_response("mycallsign", False) command_response("mycallsign", False)
@ -847,8 +847,8 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
self.request.sendall(b"INVALID GRID") self.request.sendall(b"INVALID GRID")
command_response("mygrid", False) command_response("mygrid", False)
else: else:
static.MYGRID = bytes(mygrid, "utf-8") Station.mygrid = bytes(mygrid, "utf-8")
log.info("[SCK] SET MYGRID", grid=static.MYGRID) log.info("[SCK] SET MYGRID", grid=Station.mygrid)
command_response("mygrid", True) command_response("mygrid", True)
except Exception as err: except Exception as err:
command_response("mygrid", False) command_response("mygrid", False)
@ -929,12 +929,12 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
def daemon_stop_tnc(self, received_json): def daemon_stop_tnc(self, received_json):
try: try:
static.TNCPROCESS.kill() Daemon.tncprocess.kill()
# unregister process from atexit to avoid process zombies # unregister process from atexit to avoid process zombies
atexit.unregister(static.TNCPROCESS.kill) atexit.unregister(Daemon.tncprocess.kill)
log.warning("[SCK] Stopping TNC") log.warning("[SCK] Stopping TNC")
static.TNCSTARTED = False Daemon.tncstarted = False
command_response("stop_tnc", True) command_response("stop_tnc", True)
except Exception as err: except Exception as err:
command_response("stop_tnc", False) command_response("stop_tnc", False)
@ -973,15 +973,15 @@ def send_daemon_state():
"command": "daemon_state", "command": "daemon_state",
"daemon_state": [], "daemon_state": [],
"python_version": str(python_version), "python_version": str(python_version),
"input_devices": static.AUDIO_INPUT_DEVICES, "input_devices": AudioParam.audio_input_devices,
"output_devices": static.AUDIO_OUTPUT_DEVICES, "output_devices": AudioParam.audio_output_devices,
"serial_devices": static.SERIAL_DEVICES, "serial_devices": Daemon.serial_devices,
# 'cpu': str(psutil.cpu_percent()), # 'cpu': str(psutil.cpu_percent()),
# 'ram': str(psutil.virtual_memory().percent), # 'ram': str(psutil.virtual_memory().percent),
"version": "0.1", "version": "0.1",
} }
if static.TNCSTARTED: if Daemon.tncstarted:
output["daemon_state"].append({"status": "running"}) output["daemon_state"].append({"status": "running"})
else: else:
output["daemon_state"].append({"status": "stopped"}) output["daemon_state"].append({"status": "stopped"})
@ -999,53 +999,53 @@ def send_tnc_state():
encoding = "utf-8" encoding = "utf-8"
output = { output = {
"command": "tnc_state", "command": "tnc_state",
"ptt_state": str(static.PTT_STATE), "ptt_state": str(HamlibParam.ptt_state),
"tnc_state": str(static.TNC_STATE), "tnc_state": str(TNC.tnc_state),
"arq_state": str(static.ARQ_STATE), "arq_state": str(ARQ.arq_state),
"arq_session": str(static.ARQ_SESSION), "arq_session": str(ARQ.arq_session),
"arq_session_state": str(static.ARQ_SESSION_STATE), "arq_session_state": str(ARQ.arq_session_state),
"audio_dbfs": str(static.AUDIO_DBFS), "audio_dbfs": str(AudioParam.audio_dbfs),
"snr": str(static.SNR), "snr": str(ModemParam.snr),
"frequency": str(static.HAMLIB_FREQUENCY), "frequency": str(HamlibParam.hamlib_frequency),
"rf_level": str(static.HAMLIB_RF), "rf_level": str(HamlibParam.hamlib_rf),
"strength": str(static.HAMLIB_STRENGTH), "strength": str(HamlibParam.hamlib_strength),
"alc": str(static.HAMLIB_ALC), "alc": str(HamlibParam.alc),
"audio_level": str(static.TX_AUDIO_LEVEL), "audio_level": str(AudioParam.tx_audio_level),
"audio_auto_tune": str(static.AUDIO_AUTO_TUNE), "audio_auto_tune": str(AudioParam.audio_auto_tune),
"speed_level": str(static.ARQ_SPEED_LEVEL), "speed_level": str(ARQ.arq_speed_level),
"mode": str(static.HAMLIB_MODE), "mode": str(HamlibParam.hamlib_mode),
"bandwidth": str(static.HAMLIB_BANDWIDTH), "bandwidth": str(HamlibParam.hamlib_bandwidth),
"fft": str(static.FFT), "fft": str(AudioParam.fft),
"channel_busy": str(static.CHANNEL_BUSY), "channel_busy": str(ModemParam.channel_busy),
"channel_busy_slot": str(static.CHANNEL_BUSY_SLOT), "channel_busy_slot": str(ModemParam.channel_busy_slot),
"is_codec2_traffic": str(static.IS_CODEC2_TRAFFIC), "is_codec2_traffic": str(ModemParam.is_codec2_traffic),
"scatter": static.SCATTER, "scatter": ModemParam.scatter,
"rx_buffer_length": str(RX_BUFFER.qsize()), "rx_buffer_length": str(RX_BUFFER.qsize()),
"rx_msg_buffer_length": str(len(static.RX_MSG_BUFFER)), "rx_msg_buffer_length": str(len(ARQ.rx_msg_buffer)),
"arq_bytes_per_minute": str(static.ARQ_BYTES_PER_MINUTE), "arq_bytes_per_minute": str(ARQ.bytes_per_minute),
"arq_bytes_per_minute_burst": str(static.ARQ_BYTES_PER_MINUTE_BURST), "arq_bytes_per_minute_burst": str(ARQ.bytes_per_minute_burst),
"arq_seconds_until_finish": str(static.ARQ_SECONDS_UNTIL_FINISH), "arq_seconds_until_finish": str(ARQ.arq_seconds_until_finish),
"arq_compression_factor": str(static.ARQ_COMPRESSION_FACTOR), "arq_compression_factor": str(ARQ.arq_compression_factor),
"arq_transmission_percent": str(static.ARQ_TRANSMISSION_PERCENT), "arq_transmission_percent": str(ARQ.arq_transmission_percent),
"speed_list": static.SPEED_LIST, "speed_list": ARQ.speed_list,
"total_bytes": str(static.TOTAL_BYTES), "total_bytes": str(ARQ.total_bytes),
"beacon_state": str(static.BEACON_STATE), "beacon_state": str(Beacon.beacon_state),
"stations": [], "stations": [],
"mycallsign": str(static.MYCALLSIGN, encoding), "mycallsign": str(Station.mycallsign, encoding),
"mygrid": str(static.MYGRID, encoding), "mygrid": str(Station.mygrid, encoding),
"dxcallsign": str(static.DXCALLSIGN, encoding), "dxcallsign": str(Station.dxcallsign, encoding),
"dxgrid": str(static.DXGRID, encoding), "dxgrid": str(Station.dxgrid, encoding),
"hamlib_status": static.HAMLIB_STATUS, "hamlib_status": HamlibParam.hamlib_status,
"listen": str(static.LISTEN), "listen": str(TNC.listen),
"audio_recording": str(static.AUDIO_RECORD), "audio_recording": str(AudioParam.audio_record),
} }
# add heard stations to heard stations object # add heard stations to heard stations object
for heard in static.HEARD_STATIONS: for heard in TNC.heard_stations:
output["stations"].append( output["stations"].append(
{ {
"dxcallsign": str(heard[0], "utf-8"), "dxcallsign": str(heard[0], encoding),
"dxgrid": str(heard[1], "utf-8"), "dxgrid": str(heard[1], encoding),
"timestamp": heard[2], "timestamp": heard[2],
"datatype": heard[3], "datatype": heard[3],
"snr": heard[4], "snr": heard[4],

View file

@ -5,143 +5,144 @@ Created on Wed Dec 23 11:13:57 2020
@author: DJ2LS @author: DJ2LS
Here we are saving application wide variables and stats, which have to be accessed everywhere. 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 dataclasses import dataclass, field
from typing import List from typing import List
import subprocess import subprocess
from enum import Enum 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' # CHANNEL_STATE = 'RECEIVING_SIGNALLING'
TNC_STATE: str = "IDLE"
ARQ_STATE: bool = False
ARQ_SESSION: bool = False
# disconnected, connecting, connected, disconnecting, failed # disconnected, connecting, connected, disconnecting, failed
ARQ_SESSION_STATE: str = "disconnected"
# BEACON STATE
BEACON_STATE: bool = False
BEACON_PAUSE: bool = False
# ------- RX BUFFER # ------- RX BUFFER
RX_MSG_BUFFER: list = []
RX_BURST_BUFFER: list = []
RX_FRAME_BUFFER: bytes = b""
RX_BUFFER_SIZE: int = 16
# ------- HEARD STATIONS BUFFER @dataclass
HEARD_STATIONS: list = [] 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 @dataclass
TUNING_RANGE_FMIN: float = -50.0 class AudioParam:
TUNING_RANGE_FMAX: float = 50.0 tx_audio_level: int = 50
IS_CODEC2_TRAFFIC: bool = False # true if we have codec2 signalling mode traffic on channel 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): class FRAME_TYPE(Enum):
@ -176,50 +177,3 @@ class FRAME_TYPE(Enum):
IDENT = 254 IDENT = 254
TEST_FRAME = 255 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 ujson as json
import structlog import structlog
import static 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") log = structlog.get_logger("stats")
@ -26,29 +26,29 @@ class stats():
crcerror = status in ["crc_error", "wrong_crc"] crcerror = status in ["crc_error", "wrong_crc"]
# get avg snr # get avg snr
try: 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 ) avg_snr = round(sum(snr_raw) / len(snr_raw), 2 )
except Exception: except Exception:
avg_snr = 0 avg_snr = 0
headers = {"Content-Type": "application/json"} headers = {"Content-Type": "application/json"}
station_data = { station_data = {
'callsign': str(static.MYCALLSIGN, "utf-8"), 'callsign': str(Station.mycallsign, "utf-8"),
'dxcallsign': str(static.DXCALLSIGN, "utf-8"), 'dxcallsign': str(Station.dxcallsign, "utf-8"),
'gridsquare': str(static.MYGRID, "utf-8"), 'gridsquare': str(Station.mygrid, "utf-8"),
'dxgridsquare': str(static.DXGRID, "utf-8"), 'dxgridsquare': str(Station.dxgrid, "utf-8"),
'frequency': 0 if static.HAMLIB_FREQUENCY is None else static.HAMLIB_FREQUENCY, 'frequency': 0 if HamlibParam.hamlib_frequency is None else HamlibParam.hamlib_frequency,
'avgstrength': 0, 'avgstrength': 0,
'avgsnr': avg_snr, 'avgsnr': avg_snr,
'bytesperminute': static.ARQ_BYTES_PER_MINUTE, 'bytesperminute': ARQ.bytes_per_minute,
'filesize': static.TOTAL_BYTES, 'filesize': ARQ.total_bytes,
'compressionfactor': static.ARQ_COMPRESSION_FACTOR, 'compressionfactor': ARQ.arq_compression_factor,
'nacks': frame_nack_counter, 'nacks': frame_nack_counter,
'crcerror': crcerror, 'crcerror': crcerror,
'duration': duration, 'duration': duration,
'percentage': static.ARQ_TRANSMISSION_PERCENT, 'percentage': ARQ.arq_transmission_percent,
'status': status, 'status': status,
'version': static.VERSION 'version': TNC.version
} }
station_data = json.dumps(station_data) station_data = json.dumps(station_data)

View file

@ -7,9 +7,9 @@ import websocket
import numpy as np import numpy as np
import time import time
from queues import AUDIO_TRANSMIT_QUEUE, AUDIO_RECEIVED_QUEUE 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): def __init__(self, hostname='127.0.0.1', port=50001):
# websocket.enableTrace(True) # websocket.enableTrace(True)
self.log = structlog.get_logger("TCI") self.log = structlog.get_logger("TCI")