From b6face744bbe37623b8187a10e49afb6f670a58c Mon Sep 17 00:00:00 2001 From: DJ2LS <75909252+DJ2LS@users.noreply.github.com> Date: Mon, 23 May 2022 09:37:24 +0200 Subject: [PATCH 1/8] First run reducing number of problems --- tnc/audio.py | 28 +++--- tnc/codec2.py | 102 ++++++++++--------- tnc/daemon.py | 21 ++-- tnc/data_handler.py | 234 +++++++++++++++++++++----------------------- tnc/helpers.py | 123 ++++++++++++----------- 5 files changed, 259 insertions(+), 249 deletions(-) diff --git a/tnc/audio.py b/tnc/audio.py index 23c438dd..8bc66894 100644 --- a/tnc/audio.py +++ b/tnc/audio.py @@ -1,22 +1,20 @@ import atexit -import json import multiprocessing -import sys - import sounddevice as sd atexit.register(sd._terminate) + def get_audio_devices(): """ return list of input and output audio devices in own process to avoid crashes of portaudio on raspberry pi also uses a process data manager """ - # we need to run this on windows for multiprocessing support + # we need to run this on Windows for multiprocessing support # multiprocessing.freeze_support() - #multiprocessing.get_context('spawn') + # multiprocessing.get_context('spawn') # we need to reset and initialize sounddevice before running the multiprocessing part. # If we are not doing this at this early point, not all devices will be displayed @@ -26,41 +24,41 @@ def get_audio_devices(): with multiprocessing.Manager() as manager: proxy_input_devices = manager.list() proxy_output_devices = manager.list() - #print(multiprocessing.get_start_method()) + # print(multiprocessing.get_start_method()) p = multiprocessing.Process(target=fetch_audio_devices, args=(proxy_input_devices, proxy_output_devices)) p.start() p.join() return list(proxy_input_devices), list(proxy_output_devices) + def fetch_audio_devices(input_devices, output_devices): """ get audio devices from portaudio Args: input_devices: proxy variable for input devices - output_devices: proxy variable for outout devices + output_devices: proxy variable for output devices Returns: """ devices = sd.query_devices(device=None, kind=None) for index, device in enumerate(devices): - #for i in range(0, p.get_device_count()): - # we need to do a try exception, beacuse for windows theres no audio device range + # we need to do a try exception, because for windows there's no audio device range try: name = device["name"] - maxOutputChannels = device["max_output_channels"] - maxInputChannels = device["max_input_channels"] + max_output_channels = device["max_output_channels"] + max_input_channels = device["max_input_channels"] except Exception as e: print(e) - maxInputChannels = 0 - maxOutputChannels = 0 + max_input_channels = 0 + max_output_channels = 0 name = '' - if maxInputChannels > 0: + if max_input_channels > 0: input_devices.append({"id": index, "name": name}) - if maxOutputChannels > 0: + if max_output_channels > 0: output_devices.append({"id": index, "name": name}) diff --git a/tnc/codec2.py b/tnc/codec2.py index adb9f025..ad1be938 100644 --- a/tnc/codec2.py +++ b/tnc/codec2.py @@ -22,11 +22,11 @@ class FREEDV_MODE(Enum): """ fsk_ldpc_0 = 200 fsk_ldpc_1 = 201 - fsk_ldpc = 9 - datac0 = 14 - datac1 = 10 - datac3 = 12 - allmodes = 255 + fsk_ldpc = 9 + datac0 = 14 + datac1 = 10 + datac3 = 12 + allmodes = 255 # Function for returning the mode value @@ -42,6 +42,7 @@ def freedv_get_mode_value_by_name(mode: str) -> int: """ return FREEDV_MODE[mode].value + # Function for returning the mode name def freedv_get_mode_name_by_value(mode: int) -> str: """ @@ -54,6 +55,7 @@ def freedv_get_mode_name_by_value(mode: int) -> str: """ return FREEDV_MODE(mode).name + # Check if we are running in a pyinstaller environment if hasattr(sys, "_MEIPASS"): sys.path.append(getattr(sys, "_MEIPASS")) @@ -62,12 +64,12 @@ else: structlog.get_logger("structlog").info("[C2 ] Searching for libcodec2...") if sys.platform == 'linux': - files = glob.glob(r'**/*libcodec2*',recursive=True) + files = glob.glob(r'**/*libcodec2*', recursive=True) files.append('libcodec2.so') elif sys.platform == 'darwin': - files = glob.glob(r'**/*libcodec2*.dylib',recursive=True) + files = glob.glob(r'**/*libcodec2*.dylib', recursive=True) elif sys.platform in ['win32', 'win64']: - files = glob.glob(r'**\*libcodec2*.dll',recursive=True) + files = glob.glob(r'**\*libcodec2*.dll', recursive=True) else: files = [] @@ -87,8 +89,8 @@ if api is None or 'api' not in locals(): # ctypes function init -#api.freedv_set_tuning_range.restype = ctypes.c_int -#api.freedv_set_tuning_range.argype = [ctypes.c_void_p, ctypes.c_float, ctypes.c_float] +# api.freedv_set_tuning_range.restype = ctypes.c_int +# api.freedv_set_tuning_range.argype = [ctypes.c_void_p, ctypes.c_float, ctypes.c_float] api.freedv_open.argype = [ctypes.c_int] api.freedv_open.restype = ctypes.c_void_p @@ -138,12 +140,13 @@ api.freedv_get_n_tx_modem_samples.restype = ctypes.c_int api.freedv_get_n_max_modem_samples.argtype = [ctypes.c_void_p] api.freedv_get_n_max_modem_samples.restype = ctypes.c_int -api.FREEDV_FS_8000 = 8000 -api.FREEDV_MODE_DATAC1 = 10 -api.FREEDV_MODE_DATAC3 = 12 -api.FREEDV_MODE_DATAC0 = 14 +api.FREEDV_FS_8000 = 8000 +api.FREEDV_MODE_DATAC1 = 10 +api.FREEDV_MODE_DATAC3 = 12 +api.FREEDV_MODE_DATAC0 = 14 api.FREEDV_MODE_FSK_LDPC = 9 + # -------------------------------- FSK LDPC MODE SETTINGS # Advanced structure for fsk modes @@ -159,6 +162,7 @@ class ADVANCED(ctypes.Structure): ("codename", ctypes.c_char_p), ] + ''' adv.interleave_frames = 0 # max amplitude adv.M = 2 # number of fsk tones 2/4 @@ -186,9 +190,9 @@ api.FREEDV_MODE_FSK_LDPC_0_ADV.interleave_frames = 0 api.FREEDV_MODE_FSK_LDPC_0_ADV.M = 4 api.FREEDV_MODE_FSK_LDPC_0_ADV.Rs = 100 api.FREEDV_MODE_FSK_LDPC_0_ADV.Fs = 8000 -api.FREEDV_MODE_FSK_LDPC_0_ADV.first_tone = 1400 # 1150 4fsk, 1500 2fsk -api.FREEDV_MODE_FSK_LDPC_0_ADV.tone_spacing = 120 #200 -api.FREEDV_MODE_FSK_LDPC_0_ADV.codename = 'H_128_256_5'.encode('utf-8') # code word +api.FREEDV_MODE_FSK_LDPC_0_ADV.first_tone = 1400 # 1150 4fsk, 1500 2fsk +api.FREEDV_MODE_FSK_LDPC_0_ADV.tone_spacing = 120 # 200 +api.FREEDV_MODE_FSK_LDPC_0_ADV.codename = 'H_128_256_5'.encode('utf-8') # code word # --------------- 4 H_256_512_4, 7 bytes api.FREEDV_MODE_FSK_LDPC_1_ADV = ADVANCED() @@ -196,18 +200,19 @@ api.FREEDV_MODE_FSK_LDPC_1_ADV.interleave_frames = 0 api.FREEDV_MODE_FSK_LDPC_1_ADV.M = 4 api.FREEDV_MODE_FSK_LDPC_1_ADV.Rs = 100 api.FREEDV_MODE_FSK_LDPC_1_ADV.Fs = 8000 -api.FREEDV_MODE_FSK_LDPC_1_ADV.first_tone = 1250 # 1250 4fsk, 1500 2fsk +api.FREEDV_MODE_FSK_LDPC_1_ADV.first_tone = 1250 # 1250 4fsk, 1500 2fsk api.FREEDV_MODE_FSK_LDPC_1_ADV.tone_spacing = 200 -api.FREEDV_MODE_FSK_LDPC_1_ADV.codename = 'H_256_512_4'.encode('utf-8') # code word +api.FREEDV_MODE_FSK_LDPC_1_ADV.codename = 'H_256_512_4'.encode('utf-8') # code word # ------- MODEM STATS STRUCTURES -MODEM_STATS_NC_MAX = 50 + 1 -MODEM_STATS_NR_MAX = 160 -MODEM_STATS_ET_MAX = 8 -MODEM_STATS_EYE_IND_MAX = 160 -MODEM_STATS_NSPEC = 512 -MODEM_STATS_MAX_F_HZ = 4000 -MODEM_STATS_MAX_F_EST = 4 +MODEM_STATS_NC_MAX = 50 + 1 +MODEM_STATS_NR_MAX = 160 +MODEM_STATS_ET_MAX = 8 +MODEM_STATS_EYE_IND_MAX = 160 +MODEM_STATS_NSPEC = 512 +MODEM_STATS_MAX_F_HZ = 4000 +MODEM_STATS_MAX_F_EST = 4 + # Modem stats structure class MODEMSTATS(ctypes.Structure): @@ -215,7 +220,7 @@ class MODEMSTATS(ctypes.Structure): _fields_ = [ ("Nc", ctypes.c_int), ("snr_est", ctypes.c_float), - ("rx_symbols", (ctypes.c_float * MODEM_STATS_NR_MAX)*MODEM_STATS_NC_MAX), + ("rx_symbols", (ctypes.c_float * MODEM_STATS_NR_MAX) * MODEM_STATS_NC_MAX), ("nr", ctypes.c_int), ("sync", ctypes.c_int), ("foff", ctypes.c_float), @@ -225,17 +230,18 @@ class MODEMSTATS(ctypes.Structure): ("pre", ctypes.c_int), ("post", ctypes.c_int), ("uw_fails", ctypes.c_int), - ("neyetr", ctypes.c_int), # How many eye traces are plotted - ("neyesamp", ctypes.c_int), # How many samples in the eye diagram - ("f_est", (ctypes.c_float * MODEM_STATS_MAX_F_EST)), # How many samples in the eye diagram + ("neyetr", ctypes.c_int), # How many eye traces are plotted + ("neyesamp", ctypes.c_int), # How many samples in the eye diagram + ("f_est", (ctypes.c_float * MODEM_STATS_MAX_F_EST)), # How many samples in the eye diagram ("fft_buf", (ctypes.c_float * MODEM_STATS_NSPEC * 2)), ] + # Return code flags for freedv_get_rx_status() function -api.FREEDV_RX_TRIAL_SYNC = 0x1 # demodulator has trial sync -api.FREEDV_RX_SYNC = 0x2 # demodulator has sync -api.FREEDV_RX_BITS = 0x4 # data bits have been returned -api.FREEDV_RX_BIT_ERRORS = 0x8 # FEC may not have corrected all bit errors (not all parity checks OK) +api.FREEDV_RX_TRIAL_SYNC = 0x1 # demodulator has trial sync +api.FREEDV_RX_SYNC = 0x2 # demodulator has sync +api.FREEDV_RX_BITS = 0x4 # data bits have been returned +api.FREEDV_RX_BIT_ERRORS = 0x8 # FEC may not have corrected all bit errors (not all parity checks OK) api.rx_sync_flags_to_text = [ "----", @@ -255,6 +261,7 @@ api.rx_sync_flags_to_text = [ "EBS-", "EBST"] + # Audio buffer --------------------------------------------------------- class audio_buffer: """ @@ -262,6 +269,7 @@ class audio_buffer: made by David Rowe, VK5DGR """ + # A buffer of int16 samples, using a fixed length numpy array self.buffer for storage # self.nbuffer is the current number of samples in the buffer def __init__(self, size): @@ -271,7 +279,7 @@ class audio_buffer: self.nbuffer = 0 self.mutex = Lock() - def push(self,samples): + def push(self, samples): """ Push new data to buffer @@ -283,12 +291,12 @@ class audio_buffer: """ self.mutex.acquire() # Add samples at the end of the buffer - assert self.nbuffer+len(samples) <= self.size - self.buffer[self.nbuffer:self.nbuffer+len(samples)] = samples + assert self.nbuffer + len(samples) <= self.size + self.buffer[self.nbuffer:self.nbuffer + len(samples)] = samples self.nbuffer += len(samples) self.mutex.release() - def pop(self,size): + def pop(self, size): """ get data from buffer in size of NIN Args: @@ -300,18 +308,20 @@ class audio_buffer: self.mutex.acquire() # Remove samples from the start of the buffer self.nbuffer -= size - self.buffer[:self.nbuffer] = self.buffer[size:size+self.nbuffer] + self.buffer[:self.nbuffer] = self.buffer[size:size + self.nbuffer] assert self.nbuffer >= 0 self.mutex.release() + # Resampler --------------------------------------------------------- -api.FDMDV_OS_48 = int(6) # oversampling rate -api.FDMDV_OS_TAPS_48K = int(48) # number of OS filter taps at 48kHz -api.FDMDV_OS_TAPS_48_8K = int(api.FDMDV_OS_TAPS_48K/api.FDMDV_OS_48) # number of OS filter taps at 8kHz +api.FDMDV_OS_48 = 6 # oversampling rate +api.FDMDV_OS_TAPS_48K = 48 # number of OS filter taps at 48kHz +api.FDMDV_OS_TAPS_48_8K = api.FDMDV_OS_TAPS_48K // api.FDMDV_OS_48 # number of OS filter taps at 8kHz api.fdmdv_8_to_48_short.argtype = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int] api.fdmdv_48_to_8_short.argtype = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int] + class resampler: """ Re-sampler class @@ -340,7 +350,7 @@ class resampler: assert len(in48) % api.FDMDV_OS_48 == 0 # Concatenate filter memory and input samples - in48_mem = np.zeros(self.MEM48+len(in48), dtype=np.int16) + in48_mem = np.zeros(self.MEM48 + len(in48), dtype=np.int16) in48_mem[:self.MEM48] = self.filter_mem48 in48_mem[self.MEM48:] = in48 @@ -368,14 +378,14 @@ class resampler: assert in8.dtype == np.int16 # Concatenate filter memory and input samples - in8_mem = np.zeros(self.MEM8+len(in8), dtype=np.int16) + in8_mem = np.zeros(self.MEM8 + len(in8), dtype=np.int16) in8_mem[:self.MEM8] = self.filter_mem8 in8_mem[self.MEM8:] = in8 # In C: pin8=&in8_mem[MEM8] pin8 = ctypes.byref(np.ctypeslib.as_ctypes(in8_mem), 2 * self.MEM8) - out48 = np.zeros(api.FDMDV_OS_48*len(in8), dtype=np.int16) - api.fdmdv_8_to_48_short(out48.ctypes, pin8, len(in8)); + out48 = np.zeros(api.FDMDV_OS_48 * len(in8), dtype=np.int16) + api.fdmdv_8_to_48_short(out48.ctypes, pin8, len(in8)) # Store memory for next time self.filter_mem8 = in8_mem[:self.MEM8] diff --git a/tnc/daemon.py b/tnc/daemon.py index d1729887..efc30f5e 100755 --- a/tnc/daemon.py +++ b/tnc/daemon.py @@ -15,8 +15,6 @@ import argparse import atexit import multiprocessing import os -import queue -import re import signal import socketserver import subprocess @@ -25,13 +23,11 @@ import threading import time import crcengine -import psutil import serial.tools.list_ports import structlog import ujson as json import audio -import helpers import log_handler import sock import static @@ -51,9 +47,11 @@ def signal_handler(sig, frame): sock.CLOSE_SIGNAL = True sys.exit(0) + signal.signal(signal.SIGINT, signal_handler) -class DAEMON(): + +class DAEMON: """ Daemon class @@ -100,7 +98,7 @@ class DAEMON(): crc_hwid = crc_hwid.to_bytes(2, byteorder='big') crc_hwid = crc_hwid.hex() description = f"{desc} [{crc_hwid}]" - serial_devices.append({"port": str(port), "description": str(description) }) + serial_devices.append({"port": str(port), "description": str(description)}) static.SERIAL_DEVICES = serial_devices time.sleep(1) @@ -215,8 +213,9 @@ class DAEMON(): options.append('--tuning_range_fmax') options.append(data[20]) + # overriding FSK mode - #if data[21] == 'True': + # if data[21] == 'True': # options.append('--fsk') options.append('--tx-audio-level') @@ -304,7 +303,7 @@ class DAEMON(): serialspeed=serialspeed, pttport=pttport, data_bits=data_bits, stop_bits=stop_bits, handshake=handshake, rigctld_ip=rigctld_ip, rigctld_port = rigctld_port) - hamlib_version = rig.hamlib_version + # hamlib_version = rig.hamlib_version hamlib.set_ptt(True) pttstate = hamlib.get_ptt() @@ -327,10 +326,10 @@ class DAEMON(): except Exception as e: structlog.get_logger("structlog").error("[DMN] worker: Exception: ", e=e) - # print(e) + if __name__ == '__main__': - # we need to run this on windows for multiprocessing support + # we need to run this on Windows for multiprocessing support multiprocessing.freeze_support() # --------------------------------------------GET PARAMETER INPUTS @@ -354,7 +353,7 @@ if __name__ == '__main__': os.makedirs(logging_path) log_handler.setup_logging(logging_path) except Exception as e: - structlog.get_logger("structlog").error("[DMN] logger init error", exception=e) + structlog.get_logger("structlog").error("[DMN] logger init error", exception=e) try: structlog.get_logger("structlog").info("[DMN] Starting TCP/IP socket", port=static.DAEMONPORT) diff --git a/tnc/data_handler.py b/tnc/data_handler.py index 2c2c1594..74a9578e 100644 --- a/tnc/data_handler.py +++ b/tnc/data_handler.py @@ -8,9 +8,7 @@ Created on Sun Dec 27 20:43:40 2020 # pylint: disable=invalid-name, line-too-long, c-extension-no-member # pylint: disable=import-outside-toplevel -import asyncio import base64 -import logging import queue import sys import threading @@ -25,7 +23,6 @@ import ujson as json import codec2 import helpers -import log_handler import modem import sock import static @@ -39,7 +36,7 @@ DATA_QUEUE_RECEIVED = queue.Queue() class DATA(): """ Terminal Node Controller for FreeDATA """ def __init__(self): - self.mycallsign = static.MYCALLSIGN # initial callsign. Will be overwritten later + self.mycallsign = static.MYCALLSIGN # initial callsign. Will be overwritten later self.data_queue_transmit = DATA_QUEUE_TRANSMIT self.data_queue_received = DATA_QUEUE_RECEIVED @@ -56,19 +53,19 @@ class DATA(): self.received_mycall_crc = b'' # Received my callsign crc if we received a crc for another ssid self.data_channel_last_received = 0.0 # time of last "live sign" of a frame - self.burst_ack_snr = 0 # SNR from received ack frames - self.burst_ack = False # if we received an acknowledge frame for a burst - self.data_frame_ack_received = False # if we received an acknowledge frame for a data frame - self.rpt_request_received = False # if we received an request for repeater frames - self.rpt_request_buffer = [] # requested frames, saved in a list - self.rx_start_of_transmission = 0 # time of transmission start - self.data_frame_bof = b'BOF' # 2 bytes for the BOF End of File indicator in a data frame - self.data_frame_eof = b'EOF' # 2 bytes for the EOF End of File indicator in a data frame + self.burst_ack_snr = 0 # SNR from received ack frames + self.burst_ack = False # if we received an acknowledge frame for a burst + self.data_frame_ack_received = False # if we received an acknowledge frame for a data frame + self.rpt_request_received = False # if we received an request for repeater frames + self.rpt_request_buffer = [] # requested frames, saved in a list + self.rx_start_of_transmission = 0 # time of transmission start + self.data_frame_bof = b'BOF' # 2 bytes for the BOF End of File indicator in a data frame + self.data_frame_eof = b'EOF' # 2 bytes for the EOF End of File indicator in a data frame self.rx_n_max_retries_per_burst = 50 self.n_retries_per_burst = 0 - self.received_low_bandwith_mode = False # indicator if we recevied a low bandwith mode channel opener + self.received_low_bandwith_mode = False # indicator if we recevied a low bandwith mode channel opener self.data_channel_max_retries = 5 self.datachannel_timeout = False @@ -76,19 +73,19 @@ class DATA(): self.mode_list_low_bw = [14, 12] self.time_list_low_bw = [3, 7] - self.mode_list_high_bw = [14, 12, 10] #201 = FSK mode list of available modes, each mode will be used 2times per speed level - self.time_list_high_bw = [3, 7, 8, 30] # list for time to wait for correspinding mode in seconds + self.mode_list_high_bw = [14, 12, 10] # 201 = FSK mode list of available modes, each mode will be used 2times per speed level + self.time_list_high_bw = [3, 7, 8, 30] # list for time to wait for correspinding mode in seconds # mode list for selecting between low bandwith ( 500Hz ) and normal modes with higher bandwith if static.LOW_BANDWITH_MODE: - self.mode_list = self.mode_list_low_bw # mode list of available modes, each mode will be used 2times per speed level - self.time_list = self.time_list_low_bw # list for time to wait for correspinding mode in seconds + self.mode_list = self.mode_list_low_bw # mode list of available modes, each mode will be used 2times per speed level + self.time_list = self.time_list_low_bw # list for time to wait for correspinding mode in seconds else: - self.mode_list = self.mode_list_high_bw # mode list of available modes, each mode will be used 2times per speed level - self.time_list = self.time_list_high_bw # list for time to wait for correspinding mode in seconds + self.mode_list = self.mode_list_high_bw # mode list of available modes, each mode will be used 2times per speed level + self.time_list = self.time_list_high_bw # list for time to wait for correspinding mode in seconds - self.speed_level = len(self.mode_list) - 1 # speed level for selecting mode + self.speed_level = len(self.mode_list) - 1 # speed level for selecting mode static.ARQ_SPEED_LEVEL = self.speed_level self.is_IRS = False @@ -101,21 +98,21 @@ class DATA(): self.transmission_timeout = 360 # transmission timeout in seconds - worker_thread_transmit = threading.Thread(target=self.worker_transmit, name="worker thread transmit",daemon=True) + worker_thread_transmit = threading.Thread(target=self.worker_transmit, name="worker thread transmit", daemon=True) worker_thread_transmit.start() - worker_thread_receive = threading.Thread(target=self.worker_receive, name="worker thread receive",daemon=True) + worker_thread_receive = threading.Thread(target=self.worker_receive, name="worker thread receive", daemon=True) worker_thread_receive.start() # START THE THREAD FOR THE TIMEOUT WATCHDOG - watchdog_thread = threading.Thread(target=self.watchdog, name="watchdog",daemon=True) + watchdog_thread = threading.Thread(target=self.watchdog, name="watchdog", daemon=True) watchdog_thread.start() - arq_session_thread = threading.Thread(target=self.heartbeat, name="watchdog",daemon=True) + arq_session_thread = threading.Thread(target=self.heartbeat, name="watchdog", daemon=True) arq_session_thread.start() self.beacon_interval = 0 - self.beacon_thread = threading.Thread(target=self.run_beacon, name="watchdog",daemon=True) + self.beacon_thread = threading.Thread(target=self.run_beacon, name="watchdog", daemon=True) self.beacon_thread.start() def worker_transmit(self): @@ -204,7 +201,7 @@ class DATA(): if 50 >= frametype >= 10: # get snr of received data - #snr = self.calculate_snr(freedv) + # snr = self.calculate_snr(freedv) # we need to find a way of fixing this because after moving to class system this doesn't work anymore snr = static.SNR structlog.get_logger("structlog").debug("[TNC] RX SNR", snr=snr) @@ -212,7 +209,7 @@ class DATA(): self.arq_data_received(bytes(bytes_out[:-2]), bytes_per_frame, snr, freedv) # 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 static.RX_BURST_BUFFER.count(None) <= 1 or (frame+1) == n_frames_per_burst: # structlog.get_logger("structlog").debug(f"[TNC] LAST FRAME OF BURST --> UNSYNC {frame+1}/{n_frames_per_burst}") # self.c_lib.freedv_set_sync(freedv, 0) @@ -339,8 +336,8 @@ class DATA(): def send_burst_ack_frame(self, snr): """ Build and send ACK frame for burst DATA frame """ - ack_frame = bytearray(14) - ack_frame[:1] = bytes([60]) + ack_frame = bytearray(14) + ack_frame[:1] = bytes([60]) ack_frame[1:4] = static.DXCALLSIGN_CRC ack_frame[4:7] = static.MYCALLSIGN_CRC ack_frame[7:8] = bytes([int(snr)]) @@ -351,8 +348,8 @@ class DATA(): def send_data_ack_frame(self, snr): """ Build and send ACK frame for received DATA frame """ - ack_frame = bytearray(14) - ack_frame[:1] = bytes([61]) + ack_frame = bytearray(14) + ack_frame[:1] = bytes([61]) ack_frame[1:4] = static.DXCALLSIGN_CRC ack_frame[4:7] = static.MYCALLSIGN_CRC ack_frame[7:8] = bytes([int(snr)]) @@ -362,21 +359,21 @@ class DATA(): self.enqueue_frame_for_tx(ack_frame, copies=3, repeat_delay=100) def send_retransmit_request_frame(self, freedv): - # check where a None is in our burst buffer and do frame+1, beacuse lists start at 0 + # check where a None is in our burst buffer and do frame+1, because lists start at 0 missing_frames = [frame + 1 for frame, element in enumerate(static.RX_BURST_BUFFER) if element is None] # set n frames per burst to modem - # this is an idea so its not getting lost.... + # this is an idea, so it's not getting lost.... # we need to work on this codec2.api.freedv_set_frames_per_burst(freedv,len(missing_frames)) # TODO: Trim `missing_frames` bytesarray to [7:13] (6) frames, if it's larger. # then create a repeat frame - rpt_frame = bytearray(14) - rpt_frame[:1] = bytes([62]) - rpt_frame[1:4] = static.DXCALLSIGN_CRC - rpt_frame[4:7] = static.MYCALLSIGN_CRC + rpt_frame = bytearray(14) + rpt_frame[:1] = bytes([62]) + rpt_frame[1:4] = static.DXCALLSIGN_CRC + rpt_frame[4:7] = static.MYCALLSIGN_CRC rpt_frame[7:13] = missing_frames structlog.get_logger("structlog").info("[TNC] ARQ | RX | Requesting", frames=missing_frames) @@ -385,8 +382,8 @@ class DATA(): def send_burst_nack_frame(self, snr=0): """ Build and send NACK frame for received DATA frame """ - nack_frame = bytearray(14) - nack_frame[:1] = bytes([63]) + nack_frame = bytearray(14) + nack_frame[:1] = bytes([63]) nack_frame[1:4] = static.DXCALLSIGN_CRC nack_frame[4:7] = static.MYCALLSIGN_CRC nack_frame[7:8] = bytes([int(snr)]) @@ -397,8 +394,8 @@ class DATA(): def send_burst_nack_frame_watchdog(self, snr=0): """ Build and send NACK frame for watchdog timeout """ - nack_frame = bytearray(14) - nack_frame[:1] = bytes([64]) + nack_frame = bytearray(14) + nack_frame[:1] = bytes([64]) nack_frame[1:4] = static.DXCALLSIGN_CRC nack_frame[4:7] = static.MYCALLSIGN_CRC nack_frame[7:8] = bytes([int(snr)]) @@ -409,10 +406,10 @@ class DATA(): def send_disconnect_frame(self): """ Build and send a disconnect frame """ - disconnection_frame = bytearray(14) - disconnection_frame[:1] = bytes([223]) - disconnection_frame[1:4] = static.DXCALLSIGN_CRC - disconnection_frame[4:7] = static.MYCALLSIGN_CRC + disconnection_frame = bytearray(14) + disconnection_frame[:1] = bytes([223]) + disconnection_frame[1:4] = static.DXCALLSIGN_CRC + disconnection_frame[4:7] = static.MYCALLSIGN_CRC disconnection_frame[7:13] = helpers.callsign_to_bytes(self.mycallsign) self.enqueue_frame_for_tx(disconnection_frame, copies=5, repeat_delay=250) @@ -464,7 +461,7 @@ class DATA(): static.RX_BURST_BUFFER = [None] * RX_N_FRAMES_PER_BURST # Append data to rx burst buffer - static.RX_BURST_BUFFER[RX_N_FRAME_OF_BURST] = data_in[8:] # [frame_type][n_frames_per_burst][CRC24][CRC24] + static.RX_BURST_BUFFER[RX_N_FRAME_OF_BURST] = data_in[8:] # [frame_type][n_frames_per_burst][CRC24][CRC24] structlog.get_logger("structlog").debug("[TNC] static.RX_BURST_BUFFER", buffer=static.RX_BURST_BUFFER) @@ -477,7 +474,7 @@ class DATA(): # the temp burst buffer is needed for checking, if we already recevied data temp_burst_buffer = b'' for value in static.RX_BURST_BUFFER: - #static.RX_FRAME_BUFFER += static.RX_BURST_BUFFER[i] + # static.RX_FRAME_BUFFER += static.RX_BURST_BUFFER[i] temp_burst_buffer += bytes(value) # if frame buffer ends not with the current frame, we are going to append new data @@ -490,7 +487,7 @@ 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 --> exisitng data + # static.RX_FRAME_BUFFER --> existing data # temp_burst_buffer --> new data # search_area --> area where we want to search search_area = 510 @@ -504,7 +501,7 @@ class DATA(): static.RX_FRAME_BUFFER = static.RX_FRAME_BUFFER[:search_position + get_position] static.RX_FRAME_BUFFER += temp_burst_buffer structlog.get_logger("structlog").warning("[TNC] ARQ | RX | replacing existing buffer data", area=search_area, pos=get_position) - # if we dont find data n this range, we really have new data and going to replace it + # if we don't find data n this range, we really have new data and going to replace it else: static.RX_FRAME_BUFFER += temp_burst_buffer structlog.get_logger("structlog").debug("[TNC] ARQ | RX | appending data to buffer") @@ -558,10 +555,10 @@ class DATA(): if bof_position >=0: payload = static.RX_FRAME_BUFFER[bof_position+len(self.data_frame_bof):eof_position] - frame_length = int.from_bytes(payload[4:8], "big") #4:8 4bytes + frame_length = int.from_bytes(payload[4:8], "big") # 4:8 4bytes static.TOTAL_BYTES = frame_length - compression_factor = int.from_bytes(payload[8:9], "big") #4:8 4bytes - compression_factor = np.clip(compression_factor, 0, 255) #limit to max value of 255 + compression_factor = int.from_bytes(payload[8:9], "big") # 4:8 4bytes + compression_factor = np.clip(compression_factor, 0, 255) # limit to max value of 255 static.ARQ_COMPRESSION_FACTOR = compression_factor / 10 self.calculate_transfer_rate_rx(self.rx_start_of_transmission, len(static.RX_FRAME_BUFFER)) @@ -574,9 +571,9 @@ class DATA(): # Extract raw data from buffer payload = static.RX_FRAME_BUFFER[bof_position+len(self.data_frame_bof):eof_position] # Get the data frame crc - data_frame_crc = payload[:4] #0:4 4bytes + data_frame_crc = payload[:4] # 0:4 4bytes # Get the data frame length - frame_length = int.from_bytes(payload[4:8], "big") #4:8 4bytes + frame_length = int.from_bytes(payload[4:8], "big") # 4:8 4bytes static.TOTAL_BYTES = frame_length # 8:9 = compression factor @@ -609,7 +606,6 @@ class DATA(): jsondata = {"arq":"received", "uuid" : uniqueid, "timestamp": timestamp, "mycallsign" : str(mycallsign, 'utf-8'), "dxcallsign": str(static.DXCALLSIGN, 'utf-8'), "dxgrid": str(static.DXGRID, 'utf-8'), "data": base64_data} json_data_out = json.dumps(jsondata) structlog.get_logger("structlog").debug("[TNC] arq_data_received:", jsondata=jsondata) - # print(jsondata) sock.SOCKET_QUEUE.put(json_data_out) static.INFO.append("ARQ;RECEIVING;SUCCESS") @@ -652,19 +648,19 @@ class DATA(): self.speed_level = len(self.mode_list) - 1 # speed level for selecting mode static.ARQ_SPEED_LEVEL = self.speed_level - TX_N_SENT_BYTES = 0 # already sent bytes per data frame - self.tx_n_retry_of_burst = 0 # retries we already sent data - TX_N_MAX_RETRIES_PER_BURST = 50 # max amount of retries we sent before frame is lost - TX_N_FRAMES_PER_BURST = n_frames_per_burst # amount of n frames per burst + TX_N_SENT_BYTES = 0 # already sent bytes per data frame + self.tx_n_retry_of_burst = 0 # retries we already sent data + TX_N_MAX_RETRIES_PER_BURST = 50 # max amount of retries we sent before frame is lost + TX_N_FRAMES_PER_BURST = n_frames_per_burst # amount of n frames per burst TX_BUFFER = [] # our buffer for appending new data # TIMEOUTS - BURST_ACK_TIMEOUT_SECONDS = 3.0 # timeout for burst acknowledges - DATA_FRAME_ACK_TIMEOUT_SECONDS = 3.0 # timeout for data frame acknowledges - RPT_ACK_TIMEOUT_SECONDS = 3.0 # timeout for rpt frame acknowledges + BURST_ACK_TIMEOUT_SECONDS = 3.0 # timeout for burst acknowledges + DATA_FRAME_ACK_TIMEOUT_SECONDS = 3.0 # timeout for data frame acknowledges + RPT_ACK_TIMEOUT_SECONDS = 3.0 # timeout for rpt frame acknowledges # save len of data_out to TOTAL_BYTES for our statistics --> kBytes - #static.TOTAL_BYTES = round(len(data_out) / 1024, 2) + # static.TOTAL_BYTES = round(len(data_out) / 1024, 2) static.TOTAL_BYTES = len(data_out) frame_total_size = len(data_out).to_bytes(4, byteorder='big') static.INFO.append("ARQ;TRANSMITTING") @@ -710,10 +706,10 @@ class DATA(): structlog.get_logger("structlog").debug("[TNC] FIXED MODE:", mode=data_mode) else: # we are doing a modulo check of transmission retries of the actual burst - # every 2nd retry which failes, decreases speedlevel by 1. + # every 2nd retry which fails, decreases speedlevel by 1. # as soon as we received an ACK for the current burst, speed_level will increase # by 1. - # the can be optimised by checking the optimal speed level for the current conditions + # They can be optimised by checking the optimal speed level for the current conditions ''' if not self.tx_n_retry_of_burst % 2 and self.tx_n_retry_of_burst > 0: self.speed_level -= 1 @@ -721,7 +717,7 @@ class DATA(): self.speed_level = 0 ''' - #if self.tx_n_retry_of_burst <= 1: + # if self.tx_n_retry_of_burst <= 1: # self.speed_level += 1 # if self.speed_level >= len(self.mode_list)-1: # self.speed_level = len(self.mode_list)-1 @@ -746,8 +742,8 @@ class DATA(): # TODO: this part needs a complete rewrite! # TX_N_FRAMES_PER_BURST = 1 is working - arqheader = bytearray() - arqheader[:1] = bytes([10]) #bytes([10 + i]) + arqheader = bytearray() + arqheader[:1] = bytes([10]) # bytes([10 + i]) arqheader[1:2] = bytes([TX_N_FRAMES_PER_BURST]) arqheader[2:5] = static.DXCALLSIGN_CRC arqheader[5:8] = static.MYCALLSIGN_CRC @@ -790,7 +786,7 @@ class DATA(): while not self.burst_ack and not self.burst_nack and not self.rpt_request_received and not self.data_frame_ack_received and time.time() < burstacktimeout and static.ARQ_STATE: time.sleep(0.01) ''' - #burstacktimeout = time.time() + BURST_ACK_TIMEOUT_SECONDS + 100 + # burstacktimeout = time.time() + BURST_ACK_TIMEOUT_SECONDS + 100 while (static.ARQ_STATE and not (self.burst_ack or self.burst_nack or self.rpt_request_received or self.data_frame_ack_received)): @@ -800,22 +796,22 @@ class DATA(): if self.burst_ack: self.burst_ack = False # reset ack state self.tx_n_retry_of_burst = 0 # reset retries - break #break retry loop + break # break retry loop if self.burst_nack: - self.burst_nack = False #reset nack state + self.burst_nack = False # reset nack state # not yet implemented if self.rpt_request_received: pass if self.data_frame_ack_received: - break #break retry loop + 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: - #print("not ready for data...leaving loop....") + # print("not ready for data...leaving loop....") break self.calculate_transfer_rate_tx(tx_start_of_transmission, bufferposition_end, len(data_out)) @@ -832,7 +828,7 @@ class DATA(): json_data_out = json.dumps(jsondata) sock.SOCKET_QUEUE.put(json_data_out) - #GOING TO NEXT ITERATION + # GOING TO NEXT ITERATION if self.data_frame_ack_received: static.INFO.append("ARQ;TRANSMITTING;SUCCESS") @@ -870,8 +866,8 @@ class DATA(): """ # increase speed level if we received a burst ack - #self.speed_level += 1 - #if self.speed_level >= len(self.mode_list)-1: + # self.speed_level += 1 + # if self.speed_level >= len(self.mode_list)-1: # self.speed_level = len(self.mode_list)-1 # only process data if we are in ARQ and BUSY state @@ -900,8 +896,8 @@ class DATA(): """ # increase speed level if we received a burst ack - #self.speed_level += 1 - #if self.speed_level >= len(self.mode_list)-1: + # self.speed_level += 1 + # if self.speed_level >= len(self.mode_list)-1: # self.speed_level = len(self.mode_list)-1 # only process data if we are in ARQ and BUSY state @@ -980,7 +976,7 @@ class DATA(): Returns: """ - # das hier müssen wir checken. Sollte vielleicht in INIT!!! + # TODO: we need to check this, maybe placing it to class init self.datachannel_timeout = False structlog.get_logger("structlog").info("[TNC] SESSION [" + str(self.mycallsign, 'utf-8') + "]>> <<[" + str(static.DXCALLSIGN, 'utf-8') + "]", state=static.ARQ_SESSION_STATE) @@ -1010,10 +1006,10 @@ class DATA(): self.IS_ARQ_SESSION_MASTER = True static.ARQ_SESSION_STATE = 'connecting' - connection_frame = bytearray(14) - connection_frame[:1] = bytes([221]) - connection_frame[1:4] = static.DXCALLSIGN_CRC - connection_frame[4:7] = static.MYCALLSIGN_CRC + connection_frame = bytearray(14) + connection_frame[:1] = bytes([221]) + connection_frame[1:4] = static.DXCALLSIGN_CRC + connection_frame[4:7] = static.MYCALLSIGN_CRC connection_frame[7:13] = helpers.callsign_to_bytes(self.mycallsign) while not static.ARQ_SESSION: @@ -1028,7 +1024,6 @@ class DATA(): time.sleep(0.01) # break if data channel is opened if static.ARQ_SESSION: - # eventuell einfach nur return true um die nächste break ebene zu vermeiden? return True # if static.ARQ_SESSION: # break @@ -1205,11 +1200,11 @@ class DATA(): structlog.get_logger("structlog").debug("[TNC] Requesting manual mode --> not yet implemented ") frametype = bytes([mode]) - connection_frame = bytearray(14) - connection_frame[:1] = frametype - connection_frame[1:4] = static.DXCALLSIGN_CRC - connection_frame[4:7] = static.MYCALLSIGN_CRC - connection_frame[7:13] = helpers.callsign_to_bytes(mycallsign) + connection_frame = bytearray(14) + connection_frame[:1] = frametype + connection_frame[1:4] = static.DXCALLSIGN_CRC + connection_frame[4:7] = static.MYCALLSIGN_CRC + connection_frame[7:13] = helpers.callsign_to_bytes(mycallsign) connection_frame[13:14] = bytes([n_frames_per_burst]) while not static.ARQ_STATE: @@ -1233,7 +1228,6 @@ class DATA(): if attempt == self.data_channel_max_retries: static.INFO.append("DATACHANNEL;FAILED") structlog.get_logger("structlog").debug("[TNC] arq_open_data_channel:", transmission_uuid=self.transmission_uuid) - # print(self.transmission_uuid) jsondata = {"arq":"transmission", "status" :"failed", "uuid" : self.transmission_uuid, "percent" : static.ARQ_TRANSMISSION_PERCENT, "bytesperminute" : static.ARQ_BYTES_PER_MINUTE} json_data_out = json.dumps(jsondata) sock.SOCKET_QUEUE.put(json_data_out) @@ -1266,7 +1260,7 @@ class DATA(): n_frames_per_burst = int.from_bytes(bytes(data_in[13:14]), "big") frametype = int.from_bytes(bytes(data_in[:1]), "big") - #check if we received low bandwith mode + # check if we received low bandwith mode if frametype == 225: self.received_low_bandwith_mode = False self.mode_list = self.mode_list_high_bw @@ -1310,11 +1304,11 @@ class DATA(): frametype = bytes([226]) structlog.get_logger("structlog").debug("[TNC] Responding with high bandwidth mode") - connection_frame = bytearray(14) - connection_frame[:1] = frametype - connection_frame[1:4] = static.DXCALLSIGN_CRC - connection_frame[4:7] = static.MYCALLSIGN_CRC - connection_frame[13:14] = bytes([static.ARQ_PROTOCOL_VERSION]) #crc8 of version for checking protocol version + connection_frame = bytearray(14) + connection_frame[:1] = frametype + connection_frame[1:4] = static.DXCALLSIGN_CRC + connection_frame[4:7] = static.MYCALLSIGN_CRC + connection_frame[13:14] = bytes([static.ARQ_PROTOCOL_VERSION]) # crc8 of version for checking protocol version self.enqueue_frame_for_tx(connection_frame) @@ -1380,10 +1374,10 @@ class DATA(): static.INFO.append("PING;SENDING") structlog.get_logger("structlog").info("[TNC] PING REQ [" + str(self.mycallsign, 'utf-8') + "] >>> [" + str(static.DXCALLSIGN, 'utf-8') + "]" ) - ping_frame = bytearray(14) - ping_frame[:1] = bytes([210]) - ping_frame[1:4] = static.DXCALLSIGN_CRC - ping_frame[4:7] = static.MYCALLSIGN_CRC + ping_frame = bytearray(14) + ping_frame[:1] = bytes([210]) + ping_frame[1:4] = static.DXCALLSIGN_CRC + ping_frame[4:7] = static.MYCALLSIGN_CRC ping_frame[7:13] = helpers.callsign_to_bytes(self.mycallsign) structlog.get_logger("structlog").info("[TNC] ENABLE FSK", state=static.ENABLE_FSK) @@ -1418,8 +1412,8 @@ class DATA(): structlog.get_logger("structlog").info("[TNC] PING REQ [" + str(mycallsign, 'utf-8') + "] <<< [" + str(static.DXCALLSIGN, 'utf-8') + "]", snr=static.SNR ) - ping_frame = bytearray(14) - ping_frame[:1] = bytes([211]) + ping_frame = bytearray(14) + ping_frame[:1] = bytes([211]) ping_frame[1:4] = static.DXCALLSIGN_CRC ping_frame[4:7] = static.MYCALLSIGN_CRC ping_frame[7:13] = static.MYGRID @@ -1458,11 +1452,11 @@ class DATA(): Force a stop of the running transmission """ structlog.get_logger("structlog").warning("[TNC] Stopping transmission!") - stop_frame = bytearray(14) - stop_frame[:1] = bytes([249]) + stop_frame = bytearray(14) + stop_frame[:1] = bytes([249]) stop_frame[1:4] = static.DXCALLSIGN_CRC stop_frame[4:7] = static.MYCALLSIGN_CRC - stop_frame[7:13] = helpers.callsign_to_bytes(self.mycallsign) + stop_frame[7:13] = helpers.callsign_to_bytes(self.mycallsign) self.enqueue_frame_for_tx(stop_frame, copies=2, repeat_delay=250) @@ -1486,7 +1480,7 @@ class DATA(): """ Controlling funktion for running a beacon Args: - interval:int: + self: Returns: @@ -1551,9 +1545,9 @@ class DATA(): structlog.get_logger("structlog").info("[TNC] CQ CQ CQ") static.INFO.append("CQ;SENDING") - cq_frame = bytearray(14) - cq_frame[:1] = bytes([200]) - cq_frame[1:7] = helpers.callsign_to_bytes(self.mycallsign) + cq_frame = bytearray(14) + cq_frame[:1] = bytes([200]) + cq_frame[1:7] = helpers.callsign_to_bytes(self.mycallsign) cq_frame[7:11] = helpers.encode_grid(static.MYGRID.decode("utf-8")) structlog.get_logger("structlog").info("[TNC] ENABLE FSK", state=static.ENABLE_FSK) @@ -1602,9 +1596,9 @@ class DATA(): static.INFO.append("QRV;SENDING") structlog.get_logger("structlog").info("[TNC] Sending QRV!") - qrv_frame = bytearray(14) - qrv_frame[:1] = bytes([201]) - qrv_frame[1:7] = helpers.callsign_to_bytes(self.mycallsign) + qrv_frame = bytearray(14) + qrv_frame[:1] = bytes([201]) + qrv_frame[1:7] = helpers.callsign_to_bytes(self.mycallsign) qrv_frame[7:11] = helpers.encode_grid(static.MYGRID.decode("utf-8")) structlog.get_logger("structlog").info("[TNC] ENABLE FSK", state=static.ENABLE_FSK) @@ -1686,7 +1680,7 @@ class DATA(): def calculate_transfer_rate_tx(self, tx_start_of_transmission:float, sentbytes:int, tx_buffer_length:int) -> list: """ - Calcualte Transferrate for transmission + Calculate transfer rate for transmission Args: tx_start_of_transmission:float: sentbytes:int: @@ -1701,8 +1695,8 @@ class DATA(): transmissiontime = time.time() - tx_start_of_transmission if sentbytes > 0: - static.ARQ_BITS_PER_SECOND = int((sentbytes * 8) / transmissiontime) # Bits per Second - static.ARQ_BYTES_PER_MINUTE = int((sentbytes) / (transmissiontime / 60)) # Bytes per Minute + static.ARQ_BITS_PER_SECOND = int((sentbytes * 8) / transmissiontime) # Bits per Second + static.ARQ_BYTES_PER_MINUTE = int((sentbytes) / (transmissiontime / 60)) # Bytes per Minute else: static.ARQ_BITS_PER_SECOND = 0 @@ -1739,7 +1733,7 @@ class DATA(): # reset modem receiving state to reduce cpu load modem.RECEIVE_DATAC1 = False modem.RECEIVE_DATAC3 = False - #modem.RECEIVE_FSK_LDPC_0 = False + # modem.RECEIVE_FSK_LDPC_0 = False modem.RECEIVE_FSK_LDPC_1 = False # reset buffer overflow counter @@ -1842,8 +1836,8 @@ class DATA(): self.burst_nack_counter += 1 if self.burst_nack_counter >= 2: self.speed_level -= 1 - #print(self.burst_nack_counter) - #print(self.speed_level) + # print(self.burst_nack_counter) + # print(self.speed_level) static.ARQ_SPEED_LEVEL = self.speed_level self.burst_nack_counter = 0 if self.speed_level <= 0: @@ -1873,8 +1867,8 @@ class DATA(): time.sleep(0.01) if self.data_channel_last_received + self.transmission_timeout > time.time(): time.sleep(0.01) - #print(self.data_channel_last_received + self.transmission_timeout - time.time()) - #pass + # print(self.data_channel_last_received + self.transmission_timeout - time.time()) + # pass else: self.data_channel_last_received = 0 structlog.get_logger("structlog").info("[TNC] DATA [" + str(self.mycallsign, 'utf-8') + "]<>[" + str(static.DXCALLSIGN, 'utf-8') + "]") diff --git a/tnc/helpers.py b/tnc/helpers.py index 00378f7d..57697f8a 100644 --- a/tnc/helpers.py +++ b/tnc/helpers.py @@ -27,6 +27,7 @@ def wait(seconds: float) -> bool: time.sleep(0.01) return True + def get_crc_8(data) -> bytes: """Author: DJ2LS @@ -45,6 +46,7 @@ def get_crc_8(data) -> bytes: crc_data = crc_data.to_bytes(1, byteorder='big') return crc_data + def get_crc_16(data) -> bytes: """Author: DJ2LS @@ -63,6 +65,7 @@ def get_crc_16(data) -> bytes: crc_data = crc_data.to_bytes(2, byteorder='big') return crc_data + def get_crc_24(data) -> bytes: """Author: DJ2LS @@ -84,6 +87,7 @@ def get_crc_24(data) -> bytes: crc_data = crc_data.to_bytes(3, byteorder='big') return crc_data + def get_crc_32(data: bytes) -> bytes: """Author: DJ2LS @@ -102,6 +106,7 @@ def get_crc_32(data: bytes) -> bytes: crc_data = crc_data.to_bytes(4, byteorder='big') return crc_data + def add_to_heard_stations(dxcallsign, dxgrid, datatype, snr, offset, frequency): """ @@ -136,6 +141,7 @@ def add_to_heard_stations(dxcallsign, dxgrid, datatype, snr, offset, frequency): # item = [dxcallsign, int(time.time())] # static.HEARD_STATIONS[idx] = item + def callsign_to_bytes(callsign) -> bytes: """ @@ -146,22 +152,22 @@ def callsign_to_bytes(callsign) -> bytes: """ # http://www.aprs.org/aprs11/SSIDs.txt - #-0 Your primary station usually fixed and message capable - #-1 generic additional station, digi, mobile, wx, etc - #-2 generic additional station, digi, mobile, wx, etc - #-3 generic additional station, digi, mobile, wx, etc - #-4 generic additional station, digi, mobile, wx, etc - #-5 Other networks (Dstar, Iphones, Androids, Blackberry's etc) - #-6 Special activity, Satellite ops, camping or 6 meters, etc - #-7 walkie talkies, HT's or other human portable - #-8 boats, sailboats, RV's or second main mobile - #-9 Primary Mobile (usually message capable) - #-10 internet, Igates, echolink, winlink, AVRS, APRN, etc - #-11 balloons, aircraft, spacecraft, etc - #-12 APRStt, DTMF, RFID, devices, one-way trackers*, etc - #-13 Weather stations - #-14 Truckers or generally full time drivers - #-15 generic additional station, digi, mobile, wx, etc + # -0 Your primary station usually fixed and message capable + # -1 generic additional station, digi, mobile, wx, etc + # -2 generic additional station, digi, mobile, wx, etc + # -3 generic additional station, digi, mobile, wx, etc + # -4 generic additional station, digi, mobile, wx, etc + # -5 Other networks (Dstar, Iphones, Androids, Blackberry's etc) + # -6 Special activity, Satellite ops, camping or 6 meters, etc + # -7 walkie talkies, HT's or other human portable + # -8 boats, sailboats, RV's or second main mobile + # -9 Primary Mobile (usually message capable) + # -10 internet, Igates, echolink, winlink, AVRS, APRN, etc + # -11 balloons, aircraft, spacecraft, etc + # -12 APRStt, DTMF, RFID, devices, one-way trackers*, etc + # -13 Weather stations + # -14 Truckers or generally full time drivers + # -15 generic additional station, digi, mobile, wx, etc # Try converting to bytestring if possible type string try: @@ -178,16 +184,16 @@ def callsign_to_bytes(callsign) -> bytes: except IndexError as e: structlog.get_logger("structlog").debug("[HLP] callsign_to_bytes: Error callsign SSID to integer:", e=e) - #callsign = callsign[0] - #bytestring = bytearray(8) - #bytestring[:len(callsign)] = callsign - #bytestring[7:8] = bytes([ssid]) + # callsign = callsign[0] + # bytestring = bytearray(8) + # bytestring[:len(callsign)] = callsign + # bytestring[7:8] = bytes([ssid]) # ---- callsign with encoding always 6 bytes long callsign = callsign[0].decode("utf-8") ssid = bytes([ssid]).decode("utf-8") return encode_call(callsign + ssid) - #return bytes(bytestring) + # return bytes(bytestring) def bytes_to_callsign(bytestring: bytes) -> bytes: """ @@ -200,22 +206,22 @@ def bytes_to_callsign(bytestring: bytes) -> bytes: bytes """ # http://www.aprs.org/aprs11/SSIDs.txt - #-0 Your primary station usually fixed and message capable - #-1 generic additional station, digi, mobile, wx, etc - #-2 generic additional station, digi, mobile, wx, etc - #-3 generic additional station, digi, mobile, wx, etc - #-4 generic additional station, digi, mobile, wx, etc - #-5 Other networks (Dstar, Iphones, Androids, Blackberry's etc) - #-6 Special activity, Satellite ops, camping or 6 meters, etc - #-7 walkie talkies, HT's or other human portable - #-8 boats, sailboats, RV's or second main mobile - #-9 Primary Mobile (usually message capable) - #-10 internet, Igates, echolink, winlink, AVRS, APRN, etc - #-11 balloons, aircraft, spacecraft, etc - #-12 APRStt, DTMF, RFID, devices, one-way trackers*, etc - #-13 Weather stations - #-14 Truckers or generally full time drivers - #-15 generic additional station, digi, mobile, wx, etc + # -0 Your primary station usually fixed and message capable + # -1 generic additional station, digi, mobile, wx, etc + # -2 generic additional station, digi, mobile, wx, etc + # -3 generic additional station, digi, mobile, wx, etc + # -4 generic additional station, digi, mobile, wx, etc + # -5 Other networks (Dstar, Iphones, Androids, Blackberry's etc) + # -6 Special activity, Satellite ops, camping or 6 meters, etc + # -7 walkie talkies, HT's or other human portable + # -8 boats, sailboats, RV's or second main mobile + # -9 Primary Mobile (usually message capable) + # -10 internet, Igates, echolink, winlink, AVRS, APRN, etc + # -11 balloons, aircraft, spacecraft, etc + # -12 APRStt, DTMF, RFID, devices, one-way trackers*, etc + # -13 Weather stations + # -14 Truckers or generally full time drivers + # -15 generic additional station, digi, mobile, wx, etc # we need to do this step to reduce the needed paypload by the callsign ( stripping "-" out of the callsign ) ''' @@ -235,6 +241,7 @@ def bytes_to_callsign(bytestring: bytes) -> bytes: ssid = ord(bytes(decoded[-1], "utf-8")) return bytes(f"{callsign}-{ssid}", "utf-8") + def check_callsign(callsign:bytes, crc_to_check:bytes): """ Funktion to check a crc against a callsign to calculate the ssid by generating crc until we got it @@ -270,9 +277,10 @@ def check_callsign(callsign:bytes, crc_to_check:bytes): return [False, ""] + def encode_grid(grid): """ - @auther: DB1UJ + @author: DB1UJ Args: grid:string: maidenhead QTH locater [a-r][a-r][0-9][0-9][a-x][a-x] Returns: @@ -282,30 +290,30 @@ def encode_grid(grid): grid = grid.upper() # upper case to be save - int_first = ord(grid[0]) - 65 # -65 offset for 'A' become zero, utf8 table - int_sec = ord(grid[1]) - 65 # -65 offset for 'A' become zero, utf8 table + int_first = ord(grid[0]) - 65 # -65 offset for 'A' become zero, utf8 table + int_sec = ord(grid[1]) - 65 # -65 offset for 'A' become zero, utf8 table int_val = (int_first * 18) + int_sec # encode for modulo devision, 2 numbers in 1 out_code_word = (int_val & 0b111111111) # only 9 bit LSB A - R * A - R is needed - out_code_word <<= 9 # shift 9 bit left having space next bits, letter A-R * A-R + out_code_word <<= 9 # shift 9 bit left having space next bits, letter A-R * A-R - int_val = int(grid[2:4]) # number string to number int, highest value 99 + int_val = int(grid[2:4]) # number string to number int, highest value 99 out_code_word |= (int_val & 0b1111111) # using bit OR to add new value - out_code_word <<= 7 # shift 7 bit left having space next bits, letter A-X + out_code_word <<= 7 # shift 7 bit left having space next bits, letter A-X - int_val = ord(grid[4]) - 65 # -65 offset for 'A' become zero, utf8 table + int_val = ord(grid[4]) - 65 # -65 offset for 'A' become zero, utf8 table out_code_word |= (int_val & 0b11111) # using bit OR to add new value - out_code_word <<= 5 # shift 5 bit left having space next bits, letter A-X + out_code_word <<= 5 # shift 5 bit left having space next bits, letter A-X - int_val = ord(grid[5]) - 65 # -65 offset for 'A' become zero, utf8 table + int_val = ord(grid[5]) - 65 # -65 offset for 'A' become zero, utf8 table out_code_word |= (int_val & 0b11111) # using bit OR to add new value return out_code_word.to_bytes(length=4, byteorder='big') def decode_grid(b_code_word:bytes): """ - @auther: DB1UJ + @author: DB1UJ Args: b_code_word:bytes: 4 bytes with 26 bit valid data LSB Returns: @@ -334,7 +342,7 @@ def decode_grid(b_code_word:bytes): def encode_call(call): """ - @auther: DB1UJ + @author: DB1UJ Args: call:string: ham radio call sign [A-Z,0-9], last char SSID 0-63 @@ -346,18 +354,19 @@ def encode_call(call): call = call.upper() # upper case to be save for x in call: - int_val = ord(x) - 48 # -48 reduce bits, begin with first number utf8 table - out_code_word <<= 6 # shift left 6 bit, making space for a new char - out_code_word |= (int_val & 0b111111) # bit OR adds the new char, masked with AND 0b111111 - out_code_word >>= 6 # clean last char - out_code_word <<= 6 # make clean space - out_code_word |= (ord(call[-1]) & 0b111111) # add the SSID uncoded only 0 - 63 + int_val = ord(x) - 48 # -48 reduce bits, begin with first number utf8 table + out_code_word <<= 6 # shift left 6 bit, making space for a new char + out_code_word |= (int_val & 0b111111) # bit OR adds the new char, masked with AND 0b111111 + out_code_word >>= 6 # clean last char + out_code_word <<= 6 # make clean space + out_code_word |= (ord(call[-1]) & 0b111111) # add the SSID uncoded only 0 - 63 return out_code_word.to_bytes(length=6, byteorder='big') + def decode_call(b_code_word:bytes): """ - @auther: DB1UJ + @author: DB1UJ Args: b_code_word:bytes: 6 bytes with 6 bits/sign valid data char signs LSB @@ -365,13 +374,13 @@ def decode_call(b_code_word:bytes): call:str: upper case ham radio call sign [A-Z,0-9] + binary SSID """ code_word = int.from_bytes(b_code_word, byteorder='big', signed=False) - ssid = chr(code_word & 0b111111) # save the uncoded binary SSID + ssid = chr(code_word & 0b111111) # save the uncoded binary SSID call = str() while code_word != 0: call = chr((code_word & 0b111111)+48) + call code_word >>= 6 - call = call[:-1] + ssid # remove the last char from call and replace with SSID + call = call[:-1] + ssid # remove the last char from call and replace with SSID return call From d992fd8dc0de83c81cc4405e80f87016cd3c1759 Mon Sep 17 00:00:00 2001 From: DJ2LS <75909252+DJ2LS@users.noreply.github.com> Date: Mon, 23 May 2022 13:11:16 +0200 Subject: [PATCH 2/8] Second run reducing number of problems --- tnc/helpers.py | 37 +++++++----- tnc/main.py | 7 ++- tnc/modem.py | 150 +++++++++++++++++++++++++++++-------------------- tnc/rig.py | 12 ++-- tnc/rigctl.py | 8 +-- tnc/rigctld.py | 4 +- tnc/sock.py | 141 +++++++++++++++++++++++++--------------------- tnc/static.py | 14 ++--- 8 files changed, 211 insertions(+), 162 deletions(-) diff --git a/tnc/helpers.py b/tnc/helpers.py index 57697f8a..c29ab467 100644 --- a/tnc/helpers.py +++ b/tnc/helpers.py @@ -80,9 +80,13 @@ def get_crc_24(data) -> bytes: Returns: CRC-24 (OpenPGP) of the provided data as bytes """ - crc_algorithm = crcengine.create(0x864cfb, 24, 0xb704ce, ref_in=False, - ref_out=False, xor_out=0, - name='crc-24-openpgp') + crc_algorithm = crcengine.create(0x864cfb, + 24, + 0xb704ce, + ref_in=False, + ref_out=False, + xor_out=0, + name='crc-24-openpgp') crc_data = crc_algorithm(data) crc_data = crc_data.to_bytes(3, byteorder='big') return crc_data @@ -136,6 +140,7 @@ def add_to_heard_stations(dxcallsign, dxgrid, datatype, snr, offset, frequency): static.HEARD_STATIONS.append([dxcallsign, dxgrid, int(time.time()), datatype, snr, offset, frequency]) break + # for idx, item in enumerate(static.HEARD_STATIONS): # if dxcallsign in item: # item = [dxcallsign, int(time.time())] @@ -174,7 +179,6 @@ def callsign_to_bytes(callsign) -> bytes: callsign = bytes(callsign, 'utf-8') except TypeError as e: structlog.get_logger("structlog").debug("[HLP] callsign_to_bytes: Exception converting callsign to bytes:", e=e) - pass # Need this step to reduce the needed payload by the callsign (stripping "-" out of the callsign) callsign = callsign.split(b'-') @@ -195,6 +199,7 @@ def callsign_to_bytes(callsign) -> bytes: return encode_call(callsign + ssid) # return bytes(bytestring) + def bytes_to_callsign(bytestring: bytes) -> bytes: """ Convert our callsign, received by a frame to a callsign in a human readable format @@ -242,7 +247,7 @@ def bytes_to_callsign(bytestring: bytes) -> bytes: return bytes(f"{callsign}-{ssid}", "utf-8") -def check_callsign(callsign:bytes, crc_to_check:bytes): +def check_callsign(callsign: bytes, crc_to_check: bytes): """ Funktion to check a crc against a callsign to calculate the ssid by generating crc until we got it @@ -288,30 +293,31 @@ def encode_grid(grid): """ out_code_word = 0 - grid = grid.upper() # upper case to be save + grid = grid.upper() # upper case to be save int_first = ord(grid[0]) - 65 # -65 offset for 'A' become zero, utf8 table int_sec = ord(grid[1]) - 65 # -65 offset for 'A' become zero, utf8 table - int_val = (int_first * 18) + int_sec # encode for modulo devision, 2 numbers in 1 + int_val = (int_first * 18) + int_sec # encode for modulo devision, 2 numbers in 1 - out_code_word = (int_val & 0b111111111) # only 9 bit LSB A - R * A - R is needed + out_code_word = (int_val & 0b111111111) # only 9 bit LSB A - R * A - R is needed out_code_word <<= 9 # shift 9 bit left having space next bits, letter A-R * A-R int_val = int(grid[2:4]) # number string to number int, highest value 99 - out_code_word |= (int_val & 0b1111111) # using bit OR to add new value + out_code_word |= (int_val & 0b1111111) # using bit OR to add new value out_code_word <<= 7 # shift 7 bit left having space next bits, letter A-X int_val = ord(grid[4]) - 65 # -65 offset for 'A' become zero, utf8 table - out_code_word |= (int_val & 0b11111) # using bit OR to add new value + out_code_word |= (int_val & 0b11111) # using bit OR to add new value out_code_word <<= 5 # shift 5 bit left having space next bits, letter A-X int_val = ord(grid[5]) - 65 # -65 offset for 'A' become zero, utf8 table - out_code_word |= (int_val & 0b11111) # using bit OR to add new value + out_code_word |= (int_val & 0b11111) # using bit OR to add new value return out_code_word.to_bytes(length=4, byteorder='big') -def decode_grid(b_code_word:bytes): + +def decode_grid(b_code_word: bytes): """ @author: DB1UJ Args: @@ -340,6 +346,7 @@ def decode_grid(b_code_word:bytes): return grid + def encode_call(call): """ @author: DB1UJ @@ -351,7 +358,7 @@ def encode_call(call): """ out_code_word = 0 - call = call.upper() # upper case to be save + call = call.upper() # upper case to be save for x in call: int_val = ord(x) - 48 # -48 reduce bits, begin with first number utf8 table @@ -364,7 +371,7 @@ def encode_call(call): return out_code_word.to_bytes(length=6, byteorder='big') -def decode_call(b_code_word:bytes): +def decode_call(b_code_word: bytes): """ @author: DB1UJ Args: @@ -378,7 +385,7 @@ def decode_call(b_code_word:bytes): call = str() while code_word != 0: - call = chr((code_word & 0b111111)+48) + call + call = chr((code_word & 0b111111) + 48) + call code_word >>= 6 call = call[:-1] + ssid # remove the last char from call and replace with SSID diff --git a/tnc/main.py b/tnc/main.py index 6e08dfbd..f7ceb795 100755 --- a/tnc/main.py +++ b/tnc/main.py @@ -24,7 +24,7 @@ import log_handler import modem import static -# signal handler for closing aplication + def signal_handler(sig, frame): """ a signal handler, which closes the network/socket when closing the application @@ -39,15 +39,16 @@ def signal_handler(sig, frame): sock.CLOSE_SIGNAL = True sys.exit(0) + signal.signal(signal.SIGINT, signal_handler) if __name__ == '__main__': - # we need to run this on windows for multiprocessing support + # we need to run this on Windows for multiprocessing support multiprocessing.freeze_support() # --------------------------------------------GET PARAMETER INPUTS PARSER = argparse.ArgumentParser(description='FreeDATA TNC') PARSER.add_argument('--mycall', dest="mycall", default="AA0AA", help="My callsign", type=str) - PARSER.add_argument('--ssid', dest="ssid_list", nargs='*', default=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], help="SSID list we are responding to", type=str) + PARSER.add_argument('--ssid', dest="ssid_list", nargs='*', default=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ,11 ,12 ,13 ,14 ,15 ], help="SSID list we are responding to", type=str) PARSER.add_argument('--mygrid', dest="mygrid", default="JN12AA", help="My gridsquare", type=str) PARSER.add_argument('--rx', dest="audio_input_device", default=0, help="listening sound card", type=int) PARSER.add_argument('--tx', dest="audio_output_device", default=0, help="transmitting sound card", type=int) diff --git a/tnc/modem.py b/tnc/modem.py index 5a44d8fa..15d58e82 100644 --- a/tnc/modem.py +++ b/tnc/modem.py @@ -10,11 +10,8 @@ Created on Wed Dec 23 07:04:24 2020 import atexit import ctypes -import logging import os -import pathlib import queue -import re import sys import threading import time @@ -25,11 +22,9 @@ import sounddevice as sd import structlog import ujson as json -import audio +# import audio import codec2 import data_handler -import helpers -import log_handler import sock import static @@ -47,8 +42,10 @@ RECEIVE_DATAC1 = False RECEIVE_DATAC3 = False RECEIVE_FSK_LDPC_1 = False -class RF(): + +class RF: """ """ + def __init__(self): self.sampler_avg = 0 @@ -86,41 +83,51 @@ class RF(): # Open codec2 instances self.datac0_freedv = ctypes.cast(codec2.api.freedv_open(codec2.api.FREEDV_MODE_DATAC0), ctypes.c_void_p) - self.c_lib.freedv_set_tuning_range(self.datac0_freedv, ctypes.c_float(static.TUNING_RANGE_FMIN), ctypes.c_float(static.TUNING_RANGE_FMAX)) + self.c_lib.freedv_set_tuning_range(self.datac0_freedv, ctypes.c_float(static.TUNING_RANGE_FMIN), + ctypes.c_float(static.TUNING_RANGE_FMAX)) self.datac0_bytes_per_frame = int(codec2.api.freedv_get_bits_per_modem_frame(self.datac0_freedv) / 8) self.datac0_payload_per_frame = self.datac0_bytes_per_frame - 2 self.datac0_n_nom_modem_samples = self.c_lib.freedv_get_n_nom_modem_samples(self.datac0_freedv) self.datac0_n_tx_modem_samples = self.c_lib.freedv_get_n_tx_modem_samples(self.datac0_freedv) self.datac0_n_tx_preamble_modem_samples = self.c_lib.freedv_get_n_tx_preamble_modem_samples(self.datac0_freedv) - self.datac0_n_tx_postamble_modem_samples = self.c_lib.freedv_get_n_tx_postamble_modem_samples(self.datac0_freedv) + self.datac0_n_tx_postamble_modem_samples = self.c_lib.freedv_get_n_tx_postamble_modem_samples( + self.datac0_freedv) self.datac0_bytes_out = ctypes.create_string_buffer(self.datac0_bytes_per_frame) codec2.api.freedv_set_frames_per_burst(self.datac0_freedv, 1) - self.datac0_buffer = codec2.audio_buffer(2*self.AUDIO_FRAMES_PER_BUFFER_RX) + self.datac0_buffer = codec2.audio_buffer(2 * self.AUDIO_FRAMES_PER_BUFFER_RX) self.datac1_freedv = ctypes.cast(codec2.api.freedv_open(codec2.api.FREEDV_MODE_DATAC1), ctypes.c_void_p) - self.c_lib.freedv_set_tuning_range(self.datac1_freedv, ctypes.c_float(static.TUNING_RANGE_FMIN), ctypes.c_float(static.TUNING_RANGE_FMAX)) + self.c_lib.freedv_set_tuning_range(self.datac1_freedv, ctypes.c_float(static.TUNING_RANGE_FMIN), + ctypes.c_float(static.TUNING_RANGE_FMAX)) self.datac1_bytes_per_frame = int(codec2.api.freedv_get_bits_per_modem_frame(self.datac1_freedv) / 8) self.datac1_bytes_out = ctypes.create_string_buffer(self.datac1_bytes_per_frame) codec2.api.freedv_set_frames_per_burst(self.datac1_freedv, 1) - self.datac1_buffer = codec2.audio_buffer(2*self.AUDIO_FRAMES_PER_BUFFER_RX) + self.datac1_buffer = codec2.audio_buffer(2 * self.AUDIO_FRAMES_PER_BUFFER_RX) self.datac3_freedv = ctypes.cast(codec2.api.freedv_open(codec2.api.FREEDV_MODE_DATAC3), ctypes.c_void_p) - self.c_lib.freedv_set_tuning_range(self.datac3_freedv, ctypes.c_float(static.TUNING_RANGE_FMIN), ctypes.c_float(static.TUNING_RANGE_FMAX)) + self.c_lib.freedv_set_tuning_range(self.datac3_freedv, ctypes.c_float(static.TUNING_RANGE_FMIN), + ctypes.c_float(static.TUNING_RANGE_FMAX)) self.datac3_bytes_per_frame = int(codec2.api.freedv_get_bits_per_modem_frame(self.datac3_freedv) / 8) self.datac3_bytes_out = ctypes.create_string_buffer(self.datac3_bytes_per_frame) codec2.api.freedv_set_frames_per_burst(self.datac3_freedv, 1) - self.datac3_buffer = codec2.audio_buffer(2*self.AUDIO_FRAMES_PER_BUFFER_RX) + self.datac3_buffer = codec2.audio_buffer(2 * self.AUDIO_FRAMES_PER_BUFFER_RX) - self.fsk_ldpc_freedv_0 = ctypes.cast(codec2.api.freedv_open_advanced(codec2.api.FREEDV_MODE_FSK_LDPC, ctypes.byref(codec2.api.FREEDV_MODE_FSK_LDPC_0_ADV)), ctypes.c_void_p) + self.fsk_ldpc_freedv_0 = ctypes.cast(codec2.api.freedv_open_advanced(codec2.api.FREEDV_MODE_FSK_LDPC, + ctypes.byref( + codec2.api.FREEDV_MODE_FSK_LDPC_0_ADV)), + ctypes.c_void_p) self.fsk_ldpc_bytes_per_frame_0 = int(codec2.api.freedv_get_bits_per_modem_frame(self.fsk_ldpc_freedv_0) / 8) self.fsk_ldpc_bytes_out_0 = ctypes.create_string_buffer(self.fsk_ldpc_bytes_per_frame_0) - #codec2.api.freedv_set_frames_per_burst(self.fsk_ldpc_freedv_0, 1) + # codec2.api.freedv_set_frames_per_burst(self.fsk_ldpc_freedv_0, 1) self.fsk_ldpc_buffer_0 = codec2.audio_buffer(self.AUDIO_FRAMES_PER_BUFFER_RX) - self.fsk_ldpc_freedv_1 = ctypes.cast(codec2.api.freedv_open_advanced(codec2.api.FREEDV_MODE_FSK_LDPC, ctypes.byref(codec2.api.FREEDV_MODE_FSK_LDPC_1_ADV)), ctypes.c_void_p) + self.fsk_ldpc_freedv_1 = ctypes.cast(codec2.api.freedv_open_advanced(codec2.api.FREEDV_MODE_FSK_LDPC, + ctypes.byref( + codec2.api.FREEDV_MODE_FSK_LDPC_1_ADV)), + ctypes.c_void_p) self.fsk_ldpc_bytes_per_frame_1 = int(codec2.api.freedv_get_bits_per_modem_frame(self.fsk_ldpc_freedv_1) / 8) self.fsk_ldpc_bytes_out_1 = ctypes.create_string_buffer(self.fsk_ldpc_bytes_per_frame_1) - #codec2.api.freedv_set_frames_per_burst(self.fsk_ldpc_freedv_0, 1) + # codec2.api.freedv_set_frames_per_burst(self.fsk_ldpc_freedv_0, 1) self.fsk_ldpc_buffer_1 = codec2.audio_buffer(self.AUDIO_FRAMES_PER_BUFFER_RX) # initial nin values @@ -132,7 +139,9 @@ class RF(): # --------------------------------------------CREATE PYAUDIO INSTANCE if not TESTMODE: try: - self.stream = sd.RawStream(channels=1, dtype='int16', callback=self.callback, device=(static.AUDIO_INPUT_DEVICE, static.AUDIO_OUTPUT_DEVICE), samplerate = self.AUDIO_SAMPLE_RATE_RX, blocksize=4800) + self.stream = sd.RawStream(channels=1, dtype='int16', callback=self.callback, + device=(static.AUDIO_INPUT_DEVICE, static.AUDIO_OUTPUT_DEVICE), + samplerate=self.AUDIO_SAMPLE_RATE_RX, blocksize=4800) atexit.register(self.stream.stop) structlog.get_logger("structlog").info("[MDM] init: opened audio devices") @@ -142,7 +151,7 @@ class RF(): try: structlog.get_logger("structlog").debug("[MDM] init: starting pyaudio callback") - #self.audio_stream.start_stream() + # self.audio_stream.start_stream() self.stream.start() except Exception as e: @@ -152,6 +161,7 @@ class RF(): # create a stream object for simulating audio stream class Object(object): pass + self.stream = Object() self.stream.active = True @@ -161,12 +171,13 @@ class RF(): os.mkfifo(TXCHANNEL) except Exception as e: structlog.get_logger("structlog").error(f"[MDM] init:mkfifo: Exception: {e}") - pass - mkfifo_write_callback_thread = threading.Thread(target=self.mkfifo_write_callback, name="MKFIFO WRITE CALLBACK THREAD",daemon=True) + mkfifo_write_callback_thread = threading.Thread(target=self.mkfifo_write_callback, + name="MKFIFO WRITE CALLBACK THREAD", daemon=True) mkfifo_write_callback_thread.start() - mkfifo_read_callback_thread = threading.Thread(target=self.mkfifo_read_callback, name="MKFIFO READ CALLBACK THREAD",daemon=True) + mkfifo_read_callback_thread = threading.Thread(target=self.mkfifo_read_callback, + name="MKFIFO READ CALLBACK THREAD", daemon=True) mkfifo_read_callback_thread.start() # --------------------------------------------INIT AND OPEN HAMLIB @@ -183,7 +194,11 @@ class RF(): import rigdummy as rig self.hamlib = rig.radio() - self.hamlib.open_rig(devicename=static.HAMLIB_DEVICE_NAME, deviceport=static.HAMLIB_DEVICE_PORT, hamlib_ptt_type=static.HAMLIB_PTT_TYPE, serialspeed=static.HAMLIB_SERIAL_SPEED, pttport=static.HAMLIB_PTT_PORT, data_bits=static.HAMLIB_DATA_BITS, stop_bits=static.HAMLIB_STOP_BITS, handshake=static.HAMLIB_HANDSHAKE, rigctld_ip = static.HAMLIB_RIGCTLD_IP, rigctld_port = static.HAMLIB_RIGCTLD_PORT) + self.hamlib.open_rig(devicename=static.HAMLIB_DEVICE_NAME, deviceport=static.HAMLIB_DEVICE_PORT, + hamlib_ptt_type=static.HAMLIB_PTT_TYPE, serialspeed=static.HAMLIB_SERIAL_SPEED, + pttport=static.HAMLIB_PTT_PORT, data_bits=static.HAMLIB_DATA_BITS, + stop_bits=static.HAMLIB_STOP_BITS, handshake=static.HAMLIB_HANDSHAKE, + rigctld_ip=static.HAMLIB_RIGCTLD_IP, rigctld_port=static.HAMLIB_RIGCTLD_PORT) # --------------------------------------------START DECODER THREAD if static.ENABLE_FFT: @@ -200,10 +215,12 @@ class RF(): audio_thread_datac3.start() if static.ENABLE_FSK: - audio_thread_fsk_ldpc0 = threading.Thread(target=self.audio_fsk_ldpc_0, name="AUDIO_THREAD FSK LDPC0", daemon=True) + audio_thread_fsk_ldpc0 = threading.Thread(target=self.audio_fsk_ldpc_0, name="AUDIO_THREAD FSK LDPC0", + daemon=True) audio_thread_fsk_ldpc0.start() - audio_thread_fsk_ldpc1 = threading.Thread(target=self.audio_fsk_ldpc_1, name="AUDIO_THREAD FSK LDPC1", daemon=True) + audio_thread_fsk_ldpc1 = threading.Thread(target=self.audio_fsk_ldpc_1, name="AUDIO_THREAD FSK LDPC1", + daemon=True) audio_thread_fsk_ldpc1.start() hamlib_thread = threading.Thread(target=self.update_rig_data, name="HAMLIB_THREAD", daemon=True) @@ -235,10 +252,10 @@ class RF(): self.datac0_buffer.push(x) if not self.datac1_buffer.nbuffer + length_x > self.datac1_buffer.size and RECEIVE_DATAC1: - self.datac1_buffer.push(x) + self.datac1_buffer.push(x) if not self.datac3_buffer.nbuffer + length_x > self.datac3_buffer.size and RECEIVE_DATAC3: - self.datac3_buffer.push(x) + self.datac3_buffer.push(x) def mkfifo_write_callback(self): while 1: @@ -246,12 +263,11 @@ class RF(): # -----write if len(self.modoutqueue) <= 0 or self.mod_out_locked: - #data_out48k = np.zeros(self.AUDIO_FRAMES_PER_BUFFER_RX, dtype=np.int16) + # data_out48k = np.zeros(self.AUDIO_FRAMES_PER_BUFFER_RX, dtype=np.int16) pass else: data_out48k = self.modoutqueue.popleft() - #print(len(data_out48k)) fifo_write = open(TXCHANNEL, 'wb') fifo_write.write(data_out48k) @@ -312,7 +328,7 @@ class RF(): static.BUFFER_OVERFLOW_COUNTER[4] += 1 if len(self.modoutqueue) <= 0 or self.mod_out_locked: - # if not self.modoutqueue or self.mod_out_locked: + data_out48k = np.zeros(frames, dtype=np.int16) self.fft_data = x else: @@ -343,7 +359,7 @@ class RF(): static.TRANSMITTING = True # Toggle ptt early to save some time and send ptt state via socket static.PTT_STATE = self.hamlib.set_ptt(True) - jsondata = {"ptt":"True"} + jsondata = {"ptt": "True"} data_out = json.dumps(jsondata) sock.SOCKET_QUEUE.put(data_out) @@ -390,12 +406,13 @@ class RF(): # Create crc for data frame - we are using the crc function shipped with codec2 to avoid # CRC algorithm incompatibilities - crc = ctypes.c_ushort(codec2.api.freedv_gen_crc16(bytes(buffer), payload_bytes_per_frame)) # Generate CRC16 + crc = ctypes.c_ushort( + codec2.api.freedv_gen_crc16(bytes(buffer), payload_bytes_per_frame)) # Generate CRC16 crc = crc.value.to_bytes(2, byteorder='big') # Convert crc to 2 byte hex string buffer += crc # Append crc16 to buffer data = (ctypes.c_ubyte * bytes_per_frame).from_buffer_copy(buffer) - codec2.api.freedv_rawdatatx(freedv,mod_out,data) # modulate DATA and save it into mod_out pointer + codec2.api.freedv_rawdatatx(freedv, mod_out, data) # modulate DATA and save it into mod_out pointer txbuffer += bytes(mod_out) # codec2 fsk postamble may be broken - at least it sounds like that so we are disabling it for testing @@ -421,14 +438,14 @@ class RF(): self.mod_out_locked = False # ------------------------------- - chunk_length = self.AUDIO_FRAMES_PER_BUFFER_TX #4800 - chunk = [txbuffer_48k[i:i+chunk_length] for i in range(0, len(txbuffer_48k), chunk_length)] + chunk_length = self.AUDIO_FRAMES_PER_BUFFER_TX # 4800 + chunk = [txbuffer_48k[i:i + chunk_length] for i in range(0, len(txbuffer_48k), chunk_length)] for c in chunk: if len(c) < chunk_length: delta = chunk_length - len(c) delta_zeros = np.zeros(delta, dtype=np.int16) c = np.append(c, delta_zeros) - #structlog.get_logger("structlog").debug("[MDM] mod out shorter than audio buffer", delta=delta) + # structlog.get_logger("structlog").debug("[MDM] mod out shorter than audio buffer", delta=delta) self.modoutqueue.append(c) @@ -441,7 +458,7 @@ class RF(): static.PTT_STATE = self.hamlib.set_ptt(False) # Push ptt state to socket stream - jsondata = {"ptt":"False"} + jsondata = {"ptt": "False"} data_out = json.dumps(jsondata) sock.SOCKET_QUEUE.put(data_out) @@ -460,12 +477,14 @@ class RF(): threading.Event().wait(0.01) while self.datac0_buffer.nbuffer >= self.datac0_nin: # demodulate audio - nbytes_datac0 = codec2.api.freedv_rawdatarx(self.datac0_freedv, self.datac0_bytes_out, self.datac0_buffer.buffer.ctypes) + nbytes_datac0 = codec2.api.freedv_rawdatarx(self.datac0_freedv, self.datac0_bytes_out, + self.datac0_buffer.buffer.ctypes) self.datac0_buffer.pop(self.datac0_nin) self.datac0_nin = codec2.api.freedv_nin(self.datac0_freedv) if nbytes_datac0 == self.datac0_bytes_per_frame: - self.modem_received_queue.put([self.datac0_bytes_out, self.datac0_freedv, self.datac0_bytes_per_frame]) - #self.get_scatter(self.datac0_freedv) + self.modem_received_queue.put( + [self.datac0_bytes_out, self.datac0_freedv, self.datac0_bytes_per_frame]) + # self.get_scatter(self.datac0_freedv) self.calculate_snr(self.datac0_freedv) def audio_datac1(self): @@ -475,12 +494,14 @@ class RF(): threading.Event().wait(0.01) while self.datac1_buffer.nbuffer >= self.datac1_nin: # demodulate audio - nbytes_datac1 = codec2.api.freedv_rawdatarx(self.datac1_freedv, self.datac1_bytes_out, self.datac1_buffer.buffer.ctypes) + nbytes_datac1 = codec2.api.freedv_rawdatarx(self.datac1_freedv, self.datac1_bytes_out, + self.datac1_buffer.buffer.ctypes) self.datac1_buffer.pop(self.datac1_nin) self.datac1_nin = codec2.api.freedv_nin(self.datac1_freedv) if nbytes_datac1 == self.datac1_bytes_per_frame: - self.modem_received_queue.put([self.datac1_bytes_out, self.datac1_freedv, self.datac1_bytes_per_frame]) - #self.get_scatter(self.datac1_freedv) + self.modem_received_queue.put( + [self.datac1_bytes_out, self.datac1_freedv, self.datac1_bytes_per_frame]) + # self.get_scatter(self.datac1_freedv) self.calculate_snr(self.datac1_freedv) def audio_datac3(self): @@ -490,12 +511,14 @@ class RF(): threading.Event().wait(0.01) while self.datac3_buffer.nbuffer >= self.datac3_nin: # demodulate audio - nbytes_datac3 = codec2.api.freedv_rawdatarx(self.datac3_freedv, self.datac3_bytes_out, self.datac3_buffer.buffer.ctypes) + nbytes_datac3 = codec2.api.freedv_rawdatarx(self.datac3_freedv, self.datac3_bytes_out, + self.datac3_buffer.buffer.ctypes) self.datac3_buffer.pop(self.datac3_nin) self.datac3_nin = codec2.api.freedv_nin(self.datac3_freedv) if nbytes_datac3 == self.datac3_bytes_per_frame: - self.modem_received_queue.put([self.datac3_bytes_out, self.datac3_freedv, self.datac3_bytes_per_frame]) - #self.get_scatter(self.datac3_freedv) + self.modem_received_queue.put( + [self.datac3_bytes_out, self.datac3_freedv, self.datac3_bytes_per_frame]) + # self.get_scatter(self.datac3_freedv) self.calculate_snr(self.datac3_freedv) def audio_fsk_ldpc_0(self): @@ -505,12 +528,14 @@ class RF(): threading.Event().wait(0.01) while self.fsk_ldpc_buffer_0.nbuffer >= self.fsk_ldpc_nin_0: # demodulate audio - nbytes_fsk_ldpc_0 = codec2.api.freedv_rawdatarx(self.fsk_ldpc_freedv_0, self.fsk_ldpc_bytes_out_0, self.fsk_ldpc_buffer_0.buffer.ctypes) + nbytes_fsk_ldpc_0 = codec2.api.freedv_rawdatarx(self.fsk_ldpc_freedv_0, self.fsk_ldpc_bytes_out_0, + self.fsk_ldpc_buffer_0.buffer.ctypes) self.fsk_ldpc_buffer_0.pop(self.fsk_ldpc_nin_0) self.fsk_ldpc_nin_0 = codec2.api.freedv_nin(self.fsk_ldpc_freedv_0) if nbytes_fsk_ldpc_0 == self.fsk_ldpc_bytes_per_frame_0: - self.modem_received_queue.put([self.fsk_ldpc_bytes_out_0, self.fsk_ldpc_freedv_0, self.fsk_ldpc_bytes_per_frame_0]) - #self.get_scatter(self.fsk_ldpc_freedv_0) + self.modem_received_queue.put( + [self.fsk_ldpc_bytes_out_0, self.fsk_ldpc_freedv_0, self.fsk_ldpc_bytes_per_frame_0]) + # self.get_scatter(self.fsk_ldpc_freedv_0) self.calculate_snr(self.fsk_ldpc_freedv_0) def audio_fsk_ldpc_1(self): @@ -520,12 +545,14 @@ class RF(): threading.Event().wait(0.01) while self.fsk_ldpc_buffer_1.nbuffer >= self.fsk_ldpc_nin_1: # demodulate audio - nbytes_fsk_ldpc_1 = codec2.api.freedv_rawdatarx(self.fsk_ldpc_freedv_1, self.fsk_ldpc_bytes_out_1, self.fsk_ldpc_buffer_1.buffer.ctypes) + nbytes_fsk_ldpc_1 = codec2.api.freedv_rawdatarx(self.fsk_ldpc_freedv_1, self.fsk_ldpc_bytes_out_1, + self.fsk_ldpc_buffer_1.buffer.ctypes) self.fsk_ldpc_buffer_1.pop(self.fsk_ldpc_nin_1) self.fsk_ldpc_nin_1 = codec2.api.freedv_nin(self.fsk_ldpc_freedv_1) if nbytes_fsk_ldpc_1 == self.fsk_ldpc_bytes_per_frame_1: - self.modem_received_queue.put([self.fsk_ldpc_bytes_out_1, self.fsk_ldpc_freedv_1, self.fsk_ldpc_bytes_per_frame_1]) - #self.get_scatter(self.fsk_ldpc_freedv_1) + self.modem_received_queue.put( + [self.fsk_ldpc_bytes_out_1, self.fsk_ldpc_freedv_1, self.fsk_ldpc_bytes_per_frame_1]) + # self.get_scatter(self.fsk_ldpc_freedv_1) self.calculate_snr(self.fsk_ldpc_freedv_1) # worker for FIFO queue for processing received frames @@ -536,7 +563,7 @@ class RF(): structlog.get_logger("structlog").debug("[MDM] worker_transmit", mode=data[0]) self.transmit(mode=data[0], repeats=data[1], repeat_delay=data[2], frames=data[3]) - #self.modem_transmit_queue.task_done() + # self.modem_transmit_queue.task_done() # worker for FIFO queue for processing received frames def worker_received(self): @@ -644,7 +671,7 @@ class RF(): channel_busy_delay = 0 while True: - #time.sleep(0.01) + # time.sleep(0.01) threading.Event().wait(0.01) # WE NEED TO OPTIMIZE THIS! @@ -657,7 +684,7 @@ class RF(): # set value 0 to 1 to avoid division by zero fftarray[fftarray == 0] = 1 - dfft = 10.*np.log10(abs(fftarray)) + dfft = 10. * np.log10(abs(fftarray)) # get average of dfft avg = np.mean(dfft) @@ -666,7 +693,7 @@ class RF(): # Data higher than the average must be a signal. 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: - dfft[dfft>avg+10] = 100 + dfft[dfft > avg + 10] = 100 # Calculate audio max value # static.AUDIO_RMS = np.amax(self.fft_data) @@ -688,7 +715,7 @@ class RF(): dfft = np.around(dfft, 0) dfftlist = dfft.tolist() - static.FFT = dfftlist[:320] #320 --> bandwidth 3000 + static.FFT = dfftlist[:320] # 320 --> bandwidth 3000 except Exception as e: structlog.get_logger("structlog").error(f"[MDM] calculate_fft: Exception: {e}") structlog.get_logger("structlog").debug("[MDM] Setting fft=0") @@ -708,15 +735,18 @@ class RF(): codec2.api.freedv_set_frames_per_burst(self.datac3_freedv, n_frames_per_burst) codec2.api.freedv_set_frames_per_burst(self.fsk_ldpc_freedv_0, n_frames_per_burst) + def open_codec2_instance(mode): """ Return a codec2 instance """ if mode in ['FSK_LDPC_0', 200]: return ctypes.cast(codec2.api.freedv_open_advanced(codec2.api.FREEDV_MODE_FSK_LDPC, - ctypes.byref(codec2.api.FREEDV_MODE_FSK_LDPC_0_ADV)), ctypes.c_void_p) + ctypes.byref(codec2.api.FREEDV_MODE_FSK_LDPC_0_ADV)), + ctypes.c_void_p) if mode in ['FSK_LDPC_1', 201]: return ctypes.cast(codec2.api.freedv_open_advanced(codec2.api.FREEDV_MODE_FSK_LDPC, - ctypes.byref(codec2.api.FREEDV_MODE_FSK_LDPC_1_ADV)), ctypes.c_void_p) + ctypes.byref(codec2.api.FREEDV_MODE_FSK_LDPC_1_ADV)), + ctypes.c_void_p) return ctypes.cast(codec2.api.freedv_open(mode), ctypes.c_void_p) diff --git a/tnc/rig.py b/tnc/rig.py index cdbf879f..cbc960f3 100644 --- a/tnc/rig.py +++ b/tnc/rig.py @@ -23,13 +23,13 @@ try: python_version = str(sys.version_info[0]) + "." + str(sys.version_info[1]) # installation path for Ubuntu 20.04 LTS python modules - #sys.path.append('/usr/local/lib/python'+ python_version +'/site-packages') + # sys.path.append('/usr/local/lib/python'+ python_version +'/site-packages') # installation path for Ubuntu 20.10 + sys.path.append('/usr/local/lib/') # installation path for Suse - sys.path.append('/usr/local/lib64/python'+ python_version +'/site-packages') + sys.path.append('/usr/local/lib64/python' + python_version + '/site-packages') # everything else... not nice, but an attempt to see how its running within app bundle # this is not needed as python will be shipped with app bundle @@ -55,7 +55,7 @@ except Exception as e: structlog.get_logger("structlog").warning("[RIG] Python Hamlib binding not found", error=e) try: structlog.get_logger("structlog").warning("[RIG] Trying to open rigctl") - rigctl = subprocess.Popen("rigctl -V",shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True) + rigctl = subprocess.Popen("rigctl -V", shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True) hamlib_version = rigctl.stdout.readline() hamlib_version = hamlib_version.split(' ') @@ -166,7 +166,7 @@ class radio: elif self.hamlib_ptt_type == 'RIG_PTT_NONE': self.hamlib_ptt_type = Hamlib.RIG_PTT_NONE - else: #self.hamlib_ptt_type == 'RIG_PTT_NONE': + else: # self.hamlib_ptt_type == 'RIG_PTT_NONE': self.hamlib_ptt_type = Hamlib.RIG_PTT_NONE structlog.get_logger("structlog").info("[RIG] Opening...", device=self.devicenumber, path=self.my_rig.get_conf("rig_pathname"), serial_speed=self.my_rig.get_conf("serial_speed"), serial_handshake=self.my_rig.get_conf("serial_handshake"), stop_bits=self.my_rig.get_conf("stop_bits"), data_bits=self.my_rig.get_conf("data_bits"), ptt_pathname=self.my_rig.get_conf("ptt_pathname")) @@ -192,7 +192,7 @@ class radio: # set rig mode to USB # temporarly outcommented because of possible problems. - #self.my_rig.set_mode(Hamlib.RIG_MODE_USB) + # self.my_rig.set_mode(Hamlib.RIG_MODE_USB) # self.my_rig.set_mode(Hamlib.RIG_MODE_PKTUSB) return True @@ -215,7 +215,7 @@ class radio: return bandwith # not needed yet beacuse of some possible problems - #def set_mode(self, mode): + # def set_mode(self, mode): # return 0 def get_ptt(self): diff --git a/tnc/rigctl.py b/tnc/rigctl.py index 319d511a..8115d3e7 100644 --- a/tnc/rigctl.py +++ b/tnc/rigctl.py @@ -54,14 +54,14 @@ class radio: """ self.devicename = devicename self.deviceport = deviceport - self.serialspeed = str(serialspeed) # we need to ensure this is a str, otherwise set_conf functions are crashing + self.serialspeed = str(serialspeed) # we need to ensure this is a str, otherwise set_conf functions are crashing self.hamlib_ptt_type = hamlib_ptt_type self.pttport = pttport self.data_bits = data_bits self.stop_bits = stop_bits self.handshake = handshake - # check if we are running in a pyinstaller environment + # check if we are running in a pyinstaller environment if hasattr(sys, "_MEIPASS"): sys.path.append(getattr(sys, "_MEIPASS")) else: @@ -75,7 +75,7 @@ class radio: if int(self.devicename): self.devicenumber = int(self.devicename) else: - self.devicenumber = 6 #dummy + self.devicenumber = 6 # dummy structlog.get_logger("structlog").warning("[RIGCTL] Radio not found. Using DUMMY!", error=e) # set deviceport to dummy port, if we selected dummy model @@ -179,5 +179,5 @@ class radio: def close_rig(self): """ """ - #self.my_rig.close() + # self.my_rig.close() return diff --git a/tnc/rigctld.py b/tnc/rigctld.py index 422a6e95..0b9e4f43 100644 --- a/tnc/rigctld.py +++ b/tnc/rigctld.py @@ -24,7 +24,7 @@ class radio(): def __init__(self, hostname="localhost", port=4532, poll_rate=5, timeout=5): """ Open a connection to rotctld, and test it for validity """ self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - #self.sock.settimeout(timeout) + # self.sock.settimeout(timeout) self.connected = False self.hostname = hostname @@ -63,7 +63,7 @@ class radio(): """Connect to rigctld instance""" if not self.connected: try: - self.connection = socket.create_connection((self.hostname,self.port)) + self.connection = socket.create_connection((self.hostname, self.port)) self.connected = True structlog.get_logger("structlog").info("[RIGCTLD] Connected to rigctld!", ip=self.hostname, port=self.port) return True diff --git a/tnc/sock.py b/tnc/sock.py index 6b6179b0..f3493785 100644 --- a/tnc/sock.py +++ b/tnc/sock.py @@ -21,22 +21,19 @@ Created on Fri Dec 25 21:25:14 2020 """ import atexit import base64 -import logging -import os + import queue import socketserver import sys import threading import time -import psutil import structlog import ujson as json -import audio import data_handler import helpers -import log_handler + import static SOCKET_QUEUE = queue.Queue() @@ -81,10 +78,10 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): while not SOCKET_QUEUE.empty(): data = SOCKET_QUEUE.get() sock_data = bytes(data, 'utf-8') - sock_data += b'\n' # append line limiter + sock_data += b'\n' # append line limiter # send data to all clients - #try: + # try: for client in CONNECTED_CLIENTS: try: client.send(sock_data) @@ -97,7 +94,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): static.SCATTER = [] # we want to display INFO messages only once static.INFO = [] - #self.request.sendall(sock_data) + # self.request.sendall(sock_data) time.sleep(0.15) def receive_from_client(self): @@ -112,7 +109,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): data += chunk if chunk == b'': - #print("connection broken. Closing...") + # print("connection broken. Closing...") self.connection_alive = False if data.startswith(b'{') and data.endswith(b'}\n'): @@ -138,7 +135,8 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): # finally delete our rx buffer to be ready for new commands data = bytes() except Exception as e: - structlog.get_logger("structlog").info("[SCK] Connection closed", ip=self.client_address[0], port=self.client_address[1], e=e) + structlog.get_logger("structlog").info("[SCK] Connection closed", ip=self.client_address[0], + port=self.client_address[1], e=e) self.connection_alive = False def handle(self): @@ -147,11 +145,12 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): """ CONNECTED_CLIENTS.add(self.request) - structlog.get_logger("structlog").debug("[SCK] Client connected", ip=self.client_address[0], port=self.client_address[1]) + structlog.get_logger("structlog").debug("[SCK] Client connected", ip=self.client_address[0], + port=self.client_address[1]) self.connection_alive = True - self.sendThread = threading.Thread(target=self.send_to_client, args=[],daemon=True).start() - self.receiveThread = threading.Thread(target=self.receive_from_client, args=[],daemon=True).start() + self.sendThread = threading.Thread(target=self.send_to_client, args=[], daemon=True).start() + self.receiveThread = threading.Thread(target=self.receive_from_client, args=[], daemon=True).start() # keep connection alive until we close it while self.connection_alive and not CLOSE_SIGNAL: @@ -159,11 +158,14 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): def finish(self): """ """ - structlog.get_logger("structlog").warning("[SCK] Closing client socket", ip=self.client_address[0], port=self.client_address[1]) + structlog.get_logger("structlog").warning("[SCK] Closing client socket", ip=self.client_address[0], + port=self.client_address[1]) try: CONNECTED_CLIENTS.remove(self.request) except: - structlog.get_logger("structlog").warning("[SCK] client connection already removed from client list", client=self.request) + structlog.get_logger("structlog").warning("[SCK] client connection already removed from client list", + client=self.request) + def process_tnc_commands(data): """ @@ -346,13 +348,15 @@ def process_tnc_commands(data): } for i in range(len(static.RX_BUFFER)): - #print(static.RX_BUFFER[i][4]) - #rawdata = json.loads(static.RX_BUFFER[i][4]) + # print(static.RX_BUFFER[i][4]) + # rawdata = json.loads(static.RX_BUFFER[i][4]) base64_data = static.RX_BUFFER[i][4] - output["data-array"].append({"uuid": static.RX_BUFFER[i][0],"timestamp": static.RX_BUFFER[i][1], "dxcallsign": str(static.RX_BUFFER[i][2], 'utf-8'), "dxgrid": str(static.RX_BUFFER[i][3], 'utf-8'), "data": base64_data}) + output["data-array"].append({"uuid": static.RX_BUFFER[i][0], "timestamp": static.RX_BUFFER[i][1], + "dxcallsign": str(static.RX_BUFFER[i][2], 'utf-8'), + "dxgrid": str(static.RX_BUFFER[i][3], 'utf-8'), "data": base64_data}) jsondata = json.dumps(output) - #self.request.sendall(bytes(jsondata, encoding)) + # self.request.sendall(bytes(jsondata, encoding)) SOCKET_QUEUE.put(jsondata) command_response("rx_buffer", True) @@ -368,10 +372,11 @@ def process_tnc_commands(data): command_response("del_rx_buffer", False) structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json) - # exception, if JSON cant be decoded + # exception, if JSON can't be decoded except Exception as e: structlog.get_logger("structlog").error("[TNC] JSON decoding error", e=e) + def send_tnc_state(): """ send the tnc state to network @@ -401,8 +406,8 @@ def send_tnc_state(): "arq_compression_factor": str(static.ARQ_COMPRESSION_FACTOR), "arq_transmission_percent": str(static.ARQ_TRANSMISSION_PERCENT), "total_bytes": str(static.TOTAL_BYTES), - "info" : static.INFO, - "beacon_state" : str(static.BEACON_STATE), + "info": static.INFO, + "beacon_state": str(static.BEACON_STATE), "stations": [], "mycallsign": str(static.MYCALLSIGN, encoding), "dxcallsign": str(static.DXCALLSIGN, encoding), @@ -422,6 +427,7 @@ def send_tnc_state(): return json.dumps(output) + def process_daemon_commands(data): """ process daemon commands @@ -441,13 +447,15 @@ def process_daemon_commands(data): if bytes(callsign, 'utf-8') == b'': self.request.sendall(b'INVALID CALLSIGN') - structlog.get_logger("structlog").warning("[DMN] SET MYCALL FAILED", call=static.MYCALLSIGN, crc=static.MYCALLSIGN_CRC) + structlog.get_logger("structlog").warning("[DMN] SET MYCALL FAILED", call=static.MYCALLSIGN, + crc=static.MYCALLSIGN_CRC) else: static.MYCALLSIGN = bytes(callsign, 'utf-8') static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN) command_response("mycallsign", True) - structlog.get_logger("structlog").info("[DMN] SET MYCALL", call=static.MYCALLSIGN, crc=static.MYCALLSIGN_CRC) + structlog.get_logger("structlog").info("[DMN] SET MYCALL", call=static.MYCALLSIGN, + crc=static.MYCALLSIGN_CRC) except Exception as e: command_response("mycallsign", False) structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json) @@ -494,33 +502,34 @@ def process_daemon_commands(data): # print some debugging parameters for item in received_json["parameter"][0]: - structlog.get_logger("structlog").debug("[DMN] TNC Startup Config : " + item, value=received_json["parameter"][0][item]) + structlog.get_logger("structlog").debug("[DMN] TNC Startup Config : " + item, + value=received_json["parameter"][0][item]) DAEMON_QUEUE.put(['STARTTNC', - mycall, - mygrid, - rx_audio, - tx_audio, - devicename, - deviceport, - serialspeed, - pttprotocol, - pttport, - data_bits, - stop_bits, - handshake, - radiocontrol, - rigctld_ip, - rigctld_port, - enable_scatter, - enable_fft, - low_bandwith_mode, - tuning_range_fmin, - tuning_range_fmax, - enable_fsk, - tx_audio_level, - respond_to_cq, - ]) + mycall, + mygrid, + rx_audio, + tx_audio, + devicename, + deviceport, + serialspeed, + pttprotocol, + pttport, + data_bits, + stop_bits, + handshake, + radiocontrol, + rigctld_ip, + rigctld_port, + enable_scatter, + enable_fft, + low_bandwith_mode, + tuning_range_fmin, + tuning_range_fmax, + enable_fsk, + tx_audio_level, + respond_to_cq, + ]) command_response("start_tnc", True) except Exception as e: @@ -542,18 +551,18 @@ def process_daemon_commands(data): rigctld_port = str(received_json["parameter"][0]["rigctld_port"]) DAEMON_QUEUE.put(['TEST_HAMLIB', - devicename, - deviceport, - serialspeed, - pttprotocol, - pttport, - data_bits, - stop_bits, - handshake, - radiocontrol, - rigctld_ip, - rigctld_port, - ]) + devicename, + deviceport, + serialspeed, + pttprotocol, + pttport, + data_bits, + stop_bits, + handshake, + radiocontrol, + rigctld_ip, + rigctld_port, + ]) command_response("test_hamlib", True) except Exception as e: command_response("test_hamlib", False) @@ -572,6 +581,7 @@ def process_daemon_commands(data): command_response("stop_tnc", False) structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json) + def send_daemon_state(): """ send the daemon state to network @@ -587,10 +597,10 @@ def send_daemon_state(): 'input_devices': static.AUDIO_INPUT_DEVICES, 'output_devices': static.AUDIO_OUTPUT_DEVICES, 'serial_devices': static.SERIAL_DEVICES, - #'cpu': str(psutil.cpu_percent()), - #'ram': str(psutil.virtual_memory().percent), + # 'cpu': str(psutil.cpu_percent()), + # 'ram': str(psutil.virtual_memory().percent), 'version': '0.1' - } + } if static.TNCSTARTED: output["daemon_state"].append({"status": "running"}) @@ -604,8 +614,9 @@ def send_daemon_state(): structlog.get_logger("structlog").warning("[SCK] error", e=e) return None + def command_response(command, status): s_status = "OK" if status else "Failed" - jsondata = {"command_response": command, "status" : s_status} + jsondata = {"command_response": command, "status": s_status} data_out = json.dumps(jsondata) SOCKET_QUEUE.put(data_out) diff --git a/tnc/static.py b/tnc/static.py index 2922520c..9b2e311a 100644 --- a/tnc/static.py +++ b/tnc/static.py @@ -25,7 +25,7 @@ DXCALLSIGN_CRC = b'A' MYGRID = b'' DXGRID = b'' -SSID_LIST = [] # ssid list we are responding to +SSID_LIST = [] # ssid list we are responding to LOW_BANDWITH_MODE = False # --------------------------------- @@ -33,7 +33,7 @@ LOW_BANDWITH_MODE = False # Server Defaults HOST = "0.0.0.0" PORT = 3000 -SOCKET_TIMEOUT = 1 # seconds +SOCKET_TIMEOUT = 1 # seconds # --------------------------------- SERIAL_DEVICES = [] # --------------------------------- @@ -74,7 +74,7 @@ AUDIO_INPUT_DEVICES = [] AUDIO_OUTPUT_DEVICES = [] AUDIO_INPUT_DEVICE = -2 AUDIO_OUTPUT_DEVICE = -2 -BUFFER_OVERFLOW_COUNTER = [0,0,0,0,0] +BUFFER_OVERFLOW_COUNTER = [0, 0, 0, 0, 0] AUDIO_RMS = 0 FFT = [0] @@ -94,11 +94,11 @@ ARQ_TRANSMISSION_PERCENT = 0 ARQ_SPEED_LEVEL = 0 TOTAL_BYTES = 0 -#CHANNEL_STATE = 'RECEIVING_SIGNALLING' +# CHANNEL_STATE = 'RECEIVING_SIGNALLING' TNC_STATE = 'IDLE' ARQ_STATE = False ARQ_SESSION = False -ARQ_SESSION_STATE = 'disconnected' # disconnected, connecting, connected, disconnecting, failed +ARQ_SESSION_STATE = 'disconnected' # disconnected, connecting, connected, disconnecting, failed # BEACON STATE BEACON_STATE = False @@ -109,9 +109,9 @@ RX_BUFFER = [] RX_MSG_BUFFER = [] RX_BURST_BUFFER = [] RX_FRAME_BUFFER = b'' -#RX_BUFFER_SIZE = 0 +# RX_BUFFER_SIZE = 0 -# ------- HEARD STATIOS BUFFER +# ------- HEARD STATIONS BUFFER HEARD_STATIONS = [] # ------- INFO MESSAGE BUFFER From 7a530175f83344b22d75d3de1661cb6001ce2309 Mon Sep 17 00:00:00 2001 From: DJ2LS <75909252+DJ2LS@users.noreply.github.com> Date: Mon, 23 May 2022 14:02:22 +0200 Subject: [PATCH 3/8] Accepted some Sourcery solutions --- tnc/modem.py | 28 ++++++++++++---------------- tnc/rig.py | 20 +++++++++++--------- tnc/rigctl.py | 23 ++++++++++------------- tnc/rigctld.py | 14 +++++++------- tnc/sock.py | 15 +++++++-------- 5 files changed, 47 insertions(+), 53 deletions(-) diff --git a/tnc/modem.py b/tnc/modem.py index 74eba890..5a10c3e6 100644 --- a/tnc/modem.py +++ b/tnc/modem.py @@ -300,33 +300,29 @@ class RF: static.BUFFER_OVERFLOW_COUNTER[0] += 1 # Avoid buffer overflow by filling only if buffer not full and selected datachannel mode - if not self.datac1_buffer.nbuffer + length_x > self.datac1_buffer.size: - if RECEIVE_DATAC1: - self.datac1_buffer.push(x) - else: + if self.datac1_buffer.nbuffer + length_x > self.datac1_buffer.size: static.BUFFER_OVERFLOW_COUNTER[1] += 1 + elif RECEIVE_DATAC1: + self.datac1_buffer.push(x) # Avoid buffer overflow by filling only if buffer not full and selected datachannel mode - if not self.datac3_buffer.nbuffer + length_x > self.datac3_buffer.size: - if RECEIVE_DATAC3: - self.datac3_buffer.push(x) - else: + if self.datac3_buffer.nbuffer + length_x > self.datac3_buffer.size: static.BUFFER_OVERFLOW_COUNTER[2] += 1 + elif RECEIVE_DATAC3: + self.datac3_buffer.push(x) # Avoid buffer overflow by filling only if buffer not full and selected datachannel mode - if not self.fsk_ldpc_buffer_0.nbuffer + length_x > self.fsk_ldpc_buffer_0.size: - if static.ENABLE_FSK: - self.fsk_ldpc_buffer_0.push(x) - else: + if self.fsk_ldpc_buffer_0.nbuffer + length_x > self.fsk_ldpc_buffer_0.size: static.BUFFER_OVERFLOW_COUNTER[3] += 1 + elif static.ENABLE_FSK: + self.fsk_ldpc_buffer_0.push(x) # Avoid buffer overflow by filling only if buffer not full and selected datachannel mode - if not self.fsk_ldpc_buffer_1.nbuffer + length_x > self.fsk_ldpc_buffer_1.size: - if RECEIVE_FSK_LDPC_1 and static.ENABLE_FSK: - self.fsk_ldpc_buffer_1.push(x) - else: + if self.fsk_ldpc_buffer_1.nbuffer + length_x > self.fsk_ldpc_buffer_1.size: static.BUFFER_OVERFLOW_COUNTER[4] += 1 + elif RECEIVE_FSK_LDPC_1 and static.ENABLE_FSK: + self.fsk_ldpc_buffer_1.push(x) if len(self.modoutqueue) <= 0 or self.mod_out_locked: data_out48k = np.zeros(frames, dtype=np.int16) diff --git a/tnc/rig.py b/tnc/rig.py index cbc960f3..c0e01cb8 100644 --- a/tnc/rig.py +++ b/tnc/rig.py @@ -20,7 +20,7 @@ else: # try importing hamlib try: # get python version - python_version = str(sys.version_info[0]) + "." + str(sys.version_info[1]) + python_version = f"{str(sys.version_info[0])}.{str(sys.version_info[1])}" # installation path for Ubuntu 20.04 LTS python modules # sys.path.append('/usr/local/lib/python'+ python_version +'/site-packages') @@ -29,7 +29,7 @@ try: sys.path.append('/usr/local/lib/') # installation path for Suse - sys.path.append('/usr/local/lib64/python' + python_version + '/site-packages') + sys.path.append(f'/usr/local/lib64/python{python_version}/site-packages') # everything else... not nice, but an attempt to see how its running within app bundle # this is not needed as python will be shipped with app bundle @@ -53,19 +53,21 @@ try: structlog.get_logger("structlog").warning("[RIG] Hamlib outdated", found=hamlib_version, recommend=min_hamlib_version) except Exception as e: structlog.get_logger("structlog").warning("[RIG] Python Hamlib binding not found", error=e) + try: structlog.get_logger("structlog").warning("[RIG] Trying to open rigctl") rigctl = subprocess.Popen("rigctl -V", shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True) + hamlib_version = rigctl.stdout.readline() hamlib_version = hamlib_version.split(' ') + if hamlib_version[1] != 'Hamlib': + raise Exception from e + structlog.get_logger("structlog").warning("[RIG] Rigctl found! Please try using this", version=hamlib_version[2]) - if hamlib_version[1] == 'Hamlib': - structlog.get_logger("structlog").warning("[RIG] Rigctl found! Please try using this", version=hamlib_version[2]) - sys.exit() - else: - raise Exception + sys.exit() except Exception as e: structlog.get_logger("structlog").critical("[RIG] HAMLIB NOT INSTALLED", error=e) + hamlib_version = 0 sys.exit() @@ -118,7 +120,7 @@ class radio: # get devicenumber by looking for deviceobject in Hamlib module try: self.devicenumber = int(getattr(Hamlib, self.devicename)) - except: + except Exception: structlog.get_logger("structlog").error("[RIG] Hamlib: rig not supported...") self.devicenumber = 0 @@ -184,7 +186,7 @@ class radio: structlog.get_logger("structlog").error("[RIG] Hamlib has no permissions", e = error) help_url = 'https://github.com/DJ2LS/FreeDATA/wiki/UBUNTU-Manual-installation#1-permissions' structlog.get_logger("structlog").error("[RIG] HELP:", check = help_url) - except: + except Exception: structlog.get_logger("structlog").info("[RIG] Hamlib device opened", status='SUCCESS') # set ptt to false if ptt is stuck for some reason diff --git a/tnc/rigctl.py b/tnc/rigctl.py index 8115d3e7..3e9a5e6c 100644 --- a/tnc/rigctl.py +++ b/tnc/rigctl.py @@ -79,7 +79,7 @@ class radio: structlog.get_logger("structlog").warning("[RIGCTL] Radio not found. Using DUMMY!", error=e) # set deviceport to dummy port, if we selected dummy model - if self.devicenumber == 1 or self.devicenumber == 6: + if self.devicenumber in {1, 6}: self.deviceport = '/dev/ttyUSB0' print(self.devicenumber, self.deviceport, self.serialspeed) @@ -101,14 +101,14 @@ class radio: def get_frequency(self): """ """ - cmd = self.cmd + ' f' + cmd = f'{self.cmd} f' sw_proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True) time.sleep(0.5) freq = sw_proc.communicate()[0] #print('get_frequency', freq, sw_proc.communicate()) try: return int(freq) - except: + except Exception: return False def get_mode(self): @@ -117,7 +117,7 @@ class radio: #return Hamlib.rig_strrmode(hamlib_mode) try: return 'PKTUSB' - except: + except Exception: return False def get_bandwith(self): @@ -127,7 +127,7 @@ class radio: try: return bandwith - except: + except Exception: return False def set_mode(self, mode): @@ -144,14 +144,14 @@ class radio: def get_ptt(self): """ """ - cmd = self.cmd + ' t' + cmd = f'{self.cmd} t' sw_proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True) time.sleep(0.5) status = sw_proc.communicate()[0] try: return status - except: + except Exception: return False def set_ptt(self, state): @@ -163,18 +163,15 @@ class radio: Returns: """ - cmd = self.cmd + ' T ' + cmd = f'{self.cmd} T ' print('set_ptt', state) - if state: - cmd = cmd + '1' - else: - cmd = cmd + '0' + cmd = f'{cmd}1' if state else f'{cmd}0' print('set_ptt', cmd) sw_proc = subprocess.Popen(cmd, shell=True, text=True) try: return state - except: + except Exception: return False def close_rig(self): diff --git a/tnc/rigctld.py b/tnc/rigctld.py index 244b37ce..67b16f3a 100644 --- a/tnc/rigctld.py +++ b/tnc/rigctld.py @@ -91,13 +91,13 @@ class radio(): if self.connected: try: self.connection.sendall(command+b'\n') - except: + except Exception: structlog.get_logger("structlog").warning("[RIGCTLD] Command not executed!", command=command, ip=self.hostname, port=self.port) self.connected = False try: return self.connection.recv(1024) - except: + except Exception: structlog.get_logger("structlog").warning("[RIGCTLD] No command response!", command=command, ip=self.hostname, port=self.port) self.connected = False else: @@ -113,7 +113,7 @@ class radio(): data = data.split(b'\n') mode = data[0] return mode.decode("utf-8") - except: + except Exception: return 0 def get_bandwith(self): @@ -123,7 +123,7 @@ class radio(): data = data.split(b'\n') bandwith = data[1] return bandwith.decode("utf-8") - except: + except Exception: return 0 def get_frequency(self): @@ -131,14 +131,14 @@ class radio(): try: frequency = self.send_command(b"f") return frequency.decode("utf-8") - except: + except Exception: return 0 def get_ptt(self): """ """ try: return self.send_command(b"t") - except: + except Exception: return False def set_ptt(self, state): @@ -156,5 +156,5 @@ class radio(): else: self.send_command(b"T 0") return state - except: + except Exception: return False diff --git a/tnc/sock.py b/tnc/sock.py index f3493785..e5ba20fe 100644 --- a/tnc/sock.py +++ b/tnc/sock.py @@ -162,9 +162,9 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): port=self.client_address[1]) try: CONNECTED_CLIENTS.remove(self.request) - except: + except Exception as e: structlog.get_logger("structlog").warning("[SCK] client connection already removed from client list", - client=self.request) + client=self.request, e=e) def process_tnc_commands(data): @@ -308,13 +308,13 @@ def process_tnc_commands(data): # check if specific callsign is set with different SSID than the TNC is initialized try: mycallsign = received_json["parameter"][0]["mycallsign"] - except: + except Exception: mycallsign = static.MYCALLSIGN # check if transmission uuid provided else set no-uuid try: arq_uuid = received_json["uuid"] - except: + except Exception: arq_uuid = 'no-uuid' if not len(base64data) % 4: @@ -502,8 +502,8 @@ def process_daemon_commands(data): # print some debugging parameters for item in received_json["parameter"][0]: - structlog.get_logger("structlog").debug("[DMN] TNC Startup Config : " + item, - value=received_json["parameter"][0][item]) + structlog.get_logger("structlog").debug(f"[DMN] TNC Startup Config : {item}", value=received_json["parameter"][0][item]) + DAEMON_QUEUE.put(['STARTTNC', mycall, @@ -607,9 +607,8 @@ def send_daemon_state(): else: output["daemon_state"].append({"status": "stopped"}) - jsondata = json.dumps(output) + return json.dumps(output) - return jsondata except Exception as e: structlog.get_logger("structlog").warning("[SCK] error", e=e) return None From e05bc262ad6e3cfa34e731b90557b8809ad99057 Mon Sep 17 00:00:00 2001 From: DJ2LS <75909252+DJ2LS@users.noreply.github.com> Date: Mon, 23 May 2022 14:26:14 +0200 Subject: [PATCH 4/8] and some more typos and whitespace correction.. --- .github/workflows/ctest.yml | 2 +- README.md | 4 +- test/README.md | 2 +- test/hamlib-test.py | 28 +++++-------- test/ping.py | 2 +- test/pong.py | 48 +++++++++++----------- test/test_arq_short.py | 1 + test/test_audiobuffer.py | 2 +- test/test_callback_multimode_rx.py | 2 +- test/test_callback_multimode_rx_outside.py | 2 +- test/test_callback_multimode_tx.py | 4 +- test/test_callback_rx.py | 2 +- test/test_callback_rx_outside.py | 2 +- test/test_callback_tx.py | 4 +- test/test_multimode_rx.py | 2 +- test/test_multimode_tx.py | 2 +- test/test_rx.py | 2 +- test/test_tnc_states.py | 4 +- test/test_tx.py | 4 +- tnc/codec2.py | 2 +- tnc/daemon.py | 2 - tnc/data_handler.py | 4 -- tnc/main.py | 4 +- tnc/rig.py | 4 +- tnc/rigctl.py | 8 ++-- tnc/rigctld.py | 4 +- tnc/sock.py | 1 - tools/list_audio_devices.py | 7 ---- tools/readfromsocket.py | 5 +-- tools/socketclient.py | 26 ++++-------- 30 files changed, 76 insertions(+), 110 deletions(-) diff --git a/.github/workflows/ctest.yml b/.github/workflows/ctest.yml index 8721a823..c6c5c9a3 100644 --- a/.github/workflows/ctest.yml +++ b/.github/workflows/ctest.yml @@ -4,7 +4,7 @@ on: [push] jobs: build: - # The CMake configure and build commands are platform agnostic and should work equally + # The CMake configure and build commands are platform-agnostic and should work equally # well on Windows or Mac. You can convert this to a matrix build if you need # cross-platform coverage. # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix diff --git a/README.md b/README.md index 755a8c57..5c681dbc 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ My attempt to create a free and open-source TNC with a GUI for [codec2](https:// Please keep in mind, that this project is still a prototype with many issues which need to be solved. Build steps for other OS than Ubuntu are provided, but not fully working, yet. -Please check the [Releases](https://github.com/DJ2LS/FreeDATA/releases) section for downloading nightly builds +Please check the ['Releases'](https://github.com/DJ2LS/FreeDATA/releases) section for downloading nightly builds ## Preview ![preview](https://github.com/DJ2LS/FreeDATA/blob/main/documentation/FreeDATA_preview.gif?raw=true "Preview") @@ -22,7 +22,7 @@ Please check the [Releases](https://github.com/DJ2LS/FreeDATA/releases) section FreeDV Codec 2 : https://github.com/drowe67/codec2 * xssfox, her repository helped me a lot in an early stage of development - xssfox : https://github.com/xssfox/freedv-tnc -* Wolfgang, for lending me his radio so I'm able to do real hf tests +* Wolfgang, for lending me his radio, so I'm able to do real hf tests ## Running the Ubuntu app bundle Download the latest developer release from the releases section, unpack it and just start the ".AppImage file". No more dependencies diff --git a/test/README.md b/test/README.md index 8e0a1a6c..dc1be690 100644 --- a/test/README.md +++ b/test/README.md @@ -102,7 +102,7 @@ python3 test_tx.py --mode datac1 --delay 500 --frames 2 --bursts 1 | python3 tes ## AUDIO test via virtual audio devices ### Important: -The virtual audio devices are great for testing, but they are also a little bit tricky to handle. So there's a high chance, the tests will fail, if you are running them via virtual audio devices. You should run the tests several times, while keeping this in mind. Most time the ctest is working even if it is failing. +The virtual audio devices are great for testing, but they are also a little tricky to handle. So there's a high chance, the tests will fail, if you are running them via virtual audio devices. You should run the tests several times, while keeping this in mind. Most time the ctest is working even if it is failing. 1. Create virtual audio devices. Note: This command needs to be run again after every reboot ``` diff --git a/test/hamlib-test.py b/test/hamlib-test.py index 289ceead..87ddb6b7 100644 --- a/test/hamlib-test.py +++ b/test/hamlib-test.py @@ -18,6 +18,7 @@ class DEBUGLEVEL(Enum): RIG_DEBUG_TRACE = 5 RIG_DEBUG_CACHE = 6 + class RETCODE(Enum): RIG_OK = 0 RIG_EINVAL = 1 @@ -38,13 +39,9 @@ class RETCODE(Enum): RIG_EVFO = 16 RIG_EDOM = 17 - - - libname = pathlib.Path("../tnc/lib/hamlib/linux/libhamlib.so") hamlib = ctypes.CDLL(libname) - class SERIAL(ctypes.Structure): _fields_ = [ ("data_bits", ctypes.c_int), @@ -53,17 +50,20 @@ class SERIAL(ctypes.Structure): ("parity", ctypes.c_int), ("handshake", ctypes.c_void_p), ] - + + class PARM(ctypes.Structure): _fields_ = [ ("serial", SERIAL), ] - + + class TYPE(ctypes.Structure): _fields_ = [ ("rig", ctypes.c_void_p), ] - + + class MYPORT(ctypes.Structure): _fields_ = [ ("pathname", ctypes.c_char), @@ -74,16 +74,14 @@ class MYPORT(ctypes.Structure): ] -hamlib.rig_set_debug(9) #6 -myrig_model = 3085 #3085 = ICOM 6 = DUMMY +hamlib.rig_set_debug(9) # 6 +myrig_model = 3085 # 3085 = ICOM 6 = DUMMY myport = MYPORT() myport.parm.serial.data_bits = 7 myport.parm.serial.stop_bits = 2 myport.parm.serial.rate = 9600 - - rig = hamlib.rig_init(myrig_model) retcode = hamlib.rig_set_parm(rig, 'stop_bits', 5) @@ -111,15 +109,11 @@ print(retcode) ''' retcode = hamlib.rig_open(rig) print(retcode) - - hamlib.rig_close(rig) ''' - - -#riginfo = create_string_buffer(1024) -#retcode = hamlib.rig_get_rig_info(rig, riginfo, 1024); +# riginfo = create_string_buffer(1024) +# retcode = hamlib.rig_get_rig_info(rig, riginfo, 1024); ''' char riginfo[1024]; diff --git a/test/ping.py b/test/ping.py index f63b5b7d..00672f11 100644 --- a/test/ping.py +++ b/test/ping.py @@ -188,7 +188,7 @@ for i in range(N_BURSTS): ) # use this if CRC16 checksum is required ( DATA1-3) buffer[ : len(data_out) - ] = data_out # set buffersize to length of data which will be send + ] = data_out # set buffer size to length of data which will be sent crc = ctypes.c_ushort( c_lib.freedv_gen_crc16(bytes(buffer), payload_per_frame) diff --git a/test/pong.py b/test/pong.py index c9cb4860..39c56490 100644 --- a/test/pong.py +++ b/test/pong.py @@ -17,7 +17,7 @@ import threading import sys import argparse -#--------------------------------------------GET PARAMETER INPUTS +# --------------------------------------------GET PARAMETER INPUTS parser = argparse.ArgumentParser(description='Simons TEST TNC') parser.add_argument('--bursts', dest="N_BURSTS", default=0, type=int) parser.add_argument('--frames', dest="N_FRAMES_PER_BURST", default=0, type=int) @@ -44,23 +44,23 @@ DEBUGGING_MODE = args.DEBUGGING_MODE AUDIO_FRAMES_PER_BUFFER = 2048 MODEM_SAMPLE_RATE = 8000 - #-------------------------------------------- LOAD FREEDV +# -------------------------------------------- LOAD FREEDV libname = pathlib.Path().absolute() / "codec2/build_linux/src/libcodec2.so" c_lib = ctypes.CDLL(libname) - #--------------------------------------------CREATE PYAUDIO INSTANCE +# --------------------------------------------CREATE PYAUDIO INSTANCE p = pyaudio.PyAudio() - #--------------------------------------------GET SUPPORTED SAMPLE RATES FROM SOUND DEVICE +# --------------------------------------------GET SUPPORTED SAMPLE RATES FROM SOUND DEVICE -#AUDIO_SAMPLE_RATE_TX = int(p.get_device_info_by_index(AUDIO_OUTPUT_DEVICE)['defaultSampleRate']) -#AUDIO_SAMPLE_RATE_RX = int(p.get_device_info_by_index(AUDIO_INPUT_DEVICE)['defaultSampleRate']) +# AUDIO_SAMPLE_RATE_TX = int(p.get_device_info_by_index(AUDIO_OUTPUT_DEVICE)['defaultSampleRate']) +# AUDIO_SAMPLE_RATE_RX = int(p.get_device_info_by_index(AUDIO_INPUT_DEVICE)['defaultSampleRate']) AUDIO_SAMPLE_RATE_TX = 8000 AUDIO_SAMPLE_RATE_RX = 8000 - #--------------------------------------------OPEN AUDIO CHANNEL RX +# --------------------------------------------OPEN AUDIO CHANNEL RX stream_tx = p.open(format=pyaudio.paInt16, channels=1, rate=AUDIO_SAMPLE_RATE_TX, - frames_per_buffer=AUDIO_FRAMES_PER_BUFFER, #n_nom_modem_samples + frames_per_buffer=AUDIO_FRAMES_PER_BUFFER, # n_nom_modem_samples output=True, output_device_index=AUDIO_OUTPUT_DEVICE, ) @@ -74,7 +74,7 @@ stream_rx = p.open(format=pyaudio.paInt16, ) - # GENERAL PARAMETERS +# GENERAL PARAMETERS c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte) @@ -93,26 +93,26 @@ def send_pong(burst,n_total_burst,frame,n_total_frame): bytes_per_frame = int(c_lib.freedv_get_bits_per_modem_frame(freedv)/8) payload_per_frame = bytes_per_frame -2 n_nom_modem_samples = c_lib.freedv_get_n_nom_modem_samples(freedv) - n_tx_modem_samples = c_lib.freedv_get_n_tx_modem_samples(freedv) #get n_tx_modem_samples which defines the size of the modulation object # --> *2 + n_tx_modem_samples = c_lib.freedv_get_n_tx_modem_samples(freedv) # get n_tx_modem_samples which defines the size of the modulation object # --> *2 mod_out = ctypes.c_short * n_tx_modem_samples mod_out = mod_out() - mod_out_preamble = ctypes.c_short * (1760*2) #1760 for mode 10,11,12 #4000 for mode 9 + mod_out_preamble = ctypes.c_short * (1760*2) # 1760 for mode 10,11,12 #4000 for mode 9 mod_out_preamble = mod_out_preamble() - buffer = bytearray(payload_per_frame) # use this if CRC16 checksum is required ( DATA1-3) - buffer[:len(data_out)] = data_out # set buffersize to length of data which will be send + buffer = bytearray(payload_per_frame) # use this if CRC16 checksum is required ( DATA1-3) + buffer[:len(data_out)] = data_out # set buffer size to length of data which will be sent crc = ctypes.c_ushort(c_lib.freedv_gen_crc16(bytes(buffer), payload_per_frame)) # generate CRC16 - crc = crc.value.to_bytes(2, byteorder='big') # convert crc to 2 byte hex string - buffer += crc # append crc16 to buffer + crc = crc.value.to_bytes(2, byteorder='big') # convert crc to 2 byte hex string + buffer += crc # append crc16 to buffer c_lib.freedv_rawdatapreambletx(freedv, mod_out_preamble); txbuffer = bytearray() txbuffer += bytes(mod_out_preamble) data = (ctypes.c_ubyte * bytes_per_frame).from_buffer_copy(buffer) - c_lib.freedv_rawdatatx(freedv,mod_out,data) # modulate DATA and safe it into mod_out pointer + c_lib.freedv_rawdatatx(freedv,mod_out,data) # modulate DATA and safe it into mod_out pointer txbuffer += bytes(mod_out) stream_tx.write(bytes(txbuffer)) @@ -126,30 +126,28 @@ def send_pong(burst,n_total_burst,frame,n_total_frame): freedv = c_lib.freedv_open(FREEDV_RX_MODE) bytes_per_frame = int(c_lib.freedv_get_bits_per_modem_frame(freedv)/8) n_max_modem_samples = c_lib.freedv_get_n_max_modem_samples(freedv) -bytes_out = (ctypes.c_ubyte * bytes_per_frame) #bytes_per_frame -bytes_out = bytes_out() #get pointer from bytes_out - - +bytes_out = (ctypes.c_ubyte * bytes_per_frame) # bytes_per_frame +bytes_out = bytes_out() # get pointer from bytes_out receive = True -while receive == True: +while receive: time.sleep(0.01) data_in = b'' nin = c_lib.freedv_nin(freedv) nin_converted = int(nin*(AUDIO_SAMPLE_RATE_RX/MODEM_SAMPLE_RATE)) - if DEBUGGING_MODE == True: + if DEBUGGING_MODE: print("-----------------------------") print("NIN: " + str(nin) + " [ " + str(nin_converted) + " ]") data_in = stream_rx.read(nin_converted, exception_on_overflow = False) data_in = data_in.rstrip(b'\x00') - c_lib.freedv_rawdatarx.argtype = [ctypes.POINTER(ctypes.c_ubyte), bytes_out, data_in] # check if really neccessary - nbytes = c_lib.freedv_rawdatarx(freedv, bytes_out, data_in) # demodulate audio + c_lib.freedv_rawdatarx.argtype = [ctypes.POINTER(ctypes.c_ubyte), bytes_out, data_in] # check if really neccessary + nbytes = c_lib.freedv_rawdatarx(freedv, bytes_out, data_in) # demodulate audio - if DEBUGGING_MODE == True: + if DEBUGGING_MODE: print("SYNC: " + str(c_lib.freedv_get_rx_status(freedv))) if nbytes == bytes_per_frame: diff --git a/test/test_arq_short.py b/test/test_arq_short.py index 78305a32..f5a4be1b 100644 --- a/test/test_arq_short.py +++ b/test/test_arq_short.py @@ -61,6 +61,7 @@ def test_highsnr_arq_short(freedv_mode: str, n_frames_per_burst: int): # This test isn't complete yet, or is obsolete. assert False + if __name__ == "__main__": # Run pytest with the current script as the filename. ecode = pytest.main(["-v", sys.argv[0]]) diff --git a/test/test_audiobuffer.py b/test/test_audiobuffer.py index 94003105..fd005458 100644 --- a/test/test_audiobuffer.py +++ b/test/test_audiobuffer.py @@ -14,7 +14,7 @@ import numpy as np import pytest BUFFER_SZ = 1024 -N_MAX = 100 # write a repeating sequence of 0..N_MAX-1 +N_MAX = 100 # write a repeating sequence of 0....N_MAX-1 WRITE_SZ = 10 # different read and write sized buffers READ_SZ = 8 NTESTS = 10000 diff --git a/test/test_callback_multimode_rx.py b/test/test_callback_multimode_rx.py index 12c671f5..f031071f 100644 --- a/test/test_callback_multimode_rx.py +++ b/test/test_callback_multimode_rx.py @@ -72,7 +72,7 @@ class Test: self.AUDIO_SAMPLE_RATE_RX / self.MODEM_SAMPLE_RATE ) == codec2.api.FDMDV_OS_48 - # check if we want to use an audio device then do an pyaudio init + # check if we want to use an audio device then do a pyaudio init if self.AUDIO_INPUT_DEVICE != -1: self.p = pyaudio.PyAudio() # auto search for loopback devices diff --git a/test/test_callback_multimode_rx_outside.py b/test/test_callback_multimode_rx_outside.py index cd704a81..8f1900ff 100644 --- a/test/test_callback_multimode_rx_outside.py +++ b/test/test_callback_multimode_rx_outside.py @@ -71,7 +71,7 @@ class Test: self.AUDIO_SAMPLE_RATE_RX / self.MODEM_SAMPLE_RATE ) == codec2.api.FDMDV_OS_48 - # check if we want to use an audio device then do an pyaudio init + # check if we want to use an audio device then do a pyaudio init if self.AUDIO_INPUT_DEVICE != -1: self.p = pyaudio.PyAudio() # auto search for loopback devices diff --git a/test/test_callback_multimode_tx.py b/test/test_callback_multimode_tx.py index bc80bd21..1f254175 100644 --- a/test/test_callback_multimode_tx.py +++ b/test/test_callback_multimode_tx.py @@ -77,7 +77,7 @@ class Test: self.resampler = codec2.resampler() - # check if we want to use an audio device then do an pyaudio init + # check if we want to use an audio device then do a pyaudio init if self.AUDIO_OUTPUT_DEVICE != -1: self.p = pyaudio.PyAudio() # auto search for loopback devices @@ -189,7 +189,7 @@ class Test: payload_per_frame = bytes_per_frame - 2 buffer = bytearray(payload_per_frame) - # set buffersize to length of data which will be send + # set buffer size to length of data which will be sent buffer[: len(self.data_out)] = self.data_out crc = ctypes.c_ushort( diff --git a/test/test_callback_rx.py b/test/test_callback_rx.py index ffbb6c02..11af818f 100644 --- a/test/test_callback_rx.py +++ b/test/test_callback_rx.py @@ -76,7 +76,7 @@ class Test: self.AUDIO_SAMPLE_RATE_RX / self.MODEM_SAMPLE_RATE ) == codec2.api.FDMDV_OS_48 - # check if we want to use an audio device then do an pyaudio init + # check if we want to use an audio device then do a pyaudio init if self.AUDIO_INPUT_DEVICE != -1: self.p = pyaudio.PyAudio() # auto search for loopback devices diff --git a/test/test_callback_rx_outside.py b/test/test_callback_rx_outside.py index a006c740..82f75cb4 100644 --- a/test/test_callback_rx_outside.py +++ b/test/test_callback_rx_outside.py @@ -76,7 +76,7 @@ class Test: self.AUDIO_SAMPLE_RATE_RX / self.MODEM_SAMPLE_RATE ) == codec2.api.FDMDV_OS_48 - # check if we want to use an audio device then do an pyaudio init + # check if we want to use an audio device then do a pyaudio init if self.AUDIO_INPUT_DEVICE != -1: self.p = pyaudio.PyAudio() # auto search for loopback devices diff --git a/test/test_callback_tx.py b/test/test_callback_tx.py index f30d7bdf..bf63db31 100644 --- a/test/test_callback_tx.py +++ b/test/test_callback_tx.py @@ -82,7 +82,7 @@ class Test: self.resampler = codec2.resampler() - # check if we want to use an audio device then do an pyaudio init + # check if we want to use an audio device then do a pyaudio init if self.AUDIO_OUTPUT_DEVICE != -1: self.p = pyaudio.PyAudio() # auto search for loopback devices @@ -196,7 +196,7 @@ class Test: ) # use this if CRC16 checksum is required ( DATA1-3) buffer[ : len(self.data_out) - ] = self.data_out # set buffersize to length of data which will be send + ] = self.data_out # set buffer size to length of data which will be sent # create crc for data frame - we are using the crc function shipped with codec2 to avoid # crc algorithm incompatibilities diff --git a/test/test_multimode_rx.py b/test/test_multimode_rx.py index 3b58b306..807d2155 100755 --- a/test/test_multimode_rx.py +++ b/test/test_multimode_rx.py @@ -67,7 +67,7 @@ def test_mm_rx(): resampler = codec2.resampler() - # check if we want to use an audio device then do an pyaudio init + # check if we want to use an audio device then do a pyaudio init if AUDIO_INPUT_DEVICE != -1: p_audio = pyaudio.PyAudio() # auto search for loopback devices diff --git a/test/test_multimode_tx.py b/test/test_multimode_tx.py index dd4ef8b1..9335e795 100644 --- a/test/test_multimode_tx.py +++ b/test/test_multimode_tx.py @@ -93,7 +93,7 @@ def test_mm_tx(): payload_per_frame = bytes_per_frame - 2 buffer = bytearray(payload_per_frame) - # Set buffersize to length of data which will be send + # Set buffer size to length of data which will be sent buffer[: len(data_out)] = data_out # Generate CRC16 diff --git a/test/test_rx.py b/test/test_rx.py index 36057ab3..ddbf20ec 100644 --- a/test/test_rx.py +++ b/test/test_rx.py @@ -47,7 +47,7 @@ def test_rx(): # make sure our resampler will work assert (AUDIO_SAMPLE_RATE_RX / MODEM_SAMPLE_RATE) == codec2.api.FDMDV_OS_48 - # check if we want to use an audio device then do an pyaudio init + # check if we want to use an audio device then do a pyaudio init if AUDIO_INPUT_DEVICE != -1: # auto search for loopback devices if AUDIO_INPUT_DEVICE == -2: diff --git a/test/test_tnc_states.py b/test/test_tnc_states.py index b9384be0..4904f1df 100644 --- a/test/test_tnc_states.py +++ b/test/test_tnc_states.py @@ -107,7 +107,7 @@ def test_valid_disconnect(mycall: str, dxcall: str): # Set the SSIDs we'll use for this test. static.SSID_LIST = [0, 1, 2, 3, 4] - # Setup the static parameters for the connection. + # set up the static parameters for the connection. mycallsign_bytes = helpers.callsign_to_bytes(mycall) mycallsign = helpers.bytes_to_callsign(mycallsign_bytes) static.MYCALLSIGN = mycallsign @@ -160,7 +160,7 @@ def test_foreign_disconnect(mycall: str, dxcall: str): :return: Bytearray of the requested frame :rtype: bytearray """ - # Setup the static parameters for the connection. + # set up the static parameters for the connection. mycallsign_bytes = helpers.callsign_to_bytes(mycall) mycallsign = helpers.bytes_to_callsign(mycallsign_bytes) static.MYCALLSIGN = mycallsign diff --git a/test/test_tx.py b/test/test_tx.py index 2855a927..2187dab1 100644 --- a/test/test_tx.py +++ b/test/test_tx.py @@ -37,7 +37,7 @@ def test_tx(): AUDIO_SAMPLE_RATE_TX = 48000 assert (AUDIO_SAMPLE_RATE_TX % MODEM_SAMPLE_RATE) == 0 - # check if we want to use an audio device then do an pyaudio init + # check if we want to use an audio device then do a pyaudio init if AUDIO_OUTPUT_DEVICE != -1: # auto search for loopback devices if AUDIO_OUTPUT_DEVICE == -2: @@ -109,7 +109,7 @@ def test_tx(): # Create buffer for data # Use this if CRC16 checksum is required (DATA1-3) buffer = bytearray(payload_bytes_per_frame) - # set buffersize to length of data which will be send + # set buffer size to length of data which will be sent buffer[: len(data_out)] = data_out # Create CRC for data frame - we are using the CRC function shipped with codec2 to avoid diff --git a/tnc/codec2.py b/tnc/codec2.py index ad1be938..96468f01 100644 --- a/tnc/codec2.py +++ b/tnc/codec2.py @@ -265,7 +265,7 @@ api.rx_sync_flags_to_text = [ # Audio buffer --------------------------------------------------------- class audio_buffer: """ - Thread safe audio buffer, which fits to needs of codec2 + Thread safe audio buffer, which fits to need of codec2 made by David Rowe, VK5DGR """ diff --git a/tnc/daemon.py b/tnc/daemon.py index 2c6e05ec..e3b625a9 100755 --- a/tnc/daemon.py +++ b/tnc/daemon.py @@ -89,7 +89,6 @@ class DAEMON: """ while 1: try: - #print("update serial") serial_devices = [] ports = serial.tools.list_ports.comports() for port, desc, hwid in ports: @@ -213,7 +212,6 @@ class DAEMON: options.append('--tuning_range_fmax') options.append(data[20]) - # overriding FSK mode # if data[21] == 'True': # options.append('--fsk') diff --git a/tnc/data_handler.py b/tnc/data_handler.py index 56a109c4..668f685f 100644 --- a/tnc/data_handler.py +++ b/tnc/data_handler.py @@ -53,7 +53,6 @@ class DATA: self.received_mycall_crc = b'' # Received my callsign crc if we received a crc for another ssid - self.data_channel_last_received = 0.0 # time of last "live sign" of a frame self.burst_ack_snr = 0 # SNR from received ack frames self.burst_ack = False # if we received an acknowledge frame for a burst @@ -76,7 +75,6 @@ class DATA: self.mode_list_low_bw = [14, 12] self.time_list_low_bw = [3, 7] - self.mode_list_high_bw = [14, 12, 10] # mode list of available modes,each mode will be used 2 times per level self.time_list_high_bw = [3, 7, 8, 30] # list for time to wait for corresponding mode in seconds @@ -103,7 +101,6 @@ class DATA: self.transmission_timeout = 360 # transmission timeout in seconds - worker_thread_transmit = threading.Thread(target=self.worker_transmit, name="worker thread transmit", daemon=True) worker_thread_transmit.start() @@ -815,7 +812,6 @@ class DATA: # once we received a burst ack, reset its state and break the RETRIES loop if self.burst_ack: - self.burst_ack = False # reset ack state self.tx_n_retry_of_burst = 0 # reset retries break # break retry loop diff --git a/tnc/main.py b/tnc/main.py index f7ceb795..d9d707c8 100755 --- a/tnc/main.py +++ b/tnc/main.py @@ -48,7 +48,7 @@ if __name__ == '__main__': # --------------------------------------------GET PARAMETER INPUTS PARSER = argparse.ArgumentParser(description='FreeDATA TNC') PARSER.add_argument('--mycall', dest="mycall", default="AA0AA", help="My callsign", type=str) - PARSER.add_argument('--ssid', dest="ssid_list", nargs='*', default=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ,11 ,12 ,13 ,14 ,15 ], help="SSID list we are responding to", type=str) + PARSER.add_argument('--ssid', dest="ssid_list", nargs='*', default=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], help="SSID list we are responding to", type=str) PARSER.add_argument('--mygrid', dest="mygrid", default="JN12AA", help="My gridsquare", type=str) PARSER.add_argument('--rx', dest="audio_input_device", default=0, help="listening sound card", type=int) PARSER.add_argument('--tx', dest="audio_output_device", default=0, help="transmitting sound card", type=int) @@ -127,7 +127,7 @@ if __name__ == '__main__': os.makedirs(logging_path) log_handler.setup_logging(logging_path) except Exception as e: - structlog.get_logger("structlog").error("[DMN] logger init error", exception=e) + structlog.get_logger("structlog").error("[DMN] logger init error", exception=e) structlog.get_logger("structlog").info("[TNC] Starting FreeDATA", author="DJ2LS", year="2022", version=static.VERSION) diff --git a/tnc/rig.py b/tnc/rig.py index c0e01cb8..3350f2d9 100644 --- a/tnc/rig.py +++ b/tnc/rig.py @@ -31,7 +31,7 @@ try: # installation path for Suse sys.path.append(f'/usr/local/lib64/python{python_version}/site-packages') - # everything else... not nice, but an attempt to see how its running within app bundle + # everything else... not nice, but an attempt to see how it's running within app bundle # this is not needed as python will be shipped with app bundle sys.path.append('/usr/local/lib/python3.6/site-packages') sys.path.append('/usr/local/lib/python3.7/site-packages') @@ -106,7 +106,7 @@ class radio: """ self.devicename = devicename self.deviceport = str(deviceport) - self.serialspeed = str(serialspeed) # we need to ensure this is a str, otherwise set_conf functions are crashing + self.serialspeed = str(serialspeed) # we need to ensure this is a str, otherwise set_conf functions are crashing self.hamlib_ptt_type = str(hamlib_ptt_type) self.pttport = str(pttport) self.data_bits = str(data_bits) diff --git a/tnc/rigctl.py b/tnc/rigctl.py index 3e9a5e6c..f275ff81 100644 --- a/tnc/rigctl.py +++ b/tnc/rigctl.py @@ -105,7 +105,7 @@ class radio: sw_proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True) time.sleep(0.5) freq = sw_proc.communicate()[0] - #print('get_frequency', freq, sw_proc.communicate()) + # print('get_frequency', freq, sw_proc.communicate()) try: return int(freq) except Exception: @@ -113,8 +113,8 @@ class radio: def get_mode(self): """ """ - #(hamlib_mode, bandwith) = self.my_rig.get_mode() - #return Hamlib.rig_strrmode(hamlib_mode) + # (hamlib_mode, bandwith) = self.my_rig.get_mode() + # return Hamlib.rig_strrmode(hamlib_mode) try: return 'PKTUSB' except Exception: @@ -122,7 +122,7 @@ class radio: def get_bandwith(self): """ """ - #(hamlib_mode, bandwith) = self.my_rig.get_mode() + # (hamlib_mode, bandwith) = self.my_rig.get_mode() bandwith = 2700 try: diff --git a/tnc/rigctld.py b/tnc/rigctld.py index 67b16f3a..ef388acb 100644 --- a/tnc/rigctld.py +++ b/tnc/rigctld.py @@ -152,9 +152,9 @@ class radio(): """ try: if state: - self.send_command(b"T 1") + self.send_command(b"T 1") else: - self.send_command(b"T 0") + self.send_command(b"T 0") return state except Exception: return False diff --git a/tnc/sock.py b/tnc/sock.py index e5ba20fe..e78a7776 100644 --- a/tnc/sock.py +++ b/tnc/sock.py @@ -504,7 +504,6 @@ def process_daemon_commands(data): for item in received_json["parameter"][0]: structlog.get_logger("structlog").debug(f"[DMN] TNC Startup Config : {item}", value=received_json["parameter"][0][item]) - DAEMON_QUEUE.put(['STARTTNC', mycall, mygrid, diff --git a/tools/list_audio_devices.py b/tools/list_audio_devices.py index 5c0db651..8b869b4c 100755 --- a/tools/list_audio_devices.py +++ b/tools/list_audio_devices.py @@ -13,12 +13,5 @@ def list_audio_devices(): for line in devices: print(line) - - - - - - - list_audio_devices() diff --git a/tools/readfromsocket.py b/tools/readfromsocket.py index 9b63a427..df20f6e2 100644 --- a/tools/readfromsocket.py +++ b/tools/readfromsocket.py @@ -11,10 +11,7 @@ import sys import argparse import time - - - -#--------------------------------------------GET PARAMETER INPUTS +# --------------------------------------------GET PARAMETER INPUTS parser = argparse.ArgumentParser(description='Simons TEST TNC') parser.add_argument('--port', dest="socket_port", default=3000, help="Set the port, the socket is listening on.", type=int) parser.add_argument('--data', dest="data", default=False, help="data", type=str) diff --git a/tools/socketclient.py b/tools/socketclient.py index 753b4bea..753ce568 100644 --- a/tools/socketclient.py +++ b/tools/socketclient.py @@ -11,8 +11,10 @@ import sys import argparse import random -#https://www.askpython.com/python/examples/generate-random-strings-in-python + def create_string(length): + # https://www.askpython.com/python/examples/generate-random-strings-in-python + random_string = '' for _ in range(length): # Considering only upper and lowercase letters @@ -25,39 +27,27 @@ def create_string(length): print("STR:" + str(random_string)) return random_string - - - - -#--------------------------------------------GET PARAMETER INPUTS + +# --------------------------------------------GET PARAMETER INPUTS parser = argparse.ArgumentParser(description='Simons TEST TNC') parser.add_argument('--port', dest="socket_port", default=9000, help="Set the port, the socket is listening on.", type=int) -#parser.add_argument('--data', dest="data", default=False, help="data", type=str) +# parser.add_argument('--data', dest="data", default=False, help="data", type=str) parser.add_argument('--random', dest="datalength", default=False, help="data", type=int) - - - args = parser.parse_args() - data = create_string(args.datalength) data = bytes("ARQ:DATA:" + "" + data + "" + "\n", "utf-8") - - -#print(data) - - HOST, PORT = "localhost", args.socket_port -#data = args.data +# data = args.data # Create a socket (SOCK_STREAM means a TCP socket) with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: # Connect to server and send data sock.connect((HOST, PORT)) - #sock.sendall(bytes(data + "\n", "utf-8")) + # sock.sendall(bytes(data + "\n", "utf-8")) sock.sendall(data) # Receive data from the server and shut down received = str(sock.recv(1024), "utf-8") From 08202bbaec25f0944315a8235c73c3e3ab42573d Mon Sep 17 00:00:00 2001 From: Paul Kronenwetter Date: Wed, 25 May 2022 18:27:33 -0400 Subject: [PATCH 5/8] Prefer double- over single-quote. Other minor fixes. --- tnc/audio.py | 19 ++-- tnc/codec2.py | 30 +++--- tnc/daemon.py | 167 ++++++++++++++++---------------- tnc/data_handler.py | 229 ++++++++++++++++++++++---------------------- tnc/helpers.py | 74 +++++++------- tnc/log_handler.py | 17 ++-- tnc/main.py | 83 ++++++++-------- tnc/modem.py | 61 ++++++------ tnc/rig.py | 105 ++++++++++---------- tnc/rigctl.py | 53 +++++----- tnc/rigctld.py | 21 ++-- tnc/rigdummy.py | 1 + tnc/sock.py | 222 +++++++++++++++++++++--------------------- tnc/static.py | 46 ++++----- 14 files changed, 565 insertions(+), 563 deletions(-) diff --git a/tnc/audio.py b/tnc/audio.py index 8bc66894..b7a2accf 100644 --- a/tnc/audio.py +++ b/tnc/audio.py @@ -1,6 +1,9 @@ - +""" +Gather information about audio devices. +""" import atexit import multiprocessing + import sounddevice as sd atexit.register(sd._terminate) @@ -14,7 +17,7 @@ def get_audio_devices(): """ # we need to run this on Windows for multiprocessing support # multiprocessing.freeze_support() - # multiprocessing.get_context('spawn') + # multiprocessing.get_context("spawn") # we need to reset and initialize sounddevice before running the multiprocessing part. # If we are not doing this at this early point, not all devices will be displayed @@ -25,9 +28,9 @@ def get_audio_devices(): proxy_input_devices = manager.list() proxy_output_devices = manager.list() # print(multiprocessing.get_start_method()) - p = multiprocessing.Process(target=fetch_audio_devices, args=(proxy_input_devices, proxy_output_devices)) - p.start() - p.join() + proc = multiprocessing.Process(target=fetch_audio_devices, args=(proxy_input_devices, proxy_output_devices)) + proc.start() + proc.join() return list(proxy_input_devices), list(proxy_output_devices) @@ -52,11 +55,11 @@ def fetch_audio_devices(input_devices, output_devices): max_output_channels = device["max_output_channels"] max_input_channels = device["max_input_channels"] - except Exception as e: - print(e) + except Exception as err: + print(err) max_input_channels = 0 max_output_channels = 0 - name = '' + name = "" if max_input_channels > 0: input_devices.append({"id": index, "name": name}) diff --git a/tnc/codec2.py b/tnc/codec2.py index 96468f01..531deeca 100644 --- a/tnc/codec2.py +++ b/tnc/codec2.py @@ -63,13 +63,13 @@ else: sys.path.append(os.path.abspath(".")) structlog.get_logger("structlog").info("[C2 ] Searching for libcodec2...") -if sys.platform == 'linux': - files = glob.glob(r'**/*libcodec2*', recursive=True) - files.append('libcodec2.so') -elif sys.platform == 'darwin': - files = glob.glob(r'**/*libcodec2*.dylib', recursive=True) -elif sys.platform in ['win32', 'win64']: - files = glob.glob(r'**\*libcodec2*.dll', recursive=True) +if sys.platform == "linux": + files = glob.glob(r"**/*libcodec2*", recursive=True) + files.append("libcodec2.so") +elif sys.platform == "darwin": + files = glob.glob(r"**/*libcodec2*.dylib", recursive=True) +elif sys.platform in ["win32", "win64"]: + files = glob.glob(r"**\*libcodec2*.dll", recursive=True) else: files = [] @@ -79,11 +79,11 @@ for file in files: api = ctypes.CDLL(file) structlog.get_logger("structlog").info("[C2 ] Libcodec2 loaded", path=file) break - except Exception as e: - structlog.get_logger("structlog").warning("[C2 ] Libcodec2 found but not loaded", path=file, e=e) + except Exception as err: + structlog.get_logger("structlog").warning("[C2 ] Libcodec2 found but not loaded", path=file, e=err) # Quit module if codec2 cant be loaded -if api is None or 'api' not in locals(): +if api is None or "api" not in locals(): structlog.get_logger("structlog").critical("[C2 ] Libcodec2 not loaded") sys.exit(1) @@ -163,14 +163,14 @@ class ADVANCED(ctypes.Structure): ] -''' +""" adv.interleave_frames = 0 # max amplitude adv.M = 2 # number of fsk tones 2/4 adv.Rs = 100 # symbol rate adv.Fs = 8000 # sample rate adv.first_tone = 1500 # first tone freq adv.tone_spacing = 200 # shift between tones -adv.codename = 'H_128_256_5'.encode('utf-8') # code word +adv.codename = "H_128_256_5".encode("utf-8") # code word HRA_112_112 rate 0.50 (224,112) BPF: 14 not working HRA_56_56 rate 0.50 (112,56) BPF: 7 not working @@ -183,7 +183,7 @@ H_128_256_5 rate 0.50 (256,128) BPF: 16 working H_4096_8192_3d rate 0.50 (8192,4096) BPF: 512 not working H_16200_9720 rate 0.60 (16200,9720) BPF: 1215 not working H_1024_2048_4f rate 0.50 (2048,1024) BPF: 128 working -''' +""" # --------------- 2 FSK H_128_256_5, 16 bytes api.FREEDV_MODE_FSK_LDPC_0_ADV = ADVANCED() api.FREEDV_MODE_FSK_LDPC_0_ADV.interleave_frames = 0 @@ -192,7 +192,7 @@ api.FREEDV_MODE_FSK_LDPC_0_ADV.Rs = 100 api.FREEDV_MODE_FSK_LDPC_0_ADV.Fs = 8000 api.FREEDV_MODE_FSK_LDPC_0_ADV.first_tone = 1400 # 1150 4fsk, 1500 2fsk api.FREEDV_MODE_FSK_LDPC_0_ADV.tone_spacing = 120 # 200 -api.FREEDV_MODE_FSK_LDPC_0_ADV.codename = 'H_128_256_5'.encode('utf-8') # code word +api.FREEDV_MODE_FSK_LDPC_0_ADV.codename = "H_128_256_5".encode("utf-8") # code word # --------------- 4 H_256_512_4, 7 bytes api.FREEDV_MODE_FSK_LDPC_1_ADV = ADVANCED() @@ -202,7 +202,7 @@ api.FREEDV_MODE_FSK_LDPC_1_ADV.Rs = 100 api.FREEDV_MODE_FSK_LDPC_1_ADV.Fs = 8000 api.FREEDV_MODE_FSK_LDPC_1_ADV.first_tone = 1250 # 1250 4fsk, 1500 2fsk api.FREEDV_MODE_FSK_LDPC_1_ADV.tone_spacing = 200 -api.FREEDV_MODE_FSK_LDPC_1_ADV.codename = 'H_256_512_4'.encode('utf-8') # code word +api.FREEDV_MODE_FSK_LDPC_1_ADV.codename = "H_256_512_4".encode("utf-8") # code word # ------- MODEM STATS STRUCTURES MODEM_STATS_NC_MAX = 50 + 1 diff --git a/tnc/daemon.py b/tnc/daemon.py index e3b625a9..5b751e75 100755 --- a/tnc/daemon.py +++ b/tnc/daemon.py @@ -22,15 +22,14 @@ import sys import threading import time -import crcengine -import serial.tools.list_ports -import structlog -import ujson as json - import audio +import crcengine import log_handler +import serial.tools.list_ports import sock import static +import structlog +import ujson as json # signal handler for closing aplication @@ -43,7 +42,7 @@ def signal_handler(sig, frame): Returns: system exit """ - print('Closing daemon...') + print("Closing daemon...") sock.CLOSE_SIGNAL = True sys.exit(0) @@ -58,7 +57,7 @@ class DAEMON: """ def __init__(self): # load crc engine - self.crc_algorithm = crcengine.new('crc16-ccitt-false') # load crc8 library + self.crc_algorithm = crcengine.new("crc16-ccitt-false") # load crc8 library self.daemon_queue = sock.DAEMON_QUEUE update_audio_devices = threading.Thread(target=self.update_audio_devices, name="UPDATE_AUDIO_DEVICES", daemon=True) @@ -78,8 +77,8 @@ class DAEMON: try: if not static.TNCSTARTED: static.AUDIO_INPUT_DEVICES, static.AUDIO_OUTPUT_DEVICES = audio.get_audio_devices() - except Exception as e: - structlog.get_logger("structlog").error("[DMN] update_audio_devices: Exception gathering audio devices:", e=e) + except Exception as err1: + structlog.get_logger("structlog").error("[DMN] update_audio_devices: Exception gathering audio devices:", e=err1) # print(e) time.sleep(1) @@ -93,16 +92,16 @@ class DAEMON: ports = serial.tools.list_ports.comports() for port, desc, hwid in ports: # calculate hex of hwid if we have unique names - crc_hwid = self.crc_algorithm(bytes(hwid, encoding='utf-8')) - crc_hwid = crc_hwid.to_bytes(2, byteorder='big') + crc_hwid = self.crc_algorithm(bytes(hwid, encoding="utf-8")) + crc_hwid = crc_hwid.to_bytes(2, byteorder="big") crc_hwid = crc_hwid.hex() description = f"{desc} [{crc_hwid}]" serial_devices.append({"port": str(port), "description": str(description)}) static.SERIAL_DEVICES = serial_devices time.sleep(1) - except Exception as e: - structlog.get_logger("structlog").error("[DMN] update_serial_devices: Exception gathering serial devices:", e=e) + except Exception as err1: + structlog.get_logger("structlog").error("[DMN] update_serial_devices: Exception gathering serial devices:", e=err1) # print(e) def worker(self): @@ -137,99 +136,99 @@ class DAEMON: # data[22] tx-audio-level # data[23] respond_to_cq - if data[0] == 'STARTTNC': + if data[0] == "STARTTNC": structlog.get_logger("structlog").warning("[DMN] Starting TNC", rig=data[5], port=data[6]) # list of parameters, necessary for running subprocess command as a list options = [] - options.append('--port') + options.append("--port") options.append(str(static.DAEMONPORT - 1)) - options.append('--mycall') + options.append("--mycall") options.append(data[1]) - options.append('--mygrid') + options.append("--mygrid") options.append(data[2]) - options.append('--rx') + options.append("--rx") options.append(data[3]) - options.append('--tx') + options.append("--tx") options.append(data[4]) # if radiocontrol != disabled # this should hopefully avoid a ton of problems if we are just running in # disabled mode - if data[13] != 'disabled': - options.append('--devicename') + if data[13] != "disabled": + options.append("--devicename") options.append(data[5]) - options.append('--deviceport') + options.append("--deviceport") options.append(data[6]) - options.append('--serialspeed') + options.append("--serialspeed") options.append(data[7]) - options.append('--pttprotocol') + options.append("--pttprotocol") options.append(data[8]) - options.append('--pttport') + options.append("--pttport") options.append(data[9]) - options.append('--data_bits') + options.append("--data_bits") options.append(data[10]) - options.append('--stop_bits') + options.append("--stop_bits") options.append(data[11]) - options.append('--handshake') + options.append("--handshake") options.append(data[12]) - options.append('--radiocontrol') + options.append("--radiocontrol") options.append(data[13]) - if data[13] == 'rigctld': - options.append('--rigctld_ip') + if data[13] == "rigctld": + options.append("--rigctld_ip") options.append(data[14]) - options.append('--rigctld_port') + options.append("--rigctld_port") options.append(data[15]) - if data[16] == 'True': - options.append('--scatter') + if data[16] == "True": + options.append("--scatter") - if data[17] == 'True': - options.append('--fft') + if data[17] == "True": + options.append("--fft") - if data[18] == 'True': - options.append('--500hz') + if data[18] == "True": + options.append("--500hz") - options.append('--tuning_range_fmin') + options.append("--tuning_range_fmin") options.append(data[19]) - options.append('--tuning_range_fmax') + options.append("--tuning_range_fmax") options.append(data[20]) # overriding FSK mode - # if data[21] == 'True': - # options.append('--fsk') + # if data[21] == "True": + # options.append("--fsk") - options.append('--tx-audio-level') + options.append("--tx-audio-level") options.append(data[22]) - if data[23] == 'True': - options.append('--qrv') + if data[23] == "True": + options.append("--qrv") # Try running tnc from binary, else run from source # This helps running the tnc in a developer environment try: command = [] - if sys.platform in ['linux', 'darwin']: - command.append('./freedata-tnc') - elif sys.platform in ['win32', 'win64']: - command.append('freedata-tnc.exe') + if sys.platform in ["linux", "darwin"]: + command.append("./freedata-tnc") + elif sys.platform in ["win32", "win64"]: + command.append("freedata-tnc.exe") command += options p = subprocess.Popen(command) @@ -237,15 +236,15 @@ class DAEMON: atexit.register(p.kill) structlog.get_logger("structlog").info("[DMN] TNC started", path="binary") - except FileNotFoundError as e: - structlog.get_logger("structlog").error("[DMN] worker: Exception:", e=e) + except FileNotFoundError as err1: + structlog.get_logger("structlog").error("[DMN] worker: Exception:", e=err1) command = [] - if sys.platform in ['linux', 'darwin']: - command.append('python3') - elif sys.platform in ['win32', 'win64']: - command.append('python') + if sys.platform in ["linux", "darwin"]: + command.append("python3") + elif sys.platform in ["win32", "win64"]: + command.append("python") - command.append('main.py') + command.append("main.py") command += options p = subprocess.Popen(command) atexit.register(p.kill) @@ -254,14 +253,14 @@ class DAEMON: static.TNCPROCESS = p # .pid static.TNCSTARTED = True - ''' + """ # WE HAVE THIS PART in SOCKET - if data[0] == 'STOPTNC': + if data[0] == "STOPTNC": static.TNCPROCESS.kill() structlog.get_logger("structlog").warning("[DMN] Stopping TNC") #os.kill(static.TNCPROCESS, signal.SIGKILL) static.TNCSTARTED = False - ''' + """ # data[1] devicename # data[2] deviceport # data[3] serialspeed @@ -273,7 +272,7 @@ class DAEMON: # data[9] radiocontrol # data[10] rigctld_ip # data[11] rigctld_port - if data[0] == 'TEST_HAMLIB': + if data[0] == "TEST_HAMLIB": devicename = data[1] deviceport = data[2] serialspeed = data[3] @@ -287,11 +286,11 @@ class DAEMON: rigctld_port = data[11] # check how we want to control the radio - if radiocontrol == 'direct': + if radiocontrol == "direct": import rig - elif radiocontrol == 'rigctl': + elif radiocontrol == "rigctl": import rigctl as rig - elif radiocontrol == 'rigctld': + elif radiocontrol == "rigctld": import rigctld as rig else: import rigdummy as rig @@ -307,14 +306,14 @@ class DAEMON: pttstate = hamlib.get_ptt() if pttstate: - structlog.get_logger("structlog").info("[DMN] Hamlib PTT", status='SUCCESS') - response = {'command': 'test_hamlib', 'result': 'SUCCESS'} + structlog.get_logger("structlog").info("[DMN] Hamlib PTT", status="SUCCESS") + response = {"command": "test_hamlib", "result": "SUCCESS"} elif not pttstate: - structlog.get_logger("structlog").warning("[DMN] Hamlib PTT", status='NO SUCCESS') - response = {'command': 'test_hamlib', 'result': 'NOSUCCESS'} + structlog.get_logger("structlog").warning("[DMN] Hamlib PTT", status="NO SUCCESS") + response = {"command": "test_hamlib", "result": "NOSUCCESS"} else: - structlog.get_logger("structlog").error("[DMN] Hamlib PTT", status='FAILED') - response = {'command': 'test_hamlib', 'result': 'FAILED'} + structlog.get_logger("structlog").error("[DMN] Hamlib PTT", status="FAILED") + response = {"command": "test_hamlib", "result": "FAILED"} hamlib.set_ptt(False) hamlib.close_rig() @@ -322,36 +321,36 @@ class DAEMON: jsondata = json.dumps(response) sock.SOCKET_QUEUE.put(jsondata) - except Exception as e: - structlog.get_logger("structlog").error("[DMN] worker: Exception: ", e=e) + except Exception as err1: + structlog.get_logger("structlog").error("[DMN] worker: Exception: ", e=err1) -if __name__ == '__main__': +if __name__ == "__main__": # we need to run this on Windows for multiprocessing support multiprocessing.freeze_support() # --------------------------------------------GET PARAMETER INPUTS - PARSER = argparse.ArgumentParser(description='FreeDATA Daemon') - PARSER.add_argument('--port', dest="socket_port", default=3001, help="Socket port in the range of 1024-65536", type=int) + PARSER = argparse.ArgumentParser(description="FreeDATA Daemon") + PARSER.add_argument("--port", dest="socket_port", default=3001, help="Socket port in the range of 1024-65536", type=int) ARGS = PARSER.parse_args() static.DAEMONPORT = ARGS.socket_port try: - if sys.platform == 'linux': - logging_path = os.getenv("HOME") + '/.config/' + 'FreeDATA/' + 'daemon' + if sys.platform == "linux": + logging_path = os.getenv("HOME") + "/.config/" + "FreeDATA/" + "daemon" - if sys.platform == 'darwin': - logging_path = os.getenv("HOME") + '/Library/' + 'Application Support/' + 'FreeDATA/' + 'daemon' + if sys.platform == "darwin": + logging_path = os.getenv("HOME") + "/Library/" + "Application Support/" + "FreeDATA/" + "daemon" - if sys.platform in ['win32', 'win64']: - logging_path = os.getenv('APPDATA') + '/' + 'FreeDATA/' + 'daemon' + if sys.platform in ["win32", "win64"]: + logging_path = os.getenv("APPDATA") + "/" + "FreeDATA/" + "daemon" if not os.path.exists(logging_path): os.makedirs(logging_path) log_handler.setup_logging(logging_path) - except Exception as e: - structlog.get_logger("structlog").error("[DMN] logger init error", exception=e) + except Exception as err: + structlog.get_logger("structlog").error("[DMN] logger init error", exception=err) try: structlog.get_logger("structlog").info("[DMN] Starting TCP/IP socket", port=static.DAEMONPORT) @@ -362,8 +361,8 @@ if __name__ == '__main__': server_thread.daemon = True server_thread.start() - except Exception as e: - structlog.get_logger("structlog").error("[DMN] Starting TCP/IP socket failed", port=static.DAEMONPORT, e=e) + except Exception as err: + structlog.get_logger("structlog").error("[DMN] Starting TCP/IP socket failed", port=static.DAEMONPORT, e=err) sys.exit(1) daemon = DAEMON() diff --git a/tnc/data_handler.py b/tnc/data_handler.py index 668f685f..eb6b8591 100644 --- a/tnc/data_handler.py +++ b/tnc/data_handler.py @@ -17,15 +17,14 @@ import uuid import zlib from random import randrange -import numpy as np -import structlog -import ujson as json - import codec2 import helpers import modem +import numpy as np import sock import static +import structlog +import ujson as json TESTMODE = False @@ -49,9 +48,9 @@ class DATA: self.arq_session_timeout = 30 self.session_connect_max_retries = 3 - self.transmission_uuid = '' + self.transmission_uuid = "" - self.received_mycall_crc = b'' # Received my callsign crc if we received a crc for another ssid + self.received_mycall_crc = b"" # Received my callsign crc if we received a crc for another ssid self.data_channel_last_received = 0.0 # time of last "live sign" of a frame self.burst_ack_snr = 0 # SNR from received ack frames @@ -61,8 +60,8 @@ class DATA: self.rpt_request_buffer = [] # requested frames, saved in a list self.rx_start_of_transmission = 0 # time of transmission start - self.data_frame_bof = b'BOF' # 2 bytes for the BOF End of File indicator in a data frame - self.data_frame_eof = b'EOF' # 2 bytes for the EOF End of File indicator in a data frame + self.data_frame_bof = b"BOF" # 2 bytes for the BOF End of File indicator in a data frame + self.data_frame_eof = b"EOF" # 2 bytes for the EOF End of File indicator in a data frame self.rx_n_max_retries_per_burst = 50 self.n_retries_per_burst = 0 @@ -125,17 +124,17 @@ class DATA: data = self.data_queue_transmit.get() # [0] == Command - if data[0] == 'CQ': + if data[0] == "CQ": self.transmit_cq() - elif data[0] == 'STOP': + elif data[0] == "STOP": self.stop_transmission() - elif data[0] == 'PING': + elif data[0] == "PING": # [1] dxcallsign self.transmit_ping(data[1]) - elif data[0] == 'BEACON': + elif data[0] == "BEACON": # [1] INTERVAL int # [2] STATE bool if data[2]: @@ -144,7 +143,7 @@ class DATA: else: static.BEACON_STATE = False - elif data[0] == 'ARQ_RAW': + elif data[0] == "ARQ_RAW": # [1] DATA_OUT bytes # [2] MODE int # [3] N_FRAMES_PER_BURST int @@ -152,15 +151,15 @@ class DATA: # [5] mycallsign with ssid self.open_dc_and_transmit(data[1], data[2], data[3], data[4], data[5]) - elif data[0] == 'CONNECT': + elif data[0] == "CONNECT": # [1] DX CALLSIGN self.arq_session_handler(data[1]) - elif data[0] == 'DISCONNECT': + elif data[0] == "DISCONNECT": # [1] DX CALLSIGN self.close_session() - elif data[0] == 'SEND_TEST_FRAME': + elif data[0] == "SEND_TEST_FRAME": # [1] DX CALLSIGN self.send_test_frame() else: @@ -442,12 +441,12 @@ class DATA: return # only process data if we are in ARQ and BUSY state else return to quit - if not static.ARQ_STATE and static.TNC_STATE != 'BUSY': + if not static.ARQ_STATE and static.TNC_STATE != "BUSY": return self.arq_file_transfer = True - static.TNC_STATE = 'BUSY' + static.TNC_STATE = "BUSY" static.ARQ_STATE = True static.INFO.append("ARQ;RECEIVING") self.data_channel_last_received = int(time.time()) @@ -467,7 +466,7 @@ class DATA: structlog.get_logger("structlog").debug("[TNC] static.RX_BURST_BUFFER", buffer=static.RX_BURST_BUFFER) - helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, 'DATA-CHANNEL', snr, static.FREQ_OFFSET, + helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "DATA-CHANNEL", snr, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) # Check if we received all frames in the burst by checking if burst buffer has no more "Nones" @@ -475,7 +474,7 @@ class DATA: if None not in static.RX_BURST_BUFFER: # then iterate through burst buffer and stick the burst together # the temp burst buffer is needed for checking, if we already recevied data - temp_burst_buffer = b'' + temp_burst_buffer = b"" for value in static.RX_BURST_BUFFER: # static.RX_FRAME_BUFFER += static.RX_BURST_BUFFER[i] temp_burst_buffer += bytes(value) @@ -612,8 +611,8 @@ class DATA: base64_data = base64.b64encode(data_frame).decode("utf-8") static.RX_BUFFER.append([uniqueid, timestamp, static.DXCALLSIGN, static.DXGRID, base64_data]) jsondata = {"arq": "received", "uuid": uniqueid, "timestamp": timestamp, - "mycallsign": str(mycallsign, 'utf-8'), "dxcallsign": str(static.DXCALLSIGN, 'utf-8'), - "dxgrid": str(static.DXGRID, 'utf-8'), "data": base64_data} + "mycallsign": str(mycallsign, "utf-8"), "dxcallsign": str(static.DXCALLSIGN, "utf-8"), + "dxgrid": str(static.DXGRID, "utf-8"), "data": base64_data} json_data_out = json.dumps(jsondata) structlog.get_logger("structlog").debug("[TNC] arq_data_received:", jsondata=jsondata) sock.SOCKET_QUEUE.put(json_data_out) @@ -626,8 +625,8 @@ class DATA: self.calculate_transfer_rate_rx(self.rx_start_of_transmission, len(static.RX_FRAME_BUFFER)) structlog.get_logger("structlog").info("[TNC] | RX | DATACHANNEL [" + - str(self.mycallsign, 'utf-8') + "]<< >>[" + str( - static.DXCALLSIGN, 'utf-8') + "]", snr=snr) + str(self.mycallsign, "utf-8") + "]<< >>[" + str( + static.DXCALLSIGN, "utf-8") + "]", snr=snr) else: static.INFO.append("ARQ;RECEIVING;FAILED") @@ -677,7 +676,7 @@ class DATA: # save len of data_out to TOTAL_BYTES for our statistics --> kBytes # static.TOTAL_BYTES = round(len(data_out) / 1024, 2) static.TOTAL_BYTES = len(data_out) - frame_total_size = len(data_out).to_bytes(4, byteorder='big') + frame_total_size = len(data_out).to_bytes(4, byteorder="big") static.INFO.append("ARQ;TRANSMITTING") jsondata = {"arq": "transmission", "status": "transmitting", "uuid": self.transmission_uuid, @@ -827,7 +826,7 @@ class DATA: break # break retry loop # we need this part for leaving the repeat loop - # static.ARQ_STATE == 'DATA' --> when stopping transmission manually + # static.ARQ_STATE == "DATA" --> when stopping transmission manually if not static.ARQ_STATE: # print("not ready for data...leaving loop....") break @@ -899,7 +898,7 @@ class DATA: # only process data if we are in ARQ and BUSY state if static.ARQ_STATE: - helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, 'DATA-CHANNEL', static.SNR, + helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "DATA-CHANNEL", static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) self.burst_ack = True # Force data loops of TNC to stop and continue with next frame self.data_channel_last_received = int(time.time()) # we need to update our timeout timestamp @@ -930,7 +929,7 @@ class DATA: # only process data if we are in ARQ and BUSY state if static.ARQ_STATE: - helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, 'DATA-CHANNEL', static.SNR, + helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "DATA-CHANNEL", static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) self.burst_nack = True # Force data loops of TNC to stop and continue with next frame self.data_channel_last_received = int(time.time()) # we need to update our timeout timestamp @@ -945,7 +944,7 @@ class DATA: """ """ # only process data if we are in ARQ and BUSY state if static.ARQ_STATE: - helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, 'DATA-CHANNEL', static.SNR, + helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "DATA-CHANNEL", static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) self.data_frame_ack_received = True # Force data loops of TNC to stop and continue with next frame self.data_channel_last_received = int(time.time()) # we need to update our timeout timestamp @@ -960,7 +959,7 @@ class DATA: Returns: """ - helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, 'DATA-CHANNEL', static.SNR, static.FREQ_OFFSET, + helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "DATA-CHANNEL", static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) static.INFO.append("ARQ;TRANSMITTING;FAILED") jsondata = {"arq": "transmission", "status": "failed", "uuid": self.transmission_uuid, @@ -982,8 +981,8 @@ class DATA: """ # only process data if we are in ARQ and BUSY state - if static.ARQ_STATE and static.TNC_STATE == 'BUSY': - helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, 'DATA-CHANNEL', static.SNR, + if static.ARQ_STATE and static.TNC_STATE == "BUSY": + helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "DATA-CHANNEL", static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) self.rpt_request_received = True @@ -993,7 +992,7 @@ class DATA: missing_area = bytes(data_in[3:12]) # 1:9 for i in range(0, 6, 2): - if not missing_area[i:i + 2].endswith(b'\x00\x00'): + if not missing_area[i:i + 2].endswith(b"\x00\x00"): missing = missing_area[i:i + 2] self.rpt_request_buffer.insert(0, missing) @@ -1012,7 +1011,7 @@ class DATA: # TODO: we need to check this, maybe placing it to class init self.datachannel_timeout = False structlog.get_logger("structlog").info( - "[TNC] SESSION [" + str(self.mycallsign, 'utf-8') + "]>> <<[" + str(static.DXCALLSIGN, 'utf-8') + "]", + "[TNC] SESSION [" + str(self.mycallsign, "utf-8") + "]>> <<[" + str(static.DXCALLSIGN, "utf-8") + "]", state=static.ARQ_SESSION_STATE) self.open_session(callsign) @@ -1020,13 +1019,13 @@ class DATA: # wait until data channel is open while not static.ARQ_SESSION and not self.arq_session_timeout: time.sleep(0.01) - static.ARQ_SESSION_STATE = 'connecting' + static.ARQ_SESSION_STATE = "connecting" - if static.ARQ_SESSION and static.ARQ_SESSION_STATE == 'connected': - # static.ARQ_SESSION_STATE = 'connected' + if static.ARQ_SESSION and static.ARQ_SESSION_STATE == "connected": + # static.ARQ_SESSION_STATE = "connected" return True - static.ARQ_SESSION_STATE = 'failed' + static.ARQ_SESSION_STATE = "failed" return False def open_session(self, callsign): @@ -1039,7 +1038,7 @@ class DATA: """ self.IS_ARQ_SESSION_MASTER = True - static.ARQ_SESSION_STATE = 'connecting' + static.ARQ_SESSION_STATE = "connecting" connection_frame = bytearray(14) connection_frame[:1] = bytes([221]) @@ -1051,8 +1050,8 @@ class DATA: time.sleep(0.01) for attempt in range(1, self.session_connect_max_retries + 1): structlog.get_logger("structlog").info( - "[TNC] SESSION [" + str(self.mycallsign, 'utf-8') + "]>>?<<[" + str(static.DXCALLSIGN, - 'utf-8') + "]", a=attempt, + "[TNC] SESSION [" + str(self.mycallsign, "utf-8") + "]>>?<<[" + str(static.DXCALLSIGN, + "utf-8") + "]", a=attempt, state=static.ARQ_SESSION_STATE) self.enqueue_frame_for_tx(connection_frame) @@ -1083,30 +1082,30 @@ class DATA: """ self.IS_ARQ_SESSION_MASTER = False - static.ARQ_SESSION_STATE = 'connecting' + static.ARQ_SESSION_STATE = "connecting" self.arq_session_last_received = int(time.time()) static.DXCALLSIGN_CRC = bytes(data_in[4:7]) static.DXCALLSIGN = helpers.bytes_to_callsign(bytes(data_in[7:13])) - helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, 'DATA-CHANNEL', static.SNR, static.FREQ_OFFSET, + helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "DATA-CHANNEL", static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) structlog.get_logger("structlog").info( - "[TNC] SESSION [" + str(self.mycallsign, 'utf-8') + "]>>|<<[" + str(static.DXCALLSIGN, 'utf-8') + "]", + "[TNC] SESSION [" + str(self.mycallsign, "utf-8") + "]>>|<<[" + str(static.DXCALLSIGN, "utf-8") + "]", state=static.ARQ_SESSION_STATE) static.ARQ_SESSION = True - static.TNC_STATE = 'BUSY' + static.TNC_STATE = "BUSY" self.transmit_session_heartbeat() def close_session(self): """ Close the ARQ session """ - static.ARQ_SESSION_STATE = 'disconnecting' - helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, 'DATA-CHANNEL', static.SNR, static.FREQ_OFFSET, + static.ARQ_SESSION_STATE = "disconnecting" + helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "DATA-CHANNEL", static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) structlog.get_logger("structlog").info( - "[TNC] SESSION [" + str(self.mycallsign, 'utf-8') + "]<>[" + str(static.DXCALLSIGN, 'utf-8') + "]", + "[TNC] SESSION [" + str(self.mycallsign, "utf-8") + "]<>[" + str(static.DXCALLSIGN, "utf-8") + "]", state=static.ARQ_SESSION_STATE) static.INFO.append("ARQ;SESSION;CLOSE") self.IS_ARQ_SESSION_MASTER = False @@ -1129,11 +1128,11 @@ class DATA: # Close the session if the DXCALLSIGN_CRC matches the station in static. _valid_crc, _ = helpers.check_callsign(static.DXCALLSIGN, bytes(data_in[4:7])) if _valid_crc: - static.ARQ_SESSION_STATE = 'disconnected' - helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, 'DATA-CHANNEL', static.SNR, + static.ARQ_SESSION_STATE = "disconnected" + helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "DATA-CHANNEL", static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) structlog.get_logger("structlog").info( - "[TNC] SESSION [" + str(self.mycallsign, 'utf-8') + "]<>[" + str(static.DXCALLSIGN, 'utf-8') + "]", + "[TNC] SESSION [" + str(self.mycallsign, "utf-8") + "]<>[" + str(static.DXCALLSIGN, "utf-8") + "]", state=static.ARQ_SESSION_STATE) static.INFO.append("ARQ;SESSION;CLOSE") @@ -1144,8 +1143,8 @@ class DATA: def transmit_session_heartbeat(self): """ """ # static.ARQ_SESSION = True - # static.TNC_STATE = 'BUSY' - # static.ARQ_SESSION_STATE = 'connected' + # static.TNC_STATE = "BUSY" + # static.ARQ_SESSION_STATE = "connected" connection_frame = bytearray(14) connection_frame[:1] = bytes([222]) @@ -1167,14 +1166,14 @@ class DATA: _valid_crc, _ = helpers.check_callsign(static.DXCALLSIGN, bytes(data_in[4:7])) if _valid_crc: structlog.get_logger("structlog").debug("[TNC] Received session heartbeat") - helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, 'SESSION-HB', static.SNR, + helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "SESSION-HB", static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) self.arq_session_last_received = int(time.time()) # we need to update our timeout timestamp static.ARQ_SESSION = True - static.ARQ_SESSION_STATE = 'connected' - static.TNC_STATE = 'BUSY' + static.ARQ_SESSION_STATE = "connected" + static.TNC_STATE = "BUSY" self.data_channel_last_received = int(time.time()) if not self.IS_ARQ_SESSION_MASTER and not self.arq_file_transfer: self.transmit_session_heartbeat() @@ -1197,7 +1196,7 @@ class DATA: # overwrite mycallsign in case of different SSID self.mycallsign = mycallsign - static.TNC_STATE = 'BUSY' + static.TNC_STATE = "BUSY" self.arq_file_transfer = True self.transmission_uuid = transmission_uuid @@ -1261,8 +1260,8 @@ class DATA: for attempt in range(1, self.data_channel_max_retries + 1): static.INFO.append("DATACHANNEL;OPENING") structlog.get_logger("structlog").info( - "[TNC] ARQ | DATA | TX | [" + str(mycallsign, 'utf-8') + "]>> <<[" + str(static.DXCALLSIGN, - 'utf-8') + "]", + "[TNC] ARQ | DATA | TX | [" + str(mycallsign, "utf-8") + "]>> <<[" + str(static.DXCALLSIGN, + "utf-8") + "]", attempt=f"{str(attempt)}/{str(self.data_channel_max_retries)}") self.enqueue_frame_for_tx(connection_frame) @@ -1290,8 +1289,8 @@ class DATA: sock.SOCKET_QUEUE.put(json_data_out) structlog.get_logger("structlog").warning( - "[TNC] ARQ | TX | DATA [" + str(mycallsign, 'utf-8') + "]>>X<<[" + str(static.DXCALLSIGN, - 'utf-8') + "]") + "[TNC] ARQ | TX | DATA [" + str(mycallsign, "utf-8") + "]>>X<<[" + str(static.DXCALLSIGN, + "utf-8") + "]") self.datachannel_timeout = True if not TESTMODE: self.arq_cleanup() @@ -1337,7 +1336,7 @@ class DATA: # updated modes we are listening to self.set_listening_modes(self.mode_list[self.speed_level]) - helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, 'DATA-CHANNEL', static.SNR, static.FREQ_OFFSET, + helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "DATA-CHANNEL", static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) # check if callsign ssid override @@ -1349,11 +1348,11 @@ class DATA: return structlog.get_logger("structlog").info( - "[TNC] ARQ | DATA | RX | [" + str(mycallsign, 'utf-8') + "]>> <<[" + str(static.DXCALLSIGN, 'utf-8') + "]", + "[TNC] ARQ | DATA | RX | [" + str(mycallsign, "utf-8") + "]>> <<[" + str(static.DXCALLSIGN, "utf-8") + "]", bandwith="wide") static.ARQ_STATE = True - static.TNC_STATE = 'BUSY' + static.TNC_STATE = "BUSY" self.reset_statistics() @@ -1375,7 +1374,7 @@ class DATA: self.enqueue_frame_for_tx(connection_frame) structlog.get_logger("structlog").info( - "[TNC] ARQ | DATA | RX | [" + str(mycallsign, 'utf-8') + "]>>|<<[" + str(static.DXCALLSIGN, 'utf-8') + "]", + "[TNC] ARQ | DATA | RX | [" + str(mycallsign, "utf-8") + "]>>|<<[" + str(static.DXCALLSIGN, "utf-8") + "]", bandwith="wide", snr=static.SNR) # set start of transmission for our statistics @@ -1411,19 +1410,19 @@ class DATA: self.speed_level = len(self.mode_list) - 1 structlog.get_logger("structlog").debug("[TNC] high bandwidth mode", modes=self.mode_list) - helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, 'DATA-CHANNEL', static.SNR, + helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "DATA-CHANNEL", static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) structlog.get_logger("structlog").info( - "[TNC] ARQ | DATA | TX | [" + str(self.mycallsign, 'utf-8') + "]>>|<<[" + str(static.DXCALLSIGN, - 'utf-8') + "]", + "[TNC] ARQ | DATA | TX | [" + str(self.mycallsign, "utf-8") + "]>>|<<[" + str(static.DXCALLSIGN, + "utf-8") + "]", snr=static.SNR) # as soon as we set ARQ_STATE to DATA, transmission starts static.ARQ_STATE = True self.data_channel_last_received = int(time.time()) else: - static.TNC_STATE = 'IDLE' + static.TNC_STATE = "IDLE" static.ARQ_STATE = False static.INFO.append("PROTOCOL;VERSION_MISMATCH") structlog.get_logger("structlog").warning("[TNC] protocol version mismatch:", received=protocol_version, @@ -1445,7 +1444,7 @@ class DATA: static.INFO.append("PING;SENDING") structlog.get_logger("structlog").info( - "[TNC] PING REQ [" + str(self.mycallsign, 'utf-8') + "] >>> [" + str(static.DXCALLSIGN, 'utf-8') + "]") + "[TNC] PING REQ [" + str(self.mycallsign, "utf-8") + "] >>> [" + str(static.DXCALLSIGN, "utf-8") + "]") ping_frame = bytearray(14) ping_frame[:1] = bytes([210]) @@ -1455,7 +1454,7 @@ class DATA: structlog.get_logger("structlog").info("[TNC] ENABLE FSK", state=static.ENABLE_FSK) if static.ENABLE_FSK: - self.enqueue_frame_for_tx(ping_frame, c2_mode='FSK_LDPC_0') + self.enqueue_frame_for_tx(ping_frame, c2_mode=codec2.freedv_get_mode_value_by_name("FSK_LDPC_0")) else: self.enqueue_frame_for_tx(ping_frame) @@ -1471,7 +1470,7 @@ class DATA: """ static.DXCALLSIGN_CRC = bytes(data_in[4:7]) static.DXCALLSIGN = helpers.bytes_to_callsign(bytes(data_in[7:13])) - helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, 'PING', static.SNR, static.FREQ_OFFSET, + helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "PING", static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) static.INFO.append("PING;RECEIVING") @@ -1485,7 +1484,7 @@ class DATA: return structlog.get_logger("structlog").info( - "[TNC] PING REQ [" + str(mycallsign, 'utf-8') + "] <<< [" + str(static.DXCALLSIGN, 'utf-8') + "]", + "[TNC] PING REQ [" + str(mycallsign, "utf-8") + "] <<< [" + str(static.DXCALLSIGN, "utf-8") + "]", snr=static.SNR) ping_frame = bytearray(14) @@ -1496,7 +1495,7 @@ class DATA: structlog.get_logger("structlog").info("[TNC] ENABLE FSK", state=static.ENABLE_FSK) if static.ENABLE_FSK: - self.enqueue_frame_for_tx(ping_frame, c2_mode='FSK_LDPC_0') + self.enqueue_frame_for_tx(ping_frame, c2_mode=codec2.freedv_get_mode_value_by_name("FSK_LDPC_0")) else: self.enqueue_frame_for_tx(ping_frame) @@ -1510,23 +1509,23 @@ class DATA: """ static.DXCALLSIGN_CRC = bytes(data_in[4:7]) - static.DXGRID = bytes(data_in[7:13]).rstrip(b'\x00') + static.DXGRID = bytes(data_in[7:13]).rstrip(b"\x00") jsondata = {"type": "ping", "status": "ack", "uuid": str(uuid.uuid4()), "timestamp": int(time.time()), - "mycallsign": str(self.mycallsign, 'utf-8'), "dxcallsign": str(static.DXCALLSIGN, 'utf-8'), - "dxgrid": str(static.DXGRID, 'utf-8'), "snr": str(static.SNR)} + "mycallsign": str(self.mycallsign, "utf-8"), "dxcallsign": str(static.DXCALLSIGN, "utf-8"), + "dxgrid": str(static.DXGRID, "utf-8"), "snr": str(static.SNR)} json_data_out = json.dumps(jsondata) sock.SOCKET_QUEUE.put(json_data_out) - helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, 'PING-ACK', static.SNR, static.FREQ_OFFSET, + helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "PING-ACK", static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) static.INFO.append("PING;RECEIVEDACK") structlog.get_logger("structlog").info( - "[TNC] PING ACK [" + str(self.mycallsign, 'utf-8') + "] >|< [" + str(static.DXCALLSIGN, 'utf-8') + "]", + "[TNC] PING ACK [" + str(self.mycallsign, "utf-8") + "] >|< [" + str(static.DXCALLSIGN, "utf-8") + "]", snr=static.SNR) - static.TNC_STATE = 'IDLE' + static.TNC_STATE = "IDLE" def stop_transmission(self): """ @@ -1541,7 +1540,7 @@ class DATA: self.enqueue_frame_for_tx(stop_frame, copies=2, repeat_delay=250) - static.TNC_STATE = 'IDLE' + static.TNC_STATE = "IDLE" static.ARQ_STATE = False static.INFO.append("TRANSMISSION;STOPPED") self.arq_cleanup() @@ -1551,7 +1550,7 @@ class DATA: Received a transmission stop """ structlog.get_logger("structlog").warning("[TNC] Stopping transmission!") - static.TNC_STATE = 'IDLE' + static.TNC_STATE = "IDLE" static.ARQ_STATE = False static.INFO.append("TRANSMISSION;STOPPED") self.arq_cleanup() @@ -1582,7 +1581,7 @@ class DATA: structlog.get_logger("structlog").info("[TNC] ENABLE FSK", state=static.ENABLE_FSK) if static.ENABLE_FSK: - self.enqueue_frame_for_tx(beacon_frame, c2_mode='FSK_LDPC_0') + self.enqueue_frame_for_tx(beacon_frame, c2_mode=codec2.freedv_get_mode_value_by_name("FSK_LDPC_0")) else: self.enqueue_frame_for_tx(beacon_frame) @@ -1590,8 +1589,8 @@ class DATA: while time.time() < interval_timer and static.BEACON_STATE and not static.BEACON_PAUSE: time.sleep(0.01) - except Exception as e: - structlog.get_logger("structlog").debug("[TNC] run_beacon: ", exception=e) + except Exception as err: + structlog.get_logger("structlog").debug("[TNC] run_beacon: ", exception=err) # print(e) def received_beacon(self, data_in: bytes): @@ -1605,18 +1604,18 @@ class DATA: """ # here we add the received station to the heard stations buffer dxcallsign = helpers.bytes_to_callsign(bytes(data_in[1:7])) - dxgrid = bytes(data_in[9:13]).rstrip(b'\x00') + dxgrid = bytes(data_in[9:13]).rstrip(b"\x00") jsondata = {"type": "beacon", "status": "received", "uuid": str(uuid.uuid4()), "timestamp": int(time.time()), - "mycallsign": str(self.mycallsign, 'utf-8'), "dxcallsign": str(dxcallsign, 'utf-8'), - "dxgrid": str(dxgrid, 'utf-8'), "snr": str(static.SNR)} + "mycallsign": str(self.mycallsign, "utf-8"), "dxcallsign": str(dxcallsign, "utf-8"), + "dxgrid": str(dxgrid, "utf-8"), "snr": str(static.SNR)} json_data_out = json.dumps(jsondata) sock.SOCKET_QUEUE.put(json_data_out) static.INFO.append("BEACON;RECEIVING") structlog.get_logger("structlog").info( - "[TNC] BEACON RCVD [" + str(dxcallsign, 'utf-8') + "][" + str(dxgrid, 'utf-8') + "] ", snr=static.SNR) - helpers.add_to_heard_stations(dxcallsign, dxgrid, 'BEACON', static.SNR, static.FREQ_OFFSET, + "[TNC] BEACON RCVD [" + str(dxcallsign, "utf-8") + "][" + str(dxgrid, "utf-8") + "] ", snr=static.SNR) + helpers.add_to_heard_stations(dxcallsign, dxgrid, "BEACON", static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) def transmit_cq(self): @@ -1640,7 +1639,7 @@ class DATA: structlog.get_logger("structlog").debug("[TNC] CQ Frame:", data=[cq_frame]) if static.ENABLE_FSK: - self.enqueue_frame_for_tx(cq_frame, c2_mode='FSK_LDPC_0') + self.enqueue_frame_for_tx(cq_frame, c2_mode=codec2.freedv_get_mode_value_by_name("FSK_LDPC_0")) else: self.enqueue_frame_for_tx(cq_frame) @@ -1660,8 +1659,8 @@ class DATA: dxgrid = bytes(helpers.decode_grid(data_in[7:11]), "utf-8") static.INFO.append("CQ;RECEIVING") structlog.get_logger("structlog").info( - "[TNC] CQ RCVD [" + str(dxcallsign, 'utf-8') + "][" + str(dxgrid, 'utf-8') + "] ", snr=static.SNR) - helpers.add_to_heard_stations(dxcallsign, dxgrid, 'CQ CQ CQ', static.SNR, static.FREQ_OFFSET, + "[TNC] CQ RCVD [" + str(dxcallsign, "utf-8") + "][" + str(dxgrid, "utf-8") + "] ", snr=static.SNR) + helpers.add_to_heard_stations(dxcallsign, dxgrid, "CQ CQ CQ", static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) if static.RESPOND_TO_CQ: @@ -1692,7 +1691,7 @@ class DATA: structlog.get_logger("structlog").info("[TNC] ENABLE FSK", state=static.ENABLE_FSK) if static.ENABLE_FSK: - self.enqueue_frame_for_tx(qrv_frame, c2_mode='FSK_LDPC_0') + self.enqueue_frame_for_tx(qrv_frame, c2_mode=codec2.freedv_get_mode_value_by_name("FSK_LDPC_0")) else: self.enqueue_frame_for_tx(qrv_frame) @@ -1710,15 +1709,15 @@ class DATA: dxgrid = bytes(helpers.decode_grid(data_in[7:11]), "utf-8") jsondata = {"type": "qrv", "status": "received", "uuid": str(uuid.uuid4()), "timestamp": int(time.time()), - "mycallsign": str(self.mycallsign, 'utf-8'), "dxcallsign": str(dxcallsign, 'utf-8'), - "dxgrid": str(dxgrid, 'utf-8'), "snr": str(static.SNR)} + "mycallsign": str(self.mycallsign, "utf-8"), "dxcallsign": str(dxcallsign, "utf-8"), + "dxgrid": str(dxgrid, "utf-8"), "snr": str(static.SNR)} json_data_out = json.dumps(jsondata) sock.SOCKET_QUEUE.put(json_data_out) static.INFO.append("QRV;RECEIVING") structlog.get_logger("structlog").info( - "[TNC] QRV RCVD [" + str(dxcallsign, 'utf-8') + "][" + str(dxgrid, 'utf-8') + "] ", snr=static.SNR) - helpers.add_to_heard_stations(dxcallsign, dxgrid, 'QRV', static.SNR, static.FREQ_OFFSET, + "[TNC] QRV RCVD [" + str(dxcallsign, "utf-8") + "][" + str(dxgrid, "utf-8") + "] ", snr=static.SNR) + helpers.add_to_heard_stations(dxcallsign, dxgrid, "QRV", static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) # ------------ CALUCLATE TRANSFER RATES @@ -1749,8 +1748,8 @@ class DATA: else: static.ARQ_BITS_PER_SECOND = 0 static.ARQ_BYTES_PER_MINUTE = 0 - except Exception as e: - structlog.get_logger("structlog").error(f"[TNC] calculate_transfer_rate_rx: Exception: {e}") + except Exception as err: + structlog.get_logger("structlog").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 @@ -1796,8 +1795,8 @@ class DATA: static.ARQ_BITS_PER_SECOND = 0 static.ARQ_BYTES_PER_MINUTE = 0 - except Exception as e: - structlog.get_logger("structlog").error(f"[TNC] calculate_transfer_rate_tx: Exception: {e}") + except Exception as err: + structlog.get_logger("structlog").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 @@ -1813,7 +1812,7 @@ class DATA: """ structlog.get_logger("structlog").debug("[TNC] arq_cleanup") - self.received_mycall_crc = b'' + self.received_mycall_crc = b"" self.rx_frame_bof_received = False self.rx_frame_eof_received = False @@ -1821,7 +1820,7 @@ class DATA: self.rpt_request_received = False self.data_frame_ack_received = False static.RX_BURST_BUFFER = [] - static.RX_FRAME_BUFFER = b'' + static.RX_FRAME_BUFFER = b"" self.burst_ack_snr = 255 # reset modem receiving state to reduce cpu load @@ -1847,7 +1846,7 @@ class DATA: self.n_retries_per_burst = 0 if not static.ARQ_SESSION: - static.TNC_STATE = 'IDLE' + static.TNC_STATE = "IDLE" static.ARQ_STATE = False self.arq_file_transfer = False @@ -1880,16 +1879,16 @@ class DATA: # set modes we want to listen to mode_name = codec2.freedv_get_mode_name_by_value(mode) - if mode_name == 'datac1': + if mode_name == "datac1": modem.RECEIVE_DATAC1 = True structlog.get_logger("structlog").debug("[TNC] Changing listening data mode", mode="datac1") - elif mode_name == 'datac3': + elif mode_name == "datac3": modem.RECEIVE_DATAC3 = True structlog.get_logger("structlog").debug("[TNC] Changing listening data mode", mode="datac3") - elif mode_name == 'fsk_ldpc_1': + elif mode_name == "fsk_ldpc_1": modem.RECEIVE_FSK_LDPC_1 = True structlog.get_logger("structlog").debug("[TNC] Changing listening data mode", mode="fsk_ldpc_1") - elif mode_name == 'allmodes': + elif mode_name == "allmodes": modem.RECEIVE_DATAC1 = True modem.RECEIVE_DATAC3 = True modem.RECEIVE_FSK_LDPC_1 = True @@ -1920,7 +1919,7 @@ class DATA: # IRS SIDE # TODO: We need to redesign this part for cleaner state handling # return only 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' or not self.is_IRS: + if not static.ARQ_STATE and static.ARQ_SESSION_STATE != "connected" or not self.is_IRS: return # we want to reach this state only if connected ( == return above not called ) if self.data_channel_last_received + self.time_list[self.speed_level] > time.time(): @@ -1960,7 +1959,7 @@ class DATA: DATA CHANNEL """ # and not static.ARQ_SEND_KEEP_ALIVE: - if static.ARQ_STATE and static.TNC_STATE == 'BUSY': + if static.ARQ_STATE and static.TNC_STATE == "BUSY": time.sleep(0.01) if self.data_channel_last_received + self.transmission_timeout > time.time(): time.sleep(0.01) @@ -1969,7 +1968,7 @@ class DATA: else: self.data_channel_last_received = 0 structlog.get_logger("structlog").info( - "[TNC] DATA [" + str(self.mycallsign, 'utf-8') + "]<>[" + str(static.DXCALLSIGN, 'utf-8') + "]") + "[TNC] DATA [" + str(self.mycallsign, "utf-8") + "]<>[" + str(static.DXCALLSIGN, "utf-8") + "]") static.INFO.append("ARQ;RECEIVING;FAILED") if not TESTMODE: self.arq_cleanup() @@ -1979,13 +1978,13 @@ class DATA: watchdog which checks if we are running into a connection timeout ARQ SESSION """ - if static.ARQ_SESSION and static.TNC_STATE == 'BUSY' and not self.arq_file_transfer: + if static.ARQ_SESSION and static.TNC_STATE == "BUSY" and not self.arq_file_transfer: if self.arq_session_last_received + self.arq_session_timeout > time.time(): time.sleep(0.01) else: structlog.get_logger("structlog").info( - "[TNC] SESSION [" + str(self.mycallsign, 'utf-8') + "]<>[" + str(static.DXCALLSIGN, - 'utf-8') + "]") + "[TNC] SESSION [" + str(self.mycallsign, "utf-8") + "]<>[" + str(static.DXCALLSIGN, + "utf-8") + "]") static.INFO.append("ARQ;SESSION;TIMEOUT") self.close_session() diff --git a/tnc/helpers.py b/tnc/helpers.py index c29ab467..81338418 100644 --- a/tnc/helpers.py +++ b/tnc/helpers.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Created on Fri Dec 25 21:25:14 2020 @@ -8,9 +7,8 @@ Created on Fri Dec 25 21:25:14 2020 import time import crcengine -import structlog - import static +import structlog def wait(seconds: float) -> bool: @@ -41,9 +39,9 @@ def get_crc_8(data) -> bytes: Returns: CRC-8 (CCITT) of the provided data as bytes """ - crc_algorithm = crcengine.new('crc8-ccitt') # load crc8 library + crc_algorithm = crcengine.new("crc8-ccitt") # load crc8 library crc_data = crc_algorithm(data) - crc_data = crc_data.to_bytes(1, byteorder='big') + crc_data = crc_data.to_bytes(1, byteorder="big") return crc_data @@ -60,9 +58,9 @@ def get_crc_16(data) -> bytes: Returns: CRC-16 (CCITT) of the provided data as bytes """ - crc_algorithm = crcengine.new('crc16-ccitt-false') # load crc16 library + crc_algorithm = crcengine.new("crc16-ccitt-false") # load crc16 library crc_data = crc_algorithm(data) - crc_data = crc_data.to_bytes(2, byteorder='big') + crc_data = crc_data.to_bytes(2, byteorder="big") return crc_data @@ -86,9 +84,9 @@ def get_crc_24(data) -> bytes: ref_in=False, ref_out=False, xor_out=0, - name='crc-24-openpgp') + name="crc-24-openpgp") crc_data = crc_algorithm(data) - crc_data = crc_data.to_bytes(3, byteorder='big') + crc_data = crc_data.to_bytes(3, byteorder="big") return crc_data @@ -105,9 +103,9 @@ def get_crc_32(data: bytes) -> bytes: Returns: CRC-32 of the provided data as bytes """ - crc_algorithm = crcengine.new('crc32') # load crc32 library + crc_algorithm = crcengine.new("crc32") # load crc32 library crc_data = crc_algorithm(data) - crc_data = crc_data.to_bytes(4, byteorder='big') + crc_data = crc_data.to_bytes(4, byteorder="big") return crc_data @@ -176,17 +174,17 @@ def callsign_to_bytes(callsign) -> bytes: # Try converting to bytestring if possible type string try: - callsign = bytes(callsign, 'utf-8') - except TypeError as e: - structlog.get_logger("structlog").debug("[HLP] callsign_to_bytes: Exception converting callsign to bytes:", e=e) + callsign = bytes(callsign, "utf-8") + except TypeError as err: + structlog.get_logger("structlog").debug("[HLP] callsign_to_bytes: Exception converting callsign to bytes:", e=err) # Need this step to reduce the needed payload by the callsign (stripping "-" out of the callsign) - callsign = callsign.split(b'-') + callsign = callsign.split(b"-") ssid = 0 try: ssid = int(callsign[1]) - except IndexError as e: - structlog.get_logger("structlog").debug("[HLP] callsign_to_bytes: Error callsign SSID to integer:", e=e) + except IndexError as err: + structlog.get_logger("structlog").debug("[HLP] callsign_to_bytes: Error callsign SSID to integer:", e=err) # callsign = callsign[0] # bytestring = bytearray(8) @@ -229,18 +227,18 @@ def bytes_to_callsign(bytestring: bytes) -> bytes: # -15 generic additional station, digi, mobile, wx, etc # we need to do this step to reduce the needed paypload by the callsign ( stripping "-" out of the callsign ) - ''' + """ callsign = bytes(bytestring[:7]) - callsign = callsign.rstrip(b'\x00') + callsign = callsign.rstrip(b"\x00") ssid = int.from_bytes(bytes(bytestring[7:8]), "big") - callsign = callsign + b'-' - callsign = callsign.decode('utf-8') + callsign = callsign + b"-" + callsign = callsign.decode("utf-8") callsign = callsign + str(ssid) - callsign = callsign.encode('utf-8') + callsign = callsign.encode("utf-8") return bytes(callsign) - ''' + """ decoded = decode_call(bytestring) callsign = decoded[:-1] ssid = ord(bytes(decoded[-1], "utf-8")) @@ -260,19 +258,18 @@ def check_callsign(callsign: bytes, crc_to_check: bytes): False """ - # print(callsign) structlog.get_logger("structlog").debug("[HLP] check_callsign: Checking:", callsign=callsign) try: # We want the callsign without SSID - callsign = callsign.split(b'-')[0] + callsign = callsign.split(b"-")[0] - except Exception as e: - structlog.get_logger("structlog").debug("[HLP] check_callsign: Error callsign SSIG to integer:", e=e) + except Exception as err: + structlog.get_logger("structlog").debug("[HLP] check_callsign: Error callsign SSIG to integer:", e=err) for ssid in static.SSID_LIST: call_with_ssid = bytearray(callsign) - call_with_ssid.extend('-'.encode('utf-8')) - call_with_ssid.extend(str(ssid).encode('utf-8')) + call_with_ssid.extend("-".encode("utf-8")) + call_with_ssid.extend(str(ssid).encode("utf-8")) callsign_crc = get_crc_24(call_with_ssid) @@ -295,8 +292,8 @@ def encode_grid(grid): grid = grid.upper() # upper case to be save - int_first = ord(grid[0]) - 65 # -65 offset for 'A' become zero, utf8 table - int_sec = ord(grid[1]) - 65 # -65 offset for 'A' become zero, utf8 table + int_first = ord(grid[0]) - 65 # -65 offset for "A" become zero, utf8 table + int_sec = ord(grid[1]) - 65 # -65 offset for "A" become zero, utf8 table int_val = (int_first * 18) + int_sec # encode for modulo devision, 2 numbers in 1 @@ -307,14 +304,14 @@ def encode_grid(grid): out_code_word |= (int_val & 0b1111111) # using bit OR to add new value out_code_word <<= 7 # shift 7 bit left having space next bits, letter A-X - int_val = ord(grid[4]) - 65 # -65 offset for 'A' become zero, utf8 table + int_val = ord(grid[4]) - 65 # -65 offset for "A" become zero, utf8 table out_code_word |= (int_val & 0b11111) # using bit OR to add new value out_code_word <<= 5 # shift 5 bit left having space next bits, letter A-X - int_val = ord(grid[5]) - 65 # -65 offset for 'A' become zero, utf8 table + int_val = ord(grid[5]) - 65 # -65 offset for "A" become zero, utf8 table out_code_word |= (int_val & 0b11111) # using bit OR to add new value - return out_code_word.to_bytes(length=4, byteorder='big') + return out_code_word.to_bytes(length=4, byteorder="big") def decode_grid(b_code_word: bytes): @@ -325,7 +322,7 @@ def decode_grid(b_code_word: bytes): Returns: grid:str: upper case maidenhead QTH locater [A-R][A-R][0-9][0-9][A-X][A-X] """ - code_word = int.from_bytes(b_code_word, byteorder='big', signed=False) + code_word = int.from_bytes(b_code_word, byteorder="big", signed=False) grid = chr((code_word & 0b11111) + 65) code_word >>= 5 @@ -335,7 +332,7 @@ def decode_grid(b_code_word: bytes): grid = str(int(code_word & 0b1111111)) + grid if (code_word & 0b1111111) < 10: - grid = f'0{grid}' + grid = f"0{grid}" code_word >>= 9 int_val = int(code_word & 0b111111111) @@ -364,11 +361,12 @@ def encode_call(call): int_val = ord(x) - 48 # -48 reduce bits, begin with first number utf8 table out_code_word <<= 6 # shift left 6 bit, making space for a new char out_code_word |= (int_val & 0b111111) # bit OR adds the new char, masked with AND 0b111111 + out_code_word >>= 6 # clean last char out_code_word <<= 6 # make clean space out_code_word |= (ord(call[-1]) & 0b111111) # add the SSID uncoded only 0 - 63 - return out_code_word.to_bytes(length=6, byteorder='big') + return out_code_word.to_bytes(length=6, byteorder="big") def decode_call(b_code_word: bytes): @@ -380,7 +378,7 @@ def decode_call(b_code_word: bytes): Returns: call:str: upper case ham radio call sign [A-Z,0-9] + binary SSID """ - code_word = int.from_bytes(b_code_word, byteorder='big', signed=False) + code_word = int.from_bytes(b_code_word, byteorder="big", signed=False) ssid = chr(code_word & 0b111111) # save the uncoded binary SSID call = str() diff --git a/tnc/log_handler.py b/tnc/log_handler.py index 6d489cca..bda36caf 100644 --- a/tnc/log_handler.py +++ b/tnc/log_handler.py @@ -1,3 +1,8 @@ +import logging.config + +import structlog + + # https://www.structlog.org/en/stable/standard-library.html def setup_logging(filename): """ @@ -8,8 +13,6 @@ def setup_logging(filename): Returns: """ - import logging.config - import structlog timestamper = structlog.processors.TimeStamper(fmt="%Y-%m-%d %H:%M:%S") pre_chain = [ @@ -19,7 +22,8 @@ def setup_logging(filename): timestamper, ] - logging.config.dictConfig({ + logging.config.dictConfig( + { "version": 1, "disable_existing_loggers": False, "formatters": { @@ -43,7 +47,7 @@ def setup_logging(filename): "file": { "level": "DEBUG", "class": "logging.handlers.WatchedFileHandler", - "filename": filename + '.log', + "filename": f"{filename}.log", "formatter": "plain", }, }, @@ -53,8 +57,9 @@ def setup_logging(filename): "level": "DEBUG", "propagate": True, }, - } - }) + }, + } + ) structlog.configure( processors=[ structlog.stdlib.add_log_level, diff --git a/tnc/main.py b/tnc/main.py index d9d707c8..3f076fdf 100755 --- a/tnc/main.py +++ b/tnc/main.py @@ -16,13 +16,12 @@ import sys import threading import time -import structlog - import data_handler import helpers import log_handler import modem import static +import structlog def signal_handler(sig, frame): @@ -35,57 +34,57 @@ def signal_handler(sig, frame): Returns: system exit """ - print('Closing TNC...') + print("Closing TNC...") sock.CLOSE_SIGNAL = True sys.exit(0) signal.signal(signal.SIGINT, signal_handler) -if __name__ == '__main__': +if __name__ == "__main__": # we need to run this on Windows for multiprocessing support multiprocessing.freeze_support() # --------------------------------------------GET PARAMETER INPUTS - PARSER = argparse.ArgumentParser(description='FreeDATA TNC') - PARSER.add_argument('--mycall', dest="mycall", default="AA0AA", help="My callsign", type=str) - PARSER.add_argument('--ssid', dest="ssid_list", nargs='*', default=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], help="SSID list we are responding to", type=str) - PARSER.add_argument('--mygrid', dest="mygrid", default="JN12AA", help="My gridsquare", type=str) - PARSER.add_argument('--rx', dest="audio_input_device", default=0, help="listening sound card", type=int) - PARSER.add_argument('--tx', dest="audio_output_device", default=0, help="transmitting sound card", type=int) - PARSER.add_argument('--port', dest="socket_port", default=3000, help="Socket port in the range of 1024-65536", type=int) - PARSER.add_argument('--deviceport', dest="hamlib_device_port", default="/dev/ttyUSB0", help="Hamlib device port", type=str) - PARSER.add_argument('--devicename', dest="hamlib_device_name", default="2028", help="Hamlib device name", type=str) - PARSER.add_argument('--serialspeed', dest="hamlib_serialspeed", choices=[1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200], default=9600, help="Serialspeed", type=int) - PARSER.add_argument('--pttprotocol', dest="hamlib_ptt_type", choices=['USB', 'RIG', 'RTS', 'DTR', 'CM108', 'MICDATA', 'PARALLEL', 'DTR-H', 'DTR-L', 'NONE'], default='USB', help="PTT Type", type=str) - PARSER.add_argument('--pttport', dest="hamlib_ptt_port", default="/dev/ttyUSB0", help="PTT Port", type=str) - PARSER.add_argument('--data_bits', dest="hamlib_data_bits", choices=[7, 8], default=8, help="Hamlib data bits", type=int) - PARSER.add_argument('--stop_bits', dest="hamlib_stop_bits", choices=[1, 2], default=1, help="Hamlib stop bits", type=int) - PARSER.add_argument('--handshake', dest="hamlib_handshake", default="None", help="Hamlib handshake", type=str) - PARSER.add_argument('--radiocontrol', dest="hamlib_radiocontrol", choices=['disabled', 'direct', 'rigctl', 'rigctld'], default="disabled", help="Set how you want to control your radio") - PARSER.add_argument('--rigctld_port', dest="rigctld_port", default=4532, type=int, help="Set rigctld port") - PARSER.add_argument('--rigctld_ip', dest="rigctld_ip", default="localhost", help="Set rigctld ip") - PARSER.add_argument('--scatter', dest="send_scatter", action="store_true", help="Send scatter information via network") - PARSER.add_argument('--fft', dest="send_fft", action="store_true", help="Send fft information via network") - PARSER.add_argument('--500hz', dest="low_bandwith_mode", action="store_true", help="Enable low bandwith mode ( 500 Hz only )") - PARSER.add_argument('--fsk', dest="enable_fsk", action="store_true", help="Enable FSK mode for ping, beacon and CQ") - PARSER.add_argument('--qrv', dest="enable_respond_to_cq", action="store_true", help="Enable sending a QRV frame if CQ received") - PARSER.add_argument('--tuning_range_fmin', dest="tuning_range_fmin", choices=[-50.0, -100.0, -150.0, -200.0, -250.0], default=-50.0, help="Tuning range fmin", type=float) - PARSER.add_argument('--tuning_range_fmax', dest="tuning_range_fmax", choices=[50.0, 100.0, 150.0, 200.0, 250.0], default=50.0, help="Tuning range fmax", type=float) - PARSER.add_argument('--tx-audio-level', dest="tx_audio_level", default=50, help="Set the tx audio level at an early stage", type=int) + PARSER = argparse.ArgumentParser(description="FreeDATA TNC") + PARSER.add_argument("--mycall", dest="mycall", default="AA0AA", help="My callsign", type=str) + PARSER.add_argument("--ssid", dest="ssid_list", nargs="*", default=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], help="SSID list we are responding to", type=str) + PARSER.add_argument("--mygrid", dest="mygrid", default="JN12AA", help="My gridsquare", type=str) + PARSER.add_argument("--rx", dest="audio_input_device", default=0, help="listening sound card", type=int) + PARSER.add_argument("--tx", dest="audio_output_device", default=0, help="transmitting sound card", type=int) + PARSER.add_argument("--port", dest="socket_port", default=3000, help="Socket port in the range of 1024-65536", type=int) + PARSER.add_argument("--deviceport", dest="hamlib_device_port", default="/dev/ttyUSB0", help="Hamlib device port", type=str) + PARSER.add_argument("--devicename", dest="hamlib_device_name", default="2028", help="Hamlib device name", type=str) + PARSER.add_argument("--serialspeed", dest="hamlib_serialspeed", choices=[1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200], default=9600, help="Serialspeed", type=int) + PARSER.add_argument("--pttprotocol", dest="hamlib_ptt_type", choices=["USB", "RIG", "RTS", "DTR", "CM108", "MICDATA", "PARALLEL", "DTR-H", "DTR-L", "NONE"], default="USB", help="PTT Type", type=str) + PARSER.add_argument("--pttport", dest="hamlib_ptt_port", default="/dev/ttyUSB0", help="PTT Port", type=str) + PARSER.add_argument("--data_bits", dest="hamlib_data_bits", choices=[7, 8], default=8, help="Hamlib data bits", type=int) + PARSER.add_argument("--stop_bits", dest="hamlib_stop_bits", choices=[1, 2], default=1, help="Hamlib stop bits", type=int) + PARSER.add_argument("--handshake", dest="hamlib_handshake", default="None", help="Hamlib handshake", type=str) + PARSER.add_argument("--radiocontrol", dest="hamlib_radiocontrol", choices=["disabled", "direct", "rigctl", "rigctld"], default="disabled", help="Set how you want to control your radio") + PARSER.add_argument("--rigctld_port", dest="rigctld_port", default=4532, type=int, help="Set rigctld port") + PARSER.add_argument("--rigctld_ip", dest="rigctld_ip", default="localhost", help="Set rigctld ip") + PARSER.add_argument("--scatter", dest="send_scatter", action="store_true", help="Send scatter information via network") + PARSER.add_argument("--fft", dest="send_fft", action="store_true", help="Send fft information via network") + PARSER.add_argument("--500hz", dest="low_bandwith_mode", action="store_true", help="Enable low bandwith mode ( 500 Hz only )") + PARSER.add_argument("--fsk", dest="enable_fsk", action="store_true", help="Enable FSK mode for ping, beacon and CQ") + PARSER.add_argument("--qrv", dest="enable_respond_to_cq", action="store_true", help="Enable sending a QRV frame if CQ received") + PARSER.add_argument("--tuning_range_fmin", dest="tuning_range_fmin", choices=[-50.0, -100.0, -150.0, -200.0, -250.0], default=-50.0, help="Tuning range fmin", type=float) + PARSER.add_argument("--tuning_range_fmax", dest="tuning_range_fmax", choices=[50.0, 100.0, 150.0, 200.0, 250.0], default=50.0, help="Tuning range fmax", type=float) + PARSER.add_argument("--tx-audio-level", dest="tx_audio_level", default=50, help="Set the tx audio level at an early stage", type=int) ARGS = PARSER.parse_args() # additional step for beeing sure our callsign is correctly # in case we are not getting a station ssid # then we are forcing a station ssid = 0 - mycallsign = bytes(ARGS.mycall.upper(), 'utf-8') + 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 - static.MYGRID = bytes(ARGS.mygrid, 'utf-8') + static.MYGRID = bytes(ARGS.mygrid, "utf-8") static.AUDIO_INPUT_DEVICE = ARGS.audio_input_device static.AUDIO_OUTPUT_DEVICE = ARGS.audio_output_device static.PORT = ARGS.socket_port @@ -114,20 +113,20 @@ if __name__ == '__main__': # config logging try: - if sys.platform == 'linux': - logging_path = os.getenv("HOME") + '/.config/' + 'FreeDATA/' + 'tnc' + if sys.platform == "linux": + logging_path = os.getenv("HOME") + "/.config/" + "FreeDATA/" + "tnc" - if sys.platform == 'darwin': - logging_path = os.getenv("HOME") + '/Library/' + 'Application Support/' + 'FreeDATA/' + 'tnc' + if sys.platform == "darwin": + logging_path = os.getenv("HOME") + "/Library/" + "Application Support/" + "FreeDATA/" + "tnc" - if sys.platform in ['win32', 'win64']: - logging_path = os.getenv('APPDATA') + '/' + 'FreeDATA/' + 'tnc' + if sys.platform in ["win32", "win64"]: + logging_path = os.getenv("APPDATA") + "/" + "FreeDATA/" + "tnc" if not os.path.exists(logging_path): os.makedirs(logging_path) log_handler.setup_logging(logging_path) - except Exception as e: - structlog.get_logger("structlog").error("[DMN] logger init error", exception=e) + except Exception as err: + structlog.get_logger("structlog").error("[DMN] logger init error", exception=err) structlog.get_logger("structlog").info("[TNC] Starting FreeDATA", author="DJ2LS", year="2022", version=static.VERSION) @@ -148,8 +147,8 @@ if __name__ == '__main__': server_thread.daemon = True server_thread.start() - except Exception as e: - structlog.get_logger("structlog").error("[TNC] Starting TCP/IP socket failed", port=static.PORT, e=e) + except Exception as err: + structlog.get_logger("structlog").error("[TNC] Starting TCP/IP socket failed", port=static.PORT, e=err) sys.exit(1) while 1: time.sleep(1) diff --git a/tnc/modem.py b/tnc/modem.py index 5a10c3e6..f3b0bf2d 100644 --- a/tnc/modem.py +++ b/tnc/modem.py @@ -17,20 +17,19 @@ import threading import time from collections import deque -import numpy as np -import sounddevice as sd -import structlog -import ujson as json - # import audio import codec2 import data_handler +import numpy as np import sock +import sounddevice as sd import static +import structlog +import ujson as json TESTMODE = False -RXCHANNEL = '' -TXCHANNEL = '' +RXCHANNEL = "" +TXCHANNEL = "" # Initialize FIFO queue to store received frames MODEM_RECEIVED_QUEUE = queue.Queue() @@ -114,7 +113,7 @@ class RF: self.fsk_ldpc_freedv_0 = ctypes.cast(codec2.api.freedv_open_advanced(codec2.api.FREEDV_MODE_FSK_LDPC, ctypes.byref( - codec2.api.FREEDV_MODE_FSK_LDPC_0_ADV)), + codec2.api.FREEDV_MODE_FSK_LDPC_0_ADV)), ctypes.c_void_p) self.fsk_ldpc_bytes_per_frame_0 = int(codec2.api.freedv_get_bits_per_modem_frame(self.fsk_ldpc_freedv_0) / 8) self.fsk_ldpc_bytes_out_0 = ctypes.create_string_buffer(self.fsk_ldpc_bytes_per_frame_0) @@ -123,7 +122,7 @@ class RF: self.fsk_ldpc_freedv_1 = ctypes.cast(codec2.api.freedv_open_advanced(codec2.api.FREEDV_MODE_FSK_LDPC, ctypes.byref( - codec2.api.FREEDV_MODE_FSK_LDPC_1_ADV)), + codec2.api.FREEDV_MODE_FSK_LDPC_1_ADV)), ctypes.c_void_p) self.fsk_ldpc_bytes_per_frame_1 = int(codec2.api.freedv_get_bits_per_modem_frame(self.fsk_ldpc_freedv_1) / 8) self.fsk_ldpc_bytes_out_1 = ctypes.create_string_buffer(self.fsk_ldpc_bytes_per_frame_1) @@ -139,14 +138,14 @@ class RF: # --------------------------------------------CREATE PYAUDIO INSTANCE if not TESTMODE: try: - self.stream = sd.RawStream(channels=1, dtype='int16', callback=self.callback, + self.stream = sd.RawStream(channels=1, dtype="int16", callback=self.callback, device=(static.AUDIO_INPUT_DEVICE, static.AUDIO_OUTPUT_DEVICE), samplerate=self.AUDIO_SAMPLE_RATE_RX, blocksize=4800) atexit.register(self.stream.stop) structlog.get_logger("structlog").info("[MDM] init: opened audio devices") - except Exception as e: - structlog.get_logger("structlog").error("[MDM] init: can't open audio device. Exit", e=e) + except Exception as err: + structlog.get_logger("structlog").error("[MDM] init: can't open audio device. Exit", e=err) sys.exit(1) try: @@ -154,8 +153,8 @@ class RF: # self.audio_stream.start_stream() self.stream.start() - except Exception as e: - structlog.get_logger("structlog").error("[MDM] init: starting pyaudio callback failed", e=e) + except Exception as err: + structlog.get_logger("structlog").error("[MDM] init: starting pyaudio callback failed", e=err) else: # create a stream object for simulating audio stream @@ -169,8 +168,8 @@ class RF: try: os.mkfifo(RXCHANNEL) os.mkfifo(TXCHANNEL) - except Exception as e: - structlog.get_logger("structlog").error(f"[MDM] init:mkfifo: Exception: {e}") + except Exception as err: + structlog.get_logger("structlog").error(f"[MDM] init:mkfifo: Exception: {err}") mkfifo_write_callback_thread = threading.Thread(target=self.mkfifo_write_callback, name="MKFIFO WRITE CALLBACK THREAD", daemon=True) @@ -182,13 +181,13 @@ class RF: # --------------------------------------------INIT AND OPEN HAMLIB # Check how we want to control the radio - if static.HAMLIB_RADIOCONTROL == 'direct': + if static.HAMLIB_RADIOCONTROL == "direct": import rig - elif static.HAMLIB_RADIOCONTROL == 'rigctl': + elif static.HAMLIB_RADIOCONTROL == "rigctl": import rigctl as rig - elif static.HAMLIB_RADIOCONTROL == 'rigctld': + elif static.HAMLIB_RADIOCONTROL == "rigctld": import rigctld as rig - elif static.HAMLIB_RADIOCONTROL == 'disabled': + elif static.HAMLIB_RADIOCONTROL == "disabled": import rigdummy as rig else: import rigdummy as rig @@ -238,7 +237,7 @@ class RF: time.sleep(0.01) # -----read data_in48k = bytes() - with open(RXCHANNEL, 'rb') as fifo: + with open(RXCHANNEL, "rb") as fifo: for line in fifo: data_in48k += line @@ -269,7 +268,7 @@ class RF: else: data_out48k = self.modoutqueue.popleft() - fifo_write = open(TXCHANNEL, 'wb') + fifo_write = open(TXCHANNEL, "wb") fifo_write.write(data_out48k) fifo_write.flush() @@ -389,7 +388,7 @@ class RF: for _ in range(repeats): # codec2 fsk preamble may be broken - at least it sounds like that so we are disabling it for testing - if self.MODE not in ['FSK_LDPC_0', 'FSK_LDPC_1', 200, 201]: + if self.MODE not in ["FSK_LDPC_0", "FSK_LDPC_1", 200, 201]: # Write preamble to txbuffer codec2.api.freedv_rawdatapreambletx(freedv, mod_out_preamble) txbuffer += bytes(mod_out_preamble) @@ -404,7 +403,7 @@ class RF: # CRC algorithm incompatibilities crc = ctypes.c_ushort( codec2.api.freedv_gen_crc16(bytes(buffer), payload_bytes_per_frame)) # Generate CRC16 - crc = crc.value.to_bytes(2, byteorder='big') # Convert crc to 2 byte hex string + crc = crc.value.to_bytes(2, byteorder="big") # Convert crc to 2 byte hex string buffer += crc # Append crc16 to buffer data = (ctypes.c_ubyte * bytes_per_frame).from_buffer_copy(buffer) @@ -412,7 +411,7 @@ class RF: txbuffer += bytes(mod_out) # codec2 fsk postamble may be broken - at least it sounds like that so we are disabling it for testing - if self.MODE not in ['FSK_LDPC_0', 'FSK_LDPC_1', 200, 201]: + if self.MODE not in ["FSK_LDPC_0", "FSK_LDPC_1", 200, 201]: # Write postamble to txbuffer codec2.api.freedv_rawdatapostambletx(freedv, mod_out_postamble) # Append postamble to txbuffer @@ -646,8 +645,8 @@ class RF: # static.SNR = np.clip(snr, 0, 255) # limit to max value of 255 static.SNR = np.clip(snr, -128, 128) # limit to max value of -128/128 as a possible fix of #188 return static.SNR - except Exception as e: - structlog.get_logger("structlog").error(f"[MDM] calculate_snr: Exception: {e}") + except Exception as err: + structlog.get_logger("structlog").error(f"[MDM] calculate_snr: Exception: {err}") static.SNR = 0 return static.SNR @@ -712,8 +711,8 @@ class RF: dfftlist = dfft.tolist() static.FFT = dfftlist[:320] # 320 --> bandwidth 3000 - except Exception as e: - structlog.get_logger("structlog").error(f"[MDM] calculate_fft: Exception: {e}") + except Exception as err: + structlog.get_logger("structlog").error(f"[MDM] calculate_fft: Exception: {err}") structlog.get_logger("structlog").debug("[MDM] Setting fft=0") # else 0 static.FFT = [0] @@ -734,12 +733,12 @@ class RF: def open_codec2_instance(mode): """ Return a codec2 instance """ - if mode in ['FSK_LDPC_0', 200]: + if mode in ["FSK_LDPC_0", 200]: return ctypes.cast(codec2.api.freedv_open_advanced(codec2.api.FREEDV_MODE_FSK_LDPC, ctypes.byref(codec2.api.FREEDV_MODE_FSK_LDPC_0_ADV)), ctypes.c_void_p) - if mode in ['FSK_LDPC_1', 201]: + if mode in ["FSK_LDPC_1", 201]: return ctypes.cast(codec2.api.freedv_open_advanced(codec2.api.FREEDV_MODE_FSK_LDPC, ctypes.byref(codec2.api.FREEDV_MODE_FSK_LDPC_1_ADV)), ctypes.c_void_p) diff --git a/tnc/rig.py b/tnc/rig.py index 3350f2d9..23e24701 100644 --- a/tnc/rig.py +++ b/tnc/rig.py @@ -1,11 +1,12 @@ #!/usr/bin/env python3 -import sys -import re -import structlog import atexit -import subprocess import os +import re +import subprocess +import sys + +import structlog # set global hamlib version hamlib_version = 0 @@ -23,23 +24,23 @@ try: python_version = f"{str(sys.version_info[0])}.{str(sys.version_info[1])}" # installation path for Ubuntu 20.04 LTS python modules - # sys.path.append('/usr/local/lib/python'+ python_version +'/site-packages') + # sys.path.append("/usr/local/lib/python"+ python_version +"/site-packages") # installation path for Ubuntu 20.10 + - sys.path.append('/usr/local/lib/') + sys.path.append("/usr/local/lib/") # installation path for Suse - sys.path.append(f'/usr/local/lib64/python{python_version}/site-packages') + sys.path.append(f"/usr/local/lib64/python{python_version}/site-packages") # everything else... not nice, but an attempt to see how it's running within app bundle # this is not needed as python will be shipped with app bundle - sys.path.append('/usr/local/lib/python3.6/site-packages') - sys.path.append('/usr/local/lib/python3.7/site-packages') - sys.path.append('/usr/local/lib/python3.8/site-packages') - sys.path.append('/usr/local/lib/python3.9/site-packages') - sys.path.append('/usr/local/lib/python3.10/site-packages') + sys.path.append("/usr/local/lib/python3.6/site-packages") + sys.path.append("/usr/local/lib/python3.7/site-packages") + sys.path.append("/usr/local/lib/python3.8/site-packages") + sys.path.append("/usr/local/lib/python3.9/site-packages") + sys.path.append("/usr/local/lib/python3.10/site-packages") - sys.path.append('lib/hamlib/linux/python3.8/site-packages') + sys.path.append("lib/hamlib/linux/python3.8/site-packages") import Hamlib # https://stackoverflow.com/a/4703409 @@ -51,22 +52,22 @@ try: structlog.get_logger("structlog").info("[RIG] Hamlib found", version=hamlib_version) else: structlog.get_logger("structlog").warning("[RIG] Hamlib outdated", found=hamlib_version, recommend=min_hamlib_version) -except Exception as e: - structlog.get_logger("structlog").warning("[RIG] Python Hamlib binding not found", error=e) +except Exception as err: + structlog.get_logger("structlog").warning("[RIG] Python Hamlib binding not found", error=err) try: structlog.get_logger("structlog").warning("[RIG] Trying to open rigctl") rigctl = subprocess.Popen("rigctl -V", shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True) hamlib_version = rigctl.stdout.readline() - hamlib_version = hamlib_version.split(' ') - if hamlib_version[1] != 'Hamlib': - raise Exception from e + hamlib_version = hamlib_version.split(" ") + if hamlib_version[1] != "Hamlib": + raise Exception from err structlog.get_logger("structlog").warning("[RIG] Rigctl found! Please try using this", version=hamlib_version[2]) sys.exit() - except Exception as e: - structlog.get_logger("structlog").critical("[RIG] HAMLIB NOT INSTALLED", error=e) + except Exception as err1: + structlog.get_logger("structlog").critical("[RIG] HAMLIB NOT INSTALLED", error=err1) hamlib_version = 0 sys.exit() @@ -75,16 +76,16 @@ except Exception as e: class radio: """ """ def __init__(self): - self.devicename = '' - self.devicenumber = '' - self.deviceport = '' - self.serialspeed = '' - self.hamlib_ptt_type = '' - self.my_rig = '' - self.pttport = '' - self.data_bits = '' - self.stop_bits = '' - self.handshake = '' + self.devicename = "" + self.devicenumber = "" + self.deviceport = "" + self.serialspeed = "" + self.hamlib_ptt_type = "" + self.my_rig = "" + self.pttport = "" + self.data_bits = "" + self.stop_bits = "" + self.handshake = "" def open_rig(self, devicename, deviceport, hamlib_ptt_type, serialspeed, pttport, data_bits, stop_bits, handshake, rigctld_port, rigctld_ip): """ @@ -133,42 +134,42 @@ class radio: self.my_rig.set_conf("data_bits", self.data_bits) self.my_rig.set_conf("ptt_pathname", self.pttport) - if self.hamlib_ptt_type == 'RIG': + if self.hamlib_ptt_type == "RIG": self.hamlib_ptt_type = Hamlib.RIG_PTT_RIG - self.my_rig.set_conf("ptt_type", 'RIG') + self.my_rig.set_conf("ptt_type", "RIG") - elif self.hamlib_ptt_type == 'USB': + elif self.hamlib_ptt_type == "USB": self.hamlib_ptt_type = Hamlib.RIG_PORT_USB - self.my_rig.set_conf("ptt_type", 'USB') + self.my_rig.set_conf("ptt_type", "USB") - elif self.hamlib_ptt_type == 'DTR-H': + elif self.hamlib_ptt_type == "DTR-H": self.hamlib_ptt_type = Hamlib.RIG_PTT_SERIAL_DTR self.my_rig.set_conf("dtr_state", "HIGH") self.my_rig.set_conf("ptt_type", "DTR") - elif self.hamlib_ptt_type == 'DTR-L': + elif self.hamlib_ptt_type == "DTR-L": self.hamlib_ptt_type = Hamlib.RIG_PTT_SERIAL_DTR self.my_rig.set_conf("dtr_state", "LOW") self.my_rig.set_conf("ptt_type", "DTR") - elif self.hamlib_ptt_type == 'RTS': + elif self.hamlib_ptt_type == "RTS": self.hamlib_ptt_type = Hamlib.RIG_PTT_SERIAL_RTS self.my_rig.set_conf("dtr_state", "OFF") self.my_rig.set_conf("ptt_type", "RTS") - elif self.hamlib_ptt_type == 'PARALLEL': + elif self.hamlib_ptt_type == "PARALLEL": self.hamlib_ptt_type = Hamlib.RIG_PTT_PARALLEL - elif self.hamlib_ptt_type == 'MICDATA': + elif self.hamlib_ptt_type == "MICDATA": self.hamlib_ptt_type = Hamlib.RIG_PTT_RIG_MICDATA - elif self.hamlib_ptt_type == 'CM108': + elif self.hamlib_ptt_type == "CM108": self.hamlib_ptt_type = Hamlib.RIG_PTT_CM108 - elif self.hamlib_ptt_type == 'RIG_PTT_NONE': + elif self.hamlib_ptt_type == "RIG_PTT_NONE": self.hamlib_ptt_type = Hamlib.RIG_PTT_NONE - else: # self.hamlib_ptt_type == 'RIG_PTT_NONE': + else: # self.hamlib_ptt_type == "RIG_PTT_NONE": self.hamlib_ptt_type = Hamlib.RIG_PTT_NONE structlog.get_logger("structlog").info("[RIG] Opening...", device=self.devicenumber, path=self.my_rig.get_conf("rig_pathname"), serial_speed=self.my_rig.get_conf("serial_speed"), serial_handshake=self.my_rig.get_conf("serial_handshake"), stop_bits=self.my_rig.get_conf("stop_bits"), data_bits=self.my_rig.get_conf("data_bits"), ptt_pathname=self.my_rig.get_conf("ptt_pathname")) @@ -178,16 +179,16 @@ class radio: try: # lets determine the error message when opening rig - error = str(Hamlib.rigerror(my_rig.error_status)).splitlines() - error = error[1].split('err=') + error = str(Hamlib.rigerror(self.my_rig.error_status)).splitlines() + error = error[1].split("err=") error = error[1] - if error == 'Permission denied': + if error == "Permission denied": structlog.get_logger("structlog").error("[RIG] Hamlib has no permissions", e = error) - help_url = 'https://github.com/DJ2LS/FreeDATA/wiki/UBUNTU-Manual-installation#1-permissions' + help_url = "https://github.com/DJ2LS/FreeDATA/wiki/UBUNTU-Manual-installation#1-permissions" structlog.get_logger("structlog").error("[RIG] HELP:", check = help_url) except Exception: - structlog.get_logger("structlog").info("[RIG] Hamlib device opened", status='SUCCESS') + structlog.get_logger("structlog").info("[RIG] Hamlib device opened", status="SUCCESS") # set ptt to false if ptt is stuck for some reason self.set_ptt(False) @@ -198,8 +199,8 @@ class radio: # self.my_rig.set_mode(Hamlib.RIG_MODE_PKTUSB) return True - except Exception as e: - structlog.get_logger("structlog").error("[RIG] Hamlib - can't open rig", error=e, e=sys.exc_info()[0]) + except Exception as err2: + structlog.get_logger("structlog").error("[RIG] Hamlib - can't open rig", error=err2, e=sys.exc_info()[0]) return False def get_frequency(self): @@ -208,13 +209,13 @@ class radio: def get_mode(self): """ """ - (hamlib_mode, bandwith) = self.my_rig.get_mode() + (hamlib_mode, bandwidth) = self.my_rig.get_mode() return Hamlib.rig_strrmode(hamlib_mode) def get_bandwith(self): """ """ - (hamlib_mode, bandwith) = self.my_rig.get_mode() - return bandwith + (hamlib_mode, bandwidth) = self.my_rig.get_mode() + return bandwidth # not needed yet beacuse of some possible problems # def set_mode(self, mode): diff --git a/tnc/rigctl.py b/tnc/rigctl.py index f275ff81..13efef56 100644 --- a/tnc/rigctl.py +++ b/tnc/rigctl.py @@ -23,16 +23,17 @@ hamlib_version = 0 class radio: """ """ def __init__(self): - self.devicename = '' - self.devicenumber = '' - self.deviceport = '' - self.serialspeed = '' - self.hamlib_ptt_type = '' - self.my_rig = '' - self.pttport = '' - self.data_bits = '' - self.stop_bits = '' - self.handshake = '' + self.devicename = "" + self.devicenumber = "" + self.deviceport = "" + self.serialspeed = "" + self.hamlib_ptt_type = "" + self.my_rig = "" + self.pttport = "" + self.data_bits = "" + self.stop_bits = "" + self.handshake = "" + self.cmd = "" def open_rig(self, devicename, deviceport, hamlib_ptt_type, serialspeed, pttport, data_bits, stop_bits, handshake, rigctld_ip, rigctld_port): """ @@ -71,26 +72,26 @@ class radio: try: import Hamlib self.devicenumber = int(getattr(Hamlib, self.devicename)) - except Exception as e: + except Exception as err: if int(self.devicename): self.devicenumber = int(self.devicename) else: self.devicenumber = 6 # dummy - structlog.get_logger("structlog").warning("[RIGCTL] Radio not found. Using DUMMY!", error=e) + structlog.get_logger("structlog").warning("[RIGCTL] Radio not found. Using DUMMY!", error=err) # set deviceport to dummy port, if we selected dummy model if self.devicenumber in {1, 6}: - self.deviceport = '/dev/ttyUSB0' + self.deviceport = "/dev/ttyUSB0" print(self.devicenumber, self.deviceport, self.serialspeed) # select precompiled executable for win32/win64 rigctl # this is really a hack...somewhen we need a native hamlib integration for windows - if sys.platform in ['win32', 'win64']: - self.cmd = app_path + 'lib\\hamlib\\'+sys.platform+'\\rigctl -m %d -r %s -s %d ' % (int(self.devicenumber), self.deviceport, int(self.serialspeed)) + if sys.platform in ["win32", "win64"]: + self.cmd = app_path + "lib\\hamlib\\" + sys.platform + "\\rigctl -m %d -r %s -s %d " % (int(self.devicenumber), self.deviceport, int(self.serialspeed)) else: - self.cmd = 'rigctl -m %d -r %s -s %d ' % (int(self.devicenumber), self.deviceport, int(self.serialspeed)) + self.cmd = "rigctl -m %d -r %s -s %d " % (int(self.devicenumber), self.deviceport, int(self.serialspeed)) # eseguo semplicemente rigctl con il solo comando T 1 o T 0 per # il set e t per il get @@ -101,11 +102,11 @@ class radio: def get_frequency(self): """ """ - cmd = f'{self.cmd} f' + cmd = f"{self.cmd} f" sw_proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True) time.sleep(0.5) freq = sw_proc.communicate()[0] - # print('get_frequency', freq, sw_proc.communicate()) + # print("get_frequency", freq, sw_proc.communicate()) try: return int(freq) except Exception: @@ -116,17 +117,17 @@ class radio: # (hamlib_mode, bandwith) = self.my_rig.get_mode() # return Hamlib.rig_strrmode(hamlib_mode) try: - return 'PKTUSB' + return "PKTUSB" except Exception: return False def get_bandwith(self): """ """ # (hamlib_mode, bandwith) = self.my_rig.get_mode() - bandwith = 2700 + bandwidth = 2700 try: - return bandwith + return bandwidth except Exception: return False @@ -144,7 +145,7 @@ class radio: def get_ptt(self): """ """ - cmd = f'{self.cmd} t' + cmd = f"{self.cmd} t" sw_proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True) time.sleep(0.5) status = sw_proc.communicate()[0] @@ -163,10 +164,10 @@ class radio: Returns: """ - cmd = f'{self.cmd} T ' - print('set_ptt', state) - cmd = f'{cmd}1' if state else f'{cmd}0' - print('set_ptt', cmd) + cmd = f"{self.cmd} T " + print("set_ptt", state) + cmd = f"{cmd}1" if state else f"{cmd}0" + print("set_ptt", cmd) sw_proc = subprocess.Popen(cmd, shell=True, text=True) try: diff --git a/tnc/rigctld.py b/tnc/rigctld.py index ef388acb..34c02806 100644 --- a/tnc/rigctld.py +++ b/tnc/rigctld.py @@ -8,10 +8,9 @@ import logging import socket import time -import structlog - import log_handler import static +import structlog # set global hamlib version hamlib_version = 0 @@ -22,7 +21,7 @@ class radio(): # Note: This is a massive hack. def __init__(self, hostname="localhost", port=4532, poll_rate=5, timeout=5): - """ Open a connection to rotctld, and test it for validity """ + """ Open a connection to rigctld, and test it for validity """ self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # self.sock.settimeout(timeout) @@ -51,7 +50,7 @@ class radio(): """ self.hostname = rigctld_ip self.port = int(rigctld_port) - + if self.connect(): logging.debug("Rigctl intialized") return True @@ -67,10 +66,10 @@ class radio(): self.connected = True structlog.get_logger("structlog").info("[RIGCTLD] Connected to rigctld!", ip=self.hostname, port=self.port) return True - except Exception as e: + except Exception as err: # ConnectionRefusedError: [Errno 111] Connection refused self.close_rig() - structlog.get_logger("structlog").warning("[RIGCTLD] Connection to rigctld refused! Reconnect...", ip=self.hostname, port=self.port, e=e) + structlog.get_logger("structlog").warning("[RIGCTLD] Connection to rigctld refused! Reconnect...", ip=self.hostname, port=self.port, e=err) return False def close_rig(self): @@ -78,7 +77,7 @@ class radio(): self.sock.close() self.connected = False - def send_command(self, command): + def send_command(self, command) -> bytes: """Send a command to the connected rotctld instance, and return the return value. @@ -90,7 +89,7 @@ class radio(): """ if self.connected: try: - self.connection.sendall(command+b'\n') + self.connection.sendall(command + b"\n") except Exception: structlog.get_logger("structlog").warning("[RIGCTLD] Command not executed!", command=command, ip=self.hostname, port=self.port) self.connected = False @@ -106,11 +105,13 @@ class radio(): time.sleep(0.5) self.connect() + return b"" + def get_mode(self): """ """ try: data = self.send_command(b"m") - data = data.split(b'\n') + data = data.split(b"\n") mode = data[0] return mode.decode("utf-8") except Exception: @@ -120,7 +121,7 @@ class radio(): """ """ try: data = self.send_command(b"m") - data = data.split(b'\n') + data = data.split(b"\n") bandwith = data[1] return bandwith.decode("utf-8") except Exception: diff --git a/tnc/rigdummy.py b/tnc/rigdummy.py index 445cfb58..ccd3012f 100644 --- a/tnc/rigdummy.py +++ b/tnc/rigdummy.py @@ -7,6 +7,7 @@ hamlib_version = 0 class radio: """ """ + def __init__(self): pass diff --git a/tnc/sock.py b/tnc/sock.py index e78a7776..e241bd7c 100644 --- a/tnc/sock.py +++ b/tnc/sock.py @@ -6,35 +6,31 @@ Created on Fri Dec 25 21:25:14 2020 @author: DJ2LS # GET COMMANDS - # "command" : "..." + # "command" : "..." - # SET COMMANDS - # "command" : "..." - # "parameter" : " ..." - - # DATA COMMANDS - # "command" : "..." - # "type" : "..." - # "dxcallsign" : "..." - # "data" : "..." + # SET COMMANDS + # "command" : "..." + # "parameter" : " ..." + # DATA COMMANDS + # "command" : "..." + # "type" : "..." + # "dxcallsign" : "..." + # "data" : "..." """ import atexit import base64 - import queue import socketserver import sys import threading import time -import structlog -import ujson as json - import data_handler import helpers - import static +import structlog +import ujson as json SOCKET_QUEUE = queue.Queue() DAEMON_QUEUE = queue.Queue() @@ -59,7 +55,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): function called by socket handler send data to a network client if available """ - tempdata = b'' + tempdata = b"" while self.connection_alive and not CLOSE_SIGNAL: # send tnc state as network stream # check server port against daemon port and send corresponding data @@ -77,17 +73,17 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): while not SOCKET_QUEUE.empty(): data = SOCKET_QUEUE.get() - sock_data = bytes(data, 'utf-8') - sock_data += b'\n' # append line limiter + sock_data = bytes(data, "utf-8") + sock_data += b"\n" # append line limiter # send data to all clients # try: for client in CONNECTED_CLIENTS: try: client.send(sock_data) - except Exception as e: + except Exception as err: # print("connection lost...") - structlog.get_logger("structlog").info("[SCK] Connection lost", e=e) + structlog.get_logger("structlog").info("[SCK] Connection lost", e=err) self.connection_alive = False # we want to transmit scatter data only once to reduce network traffic @@ -108,15 +104,15 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): chunk = self.request.recv(1024) data += chunk - if chunk == b'': + if chunk == b"": # print("connection broken. Closing...") self.connection_alive = False - if data.startswith(b'{') and data.endswith(b'}\n'): + if data.startswith(b"{") and data.endswith(b"}\n"): # split data by \n if we have multiple commands in socket buffer - data = data.split(b'\n') + data = data.split(b"\n") # remove empty data - data.remove(b'') + data.remove(b"") # iterate thorugh data list for commands in data: @@ -134,9 +130,9 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): # finally delete our rx buffer to be ready for new commands data = bytes() - except Exception as e: + except Exception as err: structlog.get_logger("structlog").info("[SCK] Connection closed", ip=self.client_address[0], - port=self.client_address[1], e=e) + port=self.client_address[1], e=err) self.connection_alive = False def handle(self): @@ -162,9 +158,9 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): port=self.client_address[1]) try: CONNECTED_CLIENTS.remove(self.request) - except Exception as e: + except Exception as err: structlog.get_logger("structlog").warning("[SCK] client connection already removed from client list", - client=self.request, e=e) + client=self.request, e=err) def process_tnc_commands(data): @@ -188,53 +184,53 @@ def process_tnc_commands(data): static.TX_AUDIO_LEVEL = int(received_json["value"]) command_response("tx_audio_level", True) - except Exception as e: + except Exception as err: command_response("tx_audio_level", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json) + structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) # TRANSMIT SINE WAVE ----------------------------------------------------- if received_json["type"] == "set" and received_json["command"] == "send_test_frame": try: - data_handler.DATA_QUEUE_TRANSMIT.put(['SEND_TEST_FRAME']) + data_handler.DATA_QUEUE_TRANSMIT.put(["SEND_TEST_FRAME"]) command_response("send_test_frame", True) - except Exception as e: + except Exception as err: command_response("send_test_frame", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json) + structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) # CQ CQ CQ ----------------------------------------------------- if received_json["command"] == "cqcqcq": try: - data_handler.DATA_QUEUE_TRANSMIT.put(['CQ']) + data_handler.DATA_QUEUE_TRANSMIT.put(["CQ"]) command_response("cqcqcq", True) - except Exception as e: + except Exception as err: command_response("cqcqcq", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json) + structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) # START_BEACON ----------------------------------------------------- if received_json["command"] == "start_beacon": try: static.BEACON_STATE = True interval = int(received_json["parameter"]) - data_handler.DATA_QUEUE_TRANSMIT.put(['BEACON', interval, True]) + data_handler.DATA_QUEUE_TRANSMIT.put(["BEACON", interval, True]) command_response("start_beacon", True) - except Exception as e: + except Exception as err: command_response("start_beacon", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json) + structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) # STOP_BEACON ----------------------------------------------------- if received_json["command"] == "stop_beacon": try: structlog.get_logger("structlog").warning("[TNC] Stopping beacon!") static.BEACON_STATE = False - data_handler.DATA_QUEUE_TRANSMIT.put(['BEACON', None, False]) + data_handler.DATA_QUEUE_TRANSMIT.put(["BEACON", None, False]) command_response("stop_beacon", True) - except Exception as e: + except Exception as err: command_response("stop_beacon", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json) + structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) # PING ---------------------------------------------------------- - if received_json["type"] == 'ping' and received_json["command"] == "ping": + if received_json["type"] == "ping" and received_json["command"] == "ping": # send ping frame and wait for ACK try: dxcallsign = received_json["dxcallsign"] @@ -245,14 +241,14 @@ def process_tnc_commands(data): dxcallsign = helpers.callsign_to_bytes(dxcallsign) dxcallsign = helpers.bytes_to_callsign(dxcallsign) - data_handler.DATA_QUEUE_TRANSMIT.put(['PING', dxcallsign]) + data_handler.DATA_QUEUE_TRANSMIT.put(["PING", dxcallsign]) command_response("ping", True) - except Exception as e: + except Exception as err: command_response("ping", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json) + structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) # CONNECT ---------------------------------------------------------- - if received_json["type"] == 'arq' and received_json["command"] == "connect": + if received_json["type"] == "arq" and received_json["command"] == "connect": static.BEACON_PAUSE = True # send ping frame and wait for ACK try: @@ -267,24 +263,24 @@ def process_tnc_commands(data): static.DXCALLSIGN = dxcallsign static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN) - data_handler.DATA_QUEUE_TRANSMIT.put(['CONNECT', dxcallsign]) + data_handler.DATA_QUEUE_TRANSMIT.put(["CONNECT", dxcallsign]) command_response("connect", True) - except Exception as e: + except Exception as err: command_response("connect", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json) + structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) # DISCONNECT ---------------------------------------------------------- - if received_json["type"] == 'arq' and received_json["command"] == "disconnect": + if received_json["type"] == "arq" and received_json["command"] == "disconnect": # send ping frame and wait for ACK try: - data_handler.DATA_QUEUE_TRANSMIT.put(['DISCONNECT']) + data_handler.DATA_QUEUE_TRANSMIT.put(["DISCONNECT"]) command_response("disconnect", True) - except Exception as e: + except Exception as err: command_response("disconnect", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json) + structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) # TRANSMIT RAW DATA ------------------------------------------- - if received_json["type"] == 'arq' and received_json["command"] == "send_raw": + if received_json["type"] == "arq" and received_json["command"] == "send_raw": static.BEACON_PAUSE = True try: if not static.ARQ_SESSION: @@ -315,32 +311,32 @@ def process_tnc_commands(data): try: arq_uuid = received_json["uuid"] except Exception: - arq_uuid = 'no-uuid' + arq_uuid = "no-uuid" if not len(base64data) % 4: binarydata = base64.b64decode(base64data) - data_handler.DATA_QUEUE_TRANSMIT.put(['ARQ_RAW', binarydata, mode, n_frames, arq_uuid, mycallsign]) + data_handler.DATA_QUEUE_TRANSMIT.put(["ARQ_RAW", binarydata, mode, n_frames, arq_uuid, mycallsign]) else: raise TypeError - except Exception as e: + except Exception as err: command_response("send_raw", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json) + structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) # STOP TRANSMISSION ---------------------------------------------------------- - if received_json["type"] == 'arq' and received_json["command"] == "stop_transmission": + if received_json["type"] == "arq" and received_json["command"] == "stop_transmission": try: - if static.TNC_STATE == 'BUSY' or static.ARQ_STATE: - data_handler.DATA_QUEUE_TRANSMIT.put(['STOP']) + if static.TNC_STATE == "BUSY" or static.ARQ_STATE: + data_handler.DATA_QUEUE_TRANSMIT.put(["STOP"]) structlog.get_logger("structlog").warning("[TNC] Stopping transmission!") - static.TNC_STATE = 'IDLE' + static.TNC_STATE = "IDLE" static.ARQ_STATE = False command_response("stop_transmission", True) - except Exception as e: + except Exception as err: command_response("stop_transmission", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json) + structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) - if received_json["type"] == 'get' and received_json["command"] == 'rx_buffer': + if received_json["type"] == "get" and received_json["command"] == "rx_buffer": try: output = { "command": "rx_buffer", @@ -352,36 +348,36 @@ def process_tnc_commands(data): # rawdata = json.loads(static.RX_BUFFER[i][4]) base64_data = static.RX_BUFFER[i][4] output["data-array"].append({"uuid": static.RX_BUFFER[i][0], "timestamp": static.RX_BUFFER[i][1], - "dxcallsign": str(static.RX_BUFFER[i][2], 'utf-8'), - "dxgrid": str(static.RX_BUFFER[i][3], 'utf-8'), "data": base64_data}) + "dxcallsign": str(static.RX_BUFFER[i][2], "utf-8"), + "dxgrid": str(static.RX_BUFFER[i][3], "utf-8"), "data": base64_data}) jsondata = json.dumps(output) # self.request.sendall(bytes(jsondata, encoding)) SOCKET_QUEUE.put(jsondata) command_response("rx_buffer", True) - except Exception as e: + except Exception as err: command_response("rx_buffer", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json) + structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) - if received_json["type"] == 'set' and received_json["command"] == 'del_rx_buffer': + if received_json["type"] == "set" and received_json["command"] == "del_rx_buffer": try: static.RX_BUFFER = [] command_response("del_rx_buffer", True) - except Exception as e: + except Exception as err: command_response("del_rx_buffer", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json) + structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) # exception, if JSON can't be decoded - except Exception as e: - structlog.get_logger("structlog").error("[TNC] JSON decoding error", e=e) + except Exception as err: + structlog.get_logger("structlog").error("[TNC] JSON decoding error", e=err) def send_tnc_state(): """ send the tnc state to network """ - encoding = 'utf-8' + encoding = "utf-8" output = { "command": "tnc_state", @@ -417,8 +413,8 @@ def send_tnc_state(): # add heard stations to heard stations object for heard in static.HEARD_STATIONS: output["stations"].append({ - "dxcallsign": str(heard[0], 'utf-8'), - "dxgrid": str(heard[1], 'utf-8'), + "dxcallsign": str(heard[0], "utf-8"), + "dxgrid": str(heard[1], "utf-8"), "timestamp": heard[2], "datatype": heard[3], "snr": heard[4], @@ -441,40 +437,40 @@ def process_daemon_commands(data): # convert data to json object received_json = json.loads(data) structlog.get_logger("structlog").debug("[SCK] CMD", command=received_json) - if received_json["type"] == 'set' and received_json["command"] == 'mycallsign': + if received_json["type"] == "set" and received_json["command"] == "mycallsign": try: callsign = received_json["parameter"] - if bytes(callsign, 'utf-8') == b'': - self.request.sendall(b'INVALID CALLSIGN') + if bytes(callsign, "utf-8") == b"": + self.request.sendall(b"INVALID CALLSIGN") structlog.get_logger("structlog").warning("[DMN] SET MYCALL FAILED", call=static.MYCALLSIGN, crc=static.MYCALLSIGN_CRC) else: - static.MYCALLSIGN = bytes(callsign, 'utf-8') + static.MYCALLSIGN = bytes(callsign, "utf-8") static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN) command_response("mycallsign", True) structlog.get_logger("structlog").info("[DMN] SET MYCALL", call=static.MYCALLSIGN, crc=static.MYCALLSIGN_CRC) - except Exception as e: + except Exception as err: command_response("mycallsign", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json) + structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) - if received_json["type"] == 'set' and received_json["command"] == 'mygrid': + if received_json["type"] == "set" and received_json["command"] == "mygrid": try: mygrid = received_json["parameter"] - if bytes(mygrid, 'utf-8') == b'': - self.request.sendall(b'INVALID GRID') + if bytes(mygrid, "utf-8") == b"": + self.request.sendall(b"INVALID GRID") else: - static.MYGRID = bytes(mygrid, 'utf-8') + static.MYGRID = bytes(mygrid, "utf-8") structlog.get_logger("structlog").info("[SCK] SET MYGRID", grid=static.MYGRID) command_response("mygrid", True) - except Exception as e: + except Exception as err: command_response("mygrid", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json) + structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) - if received_json["type"] == 'set' and received_json["command"] == 'start_tnc' and not static.TNCSTARTED: + if received_json["type"] == "set" and received_json["command"] == "start_tnc" and not static.TNCSTARTED: try: mycall = str(received_json["parameter"][0]["mycall"]) mygrid = str(received_json["parameter"][0]["mygrid"]) @@ -504,7 +500,7 @@ def process_daemon_commands(data): for item in received_json["parameter"][0]: structlog.get_logger("structlog").debug(f"[DMN] TNC Startup Config : {item}", value=received_json["parameter"][0][item]) - DAEMON_QUEUE.put(['STARTTNC', + DAEMON_QUEUE.put(["STARTTNC", mycall, mygrid, rx_audio, @@ -531,11 +527,11 @@ def process_daemon_commands(data): ]) command_response("start_tnc", True) - except Exception as e: + except Exception as err: command_response("start_tnc", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json) + structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) - if received_json["type"] == 'get' and received_json["command"] == 'test_hamlib': + if received_json["type"] == "get" and received_json["command"] == "test_hamlib": try: devicename = str(received_json["parameter"][0]["devicename"]) deviceport = str(received_json["parameter"][0]["deviceport"]) @@ -549,7 +545,7 @@ def process_daemon_commands(data): rigctld_ip = str(received_json["parameter"][0]["rigctld_ip"]) rigctld_port = str(received_json["parameter"][0]["rigctld_port"]) - DAEMON_QUEUE.put(['TEST_HAMLIB', + DAEMON_QUEUE.put(["TEST_HAMLIB", devicename, deviceport, serialspeed, @@ -563,11 +559,11 @@ def process_daemon_commands(data): rigctld_port, ]) command_response("test_hamlib", True) - except Exception as e: + except Exception as err: command_response("test_hamlib", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json) + structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) - if received_json["type"] == 'set' and received_json["command"] == 'stop_tnc': + if received_json["type"] == "set" and received_json["command"] == "stop_tnc": try: static.TNCPROCESS.kill() # unregister process from atexit to avoid process zombies @@ -576,9 +572,9 @@ def process_daemon_commands(data): structlog.get_logger("structlog").warning("[DMN] Stopping TNC") static.TNCSTARTED = False command_response("stop_tnc", True) - except Exception as e: + except Exception as err: command_response("stop_tnc", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json) + structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) def send_daemon_state(): @@ -589,16 +585,16 @@ def send_daemon_state(): python_version = f"{str(sys.version_info[0])}.{str(sys.version_info[1])}" output = { - 'command': 'daemon_state', - 'daemon_state': [], - 'python_version': str(python_version), - 'hamlib_version': static.HAMLIB_VERSION, - 'input_devices': static.AUDIO_INPUT_DEVICES, - 'output_devices': static.AUDIO_OUTPUT_DEVICES, - 'serial_devices': static.SERIAL_DEVICES, - # 'cpu': str(psutil.cpu_percent()), - # 'ram': str(psutil.virtual_memory().percent), - 'version': '0.1' + "command": "daemon_state", + "daemon_state": [], + "python_version": str(python_version), + "hamlib_version": static.HAMLIB_VERSION, + "input_devices": static.AUDIO_INPUT_DEVICES, + "output_devices": static.AUDIO_OUTPUT_DEVICES, + "serial_devices": static.SERIAL_DEVICES, + # "cpu": str(psutil.cpu_percent()), + # "ram": str(psutil.virtual_memory().percent), + "version": "0.1" } if static.TNCSTARTED: @@ -608,8 +604,8 @@ def send_daemon_state(): return json.dumps(output) - except Exception as e: - structlog.get_logger("structlog").warning("[SCK] error", e=e) + except Exception as err: + structlog.get_logger("structlog").warning("[SCK] error", e=err) return None diff --git a/tnc/static.py b/tnc/static.py index 9b2e311a..aef93c35 100644 --- a/tnc/static.py +++ b/tnc/static.py @@ -8,7 +8,7 @@ Here we are saving application wide variables and stats, which have to be access Not nice, suggestions are appreciated :-) """ -VERSION = '0.4.0-alpha' +VERSION = "0.4.0-alpha" # DAEMON DAEMONPORT = 3001 @@ -16,14 +16,14 @@ TNCSTARTED = False TNCPROCESS = 0 # Operator Defaults -MYCALLSIGN = b'AA0AA' -MYCALLSIGN_CRC = b'A' +MYCALLSIGN = b"AA0AA" +MYCALLSIGN_CRC = b"A" -DXCALLSIGN = b'AA0AA' -DXCALLSIGN_CRC = b'A' +DXCALLSIGN = b"AA0AA" +DXCALLSIGN_CRC = b"A" -MYGRID = b'' -DXGRID = b'' +MYGRID = b"" +DXGRID = b"" SSID_LIST = [] # ssid list we are responding to @@ -41,21 +41,21 @@ SERIAL_DEVICES = [] PTT_STATE = False TRANSMITTING = False -HAMLIB_VERSION = '0' -HAMLIB_PTT_TYPE = 'RTS' -HAMLIB_DEVICE_NAME = 'RIG_MODEL_DUMMY_NOVFO' -HAMLIB_DEVICE_PORT = '/dev/ttyUSB0' -HAMLIB_SERIAL_SPEED = '9600' -HAMLIB_PTT_PORT = '/dev/ttyUSB0' -HAMLIB_STOP_BITS = '1' -HAMLIB_DATA_BITS = '8' -HAMLIB_HANDSHAKE = 'None' -HAMLIB_RADIOCONTROL = 'direct' -HAMLIB_RIGCTLD_IP = '127.0.0.1' -HAMLIB_RIGCTLD_PORT = '4532' +HAMLIB_VERSION = "0" +HAMLIB_PTT_TYPE = "RTS" +HAMLIB_DEVICE_NAME = "RIG_MODEL_DUMMY_NOVFO" +HAMLIB_DEVICE_PORT = "/dev/ttyUSB0" +HAMLIB_SERIAL_SPEED = "9600" +HAMLIB_PTT_PORT = "/dev/ttyUSB0" +HAMLIB_STOP_BITS = "1" +HAMLIB_DATA_BITS = "8" +HAMLIB_HANDSHAKE = "None" +HAMLIB_RADIOCONTROL = "direct" +HAMLIB_RIGCTLD_IP = "127.0.0.1" +HAMLIB_RIGCTLD_PORT = "4532" HAMLIB_FREQUENCY = 0 -HAMLIB_MODE = '' +HAMLIB_MODE = "" HAMLIB_BANDWITH = 0 # ------------------------- # FreeDV Defaults @@ -95,10 +95,10 @@ ARQ_SPEED_LEVEL = 0 TOTAL_BYTES = 0 # CHANNEL_STATE = 'RECEIVING_SIGNALLING' -TNC_STATE = 'IDLE' +TNC_STATE = "IDLE" ARQ_STATE = False ARQ_SESSION = False -ARQ_SESSION_STATE = 'disconnected' # disconnected, connecting, connected, disconnecting, failed +ARQ_SESSION_STATE = "disconnected" # disconnected, connecting, connected, disconnecting, failed # BEACON STATE BEACON_STATE = False @@ -108,7 +108,7 @@ BEACON_PAUSE = False RX_BUFFER = [] RX_MSG_BUFFER = [] RX_BURST_BUFFER = [] -RX_FRAME_BUFFER = b'' +RX_FRAME_BUFFER = b"" # RX_BUFFER_SIZE = 0 # ------- HEARD STATIONS BUFFER From 2fa9aead44b5cf8a100e30fc823e7ecb21456a6a Mon Sep 17 00:00:00 2001 From: Paul Kronenwetter Date: Fri, 27 May 2022 22:17:15 -0400 Subject: [PATCH 6/8] Another round of formatting changes. Implement class-level logging in places. --- tnc/daemon.py | 49 ++--- tnc/data_handler.py | 395 ++++++++++++++++++------------------ tnc/main.py | 2 +- tnc/modem.py | 47 ++--- tnc/rigctld.py | 2 - tnc/rigdummy.py | 2 - tnc/sock.py | 89 ++++---- tnc/static.py | 147 +++++++------- tools/list_audio_devices.py | 12 +- tools/socketclient.py | 14 +- 10 files changed, 380 insertions(+), 379 deletions(-) diff --git a/tnc/daemon.py b/tnc/daemon.py index 5b751e75..63551b81 100755 --- a/tnc/daemon.py +++ b/tnc/daemon.py @@ -55,6 +55,8 @@ class DAEMON: Daemon class """ + log = structlog.get_logger("DAEMON") + def __init__(self): # load crc engine self.crc_algorithm = crcengine.new("crc16-ccitt-false") # load crc8 library @@ -73,12 +75,12 @@ class DAEMON: """ Update audio devices and set to static """ - while 1: + while True: try: if not static.TNCSTARTED: static.AUDIO_INPUT_DEVICES, static.AUDIO_OUTPUT_DEVICES = audio.get_audio_devices() except Exception as err1: - structlog.get_logger("structlog").error("[DMN] update_audio_devices: Exception gathering audio devices:", e=err1) + self.log.error("[DMN] update_audio_devices: Exception gathering audio devices:", e=err1) # print(e) time.sleep(1) @@ -86,7 +88,7 @@ class DAEMON: """ Update serial devices and set to static """ - while 1: + while True: try: serial_devices = [] ports = serial.tools.list_ports.comports() @@ -101,14 +103,14 @@ class DAEMON: static.SERIAL_DEVICES = serial_devices time.sleep(1) except Exception as err1: - structlog.get_logger("structlog").error("[DMN] update_serial_devices: Exception gathering serial devices:", e=err1) + self.log.error("[DMN] update_serial_devices: Exception gathering serial devices:", e=err1) # print(e) def worker(self): """ Worker to handle the received commands """ - while 1: + while True: try: data = self.daemon_queue.get() @@ -137,7 +139,7 @@ class DAEMON: # data[23] respond_to_cq if data[0] == "STARTTNC": - structlog.get_logger("structlog").warning("[DMN] Starting TNC", rig=data[5], port=data[6]) + self.log.warning("[DMN] Starting TNC", rig=data[5], port=data[6]) # list of parameters, necessary for running subprocess command as a list options = [] @@ -231,13 +233,13 @@ class DAEMON: command.append("freedata-tnc.exe") command += options - p = subprocess.Popen(command) + proc = subprocess.Popen(command) - atexit.register(p.kill) + atexit.register(proc.kill) - structlog.get_logger("structlog").info("[DMN] TNC started", path="binary") + self.log.info("[DMN] TNC started", path="binary") except FileNotFoundError as err1: - structlog.get_logger("structlog").error("[DMN] worker: Exception:", e=err1) + self.log.error("[DMN] worker: Exception:", e=err1) command = [] if sys.platform in ["linux", "darwin"]: command.append("python3") @@ -246,18 +248,18 @@ class DAEMON: command.append("main.py") command += options - p = subprocess.Popen(command) - atexit.register(p.kill) + proc = subprocess.Popen(command) + atexit.register(proc.kill) - structlog.get_logger("structlog").info("[DMN] TNC started", path="source") + self.log.info("[DMN] TNC started", path="source") - static.TNCPROCESS = p # .pid + static.TNCPROCESS = proc static.TNCSTARTED = True """ # WE HAVE THIS PART in SOCKET if data[0] == "STOPTNC": static.TNCPROCESS.kill() - structlog.get_logger("structlog").warning("[DMN] Stopping TNC") + self.log.warning("[DMN] Stopping TNC") #os.kill(static.TNCPROCESS, signal.SIGKILL) static.TNCSTARTED = False """ @@ -306,13 +308,13 @@ class DAEMON: pttstate = hamlib.get_ptt() if pttstate: - structlog.get_logger("structlog").info("[DMN] Hamlib PTT", status="SUCCESS") + self.log.info("[DMN] Hamlib PTT", status="SUCCESS") response = {"command": "test_hamlib", "result": "SUCCESS"} elif not pttstate: - structlog.get_logger("structlog").warning("[DMN] Hamlib PTT", status="NO SUCCESS") + self.log.warning("[DMN] Hamlib PTT", status="NO SUCCESS") response = {"command": "test_hamlib", "result": "NOSUCCESS"} else: - structlog.get_logger("structlog").error("[DMN] Hamlib PTT", status="FAILED") + self.log.error("[DMN] Hamlib PTT", status="FAILED") response = {"command": "test_hamlib", "result": "FAILED"} hamlib.set_ptt(False) @@ -322,10 +324,11 @@ class DAEMON: sock.SOCKET_QUEUE.put(jsondata) except Exception as err1: - structlog.get_logger("structlog").error("[DMN] worker: Exception: ", e=err1) + self.log.error("[DMN] worker: Exception: ", e=err1) if __name__ == "__main__": + mainlog = structlog.get_logger(__file__) # we need to run this on Windows for multiprocessing support multiprocessing.freeze_support() @@ -350,10 +353,10 @@ if __name__ == "__main__": os.makedirs(logging_path) log_handler.setup_logging(logging_path) except Exception as err: - structlog.get_logger("structlog").error("[DMN] logger init error", exception=err) + mainlog.error("[DMN] logger init error", exception=err) try: - structlog.get_logger("structlog").info("[DMN] Starting TCP/IP socket", port=static.DAEMONPORT) + mainlog.info("[DMN] Starting TCP/IP socket", port=static.DAEMONPORT) # https://stackoverflow.com/a/16641793 socketserver.TCPServer.allow_reuse_address = True cmdserver = sock.ThreadedTCPServer((static.HOST, static.DAEMONPORT), sock.ThreadedTCPRequestHandler) @@ -362,10 +365,10 @@ if __name__ == "__main__": server_thread.start() except Exception as err: - structlog.get_logger("structlog").error("[DMN] Starting TCP/IP socket failed", port=static.DAEMONPORT, e=err) + mainlog.error("[DMN] Starting TCP/IP socket failed", port=static.DAEMONPORT, e=err) sys.exit(1) daemon = DAEMON() - structlog.get_logger("structlog").info("[DMN] Starting FreeDATA Daemon", author="DJ2LS", year="2022", version=static.VERSION) + mainlog.info("[DMN] Starting FreeDATA Daemon", author="DJ2LS", year="2022", version=static.VERSION) while True: time.sleep(1) diff --git a/tnc/data_handler.py b/tnc/data_handler.py index eb6b8591..d4e37bea 100644 --- a/tnc/data_handler.py +++ b/tnc/data_handler.py @@ -34,6 +34,7 @@ DATA_QUEUE_RECEIVED = queue.Queue() class DATA: """ Terminal Node Controller for FreeDATA """ + log = structlog.get_logger("DATA") def __init__(self): self.mycallsign = static.MYCALLSIGN # initial call sign. Will be overwritten later @@ -104,7 +105,8 @@ class DATA: daemon=True) worker_thread_transmit.start() - worker_thread_receive = threading.Thread(target=self.worker_receive, name="worker thread receive", daemon=True) + worker_thread_receive = threading.Thread(target=self.worker_receive, name="worker thread receive", + daemon=True) worker_thread_receive.start() # START THE THREAD FOR THE TIMEOUT WATCHDOG @@ -163,8 +165,7 @@ class DATA: # [1] DX CALLSIGN self.send_test_frame() else: - structlog.get_logger("structlog").error("[TNC] worker_transmit: received invalid command:", data=data) - # print(f"Invalid command: {data}") + self.log.error("[TNC] worker_transmit: received invalid command:", data=data) def worker_receive(self): """ """ @@ -186,8 +187,7 @@ class DATA: Returns: """ - structlog.get_logger("structlog").debug("[TNC] process_data:", n_retries_per_burst=self.n_retries_per_burst) - # print(f"self.n_retries_per_burst = {self.n_retries_per_burst}") + self.log.debug("[TNC] process_data:", n_retries_per_burst=self.n_retries_per_burst) # forward data only if broadcast or we are the receiver # bytes_out[1:4] == callsign check for signalling frames, @@ -207,111 +207,111 @@ class DATA: # snr = self.calculate_snr(freedv) # we need to find a way of fixing this because after moving to class system this doesn't work anymore snr = static.SNR - structlog.get_logger("structlog").debug("[TNC] RX SNR", snr=snr) + self.log.debug("[TNC] RX SNR", snr=snr) # send payload data to arq checker without CRC16 self.arq_data_received(bytes(bytes_out[:-2]), bytes_per_frame, snr, freedv) # 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: - # structlog.get_logger("structlog").debug(f"[TNC] LAST FRAME OF BURST --> UNSYNC {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) # BURST ACK elif frametype == 60: - structlog.get_logger("structlog").debug("[TNC] ACK RECEIVED....") + self.log.debug("[TNC] ACK RECEIVED....") self.burst_ack_received(bytes_out[:-2]) # FRAME ACK elif frametype == 61: - structlog.get_logger("structlog").debug("[TNC] FRAME ACK RECEIVED....") + self.log.debug("[TNC] FRAME ACK RECEIVED....") self.frame_ack_received() # FRAME RPT elif frametype == 62: - structlog.get_logger("structlog").debug("[TNC] REPEAT REQUEST RECEIVED....") + self.log.debug("[TNC] REPEAT REQUEST RECEIVED....") self.burst_rpt_received(bytes_out[:-2]) # FRAME NACK elif frametype == 63: - structlog.get_logger("structlog").debug("[TNC] FRAME NACK RECEIVED....") + self.log.debug("[TNC] FRAME NACK RECEIVED....") self.frame_nack_received(bytes_out[:-2]) # BURST NACK elif frametype == 64: - structlog.get_logger("structlog").debug("[TNC] BURST NACK RECEIVED....") + self.log.debug("[TNC] BURST NACK RECEIVED....") self.burst_nack_received(bytes_out[:-2]) # CQ FRAME elif frametype == 200: - structlog.get_logger("structlog").debug("[TNC] CQ RECEIVED....") + self.log.debug("[TNC] CQ RECEIVED....") self.received_cq(bytes_out[:-2]) # QRV FRAME elif frametype == 201: - structlog.get_logger("structlog").debug("[TNC] QRV RECEIVED....") + self.log.debug("[TNC] QRV RECEIVED....") self.received_qrv(bytes_out[:-2]) # PING FRAME elif frametype == 210: - structlog.get_logger("structlog").debug("[TNC] PING RECEIVED....") + self.log.debug("[TNC] PING RECEIVED....") self.received_ping(bytes_out[:-2]) # PING ACK elif frametype == 211: - structlog.get_logger("structlog").debug("[TNC] PING ACK RECEIVED....") + self.log.debug("[TNC] PING ACK RECEIVED....") self.received_ping_ack(bytes_out[:-2]) # SESSION OPENER elif frametype == 221: - structlog.get_logger("structlog").debug("[TNC] OPEN SESSION RECEIVED....") + self.log.debug("[TNC] OPEN SESSION RECEIVED....") self.received_session_opener(bytes_out[:-2]) # SESSION HEARTBEAT elif frametype == 222: - structlog.get_logger("structlog").debug("[TNC] SESSION HEARTBEAT RECEIVED....") + self.log.debug("[TNC] SESSION HEARTBEAT RECEIVED....") self.received_session_heartbeat(bytes_out[:-2]) # SESSION CLOSE elif frametype == 223: - structlog.get_logger("structlog").debug("[TNC] CLOSE ARQ SESSION RECEIVED....") + self.log.debug("[TNC] CLOSE ARQ SESSION RECEIVED....") self.received_session_close(bytes_out[:-2]) # ARQ FILE TRANSFER RECEIVED! elif frametype in [225, 227]: - structlog.get_logger("structlog").debug("[TNC] ARQ arq_received_data_channel_opener") + self.log.debug("[TNC] ARQ arq_received_data_channel_opener") self.arq_received_data_channel_opener(bytes_out[:-2]) # ARQ CHANNEL IS OPENED elif frametype in [226, 228]: - structlog.get_logger("structlog").debug("[TNC] ARQ arq_received_channel_is_open") + self.log.debug("[TNC] ARQ arq_received_channel_is_open") self.arq_received_channel_is_open(bytes_out[:-2]) # ARQ MANUAL MODE TRANSMISSION elif 230 <= frametype <= 240: - structlog.get_logger("structlog").debug("[TNC] ARQ manual mode") + self.log.debug("[TNC] ARQ manual mode") self.arq_received_data_channel_opener(bytes_out[:-2]) # ARQ STOP TRANSMISSION elif frametype == 249: - structlog.get_logger("structlog").debug("[TNC] ARQ received stop transmission") + self.log.debug("[TNC] ARQ received stop transmission") self.received_stop_transmission() # this is outdated and we may remove it elif frametype == 250: - structlog.get_logger("structlog").debug("[TNC] BEACON RECEIVED") + self.log.debug("[TNC] BEACON RECEIVED") self.received_beacon(bytes_out[:-2]) # TESTFRAMES elif frametype == 255: - structlog.get_logger("structlog").debug("[TNC] TESTFRAME RECEIVED", frame=bytes_out[:]) + self.log.debug("[TNC] TESTFRAME RECEIVED", frame=bytes_out[:]) # Unknown frame type else: - structlog.get_logger("structlog").warning("[TNC] ARQ - other frame type", frametype=frametype) + self.log.warning("[TNC] ARQ - other frame type", frametype=frametype) else: # for debugging purposes to receive all data - structlog.get_logger("structlog").debug("[TNC] Unknown frame received", frame=bytes_out[:-2]) + self.log.debug("[TNC] Unknown frame received", frame=bytes_out[:-2]) def enqueue_frame_for_tx(self, frame_to_tx: bytearray, c2_mode=14, copies=1, repeat_delay=0): """ @@ -326,7 +326,7 @@ class DATA: :param repeat_delay: Delay time before sending repeat frame, defaults to 0 :type repeat_delay: int, optional """ - structlog.get_logger("structlog").debug("[TNC] enqueue_frame_for_tx", c2_mode=c2_mode) + self.log.debug("[TNC] enqueue_frame_for_tx", c2_mode=c2_mode) if isinstance(c2_mode, str): _mode = codec2.freedv_get_mode_value_by_name(c2_mode.lower()) else: @@ -379,7 +379,7 @@ class DATA: rpt_frame[4:7] = static.MYCALLSIGN_CRC rpt_frame[7:13] = missing_frames - structlog.get_logger("structlog").info("[TNC] ARQ | RX | Requesting", frames=missing_frames) + self.log.info("[TNC] ARQ | RX | Requesting", frames=missing_frames) # Transmit frame self.enqueue_frame_for_tx(rpt_frame) @@ -464,10 +464,10 @@ class DATA: # Append data to rx burst buffer static.RX_BURST_BUFFER[RX_N_FRAME_OF_BURST] = data_in[8:] # [frame_type][n_frames_per_burst][CRC24][CRC24] - structlog.get_logger("structlog").debug("[TNC] static.RX_BURST_BUFFER", buffer=static.RX_BURST_BUFFER) + self.log.debug("[TNC] static.RX_BURST_BUFFER", buffer=static.RX_BURST_BUFFER) - helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "DATA-CHANNEL", snr, static.FREQ_OFFSET, - static.HAMLIB_FREQUENCY) + helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "DATA-CHANNEL", + snr, static.FREQ_OFFSET, static.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 @@ -482,7 +482,7 @@ class DATA: # 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 didnt receive its destination (ISS) if static.RX_FRAME_BUFFER.endswith(temp_burst_buffer): - structlog.get_logger("structlog").info("[TNC] ARQ | RX | Frame already received - sending ACK again") + self.log.info("[TNC] ARQ | RX | Frame already received - sending ACK again") static.RX_BURST_BUFFER = [] else: @@ -503,12 +503,12 @@ class DATA: static.RX_FRAME_BUFFER = static.RX_FRAME_BUFFER[:search_position + get_position] static.RX_FRAME_BUFFER += temp_burst_buffer - structlog.get_logger("structlog").warning("[TNC] ARQ | RX | replacing existing buffer data", - area=search_area, pos=get_position) + self.log.warning("[TNC] ARQ | RX | replacing existing buffer data", + area=search_area, pos=get_position) # if we dont find data n this range, we really have new data and going to replace it else: static.RX_FRAME_BUFFER += temp_burst_buffer - structlog.get_logger("structlog").debug("[TNC] ARQ | RX | appending data to buffer") + self.log.debug("[TNC] ARQ | RX | appending data to buffer") # lets check if we didnt receive a BOF and EOF yet to avoid sending ack frames if we already received all data if (not self.rx_frame_bof_received and @@ -527,7 +527,7 @@ class DATA: self.set_listening_modes(self.mode_list[self.speed_level]) # Create and send ACK frame - structlog.get_logger("structlog").info("[TNC] ARQ | RX | SENDING ACK") + self.log.info("[TNC] ARQ | RX | SENDING ACK") self.send_burst_ack_frame(snr) # Reset n retries per burst counter @@ -541,15 +541,15 @@ class DATA: # Check if we received last frame of burst - this is an indicator for missed frames. # With this way of doing this, we always MUST receive the last frame of a burst otherwise the entire # burst is lost - structlog.get_logger("structlog").debug("[TNC] all frames in burst received:", frame=RX_N_FRAME_OF_BURST, - frames=RX_N_FRAMES_PER_BURST) + self.log.debug("[TNC] all frames in burst received:", frame=RX_N_FRAME_OF_BURST, + frames=RX_N_FRAMES_PER_BURST) self.send_retransmit_request_frame(freedv) self.calculate_transfer_rate_rx(self.rx_start_of_transmission, len(static.RX_FRAME_BUFFER)) # Should never reach this point else: - structlog.get_logger("structlog").error("[TNC] data_handler: Should not reach this point...", - frame=RX_N_FRAME_OF_BURST, frames=RX_N_FRAMES_PER_BURST) + self.log.error("[TNC] data_handler: Should not reach this point...", + frame=RX_N_FRAME_OF_BURST, frames=RX_N_FRAMES_PER_BURST) # 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 @@ -569,8 +569,8 @@ class DATA: self.calculate_transfer_rate_rx(self.rx_start_of_transmission, len(static.RX_FRAME_BUFFER)) if bof_position >= 0 and eof_position > 0 and None not in static.RX_BURST_BUFFER: - structlog.get_logger("structlog").debug("[TNC] arq_data_received:", bof_position=bof_position, - eof_position=eof_position) + self.log.debug("[TNC] arq_data_received:", bof_position=bof_position, + eof_position=eof_position) # print(f"bof_position {bof_position} / eof_position {eof_position}") self.rx_frame_bof_received = True self.rx_frame_eof_received = True @@ -589,7 +589,7 @@ class DATA: # Check if data_frame_crc is equal with received crc if data_frame_crc == data_frame_crc_received: - structlog.get_logger("structlog").info("[TNC] ARQ | RX | DATA FRAME SUCESSFULLY RECEIVED") + self.log.info("[TNC] ARQ | RX | DATA FRAME SUCESSFULLY RECEIVED") # Decompress the data frame data_frame_decompressed = zlib.decompress(data_frame) @@ -611,31 +611,31 @@ class DATA: base64_data = base64.b64encode(data_frame).decode("utf-8") static.RX_BUFFER.append([uniqueid, timestamp, static.DXCALLSIGN, static.DXGRID, base64_data]) jsondata = {"arq": "received", "uuid": uniqueid, "timestamp": timestamp, - "mycallsign": str(mycallsign, "utf-8"), "dxcallsign": str(static.DXCALLSIGN, "utf-8"), + "mycallsign": str(mycallsign, "utf-8"), + "dxcallsign": str(static.DXCALLSIGN, "utf-8"), "dxgrid": str(static.DXGRID, "utf-8"), "data": base64_data} json_data_out = json.dumps(jsondata) - structlog.get_logger("structlog").debug("[TNC] arq_data_received:", jsondata=jsondata) + self.log.debug("[TNC] arq_data_received:", jsondata=jsondata) sock.SOCKET_QUEUE.put(json_data_out) static.INFO.append("ARQ;RECEIVING;SUCCESS") - structlog.get_logger("structlog").info("[TNC] ARQ | RX | SENDING DATA FRAME ACK", snr=snr, - crc=data_frame_crc.hex()) + self.log.info("[TNC] ARQ | RX | SENDING DATA FRAME ACK", snr=snr, + crc=data_frame_crc.hex()) self.send_data_ack_frame(snr) # update our statistics AFTER the frame ACK self.calculate_transfer_rate_rx(self.rx_start_of_transmission, len(static.RX_FRAME_BUFFER)) - structlog.get_logger("structlog").info("[TNC] | RX | DATACHANNEL [" + - str(self.mycallsign, "utf-8") + "]<< >>[" + str( - static.DXCALLSIGN, "utf-8") + "]", snr=snr) + self.log.info("[TNC] | RX | DATACHANNEL [" + str(self.mycallsign, "utf-8") + + "]<< >>[" + str(static.DXCALLSIGN, "utf-8") + "]", snr=snr) else: static.INFO.append("ARQ;RECEIVING;FAILED") - structlog.get_logger("structlog").warning("[TNC] ARQ | RX | DATA FRAME NOT SUCESSFULLY RECEIVED!", - e="wrong crc", expected=data_frame_crc, - received=data_frame_crc_received, - overflows=static.BUFFER_OVERFLOW_COUNTER) + self.log.warning("[TNC] ARQ | RX | DATA FRAME NOT SUCESSFULLY RECEIVED!", + e="wrong crc", expected=data_frame_crc, + received=data_frame_crc_received, + overflows=static.BUFFER_OVERFLOW_COUNTER) - structlog.get_logger("structlog").info("[TNC] ARQ | RX | Sending NACK") + self.log.info("[TNC] ARQ | RX | Sending NACK") self.send_burst_nack_frame(snr) # update session timeout @@ -684,7 +684,7 @@ class DATA: json_data_out = json.dumps(jsondata) sock.SOCKET_QUEUE.put(json_data_out) - structlog.get_logger("structlog").info("[TNC] | TX | DATACHANNEL", mode=mode, Bytes=static.TOTAL_BYTES) + self.log.info("[TNC] | TX | DATACHANNEL", mode=mode, Bytes=static.TOTAL_BYTES) # Compress data frame data_frame_compressed = zlib.compress(data_out) @@ -700,7 +700,7 @@ class DATA: # Append a crc and the begin and end of file indicators frame_payload_crc = helpers.get_crc_32(data_out) - structlog.get_logger("structlog").debug("[TNC] frame payload CRC:", crc=frame_payload_crc) + self.log.debug("[TNC] frame payload CRC:", crc=frame_payload_crc) # data_out = self.data_frame_bof + frame_payload_crc + data_out + self.data_frame_eof data_out = self.data_frame_bof + frame_payload_crc + frame_total_size + compression_factor + data_out + self.data_frame_eof @@ -718,7 +718,7 @@ class DATA: # force usage of selected mode if mode != 255: data_mode = mode - structlog.get_logger("structlog").debug("[TNC] FIXED MODE:", mode=data_mode) + self.log.debug("[TNC] FIXED MODE:", mode=data_mode) else: # we are doing a modulo check of transmission retries of the actual burst # every 2nd retry which fails, decreases speedlevel by 1. @@ -745,8 +745,8 @@ class DATA: static.ARQ_SPEED_LEVEL = self.speed_level data_mode = self.mode_list[self.speed_level] - structlog.get_logger("structlog").debug("[TNC] Speed-level:", level=self.speed_level, - retry=self.tx_n_retry_of_burst, mode=data_mode) + self.log.debug("[TNC] Speed-level:", level=self.speed_level, + retry=self.tx_n_retry_of_burst, mode=data_mode) # payload information payload_per_frame = modem.get_bytes_per_frame(data_mode) - 2 @@ -784,9 +784,9 @@ class DATA: # append frame to tempbuffer for transmission tempbuffer.append(frame) - structlog.get_logger("structlog").debug("[TNC] tempbuffer:", tempbuffer=tempbuffer) - structlog.get_logger("structlog").info("[TNC] ARQ | TX | FRAMES", mode=data_mode, - fpb=TX_N_FRAMES_PER_BURST, retry=self.tx_n_retry_of_burst) + self.log.debug("[TNC] tempbuffer:", tempbuffer=tempbuffer) + self.log.info("[TNC] ARQ | TX | FRAMES", mode=data_mode, + fpb=TX_N_FRAMES_PER_BURST, retry=self.tx_n_retry_of_burst) # we need to set our TRANSMITTING flag before we are adding an object the transmit queue # this is not that nice, we could improve this somehow @@ -833,9 +833,8 @@ class DATA: self.calculate_transfer_rate_tx(tx_start_of_transmission, bufferposition_end, len(data_out)) # NEXT ATTEMPT - structlog.get_logger("structlog").debug("[TNC] ATTEMPT:", retry=self.tx_n_retry_of_burst, - maxretries=TX_N_MAX_RETRIES_PER_BURST, - overflows=static.BUFFER_OVERFLOW_COUNTER) + self.log.debug("[TNC] ATTEMPT:", retry=self.tx_n_retry_of_burst, + maxretries=TX_N_MAX_RETRIES_PER_BURST, overflows=static.BUFFER_OVERFLOW_COUNTER) # update buffer position bufferposition = bufferposition_end @@ -844,7 +843,7 @@ class DATA: self.calculate_transfer_rate_tx(tx_start_of_transmission, bufferposition_end, len(data_out)) jsondata = {"arq": "transmission", "status": "transmitting", "uuid": self.transmission_uuid, - "percent": static.ARQ_TRANSMISSION_PERCENT, "bytesperminute": static.ARQ_BYTES_PER_MINUTE} + "percent": static.ARQ_TRANSMISSION_PERCENT, "bytesperminute": static.ARQ_BYTES_PER_MINUTE} json_data_out = json.dumps(jsondata) sock.SOCKET_QUEUE.put(json_data_out) @@ -853,24 +852,24 @@ class DATA: if self.data_frame_ack_received: static.INFO.append("ARQ;TRANSMITTING;SUCCESS") jsondata = {"arq": "transmission", "status": "success", "uuid": self.transmission_uuid, - "percent": static.ARQ_TRANSMISSION_PERCENT, "bytesperminute": static.ARQ_BYTES_PER_MINUTE} + "percent": static.ARQ_TRANSMISSION_PERCENT, "bytesperminute": static.ARQ_BYTES_PER_MINUTE} json_data_out = json.dumps(jsondata) sock.SOCKET_QUEUE.put(json_data_out) - structlog.get_logger("structlog").info("[TNC] ARQ | TX | DATA TRANSMITTED!", - BytesPerMinute=static.ARQ_BYTES_PER_MINUTE, - BitsPerSecond=static.ARQ_BITS_PER_SECOND, - overflows=static.BUFFER_OVERFLOW_COUNTER) + self.log.info("[TNC] ARQ | TX | DATA TRANSMITTED!", + BytesPerMinute=static.ARQ_BYTES_PER_MINUTE, BitsPerSecond=static.ARQ_BITS_PER_SECOND, + overflows=static.BUFFER_OVERFLOW_COUNTER) else: static.INFO.append("ARQ;TRANSMITTING;FAILED") jsondata = {"arq": "transmission", "status": "failed", "uuid": self.transmission_uuid, - "percent": static.ARQ_TRANSMISSION_PERCENT, "bytesperminute": static.ARQ_BYTES_PER_MINUTE} + "percent": static.ARQ_TRANSMISSION_PERCENT, + "bytesperminute": static.ARQ_BYTES_PER_MINUTE} json_data_out = json.dumps(jsondata) sock.SOCKET_QUEUE.put(json_data_out) - structlog.get_logger("structlog").info("[TNC] ARQ | TX | TRANSMISSION FAILED OR TIME OUT!", - overflows=static.BUFFER_OVERFLOW_COUNTER) + self.log.info("[TNC] ARQ | TX | TRANSMISSION FAILED OR TIME OUT!", + overflows=static.BUFFER_OVERFLOW_COUNTER) self.stop_transmission() # and last but not least doing a state cleanup @@ -905,8 +904,8 @@ class DATA: self.burst_ack_snr = int.from_bytes(bytes(data_in[7:8]), "big") self.speed_level = int.from_bytes(bytes(data_in[8:9]), "big") static.ARQ_SPEED_LEVEL = self.speed_level - structlog.get_logger("structlog").debug("[TNC] burst_ack_received:", speed_level=self.speed_level) - # print(self.speed_level) + self.log.debug("[TNC] burst_ack_received:", speed_level=self.speed_level) + # reset burst nack counter self.burst_nack_counter = 0 # reset n retries per burst counter @@ -919,8 +918,6 @@ class DATA: Args: data_in:bytes: - Returns: - """ # increase speed level if we received a burst ack # self.speed_level += 1 @@ -937,8 +934,7 @@ class DATA: self.speed_level = int.from_bytes(bytes(data_in[8:9]), "big") static.ARQ_SPEED_LEVEL = self.speed_level self.burst_nack_counter += 1 - structlog.get_logger("structlog").debug("[TNC] burst_nack_received:", speed_level=self.speed_level) - # print(self.speed_level) + self.log.debug("[TNC] burst_nack_received:", speed_level=self.speed_level) def frame_ack_received(self): """ """ @@ -946,9 +942,11 @@ class DATA: if static.ARQ_STATE: helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "DATA-CHANNEL", static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) - self.data_frame_ack_received = True # Force data loops of TNC to stop and continue with next frame - self.data_channel_last_received = int(time.time()) # we need to update our timeout timestamp - self.arq_session_last_received = int(time.time()) # we need to update our timeout timestamp + # Force data loops of TNC to stop and continue with next frame + self.data_frame_ack_received = True + # Update timeout timestamps + self.data_channel_last_received = int(time.time()) + self.arq_session_last_received = int(time.time()) def frame_nack_received(self, data_in: bytes): # pylint: disable=unused-argument """ @@ -959,8 +957,8 @@ class DATA: Returns: """ - helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "DATA-CHANNEL", static.SNR, static.FREQ_OFFSET, - static.HAMLIB_FREQUENCY) + helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "DATA-CHANNEL", + static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) static.INFO.append("ARQ;TRANSMITTING;FAILED") jsondata = {"arq": "transmission", "status": "failed", "uuid": self.transmission_uuid, "percent": static.ARQ_TRANSMISSION_PERCENT, "bytesperminute": static.ARQ_BYTES_PER_MINUTE} @@ -1010,8 +1008,9 @@ class DATA: """ # TODO: we need to check this, maybe placing it to class init self.datachannel_timeout = False - structlog.get_logger("structlog").info( - "[TNC] SESSION [" + str(self.mycallsign, "utf-8") + "]>> <<[" + str(static.DXCALLSIGN, "utf-8") + "]", + self.log.info( + "[TNC] SESSION [" + str(self.mycallsign, "utf-8") + + "]>> <<[" + str(static.DXCALLSIGN, "utf-8") + "]", state=static.ARQ_SESSION_STATE) self.open_session(callsign) @@ -1049,10 +1048,10 @@ class DATA: while not static.ARQ_SESSION: time.sleep(0.01) for attempt in range(1, self.session_connect_max_retries + 1): - structlog.get_logger("structlog").info( - "[TNC] SESSION [" + str(self.mycallsign, "utf-8") + "]>>?<<[" + str(static.DXCALLSIGN, - "utf-8") + "]", a=attempt, - state=static.ARQ_SESSION_STATE) + self.log.info( + "[TNC] SESSION [" + str(self.mycallsign, "utf-8") + + "]>>?<<[" + str(static.DXCALLSIGN, "utf-8") + "]", + a=attempt, state=static.ARQ_SESSION_STATE) self.enqueue_frame_for_tx(connection_frame) @@ -1089,10 +1088,11 @@ class DATA: static.DXCALLSIGN_CRC = bytes(data_in[4:7]) static.DXCALLSIGN = helpers.bytes_to_callsign(bytes(data_in[7:13])) - helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "DATA-CHANNEL", static.SNR, static.FREQ_OFFSET, - static.HAMLIB_FREQUENCY) - structlog.get_logger("structlog").info( - "[TNC] SESSION [" + str(self.mycallsign, "utf-8") + "]>>|<<[" + str(static.DXCALLSIGN, "utf-8") + "]", + helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "DATA-CHANNEL", + static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) + self.log.info( + "[TNC] SESSION [" + str(self.mycallsign, "utf-8") + + "]>>|<<[" + str(static.DXCALLSIGN, "utf-8") + "]", state=static.ARQ_SESSION_STATE) static.ARQ_SESSION = True static.TNC_STATE = "BUSY" @@ -1102,10 +1102,11 @@ class DATA: def close_session(self): """ Close the ARQ session """ static.ARQ_SESSION_STATE = "disconnecting" - helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "DATA-CHANNEL", static.SNR, static.FREQ_OFFSET, - static.HAMLIB_FREQUENCY) - structlog.get_logger("structlog").info( - "[TNC] SESSION [" + str(self.mycallsign, "utf-8") + "]<>[" + str(static.DXCALLSIGN, "utf-8") + "]", + helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "DATA-CHANNEL", + static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) + self.log.info( + "[TNC] SESSION [" + str(self.mycallsign, "utf-8") + + "]<>[" + str(static.DXCALLSIGN, "utf-8") + "]", state=static.ARQ_SESSION_STATE) static.INFO.append("ARQ;SESSION;CLOSE") self.IS_ARQ_SESSION_MASTER = False @@ -1131,8 +1132,9 @@ class DATA: static.ARQ_SESSION_STATE = "disconnected" helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "DATA-CHANNEL", static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) - structlog.get_logger("structlog").info( - "[TNC] SESSION [" + str(self.mycallsign, "utf-8") + "]<>[" + str(static.DXCALLSIGN, "utf-8") + "]", + self.log.info( + "[TNC] SESSION [" + str(self.mycallsign, "utf-8") + + "]<>[" + str(static.DXCALLSIGN, "utf-8") + "]", state=static.ARQ_SESSION_STATE) static.INFO.append("ARQ;SESSION;CLOSE") @@ -1165,7 +1167,7 @@ class DATA: # Accept session data if the DXCALLSIGN_CRC matches the station in static. _valid_crc, _ = helpers.check_callsign(static.DXCALLSIGN, bytes(data_in[4:7])) if _valid_crc: - structlog.get_logger("structlog").debug("[TNC] Received session heartbeat") + self.log.debug("[TNC] Received session heartbeat") helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "SESSION-HB", static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) @@ -1238,14 +1240,14 @@ class DATA: if static.LOW_BANDWITH_MODE and mode == 255: frametype = bytes([227]) - structlog.get_logger("structlog").debug("[TNC] Requesting low bandwidth mode") + self.log.debug("[TNC] Requesting low bandwidth mode") else: frametype = bytes([225]) - structlog.get_logger("structlog").debug("[TNC] Requesting high bandwidth mode") + self.log.debug("[TNC] Requesting high bandwidth mode") if 230 <= mode <= 240: - structlog.get_logger("structlog").debug("[TNC] Requesting manual mode --> not yet implemented ") + self.log.debug("[TNC] Requesting manual mode --> not yet implemented ") frametype = bytes([mode]) connection_frame = bytearray(14) @@ -1259,9 +1261,9 @@ class DATA: time.sleep(0.01) for attempt in range(1, self.data_channel_max_retries + 1): static.INFO.append("DATACHANNEL;OPENING") - structlog.get_logger("structlog").info( - "[TNC] ARQ | DATA | TX | [" + str(mycallsign, "utf-8") + "]>> <<[" + str(static.DXCALLSIGN, - "utf-8") + "]", + self.log.info( + "[TNC] ARQ | DATA | TX | [" + str(mycallsign, "utf-8") + + "]>> <<[" + str(static.DXCALLSIGN, "utf-8") + "]", attempt=f"{str(attempt)}/{str(self.data_channel_max_retries)}") self.enqueue_frame_for_tx(connection_frame) @@ -1279,8 +1281,8 @@ class DATA: if attempt == self.data_channel_max_retries: static.INFO.append("DATACHANNEL;FAILED") - structlog.get_logger("structlog").debug("[TNC] arq_open_data_channel:", - transmission_uuid=self.transmission_uuid) + self.log.debug("[TNC] arq_open_data_channel:", + transmission_uuid=self.transmission_uuid) # print(self.transmission_uuid) jsondata = {"arq": "transmission", "status": "failed", "uuid": self.transmission_uuid, "percent": static.ARQ_TRANSMISSION_PERCENT, @@ -1288,9 +1290,10 @@ class DATA: json_data_out = json.dumps(jsondata) sock.SOCKET_QUEUE.put(json_data_out) - structlog.get_logger("structlog").warning( - "[TNC] ARQ | TX | DATA [" + str(mycallsign, "utf-8") + "]>>X<<[" + str(static.DXCALLSIGN, - "utf-8") + "]") + self.log.warning( + "[TNC] ARQ | TX | DATA [" + str(mycallsign, "utf-8") + + "]>>X<<[" + str(static.DXCALLSIGN, "utf-8") + "]" + ) self.datachannel_timeout = True if not TESTMODE: self.arq_cleanup() @@ -1307,8 +1310,6 @@ class DATA: Args: data_in:bytes: - Returns: - """ self.arq_file_transfer = True self.is_IRS = True @@ -1330,14 +1331,13 @@ class DATA: self.speed_level = len(self.mode_list) - 1 if 230 <= frametype <= 240: - structlog.get_logger("structlog").debug("[TNC] arq_received_data_channel_opener: manual mode request") - # print("manual mode request") + self.log.debug("[TNC] arq_received_data_channel_opener: manual mode request") # updated modes we are listening to self.set_listening_modes(self.mode_list[self.speed_level]) - helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "DATA-CHANNEL", static.SNR, static.FREQ_OFFSET, - static.HAMLIB_FREQUENCY) + helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "DATA-CHANNEL", + static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) # check if callsign ssid override valid, mycallsign = helpers.check_callsign(self.mycallsign, data_in[1:4]) @@ -1347,8 +1347,9 @@ class DATA: self.arq_cleanup() return - structlog.get_logger("structlog").info( - "[TNC] ARQ | DATA | RX | [" + str(mycallsign, "utf-8") + "]>> <<[" + str(static.DXCALLSIGN, "utf-8") + "]", + self.log.info( + "[TNC] ARQ | DATA | RX | [" + str(mycallsign, "utf-8") + + "]>> <<[" + str(static.DXCALLSIGN, "utf-8") + "]", bandwith="wide") static.ARQ_STATE = True @@ -1360,10 +1361,10 @@ class DATA: # check if we are in low bandwith mode if static.LOW_BANDWITH_MODE or self.received_low_bandwith_mode: frametype = bytes([228]) - structlog.get_logger("structlog").debug("[TNC] Responding with low bandwidth mode") + self.log.debug("[TNC] Responding with low bandwidth mode") else: frametype = bytes([226]) - structlog.get_logger("structlog").debug("[TNC] Responding with high bandwidth mode") + self.log.debug("[TNC] Responding with high bandwidth mode") connection_frame = bytearray(14) connection_frame[:1] = frametype @@ -1373,8 +1374,9 @@ class DATA: self.enqueue_frame_for_tx(connection_frame) - structlog.get_logger("structlog").info( - "[TNC] ARQ | DATA | RX | [" + str(mycallsign, "utf-8") + "]>>|<<[" + str(static.DXCALLSIGN, "utf-8") + "]", + self.log.info( + "[TNC] ARQ | DATA | RX | [" + str(mycallsign, "utf-8") + + "]>>|<<[" + str(static.DXCALLSIGN, "utf-8") + "]", bandwith="wide", snr=static.SNR) # set start of transmission for our statistics @@ -1402,20 +1404,20 @@ class DATA: self.mode_list = self.mode_list_low_bw self.time_list = self.time_list_low_bw self.speed_level = len(self.mode_list) - 1 - structlog.get_logger("structlog").debug("[TNC] low bandwidth mode", modes=self.mode_list) + self.log.debug("[TNC] low bandwidth mode", modes=self.mode_list) else: self.received_low_bandwith_mode = False self.mode_list = self.mode_list_high_bw self.time_list = self.time_list_high_bw self.speed_level = len(self.mode_list) - 1 - structlog.get_logger("structlog").debug("[TNC] high bandwidth mode", modes=self.mode_list) + self.log.debug("[TNC] high bandwidth mode", modes=self.mode_list) helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "DATA-CHANNEL", static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) - structlog.get_logger("structlog").info( - "[TNC] ARQ | DATA | TX | [" + str(self.mycallsign, "utf-8") + "]>>|<<[" + str(static.DXCALLSIGN, - "utf-8") + "]", + self.log.info( + "[TNC] ARQ | DATA | TX | [" + str(self.mycallsign, "utf-8") + + "]>>|<<[" + str(static.DXCALLSIGN, "utf-8") + "]", snr=static.SNR) # as soon as we set ARQ_STATE to DATA, transmission starts @@ -1425,8 +1427,8 @@ class DATA: static.TNC_STATE = "IDLE" static.ARQ_STATE = False static.INFO.append("PROTOCOL;VERSION_MISMATCH") - structlog.get_logger("structlog").warning("[TNC] protocol version mismatch:", received=protocol_version, - own=static.ARQ_PROTOCOL_VERSION) + self.log.warning("[TNC] protocol version mismatch:", + received=protocol_version, own=static.ARQ_PROTOCOL_VERSION) self.arq_cleanup() # ---------- PING @@ -1443,8 +1445,9 @@ class DATA: static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN) static.INFO.append("PING;SENDING") - structlog.get_logger("structlog").info( - "[TNC] PING REQ [" + str(self.mycallsign, "utf-8") + "] >>> [" + str(static.DXCALLSIGN, "utf-8") + "]") + self.log.info( + "[TNC] PING REQ [" + str(self.mycallsign, "utf-8") + + "] >>> [" + str(static.DXCALLSIGN, "utf-8") + "]") ping_frame = bytearray(14) ping_frame[:1] = bytes([210]) @@ -1452,7 +1455,7 @@ class DATA: ping_frame[4:7] = static.MYCALLSIGN_CRC ping_frame[7:13] = helpers.callsign_to_bytes(self.mycallsign) - structlog.get_logger("structlog").info("[TNC] ENABLE FSK", state=static.ENABLE_FSK) + self.log.info("[TNC] ENABLE FSK", state=static.ENABLE_FSK) if static.ENABLE_FSK: self.enqueue_frame_for_tx(ping_frame, c2_mode=codec2.freedv_get_mode_value_by_name("FSK_LDPC_0")) else: @@ -1470,8 +1473,8 @@ class DATA: """ static.DXCALLSIGN_CRC = bytes(data_in[4:7]) static.DXCALLSIGN = helpers.bytes_to_callsign(bytes(data_in[7:13])) - helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "PING", static.SNR, static.FREQ_OFFSET, - static.HAMLIB_FREQUENCY) + helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "PING", static.SNR, + static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) static.INFO.append("PING;RECEIVING") @@ -1479,12 +1482,12 @@ class DATA: valid, mycallsign = helpers.check_callsign(self.mycallsign, data_in[1:4]) if not valid: # PING packet not for me. - structlog.get_logger("structlog").debug("[TNC] received_ping: ping not for this station.") - # print("ping not for me...") + self.log.debug("[TNC] received_ping: ping not for this station.") return - structlog.get_logger("structlog").info( - "[TNC] PING REQ [" + str(mycallsign, "utf-8") + "] <<< [" + str(static.DXCALLSIGN, "utf-8") + "]", + self.log.info( + "[TNC] PING REQ [" + str(mycallsign, "utf-8") + + "] <<< [" + str(static.DXCALLSIGN, "utf-8") + "]", snr=static.SNR) ping_frame = bytearray(14) @@ -1493,7 +1496,7 @@ class DATA: ping_frame[4:7] = static.MYCALLSIGN_CRC ping_frame[7:13] = static.MYGRID - structlog.get_logger("structlog").info("[TNC] ENABLE FSK", state=static.ENABLE_FSK) + self.log.info("[TNC] ENABLE FSK", state=static.ENABLE_FSK) if static.ENABLE_FSK: self.enqueue_frame_for_tx(ping_frame, c2_mode=codec2.freedv_get_mode_value_by_name("FSK_LDPC_0")) else: @@ -1511,19 +1514,21 @@ class DATA: static.DXCALLSIGN_CRC = bytes(data_in[4:7]) static.DXGRID = bytes(data_in[7:13]).rstrip(b"\x00") - jsondata = {"type": "ping", "status": "ack", "uuid": str(uuid.uuid4()), "timestamp": int(time.time()), - "mycallsign": str(self.mycallsign, "utf-8"), "dxcallsign": str(static.DXCALLSIGN, "utf-8"), - "dxgrid": str(static.DXGRID, "utf-8"), "snr": str(static.SNR)} + jsondata = {"type": "ping", "status": "ack", "uuid": str(uuid.uuid4()), + "timestamp": int(time.time()), "mycallsign": str(self.mycallsign, "utf-8"), + "dxcallsign": str(static.DXCALLSIGN, "utf-8"), "dxgrid": str(static.DXGRID, "utf-8"), + "snr": str(static.SNR)} json_data_out = json.dumps(jsondata) sock.SOCKET_QUEUE.put(json_data_out) - helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "PING-ACK", static.SNR, static.FREQ_OFFSET, - static.HAMLIB_FREQUENCY) + helpers.add_to_heard_stations(static.DXCALLSIGN, static.DXGRID, "PING-ACK", + static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) static.INFO.append("PING;RECEIVEDACK") - structlog.get_logger("structlog").info( - "[TNC] PING ACK [" + str(self.mycallsign, "utf-8") + "] >|< [" + str(static.DXCALLSIGN, "utf-8") + "]", + self.log.info( + "[TNC] PING ACK [" + str(self.mycallsign, "utf-8") + + "] >|< [" + str(static.DXCALLSIGN, "utf-8") + "]", snr=static.SNR) static.TNC_STATE = "IDLE" @@ -1531,7 +1536,7 @@ class DATA: """ Force a stop of the running transmission """ - structlog.get_logger("structlog").warning("[TNC] Stopping transmission!") + self.log.warning("[TNC] Stopping transmission!") stop_frame = bytearray(14) stop_frame[:1] = bytes([249]) stop_frame[1:4] = static.DXCALLSIGN_CRC @@ -1549,7 +1554,7 @@ class DATA: """ Received a transmission stop """ - structlog.get_logger("structlog").warning("[TNC] Stopping transmission!") + self.log.warning("[TNC] Stopping transmission!") static.TNC_STATE = "IDLE" static.ARQ_STATE = False static.INFO.append("TRANSMISSION;STOPPED") @@ -1567,18 +1572,18 @@ class DATA: """ try: - while 1: + while True: time.sleep(0.5) while static.BEACON_STATE: if not static.ARQ_SESSION and not self.arq_file_transfer and not static.BEACON_PAUSE: static.INFO.append("BEACON;SENDING") - structlog.get_logger("structlog").info("[TNC] Sending beacon!", interval=self.beacon_interval) + self.log.info("[TNC] Sending beacon!", interval=self.beacon_interval) beacon_frame = bytearray(14) beacon_frame[:1] = bytes([250]) beacon_frame[1:7] = helpers.callsign_to_bytes(self.mycallsign) beacon_frame[9:13] = static.MYGRID[:4] - structlog.get_logger("structlog").info("[TNC] ENABLE FSK", state=static.ENABLE_FSK) + self.log.info("[TNC] ENABLE FSK", state=static.ENABLE_FSK) if static.ENABLE_FSK: self.enqueue_frame_for_tx(beacon_frame, c2_mode=codec2.freedv_get_mode_value_by_name("FSK_LDPC_0")) @@ -1590,8 +1595,7 @@ class DATA: time.sleep(0.01) except Exception as err: - structlog.get_logger("structlog").debug("[TNC] run_beacon: ", exception=err) - # print(e) + self.log.debug("[TNC] run_beacon: ", exception=err) def received_beacon(self, data_in: bytes): """ @@ -1606,15 +1610,17 @@ class DATA: dxcallsign = helpers.bytes_to_callsign(bytes(data_in[1:7])) dxgrid = bytes(data_in[9:13]).rstrip(b"\x00") - jsondata = {"type": "beacon", "status": "received", "uuid": str(uuid.uuid4()), "timestamp": int(time.time()), - "mycallsign": str(self.mycallsign, "utf-8"), "dxcallsign": str(dxcallsign, "utf-8"), - "dxgrid": str(dxgrid, "utf-8"), "snr": str(static.SNR)} + jsondata = {"type": "beacon", "status": "received", "uuid": str(uuid.uuid4()), + "timestamp": int(time.time()), "mycallsign": str(self.mycallsign, "utf-8"), + "dxcallsign": str(dxcallsign, "utf-8"), "dxgrid": str(dxgrid, "utf-8"), + "snr": str(static.SNR)} json_data_out = json.dumps(jsondata) sock.SOCKET_QUEUE.put(json_data_out) static.INFO.append("BEACON;RECEIVING") - structlog.get_logger("structlog").info( - "[TNC] BEACON RCVD [" + str(dxcallsign, "utf-8") + "][" + str(dxgrid, "utf-8") + "] ", snr=static.SNR) + self.log.info( + "[TNC] BEACON RCVD [" + str(dxcallsign, "utf-8") + "][" + + str(dxgrid, "utf-8") + "] ", snr=static.SNR) helpers.add_to_heard_stations(dxcallsign, dxgrid, "BEACON", static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) @@ -1627,7 +1633,7 @@ class DATA: Returns: Nothing """ - structlog.get_logger("structlog").info("[TNC] CQ CQ CQ") + self.log.info("[TNC] CQ CQ CQ") static.INFO.append("CQ;SENDING") cq_frame = bytearray(14) @@ -1635,8 +1641,8 @@ class DATA: cq_frame[1:7] = helpers.callsign_to_bytes(self.mycallsign) cq_frame[7:11] = helpers.encode_grid(static.MYGRID.decode("utf-8")) - structlog.get_logger("structlog").info("[TNC] ENABLE FSK", state=static.ENABLE_FSK) - structlog.get_logger("structlog").debug("[TNC] CQ Frame:", data=[cq_frame]) + self.log.info("[TNC] ENABLE FSK", state=static.ENABLE_FSK) + self.log.debug("[TNC] CQ Frame:", data=[cq_frame]) if static.ENABLE_FSK: self.enqueue_frame_for_tx(cq_frame, c2_mode=codec2.freedv_get_mode_value_by_name("FSK_LDPC_0")) @@ -1654,12 +1660,13 @@ class DATA: """ # here we add the received station to the heard stations buffer dxcallsign = helpers.bytes_to_callsign(bytes(data_in[1:7])) - structlog.get_logger("structlog").debug("[TNC] received_cq:", dxcallsign=dxcallsign) - # print(dxcallsign) + self.log.debug("[TNC] received_cq:", dxcallsign=dxcallsign) + dxgrid = bytes(helpers.decode_grid(data_in[7:11]), "utf-8") static.INFO.append("CQ;RECEIVING") - structlog.get_logger("structlog").info( - "[TNC] CQ RCVD [" + str(dxcallsign, "utf-8") + "][" + str(dxgrid, "utf-8") + "] ", snr=static.SNR) + self.log.info( + "[TNC] CQ RCVD [" + str(dxcallsign, "utf-8") + "][" + + str(dxgrid, "utf-8") + "] ", snr=static.SNR) helpers.add_to_heard_stations(dxcallsign, dxgrid, "CQ CQ CQ", static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) @@ -1681,14 +1688,14 @@ class DATA: # in 0.5s increments. helpers.wait(randrange(0, 20, 5) / 10.0) static.INFO.append("QRV;SENDING") - structlog.get_logger("structlog").info("[TNC] Sending QRV!") + self.log.info("[TNC] Sending QRV!") qrv_frame = bytearray(14) qrv_frame[:1] = bytes([201]) qrv_frame[1:7] = helpers.callsign_to_bytes(self.mycallsign) qrv_frame[7:11] = helpers.encode_grid(static.MYGRID.decode("utf-8")) - structlog.get_logger("structlog").info("[TNC] ENABLE FSK", state=static.ENABLE_FSK) + self.log.info("[TNC] ENABLE FSK", state=static.ENABLE_FSK) if static.ENABLE_FSK: self.enqueue_frame_for_tx(qrv_frame, c2_mode=codec2.freedv_get_mode_value_by_name("FSK_LDPC_0")) @@ -1708,15 +1715,17 @@ class DATA: dxcallsign = helpers.bytes_to_callsign(bytes(data_in[1:7])) dxgrid = bytes(helpers.decode_grid(data_in[7:11]), "utf-8") - jsondata = {"type": "qrv", "status": "received", "uuid": str(uuid.uuid4()), "timestamp": int(time.time()), - "mycallsign": str(self.mycallsign, "utf-8"), "dxcallsign": str(dxcallsign, "utf-8"), - "dxgrid": str(dxgrid, "utf-8"), "snr": str(static.SNR)} + jsondata = {"type": "qrv", "status": "received", "uuid": str(uuid.uuid4()), + "timestamp": int(time.time()), "mycallsign": str(self.mycallsign, "utf-8"), + "dxcallsign": str(dxcallsign, "utf-8"), "dxgrid": str(dxgrid, "utf-8"), + "snr": str(static.SNR)} json_data_out = json.dumps(jsondata) sock.SOCKET_QUEUE.put(json_data_out) static.INFO.append("QRV;RECEIVING") - structlog.get_logger("structlog").info( - "[TNC] QRV RCVD [" + str(dxcallsign, "utf-8") + "][" + str(dxgrid, "utf-8") + "] ", snr=static.SNR) + self.log.info( + "[TNC] QRV RCVD [" + str(dxcallsign, "utf-8") + "][" + + str(dxgrid, "utf-8") + "] ", snr=static.SNR) helpers.add_to_heard_stations(dxcallsign, dxgrid, "QRV", static.SNR, static.FREQ_OFFSET, static.HAMLIB_FREQUENCY) @@ -1749,7 +1758,7 @@ class DATA: static.ARQ_BITS_PER_SECOND = 0 static.ARQ_BYTES_PER_MINUTE = 0 except Exception as err: - structlog.get_logger("structlog").error(f"[TNC] calculate_transfer_rate_rx: Exception: {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 @@ -1796,7 +1805,7 @@ class DATA: static.ARQ_BYTES_PER_MINUTE = 0 except Exception as err: - structlog.get_logger("structlog").error(f"[TNC] calculate_transfer_rate_tx: Exception: {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 @@ -1810,7 +1819,7 @@ class DATA: """ Cleanup funktion which clears all ARQ states """ - structlog.get_logger("structlog").debug("[TNC] arq_cleanup") + self.log.debug("[TNC] arq_cleanup") self.received_mycall_crc = b"" @@ -1881,18 +1890,18 @@ class DATA: if mode_name == "datac1": modem.RECEIVE_DATAC1 = True - structlog.get_logger("structlog").debug("[TNC] Changing listening data mode", mode="datac1") + self.log.debug("[TNC] Changing listening data mode", mode="datac1") elif mode_name == "datac3": modem.RECEIVE_DATAC3 = True - structlog.get_logger("structlog").debug("[TNC] Changing listening data mode", mode="datac3") + self.log.debug("[TNC] Changing listening data mode", mode="datac3") elif mode_name == "fsk_ldpc_1": modem.RECEIVE_FSK_LDPC_1 = True - structlog.get_logger("structlog").debug("[TNC] Changing listening data mode", mode="fsk_ldpc_1") + self.log.debug("[TNC] Changing listening data mode", mode="fsk_ldpc_1") elif mode_name == "allmodes": modem.RECEIVE_DATAC1 = True modem.RECEIVE_DATAC3 = True modem.RECEIVE_FSK_LDPC_1 = True - structlog.get_logger("structlog").debug("[TNC] Changing listening data mode", mode="datac1/datac3/fsk_ldpc") + self.log.debug("[TNC] Changing listening data mode", mode="datac1/datac3/fsk_ldpc") # ------------------------- WATCHDOG FUNCTIONS FOR TIMER def watchdog(self): @@ -1926,9 +1935,8 @@ class DATA: # print((self.data_channel_last_received + self.time_list[self.speed_level])-time.time()) pass else: - structlog.get_logger("structlog").warning("[TNC] Frame timeout", attempt=self.n_retries_per_burst, - max_attempts=self.rx_n_max_retries_per_burst, - speed_level=self.speed_level) + self.log.warning("[TNC] Frame timeout", attempt=self.n_retries_per_burst, + max_attempts=self.rx_n_max_retries_per_burst, speed_level=self.speed_level) self.frame_received_counter = 0 self.burst_nack_counter += 1 if self.burst_nack_counter >= 2: @@ -1967,8 +1975,9 @@ class DATA: # pass else: self.data_channel_last_received = 0 - structlog.get_logger("structlog").info( - "[TNC] DATA [" + str(self.mycallsign, "utf-8") + "]<>[" + str(static.DXCALLSIGN, "utf-8") + "]") + self.log.info( + "[TNC] DATA [" + str(self.mycallsign, "utf-8") + + "]<>[" + str(static.DXCALLSIGN, "utf-8") + "]") static.INFO.append("ARQ;RECEIVING;FAILED") if not TESTMODE: self.arq_cleanup() @@ -1982,9 +1991,9 @@ class DATA: if self.arq_session_last_received + self.arq_session_timeout > time.time(): time.sleep(0.01) else: - structlog.get_logger("structlog").info( - "[TNC] SESSION [" + str(self.mycallsign, "utf-8") + "]<>[" + str(static.DXCALLSIGN, - "utf-8") + "]") + self.log.info( + "[TNC] SESSION [" + str(self.mycallsign, "utf-8") + + "]<>[" + str(static.DXCALLSIGN, "utf-8") + "]") static.INFO.append("ARQ;SESSION;TIMEOUT") self.close_session() @@ -1992,7 +2001,7 @@ class DATA: """ heartbeat thread which auto resumes the heartbeat signal within a arq session """ - while 1: + while True: time.sleep(0.01) if static.ARQ_SESSION and self.IS_ARQ_SESSION_MASTER and static.ARQ_SESSION_STATE == "connected" and not self.arq_file_transfer: time.sleep(1) diff --git a/tnc/main.py b/tnc/main.py index 3f076fdf..a3acb0d1 100755 --- a/tnc/main.py +++ b/tnc/main.py @@ -150,5 +150,5 @@ if __name__ == "__main__": except Exception as err: structlog.get_logger("structlog").error("[TNC] Starting TCP/IP socket failed", port=static.PORT, e=err) sys.exit(1) - while 1: + while True: time.sleep(1) diff --git a/tnc/modem.py b/tnc/modem.py index f3b0bf2d..52aad102 100644 --- a/tnc/modem.py +++ b/tnc/modem.py @@ -44,6 +44,7 @@ RECEIVE_FSK_LDPC_1 = False class RF: """ """ + log = structlog.get_logger("RF") def __init__(self): @@ -142,19 +143,19 @@ class RF: device=(static.AUDIO_INPUT_DEVICE, static.AUDIO_OUTPUT_DEVICE), samplerate=self.AUDIO_SAMPLE_RATE_RX, blocksize=4800) atexit.register(self.stream.stop) - structlog.get_logger("structlog").info("[MDM] init: opened audio devices") + self.log.info("[MDM] init: opened audio devices") except Exception as err: - structlog.get_logger("structlog").error("[MDM] init: can't open audio device. Exit", e=err) + self.log.error("[MDM] init: can't open audio device. Exit", e=err) sys.exit(1) try: - structlog.get_logger("structlog").debug("[MDM] init: starting pyaudio callback") + self.log.debug("[MDM] init: starting pyaudio callback") # self.audio_stream.start_stream() self.stream.start() except Exception as err: - structlog.get_logger("structlog").error("[MDM] init: starting pyaudio callback failed", e=err) + self.log.error("[MDM] init: starting pyaudio callback failed", e=err) else: # create a stream object for simulating audio stream @@ -169,7 +170,7 @@ class RF: os.mkfifo(RXCHANNEL) os.mkfifo(TXCHANNEL) except Exception as err: - structlog.get_logger("structlog").error(f"[MDM] init:mkfifo: Exception: {err}") + self.log.error(f"[MDM] init:mkfifo: Exception: {err}") mkfifo_write_callback_thread = threading.Thread(target=self.mkfifo_write_callback, name="MKFIFO WRITE CALLBACK THREAD", daemon=True) @@ -233,7 +234,7 @@ class RF: # -------------------------------------------------------------------------------------------------------- def mkfifo_read_callback(self): - while 1: + while True: time.sleep(0.01) # -----read data_in48k = bytes() @@ -257,7 +258,7 @@ class RF: self.datac3_buffer.push(x) def mkfifo_write_callback(self): - while 1: + while True: time.sleep(0.01) # -----write @@ -283,8 +284,6 @@ class RF: time: status: - Returns: - Nothing """ x = np.frombuffer(data_in48k, dtype=np.int16) x = self.resampler.resample48_to_8(x) @@ -333,7 +332,7 @@ class RF: try: outdata[:] = data_out48k[:frames] except IndexError as e: - structlog.get_logger("structlog").debug(f"[MDM] callback: IndexError: {e}") + self.log.debug(f"[MDM] callback: IndexError: {e}") # return (data_out48k, audio.pyaudio.paContinue) @@ -347,10 +346,8 @@ class RF: repeat_delay: frames: - Returns: - """ - structlog.get_logger("structlog").debug("[MDM] transmit", mode=mode) + self.log.debug("[MDM] transmit", mode=mode) static.TRANSMITTING = True # Toggle ptt early to save some time and send ptt state via socket static.PTT_STATE = self.hamlib.set_ptt(True) @@ -384,7 +381,7 @@ class RF: mod_out_silence = ctypes.create_string_buffer(data_delay * 2) txbuffer = bytes(mod_out_silence) - structlog.get_logger("structlog").debug("[MDM] TRANSMIT", mode=self.MODE, payload=payload_bytes_per_frame) + self.log.debug("[MDM] TRANSMIT", mode=self.MODE, payload=payload_bytes_per_frame) for _ in range(repeats): # codec2 fsk preamble may be broken - at least it sounds like that so we are disabling it for testing @@ -440,7 +437,7 @@ class RF: delta = chunk_length - len(c) delta_zeros = np.zeros(delta, dtype=np.int16) c = np.append(c, delta_zeros) - # structlog.get_logger("structlog").debug("[MDM] mod out shorter than audio buffer", delta=delta) + # self.log.debug("[MDM] mod out shorter than audio buffer", delta=delta) self.modoutqueue.append(c) @@ -556,7 +553,7 @@ class RF: while True: data = self.modem_transmit_queue.get() - structlog.get_logger("structlog").debug("[MDM] worker_transmit", mode=data[0]) + self.log.debug("[MDM] worker_transmit", mode=data[0]) self.transmit(mode=data[0], repeats=data[1], repeat_delay=data[2], frames=data[3]) # self.modem_transmit_queue.task_done() @@ -577,8 +574,6 @@ class RF: Args: freedv: - Returns: - """ modemStats = codec2.MODEMSTATS() self.c_lib.freedv_get_modem_extended_stats.restype = None @@ -593,8 +588,6 @@ class RF: Args: freedv: - Returns: - """ if not static.ENABLE_SCATTER: return @@ -629,8 +622,6 @@ class RF: Args: freedv: - Returns: - """ try: modem_stats_snr = ctypes.c_float() @@ -641,12 +632,12 @@ class RF: modem_stats_sync = modem_stats_sync.value snr = round(modem_stats_snr, 1) - structlog.get_logger("structlog").info("[MDM] calculate_snr: ", snr=snr) + self.log.info("[MDM] calculate_snr: ", snr=snr) # static.SNR = np.clip(snr, 0, 255) # limit to max value of 255 static.SNR = np.clip(snr, -128, 128) # limit to max value of -128/128 as a possible fix of #188 return static.SNR except Exception as err: - structlog.get_logger("structlog").error(f"[MDM] calculate_snr: Exception: {err}") + self.log.error(f"[MDM] calculate_snr: Exception: {err}") static.SNR = 0 return static.SNR @@ -712,8 +703,8 @@ class RF: static.FFT = dfftlist[:320] # 320 --> bandwidth 3000 except Exception as err: - structlog.get_logger("structlog").error(f"[MDM] calculate_fft: Exception: {err}") - structlog.get_logger("structlog").debug("[MDM] Setting fft=0") + self.log.error(f"[MDM] calculate_fft: Exception: {err}") + self.log.debug("[MDM] Setting fft=0") # else 0 static.FFT = [0] @@ -723,8 +714,6 @@ class RF: Args: n_frames_per_burst: - Returns: - """ codec2.api.freedv_set_frames_per_burst(self.datac1_freedv, n_frames_per_burst) codec2.api.freedv_set_frames_per_burst(self.datac3_freedv, n_frames_per_burst) @@ -753,8 +742,6 @@ def get_bytes_per_frame(mode): Args: mode: - Returns: - """ freedv = open_codec2_instance(mode) diff --git a/tnc/rigctld.py b/tnc/rigctld.py index 34c02806..46b4c142 100644 --- a/tnc/rigctld.py +++ b/tnc/rigctld.py @@ -8,8 +8,6 @@ import logging import socket import time -import log_handler -import static import structlog # set global hamlib version diff --git a/tnc/rigdummy.py b/tnc/rigdummy.py index ccd3012f..35b98b3f 100644 --- a/tnc/rigdummy.py +++ b/tnc/rigdummy.py @@ -1,7 +1,5 @@ #!/usr/bin/env python3 -import structlog - hamlib_version = 0 diff --git a/tnc/sock.py b/tnc/sock.py index e241bd7c..94cf1c8f 100644 --- a/tnc/sock.py +++ b/tnc/sock.py @@ -38,6 +38,8 @@ DAEMON_QUEUE = queue.Queue() CONNECTED_CLIENTS = set() CLOSE_SIGNAL = False +log = structlog.get_logger("sock") + class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer): """ @@ -82,8 +84,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): try: client.send(sock_data) except Exception as err: - # print("connection lost...") - structlog.get_logger("structlog").info("[SCK] Connection lost", e=err) + log.info("[SCK] Connection lost", e=err) self.connection_alive = False # we want to transmit scatter data only once to reduce network traffic @@ -131,8 +132,8 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): # finally delete our rx buffer to be ready for new commands data = bytes() except Exception as err: - structlog.get_logger("structlog").info("[SCK] Connection closed", ip=self.client_address[0], - port=self.client_address[1], e=err) + log.info("[SCK] Connection closed", ip=self.client_address[0], + port=self.client_address[1], e=err) self.connection_alive = False def handle(self): @@ -141,12 +142,14 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): """ CONNECTED_CLIENTS.add(self.request) - structlog.get_logger("structlog").debug("[SCK] Client connected", ip=self.client_address[0], - port=self.client_address[1]) + log.debug("[SCK] Client connected", ip=self.client_address[0], + port=self.client_address[1]) self.connection_alive = True - self.sendThread = threading.Thread(target=self.send_to_client, args=[], daemon=True).start() - self.receiveThread = threading.Thread(target=self.receive_from_client, args=[], daemon=True).start() + self.send_thread = threading.Thread(target=self.send_to_client, args=[], daemon=True) + self.send_thread.start() + self.receive_thread = threading.Thread(target=self.receive_from_client, args=[], daemon=True) + self.receive_thread.start() # keep connection alive until we close it while self.connection_alive and not CLOSE_SIGNAL: @@ -154,13 +157,13 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): def finish(self): """ """ - structlog.get_logger("structlog").warning("[SCK] Closing client socket", ip=self.client_address[0], - port=self.client_address[1]) + log.warning("[SCK] Closing client socket", ip=self.client_address[0], + port=self.client_address[1]) try: CONNECTED_CLIENTS.remove(self.request) except Exception as err: - structlog.get_logger("structlog").warning("[SCK] client connection already removed from client list", - client=self.request, e=err) + log.warning("[SCK] client connection already removed from client list", + client=self.request, e=err) def process_tnc_commands(data): @@ -177,7 +180,7 @@ def process_tnc_commands(data): try: # convert data to json object received_json = json.loads(data) - structlog.get_logger("structlog").debug("[SCK] CMD", command=received_json) + log.debug("[SCK] CMD", command=received_json) # SET TX AUDIO LEVEL ----------------------------------------------------- if received_json["type"] == "set" and received_json["command"] == "tx_audio_level": try: @@ -186,7 +189,7 @@ def process_tnc_commands(data): except Exception as err: command_response("tx_audio_level", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) + log.warning("[SCK] command execution error", e=err, command=received_json) # TRANSMIT SINE WAVE ----------------------------------------------------- if received_json["type"] == "set" and received_json["command"] == "send_test_frame": @@ -195,7 +198,7 @@ def process_tnc_commands(data): command_response("send_test_frame", True) except Exception as err: command_response("send_test_frame", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) + log.warning("[SCK] command execution error", e=err, command=received_json) # CQ CQ CQ ----------------------------------------------------- if received_json["command"] == "cqcqcq": @@ -205,7 +208,7 @@ def process_tnc_commands(data): except Exception as err: command_response("cqcqcq", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) + log.warning("[SCK] command execution error", e=err, command=received_json) # START_BEACON ----------------------------------------------------- if received_json["command"] == "start_beacon": @@ -216,18 +219,18 @@ def process_tnc_commands(data): command_response("start_beacon", True) except Exception as err: command_response("start_beacon", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) + log.warning("[SCK] command execution error", e=err, command=received_json) # STOP_BEACON ----------------------------------------------------- if received_json["command"] == "stop_beacon": try: - structlog.get_logger("structlog").warning("[TNC] Stopping beacon!") + log.warning("[TNC] Stopping beacon!") static.BEACON_STATE = False data_handler.DATA_QUEUE_TRANSMIT.put(["BEACON", None, False]) command_response("stop_beacon", True) except Exception as err: command_response("stop_beacon", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) + log.warning("[SCK] command execution error", e=err, command=received_json) # PING ---------------------------------------------------------- if received_json["type"] == "ping" and received_json["command"] == "ping": @@ -245,7 +248,7 @@ def process_tnc_commands(data): command_response("ping", True) except Exception as err: command_response("ping", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) + log.warning("[SCK] command execution error", e=err, command=received_json) # CONNECT ---------------------------------------------------------- if received_json["type"] == "arq" and received_json["command"] == "connect": @@ -267,7 +270,7 @@ def process_tnc_commands(data): command_response("connect", True) except Exception as err: command_response("connect", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) + log.warning("[SCK] command execution error", e=err, command=received_json) # DISCONNECT ---------------------------------------------------------- if received_json["type"] == "arq" and received_json["command"] == "disconnect": @@ -277,7 +280,7 @@ def process_tnc_commands(data): command_response("disconnect", True) except Exception as err: command_response("disconnect", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) + log.warning("[SCK] command execution error", e=err, command=received_json) # TRANSMIT RAW DATA ------------------------------------------- if received_json["type"] == "arq" and received_json["command"] == "send_raw": @@ -321,20 +324,20 @@ def process_tnc_commands(data): raise TypeError except Exception as err: command_response("send_raw", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) + log.warning("[SCK] command execution error", e=err, command=received_json) # STOP TRANSMISSION ---------------------------------------------------------- if received_json["type"] == "arq" and received_json["command"] == "stop_transmission": try: if static.TNC_STATE == "BUSY" or static.ARQ_STATE: data_handler.DATA_QUEUE_TRANSMIT.put(["STOP"]) - structlog.get_logger("structlog").warning("[TNC] Stopping transmission!") + log.warning("[TNC] Stopping transmission!") static.TNC_STATE = "IDLE" static.ARQ_STATE = False command_response("stop_transmission", True) except Exception as err: command_response("stop_transmission", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) + log.warning("[SCK] command execution error", e=err, command=received_json) if received_json["type"] == "get" and received_json["command"] == "rx_buffer": try: @@ -358,7 +361,7 @@ def process_tnc_commands(data): except Exception as err: command_response("rx_buffer", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) + log.warning("[SCK] command execution error", e=err, command=received_json) if received_json["type"] == "set" and received_json["command"] == "del_rx_buffer": try: @@ -366,11 +369,11 @@ def process_tnc_commands(data): command_response("del_rx_buffer", True) except Exception as err: command_response("del_rx_buffer", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) + log.warning("[SCK] command execution error", e=err, command=received_json) # exception, if JSON can't be decoded except Exception as err: - structlog.get_logger("structlog").error("[TNC] JSON decoding error", e=err) + log.error("[TNC] JSON decoding error", e=err) def send_tnc_state(): @@ -424,6 +427,8 @@ def send_tnc_state(): return json.dumps(output) +# This has apparently been taken out of a class, but is never called because +# the `self.request.sendall` call is a syntax error as `self` is undefined. def process_daemon_commands(data): """ process daemon commands @@ -436,25 +441,25 @@ def process_daemon_commands(data): """ # convert data to json object received_json = json.loads(data) - structlog.get_logger("structlog").debug("[SCK] CMD", command=received_json) + log.debug("[SCK] CMD", command=received_json) if received_json["type"] == "set" and received_json["command"] == "mycallsign": try: callsign = received_json["parameter"] if bytes(callsign, "utf-8") == b"": self.request.sendall(b"INVALID CALLSIGN") - structlog.get_logger("structlog").warning("[DMN] SET MYCALL FAILED", call=static.MYCALLSIGN, - crc=static.MYCALLSIGN_CRC) + log.warning("[DMN] SET MYCALL FAILED", call=static.MYCALLSIGN, + crc=static.MYCALLSIGN_CRC) else: static.MYCALLSIGN = bytes(callsign, "utf-8") static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN) command_response("mycallsign", True) - structlog.get_logger("structlog").info("[DMN] SET MYCALL", call=static.MYCALLSIGN, - crc=static.MYCALLSIGN_CRC) + log.info("[DMN] SET MYCALL", call=static.MYCALLSIGN, + crc=static.MYCALLSIGN_CRC) except Exception as err: command_response("mycallsign", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) + log.warning("[SCK] command execution error", e=err, command=received_json) if received_json["type"] == "set" and received_json["command"] == "mygrid": try: @@ -464,11 +469,11 @@ def process_daemon_commands(data): self.request.sendall(b"INVALID GRID") else: static.MYGRID = bytes(mygrid, "utf-8") - structlog.get_logger("structlog").info("[SCK] SET MYGRID", grid=static.MYGRID) + log.info("[SCK] SET MYGRID", grid=static.MYGRID) command_response("mygrid", True) except Exception as err: command_response("mygrid", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) + log.warning("[SCK] command execution error", e=err, command=received_json) if received_json["type"] == "set" and received_json["command"] == "start_tnc" and not static.TNCSTARTED: try: @@ -498,7 +503,7 @@ def process_daemon_commands(data): # print some debugging parameters for item in received_json["parameter"][0]: - structlog.get_logger("structlog").debug(f"[DMN] TNC Startup Config : {item}", value=received_json["parameter"][0][item]) + log.debug(f"[DMN] TNC Startup Config : {item}", value=received_json["parameter"][0][item]) DAEMON_QUEUE.put(["STARTTNC", mycall, @@ -529,7 +534,7 @@ def process_daemon_commands(data): except Exception as err: command_response("start_tnc", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) + log.warning("[SCK] command execution error", e=err, command=received_json) if received_json["type"] == "get" and received_json["command"] == "test_hamlib": try: @@ -561,7 +566,7 @@ def process_daemon_commands(data): command_response("test_hamlib", True) except Exception as err: command_response("test_hamlib", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) + log.warning("[SCK] command execution error", e=err, command=received_json) if received_json["type"] == "set" and received_json["command"] == "stop_tnc": try: @@ -569,12 +574,12 @@ def process_daemon_commands(data): # unregister process from atexit to avoid process zombies atexit.unregister(static.TNCPROCESS.kill) - structlog.get_logger("structlog").warning("[DMN] Stopping TNC") + log.warning("[DMN] Stopping TNC") static.TNCSTARTED = False command_response("stop_tnc", True) except Exception as err: command_response("stop_tnc", False) - structlog.get_logger("structlog").warning("[SCK] command execution error", e=err, command=received_json) + log.warning("[SCK] command execution error", e=err, command=received_json) def send_daemon_state(): @@ -605,7 +610,7 @@ def send_daemon_state(): return json.dumps(output) except Exception as err: - structlog.get_logger("structlog").warning("[SCK] error", e=err) + log.warning("[SCK] error", e=err) return None diff --git a/tnc/static.py b/tnc/static.py index aef93c35..10a17a50 100644 --- a/tnc/static.py +++ b/tnc/static.py @@ -8,115 +8,118 @@ Here we are saving application wide variables and stats, which have to be access Not nice, suggestions are appreciated :-) """ +import subprocess + VERSION = "0.4.0-alpha" # DAEMON -DAEMONPORT = 3001 -TNCSTARTED = False -TNCPROCESS = 0 +DAEMONPORT: int = 3001 +TNCSTARTED: bool = False +TNCPROCESS: subprocess.Popen # Operator Defaults -MYCALLSIGN = b"AA0AA" -MYCALLSIGN_CRC = b"A" +MYCALLSIGN: bytes = b"AA0AA" +MYCALLSIGN_CRC: bytes = b"A" -DXCALLSIGN = b"AA0AA" -DXCALLSIGN_CRC = b"A" +DXCALLSIGN: bytes = b"AA0AA" +DXCALLSIGN_CRC: bytes = b"A" -MYGRID = b"" -DXGRID = b"" +MYGRID: bytes = b"" +DXGRID: bytes = b"" -SSID_LIST = [] # ssid list we are responding to +SSID_LIST: list = [] # ssid list we are responding to -LOW_BANDWITH_MODE = False +LOW_BANDWITH_MODE: bool = False # --------------------------------- # Server Defaults -HOST = "0.0.0.0" -PORT = 3000 -SOCKET_TIMEOUT = 1 # seconds +HOST: str = "0.0.0.0" +PORT: int = 3000 +SOCKET_TIMEOUT: int = 1 # seconds # --------------------------------- -SERIAL_DEVICES = [] +SERIAL_DEVICES: list = [] # --------------------------------- -PTT_STATE = False -TRANSMITTING = False +PTT_STATE: bool = False +TRANSMITTING: bool = False -HAMLIB_VERSION = "0" -HAMLIB_PTT_TYPE = "RTS" -HAMLIB_DEVICE_NAME = "RIG_MODEL_DUMMY_NOVFO" -HAMLIB_DEVICE_PORT = "/dev/ttyUSB0" -HAMLIB_SERIAL_SPEED = "9600" -HAMLIB_PTT_PORT = "/dev/ttyUSB0" -HAMLIB_STOP_BITS = "1" -HAMLIB_DATA_BITS = "8" -HAMLIB_HANDSHAKE = "None" -HAMLIB_RADIOCONTROL = "direct" -HAMLIB_RIGCTLD_IP = "127.0.0.1" -HAMLIB_RIGCTLD_PORT = "4532" +HAMLIB_VERSION: str = "0" +HAMLIB_PTT_TYPE: str = "RTS" +HAMLIB_DEVICE_NAME: str = "RIG_MODEL_DUMMY_NOVFO" +HAMLIB_DEVICE_PORT: str = "/dev/ttyUSB0" +HAMLIB_SERIAL_SPEED: str = "9600" +HAMLIB_PTT_PORT: str = "/dev/ttyUSB0" +HAMLIB_STOP_BITS: str = "1" +HAMLIB_DATA_BITS: str = "8" +HAMLIB_HANDSHAKE: str = "None" +HAMLIB_RADIOCONTROL: str = "direct" +HAMLIB_RIGCTLD_IP: str = "127.0.0.1" +HAMLIB_RIGCTLD_PORT: str = "4532" -HAMLIB_FREQUENCY = 0 -HAMLIB_MODE = "" -HAMLIB_BANDWITH = 0 +HAMLIB_FREQUENCY: int = 0 +HAMLIB_MODE: str = "" +HAMLIB_BANDWITH: int = 0 # ------------------------- # FreeDV Defaults -SNR = 0 -FREQ_OFFSET = 0 -SCATTER = [] -ENABLE_SCATTER = False -ENABLE_FSK = False -RESPOND_TO_CQ = False +SNR: float = 0 +FREQ_OFFSET: float = 0 +SCATTER: list = [] +ENABLE_SCATTER: bool = False +ENABLE_FSK: bool = False +RESPOND_TO_CQ: bool = False # --------------------------------- # Audio Defaults -TX_AUDIO_LEVEL = 50 -AUDIO_INPUT_DEVICES = [] -AUDIO_OUTPUT_DEVICES = [] -AUDIO_INPUT_DEVICE = -2 -AUDIO_OUTPUT_DEVICE = -2 -BUFFER_OVERFLOW_COUNTER = [0, 0, 0, 0, 0] +TX_AUDIO_LEVEL: int = 50 +AUDIO_INPUT_DEVICES: list = [] +AUDIO_OUTPUT_DEVICES: list = [] +AUDIO_INPUT_DEVICE: int = -2 +AUDIO_OUTPUT_DEVICE: int = -2 +BUFFER_OVERFLOW_COUNTER: list = [0, 0, 0, 0, 0] -AUDIO_RMS = 0 -FFT = [0] -ENABLE_FFT = False -CHANNEL_BUSY = None +AUDIO_RMS: int = 0 +FFT: list = [0] +ENABLE_FFT: bool = False +CHANNEL_BUSY: bool = False # ARQ PROTOCOL VERSION -ARQ_PROTOCOL_VERSION = 1 +ARQ_PROTOCOL_VERSION: int = 1 # ARQ statistics -ARQ_BYTES_PER_MINUTE_BURST = 0 -ARQ_BYTES_PER_MINUTE = 0 -ARQ_BITS_PER_SECOND_BURST = 0 -ARQ_BITS_PER_SECOND = 0 -ARQ_COMPRESSION_FACTOR = 0 -ARQ_TRANSMISSION_PERCENT = 0 -ARQ_SPEED_LEVEL = 0 -TOTAL_BYTES = 0 +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_SPEED_LEVEL: int = 0 +TOTAL_BYTES: int = 0 # CHANNEL_STATE = 'RECEIVING_SIGNALLING' -TNC_STATE = "IDLE" -ARQ_STATE = False -ARQ_SESSION = False -ARQ_SESSION_STATE = "disconnected" # disconnected, connecting, connected, disconnecting, failed +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 = False -BEACON_PAUSE = False +BEACON_STATE: bool = False +BEACON_PAUSE: bool = False # ------- RX BUFFER -RX_BUFFER = [] -RX_MSG_BUFFER = [] -RX_BURST_BUFFER = [] -RX_FRAME_BUFFER = b"" -# RX_BUFFER_SIZE = 0 +RX_BUFFER: list = [] +RX_MSG_BUFFER: list = [] +RX_BURST_BUFFER: list = [] +RX_FRAME_BUFFER: bytes = b"" +# RX_BUFFER_SIZE: int = 0 # ------- HEARD STATIONS BUFFER -HEARD_STATIONS = [] +HEARD_STATIONS: list = [] # ------- INFO MESSAGE BUFFER -INFO = [] +INFO: list = [] # ------- CODEC2 SETTINGS -TUNING_RANGE_FMIN = -50.0 -TUNING_RANGE_FMAX = 50.0 +TUNING_RANGE_FMIN: float = -50.0 +TUNING_RANGE_FMAX: float = 50.0 diff --git a/tools/list_audio_devices.py b/tools/list_audio_devices.py index 8b869b4c..8ee31fa2 100755 --- a/tools/list_audio_devices.py +++ b/tools/list_audio_devices.py @@ -6,12 +6,14 @@ import pyaudio def list_audio_devices(): p = pyaudio.PyAudio() - devices = [] print("--------------------------------------------------------------------") - for x in range(0, p.get_device_count()): - devices.append(f"{x} - {p.get_device_info_by_index(x)['name']}") - + devices = [ + f"{x} - {p.get_device_info_by_index(x)['name']}" + for x in range(p.get_device_count()) + ] + for line in devices: - print(line) + print(line) + list_audio_devices() diff --git a/tools/socketclient.py b/tools/socketclient.py index 753ce568..9e667b77 100644 --- a/tools/socketclient.py +++ b/tools/socketclient.py @@ -6,10 +6,9 @@ Created on Fri Dec 11 21:53:35 2020 @author: parallels """ -import socket -import sys import argparse import random +import socket def create_string(length): @@ -24,14 +23,14 @@ def create_string(length): random_integer = random_integer - 32 if flip_bit == 1 else random_integer # Keep appending random characters using chr(x) random_string += (chr(random_integer)) - print("STR:" + str(random_string)) - + print(f"STR: {random_string!s}") + return random_string # --------------------------------------------GET PARAMETER INPUTS parser = argparse.ArgumentParser(description='Simons TEST TNC') -parser.add_argument('--port', dest="socket_port", default=9000, help="Set the port, the socket is listening on.", type=int) +parser.add_argument('--port', dest="socket_port", default=9000, help="Set the port, the socket is listening on.", type=int) # parser.add_argument('--data', dest="data", default=False, help="data", type=str) parser.add_argument('--random', dest="datalength", default=False, help="data", type=int) @@ -52,7 +51,4 @@ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: # Receive data from the server and shut down received = str(sock.recv(1024), "utf-8") -print("Sent: {}".format(data)) - - - +print(f"Sent: {data}") From adf800b8229fe61b3550f16a5249813bd3a59b2e Mon Sep 17 00:00:00 2001 From: DJ2LS <75909252+DJ2LS@users.noreply.github.com> Date: Sat, 28 May 2022 14:08:33 +0200 Subject: [PATCH 7/8] changed bandwith typo --> this could break some things.. --- gui/daemon.js | 4 ++-- gui/main.js | 2 +- gui/preload-main.js | 20 ++++++++++---------- gui/sock.js | 6 +++--- gui/src/index.html | 2 +- tnc/daemon.py | 2 +- tnc/data_handler.py | 30 +++++++++++++++--------------- tnc/main.py | 4 ++-- tnc/modem.py | 4 ++-- tnc/rig.py | 2 +- tnc/rigctl.py | 6 +++--- tnc/rigctld.py | 6 +++--- tnc/rigdummy.py | 2 +- tnc/sock.py | 6 +++--- tnc/static.py | 4 ++-- 15 files changed, 50 insertions(+), 50 deletions(-) diff --git a/gui/daemon.js b/gui/daemon.js index 1e334c23..c22ec79c 100644 --- a/gui/daemon.js +++ b/gui/daemon.js @@ -217,7 +217,7 @@ exports.getDaemonState = function() { // START TNC // ` `== multi line string -exports.startTNC = function(mycall, mygrid, rx_audio, tx_audio, radiocontrol, devicename, deviceport, pttprotocol, pttport, serialspeed, data_bits, stop_bits, handshake, rigctld_ip, rigctld_port, enable_fft, enable_scatter, low_bandwith_mode, tuning_range_fmin, tuning_range_fmax, enable_fsk, tx_audio_level, respond_to_cq) { +exports.startTNC = function(mycall, mygrid, rx_audio, tx_audio, radiocontrol, devicename, deviceport, pttprotocol, pttport, serialspeed, data_bits, stop_bits, handshake, rigctld_ip, rigctld_port, enable_fft, enable_scatter, low_bandwidth_mode, tuning_range_fmin, tuning_range_fmax, enable_fsk, tx_audio_level, respond_to_cq) { var json_command = JSON.stringify({ type: 'set', command: 'start_tnc', @@ -240,7 +240,7 @@ exports.startTNC = function(mycall, mygrid, rx_audio, tx_audio, radiocontrol, de enable_scatter: enable_scatter, enable_fft: enable_fft, enable_fsk: enable_fsk, - low_bandwith_mode : low_bandwith_mode, + low_bandwidth_mode : low_bandwidth_mode, tuning_range_fmin : tuning_range_fmin, tuning_range_fmax : tuning_range_fmax, tx_audio_level : tx_audio_level, diff --git a/gui/main.js b/gui/main.js index 7c63954e..504beec7 100644 --- a/gui/main.js +++ b/gui/main.js @@ -68,7 +68,7 @@ const configDefaultSettings = '{\ "enable_scatter" : "False",\ "enable_fft" : "False",\ "enable_fsk" : "False",\ - "low_bandwith_mode" : "False",\ + "low_bandwidth_mode" : "False",\ "theme" : "default",\ "screen_height" : 430,\ "screen_width" : 1050,\ diff --git a/gui/preload-main.js b/gui/preload-main.js index 8f65b84b..cbd134cb 100644 --- a/gui/preload-main.js +++ b/gui/preload-main.js @@ -112,7 +112,7 @@ document.getElementById('openReceivedFilesFolder').addEventListener('click', () document.getElementById("scatterSwitch").value = config.enable_scatter; document.getElementById("fftSwitch").value = config.enable_fft; - //document.getElementById("500HzModeSwitch").value = config.low_bandwith_mode; + //document.getElementById("500HzModeSwitch").value = config.low_bandwidth_mode; //document.getElementById("fskModeSwitch").value = config.enable_fsk; //document.getElementById("respondCQSwitch").value = config.respond_to_cq; @@ -132,7 +132,7 @@ document.getElementById('openReceivedFilesFolder').addEventListener('click', () document.getElementById("fftSwitch").checked = false; } - if(config.low_bandwith_mode == 'True'){ + if(config.low_bandwidth_mode == 'True'){ document.getElementById("500HzModeSwitch").checked = true; } else { document.getElementById("500HzModeSwitch").checked = false; @@ -522,9 +522,9 @@ document.getElementById('openReceivedFilesFolder').addEventListener('click', () // enable 500z Switch clicked document.getElementById("500HzModeSwitch").addEventListener("click", () => { if(document.getElementById("500HzModeSwitch").checked == true){ - config.low_bandwith_mode = "True"; + config.low_bandwidth_mode = "True"; } else { - config.low_bandwith_mode = "False"; + config.low_bandwidth_mode = "False"; } fs.writeFileSync(configPath, JSON.stringify(config, null, 2)); }); @@ -650,9 +650,9 @@ document.getElementById('openReceivedFilesFolder').addEventListener('click', () } if (document.getElementById("500HzModeSwitch").checked == true){ - var low_bandwith_mode = "True"; + var low_bandwidth_mode = "True"; } else { - var low_bandwith_mode = "False"; + var low_bandwidth_mode = "False"; } if (document.getElementById("fskModeSwitch").checked == true){ @@ -732,7 +732,7 @@ document.getElementById('openReceivedFilesFolder').addEventListener('click', () config.enable_scatter = enable_scatter; config.enable_fft = enable_fft; config.enable_fsk = enable_fsk; - config.low_bandwith_mode = low_bandwith_mode; + config.low_bandwidth_mode = low_bandwidth_mode; config.tx_audio_level = tx_audio_level; config.respond_to_cq = respond_to_cq; @@ -753,7 +753,7 @@ document.getElementById('openReceivedFilesFolder').addEventListener('click', () */ - daemon.startTNC(callsign_ssid, mygrid, rx_audio, tx_audio, radiocontrol, deviceid, deviceport, pttprotocol, pttport, serialspeed, data_bits, stop_bits, handshake, rigctld_ip, rigctld_port, enable_fft, enable_scatter, low_bandwith_mode, tuning_range_fmin, tuning_range_fmax, enable_fsk, tx_audio_level, respond_to_cq); + daemon.startTNC(callsign_ssid, mygrid, rx_audio, tx_audio, radiocontrol, deviceid, deviceport, pttprotocol, pttport, serialspeed, data_bits, stop_bits, handshake, rigctld_ip, rigctld_port, enable_fft, enable_scatter, low_bandwidth_mode, tuning_range_fmin, tuning_range_fmax, enable_fsk, tx_audio_level, respond_to_cq); }) @@ -1152,8 +1152,8 @@ ipcRenderer.on('action-update-tnc-state', (event, arg) => { // SET MODE document.getElementById("mode").innerHTML = arg.mode; - // SET BANDWITH - document.getElementById("bandwith").innerHTML = arg.bandwith; + // SET bandwidth + document.getElementById("bandwidth").innerHTML = arg.bandwidth; // SET BYTES PER MINUTE if (typeof(arg.arq_bytes_per_minute) == 'undefined') { diff --git a/gui/sock.js b/gui/sock.js index 96205302..2e449c81 100644 --- a/gui/sock.js +++ b/gui/sock.js @@ -55,7 +55,7 @@ client.on('connect', function(data) { //channel_state: "-", frequency: "-", mode: "-", - bandwith: "-", + bandwidth: "-", rms_level: 0 }; ipcRenderer.send('request-update-tnc-state', Data); @@ -84,7 +84,7 @@ client.on('error', function(data) { //channel_state: "-", frequency: "-", mode: "-", - bandwith: "-", + bandwidth: "-", rms_level: 0 }; @@ -199,7 +199,7 @@ client.on('data', function(socketdata) { frequency: data['frequency'], speed_level: data['speed_level'], mode: data['mode'], - bandwith: data['bandwith'], + bandwidth: data['bandwidth'], rms_level: data['audio_rms'], fft: data['fft'], channel_busy: data['channel_busy'], diff --git a/gui/src/index.html b/gui/src/index.html index 38be56ef..a4d9830b 100644 --- a/gui/src/index.html +++ b/gui/src/index.html @@ -1054,7 +1054,7 @@
--- --- - --- + ---
diff --git a/tnc/daemon.py b/tnc/daemon.py index 63551b81..7636f81e 100755 --- a/tnc/daemon.py +++ b/tnc/daemon.py @@ -131,7 +131,7 @@ class DAEMON: # data[15] rigctld_port # data[16] send_scatter # data[17] send_fft - # data[18] low_bandwith_mode + # data[18] low_bandwidth_mode # data[19] tuning_range_fmin # data[20] tuning_range_fmax # data[21] enable FSK diff --git a/tnc/data_handler.py b/tnc/data_handler.py index d4e37bea..95abbb3c 100644 --- a/tnc/data_handler.py +++ b/tnc/data_handler.py @@ -67,7 +67,7 @@ class DATA: self.rx_n_max_retries_per_burst = 50 self.n_retries_per_burst = 0 - self.received_low_bandwith_mode = False # indicator if we recevied a low bandwith mode channel opener + self.received_LOW_BANDWIDTH_MODE = False # indicator if we recevied a low bandwidth mode channel opener self.data_channel_max_retries = 5 self.datachannel_timeout = False @@ -79,7 +79,7 @@ class DATA: self.time_list_high_bw = [3, 7, 8, 30] # list for time to wait for corresponding mode in seconds # mode list for selecting between low bandwidth ( 500Hz ) and normal modes with higher bandwidth - if static.LOW_BANDWITH_MODE: + if static.LOW_BANDWIDTH_MODE: self.mode_list = self.mode_list_low_bw # mode list of available modes, each mode will be used 2times per speed level self.time_list = self.time_list_low_bw # list for time to wait for corresponding mode in seconds @@ -1238,7 +1238,7 @@ class DATA: self.is_IRS = False self.data_channel_last_received = int(time.time()) - if static.LOW_BANDWITH_MODE and mode == 255: + if static.LOW_BANDWIDTH_MODE and mode == 255: frametype = bytes([227]) self.log.debug("[TNC] Requesting low bandwidth mode") @@ -1319,13 +1319,13 @@ class DATA: n_frames_per_burst = int.from_bytes(bytes(data_in[13:14]), "big") frametype = int.from_bytes(bytes(data_in[:1]), "big") - # check if we received low bandwith mode + # check if we received low bandwidth mode if frametype == 225: - self.received_low_bandwith_mode = False + self.received_LOW_BANDWIDTH_MODE = False self.mode_list = self.mode_list_high_bw self.time_list = self.time_list_high_bw else: - self.received_low_bandwith_mode = True + self.received_LOW_BANDWIDTH_MODE = True self.mode_list = self.mode_list_low_bw self.time_list = self.time_list_low_bw self.speed_level = len(self.mode_list) - 1 @@ -1350,7 +1350,7 @@ class DATA: self.log.info( "[TNC] ARQ | DATA | RX | [" + str(mycallsign, "utf-8") + "]>> <<[" + str(static.DXCALLSIGN, "utf-8") + "]", - bandwith="wide") + bandwidth="wide") static.ARQ_STATE = True static.TNC_STATE = "BUSY" @@ -1358,8 +1358,8 @@ class DATA: self.reset_statistics() self.data_channel_last_received = int(time.time()) - # check if we are in low bandwith mode - if static.LOW_BANDWITH_MODE or self.received_low_bandwith_mode: + # check if we are in low bandwidth mode + if static.LOW_BANDWIDTH_MODE or self.received_LOW_BANDWIDTH_MODE: frametype = bytes([228]) self.log.debug("[TNC] Responding with low bandwidth mode") else: @@ -1377,7 +1377,7 @@ class DATA: self.log.info( "[TNC] ARQ | DATA | RX | [" + str(mycallsign, "utf-8") + "]>>|<<[" + str(static.DXCALLSIGN, "utf-8") + "]", - bandwith="wide", snr=static.SNR) + bandwidth="wide", snr=static.SNR) # set start of transmission for our statistics self.rx_start_of_transmission = time.time() @@ -1400,13 +1400,13 @@ class DATA: frametype = int.from_bytes(bytes(data_in[:1]), "big") if frametype == 228: - self.received_low_bandwith_mode = True + self.received_LOW_BANDWIDTH_MODE = True self.mode_list = self.mode_list_low_bw self.time_list = self.time_list_low_bw self.speed_level = len(self.mode_list) - 1 self.log.debug("[TNC] low bandwidth mode", modes=self.mode_list) else: - self.received_low_bandwith_mode = False + self.received_LOW_BANDWIDTH_MODE = False self.mode_list = self.mode_list_high_bw self.time_list = self.time_list_high_bw self.speed_level = len(self.mode_list) - 1 @@ -1848,8 +1848,8 @@ class DATA: self.speed_level = len(self.mode_list) - 1 static.ARQ_SPEED_LEVEL = self.speed_level - # low bandwith mode indicator - self.received_low_bandwith_mode = False + # low bandwidth mode indicator + self.received_LOW_BANDWIDTH_MODE = False # reset retry counter for rx channel / burst self.n_retries_per_burst = 0 @@ -1999,7 +1999,7 @@ class DATA: def heartbeat(self): """ - heartbeat thread which auto resumes the heartbeat signal within a arq session + heartbeat thread which auto resumes the heartbeat signal within an arq session """ while True: time.sleep(0.01) diff --git a/tnc/main.py b/tnc/main.py index a3acb0d1..dabeecde 100755 --- a/tnc/main.py +++ b/tnc/main.py @@ -65,7 +65,7 @@ if __name__ == "__main__": PARSER.add_argument("--rigctld_ip", dest="rigctld_ip", default="localhost", help="Set rigctld ip") PARSER.add_argument("--scatter", dest="send_scatter", action="store_true", help="Send scatter information via network") PARSER.add_argument("--fft", dest="send_fft", action="store_true", help="Send fft information via network") - PARSER.add_argument("--500hz", dest="low_bandwith_mode", action="store_true", help="Enable low bandwith mode ( 500 Hz only )") + PARSER.add_argument("--500hz", dest="low_bandwidth_mode", action="store_true", help="Enable low bandwidth mode ( 500 Hz only )") PARSER.add_argument("--fsk", dest="enable_fsk", action="store_true", help="Enable FSK mode for ping, beacon and CQ") PARSER.add_argument("--qrv", dest="enable_respond_to_cq", action="store_true", help="Enable sending a QRV frame if CQ received") PARSER.add_argument("--tuning_range_fmin", dest="tuning_range_fmin", choices=[-50.0, -100.0, -150.0, -200.0, -250.0], default=-50.0, help="Tuning range fmin", type=float) @@ -102,7 +102,7 @@ if __name__ == "__main__": static.ENABLE_SCATTER = ARGS.send_scatter static.ENABLE_FFT = ARGS.send_fft static.ENABLE_FSK = ARGS.enable_fsk - static.LOW_BANDWITH_MODE = ARGS.low_bandwith_mode + 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 diff --git a/tnc/modem.py b/tnc/modem.py index 52aad102..50b1b3f1 100644 --- a/tnc/modem.py +++ b/tnc/modem.py @@ -646,10 +646,10 @@ class RF: while True: # time.sleep(1.5) threading.Event().wait(0.5) - # (static.HAMLIB_FREQUENCY, static.HAMLIB_MODE, static.HAMLIB_BANDWITH, static.PTT_STATE) = self.hamlib.get_rig_data() + # (static.HAMLIB_FREQUENCY, static.HAMLIB_MODE, static.HAMLIB_BANDWIDTH, static.PTT_STATE) = self.hamlib.get_rig_data() static.HAMLIB_FREQUENCY = self.hamlib.get_frequency() static.HAMLIB_MODE = self.hamlib.get_mode() - static.HAMLIB_BANDWITH = self.hamlib.get_bandwith() + static.HAMLIB_BANDWIDTH = self.hamlib.get_bandwidth() def calculate_fft(self): """ """ diff --git a/tnc/rig.py b/tnc/rig.py index 23e24701..fdf31513 100644 --- a/tnc/rig.py +++ b/tnc/rig.py @@ -212,7 +212,7 @@ class radio: (hamlib_mode, bandwidth) = self.my_rig.get_mode() return Hamlib.rig_strrmode(hamlib_mode) - def get_bandwith(self): + def get_bandwidth(self): """ """ (hamlib_mode, bandwidth) = self.my_rig.get_mode() return bandwidth diff --git a/tnc/rigctl.py b/tnc/rigctl.py index 13efef56..802aa07d 100644 --- a/tnc/rigctl.py +++ b/tnc/rigctl.py @@ -114,16 +114,16 @@ class radio: def get_mode(self): """ """ - # (hamlib_mode, bandwith) = self.my_rig.get_mode() + # (hamlib_mode, bandwidth) = self.my_rig.get_mode() # return Hamlib.rig_strrmode(hamlib_mode) try: return "PKTUSB" except Exception: return False - def get_bandwith(self): + def get_bandwidth(self): """ """ - # (hamlib_mode, bandwith) = self.my_rig.get_mode() + # (hamlib_mode, bandwidth) = self.my_rig.get_mode() bandwidth = 2700 try: diff --git a/tnc/rigctld.py b/tnc/rigctld.py index 46b4c142..177b61f7 100644 --- a/tnc/rigctld.py +++ b/tnc/rigctld.py @@ -115,13 +115,13 @@ class radio(): except Exception: return 0 - def get_bandwith(self): + def get_bandwidth(self): """ """ try: data = self.send_command(b"m") data = data.split(b"\n") - bandwith = data[1] - return bandwith.decode("utf-8") + bandwidth = data[1] + return bandwidth.decode("utf-8") except Exception: return 0 diff --git a/tnc/rigdummy.py b/tnc/rigdummy.py index 35b98b3f..e3836d94 100644 --- a/tnc/rigdummy.py +++ b/tnc/rigdummy.py @@ -28,7 +28,7 @@ class radio: """ """ return None - def get_bandwith(self): + def get_bandwidth(self): """ """ return None diff --git a/tnc/sock.py b/tnc/sock.py index 94cf1c8f..d8b15e24 100644 --- a/tnc/sock.py +++ b/tnc/sock.py @@ -394,7 +394,7 @@ def send_tnc_state(): "frequency": str(static.HAMLIB_FREQUENCY), "speed_level": str(static.ARQ_SPEED_LEVEL), "mode": str(static.HAMLIB_MODE), - "bandwith": str(static.HAMLIB_BANDWITH), + "bandwidth": str(static.HAMLIB_BANDWIDTH), "fft": str(static.FFT), "channel_busy": str(static.CHANNEL_BUSY), "scatter": static.SCATTER, @@ -495,7 +495,7 @@ def process_daemon_commands(data): enable_scatter = str(received_json["parameter"][0]["enable_scatter"]) enable_fft = str(received_json["parameter"][0]["enable_fft"]) enable_fsk = str(received_json["parameter"][0]["enable_fsk"]) - low_bandwith_mode = str(received_json["parameter"][0]["low_bandwith_mode"]) + low_bandwidth_mode = str(received_json["parameter"][0]["low_bandwidth_mode"]) tuning_range_fmin = str(received_json["parameter"][0]["tuning_range_fmin"]) tuning_range_fmax = str(received_json["parameter"][0]["tuning_range_fmax"]) tx_audio_level = str(received_json["parameter"][0]["tx_audio_level"]) @@ -523,7 +523,7 @@ def process_daemon_commands(data): rigctld_port, enable_scatter, enable_fft, - low_bandwith_mode, + low_bandwidth_mode, tuning_range_fmin, tuning_range_fmax, enable_fsk, diff --git a/tnc/static.py b/tnc/static.py index 10a17a50..75edb3d9 100644 --- a/tnc/static.py +++ b/tnc/static.py @@ -29,7 +29,7 @@ DXGRID: bytes = b"" SSID_LIST: list = [] # ssid list we are responding to -LOW_BANDWITH_MODE: bool = False +LOW_BANDWIDTH_MODE: bool = False # --------------------------------- # Server Defaults @@ -58,7 +58,7 @@ HAMLIB_RIGCTLD_PORT: str = "4532" HAMLIB_FREQUENCY: int = 0 HAMLIB_MODE: str = "" -HAMLIB_BANDWITH: int = 0 +HAMLIB_BANDWIDTH: int = 0 # ------------------------- # FreeDV Defaults From 1fa8f0f2aecf359b8ab814b0251e00ef83c2bf0a Mon Sep 17 00:00:00 2001 From: DJ2LS <75909252+DJ2LS@users.noreply.github.com> Date: Sat, 28 May 2022 14:31:58 +0200 Subject: [PATCH 8/8] smaller changes... --- gui/src/chat-module.html | 4 ++-- gui/src/index.html | 3 +-- tnc/data_handler.py | 23 ++++++++++++----------- tnc/main.py | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/gui/src/chat-module.html b/gui/src/chat-module.html index 5ed8940c..48410818 100644 --- a/gui/src/chat-module.html +++ b/gui/src/chat-module.html @@ -32,7 +32,7 @@
- +
@@ -61,7 +61,7 @@
- + diff --git a/gui/src/index.html b/gui/src/index.html index a4d9830b..523b7cab 100644 --- a/gui/src/index.html +++ b/gui/src/index.html @@ -70,7 +70,7 @@ - @@ -1023,7 +1023,6 @@
-