From 69749d30aebdb1b03fc53ed4dcd28702730b93fb Mon Sep 17 00:00:00 2001 From: DJ2LS Date: Thu, 27 Apr 2023 21:43:56 +0200 Subject: [PATCH] updated dataclasses --- test/test_helpers.py | 6 +- test/test_tnc_states.py | 66 +-- test/util_chat_text_1.py | 34 +- test/util_chat_text_2.py | 28 +- test/util_datac13.py | 28 +- test/util_datac13_negative.py | 54 +-- tnc/daemon.py | 17 +- tnc/data_handler.py | 876 +++++++++++++++++----------------- tnc/explorer.py | 18 +- tnc/helpers.py | 22 +- tnc/main.py | 128 ++--- tnc/modem.py | 220 ++++----- tnc/queues.py | 4 +- tnc/rigctld.py | 7 +- tnc/sock.py | 196 ++++---- tnc/static.py | 294 +++++------- tnc/stats.py | 24 +- tnc/tci.py | 4 +- 18 files changed, 988 insertions(+), 1038 deletions(-) diff --git a/test/test_helpers.py b/test/test_helpers.py index 49186b7a..7fc8d3db 100644 --- a/test/test_helpers.py +++ b/test/test_helpers.py @@ -14,7 +14,7 @@ import sys import helpers import pytest -import static +from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC @pytest.mark.parametrize("callsign", ["AA1AA", "DE2DE", "E4AWQ-4"]) @@ -22,7 +22,7 @@ def test_check_callsign(callsign: str): """ Execute test to demonstrate how to create and verify callsign checksums. """ - static.SSID_LIST = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + Station.ssid_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] t_callsign_bytes = helpers.callsign_to_bytes(callsign) t_callsign = helpers.bytes_to_callsign(t_callsign_bytes) @@ -41,7 +41,7 @@ def test_callsign_to_bytes(callsign: str): """ Execute test to demonsrate symmetry when converting callsigns to and from byte arrays. """ - static.SSID_LIST = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + Station.ssid_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] t_callsign_crc = helpers.get_crc_24(bytes(callsign, "UTF-8")) t_callsign_bytes = helpers.callsign_to_bytes(callsign) diff --git a/test/test_tnc_states.py b/test/test_tnc_states.py index a5365b90..d4aab6dc 100644 --- a/test/test_tnc_states.py +++ b/test/test_tnc_states.py @@ -26,7 +26,7 @@ sys.path.insert(0, "..") sys.path.insert(0, "../tnc") import data_handler import helpers -import static +from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC def print_frame(data: bytearray): @@ -148,18 +148,18 @@ def t_foreign_disconnect(mycall: str, dxcall: str): :rtype: bytearray """ # Set the SSIDs we'll use for this test. - static.SSID_LIST = [0, 1, 2, 3, 4] + Station.ssid_list = [0, 1, 2, 3, 4] # Setup the static parameters for the connection. mycallsign_bytes = helpers.callsign_to_bytes(mycall) mycallsign = helpers.bytes_to_callsign(mycallsign_bytes) - static.MYCALLSIGN = mycallsign - static.MYCALLSIGN_CRC = helpers.get_crc_24(mycallsign) + Station.mycallsign = mycallsign + Station.mycallsign_crc = helpers.get_crc_24(mycallsign) dxcallsign_bytes = helpers.callsign_to_bytes(dxcall) dxcallsign = helpers.bytes_to_callsign(dxcallsign_bytes) - static.DXCALLSIGN = dxcallsign - static.DXCALLSIGN_CRC = helpers.get_crc_24(dxcallsign) + Station.dxcallsign = dxcallsign + Station.dxcallsign_crc = helpers.get_crc_24(dxcallsign) # Create the TNC tnc = data_handler.DATA() @@ -173,12 +173,12 @@ def t_foreign_disconnect(mycall: str, dxcall: str): print_frame(create_frame) tnc.received_session_opener(create_frame) - assert helpers.callsign_to_bytes(static.MYCALLSIGN) == mycallsign_bytes - assert helpers.callsign_to_bytes(static.DXCALLSIGN) == dxcallsign_bytes + assert helpers.callsign_to_bytes(Station.mycallsign) == mycallsign_bytes + assert helpers.callsign_to_bytes(Station.dxcallsign) == dxcallsign_bytes - assert static.ARQ_SESSION is True - assert static.TNC_STATE == "BUSY" - assert static.ARQ_SESSION_STATE == "connecting" + assert ARQ.arq_session is True + assert TNC.tnc_state == "BUSY" + assert ARQ.arq_session_state == "connecting" # Set up a frame from a non-associated station. # foreigncall_bytes = helpers.callsign_to_bytes("ZZ0ZZ-0") @@ -193,8 +193,8 @@ def t_foreign_disconnect(mycall: str, dxcall: str): print_frame(close_frame) # assert ( - # helpers.check_callsign(static.DXCALLSIGN, bytes(close_frame[4:7]))[0] is False - # ), f"{helpers.get_crc_24(static.DXCALLSIGN)} == {bytes(close_frame[4:7])} but should be not equal." + # helpers.check_callsign(Station.dxcallsign, bytes(close_frame[4:7]))[0] is False + # ), f"{helpers.get_crc_24(Station.dxcallsign)} == {bytes(close_frame[4:7])} but should be not equal." # assert ( # helpers.check_callsign(foreigncall, bytes(close_frame[4:7]))[0] is True @@ -203,16 +203,16 @@ def t_foreign_disconnect(mycall: str, dxcall: str): # Send the non-associated session close frame to the TNC tnc.received_session_close(close_frame) - assert helpers.callsign_to_bytes(static.MYCALLSIGN) == helpers.callsign_to_bytes( + assert helpers.callsign_to_bytes(Station.mycallsign) == helpers.callsign_to_bytes( mycall - ), f"{static.MYCALLSIGN} != {mycall} but should equal." - assert helpers.callsign_to_bytes(static.DXCALLSIGN) == helpers.callsign_to_bytes( + ), f"{Station.mycallsign} != {mycall} but should equal." + assert helpers.callsign_to_bytes(Station.dxcallsign) == helpers.callsign_to_bytes( dxcall - ), f"{static.DXCALLSIGN} != {dxcall} but should equal." + ), f"{Station.dxcallsign} != {dxcall} but should equal." - assert static.ARQ_SESSION is True - assert static.TNC_STATE == "BUSY" - assert static.ARQ_SESSION_STATE == "connecting" + assert ARQ.arq_session is True + assert TNC.tnc_state == "BUSY" + assert ARQ.arq_session_state == "connecting" def t_valid_disconnect(mycall: str, dxcall: str): @@ -228,18 +228,18 @@ def t_valid_disconnect(mycall: str, dxcall: str): :rtype: bytearray """ # Set the SSIDs we'll use for this test. - static.SSID_LIST = [0, 1, 2, 3, 4] + Station.ssid_list = [0, 1, 2, 3, 4] # Setup the static parameters for the connection. mycallsign_bytes = helpers.callsign_to_bytes(mycall) mycallsign = helpers.bytes_to_callsign(mycallsign_bytes) - static.MYCALLSIGN = mycallsign - static.MYCALLSIGN_CRC = helpers.get_crc_24(mycallsign) + Station.mycallsign = mycallsign + Station.mycallsign_crc = helpers.get_crc_24(mycallsign) dxcallsign_bytes = helpers.callsign_to_bytes(dxcall) dxcallsign = helpers.bytes_to_callsign(dxcallsign_bytes) - static.DXCALLSIGN = dxcallsign - static.DXCALLSIGN_CRC = helpers.get_crc_24(dxcallsign) + Station.dxcallsign = dxcallsign + Station.dxcallsign_crc = helpers.get_crc_24(dxcallsign) # Create the TNC tnc = data_handler.DATA() @@ -253,9 +253,9 @@ def t_valid_disconnect(mycall: str, dxcall: str): print_frame(create_frame) tnc.received_session_opener(create_frame) - assert static.ARQ_SESSION is True - assert static.TNC_STATE == "BUSY" - assert static.ARQ_SESSION_STATE == "connecting" + assert ARQ.arq_session is True + assert TNC.tnc_state == "BUSY" + assert ARQ.arq_session_state == "connecting" # Create packet to be 'received' by this station. # close_frame = t_create_session_close_old(mycall=dxcall, dxcall=mycall) @@ -267,12 +267,12 @@ def t_valid_disconnect(mycall: str, dxcall: str): print_frame(close_frame) tnc.received_session_close(close_frame) - assert helpers.callsign_to_bytes(static.MYCALLSIGN) == mycallsign_bytes - assert helpers.callsign_to_bytes(static.DXCALLSIGN) == dxcallsign_bytes + assert helpers.callsign_to_bytes(Station.mycallsign) == mycallsign_bytes + assert helpers.callsign_to_bytes(Station.dxcallsign) == dxcallsign_bytes - assert static.ARQ_SESSION is False - assert static.TNC_STATE == "IDLE" - assert static.ARQ_SESSION_STATE == "disconnected" + assert ARQ.arq_session is False + assert TNC.tnc_state == "IDLE" + assert ARQ.arq_session_state == "disconnected" # These tests are pushed into separate processes as a workaround. These tests diff --git a/test/util_chat_text_1.py b/test/util_chat_text_1.py index d89dd364..444f5460 100644 --- a/test/util_chat_text_1.py +++ b/test/util_chat_text_1.py @@ -22,7 +22,7 @@ import data_handler import helpers import modem import sock -import static +from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC import structlog @@ -39,23 +39,23 @@ def t_setup( modem.RXCHANNEL = tmp_path / "hfchannel1" modem.TESTMODE = True modem.TXCHANNEL = tmp_path / "hfchannel2" - static.HAMLIB_RADIOCONTROL = "disabled" - static.LOW_BANDWIDTH_MODE = lowbwmode - static.MYGRID = bytes("AA12aa", "utf-8") - static.RESPOND_TO_CQ = True - static.SSID_LIST = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + HamlibParam.hamlib_radiocontrol = "disabled" + TNC.low_bandwidth_mode = lowbwmode + Station.mygrid = bytes("AA12aa", "utf-8") + TNC.respond_to_cq = True + Station.ssid_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # override ARQ SESSION STATE for allowing disconnect command - static.ARQ_SESSION_STATE = "connected" + ARQ.arq_session_state = "connected" mycallsign = helpers.callsign_to_bytes(mycall) mycallsign = helpers.bytes_to_callsign(mycallsign) - static.MYCALLSIGN = mycallsign - static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN) + Station.mycallsign = mycallsign + Station.mycallsign_crc = helpers.get_crc_24(Station.mycallsign) dxcallsign = helpers.callsign_to_bytes(dxcall) dxcallsign = helpers.bytes_to_callsign(dxcallsign) - static.DXCALLSIGN = dxcallsign - static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN) + Station.dxcallsign = dxcallsign + Station.dxcallsign_crc = helpers.get_crc_24(Station.dxcallsign) # Create the TNC tnc = data_handler.DATA() @@ -105,7 +105,7 @@ def t_highsnr_arq_short_station1( log.info("S1 TX: ", mode=static.FRAME_TYPE(frametype).name) if ( - static.LOW_BANDWIDTH_MODE + TNC.low_bandwidth_mode and frametype == static.FRAME_TYPE.ARQ_DC_OPEN_W.value ): mesg = ( @@ -116,7 +116,7 @@ def t_highsnr_arq_short_station1( log.error(mesg) assert False, mesg if ( - not static.LOW_BANDWIDTH_MODE + not TNC.low_bandwidth_mode and frametype == static.FRAME_TYPE.ARQ_DC_OPEN_N.value ): mesg = ( @@ -184,23 +184,23 @@ def t_highsnr_arq_short_station1( log.warning("station1 TIMEOUT", first=True) break time.sleep(0.1) - log.info("station1, first", arq_state=pformat(static.ARQ_STATE)) + log.info("station1, first", arq_state=pformat(ARQ.arq_state)) data = {"type": "arq", "command": "disconnect", "dxcallsign": dxcall} sock.process_tnc_commands(json.dumps(data, indent=None)) time.sleep(0.5) # override ARQ SESSION STATE for allowing disconnect command - static.ARQ_SESSION_STATE = "connected" + ARQ.arq_session_state = "connected" sock.process_tnc_commands(json.dumps(data, indent=None)) # Allow enough time for this side to process the disconnect frame. timeout = time.time() + 20 - while static.ARQ_STATE or tnc.data_queue_transmit.queue: + while ARQ.arq_state or tnc.data_queue_transmit.queue: if time.time() > timeout: log.error("station1", TIMEOUT=True) break time.sleep(0.5) - log.info("station1", arq_state=pformat(static.ARQ_STATE)) + log.info("station1", arq_state=pformat(ARQ.arq_state)) # log.info("S1 DQT: ", DQ_Tx=pformat(tnc.data_queue_transmit.queue)) # log.info("S1 DQR: ", DQ_Rx=pformat(tnc.data_queue_received.queue)) diff --git a/test/util_chat_text_2.py b/test/util_chat_text_2.py index 72f44fce..77f2523b 100644 --- a/test/util_chat_text_2.py +++ b/test/util_chat_text_2.py @@ -19,7 +19,7 @@ import data_handler import helpers import modem import sock -import static +from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC import structlog @@ -36,23 +36,23 @@ def t_setup( modem.RXCHANNEL = tmp_path / "hfchannel2" modem.TESTMODE = True modem.TXCHANNEL = tmp_path / "hfchannel1" - static.HAMLIB_RADIOCONTROL = "disabled" - static.LOW_BANDWIDTH_MODE = lowbwmode - static.MYGRID = bytes("AA12aa", "utf-8") - static.RESPOND_TO_CQ = True - static.SSID_LIST = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + HamlibParam.hamlib_radiocontrol = "disabled" + TNC.low_bandwidth_mode = lowbwmode + Station.mygrid = bytes("AA12aa", "utf-8") + TNC.respond_to_cq = True + Station.ssid_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # override ARQ SESSION STATE for allowing disconnect command - static.ARQ_SESSION_STATE = "connected" + ARQ.arq_session_state = "connected" mycallsign = helpers.callsign_to_bytes(mycall) mycallsign = helpers.bytes_to_callsign(mycallsign) - static.MYCALLSIGN = mycallsign - static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN) + Station.mycallsign = mycallsign + Station.mycallsign_crc = helpers.get_crc_24(Station.mycallsign) dxcallsign = helpers.callsign_to_bytes(dxcall) dxcallsign = helpers.bytes_to_callsign(dxcallsign) - static.DXCALLSIGN = dxcallsign - static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN) + Station.dxcallsign = dxcallsign + Station.dxcallsign_crc = helpers.get_crc_24(Station.dxcallsign) # Create the TNC tnc = data_handler.DATA() @@ -136,13 +136,13 @@ def t_highsnr_arq_short_station2( # the queue to an object for comparisons. while ( '"arq":"transmission","status":"received"' not in str(sock.SOCKET_QUEUE.queue) - or static.ARQ_STATE + or ARQ.arq_state ): if time.time() > timeout: log.warning("station2 TIMEOUT", first=True) break time.sleep(0.5) - log.info("station2, first", arq_state=pformat(static.ARQ_STATE)) + log.info("station2, first", arq_state=pformat(ARQ.arq_state)) # Allow enough time for this side to receive the disconnect frame. timeout = time.time() + 20 @@ -151,7 +151,7 @@ def t_highsnr_arq_short_station2( log.warning("station2", TIMEOUT=True) break time.sleep(0.5) - log.info("station2", arq_state=pformat(static.ARQ_STATE)) + log.info("station2", arq_state=pformat(ARQ.arq_state)) # log.info("S2 DQT: ", DQ_Tx=pformat(tnc.data_queue_transmit.queue)) # log.info("S2 DQR: ", DQ_Rx=pformat(tnc.data_queue_received.queue)) diff --git a/test/util_datac13.py b/test/util_datac13.py index c43c3caf..377d00f6 100644 --- a/test/util_datac13.py +++ b/test/util_datac13.py @@ -21,9 +21,9 @@ import data_handler import helpers import modem import sock -import static +from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC, FRAME_TYPE as FR_TYPE import structlog -from static import FRAME_TYPE as FR_TYPE +#from static import FRAME_TYPE as FR_TYPE def t_setup( @@ -46,21 +46,21 @@ def t_setup( modem.RXCHANNEL = tmp_path / rx_channel modem.TESTMODE = True modem.TXCHANNEL = tmp_path / tx_channel - static.HAMLIB_RADIOCONTROL = "disabled" - static.LOW_BANDWIDTH_MODE = lowbwmode or True - static.MYGRID = bytes("AA12aa", "utf-8") - static.RESPOND_TO_CQ = True - static.SSID_LIST = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + HamlibParam.hamlib_radiocontrol = "disabled" + TNC.low_bandwidth_mode = lowbwmode or True + Station.mygrid = bytes("AA12aa", "utf-8") + Station.respond_to_cq = True + Station.ssid_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] mycallsign = helpers.callsign_to_bytes(mycall) mycallsign = helpers.bytes_to_callsign(mycallsign) - static.MYCALLSIGN = mycallsign - static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN) + Station.mycallsign = mycallsign + Station.mycallsign_crc = helpers.get_crc_24(Station.mycallsign) dxcallsign = helpers.callsign_to_bytes(dxcall) dxcallsign = helpers.bytes_to_callsign(dxcallsign) - static.DXCALLSIGN = dxcallsign - static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN) + Station.dxcallsign = dxcallsign + Station.dxcallsign_crc = helpers.get_crc_24(Station.dxcallsign) # Create the TNC tnc = data_handler.DATA() @@ -149,8 +149,8 @@ def t_datac13_1( time.sleep(0.5) if "stop" in data["command"]: log.debug("t_datac13_1: STOP test, setting TNC state") - static.TNC_STATE = "BUSY" - static.ARQ_STATE = True + TNC.tnc_state = "BUSY" + ARQ.arq_state = True sock.ThreadedTCPRequestHandler.process_tnc_commands(None,json.dumps(data, indent=None)) time.sleep(0.5) sock.ThreadedTCPRequestHandler.process_tnc_commands(None,json.dumps(data, indent=None)) @@ -169,7 +169,7 @@ def t_datac13_1( time.sleep(0.1) log.info("station1, first") # override ARQ SESSION STATE for allowing disconnect command - static.ARQ_SESSION_STATE = "connected" + ARQ.arq_session_state = "connected" data = {"type": "arq", "command": "disconnect", "dxcallsign": dxcall} sock.ThreadedTCPRequestHandler.process_tnc_commands(None,json.dumps(data, indent=None)) time.sleep(0.5) diff --git a/test/util_datac13_negative.py b/test/util_datac13_negative.py index f57020e5..57823abd 100644 --- a/test/util_datac13_negative.py +++ b/test/util_datac13_negative.py @@ -15,9 +15,9 @@ import data_handler import helpers import modem import sock -import static +from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC, FRAME_TYPE as FR_TYPE import structlog -from static import FRAME_TYPE as FR_TYPE +#from static import FRAME_TYPE as FR_TYPE def t_setup( @@ -40,21 +40,21 @@ def t_setup( modem.RXCHANNEL = tmp_path / rx_channel modem.TESTMODE = True modem.TXCHANNEL = tmp_path / tx_channel - static.HAMLIB_RADIOCONTROL = "disabled" - static.LOW_BANDWIDTH_MODE = lowbwmode or True - static.MYGRID = bytes("AA12aa", "utf-8") - static.RESPOND_TO_CQ = True - static.SSID_LIST = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + HamlibParam.hamlib_radiocontrol = "disabled" + TNC.low_bandwidth_mode = lowbwmode or True + Station.mygrid = bytes("AA12aa", "utf-8") + Station.respond_to_cq = True + Station.ssid_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + + mycallsign_bytes = helpers.callsign_to_bytes(mycall) + mycallsign = helpers.bytes_to_callsign(mycallsign_bytes) + Station.mycallsign = mycallsign + Station.mycallsign_crc = helpers.get_crc_24(mycallsign) - mycallsign = helpers.callsign_to_bytes(mycall) - mycallsign = helpers.bytes_to_callsign(mycallsign) - static.MYCALLSIGN = mycallsign - static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN) - - dxcallsign = helpers.callsign_to_bytes(dxcall) - dxcallsign = helpers.bytes_to_callsign(dxcallsign) - static.DXCALLSIGN = dxcallsign - static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN) + dxcallsign_bytes = helpers.callsign_to_bytes(dxcall) + dxcallsign = helpers.bytes_to_callsign(dxcallsign_bytes) + Station.dxcallsign = dxcallsign + Station.dxcallsign_crc = helpers.get_crc_24(dxcallsign) # Create the TNC tnc = data_handler.DATA() @@ -140,18 +140,18 @@ def t_datac13_1( log.info("t_datac13_1:", RXCHANNEL=modem.RXCHANNEL) log.info("t_datac13_1:", TXCHANNEL=modem.TXCHANNEL) - orig_dxcall = static.DXCALLSIGN + orig_dxcall = Station.dxcallsign if "stop" in data["command"]: time.sleep(0.5) log.debug( "t_datac13_1: STOP test, setting TNC state", - mycall=static.MYCALLSIGN, - dxcall=static.DXCALLSIGN, + mycall=Station.mycallsign, + dxcall=Station.dxcallsign, ) - static.DXCALLSIGN = helpers.callsign_to_bytes(data["dxcallsign"]) - static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN) - static.TNC_STATE = "BUSY" - static.ARQ_STATE = True + Station.dxcallsign = helpers.callsign_to_bytes(data["dxcallsign"]) + Station.dxcallsign_CRC = helpers.get_crc_24(Station.dxcallsign) + TNC.tnc_state = "BUSY" + ARQ.arq_state = True sock.ThreadedTCPRequestHandler.process_tnc_commands(None,json.dumps(data, indent=None)) sock.ThreadedTCPRequestHandler.process_tnc_commands(None,json.dumps(data, indent=None)) @@ -172,10 +172,10 @@ def t_datac13_1( if "stop" in data["command"]: time.sleep(0.5) log.debug("STOP test, resetting DX callsign") - static.DXCALLSIGN = orig_dxcall - static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN) + Station.dxcallsign = orig_dxcall + Station.dxcallsign_CRC = helpers.get_crc_24(Station.dxcallsign) # override ARQ SESSION STATE for allowing disconnect command - static.ARQ_SESSION_STATE = "connected" + ARQ.arq_session_state = "connected" data = {"type": "arq", "command": "disconnect", "dxcallsign": dxcall} sock.ThreadedTCPRequestHandler.process_tnc_commands(None,json.dumps(data, indent=None)) time.sleep(0.5) @@ -266,7 +266,7 @@ def t_datac13_2( log.info("t_datac13_2:", RXCHANNEL=modem.RXCHANNEL) log.info("t_datac13_2:", TXCHANNEL=modem.TXCHANNEL) - log.info("t_datac13_2:", mycall=static.MYCALLSIGN) + log.info("t_datac13_2:", mycall=Station.mycallsign) if "cq" in data: t_data = {"type": "arq", "command": "stop_transmission"} diff --git a/tnc/daemon.py b/tnc/daemon.py index 9fdbe64a..bccca86e 100755 --- a/tnc/daemon.py +++ b/tnc/daemon.py @@ -26,8 +26,7 @@ import crcengine import log_handler import serial.tools.list_ports import sock -import static -from static import ARQ, Audio, Beacon, Channel, Daemon, Hamlib, Modem, Station, TCI, TNC +from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC import structlog import ujson as json @@ -84,10 +83,10 @@ class DAEMON: """ while True: try: - if not static.TNCSTARTED: + if not Daemon.tncstarted: ( - static.AUDIO_INPUT_DEVICES, - static.AUDIO_OUTPUT_DEVICES, + AudioParam.audio_input_devices, + AudioParam.audio_output_devices, ) = audio.get_audio_devices() except Exception as err1: self.log.error( @@ -114,7 +113,7 @@ class DAEMON: {"port": str(port), "description": str(description)} ) - static.SERIAL_DEVICES = serial_devices + Daemon.serial_devices = serial_devices threading.Event().wait(1) except Exception as err1: self.log.error( @@ -319,8 +318,8 @@ class DAEMON: self.log.info("[DMN] TNC started", path="source") - static.TNCPROCESS = proc - static.TNCSTARTED = True + Daemon.tncprocess = proc + Daemon.tncstarted = True if __name__ == "__main__": mainlog = structlog.get_logger(__file__) # we need to run this on Windows for multiprocessing support @@ -369,7 +368,7 @@ if __name__ == "__main__": # https://stackoverflow.com/a/16641793 socketserver.TCPServer.allow_reuse_address = True cmdserver = sock.ThreadedTCPServer( - (static.HOST, DAEMON.port), sock.ThreadedTCPRequestHandler + (TNC.host, DAEMON.port), sock.ThreadedTCPRequestHandler ) server_thread = threading.Thread(target=cmdserver.serve_forever) server_thread.daemon = True diff --git a/tnc/data_handler.py b/tnc/data_handler.py index f7e0d6e3..42ad520c 100644 --- a/tnc/data_handler.py +++ b/tnc/data_handler.py @@ -22,7 +22,7 @@ import modem import numpy as np import sock import static -from static import ARQ, Audio, Beacon, Channel, Daemon, Hamlib, Modem, Station, TCI, TNC +from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC import structlog import stats import ujson as json @@ -45,8 +45,8 @@ class DATA: self.stats = stats.stats() # Initial call sign. Will be overwritten later - self.mycallsign = static.MYCALLSIGN - self.dxcallsign = static.DXCALLSIGN + self.mycallsign = Station.mycallsign + self.dxcallsign = Station.dxcallsign self.data_queue_transmit = DATA_QUEUE_TRANSMIT self.data_queue_received = DATA_QUEUE_RECEIVED @@ -142,7 +142,7 @@ class DATA: # Mode list for selecting between low bandwidth ( 500Hz ) and modes with higher bandwidth # but ability to fall back to low bandwidth modes if needed. - if static.LOW_BANDWIDTH_MODE: + if TNC.low_bandwidth_mode: # List of codec2 modes to use in "low bandwidth" mode. self.mode_list = self.mode_list_low_bw # list of times to wait for corresponding mode in seconds @@ -155,7 +155,7 @@ class DATA: self.time_list = self.time_list_high_bw self.speed_level = len(self.mode_list) - 1 # speed level for selecting mode - static.ARQ_SPEED_LEVEL = self.speed_level + ARQ.arq_speed_level = self.speed_level # minimum payload for arq burst # import for avoiding byteorder bug and buffer search area @@ -272,10 +272,10 @@ class DATA: # stuck in IRS # # send transmission queued information once - if static.ARQ_STATE or static.IS_CODEC2_TRAFFIC: + if ARQ.arq_state or ModemParam.is_codec2_traffic: self.log.debug( "[TNC] TX DISPATCHER - waiting with processing command ", - arq_state=static.ARQ_STATE, + arq_state=ARQ.arq_state, ) self.send_data_to_socket_queue( @@ -285,7 +285,7 @@ class DATA: ) # now stay in while loop until state released - while static.ARQ_STATE or static.IS_CODEC2_TRAFFIC: + while ARQ.arq_state or ModemParam.is_codec2_traffic: threading.Event().wait(0.01) # and finally sleep some time @@ -313,9 +313,9 @@ class DATA: # [2] STATE bool if data[2]: self.beacon_interval = data[1] - static.BEACON_STATE = True + Beacon.beacon_state = True else: - static.BEACON_STATE = False + Beacon.beacon_state = False elif data[0] == "ARQ_RAW": # [1] DATA_OUT bytes @@ -413,7 +413,7 @@ class DATA: # get snr of received data # FIXME: find a fix for this - after moving to classes, this no longer works # snr = self.calculate_snr(freedv) - snr = static.SNR + snr = ModemParam.snr self.log.debug("[TNC] RX SNR", snr=snr) # send payload data to arq checker without CRC16 self.arq_data_received( @@ -421,7 +421,7 @@ class DATA: ) # if we received the last frame of a burst or the last remaining rpt frame, do a modem unsync - # if static.RX_BURST_BUFFER.count(None) <= 1 or (frame+1) == n_frames_per_burst: + # if ARQ.rx_burst_buffer.count(None) <= 1 or (frame+1) == n_frames_per_burst: # self.log.debug(f"[TNC] LAST FRAME OF BURST --> UNSYNC {frame+1}/{n_frames_per_burst}") # self.c_lib.freedv_set_sync(freedv, 0) @@ -470,11 +470,11 @@ class DATA: # Set the TRANSMITTING flag before adding an object to the transmit queue # TODO: This is not that nice, we could improve this somehow - static.TRANSMITTING = True + TNC.transmitting = True modem.MODEM_TRANSMIT_QUEUE.put([c2_mode, copies, repeat_delay, frame_to_tx]) # Wait while transmitting - while static.TRANSMITTING: + while TNC.transmitting: threading.Event().wait(0.01) def send_data_to_socket_queue(self, **jsondata): @@ -491,8 +491,8 @@ class DATA: uuid=self.transmission_uuid, timestamp=timestamp, mycallsign=str(self.mycallsign, "UTF-8"), - dxcallsign=str(static.DXCALLSIGN, "UTF-8"), - dxgrid=str(static.DXGRID, "UTF-8"), + dxcallsign=str(Station.dxcallsign, "UTF-8"), + dxgrid=str(Station.dxgrid, "UTF-8"), data=base64_data, ) """ @@ -503,7 +503,7 @@ class DATA: if "mycallsign" not in jsondata: jsondata["mycallsign"] = str(self.mycallsign, "UTF-8") if "dxcallsign" not in jsondata: - jsondata["dxcallsign"] = str(static.DXCALLSIGN, "UTF-8") + jsondata["dxcallsign"] = str(Station.dxcallsign, "UTF-8") except Exception as e: self.log.debug("[TNC] error adding callsigns to network message", e=e) @@ -534,11 +534,11 @@ class DATA: ack_frame[1:2] = self.session_id ack_frame[2:3] = helpers.snr_to_bytes(snr) ack_frame[3:4] = bytes([int(self.speed_level)]) - ack_frame[4:8] = len(static.RX_FRAME_BUFFER).to_bytes(4, byteorder="big") + ack_frame[4:8] = len(ARQ.rx_frame_buffer).to_bytes(4, byteorder="big") # wait while timeout not reached and our busy state is busy channel_busy_timeout = time.time() + 5 - while static.CHANNEL_BUSY and time.time() < channel_busy_timeout and not self.check_if_mode_fits_to_busy_slot(): + while ModemParam.channel_busy and time.time() < channel_busy_timeout and not self.check_if_mode_fits_to_busy_slot(): threading.Event().wait(0.01) # Transmit frame @@ -554,7 +554,7 @@ class DATA: # wait while timeout not reached and our busy state is busy channel_busy_timeout = time.time() + 5 - while static.CHANNEL_BUSY and time.time() < channel_busy_timeout and not self.check_if_mode_fits_to_busy_slot(): + while ModemParam.channel_busy and time.time() < channel_busy_timeout and not self.check_if_mode_fits_to_busy_slot(): threading.Event().wait(0.01) # reset burst timeout in case we had to wait too long @@ -567,10 +567,10 @@ class DATA: def send_retransmit_request_frame(self) -> None: # check where a None is in our burst buffer and do frame+1, because lists start at 0 # FIXME: Check to see if there's a `frame - 1` in the receive portion. Remove both if there is. - print(static.RX_BURST_BUFFER) + print(ARQ.rx_burst_buffer) missing_frames = [ frame + 1 - for frame, element in enumerate(static.RX_BURST_BUFFER) + for frame, element in enumerate(ARQ.rx_burst_buffer) if element is None ] @@ -591,7 +591,7 @@ class DATA: nack_frame[1:2] = self.session_id nack_frame[2:3] = helpers.snr_to_bytes(snr) nack_frame[3:4] = bytes([int(self.speed_level)]) - nack_frame[4:8] = len(static.RX_FRAME_BUFFER).to_bytes(4, byteorder="big") + nack_frame[4:8] = len(ARQ.rx_frame_buffer).to_bytes(4, byteorder="big") # TRANSMIT NACK FRAME FOR BURST # TODO: Do we have to send ident frame? @@ -599,7 +599,7 @@ class DATA: # wait while timeout not reached and our busy state is busy channel_busy_timeout = time.time() + 5 - while static.CHANNEL_BUSY and time.time() < channel_busy_timeout and not self.check_if_mode_fits_to_busy_slot(): + while ModemParam.channel_busy and time.time() < channel_busy_timeout and not self.check_if_mode_fits_to_busy_slot(): threading.Event().wait(0.01) self.enqueue_frame_for_tx([nack_frame], c2_mode=FREEDV_MODE.sig1.value, copies=3, repeat_delay=0) @@ -613,7 +613,7 @@ class DATA: self.frame_nack_counter += 1 # we need to clear our rx burst buffer - static.RX_BURST_BUFFER = [] + ARQ.rx_burst_buffer = [] # Create and send ACK frame self.log.info("[TNC] ARQ | RX | SENDING NACK") @@ -626,7 +626,7 @@ class DATA: # wait while timeout not reached and our busy state is busy channel_busy_timeout = time.time() + 5 + 5 - while static.CHANNEL_BUSY and time.time() < channel_busy_timeout and not self.check_if_mode_fits_to_busy_slot(): + while ModemParam.channel_busy and time.time() < channel_busy_timeout and not self.check_if_mode_fits_to_busy_slot(): threading.Event().wait(0.01) # TRANSMIT NACK FRAME FOR BURST @@ -640,7 +640,7 @@ class DATA: disconnection_frame = bytearray(self.length_sig1_frame) disconnection_frame[:1] = bytes([FR_TYPE.ARQ_SESSION_CLOSE.value]) disconnection_frame[1:2] = self.session_id - disconnection_frame[2:5] = static.DXCALLSIGN_CRC + disconnection_frame[2:5] = Station.dxcallsign_crc # TODO: Needed? disconnection_frame[7:13] = helpers.callsign_to_bytes(self.mycallsign) # self.enqueue_frame_for_tx([disconnection_frame, self.send_ident_frame(False)], c2_mode=FREEDV_MODE.sig0.value, copies=5, repeat_delay=0) # TODO: We need to add the ident frame feature with a seperate PR after publishing latest protocol @@ -649,7 +649,7 @@ class DATA: # wait while timeout not reached and our busy state is busy channel_busy_timeout = time.time() + 5 - while static.CHANNEL_BUSY and time.time() < channel_busy_timeout and not self.check_if_mode_fits_to_busy_slot(): + while ModemParam.channel_busy and time.time() < channel_busy_timeout and not self.check_if_mode_fits_to_busy_slot(): threading.Event().wait(0.01) self.enqueue_frame_for_tx([disconnection_frame], c2_mode=FREEDV_MODE.sig0.value, copies=3, repeat_delay=0) @@ -671,15 +671,15 @@ class DATA: data_in = bytes(data_in) # only process data if we are in ARQ and BUSY state else return to quit - if not static.ARQ_STATE and static.TNC_STATE not in ["BUSY"]: - self.log.warning("[TNC] wrong tnc state - dropping data", arq_state=static.ARQ_STATE, - tnc_state=static.TNC_STATE) + if not ARQ.arq_state and TNC.tnc_state not in ["BUSY"]: + self.log.warning("[TNC] wrong tnc state - dropping data", arq_state=ARQ.arq_state, + tnc_state=TNC.tnc_state) return self.arq_file_transfer = True - static.TNC_STATE = "BUSY" - static.ARQ_STATE = True + TNC.tnc_state = "BUSY" + ARQ.arq_state = True # Update data_channel timestamp self.data_channel_last_received = int(time.time()) @@ -694,34 +694,34 @@ class DATA: # The RX burst buffer needs to have a fixed length filled with "None". # We need this later for counting the "Nones" to detect missing data. # Check if burst buffer has expected length else create it - if len(static.RX_BURST_BUFFER) != self.rx_n_frames_per_burst: - static.RX_BURST_BUFFER = [None] * self.rx_n_frames_per_burst + if len(ARQ.rx_burst_buffer) != self.rx_n_frames_per_burst: + ARQ.rx_burst_buffer = [None] * self.rx_n_frames_per_burst # Append data to rx burst buffer - static.RX_BURST_BUFFER[self.rx_n_frame_of_burst] = data_in[self.arq_burst_header_size:] # type: ignore + ARQ.rx_burst_buffer[self.rx_n_frame_of_burst] = data_in[self.arq_burst_header_size:] # type: ignore - static.DXGRID = b'------' + Station.dxgrid = b'------' helpers.add_to_heard_stations( - static.DXCALLSIGN, - static.DXGRID, + Station.dxcallsign, + Station.dxgrid, "DATA-CHANNEL", snr, - static.FREQ_OFFSET, - static.HAMLIB_FREQUENCY, + ModemParam.frequency_offset, + HamlibParam.hamlib_frequency, ) # Check if we received all frames in the burst by checking if burst buffer has no more "Nones" # This is the ideal case because we received all data - if None not in static.RX_BURST_BUFFER: + if None not in ARQ.rx_burst_buffer: # then iterate through burst buffer and stick the burst together # the temp burst buffer is needed for checking, if we already received data temp_burst_buffer = b"" - for value in static.RX_BURST_BUFFER: - # static.RX_FRAME_BUFFER += static.RX_BURST_BUFFER[i] + for value in ARQ.rx_burst_buffer: + # ARQ.rx_frame_buffer += ARQ.rx_burst_buffer[i] temp_burst_buffer += bytes(value) # type: ignore # free up burst buffer - static.RX_BURST_BUFFER = [] + ARQ.rx_burst_buffer = [] # TODO: Needs to be removed as soon as mode error is fixed # catch possible modem error which leads into false byteorder @@ -731,7 +731,7 @@ class DATA: # This might only work for datac1 and datac3 try: # area_of_interest = (modem.get_bytes_per_frame(self.mode_list[speed_level] - 1) -3) * 2 - if static.RX_FRAME_BUFFER.endswith(temp_burst_buffer[:246]) and len(temp_burst_buffer) >= 246: + if ARQ.rx_frame_buffer.endswith(temp_burst_buffer[:246]) and len(temp_burst_buffer) >= 246: self.log.warning( "[TNC] ARQ | RX | wrong byteorder received - dropping data" ) @@ -743,12 +743,12 @@ class DATA: ) self.log.debug("[TNC] temp_burst_buffer", buffer=temp_burst_buffer) - self.log.debug("[TNC] static.RX_FRAME_BUFFER", buffer=static.RX_FRAME_BUFFER) + self.log.debug("[TNC] ARQ.rx_frame_buffer", buffer=ARQ.rx_frame_buffer) # if frame buffer ends not with the current frame, we are going to append new data # if data already exists, we received the frame correctly, # but the ACK frame didn't receive its destination (ISS) - if static.RX_FRAME_BUFFER.endswith(temp_burst_buffer): + if ARQ.rx_frame_buffer.endswith(temp_burst_buffer): self.log.info( "[TNC] ARQ | RX | Frame already received - sending ACK again" ) @@ -757,13 +757,13 @@ class DATA: # Here we are going to search for our data in the last received bytes. # This reduces the chance we will lose the entire frame in the case of signalling frame loss - # static.RX_FRAME_BUFFER --> existing data + # ARQ.rx_frame_buffer --> existing data # temp_burst_buffer --> new data # search_area --> area where we want to search search_area = self.arq_burst_last_payload * self.rx_n_frames_per_burst - search_position = len(static.RX_FRAME_BUFFER) - search_area + search_position = len(ARQ.rx_frame_buffer) - search_area # if search position < 0, then search position = 0 search_position = max(0, search_position) @@ -773,12 +773,12 @@ class DATA: # we are going to only check position against minimum data frame payload # use case: receive data, which already contains received data # while the payload of data received before is shorter than actual payload - get_position = static.RX_FRAME_BUFFER[search_position:].rfind( + get_position = ARQ.rx_frame_buffer[search_position:].rfind( temp_burst_buffer[:self.arq_burst_minimum_payload] ) # if we find data, replace it at this position with the new data and strip it if get_position >= 0: - static.RX_FRAME_BUFFER = static.RX_FRAME_BUFFER[ + ARQ.rx_frame_buffer = ARQ.rx_frame_buffer[ : search_position + get_position ] self.log.warning( @@ -789,7 +789,7 @@ class DATA: else: self.log.debug("[TNC] ARQ | RX | appending data to buffer") - static.RX_FRAME_BUFFER += temp_burst_buffer + ARQ.rx_frame_buffer += temp_burst_buffer self.arq_burst_last_payload = len(temp_burst_buffer) @@ -805,8 +805,8 @@ class DATA: self.data_channel_last_received = int(time.time()) + 6 + 6 self.burst_last_received = int(time.time()) + 6 + 6 # Create and send ACK frame - self.log.info("[TNC] ARQ | RX | SENDING ACK", finished=static.ARQ_SECONDS_UNTIL_FINISH, - bytesperminute=static.ARQ_BYTES_PER_MINUTE) + self.log.info("[TNC] ARQ | RX | SENDING ACK", finished=ARQ.arq_seconds_until_finish, + bytesperminute=ARQ.bytes_per_minute) self.send_burst_ack_frame(snr) @@ -815,7 +815,7 @@ class DATA: # calculate statistics self.calculate_transfer_rate_rx( - self.rx_start_of_transmission, len(static.RX_FRAME_BUFFER) + self.rx_start_of_transmission, len(ARQ.rx_frame_buffer) ) # send a network message with information @@ -824,12 +824,12 @@ class DATA: arq="transmission", status="receiving", uuid=self.transmission_uuid, - percent=static.ARQ_TRANSMISSION_PERCENT, - bytesperminute=static.ARQ_BYTES_PER_MINUTE, - compression=static.ARQ_COMPRESSION_FACTOR, + percent=ARQ.arq_transmission_percent, + bytesperminute=ARQ.bytes_per_minute, + compression=ARQ.arq_compression_factor, mycallsign=str(self.mycallsign, 'UTF-8'), dxcallsign=str(self.dxcallsign, 'UTF-8'), - finished=static.ARQ_SECONDS_UNTIL_FINISH, + finished=ARQ.arq_seconds_until_finish, irs=helpers.bool_to_string(self.is_IRS) ) @@ -846,7 +846,7 @@ class DATA: # # ) # self.calculate_transfer_rate_rx( - # self.rx_start_of_transmission, len(static.RX_FRAME_BUFFER) + # self.rx_start_of_transmission, len(ARQ.rx_frame_buffer) # ) # elif self.rx_n_frame_of_burst not in [self.rx_n_frames_per_burst - 1]: @@ -872,8 +872,8 @@ class DATA: # We have a BOF and EOF flag in our data. If we received both we received our frame. # In case of loosing data, but we received already a BOF and EOF we need to make sure, we # received the complete last burst by checking it for Nones - bof_position = static.RX_FRAME_BUFFER.find(self.data_frame_bof) - eof_position = static.RX_FRAME_BUFFER.find(self.data_frame_eof) + bof_position = ARQ.rx_frame_buffer.find(self.data_frame_bof) + eof_position = ARQ.rx_frame_buffer.find(self.data_frame_eof) # get total bytes per transmission information as soon we received a frame with a BOF @@ -882,7 +882,7 @@ class DATA: if ( bof_position >= 0 and eof_position > 0 - and None not in static.RX_BURST_BUFFER + and None not in ARQ.rx_burst_buffer ): self.log.debug( "[TNC] arq_data_received:", @@ -893,14 +893,14 @@ class DATA: self.rx_frame_eof_received = True # Extract raw data from buffer - payload = static.RX_FRAME_BUFFER[ + payload = ARQ.rx_frame_buffer[ bof_position + len(self.data_frame_bof): eof_position ] # Get the data frame crc data_frame_crc = payload[:4] # 0:4 = 4 bytes # Get the data frame length frame_length = int.from_bytes(payload[4:8], "big") # 4:8 = 4 bytes - static.TOTAL_BYTES = frame_length + ARQ.total_bytes = frame_length # 8:9 = compression factor data_frame = payload[9:] @@ -926,19 +926,19 @@ class DATA: e="wrong crc", expected=data_frame_crc.hex(), received=data_frame_crc_received.hex(), - overflows=static.BUFFER_OVERFLOW_COUNTER, + overflows=AudioParam.buffer_overflow_counter, nacks=self.frame_nack_counter, duration=duration, - bytesperminute=static.ARQ_BYTES_PER_MINUTE, - compression=static.ARQ_COMPRESSION_FACTOR, + bytesperminute=ARQ.bytes_per_minute, + compression=ARQ.arq_compression_factor, data=data_frame, ) - if static.ENABLE_STATS: + if TNC.enable_stats: self.stats.push(frame_nack_counter=self.frame_nack_counter, status="wrong_crc", duration=duration) - self.log.info("[TNC] ARQ | RX | Sending NACK", finished=static.ARQ_SECONDS_UNTIL_FINISH, - bytesperminute=static.ARQ_BYTES_PER_MINUTE) + self.log.info("[TNC] ARQ | RX | Sending NACK", finished=ARQ.arq_seconds_until_finish, + bytesperminute=ARQ.bytes_per_minute) self.send_burst_nack_frame(snr) # Update arq_session timestamp @@ -948,17 +948,17 @@ class DATA: self.arq_cleanup() def arq_extract_statistics_from_data_frame(self, bof_position, eof_position): - payload = static.RX_FRAME_BUFFER[ + payload = ARQ.rx_frame_buffer[ bof_position + len(self.data_frame_bof): eof_position ] frame_length = int.from_bytes(payload[4:8], "big") # 4:8 4bytes - static.TOTAL_BYTES = frame_length + ARQ.total_bytes = frame_length compression_factor = int.from_bytes(payload[8:9], "big") # 4:8 4bytes # limit to max value of 255 compression_factor = np.clip(compression_factor, 0, 255) - static.ARQ_COMPRESSION_FACTOR = compression_factor / 10 + ARQ.arq_compression_factor = compression_factor / 10 self.calculate_transfer_rate_rx( - self.rx_start_of_transmission, len(static.RX_FRAME_BUFFER) + self.rx_start_of_transmission, len(ARQ.rx_frame_buffer) ) def check_if_mode_fits_to_busy_slot(self): @@ -970,10 +970,10 @@ class DATA: """ mode_name = FREEDV_MODE(self.mode_list[self.speed_level]).name mode_slots = FREEDV_MODE_USED_SLOTS[mode_name].value - if mode_slots in [static.CHANNEL_BUSY_SLOT]: + if mode_slots in [ModemParam.channel_busy_slot]: self.log.warning( "[TNC] busy slot detection", - slots=static.CHANNEL_BUSY_SLOT, + slots=ModemParam.channel_busy_slot, mode_slots=mode_slots, ) return False @@ -990,13 +990,13 @@ class DATA: # make sure new speed level isn't higher than available modes new_speed_level = min(self.speed_level + 1, len(self.mode_list) - 1) # check if actual snr is higher than minimum snr for next mode - if static.SNR >= self.snr_list[new_speed_level]: + if ModemParam.snr >= self.snr_list[new_speed_level]: self.speed_level = new_speed_level else: self.log.info("[TNC] ARQ | increasing speed level not possible because of SNR limit", - given_snr=static.SNR, + given_snr=ModemParam.snr, needed_snr=self.snr_list[new_speed_level] ) @@ -1004,7 +1004,7 @@ class DATA: if not self.check_if_mode_fits_to_busy_slot(): self.speed_level = 0 - static.ARQ_SPEED_LEVEL = self.speed_level + ARQ.arq_speed_level = self.speed_level # Update modes we are listening to self.set_listening_modes(False, True, self.mode_list[self.speed_level]) @@ -1017,14 +1017,14 @@ class DATA: # transmittion duration duration = time.time() - self.rx_start_of_transmission self.calculate_transfer_rate_rx( - self.rx_start_of_transmission, len(static.RX_FRAME_BUFFER) + self.rx_start_of_transmission, len(ARQ.rx_frame_buffer) ) self.log.info("[TNC] ARQ | RX | DATA FRAME SUCCESSFULLY RECEIVED", nacks=self.frame_nack_counter, - bytesperminute=static.ARQ_BYTES_PER_MINUTE, total_bytes=static.TOTAL_BYTES, duration=duration) + bytesperminute=ARQ.bytes_per_minute, total_bytes=ARQ.total_bytes, duration=duration) # Decompress the data frame data_frame_decompressed = lzma.decompress(data_frame) - static.ARQ_COMPRESSION_FACTOR = len(data_frame_decompressed) / len( + ARQ.arq_compression_factor = len(data_frame_decompressed) / len( data_frame ) data_frame = data_frame_decompressed @@ -1038,13 +1038,13 @@ class DATA: # check if RX_BUFFER isn't full if not RX_BUFFER.full(): # make sure we have always the correct buffer size - RX_BUFFER.maxsize = int(static.RX_BUFFER_SIZE) + RX_BUFFER.maxsize = int(ARQ.rx_buffer_size) else: # if full, free space by getting an item self.log.info( "[TNC] ARQ | RX | RX_BUFFER FULL - dropping old data", buffer_size=RX_BUFFER.qsize(), - maxsize=int(static.RX_BUFFER_SIZE) + maxsize=int(ARQ.rx_buffer_size) ) RX_BUFFER.get() @@ -1059,8 +1059,8 @@ class DATA: [ self.transmission_uuid, timestamp, - static.DXCALLSIGN, - static.DXGRID, + Station.dxcallsign, + Station.dxgrid, base64_data, ] ) @@ -1075,19 +1075,19 @@ class DATA: e=e, uuid=self.transmission_uuid, timestamp=timestamp, - dxcall=static.DXCALLSIGN, - dxgrid=static.DXGRID, + dxcall=Station.dxcallsign, + dxgrid=Station.dxgrid, data=base64_data ) - if static.ARQ_SAVE_TO_FOLDER: + if ARQ.arq_save_to_folder: try: self.save_data_to_folder( self.transmission_uuid, timestamp, self.mycallsign, - static.DXCALLSIGN, - static.DXGRID, + Station.dxcallsign, + Station.dxgrid, data_frame ) except Exception as e: @@ -1096,8 +1096,8 @@ class DATA: e=e, uuid=self.transmission_uuid, timestamp=timestamp, - dxcall=static.DXCALLSIGN, - dxgrid=static.DXGRID, + dxcall=Station.dxcallsign, + dxgrid=Station.dxgrid, data=base64_data ) @@ -1106,19 +1106,19 @@ class DATA: arq="transmission", status="received", uuid=self.transmission_uuid, - percent=static.ARQ_TRANSMISSION_PERCENT, - bytesperminute=static.ARQ_BYTES_PER_MINUTE, - compression=static.ARQ_COMPRESSION_FACTOR, + percent=ARQ.arq_transmission_percent, + bytesperminute=ARQ.bytes_per_minute, + compression=ARQ.arq_compression_factor, timestamp=timestamp, finished=0, mycallsign=str(self.mycallsign, "UTF-8"), - dxcallsign=str(static.DXCALLSIGN, "UTF-8"), - dxgrid=str(static.DXGRID, "UTF-8"), + dxcallsign=str(Station.dxcallsign, "UTF-8"), + dxgrid=str(Station.dxgrid, "UTF-8"), data=base64_data, irs=helpers.bool_to_string(self.is_IRS) ) - if static.ENABLE_STATS: + if TNC.enable_stats: duration = time.time() - self.rx_start_of_transmission self.stats.push(frame_nack_counter=self.frame_nack_counter, status="received", duration=duration) @@ -1128,14 +1128,14 @@ class DATA: self.send_data_ack_frame(snr) # Update statistics AFTER the frame ACK is sent self.calculate_transfer_rate_rx( - self.rx_start_of_transmission, len(static.RX_FRAME_BUFFER) + self.rx_start_of_transmission, len(ARQ.rx_frame_buffer) ) self.log.info( "[TNC] | RX | DATACHANNEL [" + str(self.mycallsign, "UTF-8") + "]<< >>[" - + str(static.DXCALLSIGN, "UTF-8") + + str(Station.dxcallsign, "UTF-8") + "]", snr=snr, ) @@ -1160,25 +1160,25 @@ class DATA: # Maximum number of retries to send before declaring a frame is lost # save len of data_out to TOTAL_BYTES for our statistics - static.TOTAL_BYTES = len(data_out) + ARQ.total_bytes = len(data_out) self.arq_file_transfer = True frame_total_size = len(data_out).to_bytes(4, byteorder="big") # Compress data frame data_frame_compressed = lzma.compress(data_out) compression_factor = len(data_out) / len(data_frame_compressed) - static.ARQ_COMPRESSION_FACTOR = np.clip(compression_factor, 0, 255) - compression_factor = bytes([int(static.ARQ_COMPRESSION_FACTOR * 10)]) + ARQ.arq_compression_factor = np.clip(compression_factor, 0, 255) + compression_factor = bytes([int(ARQ.arq_compression_factor * 10)]) self.send_data_to_socket_queue( freedata="tnc-message", arq="transmission", status="transmitting", uuid=self.transmission_uuid, - percent=static.ARQ_TRANSMISSION_PERCENT, - bytesperminute=static.ARQ_BYTES_PER_MINUTE, - compression=static.ARQ_COMPRESSION_FACTOR, - finished=static.ARQ_SECONDS_UNTIL_FINISH, + percent=ARQ.arq_transmission_percent, + bytesperminute=ARQ.bytes_per_minute, + compression=ARQ.arq_compression_factor, + finished=ARQ.arq_seconds_until_finish, mycallsign=str(self.mycallsign, 'UTF-8'), dxcallsign=str(self.dxcallsign, 'UTF-8'), irs=helpers.bool_to_string(self.is_IRS) @@ -1186,7 +1186,7 @@ class DATA: self.log.info( "[TNC] | TX | DATACHANNEL", - Bytes=static.TOTAL_BYTES, + Bytes=ARQ.total_bytes, ) data_out = data_frame_compressed @@ -1215,7 +1215,7 @@ class DATA: bufferposition_burst_start = 0 # Iterate through data_out buffer - while not self.data_frame_ack_received and static.ARQ_STATE: + while not self.data_frame_ack_received and ARQ.arq_state: # we have self.tx_n_max_retries_per_burst attempts for sending a burst for self.tx_n_retry_of_burst in range(self.tx_n_max_retries_per_burst): # Bound speed level to: @@ -1224,7 +1224,7 @@ class DATA: self.speed_level = min(self.speed_level, len(self.mode_list) - 1) self.speed_level = max(self.speed_level, 0) - static.ARQ_SPEED_LEVEL = self.speed_level + ARQ.arq_speed_level = self.speed_level data_mode = self.mode_list[self.speed_level] self.log.debug( @@ -1274,7 +1274,7 @@ class DATA: self.log.error("[TNC] ----- data buffer offset:", iss_buffer_pos=bufferposition, irs_bufferposition=self.irs_buffer_position) # only adjust buffer position for experimental versions - if 'exp' in static.VERSION: + if 'exp' in TNC.version: self.log.warning("[TNC] ----- data adjustment disabled!") # bufferposition = self.irs_buffer_position @@ -1312,7 +1312,7 @@ class DATA: # After transmission finished, wait for an ACK or RPT frame while ( - static.ARQ_STATE + ARQ.arq_state and not self.burst_ack and not self.burst_nack and not self.rpt_request_received @@ -1342,8 +1342,8 @@ class DATA: break # break retry loop # We need this part for leaving the repeat loop - # static.ARQ_STATE == "DATA" --> when stopping transmission manually - if not static.ARQ_STATE: + # ARQ.arq_state == "DATA" --> when stopping transmission manually + if not ARQ.arq_state: self.log.debug( "[TNC] arq_transmit: ARQ State changed to FALSE. Breaking retry loop." ) @@ -1357,7 +1357,7 @@ class DATA: "[TNC] ATTEMPT:", retry=self.tx_n_retry_of_burst, maxretries=self.tx_n_max_retries_per_burst, - overflows=static.BUFFER_OVERFLOW_COUNTER, + overflows=AudioParam.buffer_overflow_counter, ) # update buffer position @@ -1373,10 +1373,10 @@ class DATA: arq="transmission", status="transmitting", uuid=self.transmission_uuid, - percent=static.ARQ_TRANSMISSION_PERCENT, - bytesperminute=static.ARQ_BYTES_PER_MINUTE, - compression=static.ARQ_COMPRESSION_FACTOR, - finished=static.ARQ_SECONDS_UNTIL_FINISH, + percent=ARQ.arq_transmission_percent, + bytesperminute=ARQ.bytes_per_minute, + compression=ARQ.arq_compression_factor, + finished=ARQ.arq_seconds_until_finish, irs_snr=self.burst_ack_snr, mycallsign=str(self.mycallsign, 'UTF-8'), dxcallsign=str(self.dxcallsign, 'UTF-8'), @@ -1415,10 +1415,10 @@ class DATA: arq="transmission", status="transmitted", uuid=self.transmission_uuid, - percent=static.ARQ_TRANSMISSION_PERCENT, - bytesperminute=static.ARQ_BYTES_PER_MINUTE, - compression=static.ARQ_COMPRESSION_FACTOR, - finished=static.ARQ_SECONDS_UNTIL_FINISH, + percent=ARQ.arq_transmission_percent, + bytesperminute=ARQ.bytes_per_minute, + compression=ARQ.arq_compression_factor, + finished=ARQ.arq_seconds_until_finish, mycallsign=str(self.mycallsign, 'UTF-8'), dxcallsign=str(self.dxcallsign, 'UTF-8'), irs=helpers.bool_to_string(self.is_IRS) @@ -1426,10 +1426,10 @@ class DATA: self.log.info( "[TNC] ARQ | TX | DATA TRANSMITTED!", - BytesPerMinute=static.ARQ_BYTES_PER_MINUTE, - total_bytes=static.TOTAL_BYTES, - BitsPerSecond=static.ARQ_BITS_PER_SECOND, - overflows=static.BUFFER_OVERFLOW_COUNTER, + BytesPerMinute=ARQ.bytes_per_minute, + total_bytes=ARQ.total_bytes, + BitsPerSecond=ARQ.arq_bits_per_second, + overflows=AudioParam.buffer_overflow_counter, ) @@ -1445,9 +1445,9 @@ class DATA: arq="transmission", status="failed", uuid=self.transmission_uuid, - percent=static.ARQ_TRANSMISSION_PERCENT, - bytesperminute=static.ARQ_BYTES_PER_MINUTE, - compression=static.ARQ_COMPRESSION_FACTOR, + percent=ARQ.arq_transmission_percent, + bytesperminute=ARQ.bytes_per_minute, + compression=ARQ.arq_compression_factor, mycallsign=str(self.mycallsign, 'UTF-8'), dxcallsign=str(self.dxcallsign, 'UTF-8'), irs=helpers.bool_to_string(self.is_IRS) @@ -1455,7 +1455,7 @@ class DATA: self.log.info( "[TNC] ARQ | TX | TRANSMISSION FAILED OR TIME OUT!", - overflows=static.BUFFER_OVERFLOW_COUNTER, + overflows=AudioParam.buffer_overflow_counter, ) self.stop_transmission() @@ -1472,15 +1472,15 @@ class DATA: """ # Process data only if we are in ARQ and BUSY state - if static.ARQ_STATE: - static.DXGRID = b'------' + if ARQ.arq_state: + Station.dxgrid = b'------' helpers.add_to_heard_stations( self.dxcallsign, - static.DXGRID, + Station.dxgrid, "DATA-CHANNEL", - static.SNR, - static.FREQ_OFFSET, - static.HAMLIB_FREQUENCY, + ModemParam.snr, + ModemParam.frequency_offset, + HamlibParam.hamlib_frequency, ) frametype = int.from_bytes(bytes(data_in[:1]), "big") @@ -1520,22 +1520,22 @@ class DATA: # self.log.info("SNR ON IRS", snr=self.burst_ack_snr) self.speed_level = int.from_bytes(bytes(data_in[3:4]), "big") - static.ARQ_SPEED_LEVEL = self.speed_level + ARQ.arq_speed_level = self.speed_level def frame_ack_received( self, data_in: bytes # pylint: disable=unused-argument ) -> None: """Received an ACK for a transmitted frame""" # Process data only if we are in ARQ and BUSY state - if static.ARQ_STATE: - static.DXGRID = b'------' + if ARQ.arq_state: + Station.dxgrid = b'------' helpers.add_to_heard_stations( - static.DXCALLSIGN, - static.DXGRID, + Station.dxcallsign, + Station.dxgrid, "DATA-CHANNEL", - static.SNR, - static.FREQ_OFFSET, - static.HAMLIB_FREQUENCY, + ModemParam.snr, + ModemParam.frequency_offset, + HamlibParam.hamlib_frequency, ) # Force data loops of TNC to stop and continue with next frame self.data_frame_ack_received = True @@ -1557,30 +1557,30 @@ class DATA: arq="transmission", status="failed", uuid=self.transmission_uuid, - percent=static.ARQ_TRANSMISSION_PERCENT, - bytesperminute=static.ARQ_BYTES_PER_MINUTE, + percent=ARQ.arq_transmission_percent, + bytesperminute=ARQ.bytes_per_minute, mycallsign=str(self.mycallsign, 'UTF-8'), dxcallsign=str(self.dxcallsign, 'UTF-8'), irs=helpers.bool_to_string(self.is_IRS) ) - static.DXGRID = b'------' + Station.dxgrid = b'------' helpers.add_to_heard_stations( - static.DXCALLSIGN, - static.DXGRID, + Station.dxcallsign, + Station.dxgrid, "DATA-CHANNEL", - static.SNR, - static.FREQ_OFFSET, - static.HAMLIB_FREQUENCY, + ModemParam.snr, + ModemParam.frequency_offset, + HamlibParam.hamlib_frequency, ) self.send_data_to_socket_queue( freedata="tnc-message", arq="transmission", status="failed", uuid=self.transmission_uuid, - percent=static.ARQ_TRANSMISSION_PERCENT, - bytesperminute=static.ARQ_BYTES_PER_MINUTE, - compression=static.ARQ_COMPRESSION_FACTOR, + percent=ARQ.arq_transmission_percent, + bytesperminute=ARQ.bytes_per_minute, + compression=ARQ.arq_compression_factor, mycallsign=str(self.mycallsign, 'UTF-8'), dxcallsign=str(self.dxcallsign, 'UTF-8'), irs=helpers.bool_to_string(self.is_IRS) @@ -1599,16 +1599,16 @@ class DATA: """ # Only process data if we are in ARQ and BUSY state - if not static.ARQ_STATE or static.TNC_STATE != "BUSY": + if not ARQ.arq_state or TNC.tnc_state != "BUSY": return - static.DXGRID = b'------' + Station.dxgrid = b'------' helpers.add_to_heard_stations( - static.DXCALLSIGN, - static.DXGRID, + Station.dxcallsign, + Station.dxgrid, "DATA-CHANNEL", - static.SNR, - static.FREQ_OFFSET, - static.HAMLIB_FREQUENCY, + ModemParam.snr, + ModemParam.frequency_offset, + HamlibParam.hamlib_frequency, ) self.log.info("[TNC] ARQ REPEAT RECEIVED") @@ -1642,7 +1642,7 @@ class DATA: ############################################################################################################ def arq_session_handler(self, mycallsign, dxcallsign, attempts) -> bool: """ - Create a session with `static.DXCALLSIGN` and wait until the session is open. + Create a session with `Station.dxcallsign` and wait until the session is open. Returns: True if the session was opened successfully @@ -1654,8 +1654,8 @@ class DATA: self.mycallsign = mycallsign self.dxcallsign = dxcallsign - static.DXCALLSIGN = self.dxcallsign - static.DXCALLSIGN_CRC = helpers.get_crc_24(self.dxcallsign) + Station.dxcallsign = self.dxcallsign + Station.dxcallsign_crc = helpers.get_crc_24(self.dxcallsign) # TODO: we need to check this, maybe placing it to class init self.datachannel_timeout = False @@ -1665,11 +1665,11 @@ class DATA: + "]>> <<[" + str(self.dxcallsign, "UTF-8") + "]", - state=static.ARQ_SESSION_STATE, + state=ARQ.arq_session_state, ) # Let's check if we have a busy channel - if static.CHANNEL_BUSY: + if ModemParam.channel_busy: self.log.warning("[TNC] Channel busy, waiting until free...") self.send_data_to_socket_queue( freedata="tnc-message", @@ -1681,13 +1681,13 @@ class DATA: # wait while timeout not reached and our busy state is busy channel_busy_timeout = time.time() + 15 - while static.CHANNEL_BUSY and time.time() < channel_busy_timeout and not self.check_if_mode_fits_to_busy_slot(): + while ModemParam.channel_busy and time.time() < channel_busy_timeout and not self.check_if_mode_fits_to_busy_slot(): threading.Event().wait(0.01) # if channel busy timeout reached stop connecting if time.time() > channel_busy_timeout: self.log.warning("[TNC] Channel busy, try again later...") - static.ARQ_SESSION_STATE = "failed" + ARQ.arq_session_state = "failed" self.send_data_to_socket_queue( freedata="tnc-message", arq="session", @@ -1701,9 +1701,9 @@ class DATA: self.open_session() # wait until data channel is open - while not static.ARQ_SESSION and not self.arq_session_timeout: + while not ARQ.arq_session and not self.arq_session_timeout: threading.Event().wait(0.01) - static.ARQ_SESSION_STATE = "connecting" + ARQ.arq_session_state = "connecting" self.send_data_to_socket_queue( freedata="tnc-message", arq="session", @@ -1711,8 +1711,8 @@ class DATA: mycallsign=str(self.mycallsign, 'UTF-8'), dxcallsign=str(self.dxcallsign, 'UTF-8'), ) - if static.ARQ_SESSION and static.ARQ_SESSION_STATE == "connected": - # static.ARQ_SESSION_STATE = "connected" + if ARQ.arq_session and ARQ.arq_session_state == "connected": + # ARQ.arq_session_state = "connected" self.send_data_to_socket_queue( freedata="tnc-message", arq="session", @@ -1730,9 +1730,9 @@ class DATA: + "]", attempts=self.session_connect_max_retries, # Adjust for 0-based for user display reason="maximum connection attempts reached", - state=static.ARQ_SESSION_STATE, + state=ARQ.arq_session_state, ) - static.ARQ_SESSION_STATE = "failed" + ARQ.arq_session_state = "failed" self.send_data_to_socket_queue( freedata="tnc-message", arq="session", @@ -1752,7 +1752,7 @@ class DATA: False if the session open request failed """ self.IS_ARQ_SESSION_MASTER = True - static.ARQ_SESSION_STATE = "connecting" + ARQ.arq_session_state = "connecting" # create a random session id self.session_id = np.random.bytes(1) @@ -1760,11 +1760,11 @@ class DATA: connection_frame = bytearray(self.length_sig0_frame) connection_frame[:1] = bytes([FR_TYPE.ARQ_SESSION_OPEN.value]) connection_frame[1:2] = self.session_id - connection_frame[2:5] = static.DXCALLSIGN_CRC - connection_frame[5:8] = static.MYCALLSIGN_CRC + connection_frame[2:5] = Station.dxcallsign_crc + connection_frame[5:8] = Station.mycallsign_crc connection_frame[8:14] = helpers.callsign_to_bytes(self.mycallsign) - while not static.ARQ_SESSION: + while not ARQ.arq_session: threading.Event().wait(0.01) for attempt in range(self.session_connect_max_retries): self.log.info( @@ -1774,7 +1774,7 @@ class DATA: + str(self.dxcallsign, "UTF-8") + "]", a=f"{str(attempt + 1)}/{str(self.session_connect_max_retries)}", - state=static.ARQ_SESSION_STATE, + state=ARQ.arq_session_state, ) self.send_data_to_socket_queue( @@ -1789,17 +1789,17 @@ class DATA: self.enqueue_frame_for_tx([connection_frame], c2_mode=FREEDV_MODE.sig0.value, copies=1, repeat_delay=0) - # Wait for a time, looking to see if `static.ARQ_SESSION` + # Wait for a time, looking to see if `ARQ.arq_session` # indicates we've received a positive response from the far station. timeout = time.time() + 3 while time.time() < timeout: threading.Event().wait(0.01) # Stop waiting if data channel is opened - if static.ARQ_SESSION: + if ARQ.arq_session: return True # Stop waiting and interrupt if data channel is getting closed while opening - if static.ARQ_SESSION_STATE == "disconnecting": + if ARQ.arq_session_state == "disconnecting": # disabled this session close as its called twice # self.close_session() return False @@ -1807,11 +1807,11 @@ class DATA: # Session connect timeout, send close_session frame to # attempt to clean up the far-side, if it received the # open_session frame and can still hear us. - if not static.ARQ_SESSION: + if not ARQ.arq_session: self.close_session() return False - # Given the while condition, it will only exit when `static.ARQ_SESSION` is True + # Given the while condition, it will only exit when `ARQ.arq_session` is True self.send_data_to_socket_queue( freedata="tnc-message", arq="session", @@ -1829,7 +1829,7 @@ class DATA: data_in:bytes: """ # if we don't want to respond to calls, return False - if not static.RESPOND_TO_CALL: + if not TNC.respond_to_call: return False # ignore channel opener if already in ARQ STATE @@ -1837,31 +1837,31 @@ class DATA: # Station B already tries connecting to Station A. # For avoiding ignoring repeated connect request in case of packet loss # we are only ignoring packets in case we are ISS - if static.ARQ_SESSION and self.IS_ARQ_SESSION_MASTER: + if ARQ.arq_session and self.IS_ARQ_SESSION_MASTER: return False self.IS_ARQ_SESSION_MASTER = False - static.ARQ_SESSION_STATE = "connecting" + ARQ.arq_session_state = "connecting" # Update arq_session timestamp self.arq_session_last_received = int(time.time()) self.session_id = bytes(data_in[1:2]) - static.DXCALLSIGN_CRC = bytes(data_in[5:8]) + Station.dxcallsign_crc = bytes(data_in[5:8]) self.dxcallsign = helpers.bytes_to_callsign(bytes(data_in[8:14])) - static.DXCALLSIGN = self.dxcallsign + Station.dxcallsign = self.dxcallsign # check if callsign ssid override valid, mycallsign = helpers.check_callsign(self.mycallsign, data_in[2:5]) self.mycallsign = mycallsign - static.DXGRID = b'------' + Station.dxgrid = b'------' helpers.add_to_heard_stations( - static.DXCALLSIGN, - static.DXGRID, + Station.dxcallsign, + Station.dxgrid, "DATA-CHANNEL", - static.SNR, - static.FREQ_OFFSET, - static.HAMLIB_FREQUENCY, + ModemParam.snr, + ModemParam.frequency_offset, + HamlibParam.hamlib_frequency, ) self.log.info( "[TNC] SESSION [" @@ -1869,10 +1869,10 @@ class DATA: + "]>>|<<[" + str(self.dxcallsign, "UTF-8") + "]", - state=static.ARQ_SESSION_STATE, + state=ARQ.arq_session_state, ) - static.ARQ_SESSION = True - static.TNC_STATE = "BUSY" + ARQ.arq_session = True + TNC.tnc_state = "BUSY" self.send_data_to_socket_queue( freedata="tnc-message", @@ -1885,7 +1885,7 @@ class DATA: def close_session(self) -> None: """Close the ARQ session""" - static.ARQ_SESSION_STATE = "disconnecting" + ARQ.arq_session_state = "disconnecting" self.log.info( "[TNC] SESSION [" @@ -1893,7 +1893,7 @@ class DATA: + "]<>[" + str(self.dxcallsign, "UTF-8") + "]", - state=static.ARQ_SESSION_STATE, + state=ARQ.arq_session_state, ) self.send_data_to_socket_queue( @@ -1905,14 +1905,14 @@ class DATA: ) self.IS_ARQ_SESSION_MASTER = False - static.ARQ_SESSION = False + ARQ.arq_session = False # we need to send disconnect frame before doing arq cleanup # we would lose our session id then self.send_disconnect_frame() self.arq_cleanup() - static.ARQ_SESSION_STATE = "disconnected" + ARQ.arq_session_state = "disconnected" def received_session_close(self, data_in: bytes): """ @@ -1928,16 +1928,16 @@ class DATA: # Close the session if the CRC matches the remote station in static. _valid_crc, mycallsign = helpers.check_callsign(self.mycallsign, bytes(data_in[2:5])) _valid_session = helpers.check_session_id(self.session_id, bytes(data_in[1:2])) - if (_valid_crc or _valid_session) and static.ARQ_SESSION_STATE not in ["disconnected"]: - static.ARQ_SESSION_STATE = "disconnected" - static.DXGRID = b'------' + if (_valid_crc or _valid_session) and ARQ.arq_session_state not in ["disconnected"]: + ARQ.arq_session_state = "disconnected" + Station.dxgrid = b'------' helpers.add_to_heard_stations( - static.DXCALLSIGN, - static.DXGRID, + Station.dxcallsign, + Station.dxgrid, "DATA-CHANNEL", - static.SNR, - static.FREQ_OFFSET, - static.HAMLIB_FREQUENCY, + ModemParam.snr, + ModemParam.frequency_offset, + HamlibParam.hamlib_frequency, ) self.log.info( "[TNC] SESSION [" @@ -1945,7 +1945,7 @@ class DATA: + "]<>[" + str(self.dxcallsign, "UTF-8") + "]", - state=static.ARQ_SESSION_STATE, + state=ARQ.arq_session_state, ) self.send_data_to_socket_queue( @@ -1957,14 +1957,14 @@ class DATA: ) self.IS_ARQ_SESSION_MASTER = False - static.ARQ_SESSION = False + ARQ.arq_session = False self.arq_cleanup() def transmit_session_heartbeat(self) -> None: """Send ARQ sesion heartbeat while connected""" - # static.ARQ_SESSION = True - # static.TNC_STATE = "BUSY" - # static.ARQ_SESSION_STATE = "connected" + # ARQ.arq_session = True + # TNC.tnc_state = "BUSY" + # ARQ.arq_session_state = "connected" connection_frame = bytearray(self.length_sig0_frame) connection_frame[:1] = bytes([FR_TYPE.ARQ_SESSION_HB.value]) @@ -1991,16 +1991,16 @@ class DATA: # Accept session data if the DXCALLSIGN_CRC matches the station in static or session id. _valid_crc, _ = helpers.check_callsign(self.dxcallsign, bytes(data_in[4:7])) _valid_session = helpers.check_session_id(self.session_id, bytes(data_in[1:2])) - if _valid_crc or _valid_session and static.ARQ_SESSION_STATE in ["connected", "connecting"]: + if _valid_crc or _valid_session and ARQ.arq_session_state in ["connected", "connecting"]: self.log.debug("[TNC] Received session heartbeat") - static.DXGRID = b'------' + Station.dxgrid = b'------' helpers.add_to_heard_stations( self.dxcallsign, - static.DXGRID, + Station.dxgrid, "SESSION-HB", - static.SNR, - static.FREQ_OFFSET, - static.HAMLIB_FREQUENCY, + ModemParam.snr, + ModemParam.frequency_offset, + HamlibParam.hamlib_frequency, ) self.send_data_to_socket_queue( @@ -2012,9 +2012,9 @@ class DATA: dxcallsign=str(self.dxcallsign, 'UTF-8'), ) - static.ARQ_SESSION = True - static.ARQ_SESSION_STATE = "connected" - static.TNC_STATE = "BUSY" + ARQ.arq_session = True + ARQ.arq_session_state = "connected" + TNC.tnc_state = "BUSY" # Update the timeout timestamps self.arq_session_last_received = int(time.time()) @@ -2028,9 +2028,9 @@ class DATA: if ( not self.IS_ARQ_SESSION_MASTER and not self.arq_file_transfer - and static.ARQ_SESSION_STATE != 'disconnecting' - and static.ARQ_SESSION_STATE != 'disconnected' - and static.ARQ_SESSION_STATE != 'failed' + and ARQ.arq_session_state != 'disconnecting' + and ARQ.arq_session_state != 'disconnected' + and ARQ.arq_session_state != 'failed' ): self.transmit_session_heartbeat() @@ -2069,14 +2069,14 @@ class DATA: # override session connection attempts self.data_channel_max_retries = attempts - static.TNC_STATE = "BUSY" + TNC.tnc_state = "BUSY" self.arq_file_transfer = True self.transmission_uuid = transmission_uuid # wait a moment for the case, a heartbeat is already on the way back to us # this makes channel establishment more clean - if static.ARQ_SESSION: + if ARQ.arq_session: threading.Event().wait(2.5) self.datachannel_timeout = False @@ -2084,15 +2084,15 @@ class DATA: # we need to compress data for getting a compression factor. # so we are compressing twice. This is not that nice and maybe there is another way # for calculating transmission statistics - # static.ARQ_COMPRESSION_FACTOR = len(data_out) / len(lzma.compress(data_out)) + # ARQ.arq_compression_factor = len(data_out) / len(lzma.compress(data_out)) self.arq_open_data_channel(mode, n_frames_per_burst, mycallsign) # wait until data channel is open - while not static.ARQ_STATE and not self.datachannel_timeout: + while not ARQ.arq_state and not self.datachannel_timeout: threading.Event().wait(0.01) - if static.ARQ_STATE: + if ARQ.arq_state: self.arq_transmit(data_out, mode, n_frames_per_burst) return True @@ -2116,14 +2116,14 @@ class DATA: self.is_IRS = False # init a new random session id if we are not in an arq session - if not static.ARQ_SESSION: + if not ARQ.arq_session: # self.session_id = randbytes(1) self.session_id = np.random.bytes(1) # Update data_channel timestamp self.data_channel_last_received = int(time.time()) - if static.LOW_BANDWIDTH_MODE: + if TNC.low_bandwidth_mode: frametype = bytes([FR_TYPE.ARQ_DC_OPEN_N.value]) self.log.debug("[TNC] Requesting low bandwidth mode") @@ -2133,13 +2133,13 @@ class DATA: connection_frame = bytearray(self.length_sig0_frame) connection_frame[:1] = frametype - connection_frame[1:4] = static.DXCALLSIGN_CRC - connection_frame[4:7] = static.MYCALLSIGN_CRC + connection_frame[1:4] = Station.dxcallsign_crc + connection_frame[4:7] = Station.mycallsign_crc connection_frame[7:13] = helpers.callsign_to_bytes(mycallsign) # connection_frame[13:14] = bytes([n_frames_per_burst]) connection_frame[13:14] = self.session_id - while not static.ARQ_STATE: + while not ARQ.arq_state: threading.Event().wait(0.01) for attempt in range(self.data_channel_max_retries): @@ -2162,7 +2162,7 @@ class DATA: ) # Let's check if we have a busy channel and if we are not in a running arq session. - if static.CHANNEL_BUSY and not static.ARQ_STATE: + if ModemParam.channel_busy and not ARQ.arq_state: self.log.warning("[TNC] Channel busy, waiting until free...") self.send_data_to_socket_queue( freedata="tnc-message", @@ -2175,18 +2175,18 @@ class DATA: # wait while timeout not reached and our busy state is busy channel_busy_timeout = time.time() + 5 - while static.CHANNEL_BUSY and time.time() < channel_busy_timeout and not self.check_if_mode_fits_to_busy_slot(): + while ModemParam.channel_busy and time.time() < channel_busy_timeout and not self.check_if_mode_fits_to_busy_slot(): threading.Event().wait(0.01) self.enqueue_frame_for_tx([connection_frame], c2_mode=FREEDV_MODE.sig0.value, copies=1, repeat_delay=0) - timeout = time.time() + self.duration_sig1_frame * 3 + (static.TX_DELAY / 1000 * 2) + timeout = time.time() + self.duration_sig1_frame * 3 + (ModemParam.tx_delay / 1000 * 2) while time.time() < timeout: threading.Event().wait(0.01) # Stop waiting if data channel is opened - if static.ARQ_STATE: + if ARQ.arq_state: return True - if static.TNC_STATE in ["IDLE"]: + if TNC.tnc_state in ["IDLE"]: return False # `data_channel_max_retries` attempts have been sent. Aborting attempt & cleaning up @@ -2201,9 +2201,9 @@ class DATA: status="failed", reason="unknown", uuid=self.transmission_uuid, - percent=static.ARQ_TRANSMISSION_PERCENT, - bytesperminute=static.ARQ_BYTES_PER_MINUTE, - compression=static.ARQ_COMPRESSION_FACTOR, + percent=ARQ.arq_transmission_percent, + bytesperminute=ARQ.bytes_per_minute, + compression=ARQ.arq_compression_factor, mycallsign=str(self.mycallsign, 'UTF-8'), dxcallsign=str(self.dxcallsign, 'UTF-8'), irs=helpers.bool_to_string(self.is_IRS) @@ -2239,12 +2239,12 @@ class DATA: # is intended for this station. # stop processing if we don't want to respond to a call when not in a arq session - if not static.RESPOND_TO_CALL and not static.ARQ_SESSION: + if not TNC.respond_to_call and not ARQ.arq_session: return False # stop processing if not in arq session, but tnc state is busy and we have a different session id # use-case we get a connection request while connecting to another station - if not static.ARQ_SESSION and static.TNC_STATE in ["BUSY"] and data_in[13:14] != self.session_id: + if not ARQ.arq_session and TNC.tnc_state in ["BUSY"] and data_in[13:14] != self.session_id: return False self.arq_file_transfer = True @@ -2257,14 +2257,14 @@ class DATA: # Station B already tries connecting to Station A. # For avoiding ignoring repeated connect request in case of packet loss # we are only ignoring packets in case we are ISS - if static.ARQ_STATE and not self.is_IRS: + if ARQ.arq_state and not self.is_IRS: return False self.is_IRS = True - static.DXCALLSIGN_CRC = bytes(data_in[4:7]) + Station.dxcallsign_crc = bytes(data_in[4:7]) self.dxcallsign = helpers.bytes_to_callsign(bytes(data_in[7:13])) - static.DXCALLSIGN = self.dxcallsign + Station.dxcallsign = self.dxcallsign self.send_data_to_socket_queue( freedata="tnc-message", @@ -2286,7 +2286,7 @@ class DATA: # ISS(n) <-> IRS(w) # ISS(n) <-> IRS(n) - if frametype == FR_TYPE.ARQ_DC_OPEN_W.value and not static.LOW_BANDWIDTH_MODE: + if frametype == FR_TYPE.ARQ_DC_OPEN_W.value and not TNC.low_bandwidth_mode: # ISS(w) <-> IRS(w) constellation = "ISS(w) <-> IRS(w)" self.received_LOW_BANDWIDTH_MODE = False @@ -2300,7 +2300,7 @@ class DATA: self.mode_list = self.mode_list_low_bw self.time_list = self.time_list_low_bw self.snr_list = self.snr_list_low_bw - elif frametype == FR_TYPE.ARQ_DC_OPEN_N.value and not static.LOW_BANDWIDTH_MODE: + elif frametype == FR_TYPE.ARQ_DC_OPEN_N.value and not TNC.low_bandwidth_mode: # ISS(n) <-> IRS(w) constellation = "ISS(n) <-> IRS(w)" self.received_LOW_BANDWIDTH_MODE = True @@ -2328,37 +2328,37 @@ class DATA: # TODO: MOVE THIS TO arq_calculate_speed_level() # calculate speed level in correlation to latest known SNR for i in range(len(self.mode_list)): - if static.SNR >= self.snr_list[i]: + if ModemParam.snr >= self.snr_list[i]: self.speed_level = i # calculate if speed level fits to busy condition mode_name = codec2.FREEDV_MODE(self.mode_list[self.speed_level]).name mode_slots = codec2.FREEDV_MODE_USED_SLOTS[mode_name].value - if mode_slots in [static.CHANNEL_BUSY_SLOT]: + if mode_slots in [ModemParam.channel_busy_slot]: self.speed_level = 0 self.log.warning( "[TNC] busy slot detection", - slots=static.CHANNEL_BUSY_SLOT, + slots=ModemParam.channel_busy_slot, mode_slots=mode_slots, ) self.log.debug( "[TNC] calculated speed level", speed_level=self.speed_level, - given_snr=static.SNR, + given_snr=ModemParam.snr, min_snr=self.snr_list[self.speed_level], ) # Update modes we are listening to self.set_listening_modes(True, True, self.mode_list[self.speed_level]) - static.DXGRID = b'------' + Station.dxgrid = b'------' helpers.add_to_heard_stations( - static.DXCALLSIGN, - static.DXGRID, + Station.dxcallsign, + Station.dxgrid, "DATA-CHANNEL", - static.SNR, - static.FREQ_OFFSET, - static.HAMLIB_FREQUENCY, + ModemParam.snr, + ModemParam.frequency_offset, + HamlibParam.hamlib_frequency, ) self.session_id = data_in[13:14] @@ -2381,13 +2381,13 @@ class DATA: # Set ARQ State AFTER resetting timeouts # this avoids timeouts starting too early - static.ARQ_STATE = True - static.TNC_STATE = "BUSY" + ARQ.arq_state = True + TNC.tnc_state = "BUSY" self.reset_statistics() # Select the frame type based on the current TNC mode - if static.LOW_BANDWIDTH_MODE or self.received_LOW_BANDWIDTH_MODE: + if TNC.low_bandwidth_mode or self.received_LOW_BANDWIDTH_MODE: frametype = bytes([FR_TYPE.ARQ_DC_OPEN_ACK_N.value]) self.log.debug("[TNC] Responding with low bandwidth mode") else: @@ -2398,7 +2398,7 @@ class DATA: connection_frame[:1] = frametype connection_frame[1:2] = self.session_id connection_frame[8:9] = bytes([self.speed_level]) - connection_frame[13:14] = bytes([static.ARQ_PROTOCOL_VERSION]) + connection_frame[13:14] = bytes([ARQ.arq_protocol_version]) self.enqueue_frame_for_tx([connection_frame], c2_mode=FREEDV_MODE.sig0.value, copies=1, repeat_delay=0) @@ -2418,7 +2418,7 @@ class DATA: + str(self.dxcallsign, "UTF-8") + "]", bandwidth="wide", - snr=static.SNR, + snr=ModemParam.snr, ) # set start of transmission for our statistics @@ -2436,7 +2436,7 @@ class DATA: """ protocol_version = int.from_bytes(bytes(data_in[13:14]), "big") - if protocol_version == static.ARQ_PROTOCOL_VERSION: + if protocol_version == ARQ.arq_protocol_version: self.send_data_to_socket_queue( freedata="tnc-message", arq="transmission", @@ -2462,14 +2462,14 @@ class DATA: self.speed_level = int.from_bytes(bytes(data_in[8:9]), "big") self.log.debug("[TNC] speed level selected for given SNR", speed_level=self.speed_level) # self.speed_level = len(self.mode_list) - 1 - static.DXGRID = b'------' + Station.dxgrid = b'------' helpers.add_to_heard_stations( - static.DXCALLSIGN, - static.DXGRID, + Station.dxcallsign, + Station.dxgrid, "DATA-CHANNEL", - static.SNR, - static.FREQ_OFFSET, - static.HAMLIB_FREQUENCY, + ModemParam.snr, + ModemParam.frequency_offset, + HamlibParam.hamlib_frequency, ) self.log.info( @@ -2478,16 +2478,16 @@ class DATA: + "]>>|<<[" + str(self.dxcallsign, "UTF-8") + "]", - snr=static.SNR, + snr=ModemParam.snr, ) # as soon as we set ARQ_STATE to DATA, transmission starts - static.ARQ_STATE = True + ARQ.arq_state = True # Update data_channel timestamp self.data_channel_last_received = int(time.time()) else: - static.TNC_STATE = "IDLE" - static.ARQ_STATE = False + TNC.tnc_state = "IDLE" + ARQ.arq_state = False self.send_data_to_socket_queue( freedata="tnc-message", arq="transmission", @@ -2501,7 +2501,7 @@ class DATA: self.log.warning( "[TNC] protocol version mismatch:", received=protocol_version, - own=static.ARQ_PROTOCOL_VERSION, + own=ARQ.arq_protocol_version, ) self.stop_transmission() @@ -2518,14 +2518,14 @@ class DATA: # TODO: We should display a message to this effect on the UI. self.log.warning("[TNC] Missing required callsign", dxcallsign=dxcallsign) return - static.DXCALLSIGN = dxcallsign - static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN) + Station.dxcallsign = dxcallsign + Station.dxcallsign_crc = helpers.get_crc_24(Station.dxcallsign) self.send_data_to_socket_queue( freedata="tnc-message", ping="transmitting", dxcallsign=str(dxcallsign, "UTF-8"), mycallsign=str(mycallsign, "UTF-8"), - snr=str(static.SNR), + snr=str(ModemParam.snr), ) self.log.info( "[TNC] PING REQ [" @@ -2537,12 +2537,12 @@ class DATA: ping_frame = bytearray(self.length_sig0_frame) ping_frame[:1] = bytes([FR_TYPE.PING.value]) - ping_frame[1:4] = static.DXCALLSIGN_CRC + ping_frame[1:4] = Station.dxcallsign_crc ping_frame[4:7] = helpers.get_crc_24(mycallsign) ping_frame[7:13] = helpers.callsign_to_bytes(mycallsign) - if static.ENABLE_FSK: - self.log.info("[TNC] ENABLE FSK", state=static.ENABLE_FSK) + if TNC.enable_fsk: + self.log.info("[TNC] ENABLE FSK", state=TNC.enable_fsk) self.enqueue_frame_for_tx([ping_frame], c2_mode=FREEDV_MODE.fsk_ldpc_0.value) else: self.enqueue_frame_for_tx([ping_frame], c2_mode=FREEDV_MODE.sig0.value) @@ -2565,25 +2565,25 @@ class DATA: self.log.debug("[TNC] received_ping: ping not for this station.") return - static.DXCALLSIGN_CRC = dxcallsign_crc - static.DXCALLSIGN = dxcallsign + Station.dxcallsign_crc = dxcallsign_crc + Station.dxcallsign = dxcallsign self.log.info( "[TNC] PING REQ [" + str(mycallsign, "UTF-8") + "] <<< [" + str(dxcallsign, "UTF-8") + "]", - snr=static.SNR, + snr=ModemParam.snr, ) - static.DXGRID = b'------' + Station.dxgrid = b'------' helpers.add_to_heard_stations( dxcallsign, - static.DXGRID, + Station.dxgrid, "PING", - static.SNR, - static.FREQ_OFFSET, - static.HAMLIB_FREQUENCY, + ModemParam.snr, + ModemParam.frequency_offset, + HamlibParam.hamlib_frequency, ) self.send_data_to_socket_queue( @@ -2591,12 +2591,12 @@ class DATA: ping="received", uuid=str(uuid.uuid4()), timestamp=int(time.time()), - dxgrid=str(static.DXGRID, "UTF-8"), + dxgrid=str(Station.dxgrid, "UTF-8"), dxcallsign=str(dxcallsign, "UTF-8"), mycallsign=str(mycallsign, "UTF-8"), - snr=str(static.SNR), + snr=str(ModemParam.snr), ) - if static.RESPOND_TO_CALL: + if TNC.respond_to_call: self.transmit_ping_ack() def transmit_ping_ack(self): @@ -2607,12 +2607,12 @@ class DATA: """ ping_frame = bytearray(self.length_sig0_frame) ping_frame[:1] = bytes([FR_TYPE.PING_ACK.value]) - ping_frame[1:4] = static.DXCALLSIGN_CRC - ping_frame[4:7] = static.MYCALLSIGN_CRC - ping_frame[7:11] = helpers.encode_grid(static.MYGRID.decode("UTF-8")) - ping_frame[13:14] = helpers.snr_to_bytes(static.SNR) + ping_frame[1:4] = Station.dxcallsign_crc + ping_frame[4:7] = Station.mycallsign_crc + ping_frame[7:11] = helpers.encode_grid(Station.mygrid.decode("UTF-8")) + ping_frame[13:14] = helpers.snr_to_bytes(ModemParam.snr) - if static.ENABLE_FSK: + if TNC.enable_fsk: self.enqueue_frame_for_tx([ping_frame], c2_mode=FREEDV_MODE.fsk_ldpc_0.value) else: self.enqueue_frame_for_tx([ping_frame], c2_mode=FREEDV_MODE.sig0.value) @@ -2630,40 +2630,40 @@ class DATA: _valid, mycallsign = helpers.check_callsign(self.mycallsign, data_in[1:4]) if _valid: - static.DXGRID = bytes(helpers.decode_grid(data_in[7:11]), "UTF-8") + Station.dxgrid = bytes(helpers.decode_grid(data_in[7:11]), "UTF-8") dxsnr = helpers.snr_from_bytes(data_in[13:14]) self.send_data_to_socket_queue( freedata="tnc-message", ping="acknowledge", uuid=str(uuid.uuid4()), timestamp=int(time.time()), - dxgrid=str(static.DXGRID, "UTF-8"), - dxcallsign=str(static.DXCALLSIGN, "UTF-8"), + dxgrid=str(Station.dxgrid, "UTF-8"), + dxcallsign=str(Station.dxcallsign, "UTF-8"), mycallsign=str(mycallsign, "UTF-8"), - snr=str(static.SNR), + snr=str(ModemParam.snr), dxsnr=str(dxsnr) ) # combined_snr = own rx snr / snr on dx side - combined_snr = f"{static.SNR}/{dxsnr}" + combined_snr = f"{ModemParam.snr}/{dxsnr}" helpers.add_to_heard_stations( - static.DXCALLSIGN, - static.DXGRID, + Station.dxcallsign, + Station.dxgrid, "PING-ACK", combined_snr, - static.FREQ_OFFSET, - static.HAMLIB_FREQUENCY, + ModemParam.frequency_offset, + HamlibParam.hamlib_frequency, ) self.log.info( "[TNC] PING ACK [" + str(mycallsign, "UTF-8") + "] >|< [" - + str(static.DXCALLSIGN, "UTF-8") + + str(Station.dxcallsign, "UTF-8") + "]", - snr=static.SNR, + snr=ModemParam.snr, dxsnr=dxsnr, ) - static.TNC_STATE = "IDLE" + TNC.tnc_state = "IDLE" else: self.log.info( "[TNC] FOREIGN PING ACK [" @@ -2671,7 +2671,7 @@ class DATA: + "] ??? [" + str(bytes(data_in[4:7]), "UTF-8") + "]", - snr=static.SNR, + snr=ModemParam.snr, ) def stop_transmission(self) -> None: @@ -2680,8 +2680,8 @@ class DATA: """ self.log.warning("[TNC] Stopping transmission!") - static.TNC_STATE = "IDLE" - static.ARQ_STATE = False + TNC.tnc_state = "IDLE" + ARQ.arq_state = False self.send_data_to_socket_queue( freedata="tnc-message", arq="transmission", @@ -2692,8 +2692,8 @@ class DATA: stop_frame = bytearray(self.length_sig0_frame) stop_frame[:1] = bytes([FR_TYPE.ARQ_STOP.value]) - stop_frame[1:4] = static.DXCALLSIGN_CRC - stop_frame[4:7] = static.MYCALLSIGN_CRC + stop_frame[1:4] = Station.dxcallsign_crc + stop_frame[4:7] = Station.mycallsign_crc # TODO: Not sure if we really need the session id when disconnecting # stop_frame[1:2] = self.session_id stop_frame[7:13] = helpers.callsign_to_bytes(self.mycallsign) @@ -2709,8 +2709,8 @@ class DATA: Received a transmission stop """ self.log.warning("[TNC] Stopping transmission!") - static.TNC_STATE = "IDLE" - static.ARQ_STATE = False + TNC.tnc_state = "IDLE" + ARQ.arq_state = False self.send_data_to_socket_queue( freedata="tnc-message", arq="transmission", @@ -2735,14 +2735,14 @@ class DATA: try: while True: threading.Event().wait(0.5) - while static.BEACON_STATE: + while Beacon.beacon_state: if ( - not static.ARQ_SESSION + not ARQ.arq_session and not self.arq_file_transfer - and not static.BEACON_PAUSE - and not static.CHANNEL_BUSY - and static.TNC_STATE not in ["busy"] - and not static.ARQ_STATE + and not Beacon.beacon_pause + and not ModemParam.channel_busy + and TNC.tnc_state not in ["busy"] + and not ARQ.arq_state ): self.send_data_to_socket_queue( freedata="tnc-message", @@ -2757,10 +2757,10 @@ class DATA: beacon_frame = bytearray(self.length_sig0_frame) beacon_frame[:1] = bytes([FR_TYPE.BEACON.value]) beacon_frame[1:7] = helpers.callsign_to_bytes(self.mycallsign) - beacon_frame[7:11] = helpers.encode_grid(static.MYGRID.decode("UTF-8")) + beacon_frame[7:11] = helpers.encode_grid(Station.mygrid.decode("UTF-8")) - if static.ENABLE_FSK: - self.log.info("[TNC] ENABLE FSK", state=static.ENABLE_FSK) + if TNC.enable_fsk: + self.log.info("[TNC] ENABLE FSK", state=TNC.enable_fsk) self.enqueue_frame_for_tx( [beacon_frame], c2_mode=FREEDV_MODE.fsk_ldpc_0.value, @@ -2772,8 +2772,8 @@ class DATA: interval_timer = time.time() + self.beacon_interval while ( time.time() < interval_timer - and static.BEACON_STATE - and not static.BEACON_PAUSE + and Beacon.beacon_state + and not Beacon.beacon_pause ): threading.Event().wait(0.01) @@ -2789,32 +2789,32 @@ class DATA: """ # here we add the received station to the heard stations buffer beacon_callsign = helpers.bytes_to_callsign(bytes(data_in[1:7])) - static.DXGRID = bytes(helpers.decode_grid(data_in[7:11]), "UTF-8") + Station.dxgrid = bytes(helpers.decode_grid(data_in[7:11]), "UTF-8") self.send_data_to_socket_queue( freedata="tnc-message", beacon="received", uuid=str(uuid.uuid4()), timestamp=int(time.time()), dxcallsign=str(beacon_callsign, "UTF-8"), - dxgrid=str(static.DXGRID, "UTF-8"), - snr=str(static.SNR), + dxgrid=str(Station.dxgrid, "UTF-8"), + snr=str(ModemParam.snr), ) self.log.info( "[TNC] BEACON RCVD [" + str(beacon_callsign, "UTF-8") + "][" - + str(static.DXGRID, "UTF-8") + + str(Station.dxgrid, "UTF-8") + "] ", - snr=static.SNR, + snr=ModemParam.snr, ) helpers.add_to_heard_stations( beacon_callsign, - static.DXGRID, + Station.dxgrid, "BEACON", - static.SNR, - static.FREQ_OFFSET, - static.HAMLIB_FREQUENCY, + ModemParam.snr, + ModemParam.frequency_offset, + HamlibParam.hamlib_frequency, ) def transmit_cq(self) -> None: @@ -2836,12 +2836,12 @@ class DATA: cq_frame = bytearray(self.length_sig0_frame) cq_frame[:1] = bytes([FR_TYPE.CQ.value]) cq_frame[1:7] = helpers.callsign_to_bytes(self.mycallsign) - cq_frame[7:11] = helpers.encode_grid(static.MYGRID.decode("UTF-8")) + cq_frame[7:11] = helpers.encode_grid(Station.mygrid.decode("UTF-8")) self.log.debug("[TNC] CQ Frame:", data=[cq_frame]) - if static.ENABLE_FSK: - self.log.info("[TNC] ENABLE FSK", state=static.ENABLE_FSK) + if TNC.enable_fsk: + self.log.info("[TNC] ENABLE FSK", state=TNC.enable_fsk) self.enqueue_frame_for_tx([cq_frame], c2_mode=FREEDV_MODE.fsk_ldpc_0.value) else: self.enqueue_frame_for_tx([cq_frame], c2_mode=FREEDV_MODE.sig0.value, copies=1, repeat_delay=0) @@ -2858,33 +2858,33 @@ class DATA: # here we add the received station to the heard stations buffer dxcallsign = helpers.bytes_to_callsign(bytes(data_in[1:7])) self.log.debug("[TNC] received_cq:", dxcallsign=dxcallsign) - static.DXGRID = bytes(helpers.decode_grid(data_in[7:11]), "UTF-8") + Station.dxgrid = bytes(helpers.decode_grid(data_in[7:11]), "UTF-8") self.send_data_to_socket_queue( freedata="tnc-message", cq="received", mycallsign=str(self.mycallsign, "UTF-8"), dxcallsign=str(dxcallsign, "UTF-8"), - dxgrid=str(static.DXGRID, "UTF-8"), + dxgrid=str(Station.dxgrid, "UTF-8"), ) self.log.info( "[TNC] CQ RCVD [" + str(dxcallsign, "UTF-8") + "][" - + str(static.DXGRID, "UTF-8") + + str(Station.dxgrid, "UTF-8") + "] ", - snr=static.SNR, + snr=ModemParam.snr, ) helpers.add_to_heard_stations( dxcallsign, - static.DXGRID, + Station.dxgrid, "CQ CQ CQ", - static.SNR, - static.FREQ_OFFSET, - static.HAMLIB_FREQUENCY, + ModemParam.snr, + ModemParam.frequency_offset, + HamlibParam.hamlib_frequency, ) - if static.RESPOND_TO_CQ and static.RESPOND_TO_CALL: + if TNC.respond_to_cq and TNC.respond_to_call: self.transmit_qrv(dxcallsign) def transmit_qrv(self, dxcallsign: bytes) -> None: @@ -2912,11 +2912,11 @@ class DATA: qrv_frame = bytearray(self.length_sig0_frame) qrv_frame[:1] = bytes([FR_TYPE.QRV.value]) qrv_frame[1:7] = helpers.callsign_to_bytes(self.mycallsign) - qrv_frame[7:11] = helpers.encode_grid(static.MYGRID.decode("UTF-8")) - qrv_frame[11:12] = helpers.snr_to_bytes(static.SNR) + qrv_frame[7:11] = helpers.encode_grid(Station.mygrid.decode("UTF-8")) + qrv_frame[11:12] = helpers.snr_to_bytes(ModemParam.snr) - if static.ENABLE_FSK: - self.log.info("[TNC] ENABLE FSK", state=static.ENABLE_FSK) + if TNC.enable_fsk: + self.log.info("[TNC] ENABLE FSK", state=TNC.enable_fsk) self.enqueue_frame_for_tx([qrv_frame], c2_mode=FREEDV_MODE.fsk_ldpc_0.value) else: self.enqueue_frame_for_tx([qrv_frame], c2_mode=FREEDV_MODE.sig0.value, copies=1, repeat_delay=0) @@ -2930,17 +2930,17 @@ class DATA: """ # here we add the received station to the heard stations buffer dxcallsign = helpers.bytes_to_callsign(bytes(data_in[1:7])) - static.DXGRID = bytes(helpers.decode_grid(data_in[7:11]), "UTF-8") + Station.dxgrid = bytes(helpers.decode_grid(data_in[7:11]), "UTF-8") dxsnr = helpers.snr_from_bytes(data_in[11:12]) - combined_snr = f"{static.SNR}/{dxsnr}" + combined_snr = f"{ModemParam.snr}/{dxsnr}" self.send_data_to_socket_queue( freedata="tnc-message", qrv="received", dxcallsign=str(dxcallsign, "UTF-8"), - dxgrid=str(static.DXGRID, "UTF-8"), - snr=str(static.SNR), + dxgrid=str(Station.dxgrid, "UTF-8"), + snr=str(ModemParam.snr), dxsnr=str(dxsnr) ) @@ -2948,18 +2948,18 @@ class DATA: "[TNC] QRV RCVD [" + str(dxcallsign, "UTF-8") + "][" - + str(static.DXGRID, "UTF-8") + + str(Station.dxgrid, "UTF-8") + "] ", - snr=static.SNR, + snr=ModemParam.snr, dxsnr=dxsnr ) helpers.add_to_heard_stations( dxcallsign, - static.DXGRID, + Station.dxgrid, "QRV", combined_snr, - static.FREQ_OFFSET, - static.HAMLIB_FREQUENCY, + ModemParam.frequency_offset, + HamlibParam.hamlib_frequency, ) def received_is_writing(self, data_in: bytes) -> None: @@ -3000,14 +3000,14 @@ class DATA: transmission_percent: float """ try: - if static.TOTAL_BYTES == 0: - static.TOTAL_BYTES = 1 - static.ARQ_TRANSMISSION_PERCENT = min( + if ARQ.total_bytes == 0: + ARQ.total_bytes = 1 + ARQ.arq_transmission_percent = min( int( ( receivedbytes - * static.ARQ_COMPRESSION_FACTOR - / static.TOTAL_BYTES + * ARQ.arq_compression_factor + / ARQ.total_bytes ) * 100 ), @@ -3017,31 +3017,31 @@ class DATA: transmissiontime = time.time() - self.rx_start_of_transmission if receivedbytes > 0: - static.ARQ_BITS_PER_SECOND = int((receivedbytes * 8) / transmissiontime) - static.ARQ_BYTES_PER_MINUTE = int( + ARQ.arq_bits_per_second = int((receivedbytes * 8) / transmissiontime) + ARQ.bytes_per_minute = int( receivedbytes / (transmissiontime / 60) ) - static.ARQ_SECONDS_UNTIL_FINISH = int(((static.TOTAL_BYTES - receivedbytes) / ( - static.ARQ_BYTES_PER_MINUTE * static.ARQ_COMPRESSION_FACTOR)) * 60) - 20 # offset because of frame ack/nack + ARQ.arq_seconds_until_finish = int(((ARQ.total_bytes - receivedbytes) / ( + ARQ.bytes_per_minute * ARQ.arq_compression_factor)) * 60) - 20 # offset because of frame ack/nack - speed_chart = {"snr": static.SNR, "bpm": static.ARQ_BYTES_PER_MINUTE, "timestamp": int(time.time())} + speed_chart = {"snr": ModemParam.snr, "bpm": ARQ.bytes_per_minute, "timestamp": int(time.time())} # check if data already in list - if speed_chart not in static.SPEED_LIST: - static.SPEED_LIST.append(speed_chart) + if speed_chart not in ARQ.speed_list: + ARQ.speed_list.append(speed_chart) else: - static.ARQ_BITS_PER_SECOND = 0 - static.ARQ_BYTES_PER_MINUTE = 0 - static.ARQ_SECONDS_UNTIL_FINISH = 0 + ARQ.arq_bits_per_second = 0 + ARQ.bytes_per_minute = 0 + ARQ.arq_seconds_until_finish = 0 except Exception as err: self.log.error(f"[TNC] calculate_transfer_rate_rx: Exception: {err}") - static.ARQ_TRANSMISSION_PERCENT = 0.0 - static.ARQ_BITS_PER_SECOND = 0 - static.ARQ_BYTES_PER_MINUTE = 0 + ARQ.arq_transmission_percent = 0.0 + ARQ.arq_bits_per_second = 0 + ARQ.bytes_per_minute = 0 return [ - static.ARQ_BITS_PER_SECOND, - static.ARQ_BYTES_PER_MINUTE, - static.ARQ_TRANSMISSION_PERCENT, + ARQ.arq_bits_per_second, + ARQ.bytes_per_minute, + ARQ.arq_transmission_percent, ] def reset_statistics(self) -> None: @@ -3049,13 +3049,13 @@ class DATA: Reset statistics """ # reset ARQ statistics - static.ARQ_BYTES_PER_MINUTE_BURST = 0 - static.ARQ_BYTES_PER_MINUTE = 0 - static.ARQ_BITS_PER_SECOND_BURST = 0 - static.ARQ_BITS_PER_SECOND = 0 - static.ARQ_TRANSMISSION_PERCENT = 0 - static.TOTAL_BYTES = 0 - static.ARQ_SECONDS_UNTIL_FINISH = 0 + ARQ.bytes_per_minute_BURST = 0 + ARQ.bytes_per_minute = 0 + ARQ.arq_bits_per_second_burst = 0 + ARQ.arq_bits_per_second = 0 + ARQ.arq_transmission_percent = 0 + ARQ.total_bytes = 0 + ARQ.arq_seconds_until_finish = 0 def calculate_transfer_rate_tx( self, tx_start_of_transmission: float, sentbytes: int, tx_buffer_length: int @@ -3073,39 +3073,39 @@ class DATA: transmission_percent: float """ try: - static.ARQ_TRANSMISSION_PERCENT = min( + ARQ.arq_transmission_percent = min( int((sentbytes / tx_buffer_length) * 100), 100 ) transmissiontime = time.time() - tx_start_of_transmission if sentbytes > 0: - static.ARQ_BITS_PER_SECOND = int((sentbytes * 8) / transmissiontime) - static.ARQ_BYTES_PER_MINUTE = int(sentbytes / (transmissiontime / 60)) - static.ARQ_SECONDS_UNTIL_FINISH = int(((tx_buffer_length - sentbytes) / ( - static.ARQ_BYTES_PER_MINUTE * static.ARQ_COMPRESSION_FACTOR)) * 60) + ARQ.arq_bits_per_second = int((sentbytes * 8) / transmissiontime) + ARQ.bytes_per_minute = int(sentbytes / (transmissiontime / 60)) + ARQ.arq_seconds_until_finish = int(((tx_buffer_length - sentbytes) / ( + ARQ.bytes_per_minute * ARQ.arq_compression_factor)) * 60) - speed_chart = {"snr": self.burst_ack_snr, "bpm": static.ARQ_BYTES_PER_MINUTE, + speed_chart = {"snr": self.burst_ack_snr, "bpm": ARQ.bytes_per_minute, "timestamp": int(time.time())} # check if data already in list - if speed_chart not in static.SPEED_LIST: - static.SPEED_LIST.append(speed_chart) + if speed_chart not in ARQ.speed_list: + ARQ.speed_list.append(speed_chart) else: - static.ARQ_BITS_PER_SECOND = 0 - static.ARQ_BYTES_PER_MINUTE = 0 - static.ARQ_SECONDS_UNTIL_FINISH = 0 + ARQ.arq_bits_per_second = 0 + ARQ.bytes_per_minute = 0 + ARQ.arq_seconds_until_finish = 0 except Exception as err: self.log.error(f"[TNC] calculate_transfer_rate_tx: Exception: {err}") - static.ARQ_TRANSMISSION_PERCENT = 0.0 - static.ARQ_BITS_PER_SECOND = 0 - static.ARQ_BYTES_PER_MINUTE = 0 + ARQ.arq_transmission_percent = 0.0 + ARQ.arq_bits_per_second = 0 + ARQ.bytes_per_minute = 0 return [ - static.ARQ_BITS_PER_SECOND, - static.ARQ_BYTES_PER_MINUTE, - static.ARQ_TRANSMISSION_PERCENT, + ARQ.arq_bits_per_second, + ARQ.bytes_per_minute, + ARQ.arq_transmission_percent, ] # ----------------------CLEANUP AND RESET FUNCTIONS @@ -3127,8 +3127,8 @@ class DATA: self.rpt_request_received = False self.burst_rpt_counter = 0 self.data_frame_ack_received = False - static.RX_BURST_BUFFER = [] - static.RX_FRAME_BUFFER = b"" + ARQ.rx_burst_buffer = [] + ARQ.rx_frame_buffer = b"" self.burst_ack_snr = 0 self.arq_burst_last_payload = 0 self.rx_n_frame_of_burst = 0 @@ -3144,7 +3144,7 @@ class DATA: modem.RECEIVE_FSK_LDPC_1 = False # reset buffer overflow counter - static.BUFFER_OVERFLOW_COUNTER = [0, 0, 0, 0, 0] + AudioParam.buffer_overflow_counter = [0, 0, 0, 0, 0] self.is_IRS = False self.burst_nack = False @@ -3152,7 +3152,7 @@ class DATA: self.frame_nack_counter = 0 self.frame_received_counter = 0 self.speed_level = len(self.mode_list) - 1 - static.ARQ_SPEED_LEVEL = self.speed_level + ARQ.arq_speed_level = self.speed_level # low bandwidth mode indicator self.received_LOW_BANDWIDTH_MODE = False @@ -3165,17 +3165,17 @@ class DATA: self.data_channel_max_retries = 10 # we need to keep these values if in ARQ_SESSION - if not static.ARQ_SESSION: - static.TNC_STATE = "IDLE" + if not ARQ.arq_session: + TNC.tnc_state = "IDLE" self.dxcallsign = b"AA0AA-0" - self.mycallsign = static.MYCALLSIGN + self.mycallsign = Station.mycallsign self.session_id = bytes(1) - static.SPEED_LIST = [] - static.ARQ_STATE = False + ARQ.speed_list = [] + ARQ.arq_state = False self.arq_file_transfer = False - static.BEACON_PAUSE = False + Beacon.beacon_pause = False def arq_reset_ack(self, state: bool) -> None: """ @@ -3258,8 +3258,8 @@ class DATA: # TODO: We need to redesign this part for cleaner state handling # Return if not ARQ STATE and not ARQ SESSION STATE as they are different use cases if ( - not static.ARQ_STATE - and static.ARQ_SESSION_STATE != "connected" + not ARQ.arq_state + and ARQ.arq_session_state != "connected" or not self.is_IRS ): return @@ -3270,7 +3270,7 @@ class DATA: # We want to reach this state only if connected ( == return above not called ) if self.rx_n_frames_per_burst > 1: # uses case for IRS: reduce time for waiting by counting "None" in burst buffer - frames_left = static.RX_BURST_BUFFER.count(None) + frames_left = ARQ.rx_burst_buffer.count(None) elif self.rx_n_frame_of_burst == 0 and self.rx_n_frames_per_burst == 0: # use case for IRS: We didn't receive a burst yet, because the first one got lost # in this case we don't have any information about the expected burst length @@ -3296,9 +3296,9 @@ class DATA: ) print( - f"frames_per_burst {self.rx_n_frame_of_burst} / {self.rx_n_frames_per_burst}, Repeats: {self.burst_rpt_counter} Nones: {static.RX_BURST_BUFFER.count(None)}") + f"frames_per_burst {self.rx_n_frame_of_burst} / {self.rx_n_frames_per_burst}, Repeats: {self.burst_rpt_counter} Nones: {ARQ.rx_burst_buffer.count(None)}") - if self.rx_n_frames_per_burst > 1 and self.burst_rpt_counter < 3 and static.RX_BURST_BUFFER.count(None) > 0: + if self.rx_n_frames_per_burst > 1 and self.burst_rpt_counter < 3 and ARQ.rx_burst_buffer.count(None) > 0: # reset self.burst_last_received self.burst_last_received = time.time() + self.time_list[self.speed_level] * frames_left self.burst_rpt_counter += 1 @@ -3315,7 +3315,7 @@ class DATA: if self.burst_nack_counter >= 2: self.burst_nack_counter = 0 self.speed_level = max(self.speed_level - 1, 0) - static.ARQ_SPEED_LEVEL = self.speed_level + ARQ.arq_speed_level = self.speed_level # TODO: Create better mechanisms for handling n frames per burst for bad channels # reduce frames per burst @@ -3347,7 +3347,7 @@ class DATA: DATA CHANNEL """ # and not static.ARQ_SEND_KEEP_ALIVE: - if static.ARQ_STATE and static.TNC_STATE == "BUSY": + if ARQ.arq_state and TNC.tnc_state == "BUSY": threading.Event().wait(0.01) if ( self.data_channel_last_received + self.transmission_timeout @@ -3368,7 +3368,7 @@ class DATA: "[TNC] DATA [" + str(self.mycallsign, "UTF-8") + "]<>[" - + str(static.DXCALLSIGN, "UTF-8") + + str(Station.dxcallsign, "UTF-8") + "]" ) self.send_data_to_socket_queue( @@ -3388,8 +3388,8 @@ class DATA: ARQ SESSION """ if ( - static.ARQ_SESSION - and static.TNC_STATE == "BUSY" + ARQ.arq_session + and TNC.tnc_state == "BUSY" and not self.arq_file_transfer ): if self.arq_session_last_received + self.arq_session_timeout > time.time(): @@ -3422,9 +3422,9 @@ class DATA: while not self.arq_file_transfer: threading.Event().wait(0.01) if ( - static.ARQ_SESSION + ARQ.arq_session and self.IS_ARQ_SESSION_MASTER - and static.ARQ_SESSION_STATE == "connected" + and ARQ.arq_session_state == "connected" # and not self.arq_file_transfer ): threading.Event().wait(1) @@ -3462,7 +3462,7 @@ class DATA: # send burst only if channel not busy - but without waiting # otherwise burst will be dropped - if not static.CHANNEL_BUSY and not static.TRANSMITTING: + if not ModemParam.channel_busy and not TNC.transmitting: self.enqueue_frame_for_tx( frame_to_tx=[fec_frame], c2_mode=codec2.FREEDV_MODE["sig0"].value ) diff --git a/tnc/explorer.py b/tnc/explorer.py index 927ec66e..dda0cd53 100644 --- a/tnc/explorer.py +++ b/tnc/explorer.py @@ -13,7 +13,7 @@ import time import ujson as json import structlog import static -from static import ARQ, Audio, Beacon, Channel, Daemon, Hamlib, Modem, Station, TCI, TNC +from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC log = structlog.get_logger("explorer") @@ -34,21 +34,21 @@ class explorer(): def push(self): - frequency = 0 if static.HAMLIB_FREQUENCY is None else static.HAMLIB_FREQUENCY + frequency = 0 if HamlibParam.hamlib_frequency is None else HamlibParam.hamlib_frequency band = "USB" - callsign = str(static.MYCALLSIGN, "utf-8") - gridsquare = str(static.MYGRID, "utf-8") - version = str(static.VERSION) - bandwidth = str(static.LOW_BANDWIDTH_MODE) - beacon = str(static.BEACON_STATE) - strength = str(static.HAMLIB_STRENGTH) + callsign = str(Station.mycall, "utf-8") + gridsquare = str(Station.mygrid, "utf-8") + version = str(TNC.version) + bandwidth = str(TNC.low_bandwidth_mode) + beacon = str(Beacon.beacon_state) + strength = str(HamlibParam.hamlib_strength) log.info("[EXPLORER] publish", frequency=frequency, band=band, callsign=callsign, gridsquare=gridsquare, version=version, bandwidth=bandwidth) headers = {"Content-Type": "application/json"} station_data = {'callsign': callsign, 'gridsquare': gridsquare, 'frequency': frequency, 'strength': strength, 'band': band, 'version': version, 'bandwidth': bandwidth, 'beacon': beacon, "lastheard": []} - for i in static.HEARD_STATIONS: + for i in TNC.heard_stations: try: callsign = str(i[0], "UTF-8") grid = str(i[1], "UTF-8") diff --git a/tnc/helpers.py b/tnc/helpers.py index 600d0637..75c1aecf 100644 --- a/tnc/helpers.py +++ b/tnc/helpers.py @@ -8,7 +8,7 @@ import time from datetime import datetime,timezone import crcengine import static -from static import ARQ, Audio, Beacon, Channel, Daemon, Hamlib, Modem, Station, TCI, TNC +from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC import structlog import numpy as np import threading @@ -131,16 +131,16 @@ def add_to_heard_stations(dxcallsign, dxgrid, datatype, snr, offset, frequency): Nothing """ # check if buffer empty - if len(static.HEARD_STATIONS) == 0: - static.HEARD_STATIONS.append( + if len(TNC.heard_stations) == 0: + TNC.heard_stations.append( [dxcallsign, dxgrid, int(datetime.now(timezone.utc).timestamp()), datatype, snr, offset, frequency] ) # if not, we search and update else: - for i in range(len(static.HEARD_STATIONS)): + for i in range(len(TNC.heard_stations)): # Update callsign with new timestamp - if static.HEARD_STATIONS[i].count(dxcallsign) > 0: - static.HEARD_STATIONS[i] = [ + if TNC.heard_stations[i].count(dxcallsign) > 0: + TNC.heard_stations[i] = [ dxcallsign, dxgrid, int(time.time()), @@ -151,8 +151,8 @@ def add_to_heard_stations(dxcallsign, dxgrid, datatype, snr, offset, frequency): ] break # Insert if nothing found - if i == len(static.HEARD_STATIONS) - 1: - static.HEARD_STATIONS.append( + if i == len(TNC.heard_stations) - 1: + TNC.heard_stations.append( [ dxcallsign, dxgrid, @@ -166,10 +166,10 @@ def add_to_heard_stations(dxcallsign, dxgrid, datatype, snr, offset, frequency): break -# for idx, item in enumerate(static.HEARD_STATIONS): +# for idx, item in enumerate(TNC.heard_stations): # if dxcallsign in item: # item = [dxcallsign, int(time.time())] -# static.HEARD_STATIONS[idx] = item +# TNC.heard_stations[idx] = item def callsign_to_bytes(callsign) -> bytes: @@ -306,7 +306,7 @@ def check_callsign(callsign: bytes, crc_to_check: bytes): except Exception as err: log.debug("[HLP] check_callsign: Error callsign SSID to integer:", e=err) - for ssid in static.SSID_LIST: + for ssid in Station.ssid_list: call_with_ssid = bytearray(callsign) call_with_ssid.extend("-".encode("utf-8")) call_with_ssid.extend(str(ssid).encode("utf-8")) diff --git a/tnc/main.py b/tnc/main.py index 48ccb759..6a76a728 100755 --- a/tnc/main.py +++ b/tnc/main.py @@ -29,7 +29,7 @@ import helpers import log_handler import modem import static -from static import ARQ, Audio, Beacon, Channel, Daemon, Hamlib, Modem, Station, TCI, TNC +from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC import structlog import explorer import json @@ -256,7 +256,7 @@ if __name__ == "__main__": ARGS = PARSER.parse_args() # set save to folder state for allowing downloading files to local file system - static.ARQ_SAVE_TO_FOLDER = ARGS.savetofolder + ARQ.arq_save_to_folder = ARGS.savetofolder if not ARGS.configfile: @@ -267,46 +267,46 @@ if __name__ == "__main__": try: mycallsign = bytes(ARGS.mycall.upper(), "utf-8") mycallsign = helpers.callsign_to_bytes(mycallsign) - static.MYCALLSIGN = helpers.bytes_to_callsign(mycallsign) - static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN) - static.SSID_LIST = ARGS.ssid_list + Station.mycallsign = helpers.bytes_to_callsign(mycallsign) + Station.mycallsign_crc = helpers.get_crc_24(Station.mycallsign) + Station.ssid_list = ARGS.ssid_list # check if own ssid is always part of ssid list - own_ssid = int(static.MYCALLSIGN.split(b"-")[1]) - if own_ssid not in static.SSID_LIST: - static.SSID_LIST.append(own_ssid) + own_ssid = int(Station.mycallsign.split(b"-")[1]) + if own_ssid not in Station.ssid_list: + Station.ssid_list.append(own_ssid) - static.MYGRID = bytes(ARGS.mygrid, "utf-8") + Station.mygrid = bytes(ARGS.mygrid, "utf-8") # check if we have an int or str as device name try: - static.AUDIO_INPUT_DEVICE = int(ARGS.audio_input_device) + AudioParam.audio_input_device = int(ARGS.audio_input_device) except ValueError: - static.AUDIO_INPUT_DEVICE = ARGS.audio_input_device + AudioParam.audio_input_device = ARGS.audio_input_device try: - static.AUDIO_OUTPUT_DEVICE = int(ARGS.audio_output_device) + AudioParam.audio_output_device = int(ARGS.audio_output_device) except ValueError: - static.AUDIO_OUTPUT_DEVICE = ARGS.audio_output_device + AudioParam.audio_output_device = ARGS.audio_output_device TNC.port = ARGS.socket_port - static.HAMLIB_RADIOCONTROL = ARGS.hamlib_radiocontrol - static.HAMLIB_RIGCTLD_IP = ARGS.rigctld_ip - static.HAMLIB_RIGCTLD_PORT = str(ARGS.rigctld_port) - static.ENABLE_SCATTER = ARGS.send_scatter - static.ENABLE_FFT = ARGS.send_fft - static.ENABLE_FSK = ARGS.enable_fsk - static.LOW_BANDWIDTH_MODE = ARGS.low_bandwidth_mode - static.TUNING_RANGE_FMIN = ARGS.tuning_range_fmin - static.TUNING_RANGE_FMAX = ARGS.tuning_range_fmax - static.TX_AUDIO_LEVEL = ARGS.tx_audio_level - static.RESPOND_TO_CQ = ARGS.enable_respond_to_cq - static.RX_BUFFER_SIZE = ARGS.rx_buffer_size - static.ENABLE_EXPLORER = ARGS.enable_explorer - static.AUDIO_AUTO_TUNE = ARGS.enable_audio_auto_tune - static.ENABLE_STATS = ARGS.enable_stats - static.AUDIO_ENABLE_TCI = ARGS.audio_enable_tci - static.TCI_IP = ARGS.tci_ip - static.TCI_PORT = ARGS.tci_port - static.TX_DELAY = ARGS.tx_delay + HamlibParam.hamlib_radiocontrol = ARGS.hamlib_radiocontrol + HamlibParam.hamlib_rigctld_ip = ARGS.rigctld_ip + HamlibParam.hamlib_rigctld_port = str(ARGS.rigctld_port) + ModemParam.enable_scatter = ARGS.send_scatter + AudioParam.enable_fft = ARGS.send_fft + TNC.enable_fsk = ARGS.enable_fsk + TNC.low_bandwidth_mode = ARGS.low_bandwidth_mode + ModemParam.tuning_range_fmin = ARGS.tuning_range_fmin + ModemParam.tuning_range_fmax = ARGS.tuning_range_fmax + AudioParam.tx_audio_level = ARGS.tx_audio_level + TNC.respond_to_cq = ARGS.enable_respond_to_cq + ARQ.rx_buffer_size = ARGS.rx_buffer_size + TNC.enable_explorer = ARGS.enable_explorer + AudioParam.audio_auto_tune = ARGS.enable_audio_auto_tune + TNC.enable_stats = ARGS.enable_stats + AudioParam.audio_enable_tci = ARGS.audio_enable_tci + TCIParam.ip = ARGS.tci_ip + TCIParam.port = ARGS.tci_port + ModemParam.tx_delay = ARGS.tx_delay except Exception as e: log.error("[DMN] Error reading config file", exception=e) @@ -321,52 +321,52 @@ if __name__ == "__main__": # then we are forcing a station ssid = 0 mycallsign = bytes(conf.get('STATION', 'mycall', 'AA0AA'), "utf-8") mycallsign = helpers.callsign_to_bytes(mycallsign) - static.MYCALLSIGN = helpers.bytes_to_callsign(mycallsign) - static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN) + Station.mycallsign = helpers.bytes_to_callsign(mycallsign) + Station.mycallsign_crc = helpers.get_crc_24(Station.mycallsign) #json.loads = for converting str list to list - static.SSID_LIST = json.loads(conf.get('STATION', 'ssid_list', '[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]')) + Station.ssid_list = json.loads(conf.get('STATION', 'ssid_list', '[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]')) - static.MYGRID = bytes(conf.get('STATION', 'mygrid', 'JN12aa'), "utf-8") + Station.mygrid = bytes(conf.get('STATION', 'mygrid', 'JN12aa'), "utf-8") # check if we have an int or str as device name try: - static.AUDIO_INPUT_DEVICE = int(conf.get('AUDIO', 'rx', '0')) + AudioParam.audio_input_device = int(conf.get('AUDIO', 'rx', '0')) except ValueError: - static.AUDIO_INPUT_DEVICE = conf.get('AUDIO', 'rx', '0') + AudioParam.audio_input_device = conf.get('AUDIO', 'rx', '0') try: - static.AUDIO_OUTPUT_DEVICE = int(conf.get('AUDIO', 'tx', '0')) + AudioParam.audio_output_device = int(conf.get('AUDIO', 'tx', '0')) except ValueError: - static.AUDIO_OUTPUT_DEVICE = conf.get('AUDIO', 'tx', '0') + AudioParam.audio_output_device = conf.get('AUDIO', 'tx', '0') TNC.port = int(conf.get('NETWORK', 'tncport', '3000')) - static.HAMLIB_RADIOCONTROL = conf.get('RADIO', 'radiocontrol', 'rigctld') - static.HAMLIB_RIGCTLD_IP = conf.get('RADIO', 'rigctld_ip', '127.0.0.1') - static.HAMLIB_RIGCTLD_PORT = str(conf.get('RADIO', 'rigctld_port', '4532')) - static.ENABLE_SCATTER = conf.get('TNC', 'scatter', 'True') - static.ENABLE_FFT = conf.get('TNC', 'fft', 'True') - static.ENABLE_FSK = conf.get('TNC', 'fsk', 'False') - static.LOW_BANDWIDTH_MODE = conf.get('TNC', 'narrowband', 'False') - static.TUNING_RANGE_FMIN = float(conf.get('TNC', 'fmin', '-50.0')) - static.TUNING_RANGE_FMAX = float(conf.get('TNC', 'fmax', '50.0')) - static.TX_AUDIO_LEVEL = int(conf.get('AUDIO', 'txaudiolevel', '100')) - static.RESPOND_TO_CQ = conf.get('TNC', 'qrv', 'True') - static.RX_BUFFER_SIZE = int(conf.get('TNC', 'rxbuffersize', '16')) - static.ENABLE_EXPLORER = conf.get('TNC', 'explorer', 'False') - static.AUDIO_AUTO_TUNE = conf.get('AUDIO', 'auto_tune', 'False') - static.ENABLE_STATS = conf.get('TNC', 'stats', 'False') - static.AUDIO_ENABLE_TCI = conf.get('AUDIO', 'enable_tci', 'False') - static.TCI_IP = str(conf.get('AUDIO', 'tci_ip', 'localhost')) - static.TCI_PORT = int(conf.get('AUDIO', 'tci_port', '50001')) - static.TX_DELAY = int(conf.get('TNC', 'tx_delay', '0')) + HamlibParam.hamlib_radiocontrol = conf.get('RADIO', 'radiocontrol', 'rigctld') + HamlibParam.hamlib_rigctld_ip = conf.get('RADIO', 'rigctld_ip', '127.0.0.1') + HamlibParam.hamlib_rigctld_port = str(conf.get('RADIO', 'rigctld_port', '4532')) + ModemParam.enable_scatter = conf.get('TNC', 'scatter', 'True') + AudioParam.enable_fft = conf.get('TNC', 'fft', 'True') + TNC.enable_fsk = conf.get('TNC', 'fsk', 'False') + TNC.low_bandwidth_mode = conf.get('TNC', 'narrowband', 'False') + ModemParam.tuning_range_fmin = float(conf.get('TNC', 'fmin', '-50.0')) + ModemParam.tuning_range_fmax = float(conf.get('TNC', 'fmax', '50.0')) + AudioParam.tx_audio_level = int(conf.get('AUDIO', 'txaudiolevel', '100')) + TNC.respond_to_cq = conf.get('TNC', 'qrv', 'True') + ARQ.rx_buffer_size = int(conf.get('TNC', 'rxbuffersize', '16')) + TNC.enable_explorer = conf.get('TNC', 'explorer', 'False') + AudioParam.audio_auto_tune = conf.get('AUDIO', 'auto_tune', 'False') + TNC.enable_stats = conf.get('TNC', 'stats', 'False') + AudioParam.audio_enable_tci = conf.get('AUDIO', 'enable_tci', 'False') + TCIParam.ip = str(conf.get('AUDIO', 'tci_ip', 'localhost')) + TCIParam.port = int(conf.get('AUDIO', 'tci_port', '50001')) + ModemParam.tx_delay = int(conf.get('TNC', 'tx_delay', '0')) except KeyError as e: log.warning("[CFG] Error reading config file near", key=str(e)) except Exception as e: log.warning("[CFG] Error", e=e) # make sure the own ssid is always part of the ssid list - my_ssid = int(static.MYCALLSIGN.split(b'-')[1]) - if my_ssid not in static.SSID_LIST: - static.SSID_LIST.append(my_ssid) + my_ssid = int(Station.mycallsign.split(b'-')[1]) + if my_ssid not in Station.ssid_list: + Station.ssid_list.append(my_ssid) # we need to wait until we got all parameters from argparse first before we can load the other modules import sock @@ -405,8 +405,8 @@ if __name__ == "__main__": modem = modem.RF() # optionally start explorer module - if static.ENABLE_EXPLORER: - log.info("[EXPLORER] Publishing to https://explorer.freedata.app", state=static.ENABLE_EXPLORER) + if TNC.enable_explorer: + log.info("[EXPLORER] Publishing to https://explorer.freedata.app", state=TNC.enable_explorer) explorer = explorer.explorer() # --------------------------------------------START CMD SERVER diff --git a/tnc/modem.py b/tnc/modem.py index 02aec8c2..e74054d7 100644 --- a/tnc/modem.py +++ b/tnc/modem.py @@ -23,7 +23,7 @@ import numpy as np import sock import sounddevice as sd import static -from static import ARQ, Audio, Beacon, Channel, Daemon, Hamlib, Modem, Station, TCI, TNC +from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC from static import FRAME_TYPE import structlog import ujson as json @@ -35,7 +35,7 @@ TESTMODE = False RXCHANNEL = "" TXCHANNEL = "" -static.TRANSMITTING = False +TNC.transmitting = False # Receive only specific modes to reduce CPU load RECEIVE_SIG0 = True @@ -73,7 +73,7 @@ class RF: self.AUDIO_FRAMES_PER_BUFFER_RX = 2400 * 2 # 8192 # 8192 Let's do some tests with very small chunks for TX - self.AUDIO_FRAMES_PER_BUFFER_TX = 1200 if static.AUDIO_ENABLE_TCI else 2400 * 2 + self.AUDIO_FRAMES_PER_BUFFER_TX = 1200 if AudioParam.audio_enable_tci else 2400 * 2 # 8 * (self.AUDIO_SAMPLE_RATE_RX/self.MODEM_SAMPLE_RATE) == 48 self.AUDIO_CHANNELS = 1 self.MODE = 0 @@ -178,13 +178,13 @@ class RF: self.freedv_ldpc1_tx = open_codec2_instance(codec2.FREEDV_MODE.fsk_ldpc_1.value) # --------------------------------------------CREATE PORTAUDIO INSTANCE - if not TESTMODE and not static.AUDIO_ENABLE_TCI: + if not TESTMODE and not AudioParam.audio_enable_tci: try: self.stream = sd.RawStream( channels=1, dtype="int16", callback=self.callback, - device=(static.AUDIO_INPUT_DEVICE, static.AUDIO_OUTPUT_DEVICE), + device=(AudioParam.audio_input_device, AudioParam.audio_output_device), samplerate=self.AUDIO_SAMPLE_RATE_RX, blocksize=4800, ) @@ -204,7 +204,7 @@ class RF: elif not TESTMODE: # placeholder area for processing audio via TCI # https://github.com/maksimus1210/TCI - self.log.warning("[MDM] [TCI] Not yet fully implemented", ip=static.TCI_IP, port=static.TCI_PORT) + self.log.warning("[MDM] [TCI] Not yet fully implemented", ip=TCIParam.tci_ip, port=TCIParam.tci_port) # we are trying this by simulating an audio stream Object like with mkfifo class Object: @@ -214,7 +214,7 @@ class RF: self.stream = Object() # lets init TCI module - self.tci_module = tci.TCI() + self.tci_module = tci.TCICtrl() tci_rx_callback_thread = threading.Thread( target=self.tci_rx_callback, @@ -264,28 +264,28 @@ class RF: # --------------------------------------------INIT AND OPEN HAMLIB # Check how we want to control the radio - if static.HAMLIB_RADIOCONTROL == "rigctld": + if HamlibParam.hamlib_radiocontrol == "rigctld": import rigctld as rig - elif static.AUDIO_ENABLE_TCI: + elif AudioParam.audio_enable_tci: self.radio = self.tci_module else: import rigdummy as rig - if not static.AUDIO_ENABLE_TCI: + if not AudioParam.audio_enable_tci: self.radio = rig.radio() self.radio.open_rig( - rigctld_ip=static.HAMLIB_RIGCTLD_IP, - rigctld_port=static.HAMLIB_RIGCTLD_PORT, + rigctld_ip=HamlibParam.hamlib_rigctld_ip, + rigctld_port=HamlibParam.hamlib_rigctld_port, ) # --------------------------------------------START DECODER THREAD - if static.ENABLE_FFT: + if AudioParam.enable_fft: fft_thread = threading.Thread( target=self.calculate_fft, name="FFT_THREAD", daemon=True ) fft_thread.start() - if static.ENABLE_FSK: + if TNC.enable_fsk: audio_thread_fsk_ldpc0 = threading.Thread( target=self.audio_fsk_ldpc_0, name="AUDIO_THREAD FSK LDPC0", daemon=True ) @@ -352,7 +352,7 @@ class RF: threading.Event().wait(0.01) if len(self.modoutqueue) > 0 and not self.mod_out_locked: - static.PTT_STATE = self.radio.set_ptt(True) + HamlibParam.ptt_state = self.radio.set_ptt(True) jsondata = {"ptt": "True"} data_out = json.dumps(jsondata) sock.SOCKET_QUEUE.put(data_out) @@ -384,8 +384,8 @@ class RF: (self.dat0_datac1_buffer, RECEIVE_DATAC1), (self.dat0_datac3_buffer, RECEIVE_DATAC3), (self.dat0_datac4_buffer, RECEIVE_DATAC4), - (self.fsk_ldpc_buffer_0, static.ENABLE_FSK), - (self.fsk_ldpc_buffer_1, static.ENABLE_FSK), + (self.fsk_ldpc_buffer_0, TNC.enable_fsk), + (self.fsk_ldpc_buffer_1, TNC.enable_fsk), ]: if ( not (data_buffer.nbuffer + length_x) > data_buffer.size @@ -418,8 +418,8 @@ class RF: (self.dat0_datac1_buffer, RECEIVE_DATAC1), (self.dat0_datac3_buffer, RECEIVE_DATAC3), (self.dat0_datac4_buffer, RECEIVE_DATAC4), - (self.fsk_ldpc_buffer_0, static.ENABLE_FSK), - (self.fsk_ldpc_buffer_1, static.ENABLE_FSK), + (self.fsk_ldpc_buffer_0, TNC.enable_fsk), + (self.fsk_ldpc_buffer_1, TNC.enable_fsk), ]: if ( not (data_buffer.nbuffer + length_x) > data_buffer.size @@ -460,13 +460,13 @@ class RF: x = self.resampler.resample48_to_8(x) # audio recording for debugging purposes - if static.AUDIO_RECORD: - # static.AUDIO_RECORD_FILE.write(x) - static.AUDIO_RECORD_FILE.writeframes(x) + if AudioParam.audio_record: + # AudioParam.audio_record_file.write(x) + AudioParam.audio_record_file.writeframes(x) # Avoid decoding when transmitting to reduce CPU # TODO: Overriding this for testing purposes - # if not static.TRANSMITTING: + # if not TNC.transmitting: length_x = len(x) # Avoid buffer overflow by filling only if buffer for # selected datachannel mode is not full @@ -476,23 +476,23 @@ class RF: (self.dat0_datac1_buffer, RECEIVE_DATAC1, 2), (self.dat0_datac3_buffer, RECEIVE_DATAC3, 3), (self.dat0_datac4_buffer, RECEIVE_DATAC4, 4), - (self.fsk_ldpc_buffer_0, static.ENABLE_FSK, 5), - (self.fsk_ldpc_buffer_1, static.ENABLE_FSK, 6), + (self.fsk_ldpc_buffer_0, TNC.enable_fsk, 5), + (self.fsk_ldpc_buffer_1, TNC.enable_fsk, 6), ]: if (audiobuffer.nbuffer + length_x) > audiobuffer.size: - static.BUFFER_OVERFLOW_COUNTER[index] += 1 + AudioParam.buffer_overflow_counter[index] += 1 elif receive: audiobuffer.push(x) - # end of "not static.TRANSMITTING" if block + # end of "not TNC.transmitting" if block if not self.modoutqueue or self.mod_out_locked: data_out48k = np.zeros(frames, dtype=np.int16) self.fft_data = x else: - if not static.PTT_STATE: + if not HamlibParam.ptt_state: # TODO: Moved to this place for testing # Maybe we can avoid moments of silence before transmitting - static.PTT_STATE = self.radio.set_ptt(True) + HamlibParam.ptt_state = self.radio.set_ptt(True) jsondata = {"ptt": "True"} data_out = json.dumps(jsondata) sock.SOCKET_QUEUE.put(data_out) @@ -539,14 +539,14 @@ class RF: else: return False - static.TRANSMITTING = True + TNC.transmitting = True # if we're transmitting FreeDATA signals, reset channel busy state - static.CHANNEL_BUSY = False + ModemParam.channel_busy = False start_of_transmission = time.time() # TODO: Moved ptt toggle some steps before audio is ready for testing # Toggle ptt early to save some time and send ptt state via socket - # static.PTT_STATE = self.radio.set_ptt(True) + # HamlibParam.ptt_state = self.radio.set_ptt(True) # jsondata = {"ptt": "True"} # data_out = json.dumps(jsondata) # sock.SOCKET_QUEUE.put(data_out) @@ -577,15 +577,15 @@ class RF: ) # Add empty data to handle ptt toggle time - if static.TX_DELAY > 0: - data_delay = int(self.MODEM_SAMPLE_RATE * (static.TX_DELAY / 1000)) # type: ignore + if ModemParam.tx_delay > 0: + data_delay = int(self.MODEM_SAMPLE_RATE * (ModemParam.tx_delay / 1000)) # type: ignore mod_out_silence = ctypes.create_string_buffer(data_delay * 2) txbuffer = bytes(mod_out_silence) else: txbuffer = bytes() self.log.debug( - "[MDM] TRANSMIT", mode=self.MODE, payload=payload_bytes_per_frame, delay=static.TX_DELAY + "[MDM] TRANSMIT", mode=self.MODE, payload=payload_bytes_per_frame, delay=ModemParam.tx_delay ) for _ in range(repeats): @@ -646,35 +646,35 @@ class RF: x = np.frombuffer(txbuffer, dtype=np.int16) # enable / disable AUDIO TUNE Feature / ALC correction - if static.AUDIO_AUTO_TUNE: - if static.HAMLIB_ALC == 0.0: - static.TX_AUDIO_LEVEL = static.TX_AUDIO_LEVEL + 20 - elif 0.0 < static.HAMLIB_ALC <= 0.1: - print("0.0 < static.HAMLIB_ALC <= 0.1") - static.TX_AUDIO_LEVEL = static.TX_AUDIO_LEVEL + 2 - self.log.debug("[MDM] AUDIO TUNE", audio_level=str(static.TX_AUDIO_LEVEL), - alc_level=str(static.HAMLIB_ALC)) - elif 0.1 < static.HAMLIB_ALC < 0.2: - print("0.1 < static.HAMLIB_ALC < 0.2") - static.TX_AUDIO_LEVEL = static.TX_AUDIO_LEVEL - self.log.debug("[MDM] AUDIO TUNE", audio_level=str(static.TX_AUDIO_LEVEL), - alc_level=str(static.HAMLIB_ALC)) - elif 0.2 < static.HAMLIB_ALC < 0.99: - print("0.2 < static.HAMLIB_ALC < 0.99") - static.TX_AUDIO_LEVEL = static.TX_AUDIO_LEVEL - 20 - self.log.debug("[MDM] AUDIO TUNE", audio_level=str(static.TX_AUDIO_LEVEL), - alc_level=str(static.HAMLIB_ALC)) - elif 1.0 >= static.HAMLIB_ALC: - print("1.0 >= static.HAMLIB_ALC") - static.TX_AUDIO_LEVEL = static.TX_AUDIO_LEVEL - 40 - self.log.debug("[MDM] AUDIO TUNE", audio_level=str(static.TX_AUDIO_LEVEL), - alc_level=str(static.HAMLIB_ALC)) + if AudioParam.audio_auto_tune: + if HamlibParam.alc == 0.0: + AudioParam.tx_audio_level = AudioParam.tx_audio_level + 20 + elif 0.0 < HamlibParam.alc <= 0.1: + print("0.0 < HamlibParam.alc <= 0.1") + AudioParam.tx_audio_level = AudioParam.tx_audio_level + 2 + self.log.debug("[MDM] AUDIO TUNE", audio_level=str(AudioParam.tx_audio_level), + alc_level=str(HamlibParam.alc)) + elif 0.1 < HamlibParam.alc < 0.2: + print("0.1 < HamlibParam.alc < 0.2") + AudioParam.tx_audio_level = AudioParam.tx_audio_level + self.log.debug("[MDM] AUDIO TUNE", audio_level=str(AudioParam.tx_audio_level), + alc_level=str(HamlibParam.alc)) + elif 0.2 < HamlibParam.alc < 0.99: + print("0.2 < HamlibParam.alc < 0.99") + AudioParam.tx_audio_level = AudioParam.tx_audio_level - 20 + self.log.debug("[MDM] AUDIO TUNE", audio_level=str(AudioParam.tx_audio_level), + alc_level=str(HamlibParam.alc)) + elif 1.0 >= HamlibParam.alc: + print("1.0 >= HamlibParam.alc") + AudioParam.tx_audio_level = AudioParam.tx_audio_level - 40 + self.log.debug("[MDM] AUDIO TUNE", audio_level=str(AudioParam.tx_audio_level), + alc_level=str(HamlibParam.alc)) else: - self.log.debug("[MDM] AUDIO TUNE", audio_level=str(static.TX_AUDIO_LEVEL), - alc_level=str(static.HAMLIB_ALC)) - x = set_audio_volume(x, static.TX_AUDIO_LEVEL) + self.log.debug("[MDM] AUDIO TUNE", audio_level=str(AudioParam.tx_audio_level), + alc_level=str(HamlibParam.alc)) + x = set_audio_volume(x, AudioParam.tx_audio_level) - if not static.AUDIO_ENABLE_TCI: + if not AudioParam.audio_enable_tci: txbuffer_out = self.resampler.resample8_to_48(x) else: txbuffer_out = x @@ -704,7 +704,7 @@ class RF: self.mod_out_locked = False # we need to wait manually for tci processing - if static.AUDIO_ENABLE_TCI: + if AudioParam.audio_enable_tci: duration = len(txbuffer_out) / 8000 timestamp_to_sleep = time.time() + duration self.log.debug("[MDM] TCI calculated duration", duration=duration) @@ -717,7 +717,7 @@ class RF: tci_timeout_reached = True while self.modoutqueue or not tci_timeout_reached: - if static.AUDIO_ENABLE_TCI: + if AudioParam.audio_enable_tci: if time.time() < timestamp_to_sleep: tci_timeout_reached = False else: @@ -725,9 +725,9 @@ class RF: threading.Event().wait(0.01) # if we're transmitting FreeDATA signals, reset channel busy state - static.CHANNEL_BUSY = False + ModemParam.channel_busy = False - static.PTT_STATE = self.radio.set_ptt(False) + HamlibParam.ptt_state = self.radio.set_ptt(False) # Push ptt state to socket stream jsondata = {"ptt": "False"} @@ -738,7 +738,7 @@ class RF: self.mod_out_locked = True self.modem_transmit_queue.task_done() - static.TRANSMITTING = False + TNC.transmitting = False threading.Event().set() end_of_transmission = time.time() @@ -796,14 +796,14 @@ class RF: if rx_status != 0: # we need to disable this if in testmode as its causing problems with FIFO it seems if not TESTMODE: - static.IS_CODEC2_TRAFFIC = True + ModemParam.is_codec2_traffic = True self.log.debug( "[MDM] [demod_audio] modem state", mode=mode_name, rx_status=rx_status, sync_flag=codec2.api.rx_sync_flags_to_text[rx_status] ) else: - static.IS_CODEC2_TRAFFIC = False + ModemParam.is_codec2_traffic = False if rx_status == 10: state_buffer.append(rx_status) @@ -812,8 +812,8 @@ class RF: nin = codec2.api.freedv_nin(freedv) if nbytes == bytes_per_frame: - # process commands only if static.LISTEN = True - if static.LISTEN: + # process commands only if TNC.listen = True + if TNC.listen: # ignore data channel opener frames for avoiding toggle states @@ -839,7 +839,7 @@ class RF: else: self.log.warning( "[MDM] [demod_audio] received frame but ignored processing", - listen=static.LISTEN + listen=TNC.listen ) except Exception as e: self.log.warning("[MDM] [demod_audio] Stream not active anymore", e=e) @@ -876,8 +876,8 @@ class RF: # set tuning range codec2.api.freedv_set_tuning_range( c2instance, - ctypes.c_float(static.TUNING_RANGE_FMIN), - ctypes.c_float(static.TUNING_RANGE_FMAX), + ctypes.c_float(ModemParam.tuning_range_fmin), + ctypes.c_float(ModemParam.tuning_range_fmax), ) # get bytes per frame @@ -1029,7 +1029,7 @@ class RF: def get_frequency_offset(self, freedv: ctypes.c_void_p) -> float: """ Ask codec2 for the calculated (audio) frequency offset of the received signal. - Side-effect: sets static.FREQ_OFFSET + Side-effect: sets ModemParam.frequency_offset :param freedv: codec2 instance to query :type freedv: ctypes.c_void_p @@ -1039,18 +1039,18 @@ class RF: modemStats = codec2.MODEMSTATS() codec2.api.freedv_get_modem_extended_stats(freedv, ctypes.byref(modemStats)) offset = round(modemStats.foff) * (-1) - static.FREQ_OFFSET = offset + ModemParam.frequency_offset = offset return offset def get_scatter(self, freedv: ctypes.c_void_p) -> None: """ Ask codec2 for data about the received signal and calculate the scatter plot. - Side-effect: sets static.SCATTER + Side-effect: sets ModemParam.scatter :param freedv: codec2 instance to query :type freedv: ctypes.c_void_p """ - if not static.ENABLE_SCATTER: + if not ModemParam.enable_scatter: return modemStats = codec2.MODEMSTATS() @@ -1078,16 +1078,16 @@ class RF: # Send all the data if we have too-few samples, otherwise send a sampling if 150 > len(scatterdata) > 0: - static.SCATTER = scatterdata + ModemParam.scatter = scatterdata else: # only take every tenth data point - static.SCATTER = scatterdata[::10] + ModemParam.scatter = scatterdata[::10] def calculate_snr(self, freedv: ctypes.c_void_p) -> float: """ Ask codec2 for data about the received signal and calculate the signal-to-noise ratio. - Side-effect: sets static.SNR + Side-effect: sets ModemParam.snr :param freedv: codec2 instance to query :type freedv: ctypes.c_void_p @@ -1106,15 +1106,15 @@ class RF: snr = round(modem_stats_snr, 1) self.log.info("[MDM] calculate_snr: ", snr=snr) - static.SNR = snr - # static.SNR = np.clip( + ModemParam.snr = snr + # ModemParam.snr = np.clip( # snr, -127, 127 # ) # limit to max value of -128/128 as a possible fix of #188 - return static.SNR + return ModemParam.snr except Exception as err: self.log.error(f"[MDM] calculate_snr: Exception: {err}") - static.SNR = 0 - return static.SNR + ModemParam.snr = 0 + return ModemParam.snr def set_rig_data(self) -> None: """ @@ -1134,29 +1134,29 @@ class RF: """ Request information about the current state of the radio via hamlib Side-effect: sets - - static.HAMLIB_FREQUENCY - - static.HAMLIB_MODE - - static.HAMLIB_BANDWIDTH + - HamlibParam.hamlib_frequency + - HamlibParam.hamlib_mode + - HamlibParam.hamlib_bandwidth """ while True: # this looks weird, but is necessary for avoiding rigctld packet colission sock threading.Event().wait(0.25) - static.HAMLIB_FREQUENCY = self.radio.get_frequency() + HamlibParam.hamlib_frequency = self.radio.get_frequency() threading.Event().wait(0.1) - static.HAMLIB_MODE = self.radio.get_mode() + HamlibParam.hamlib_mode = self.radio.get_mode() threading.Event().wait(0.1) - static.HAMLIB_BANDWIDTH = self.radio.get_bandwidth() + HamlibParam.hamlib_bandwidth = self.radio.get_bandwidth() threading.Event().wait(0.1) - static.HAMLIB_STATUS = self.radio.get_status() + HamlibParam.hamlib_status = self.radio.get_status() threading.Event().wait(0.1) - if static.TRANSMITTING: - static.HAMLIB_ALC = self.radio.get_alc() + if TNC.transmitting: + HamlibParam.alc = self.radio.get_alc() threading.Event().wait(0.1) - # static.HAMLIB_RF = self.radio.get_level() + # HamlibParam.hamlib_rf = self.radio.get_level() # threading.Event().wait(0.1) - static.HAMLIB_STRENGTH = self.radio.get_strength() + HamlibParam.hamlib_strength = self.radio.get_strength() - # print(f"ALC: {static.HAMLIB_ALC}, RF: {static.HAMLIB_RF}, STRENGTH: {static.HAMLIB_STRENGTH}") + # print(f"ALC: {HamlibParam.alc}, RF: {HamlibParam.hamlib_rf}, STRENGTH: {HamlibParam.hamlib_strength}") def calculate_fft(self) -> None: """ @@ -1195,7 +1195,7 @@ class RF: # Therefore we are setting it to 100 so it will be highlighted # Have to do this when we are not transmitting so our # own sending data will not affect this too much - if not static.TRANSMITTING: + if not TNC.transmitting: dfft[dfft > avg + 15] = 100 # Calculate audio dbfs @@ -1211,20 +1211,20 @@ class RF: rms = int(np.sqrt(np.max(d ** 2))) if rms == 0: raise ZeroDivisionError - static.AUDIO_DBFS = 20 * np.log10(rms / 32768) + AudioParam.audio_dbfs = 20 * np.log10(rms / 32768) except Exception as e: self.log.warning( "[MDM] fft calculation error - please check your audio setup", e=e, ) - static.AUDIO_DBFS = -100 + AudioParam.audio_dbfs = -100 rms_counter = 0 # Convert data to int to decrease size dfft = dfft.astype(int) - # Create list of dfft for later pushing to static.FFT + # Create list of dfft for later pushing to AudioParam.fft dfftlist = dfft.tolist() # Reduce area where the busy detection is enabled @@ -1250,14 +1250,14 @@ class RF: range_start = range[0] range_end = range[1] # define the area, we are detecting busy state - #dfft = dfft[120:176] if static.LOW_BANDWIDTH_MODE else dfft[65:231] + #dfft = dfft[120:176] if TNC.low_bandwidth_mode else dfft[65:231] dfft = dfft[range_start:range_end] # Check for signals higher than average by checking for "100" # If we have a signal, increment our channel_busy delay counter # so we have a smoother state toggle - if np.sum(dfft[dfft > avg + 15]) >= 400 and not static.TRANSMITTING: - static.CHANNEL_BUSY = True - static.CHANNEL_BUSY_SLOT[slot] = True + if np.sum(dfft[dfft > avg + 15]) >= 400 and not TNC.transmitting: + ModemParam.channel_busy = True + ModemParam.channel_busy_slot[slot] = True # Limit delay counter to a maximum of 200. The higher this value, # the longer we will wait until releasing state channel_busy_delay = min(channel_busy_delay + 10, 200) @@ -1266,18 +1266,18 @@ class RF: channel_busy_delay = max(channel_busy_delay - 1, 0) # When our channel busy counter reaches 0, toggle state to False if channel_busy_delay == 0: - static.CHANNEL_BUSY = False - static.CHANNEL_BUSY_SLOT[slot] = False + ModemParam.channel_busy = False + ModemParam.channel_busy_slot[slot] = False # increment slot slot += 1 - static.FFT = dfftlist[:315] # 315 --> bandwidth 3200 + AudioParam.fft = dfftlist[:315] # 315 --> bandwidth 3200 except Exception as err: self.log.error(f"[MDM] calculate_fft: Exception: {err}") self.log.debug("[MDM] Setting fft=0") # else 0 - static.FFT = [0] + AudioParam.fft = [0] def set_frames_per_burst(self, frames_per_burst: int) -> None: """ diff --git a/tnc/queues.py b/tnc/queues.py index f4659b2b..16974151 100644 --- a/tnc/queues.py +++ b/tnc/queues.py @@ -3,7 +3,7 @@ Hold queues used by more than one module to eliminate cyclic imports. """ import queue import static -from static import ARQ, Audio, Beacon, Channel, Daemon, Hamlib, Modem, Station, TCI, TNC +from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, TCIParam, TNC DATA_QUEUE_TRANSMIT = queue.Queue() DATA_QUEUE_RECEIVED = queue.Queue() @@ -17,7 +17,7 @@ AUDIO_RECEIVED_QUEUE = queue.Queue() AUDIO_TRANSMIT_QUEUE = queue.Queue() # Initialize FIFO queue to finally store received data -RX_BUFFER = queue.Queue(maxsize=static.RX_BUFFER_SIZE) +RX_BUFFER = queue.Queue(maxsize=ARQ.rx_buffer_size) # Commands we want to send to rigctld RIGCTLD_COMMAND_QUEUE = queue.Queue() \ No newline at end of file diff --git a/tnc/rigctld.py b/tnc/rigctld.py index 77dfdd6a..27bce855 100644 --- a/tnc/rigctld.py +++ b/tnc/rigctld.py @@ -10,10 +10,7 @@ import time import structlog import threading import static -from static import ARQ, Audio, Beacon, Channel, Daemon, Hamlib, Modem, Station, TCI, TNC - -# set global hamlib version -hamlib_version = 0 +from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, TCIParam class radio: @@ -244,7 +241,7 @@ class radio: if 'RPRT' not in alc: try: alc = float(alc) - self.alc = alc if alc != 0.0 else static.HAMLIB_ALC + self.alc = alc if alc != 0.0 else HamlibParam.alc except ValueError: self.alc = 0.0 diff --git a/tnc/sock.py b/tnc/sock.py index 529eb44b..3cdb1ac9 100644 --- a/tnc/sock.py +++ b/tnc/sock.py @@ -27,7 +27,7 @@ import time import wave import helpers import static -from static import ARQ, Audio, Beacon, Channel, Daemon, Hamlib, Modem, Station, TCI, TNC +from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, TNC import structlog from random import randrange import ujson as json @@ -68,7 +68,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): while self.connection_alive and not CLOSE_SIGNAL: # send tnc state as network stream # check server port against daemon port and send corresponding data - if self.server.server_address[1] == TNC.port and not static.TNCSTARTED: + if self.server.server_address[1] == TNC.port and not Daemon.tncstarted: data = send_tnc_state() if data != tempdata: tempdata = data @@ -99,9 +99,9 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): self.log.debug("[SCK] catch harmless RuntimeError: Set changed size during iteration", e=err) # we want to transmit scatter data only once to reduce network traffic - static.SCATTER = [] + ModemParam.scatter = [] # we want to display INFO messages only once - static.INFO = [] + #static.INFO = [] # self.request.sendall(sock_data) threading.Event().wait(0.15) @@ -355,14 +355,14 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): def tnc_set_listen(self, received_json): try: - static.LISTEN = received_json["state"] in ['true', 'True', True, "ON", "on"] + TNC.listen = received_json["state"] in ['true', 'True', True, "ON", "on"] command_response("listen", True) - # if tnc is connected, force disconnect when static.LISTEN == False - if not static.LISTEN and static.ARQ_SESSION_STATE not in ["disconnecting", "disconnected", "failed"]: + # if tnc is connected, force disconnect when TNC.listen == False + if not TNC.listen and ARQ.arq_session_state not in ["disconnecting", "disconnected", "failed"]: DATA_QUEUE_TRANSMIT.put(["DISCONNECT"]) # set early disconnecting state so we can interrupt connection attempts - static.ARQ_SESSION_STATE = "disconnecting" + ARQ.arq_session_state = "disconnecting" command_response("disconnect", True) except Exception as err: @@ -373,15 +373,15 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): def tnc_set_record_audio(self, received_json): try: - if not static.AUDIO_RECORD: - static.AUDIO_RECORD_FILE = wave.open(f"{int(time.time())}_audio_recording.wav", 'w') - static.AUDIO_RECORD_FILE.setnchannels(1) - static.AUDIO_RECORD_FILE.setsampwidth(2) - static.AUDIO_RECORD_FILE.setframerate(8000) - static.AUDIO_RECORD = True + if not AudioParam.audio_record: + AudioParam.audio_record_FILE = wave.open(f"{int(time.time())}_audio_recording.wav", 'w') + AudioParam.audio_record_FILE.setnchannels(1) + AudioParam.audio_record_FILE.setsampwidth(2) + AudioParam.audio_record_FILE.setframerate(8000) + AudioParam.audio_record = True else: - static.AUDIO_RECORD = False - static.AUDIO_RECORD_FILE.close() + AudioParam.audio_record = False + AudioParam.audio_record_FILE.close() command_response("respond_to_call", True) @@ -393,7 +393,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): def tnc_set_respond_to_call(self, received_json): try: - static.RESPOND_TO_CALL = received_json["state"] in ['true', 'True', True] + TNC.respond_to_call = received_json["state"] in ['true', 'True', True] command_response("respond_to_call", True) except Exception as err: @@ -404,7 +404,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): def tnc_set_respond_to_cq(self, received_json): try: - static.RESPOND_TO_CQ = received_json["state"] in ['true', 'True', True] + TNC.respond_to_cq = received_json["state"] in ['true', 'True', True] command_response("respond_to_cq", True) except Exception as err: @@ -415,7 +415,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): def tnc_set_tx_audio_level(self, received_json): try: - static.TX_AUDIO_LEVEL = int(received_json["value"]) + AudioParam.tx_audio_level = int(received_json["value"]) command_response("tx_audio_level", True) except Exception as err: @@ -482,7 +482,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): def tnc_start_beacon(self, received_json): try: - static.BEACON_STATE = True + Beacon.beacon_state = True interval = int(received_json["parameter"]) DATA_QUEUE_TRANSMIT.put(["BEACON", interval, True]) command_response("start_beacon", True) @@ -497,7 +497,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): def tnc_stop_beacon(self, received_json): try: log.warning("[SCK] Stopping beacon!") - static.BEACON_STATE = False + Beacon.beacon_state = False DATA_QUEUE_TRANSMIT.put(["BEACON", None, False]) command_response("stop_beacon", True) except Exception as err: @@ -528,7 +528,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): mycallsign = helpers.bytes_to_callsign(mycallsign) except Exception: - mycallsign = static.MYCALLSIGN + mycallsign = Station.mycallsign DATA_QUEUE_TRANSMIT.put(["PING", mycallsign, dxcallsign]) command_response("ping", True) @@ -544,7 +544,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): def tnc_arq_connect(self, received_json): # pause our beacon first - static.BEACON_PAUSE = True + Beacon.beacon_pause = True # check for connection attempts key try: @@ -562,7 +562,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): mycallsign = helpers.bytes_to_callsign(mycallsign) except Exception: - mycallsign = static.MYCALLSIGN + mycallsign = Station.mycallsign # additional step for being sure our callsign is correctly # in case we are not getting a station ssid @@ -570,11 +570,11 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): dxcallsign = helpers.callsign_to_bytes(dxcallsign) dxcallsign = helpers.bytes_to_callsign(dxcallsign) - if static.ARQ_SESSION_STATE not in ["disconnected", "failed"]: + if ARQ.arq_session_state not in ["disconnected", "failed"]: command_response("connect", False) log.warning( "[SCK] Connect command execution error", - e=f"already connected to station:{static.DXCALLSIGN}", + e=f"already connected to station:{Station.dxcallsign}", command=received_json, ) else: @@ -594,24 +594,24 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): command=received_json, ) # allow beacon transmission again - static.BEACON_PAUSE = False + Beacon.beacon_pause = False # allow beacon transmission again - static.BEACON_PAUSE = False + Beacon.beacon_pause = False def tnc_arq_disconnect(self, received_json): try: - if static.ARQ_SESSION_STATE not in ["disconnecting", "disconnected", "failed"]: + if ARQ.arq_session_state not in ["disconnecting", "disconnected", "failed"]: DATA_QUEUE_TRANSMIT.put(["DISCONNECT"]) # set early disconnecting state so we can interrupt connection attempts - static.ARQ_SESSION_STATE = "disconnecting" + ARQ.arq_session_state = "disconnecting" command_response("disconnect", True) else: command_response("disconnect", False) log.warning( "[SCK] Disconnect command not possible", - state=static.ARQ_SESSION_STATE, + state=ARQ.arq_session_state, command=received_json, ) except Exception as err: @@ -623,13 +623,13 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): ) def tnc_arq_send_raw(self, received_json): - static.BEACON_PAUSE = True + Beacon.beacon_pause = True # wait some random time helpers.wait(randrange(5, 25, 5) / 10.0) # we need to warn if already in arq state - if static.ARQ_STATE: + if ARQ.arq_state: command_response("send_raw", False) log.warning( "[SCK] Send raw command execution warning", @@ -639,19 +639,19 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): ) try: - if not static.ARQ_SESSION: + if not ARQ.arq_session: dxcallsign = received_json["parameter"][0]["dxcallsign"] # additional step for being sure our callsign is correctly # in case we are not getting a station ssid # then we are forcing a station ssid = 0 dxcallsign = helpers.callsign_to_bytes(dxcallsign) dxcallsign = helpers.bytes_to_callsign(dxcallsign) - static.DXCALLSIGN = dxcallsign - static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN) + Station.dxcallsign = dxcallsign + Station.dxcallsign_crc = helpers.get_crc_24(Station.dxcallsign) command_response("send_raw", True) else: - dxcallsign = static.DXCALLSIGN - static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN) + dxcallsign = Station.dxcallsign + Station.dxcallsign_crc = helpers.get_crc_24(Station.dxcallsign) mode = int(received_json["parameter"][0]["mode"]) n_frames = int(received_json["parameter"][0]["n_frames"]) @@ -664,7 +664,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): mycallsign = helpers.bytes_to_callsign(mycallsign) except Exception: - mycallsign = static.MYCALLSIGN + mycallsign = Station.mycallsign # check for connection attempts key try: @@ -698,11 +698,11 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): def tnc_arq_stop_transmission(self, received_json): try: - if static.TNC_STATE == "BUSY" or static.ARQ_STATE: + if TNC.tnc_state == "BUSY" or ARQ.arq_state: DATA_QUEUE_TRANSMIT.put(["STOP"]) log.warning("[SCK] Stopping transmission!") - static.TNC_STATE = "IDLE" - static.ARQ_STATE = False + TNC.tnc_state = "IDLE" + ARQ.arq_state = False command_response("stop_transmission", True) except Exception as err: command_response("stop_transmission", False) @@ -804,7 +804,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): if ( received_json["type"] == "set" and received_json["command"] == "start_tnc" - and not static.TNCSTARTED + and not Daemon.tncstarted ): self.daemon_start_tnc(received_json) @@ -822,18 +822,18 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): self.request.sendall(b"INVALID CALLSIGN") log.warning( "[SCK] SET MYCALL FAILED", - call=static.MYCALLSIGN, - crc=static.MYCALLSIGN_CRC.hex(), + call=Station.mycallsign, + crc=Station.mycallsign_crc.hex(), ) else: - static.MYCALLSIGN = bytes(callsign, "utf-8") - static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN) + Station.mycallsign = bytes(callsign, "utf-8") + Station.mycallsign_crc = helpers.get_crc_24(Station.mycallsign) command_response("mycallsign", True) log.info( "[SCK] SET MYCALL", - call=static.MYCALLSIGN, - crc=static.MYCALLSIGN_CRC.hex(), + call=Station.mycallsign, + crc=Station.mycallsign_crc.hex(), ) except Exception as err: command_response("mycallsign", False) @@ -847,8 +847,8 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): self.request.sendall(b"INVALID GRID") command_response("mygrid", False) else: - static.MYGRID = bytes(mygrid, "utf-8") - log.info("[SCK] SET MYGRID", grid=static.MYGRID) + Station.mygrid = bytes(mygrid, "utf-8") + log.info("[SCK] SET MYGRID", grid=Station.mygrid) command_response("mygrid", True) except Exception as err: command_response("mygrid", False) @@ -929,12 +929,12 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): def daemon_stop_tnc(self, received_json): try: - static.TNCPROCESS.kill() + Daemon.tncprocess.kill() # unregister process from atexit to avoid process zombies - atexit.unregister(static.TNCPROCESS.kill) + atexit.unregister(Daemon.tncprocess.kill) log.warning("[SCK] Stopping TNC") - static.TNCSTARTED = False + Daemon.tncstarted = False command_response("stop_tnc", True) except Exception as err: command_response("stop_tnc", False) @@ -973,15 +973,15 @@ def send_daemon_state(): "command": "daemon_state", "daemon_state": [], "python_version": str(python_version), - "input_devices": static.AUDIO_INPUT_DEVICES, - "output_devices": static.AUDIO_OUTPUT_DEVICES, - "serial_devices": static.SERIAL_DEVICES, + "input_devices": AudioParam.audio_input_devices, + "output_devices": AudioParam.audio_output_devices, + "serial_devices": Daemon.serial_devices, # 'cpu': str(psutil.cpu_percent()), # 'ram': str(psutil.virtual_memory().percent), "version": "0.1", } - if static.TNCSTARTED: + if Daemon.tncstarted: output["daemon_state"].append({"status": "running"}) else: output["daemon_state"].append({"status": "stopped"}) @@ -999,53 +999,53 @@ def send_tnc_state(): encoding = "utf-8" output = { "command": "tnc_state", - "ptt_state": str(static.PTT_STATE), - "tnc_state": str(static.TNC_STATE), - "arq_state": str(static.ARQ_STATE), - "arq_session": str(static.ARQ_SESSION), - "arq_session_state": str(static.ARQ_SESSION_STATE), - "audio_dbfs": str(static.AUDIO_DBFS), - "snr": str(static.SNR), - "frequency": str(static.HAMLIB_FREQUENCY), - "rf_level": str(static.HAMLIB_RF), - "strength": str(static.HAMLIB_STRENGTH), - "alc": str(static.HAMLIB_ALC), - "audio_level": str(static.TX_AUDIO_LEVEL), - "audio_auto_tune": str(static.AUDIO_AUTO_TUNE), - "speed_level": str(static.ARQ_SPEED_LEVEL), - "mode": str(static.HAMLIB_MODE), - "bandwidth": str(static.HAMLIB_BANDWIDTH), - "fft": str(static.FFT), - "channel_busy": str(static.CHANNEL_BUSY), - "channel_busy_slot": str(static.CHANNEL_BUSY_SLOT), - "is_codec2_traffic": str(static.IS_CODEC2_TRAFFIC), - "scatter": static.SCATTER, + "ptt_state": str(HamlibParam.ptt_state), + "tnc_state": str(TNC.tnc_state), + "arq_state": str(ARQ.arq_state), + "arq_session": str(ARQ.arq_session), + "arq_session_state": str(ARQ.arq_session_state), + "audio_dbfs": str(AudioParam.audio_dbfs), + "snr": str(ModemParam.snr), + "frequency": str(HamlibParam.hamlib_frequency), + "rf_level": str(HamlibParam.hamlib_rf), + "strength": str(HamlibParam.hamlib_strength), + "alc": str(HamlibParam.alc), + "audio_level": str(AudioParam.tx_audio_level), + "audio_auto_tune": str(AudioParam.audio_auto_tune), + "speed_level": str(ARQ.arq_speed_level), + "mode": str(HamlibParam.hamlib_mode), + "bandwidth": str(HamlibParam.hamlib_bandwidth), + "fft": str(AudioParam.fft), + "channel_busy": str(ModemParam.channel_busy), + "channel_busy_slot": str(ModemParam.channel_busy_slot), + "is_codec2_traffic": str(ModemParam.is_codec2_traffic), + "scatter": ModemParam.scatter, "rx_buffer_length": str(RX_BUFFER.qsize()), - "rx_msg_buffer_length": str(len(static.RX_MSG_BUFFER)), - "arq_bytes_per_minute": str(static.ARQ_BYTES_PER_MINUTE), - "arq_bytes_per_minute_burst": str(static.ARQ_BYTES_PER_MINUTE_BURST), - "arq_seconds_until_finish": str(static.ARQ_SECONDS_UNTIL_FINISH), - "arq_compression_factor": str(static.ARQ_COMPRESSION_FACTOR), - "arq_transmission_percent": str(static.ARQ_TRANSMISSION_PERCENT), - "speed_list": static.SPEED_LIST, - "total_bytes": str(static.TOTAL_BYTES), - "beacon_state": str(static.BEACON_STATE), + "rx_msg_buffer_length": str(len(ARQ.rx_msg_buffer)), + "arq_bytes_per_minute": str(ARQ.bytes_per_minute), + "arq_bytes_per_minute_burst": str(ARQ.bytes_per_minute_burst), + "arq_seconds_until_finish": str(ARQ.arq_seconds_until_finish), + "arq_compression_factor": str(ARQ.arq_compression_factor), + "arq_transmission_percent": str(ARQ.arq_transmission_percent), + "speed_list": ARQ.speed_list, + "total_bytes": str(ARQ.total_bytes), + "beacon_state": str(Beacon.beacon_state), "stations": [], - "mycallsign": str(static.MYCALLSIGN, encoding), - "mygrid": str(static.MYGRID, encoding), - "dxcallsign": str(static.DXCALLSIGN, encoding), - "dxgrid": str(static.DXGRID, encoding), - "hamlib_status": static.HAMLIB_STATUS, - "listen": str(static.LISTEN), - "audio_recording": str(static.AUDIO_RECORD), + "mycallsign": str(Station.mycallsign, encoding), + "mygrid": str(Station.mygrid, encoding), + "dxcallsign": str(Station.dxcallsign, encoding), + "dxgrid": str(Station.dxgrid, encoding), + "hamlib_status": HamlibParam.hamlib_status, + "listen": str(TNC.listen), + "audio_recording": str(AudioParam.audio_record), } # add heard stations to heard stations object - for heard in static.HEARD_STATIONS: + for heard in TNC.heard_stations: output["stations"].append( { - "dxcallsign": str(heard[0], "utf-8"), - "dxgrid": str(heard[1], "utf-8"), + "dxcallsign": str(heard[0], encoding), + "dxgrid": str(heard[1], encoding), "timestamp": heard[2], "datatype": heard[3], "snr": heard[4], diff --git a/tnc/static.py b/tnc/static.py index dcd81112..3e27e314 100644 --- a/tnc/static.py +++ b/tnc/static.py @@ -5,143 +5,144 @@ Created on Wed Dec 23 11:13:57 2020 @author: DJ2LS Here we are saving application wide variables and stats, which have to be accessed everywhere. -Not nice, suggestions are appreciated :-) """ - - - from dataclasses import dataclass, field from typing import List import subprocess from enum import Enum -CHANNEL_BUSY_SLOT = [False] * 5 -ENABLE_EXPLORER = False -ENABLE_STATS = False - - -# DAEMON - -TNCSTARTED: bool = False -TNCPROCESS: subprocess.Popen - -# Operator Defaults -MYCALLSIGN: bytes = b"AA0AA" -MYCALLSIGN_CRC: bytes = b"A" - -DXCALLSIGN: bytes = b"ZZ9YY" -DXCALLSIGN_CRC: bytes = b"A" - -MYGRID: bytes = b"" -DXGRID: bytes = b"" - -SSID_LIST: list = [] # ssid list we are responding to - -LOW_BANDWIDTH_MODE: bool = False -# --------------------------------- - -# Server Defaults - -# --------------------------------- -SERIAL_DEVICES: list = [] -# --------------------------------- -LISTEN: bool = True -PTT_STATE: bool = False -TRANSMITTING: bool = False - -HAMLIB_RADIOCONTROL: str = "disabled" -HAMLIB_RIGCTLD_IP: str = "127.0.0.1" -HAMLIB_RIGCTLD_PORT: str = "4532" - -HAMLIB_STATUS: str = "unknown/disconnected" -HAMLIB_FREQUENCY: int = 0 -HAMLIB_MODE: str = "" -HAMLIB_BANDWIDTH: int = 0 -HAMLIB_RF: int = 0 -HAMLIB_ALC: int = 0 -HAMLIB_STRENGTH: int = 0 -# ------------------------- -# FreeDV Defaults - -SNR: float = 0 -FREQ_OFFSET: float = 0 -SCATTER: list = [] -ENABLE_SCATTER: bool = False -ENABLE_FSK: bool = False -RESPOND_TO_CQ: bool = False -RESPOND_TO_CALL: bool = True # respond to cq, ping, connection request, file request if not in session -TX_DELAY: int = 0 # delay in ms before sending modulation for triggering VOX for example or slow PTT radios -# --------------------------------- - -# Audio Defaults -TX_AUDIO_LEVEL: int = 50 -AUDIO_INPUT_DEVICES: list = [] -AUDIO_OUTPUT_DEVICES: list = [] -AUDIO_INPUT_DEVICE: int = -2 -AUDIO_OUTPUT_DEVICE: int = -2 -AUDIO_RECORD: bool = False -AUDIO_RECORD_FILE = '' -BUFFER_OVERFLOW_COUNTER: list = [0, 0, 0, 0, 0] -AUDIO_AUTO_TUNE: bool = False -# Audio TCI Support -AUDIO_ENABLE_TCI: bool = False -TCI_IP: str = '127.0.0.1' -TCI_PORT: int = '9000' - -AUDIO_DBFS: int = 0 -FFT: list = [0] -ENABLE_FFT: bool = True -CHANNEL_BUSY: bool = False - -# ARQ PROTOCOL VERSION -# v.5 - signalling frame uses datac0 -# v.6 - signalling frame uses datac13 -ARQ_PROTOCOL_VERSION: int = 6 - -# ARQ statistics -SPEED_LIST: list = [] -ARQ_BYTES_PER_MINUTE_BURST: int = 0 -ARQ_BYTES_PER_MINUTE: int = 0 -ARQ_BITS_PER_SECOND_BURST: int = 0 -ARQ_BITS_PER_SECOND: int = 0 -ARQ_COMPRESSION_FACTOR: int = 0 -ARQ_TRANSMISSION_PERCENT: int = 0 -ARQ_SECONDS_UNTIL_FINISH: int = 0 -ARQ_SPEED_LEVEL: int = 0 -TOTAL_BYTES: int = 0 -# set save to folder state for allowing downloading files to local file system -ARQ_SAVE_TO_FOLDER: bool = False - # CHANNEL_STATE = 'RECEIVING_SIGNALLING' -TNC_STATE: str = "IDLE" -ARQ_STATE: bool = False -ARQ_SESSION: bool = False # disconnected, connecting, connected, disconnecting, failed -ARQ_SESSION_STATE: str = "disconnected" - -# BEACON STATE -BEACON_STATE: bool = False -BEACON_PAUSE: bool = False - # ------- RX BUFFER -RX_MSG_BUFFER: list = [] -RX_BURST_BUFFER: list = [] -RX_FRAME_BUFFER: bytes = b"" -RX_BUFFER_SIZE: int = 16 -# ------- HEARD STATIONS BUFFER -HEARD_STATIONS: list = [] +@dataclass +class ARQ: + bytes_per_minute: int = 0 + arq_transmission_percent: int = 0 + arq_compression_factor: int = 0 + arq_speed_level: int = 0 + arq_bits_per_second_burst: int = 0 + arq_bits_per_second: int = 0 + arq_seconds_until_finish: int = 0 + rx_buffer_size: int = 16 + rx_frame_buffer: bytes = b"" + rx_burst_buffer =[] + arq_session_state: str = "disconnected" + arq_session: bool = False + arq_state: bool = False + # ARQ PROTOCOL VERSION + # v.5 - signalling frame uses datac0 + # v.6 - signalling frame uses datac13 + arq_protocol_version: int = 6 + total_bytes: int = 0 + speed_list = [] + # set save to folder state for allowing downloading files to local file system + arq_save_to_folder: bool = False + bytes_per_minute_burst: int = 0 + rx_msg_buffer = [] -# ------- INFO MESSAGE BUFFER -# TODO: This can be removed? -INFO: list = [] -# ------- CODEC2 SETTINGS -TUNING_RANGE_FMIN: float = -50.0 -TUNING_RANGE_FMAX: float = 50.0 -IS_CODEC2_TRAFFIC: bool = False # true if we have codec2 signalling mode traffic on channel +@dataclass +class AudioParam: + tx_audio_level: int = 50 + audio_input_devices = [] + audio_output_devices = [] + audio_input_device: int = -2 + audio_output_device: int = -2 + audio_record: bool = False + audio_record_file = '' + buffer_overflow_counter = [] + audio_auto_tune: bool = False + # Audio TCI Support + audio_enable_tci: bool = False + audio_dbfs: int = 0 + fft = [] + enable_fft: bool = True + + +@dataclass +class Beacon: + beacon_state: bool = False + beacon_pause: bool = False + +@dataclass +class Channel: + pass + +@dataclass +class Daemon: + tncprocess: subprocess.Popen + tncstarted: bool = False + port: int = 3001 + serial_devices = [] + +@dataclass +class HamlibParam: + alc: int = 0 + hamlib_frequency: int = 0 + hamlib_strength: int = 0 + hamlib_radiocontrol: str = "disabled" + hamlib_rigctld_ip: str = "127.0.0.1" + hamlib_rigctld_port: str = "4532" + ptt_state: bool = False + hamlib_bandwidth: int = 0 + hamlib_status: str = "unknown/disconnected" + hamlib_mode: str = "" + hamlib_rf: int = 0 + +@dataclass +class ModemParam: + tuning_range_fmin: float = -50.0 + tuning_range_fmax: float = 50.0 + channel_busy: bool = False + channel_busy_slot = [False] * 5 + snr: float = 0 + is_codec2_traffic: bool = False # true if we have codec2 signalling mode traffic on channel + frequency_offset: float = 0 + tx_delay: int = 0 # delay in ms before sending modulation for triggering VOX for example or slow PTT radios + enable_scatter: bool = False + scatter = [] + +@dataclass +class Station: + mycallsign: bytes = b"AA0AA" + mycallsign_crc: bytes = b"A" + dxcallsign: bytes = b"ZZ9YY" + dxcallsign_crc: bytes = b"A" + mygrid: bytes = b"" + dxgrid: bytes = b"" + ssid_list = [] # ssid list we are responding to + + +@dataclass +class Statistics: + pass + +@dataclass +class TCIParam: + ip: str = '127.0.0.1' + port: int = '9000' + +@dataclass +class TNC: + version = "0.9.0-alpha-exp.5" + host: str = "0.0.0.0" + port: int = 3000 + SOCKET_TIMEOUT: int = 1 # seconds + tnc_state: str = "IDLE" + enable_explorer = False + enable_stats = False + transmitting: bool = False + low_bandwidth_mode: bool = False + enable_fsk: bool = False + respond_to_cq: bool = False + respond_to_call: bool = True # respond to cq, ping, connection request, file request if not in session + heard_stations = [] + listen: bool = True + + # ------------ class FRAME_TYPE(Enum): @@ -176,50 +177,3 @@ class FRAME_TYPE(Enum): IDENT = 254 TEST_FRAME = 255 - - -# TODO: Move settings above to dataclasses - -@dataclass -class ARQ: - pass - -@dataclass -class Audio: - pass - -@dataclass -class Beacon: - pass - -@dataclass -class Channel: - pass - -@dataclass -class Daemon: - port: int = 3001 - -@dataclass -class Hamlib: - pass - -@dataclass -class Modem: - pass - -@dataclass -class Station: - pass - -@dataclass -class TCI: - pass - -@dataclass -class TNC: - version = "0.9.0-alpha-exp.5" - host: str = "0.0.0.0" - port: int = 3000 - SOCKET_TIMEOUT: int = 1 # seconds - diff --git a/tnc/stats.py b/tnc/stats.py index 8aa17426..4fb9731c 100644 --- a/tnc/stats.py +++ b/tnc/stats.py @@ -13,7 +13,7 @@ import time import ujson as json import structlog import static -from static import ARQ, Audio, Beacon, Channel, Daemon, Hamlib, Modem, Station, TCI, TNC +from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, TCIParam, TNC log = structlog.get_logger("stats") @@ -26,29 +26,29 @@ class stats(): crcerror = status in ["crc_error", "wrong_crc"] # get avg snr try: - snr_raw = [item["snr"] for item in static.SPEED_LIST] + snr_raw = [item["snr"] for item in ARQ.speed_list] avg_snr = round(sum(snr_raw) / len(snr_raw), 2 ) except Exception: avg_snr = 0 headers = {"Content-Type": "application/json"} station_data = { - 'callsign': str(static.MYCALLSIGN, "utf-8"), - 'dxcallsign': str(static.DXCALLSIGN, "utf-8"), - 'gridsquare': str(static.MYGRID, "utf-8"), - 'dxgridsquare': str(static.DXGRID, "utf-8"), - 'frequency': 0 if static.HAMLIB_FREQUENCY is None else static.HAMLIB_FREQUENCY, + 'callsign': str(Station.mycallsign, "utf-8"), + 'dxcallsign': str(Station.dxcallsign, "utf-8"), + 'gridsquare': str(Station.mygrid, "utf-8"), + 'dxgridsquare': str(Station.dxgrid, "utf-8"), + 'frequency': 0 if HamlibParam.hamlib_frequency is None else HamlibParam.hamlib_frequency, 'avgstrength': 0, 'avgsnr': avg_snr, - 'bytesperminute': static.ARQ_BYTES_PER_MINUTE, - 'filesize': static.TOTAL_BYTES, - 'compressionfactor': static.ARQ_COMPRESSION_FACTOR, + 'bytesperminute': ARQ.bytes_per_minute, + 'filesize': ARQ.total_bytes, + 'compressionfactor': ARQ.arq_compression_factor, 'nacks': frame_nack_counter, 'crcerror': crcerror, 'duration': duration, - 'percentage': static.ARQ_TRANSMISSION_PERCENT, + 'percentage': ARQ.arq_transmission_percent, 'status': status, - 'version': static.VERSION + 'version': TNC.version } station_data = json.dumps(station_data) diff --git a/tnc/tci.py b/tnc/tci.py index cfa3629c..7b7b6ff2 100644 --- a/tnc/tci.py +++ b/tnc/tci.py @@ -7,9 +7,9 @@ import websocket import numpy as np import time from queues import AUDIO_TRANSMIT_QUEUE, AUDIO_RECEIVED_QUEUE -from static import ARQ, Audio, Beacon, Channel, Daemon, Hamlib, Modem, Station, TCI, TNC +from static import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, TCIParam, TNC -class TCI: +class TCICtrl: def __init__(self, hostname='127.0.0.1', port=50001): # websocket.enableTrace(True) self.log = structlog.get_logger("TCI")