diff --git a/tnc/daemon.py b/tnc/daemon.py index ec1c854b..4b7284ba 100644 --- a/tnc/daemon.py +++ b/tnc/daemon.py @@ -7,37 +7,38 @@ Created on Tue Dec 22 16:58:45 2020 """ - import argparse import threading import socketserver -import pyaudio import time -import ujson as json -import subprocess import os -import static -import psutil import sys +import subprocess +import ujson as json +import psutil import serial.tools.list_ports +import pyaudio +import static def start_daemon(): try: print("SRV | STARTING TCP/IP SOCKET FOR CMD ON PORT: " + str(PORT)) - socketserver.TCPServer.allow_reuse_address = True # https://stackoverflow.com/a/16641793 - daemon = socketserver.TCPServer(('0.0.0.0', PORT), CMDTCPRequestHandler) + # https://stackoverflow.com/a/16641793 + socketserver.TCPServer.allow_reuse_address = True + daemon = socketserver.TCPServer( + ('0.0.0.0', PORT), CMDTCPRequestHandler) daemon.serve_forever() finally: daemon.server_close() - - + + class CMDTCPRequestHandler(socketserver.BaseRequestHandler): def handle(self): - print("Client connected...") - + print("Client connected...") + # loop through socket buffer until timeout is reached. then close buffer socketTimeout = time.time() + 3 while socketTimeout > time.time(): @@ -47,23 +48,23 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler): #data = str(self.request.recv(1024), 'utf-8') data = bytes() - + # we need to loop through buffer until end of chunk is reached or timeout occured while True and socketTimeout > time.time(): chunk = self.request.recv(45) data += chunk - if chunk.endswith(b'}\n') or chunk.endswith(b'}'): # or chunk.endswith(b'\n'): + # or chunk.endswith(b'\n'): + if chunk.endswith(b'}\n') or chunk.endswith(b'}'): break data = data[:-1] # remove b'\n' data = str(data, 'utf-8') - - + if len(data) > 0: socketTimeout = time.time() + 3 - + # convert data to json object # we need to do some error handling in case of socket timeout - + try: # only read first line of string. multiple lines will cause an json error # this occurs possibly, if we are getting data too fast @@ -72,41 +73,44 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler): # GET COMMANDS # "command" : "..." - + # SET COMMANDS # "command" : "..." # "parameter" : " ..." - + # DATA COMMANDS # "command" : "..." # "type" : "..." # "dxcallsign" : "..." # "data" : "..." - + # print(received_json) - #print(received_json["type"]) - #print(received_json["command"]) - #try: + # print(received_json["type"]) + # print(received_json["command"]) + # try: if received_json["type"] == 'SET' and received_json["command"] == 'STARTTNC' and not static.TNCSTARTED: rx_audio = str(received_json["parameter"][0]["rx_audio"]) tx_audio = str(received_json["parameter"][0]["tx_audio"]) deviceid = str(received_json["parameter"][0]["deviceid"]) - deviceport = str(received_json["parameter"][0]["deviceport"]) - serialspeed = str(received_json["parameter"][0]["serialspeed"]) - pttprotocol = str(received_json["parameter"][0]["pttprotocol"]) + deviceport = str( + received_json["parameter"][0]["deviceport"]) + serialspeed = str( + received_json["parameter"][0]["serialspeed"]) + pttprotocol = str( + received_json["parameter"][0]["pttprotocol"]) pttport = str(received_json["parameter"][0]["pttport"]) print("---- STARTING TNC !") print(received_json["parameter"][0]) - #command = "--rx "+ rx_audio +" \ + # command = "--rx "+ rx_audio +" \ # --tx "+ tx_audio +" \ # --deviceport "+ deviceport +" \ # --deviceid "+ deviceid + " \ # --serialspeed "+ serialspeed + " \ # --pttprotocol "+ pttprotocol + " \ # --pttport "+ pttport - + # list of parameters, necessary for running subprocess command as a list options = [] options.append('--rx') @@ -123,7 +127,7 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler): options.append(pttprotocol) options.append('--pttport') options.append(pttport) - + # try running tnc from binary, else run from source # this helps running the tnc in a developer environment try: @@ -141,20 +145,20 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler): command += options p = subprocess.Popen(command) print("running TNC from source...") - - static.TNCPROCESS = p#.pid + + static.TNCPROCESS = p # .pid static.TNCSTARTED = True if received_json["type"] == 'SET' and received_json["command"] == 'STOPTNC': - parameter = received_json["parameter"] static.TNCPROCESS.kill() print("KILLING PROCESS ------------") #os.kill(static.TNCPROCESS, signal.SIGKILL) static.TNCSTARTED = False - + if received_json["type"] == 'GET' and received_json["command"] == 'DAEMON_STATE': - data = {'COMMAND' : 'DAEMON_STATE', 'DAEMON_STATE' : [], 'INPUT_DEVICES': [], 'OUTPUT_DEVICES': [], 'SERIAL_DEVICES': [], "CPU": str(psutil.cpu_percent()),"RAM": str(psutil.virtual_memory().percent), "VERSION": "0.1-prototype"} + data = {'COMMAND': 'DAEMON_STATE', 'DAEMON_STATE': [], 'INPUT_DEVICES': [], 'OUTPUT_DEVICES': [], 'SERIAL_DEVICES': [ + ], "CPU": str(psutil.cpu_percent()), "RAM": str(psutil.virtual_memory().percent), "VERSION": "0.1-prototype"} if static.TNCSTARTED: data["DAEMON_STATE"].append({"STATUS": "running"}) @@ -164,36 +168,40 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler): # UPDATE LIST OF AUDIO DEVICES p = pyaudio.PyAudio() for i in range(0, p.get_device_count()): - - maxInputChannels = p.get_device_info_by_host_api_device_index(0,i).get('maxInputChannels') - maxOutputChannels = p.get_device_info_by_host_api_device_index(0,i).get('maxOutputChannels') - name = p.get_device_info_by_host_api_device_index(0,i).get('name') - - if maxInputChannels > 0: - data["INPUT_DEVICES"].append({"ID": i, "NAME" : str(name)}) - if maxOutputChannels > 0: - data["OUTPUT_DEVICES"].append({"ID": i, "NAME" : str(name)}) - + + maxInputChannels = p.get_device_info_by_host_api_device_index( + 0, i).get('maxInputChannels') + maxOutputChannels = p.get_device_info_by_host_api_device_index( + 0, i).get('maxOutputChannels') + name = p.get_device_info_by_host_api_device_index( + 0, i).get('name') + + if maxInputChannels > 0: + data["INPUT_DEVICES"].append( + {"ID": i, "NAME": str(name)}) + if maxOutputChannels > 0: + data["OUTPUT_DEVICES"].append( + {"ID": i, "NAME": str(name)}) + # UPDATE LIST OF SERIAL DEVICES ports = serial.tools.list_ports.comports() for port, desc, hwid in ports: - data["SERIAL_DEVICES"].append({"PORT": str(port), "DESCRIPTION" : str(desc)}) + data["SERIAL_DEVICES"].append( + {"PORT": str(port), "DESCRIPTION": str(desc)}) - #print(data) + # print(data) jsondata = json.dumps(data) self.request.sendall(bytes(jsondata, encoding)) - - - - #exception, if JSON cant be decoded - #except Exception as e: + + # exception, if JSON cant be decoded + # except Exception as e: except ValueError as e: print("############ START OF ERROR #####################") - print('DAEMON PROGRAM ERROR: %s' %str(e)) + print('DAEMON PROGRAM ERROR: %s' % str(e)) print("Wrong command") print(data) print(e) - exc_type, exc_obj, exc_tb = sys.exc_info() + exc_type, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] print(exc_type, fname, exc_tb.tb_lineno) print("############ END OF ERROR #######################") @@ -203,13 +211,11 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler): if __name__ == '__main__': - # --------------------------------------------GET PARAMETER INPUTS PARSER = argparse.ArgumentParser(description='Simons TEST TNC') - PARSER.add_argument('--port', dest="socket_port", default=3001, help="Socket port", type=int) + PARSER.add_argument('--port', dest="socket_port", + default=3001, help="Socket port", type=int) - - ARGS = PARSER.parse_args() PORT = ARGS.socket_port @@ -217,9 +223,3 @@ if __name__ == '__main__': DAEMON_THREAD = threading.Thread(target=start_daemon, name="daemon") DAEMON_THREAD.start() - - - - - - diff --git a/tnc/helpers.py b/tnc/helpers.py index 12bc2eb8..89b96635 100644 --- a/tnc/helpers.py +++ b/tnc/helpers.py @@ -15,13 +15,13 @@ import crcengine import static import data_handler + def wait(seconds): timeout = time.time() + seconds - + while time.time() < timeout: time.sleep(0.01) - - + def get_crc_8(data): """ @@ -50,30 +50,34 @@ def get_crc_16(data): crc_data = crc_data.to_bytes(2, byteorder='big') return crc_data + def watchdog(): """ Author: DJ2LS - + watchdog master function. Frome here we call the watchdogs """ while True: time.sleep(0.01) data_channel_keep_alive_watchdog() + def data_channel_keep_alive_watchdog(): """ Author: DJ2LS - - + + """ - if static.ARQ_STATE == 'DATA' and static.TNC_STATE == 'BUSY': # and not static.ARQ_SEND_KEEP_ALIVE: + # and not static.ARQ_SEND_KEEP_ALIVE: + if static.ARQ_STATE == 'DATA' and static.TNC_STATE == 'BUSY': time.sleep(0.01) if static.ARQ_DATA_CHANNEL_LAST_RECEIVED + 30 > time.time(): pass else: static.ARQ_DATA_CHANNEL_LAST_RECEIVED = 0 - logging.info("DATA [" + str(static.MYCALLSIGN, 'utf-8') + "]<>[" + str(static.DXCALLSIGN, 'utf-8') + "] [BER." + str(static.BER) + "]") + logging.info("DATA [" + str(static.MYCALLSIGN, 'utf-8') + "]<>[" + str( + static.DXCALLSIGN, 'utf-8') + "] [BER." + str(static.BER) + "]") arq_reset_frame_machine() @@ -116,128 +120,141 @@ def arq_reset_frame_machine(): static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME = 0 static.ARQ_FRAME_BOF_RECEIVED = False static.ARQ_FRAME_EOF_RECEIVED = False - + static.ARQ_RX_BURST_BUFFER = [] static.ARQ_RX_FRAME_BUFFER = [] - + static.TNC_STATE = 'IDLE' static.ARQ_STATE = 'IDLE' - ###static.ARQ_CONNECTION_KEEP_ALIVE_RECEIVED = int(time.time()) # we need to reset the counter at this point + # static.ARQ_CONNECTION_KEEP_ALIVE_RECEIVED = int(time.time()) # we need to reset the counter at this point ###static.ARQ_SEND_KEEP_ALIVE = True static.CHANNEL_STATE = 'RECEIVING_SIGNALLING' static.ARQ_READY_FOR_DATA = False static.ARQ_START_OF_TRANSMISSION = 0 + def calculate_transfer_rate(): if static.ARQ_START_OF_TRANSMISSION > 0: static.TOTAL_TRANSMISSION_TIME = time.time() - static.ARQ_START_OF_TRANSMISSION - - print("ARQ_N_ARQ_FRAMES_PER_DATA_FRAME " + str(static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME)) - print("ARQ_RX_N_CURRENT_ARQ_FRAME " + str(static.ARQ_RX_N_CURRENT_ARQ_FRAME)) - - + print("ARQ_N_ARQ_FRAMES_PER_DATA_FRAME " + + str(static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME)) + print("ARQ_RX_N_CURRENT_ARQ_FRAME " + + str(static.ARQ_RX_N_CURRENT_ARQ_FRAME)) arq_n_arq_frames_per_data_frame = static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME arq_rx_n_current_arq_frame = static.ARQ_RX_N_CURRENT_ARQ_FRAME - + if static.TX_BUFFER_SIZE == 0: total_n_frames = arq_n_arq_frames_per_data_frame elif arq_n_arq_frames_per_data_frame == 0: total_n_frames = static.TX_BUFFER_SIZE else: total_n_frames = 0 - + if static.TOTAL_TRANSMISSION_TIME > 0: #total_transmission_time = time.time() - static.ARQ_START_OF_TRANSMISSION - total_transmission_time = static.TOTAL_TRANSMISSION_TIME - print("total_transmission_time: " + str(total_transmission_time)) + total_transmission_time = static.TOTAL_TRANSMISSION_TIME + print("total_transmission_time: " + str(total_transmission_time)) print("static.TOTAL_BYTES: " + str(static.TOTAL_BYTES)) - + static.ARQ_BITS_PER_SECOND = int( + (static.TOTAL_BYTES * 8) / total_transmission_time) + static.ARQ_BYTES_PER_MINUTE = int( + ((static.TOTAL_BYTES) / total_transmission_time) * 60) - static.ARQ_BITS_PER_SECOND = int((static.TOTAL_BYTES * 8) / total_transmission_time) - static.ARQ_BYTES_PER_MINUTE = int(((static.TOTAL_BYTES) / total_transmission_time) * 60) - burst_bytes = static.ARQ_PAYLOAD_PER_FRAME * static.ARQ_N_RX_FRAMES_PER_BURSTS burst_transmission_time = time.time() - static.ARQ_START_OF_BURST print("BURST TRANSMISSION TIME: " + str(burst_transmission_time)) - static.ARQ_BITS_PER_SECOND_BURST = int((burst_bytes * 8) / burst_transmission_time) - static.ARQ_BYTES_PER_MINUTE_BURST = int(((burst_bytes) / burst_transmission_time) * 60) - print("static.ARQ_BITS_PER_SECOND_BURST: " + str(static.ARQ_BITS_PER_SECOND_BURST)) - print("static.ARQ_BYTES_PER_MINUTE_BURST: " + str(static.ARQ_BYTES_PER_MINUTE_BURST)) - + static.ARQ_BITS_PER_SECOND_BURST = int( + (burst_bytes * 8) / burst_transmission_time) + static.ARQ_BYTES_PER_MINUTE_BURST = int( + ((burst_bytes) / burst_transmission_time) * 60) + print("static.ARQ_BITS_PER_SECOND_BURST: " + + str(static.ARQ_BITS_PER_SECOND_BURST)) + print("static.ARQ_BYTES_PER_MINUTE_BURST: " + + str(static.ARQ_BYTES_PER_MINUTE_BURST)) + # PERCENTAGE FOR TRANSMITTING if static.TX_BUFFER_SIZE > 0: print("static.ARQ_N_SENT_FRAMES: " + str(static.ARQ_N_SENT_FRAMES)) - static.ARQ_TRANSMISSION_PERCENT = int((static.ARQ_N_SENT_FRAMES / static.TX_BUFFER_SIZE) * 100) + static.ARQ_TRANSMISSION_PERCENT = int( + (static.ARQ_N_SENT_FRAMES / static.TX_BUFFER_SIZE) * 100) # PERCENTAGE FOR RECEIVING elif arq_n_arq_frames_per_data_frame > 0: - static.ARQ_TRANSMISSION_PERCENT = int((static.ARQ_RX_N_CURRENT_ARQ_FRAME / static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME) * 100) - + static.ARQ_TRANSMISSION_PERCENT = int( + (static.ARQ_RX_N_CURRENT_ARQ_FRAME / static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME) * 100) + else: - static.ARQ_TRANSMISSION_PERCENT = 0.0 - - print("static.ARQ_TRANSMISSION_PERCENT: " + str(static.ARQ_TRANSMISSION_PERCENT)) + static.ARQ_TRANSMISSION_PERCENT = 0.0 + + print("static.ARQ_TRANSMISSION_PERCENT: " + + str(static.ARQ_TRANSMISSION_PERCENT)) print("static.ARQ_BYTES_PER_MINUTE: " + str(static.ARQ_BYTES_PER_MINUTE)) print("static.ARQ_BITS_PER_SECOND: " + str(static.ARQ_BITS_PER_SECOND)) return [static.ARQ_BITS_PER_SECOND, static.ARQ_BYTES_PER_MINUTE, static.ARQ_BITS_PER_SECOND_BURST, static.ARQ_BYTES_PER_MINUTE_BURST] - -def add_to_heard_stations(dxcallsign,dxgrid, datatype, snr): + +def add_to_heard_stations(dxcallsign, dxgrid, datatype, snr): # check if buffer empty if len(static.HEARD_STATIONS) == 0: - static.HEARD_STATIONS.append([dxcallsign,dxgrid, int(time.time()), datatype, snr]) + static.HEARD_STATIONS.append( + [dxcallsign, dxgrid, int(time.time()), datatype, snr]) # if not, we search and update else: for i in range(0, len(static.HEARD_STATIONS)): # update callsign with new timestamp if static.HEARD_STATIONS[i].count(dxcallsign) > 0: - static.HEARD_STATIONS[i] = [dxcallsign,dxgrid, int(time.time()), datatype, snr] + static.HEARD_STATIONS[i] = [dxcallsign, + dxgrid, int(time.time()), datatype, snr] break # insert if nothing found if i == len(static.HEARD_STATIONS) - 1: - static.HEARD_STATIONS.append([dxcallsign,dxgrid, int(time.time()), datatype, snr]) + static.HEARD_STATIONS.append( + [dxcallsign, dxgrid, int(time.time()), datatype, snr]) break - - + + # for idx, item in enumerate(static.HEARD_STATIONS): # if dxcallsign in item: # item = [dxcallsign, int(time.time())] -# static.HEARD_STATIONS[idx] = item - +# static.HEARD_STATIONS[idx] = item + def setup_logging(): """ Author: DJ2LS Set the custom logging format so we can use colors - + # https://stackoverflow.com/questions/384076/how-can-i-color-python-logging-output # 'DEBUG' : 37, # white # 'INFO' : 36, # cyan # 'WARNING' : 33, # yellow # 'ERROR' : 31, # red # 'CRITICAL': 41, # white on red bg - + """ - logging.basicConfig(level=logging.INFO, \ - encoding='utf-8', \ - format='%(asctime)s.%(msecs)03d %(levelname)s:\t%(message)s', \ - datefmt='%H:%M:%S', \ - handlers=[logging.FileHandler("codec2-FreeDATA-TNC.log"),logging.StreamHandler()] - ) + logging.basicConfig(level=logging.INFO, + encoding='utf-8', + format='%(asctime)s.%(msecs)03d %(levelname)s:\t%(message)s', + datefmt='%H:%M:%S', + handlers=[logging.FileHandler( + "codec2-FreeDATA-TNC.log"), logging.StreamHandler()] + ) - logging.addLevelName(logging.DEBUG, "\033[1;36m%s\033[1;0m" % logging.getLevelName(logging.DEBUG)) - logging.addLevelName(logging.INFO, "\033[1;37m%s\033[1;0m" % logging.getLevelName(logging.INFO)) - logging.addLevelName(logging.WARNING, "\033[1;33m%s\033[1;0m" % logging.getLevelName(logging.WARNING)) + logging.addLevelName( + logging.DEBUG, "\033[1;36m%s\033[1;0m" % logging.getLevelName(logging.DEBUG)) + logging.addLevelName( + logging.INFO, "\033[1;37m%s\033[1;0m" % logging.getLevelName(logging.INFO)) + logging.addLevelName( + logging.WARNING, "\033[1;33m%s\033[1;0m" % logging.getLevelName(logging.WARNING)) logging.addLevelName(logging.ERROR, "\033[1;31m%s\033[1;0m" % "FAILED") #logging.addLevelName( logging.ERROR, "\033[1;31m%s\033[1;0m" % logging.getLevelName(logging.ERROR)) - logging.addLevelName(logging.CRITICAL, "\033[1;41m%s\033[1;0m" % logging.getLevelName(logging.CRITICAL)) + logging.addLevelName( + logging.CRITICAL, "\033[1;41m%s\033[1;0m" % logging.getLevelName(logging.CRITICAL)) logging.addLevelName(25, "\033[1;32m%s\033[1;0m" % "SUCCESS") logging.addLevelName(24, "\033[1;34m%s\033[1;0m" % "DATA") - - diff --git a/tnc/modem.py b/tnc/modem.py index f4f5aa3e..cf6c4f29 100644 --- a/tnc/modem.py +++ b/tnc/modem.py @@ -5,25 +5,24 @@ Created on Wed Dec 23 07:04:24 2020 @author: DJ2LS """ - +import sys import ctypes from ctypes import * import pathlib -import pyaudio import audioop -import asyncio -#import sys +#import asyncio import logging import time import threading import atexit - +import numpy as np +import pyaudio import helpers import static import data_handler -import sys -#sys.path.append("hamlib/linux") + +# sys.path.append("hamlib/linux") try: import Hamlib print("running Hamlib from Sys Path") @@ -34,7 +33,7 @@ else: # place for rigctld pass -import numpy as np + #import rigctld #rigctld = rigctld.Rigctld() @@ -42,27 +41,28 @@ import numpy as np MODEM_STATS_NR_MAX = 320 MODEM_STATS_NC_MAX = 51 + 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), - ("nr", ctypes.c_int), - ("sync", ctypes.c_int), - ("foff", ctypes.c_float), - ("rx_timing", ctypes.c_float), - ("clock_offset", ctypes.c_float), - ("sync_metric", ctypes.c_float), - ("pre", ctypes.c_int), - ("post", ctypes.c_int), - ("uw_fails", ctypes.c_int), - ] + _fields_ = [ + ("Nc", ctypes.c_int), + ("snr_est", ctypes.c_float), + ("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), + ("rx_timing", ctypes.c_float), + ("clock_offset", ctypes.c_float), + ("sync_metric", ctypes.c_float), + ("pre", ctypes.c_int), + ("post", ctypes.c_int), + ("uw_fails", ctypes.c_int), + ] class RF(): - def __init__(self): - + def __init__(self): + # -------------------------------------------- LOAD FREEDV try: # we check at first for libcodec2 in root - necessary if we want to run it inside a pyinstaller binary @@ -99,20 +99,23 @@ class RF(): self.audio_writing_to_stream = False # --------------------------------------------START DECODER THREAD - DECODER_THREAD = threading.Thread(target=self.receive, name="DECODER_THREAD") + DECODER_THREAD = threading.Thread( + target=self.receive, name="DECODER_THREAD") DECODER_THREAD.start() - PLAYBACK_THREAD = threading.Thread(target=self.play_audio, name="PLAYBACK_THREAD") + PLAYBACK_THREAD = threading.Thread( + target=self.play_audio, name="PLAYBACK_THREAD") PLAYBACK_THREAD.start() self.fft_data = bytes() - FFT_THREAD = threading.Thread(target=self.calculate_fft, name="FFT_THREAD") + FFT_THREAD = threading.Thread( + target=self.calculate_fft, name="FFT_THREAD") FFT_THREAD.start() # --------------------------------------------CONFIGURE HAMLIB - #my_rig.set_ptt(Hamlib.RIG_PTT_RIG,0) - #my_rig.set_ptt(Hamlib.RIG_PTT_SERIAL_DTR,0) - #my_rig.set_ptt(Hamlib.RIG_PTT_SERIAL_RTS,1) + # my_rig.set_ptt(Hamlib.RIG_PTT_RIG,0) + # my_rig.set_ptt(Hamlib.RIG_PTT_SERIAL_DTR,0) + # my_rig.set_ptt(Hamlib.RIG_PTT_SERIAL_RTS,1) #self.my_rig.set_conf("dtr_state", "OFF") #my_rig.set_conf("rts_state", "OFF") #self.my_rig.set_conf("ptt_type", "RTS") @@ -128,221 +131,241 @@ class RF(): self.my_rig.set_conf("serial_handshake", "None") self.my_rig.set_conf("stop_bits", "1") self.my_rig.set_conf("data_bits", "8") - if static.HAMLIB_PTT_TYPE == 'RIG': self.hamlib_ptt_type = Hamlib.RIG_PTT_RIG - + elif static.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 static.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 static.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") - + self.my_rig.set_conf("ptt_type", "RTS") + elif static.HAMLIB_PTT_TYPE == 'PARALLEL': self.hamlib_ptt_type = Hamlib.RIG_PTT_PARALLEL - + elif static.HAMLIB_PTT_TYPE == 'MICDATA': self.hamlib_ptt_type = Hamlib.RIG_PTT_RIG_MICDATA - + elif static.HAMLIB_PTT_TYPE == 'CM108': self.hamlib_ptt_type = Hamlib.RIG_PTT_CM108 - + else: # static.HAMLIB_PTT_TYPE == 'RIG_PTT_NONE': self.hamlib_ptt_type = Hamlib.RIG_PTT_NONE - self.my_rig.open() atexit.register(self.my_rig.close) - + # set rig mode to USB self.my_rig.set_mode(Hamlib.RIG_MODE_USB) - + # start thread for getting hamlib data - HAMLIB_THREAD = threading.Thread(target=self.get_radio_stats, name="HAMLIB_THREAD") + HAMLIB_THREAD = threading.Thread( + target=self.get_radio_stats, name="HAMLIB_THREAD") HAMLIB_THREAD.start() - + except: print("Unexpected error:", sys.exc_info()[0]) print("can't open rig") sys.exit("hamlib error") - + # -------------------------------------------------------------------------------------------------------- + def ptt_and_wait(self, state): static.PTT_STATE = state - + if state: self.my_rig.set_ptt(self.hamlib_ptt_type, 1) - #rigctld.ptt_enable() + # rigctld.ptt_enable() ptt_toggle_timeout = time.time() + 0.5 while time.time() < ptt_toggle_timeout: pass - else: - + ptt_toggle_timeout = time.time() + 0.5 while time.time() < ptt_toggle_timeout: pass - - self.my_rig.set_ptt(self.hamlib_ptt_type, 0) - #rigctld.ptt_disable() - - return False + self.my_rig.set_ptt(self.hamlib_ptt_type, 0) + # rigctld.ptt_disable() + + return False def play_audio(self): while True: time.sleep(0.01) - #while len(self.streambuffer) > 0: + # while len(self.streambuffer) > 0: # time.sleep(0.01) if len(self.streambuffer) > 0 and self.audio_writing_to_stream: self.streambuffer = bytes(self.streambuffer) - + # we need t wait a little bit until the buffer is filled. If we are not waiting, we are sending empty data time.sleep(0.1) self.stream_tx.write(self.streambuffer) # clear stream buffer after sending self.streambuffer = bytes() - + self.audio_writing_to_stream = False # -------------------------------------------------------------------------------------------------------- def transmit_signalling(self, data_out, count): state_before_transmit = static.CHANNEL_STATE static.CHANNEL_STATE = 'SENDING_SIGNALLING' - #print(static.CHANNEL_STATE) - + # print(static.CHANNEL_STATE) + self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte) freedv = self.c_lib.freedv_open(static.FREEDV_SIGNALLING_MODE) - bytes_per_frame = int(self.c_lib.freedv_get_bits_per_modem_frame(freedv) / 8) + bytes_per_frame = int( + self.c_lib.freedv_get_bits_per_modem_frame(freedv) / 8) payload_per_frame = bytes_per_frame - 2 n_nom_modem_samples = self.c_lib.freedv_get_n_nom_modem_samples(freedv) - n_tx_modem_samples = self.c_lib.freedv_get_n_tx_modem_samples(freedv) # get n_tx_modem_samples which defines the size of the modulation object - n_tx_preamble_modem_samples = self.c_lib.freedv_get_n_tx_preamble_modem_samples(freedv) - n_tx_postamble_modem_samples = self.c_lib.freedv_get_n_tx_postamble_modem_samples(freedv) - + # get n_tx_modem_samples which defines the size of the modulation object + n_tx_modem_samples = self.c_lib.freedv_get_n_tx_modem_samples(freedv) + n_tx_preamble_modem_samples = self.c_lib.freedv_get_n_tx_preamble_modem_samples( + freedv) + n_tx_postamble_modem_samples = self.c_lib.freedv_get_n_tx_postamble_modem_samples( + freedv) + mod_out = ctypes.c_short * n_tx_modem_samples mod_out = mod_out() - - mod_out_preamble = ctypes.c_short * n_tx_preamble_modem_samples # *2 #1760 for mode 10,11,12 #4000 for mode 9 + + # *2 #1760 for mode 10,11,12 #4000 for mode 9 + mod_out_preamble = ctypes.c_short * n_tx_preamble_modem_samples mod_out_preamble = mod_out_preamble() - mod_out_postamble = ctypes.c_short * n_tx_postamble_modem_samples # *2 #1760 for mode 10,11,12 #4000 for mode 9 + # *2 #1760 for mode 10,11,12 #4000 for mode 9 + mod_out_postamble = ctypes.c_short * n_tx_postamble_modem_samples mod_out_postamble = mod_out_postamble() - 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 + # use this if CRC16 checksum is required ( DATA1-3) + buffer = bytearray(payload_per_frame) + # set buffersize to length of data which will be send + buffer[:len(data_out)] = data_out - crc = ctypes.c_ushort(self.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 + crc = ctypes.c_ushort(self.c_lib.freedv_gen_crc16( + bytes(buffer), payload_per_frame)) # generate CRC16 + # convert crc to 2 byte hex string + crc = crc.value.to_bytes(2, byteorder='big') buffer += crc # append crc16 to buffer data = (ctypes.c_ubyte * bytes_per_frame).from_buffer_copy(buffer) self.c_lib.freedv_rawdatapreambletx(freedv, mod_out_preamble) - self.c_lib.freedv_rawdatatx(freedv, mod_out, data) # modulate DATA and safe it into mod_out pointer + # modulate DATA and safe it into mod_out pointer + self.c_lib.freedv_rawdatatx(freedv, mod_out, data) self.c_lib.freedv_rawdatapostambletx(freedv, mod_out_postamble) self.streambuffer = bytearray() self.streambuffer += bytes(mod_out_preamble) self.streambuffer += bytes(mod_out) self.streambuffer += bytes(mod_out_postamble) - - converted_audio = audioop.ratecv(self.streambuffer,2,1,static.MODEM_SAMPLE_RATE, static.AUDIO_SAMPLE_RATE_TX, None) + + converted_audio = audioop.ratecv( + self.streambuffer, 2, 1, static.MODEM_SAMPLE_RATE, static.AUDIO_SAMPLE_RATE_TX, None) self.streambuffer = bytes(converted_audio[0]) # append frame again with as much as in count defined for i in range(1, count): self.streambuffer += bytes(converted_audio[0]) - #print(len(self.streambuffer)) + # print(len(self.streambuffer)) #self.streambuffer += bytes(converted_audio[0]) - #print(len(self.streambuffer)) - + # print(len(self.streambuffer)) + # -------------- transmit audio #logging.debug("SENDING SIGNALLING FRAME " + str(data_out)) ##state_before_transmit = static.CHANNEL_STATE ##static.CHANNEL_STATE = 'SENDING_SIGNALLING' - + while self.ptt_and_wait(True): pass self.audio_writing_to_stream = True - + # wait until audio has been processed while self.audio_writing_to_stream: time.sleep(0.01) static.CHANNEL_STATE = 'SENDING_SIGNALLING' - self.ptt_and_wait(False) - ## we have a problem with the receiving state + self.ptt_and_wait(False) + # we have a problem with the receiving state ##static.CHANNEL_STATE = state_before_transmit if state_before_transmit != 'RECEIVING_DATA': static.CHANNEL_STATE = 'RECEIVING_SIGNALLING' else: static.CHANNEL_STATE = state_before_transmit - + self.c_lib.freedv_close(freedv) # -------------------------------------------------------------------------------------------------------- # GET ARQ BURST FRAME VOM BUFFER AND MODULATE IT def transmit_arq_burst(self): - + # we could place this timing part inside the modem... # lets see if this is a good idea.. - static.ARQ_DATA_CHANNEL_LAST_RECEIVED = int(time.time()) # we need to update our timeout timestamp - static.ARQ_START_OF_BURST = int(time.time()) # we need to update our timeout timestamp - + # we need to update our timeout timestamp + static.ARQ_DATA_CHANNEL_LAST_RECEIVED = int(time.time()) + # we need to update our timeout timestamp + static.ARQ_START_OF_BURST = int(time.time()) + state_before_transmit = static.CHANNEL_STATE static.CHANNEL_STATE = 'SENDING_DATA' self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte) freedv = self.c_lib.freedv_open(static.ARQ_DATA_CHANNEL_MODE) - static.FREEDV_DATA_BYTES_PER_FRAME = int(self.c_lib.freedv_get_bits_per_modem_frame(freedv) / 8) + static.FREEDV_DATA_BYTES_PER_FRAME = int( + self.c_lib.freedv_get_bits_per_modem_frame(freedv) / 8) static.FREEDV_DATA_PAYLOAD_PER_FRAME = static.FREEDV_DATA_BYTES_PER_FRAME - 2 n_nom_modem_samples = self.c_lib.freedv_get_n_nom_modem_samples(freedv) - n_tx_modem_samples = self.c_lib.freedv_get_n_tx_modem_samples(freedv) # *2 #get n_tx_modem_samples which defines the size of the modulation object - n_tx_preamble_modem_samples = self.c_lib.freedv_get_n_tx_preamble_modem_samples(freedv) - n_tx_postamble_modem_samples = self.c_lib.freedv_get_n_tx_postamble_modem_samples(freedv) - + # *2 #get n_tx_modem_samples which defines the size of the modulation object + n_tx_modem_samples = self.c_lib.freedv_get_n_tx_modem_samples(freedv) + n_tx_preamble_modem_samples = self.c_lib.freedv_get_n_tx_preamble_modem_samples( + freedv) + n_tx_postamble_modem_samples = self.c_lib.freedv_get_n_tx_postamble_modem_samples( + freedv) + mod_out = ctypes.c_short * n_tx_modem_samples mod_out = mod_out() - - mod_out_preamble = ctypes.c_short * n_tx_preamble_modem_samples # *2 #1760 for mode 10,11,12 #4000 for mode 9 + + # *2 #1760 for mode 10,11,12 #4000 for mode 9 + mod_out_preamble = ctypes.c_short * n_tx_preamble_modem_samples mod_out_preamble = mod_out_preamble() - mod_out_postamble = ctypes.c_short * n_tx_postamble_modem_samples # *2 #1760 for mode 10,11,12 #4000 for mode 9 + # *2 #1760 for mode 10,11,12 #4000 for mode 9 + mod_out_postamble = ctypes.c_short * n_tx_postamble_modem_samples mod_out_postamble = mod_out_postamble() - + self.streambuffer = bytearray() self.c_lib.freedv_rawdatapreambletx(freedv, mod_out_preamble) self.streambuffer += bytes(mod_out_preamble) - + if not static.ARQ_RPT_RECEIVED: - + for n in range(0, static.ARQ_TX_N_FRAMES_PER_BURST): # ---------------------------BUILD ARQ BURST --------------------------------------------------------------------- frame_type = 10 + n + 1 # static.ARQ_TX_N_FRAMES_PER_BURST frame_type = bytes([frame_type]) - payload_data = bytes(static.TX_BUFFER[static.ARQ_N_SENT_FRAMES + n]) + payload_data = bytes( + static.TX_BUFFER[static.ARQ_N_SENT_FRAMES + n]) n_current_arq_frame = static.ARQ_N_SENT_FRAMES + n + 1 - static.ARQ_TX_N_CURRENT_ARQ_FRAME = n_current_arq_frame.to_bytes(2, byteorder='big') + static.ARQ_TX_N_CURRENT_ARQ_FRAME = n_current_arq_frame.to_bytes( + 2, byteorder='big') n_total_arq_frame = len(static.TX_BUFFER) #static.ARQ_TX_N_TOTAL_ARQ_FRAMES = n_total_arq_frame @@ -355,18 +378,23 @@ class RF(): static.MYCALLSIGN_CRC8 + \ payload_data - buffer = bytearray(static.FREEDV_DATA_PAYLOAD_PER_FRAME) # create TX buffer - buffer[:len(arqframe)] = arqframe # set buffersize to length of data which will be send + # create TX buffer + buffer = bytearray(static.FREEDV_DATA_PAYLOAD_PER_FRAME) + # set buffersize to length of data which will be send + buffer[:len(arqframe)] = arqframe - crc = ctypes.c_ushort(self.c_lib.freedv_gen_crc16(bytes(buffer), static.FREEDV_DATA_PAYLOAD_PER_FRAME)) # generate CRC16 - crc = crc.value.to_bytes(2, byteorder='big') # convert crc to 2 byte hex string + crc = ctypes.c_ushort(self.c_lib.freedv_gen_crc16( + bytes(buffer), static.FREEDV_DATA_PAYLOAD_PER_FRAME)) # generate CRC16 + # convert crc to 2 byte hex string + crc = crc.value.to_bytes(2, byteorder='big') buffer += crc # append crc16 to buffer - data = (ctypes.c_ubyte * static.FREEDV_DATA_BYTES_PER_FRAME).from_buffer_copy(buffer) - - self.c_lib.freedv_rawdatatx(freedv, mod_out, data) # modulate DATA and safe it into mod_out pointer + data = ( + ctypes.c_ubyte * static.FREEDV_DATA_BYTES_PER_FRAME).from_buffer_copy(buffer) + + # modulate DATA and safe it into mod_out pointer + self.c_lib.freedv_rawdatatx(freedv, mod_out, data) self.streambuffer += bytes(mod_out) - elif static.ARQ_RPT_RECEIVED: @@ -378,12 +406,14 @@ class RF(): frame_type = bytes([frame_type]) try: - payload_data = bytes(static.TX_BUFFER[static.ARQ_N_SENT_FRAMES + missing_frame - 1]) + payload_data = bytes( + static.TX_BUFFER[static.ARQ_N_SENT_FRAMES + missing_frame - 1]) except: print("modem buffer selection problem with ARQ RPT frames") - + n_current_arq_frame = static.ARQ_N_SENT_FRAMES + missing_frame - static.ARQ_TX_N_CURRENT_ARQ_FRAME = n_current_arq_frame.to_bytes(2, byteorder='big') + static.ARQ_TX_N_CURRENT_ARQ_FRAME = n_current_arq_frame.to_bytes( + 2, byteorder='big') n_total_arq_frame = len(static.TX_BUFFER) #static.ARQ_TX_N_TOTAL_ARQ_FRAMES = n_total_arq_frame @@ -396,28 +426,33 @@ class RF(): static.MYCALLSIGN_CRC8 + \ payload_data - buffer = bytearray(static.FREEDV_DATA_PAYLOAD_PER_FRAME) # create TX buffer - buffer[:len(arqframe)] = arqframe # set buffersize to length of data which will be send + # create TX buffer + buffer = bytearray(static.FREEDV_DATA_PAYLOAD_PER_FRAME) + # set buffersize to length of data which will be send + buffer[:len(arqframe)] = arqframe - crc = ctypes.c_ushort(self.c_lib.freedv_gen_crc16(bytes(buffer), static.FREEDV_DATA_PAYLOAD_PER_FRAME)) # generate CRC16 - crc = crc.value.to_bytes(2, byteorder='big') # convert crc to 2 byte hex string + crc = ctypes.c_ushort(self.c_lib.freedv_gen_crc16( + bytes(buffer), static.FREEDV_DATA_PAYLOAD_PER_FRAME)) # generate CRC16 + # convert crc to 2 byte hex string + crc = crc.value.to_bytes(2, byteorder='big') buffer += crc # append crc16 to buffer - data = (ctypes.c_ubyte * static.FREEDV_DATA_BYTES_PER_FRAME).from_buffer_copy(buffer) - - self.c_lib.freedv_rawdatatx(freedv, mod_out, data) # modulate DATA and safe it into mod_out pointer + data = ( + ctypes.c_ubyte * static.FREEDV_DATA_BYTES_PER_FRAME).from_buffer_copy(buffer) + + # modulate DATA and safe it into mod_out pointer + self.c_lib.freedv_rawdatatx(freedv, mod_out, data) self.streambuffer += bytes(mod_out) - self.c_lib.freedv_rawdatapostambletx(freedv, mod_out_postamble) self.streambuffer += bytes(mod_out_postamble) - - converted_audio = audioop.ratecv(self.streambuffer,2,1,static.MODEM_SAMPLE_RATE, static.AUDIO_SAMPLE_RATE_TX, None) + + converted_audio = audioop.ratecv( + self.streambuffer, 2, 1, static.MODEM_SAMPLE_RATE, static.AUDIO_SAMPLE_RATE_TX, None) self.streambuffer = bytes(converted_audio[0]) - # -------------- transmit audio - + while self.ptt_and_wait(True): pass # this triggers writing buffer to audio stream @@ -439,22 +474,23 @@ class RF(): # -------------------------------------------------------------------------------------------------------- def receive(self): - + # DATAC0 self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte) datac0_freedv = self.c_lib.freedv_open(14) self.c_lib.freedv_get_bits_per_modem_frame(datac0_freedv) datac0_bytes_per_frame = int(self.c_lib.freedv_get_bits_per_modem_frame(datac0_freedv)/8) - datac0_n_max_modem_samples = self.c_lib.freedv_get_n_max_modem_samples(datac0_freedv) - - datac0_bytes_out = (ctypes.c_ubyte * datac0_bytes_per_frame) #bytes_per_frame - datac0_bytes_out = datac0_bytes_out() #get pointer from bytes_out - - self.c_lib.freedv_set_frames_per_burst(datac0_freedv,1) + datac0_n_max_modem_samples = self.c_lib.freedv_get_n_max_modem_samples(datac0_freedv) + + # bytes_per_frame + datac0_bytes_out = (ctypes.c_ubyte * datac0_bytes_per_frame) + datac0_bytes_out = datac0_bytes_out() # get pointer from bytes_out + + self.c_lib.freedv_set_frames_per_burst(datac0_freedv, 1) datac0_modem_stats_snr = c_float() datac0_modem_stats_sync = c_int() datac0_buffer = bytes() - + static.FREEDV_SIGNALLING_BYTES_PER_FRAME = datac0_bytes_per_frame static.FREEDV_SIGNALLING_PAYLOAD_PER_FRAME = datac0_bytes_per_frame - 2 @@ -462,10 +498,11 @@ class RF(): self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte) datac1_freedv = self.c_lib.freedv_open(10) datac1_bytes_per_frame = int(self.c_lib.freedv_get_bits_per_modem_frame(datac1_freedv)/8) - datac1_n_max_modem_samples = self.c_lib.freedv_get_n_max_modem_samples(datac1_freedv) - datac1_bytes_out = (ctypes.c_ubyte * datac1_bytes_per_frame) #bytes_per_frame - datac1_bytes_out = datac1_bytes_out() #get pointer from bytes_out - self.c_lib.freedv_set_frames_per_burst(datac1_freedv,1) + datac1_n_max_modem_samples = self.c_lib.freedv_get_n_max_modem_samples(datac1_freedv) + # bytes_per_frame + datac1_bytes_out = (ctypes.c_ubyte * datac1_bytes_per_frame) + datac1_bytes_out = datac1_bytes_out() # get pointer from bytes_out + self.c_lib.freedv_set_frames_per_burst(datac1_freedv, 1) datac1_modem_stats_snr = c_float() datac1_modem_stats_sync = c_int() datac1_buffer = bytes() @@ -474,10 +511,11 @@ class RF(): self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte) datac3_freedv = self.c_lib.freedv_open(12) datac3_bytes_per_frame = int(self.c_lib.freedv_get_bits_per_modem_frame(datac3_freedv)/8) - datac3_n_max_modem_samples = self.c_lib.freedv_get_n_max_modem_samples(datac3_freedv) - datac3_bytes_out = (ctypes.c_ubyte * datac3_bytes_per_frame) #bytes_per_frame - datac3_bytes_out = datac3_bytes_out() #get pointer from bytes_out - self.c_lib.freedv_set_frames_per_burst(datac3_freedv,1) + datac3_n_max_modem_samples = self.c_lib.freedv_get_n_max_modem_samples(datac3_freedv) + # bytes_per_frame + datac3_bytes_out = (ctypes.c_ubyte * datac3_bytes_per_frame) + datac3_bytes_out = datac3_bytes_out() # get pointer from bytes_out + self.c_lib.freedv_set_frames_per_burst(datac3_freedv, 1) datac3_modem_stats_snr = c_float() datac3_modem_stats_sync = c_int() datac3_buffer = bytes() @@ -503,242 +541,240 @@ class RF(): ''' data_in = bytes() - data_in = self.stream_rx.read(1024, exception_on_overflow = False) + data_in = self.stream_rx.read(1024, exception_on_overflow=False) #self.fft_data = data_in - data_in = audioop.ratecv(data_in,2,1,static.AUDIO_SAMPLE_RATE_RX, static.MODEM_SAMPLE_RATE, None) - data_in = data_in[0]#.rstrip(b'\x00') + data_in = audioop.ratecv(data_in, 2, 1, static.AUDIO_SAMPLE_RATE_RX, static.MODEM_SAMPLE_RATE, None) + data_in = data_in[0] # .rstrip(b'\x00') self.fft_data = data_in - + # we need to set nin * 2 beause of byte size in array handling datac0_nin = self.c_lib.freedv_nin(datac0_freedv) * 2 datac1_nin = self.c_lib.freedv_nin(datac1_freedv) * 2 datac3_nin = self.c_lib.freedv_nin(datac3_freedv) * 2 - + # refill buffer only if every mode has worked with its data if (len(datac0_buffer) < (datac0_nin*2)) and (len(datac1_buffer) < (datac1_nin*2)) and (len(datac3_buffer) < (datac3_nin*2)): datac0_buffer += data_in datac1_buffer += data_in datac3_buffer += data_in - - - - # DECODING DATAC0 + + # DECODING DATAC0 if len(datac0_buffer) >= (datac0_nin): - + datac0_audio = datac0_buffer[:datac0_nin] - datac0_buffer = datac0_buffer[datac0_nin:] - #print(len(datac0_audio)) + datac0_buffer = datac0_buffer[datac0_nin:] + # print(len(datac0_audio)) self.c_lib.freedv_rawdatarx.argtype = [ctypes.POINTER(ctypes.c_ubyte), datac0_bytes_out, datac0_audio] - nbytes = self.c_lib.freedv_rawdatarx(datac0_freedv, datac0_bytes_out, datac0_audio) # demodulate audio + nbytes = self.c_lib.freedv_rawdatarx(datac0_freedv, datac0_bytes_out, datac0_audio) # demodulate audio sync = self.c_lib.freedv_get_rx_status(datac0_freedv) - if sync != 0 and nbytes != 0: - - #calculate snr and scatter + if sync != 0 and nbytes != 0: + + # calculate snr and scatter self.get_scatter(datac0_freedv) self.calculate_snr(datac0_freedv) datac0_task = threading.Thread(target=self.process_data, args=[datac0_bytes_out, datac0_freedv]) datac0_task.start() - - - # DECODING DATAC1 + # DECODING DATAC1 if len(datac1_buffer) >= (datac1_nin): datac1_audio = datac1_buffer[:datac1_nin] - datac1_buffer = datac1_buffer[datac1_nin:] - #print(len(datac1_audio)) + datac1_buffer = datac1_buffer[datac1_nin:] + # print(len(datac1_audio)) self.c_lib.freedv_rawdatarx.argtype = [ctypes.POINTER(ctypes.c_ubyte), datac1_bytes_out, datac1_audio] - nbytes = self.c_lib.freedv_rawdatarx(datac1_freedv, datac1_bytes_out, datac1_audio) # demodulate audio - + nbytes = self.c_lib.freedv_rawdatarx(datac1_freedv, datac1_bytes_out, datac1_audio) # demodulate audio + sync = self.c_lib.freedv_get_rx_status(datac1_freedv) if sync != 0 and nbytes != 0: - - #calculate snr and scatter + + # calculate snr and scatter self.get_scatter(datac1_freedv) self.calculate_snr(datac1_freedv) datac1_task = threading.Thread(target=self.process_data, args=[datac1_bytes_out, datac1_freedv]) - datac1_task.start() - - # DECODING DATAC3 + datac1_task.start() + + # DECODING DATAC3 if len(datac3_buffer) >= (datac3_nin): datac3_audio = datac3_buffer[:datac3_nin] - datac3_buffer = datac3_buffer[datac3_nin:] + datac3_buffer = datac3_buffer[datac3_nin:] self.c_lib.freedv_rawdatarx.argtype = [ctypes.POINTER(ctypes.c_ubyte), datac3_bytes_out, datac3_audio] - nbytes = self.c_lib.freedv_rawdatarx(datac3_freedv, datac3_bytes_out, datac3_audio) # demodulate audio - + nbytes = self.c_lib.freedv_rawdatarx(datac3_freedv, datac3_bytes_out, datac3_audio) # demodulate audio + sync = self.c_lib.freedv_get_rx_status(datac3_freedv) if sync != 0 and nbytes != 0: - - #calculate snr and scatter + + # calculate snr and scatter self.get_scatter(datac3_freedv) self.calculate_snr(datac3_freedv) datac3_task = threading.Thread(target=self.process_data, args=[datac3_bytes_out, datac3_freedv]) datac3_task.start() - - + # forward data only if broadcast or we are the receiver # bytes_out[1:2] == callsign check for signalling frames, bytes_out[6:7] == callsign check for data frames, bytes_out[1:2] == b'\x01' --> broadcasts like CQ # we could also create an own function, which returns True. In this case we could add callsign blacklists and so on - + def process_data(self, bytes_out, freedv): force = True print(bytes(bytes_out)) if bytes(bytes_out[1:2]) == static.MYCALLSIGN_CRC8 or bytes(bytes_out[6:7]) == static.MYCALLSIGN_CRC8 or bytes(bytes_out[1:2]) == b'\x01': - - helpers.calculate_transfer_rate() - # CHECK IF FRAMETYPE IS BETWEEN 10 and 50 ------------------------ - frametype = int.from_bytes(bytes(bytes_out[:1]), "big") - frame = frametype - 10 - n_frames_per_burst = int.from_bytes(bytes(bytes_out[1:2]), "big") - #self.c_lib.freedv_set_frames_per_burst(freedv_data, n_frames_per_burst); + helpers.calculate_transfer_rate() + # CHECK IF FRAMETYPE IS BETWEEN 10 and 50 ------------------------ + frametype = int.from_bytes(bytes(bytes_out[:1]), "big") + frame = frametype - 10 + n_frames_per_burst = int.from_bytes(bytes(bytes_out[1:2]), "big") - if 50 >= frametype >= 10: - if frame != 3 or force == True: + #self.c_lib.freedv_set_frames_per_burst(freedv_data, n_frames_per_burst); - data_handler.arq_data_received(bytes(bytes_out[:-2])) # send payload data to arq checker without CRC16 + if 50 >= frametype >= 10: + if frame != 3 or force == True: - #print("static.ARQ_RX_BURST_BUFFER.count(None) " + str(static.ARQ_RX_BURST_BUFFER.count(None))) - if static.ARQ_RX_BURST_BUFFER.count(None) <= 1: - logging.debug("FULL BURST BUFFER ---> UNSYNC") - self.c_lib.freedv_set_sync(freedv, 0) + # send payload data to arq checker without CRC16 + data_handler.arq_data_received(bytes(bytes_out[:-2])) - else: - logging.critical("---------------------------SIMULATED MISSING FRAME") - force = True + #print("static.ARQ_RX_BURST_BUFFER.count(None) " + str(static.ARQ_RX_BURST_BUFFER.count(None))) + if static.ARQ_RX_BURST_BUFFER.count(None) <= 1: + logging.debug("FULL BURST BUFFER ---> UNSYNC") + self.c_lib.freedv_set_sync(freedv, 0) - # BURST ACK - elif frametype == 60: - logging.debug("ACK RECEIVED....") - data_handler.burst_ack_received() + else: + logging.critical( + "---------------------------SIMULATED MISSING FRAME") + force = True - # FRAME ACK - elif frametype == 61: - logging.debug("FRAME ACK RECEIVED....") - data_handler.frame_ack_received() + # BURST ACK + elif frametype == 60: + logging.debug("ACK RECEIVED....") + data_handler.burst_ack_received() - # FRAME RPT - elif frametype == 62: - logging.debug("REPEAT REQUEST RECEIVED....") - data_handler.burst_rpt_received(bytes_out[:-2]) + # FRAME ACK + elif frametype == 61: + logging.debug("FRAME ACK RECEIVED....") + data_handler.frame_ack_received() - # FRAME NAK - elif frametype == 63: - logging.debug("FRAME NAK RECEIVED....") - data_handler.frame_nack_received(bytes_out[:-2]) - - # CQ FRAME - elif frametype == 200: - logging.debug("CQ RECEIVED....") - data_handler.received_cq(bytes_out[:-2]) + # FRAME RPT + elif frametype == 62: + logging.debug("REPEAT REQUEST RECEIVED....") + data_handler.burst_rpt_received(bytes_out[:-2]) - # PING FRAME - elif frametype == 210: - logging.debug("PING RECEIVED....") - data_handler.received_ping(bytes_out[:-2]) + # FRAME NAK + elif frametype == 63: + logging.debug("FRAME NAK RECEIVED....") + data_handler.frame_nack_received(bytes_out[:-2]) - # PING ACK - elif frametype == 211: - logging.debug("PING ACK RECEIVED....") - data_handler.received_ping_ack(bytes_out[:-2]) + # CQ FRAME + elif frametype == 200: + logging.debug("CQ RECEIVED....") + data_handler.received_cq(bytes_out[:-2]) - # ARQ CONNECT - elif frametype == 220: - logging.info("ARQ CONNECT RECEIVED....") - data_handler.arq_received_connect(bytes_out[:-2]) + # PING FRAME + elif frametype == 210: + logging.debug("PING RECEIVED....") + data_handler.received_ping(bytes_out[:-2]) - # ARQ CONNECT ACK / KEEP ALIVE - elif frametype == 221: - logging.info("ARQ CONNECT ACK RECEIVED / KEEP ALIVE....") - data_handler.arq_received_connect_keep_alive(bytes_out[:-2]) + # PING ACK + elif frametype == 211: + logging.debug("PING ACK RECEIVED....") + data_handler.received_ping_ack(bytes_out[:-2]) - # ARQ CONNECT ACK / KEEP ALIVE - elif frametype == 222: - logging.debug("ARQ DISCONNECT RECEIVED") - data_handler.arq_disconnect_received(bytes_out[:-2]) + # ARQ CONNECT + # elif frametype == 220: + # logging.info("ARQ CONNECT RECEIVED....") + # data_handler.arq_received_connect(bytes_out[:-2]) - # ARQ FILE TRANSFER RECEIVED! - elif frametype == 225: - logging.debug("ARQ arq_received_data_channel_opener RECEIVED") - data_handler.arq_received_data_channel_opener(bytes_out[:-2]) + # ARQ CONNECT ACK / KEEP ALIVE + # elif frametype == 221: + # logging.info("ARQ CONNECT ACK RECEIVED / KEEP ALIVE....") + # data_handler.arq_received_connect_keep_alive(bytes_out[:-2]) - # ARQ CHANNEL IS OPENED - elif frametype == 226: - logging.debug("ARQ arq_received_channel_is_open RECEIVED") - data_handler.arq_received_channel_is_open(bytes_out[:-2]) + # ARQ CONNECT ACK / KEEP ALIVE + # elif frametype == 222: + # logging.debug("ARQ DISCONNECT RECEIVED") + # data_handler.arq_disconnect_received(bytes_out[:-2]) - # ARQ CONNECT ACK / KEEP ALIVE - elif frametype == 230: - logging.debug("BEACON RECEIVED") - data_handler.received_beacon(bytes_out[:-2]) + # ARQ FILE TRANSFER RECEIVED! + elif frametype == 225: + logging.debug("ARQ arq_received_data_channel_opener RECEIVED") + data_handler.arq_received_data_channel_opener(bytes_out[:-2]) - else: - logging.info("OTHER FRAME: " + str(bytes_out[:-2])) - print(frametype) + # ARQ CHANNEL IS OPENED + elif frametype == 226: + logging.debug("ARQ arq_received_channel_is_open RECEIVED") + data_handler.arq_received_channel_is_open(bytes_out[:-2]) - # DO UNSYNC AFTER LAST BURST by checking the frame nums against the total frames per burst - if frame == n_frames_per_burst: - - logging.debug("LAST FRAME ---> UNSYNC") - - self.c_lib.freedv_set_sync(freedv, 0) # FORCE UNSYNC - - # clear bytes_out buffer to be ready for next frames after successfull decoding + # ARQ CONNECT ACK / KEEP ALIVE + elif frametype == 230: + logging.debug("BEACON RECEIVED") + data_handler.received_beacon(bytes_out[:-2]) - #bytes_out = (ctypes.c_ubyte * bytes_per_frame) - #bytes_out = bytes_out() # get pointer to bytes_out + else: + logging.info("OTHER FRAME: " + str(bytes_out[:-2])) + print(frametype) + + # DO UNSYNC AFTER LAST BURST by checking the frame nums against the total frames per burst + if frame == n_frames_per_burst: + + logging.debug("LAST FRAME ---> UNSYNC") + + self.c_lib.freedv_set_sync(freedv, 0) # FORCE UNSYNC + + # clear bytes_out buffer to be ready for next frames after successfull decoding + + #bytes_out = (ctypes.c_ubyte * bytes_per_frame) + # bytes_out = bytes_out() # get pointer to bytes_out else: - # for debugging purposes to receive all data + # for debugging purposes to receive all data pass - # print(bytes_out[:-2]) - - + # print(bytes_out[:-2]) + def get_scatter(self, freedv): modemStats = MODEMSTATS() self.c_lib.freedv_get_modem_extended_stats.restype = None - self.c_lib.freedv_get_modem_extended_stats(freedv, ctypes.byref(modemStats)) - + self.c_lib.freedv_get_modem_extended_stats( + freedv, ctypes.byref(modemStats)) + scatterdata = [] for i in range(MODEM_STATS_NC_MAX): - for j in range(MODEM_STATS_NR_MAX): - #check if odd or not to get every 2nd item for x - if (j % 2) == 0: + for j in range(MODEM_STATS_NR_MAX): + # check if odd or not to get every 2nd item for x + if (j % 2) == 0: xsymbols = modemStats.rx_symbols[i][j] - ysymbols = modemStats.rx_symbols[i][j+1] + ysymbols = modemStats.rx_symbols[i][j+1] # check if value 0.0 or has real data if xsymbols != 0.0 and ysymbols != 0.0: - scatterdata.append({"x" : xsymbols, "y" : ysymbols }) - + scatterdata.append({"x": xsymbols, "y": ysymbols}) + # only append scatter data if new data arrived if len(scatterdata) > 0: - static.SCATTER = scatterdata - + static.SCATTER = scatterdata + def calculate_ber(self, freedv): Tbits = self.c_lib.freedv_get_total_bits(freedv) Terrs = self.c_lib.freedv_get_total_bit_errors(freedv) - + if Tbits != 0: ber = (Terrs / Tbits) * 100 static.BER = int(ber) self.c_lib.freedv_set_total_bit_errors(freedv, 0) self.c_lib.freedv_set_total_bits(freedv, 0) - + def calculate_snr(self, freedv): - + modem_stats_snr = c_float() modem_stats_sync = c_int() - - self.c_lib.freedv_get_modem_stats(freedv,byref(modem_stats_sync), byref(modem_stats_snr)) + + self.c_lib.freedv_get_modem_stats(freedv, byref( + modem_stats_sync), byref(modem_stats_snr)) modem_stats_snr = modem_stats_snr.value try: - static.SNR = round(modem_stats_snr,1) + static.SNR = round(modem_stats_snr, 1) except: static.SNR = 0 - + def get_radio_stats(self): while True: time.sleep(0.1) @@ -748,14 +784,13 @@ class RF(): #static.HAMLIB_FREQUENCY = rigctld.get_frequency() #static.HAMLIB_MODE = rigctld.get_mode()[0] #static.HAMLIB_BANDWITH = rigctld.get_mode()[1] - - + def calculate_fft(self): while True: time.sleep(0.01) # WE NEED TO OPTIMIZE THIS! data_in = self.fft_data - + # https://gist.github.com/ZWMiller/53232427efc5088007cab6feee7c6e4c audio_data = np.fromstring(data_in, np.int16) # Fast Fourier Transform, 10*log10(abs) is to scale it to dB @@ -763,11 +798,11 @@ class RF(): try: fftarray = np.fft.rfft(audio_data) - # set value 0 to 1 to avoid division by zero + # set value 0 to 1 to avoid division by zero fftarray[fftarray == 0] = 1 dfft = 10.*np.log10(abs(fftarray)) dfftlist = dfft.tolist() - + # send fft only if receiving if static.CHANNEL_STATE == 'RECEIVING_SIGNALLING' or static.CHANNEL_STATE == 'RECEIVING_DATA': #static.FFT = dfftlist[20:100] @@ -776,4 +811,3 @@ class RF(): print("setting fft = 0") # else 0 static.FFT = [0] * 400 - diff --git a/tnc/sock.py b/tnc/sock.py index 7e55340b..484b4a68 100644 --- a/tnc/sock.py +++ b/tnc/sock.py @@ -33,17 +33,19 @@ import static import data_handler import helpers -import sys, os +import sys +import os class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer): pass - + + class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler): def handle(self): - print("Client connected...") - + print("Client connected...") + # loop through socket buffer until timeout is reached. then close buffer socketTimeout = time.time() + 3 while socketTimeout > time.time(): @@ -53,21 +55,21 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler): #data = str(self.request.recv(1024), 'utf-8') data = bytes() - + # we need to loop through buffer until end of chunk is reached or timeout occured while True and socketTimeout > time.time(): chunk = self.request.recv(71) # we keep amount of bytes short data += chunk - if chunk.endswith(b'}\n') or chunk.endswith(b'}'): # or chunk.endswith(b'\n'): + # or chunk.endswith(b'\n'): + if chunk.endswith(b'}\n') or chunk.endswith(b'}'): break data = data[:-1] # remove b'\n' data = str(data, 'utf-8') - if len(data) > 0: socketTimeout = time.time() + static.SOCKET_TIMEOUT - + # convert data to json object # we need to do some error handling in case of socket timeout or decoding issue try: @@ -78,7 +80,7 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler): data = data.splitlines()[0] received_json = json.loads(data) - #except ValueError as e: + # except ValueError as e: # print("++++++++++++ START OF JSON ERROR +++++++++++++++++++++++") # print(e) # print("-----------------------------------") @@ -86,29 +88,32 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler): # print("++++++++++++ END OF JSON ERROR +++++++++++++++++++++++++") # received_json = {} # break - #try: + # try: # CQ CQ CQ ----------------------------------------------------- if received_json["command"] == "CQCQCQ": #socketTimeout = 0 - #asyncio.run(data_handler.transmit_cq()) - CQ_THREAD = threading.Thread(target=data_handler.transmit_cq, args=[], name="CQ") + # asyncio.run(data_handler.transmit_cq()) + CQ_THREAD = threading.Thread( + target=data_handler.transmit_cq, args=[], name="CQ") CQ_THREAD.start() # PING ---------------------------------------------------------- if received_json["type"] == 'PING' and received_json["command"] == "PING": # send ping frame and wait for ACK dxcallsign = received_json["dxcallsign"] - #asyncio.run(data_handler.transmit_ping(dxcallsign)) - PING_THREAD = threading.Thread(target=data_handler.transmit_ping, args=[dxcallsign], name="CQ") + # asyncio.run(data_handler.transmit_ping(dxcallsign)) + PING_THREAD = threading.Thread( + target=data_handler.transmit_ping, args=[dxcallsign], name="CQ") PING_THREAD.start() - if received_json["type"] == 'ARQ' and received_json["command"] == "sendFile":# and static.ARQ_READY_FOR_DATA == True: # and static.ARQ_STATE == 'CONNECTED' : + # and static.ARQ_READY_FOR_DATA == True: # and static.ARQ_STATE == 'CONNECTED' : + if received_json["type"] == 'ARQ' and received_json["command"] == "sendFile": static.TNC_STATE = 'BUSY' - - #on a new transmission we reset the timer + + # on a new transmission we reset the timer static.ARQ_START_OF_TRANSMISSION = int(time.time()) - + dxcallsign = received_json["dxcallsign"] mode = int(received_json["mode"]) n_frames = int(received_json["n_frames"]) @@ -116,12 +121,13 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler): filetype = received_json["filetype"] data = received_json["data"] checksum = received_json["checksum"] - + static.DXCALLSIGN = bytes(dxcallsign, 'utf-8') - static.DXCALLSIGN_CRC8 = helpers.get_crc_8(static.DXCALLSIGN) - + static.DXCALLSIGN_CRC8 = helpers.get_crc_8( + static.DXCALLSIGN) + #dataframe = '{"filename": "'+ filename + '", "filetype" : "' + filetype + '", "data" : "' + data + '", "checksum" : "' + checksum + '"}' - rawdata = {"filename" : filename , "filetype" :filetype, "data" : data, "checksum" : checksum} + rawdata = {"filename": filename, "filetype": filetype,"data": data, "checksum": checksum} #dataframe = {filename: filename} #data_out = bytes(received_json["data"], 'utf-8') dataframe = json.dumps(rawdata) @@ -141,9 +147,11 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler): self.request.sendall(b'INVALID CALLSIGN') else: static.MYCALLSIGN = bytes(callsign, encoding) - static.MYCALLSIGN_CRC8 = helpers.get_crc_8(static.MYCALLSIGN) - logging.info("CMD | MYCALLSIGN: " + str(static.MYCALLSIGN)) - + static.MYCALLSIGN_CRC8 = helpers.get_crc_8( + static.MYCALLSIGN) + logging.info("CMD | MYCALLSIGN: " + + str(static.MYCALLSIGN)) + if received_json["type"] == 'SET' and received_json["command"] == 'MYGRID': mygrid = received_json["parameter"] @@ -152,25 +160,24 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler): else: static.MYGRID = bytes(mygrid, encoding) logging.info("CMD | MYGRID: " + str(static.MYGRID)) - - + if received_json["type"] == 'GET' and received_json["command"] == 'STATION_INFO': output = { "COMMAND": "STATION_INFO", - "TIMESTAMP" : received_json["timestamp"], + "TIMESTAMP": received_json["timestamp"], "MY_CALLSIGN": str(static.MYCALLSIGN, encoding), "DX_CALLSIGN": str(static.DXCALLSIGN, encoding), "DX_GRID": str(static.DXGRID, encoding), - "EOF" : "EOF", + "EOF": "EOF", } - + jsondata = json.dumps(output) self.request.sendall(bytes(jsondata, encoding)) if received_json["type"] == 'GET' and received_json["command"] == 'TNC_STATE': output = { "COMMAND": "TNC_STATE", - "TIMESTAMP" : received_json["timestamp"], + "TIMESTAMP": received_json["timestamp"], "PTT_STATE": str(static.PTT_STATE), "CHANNEL_STATE": str(static.CHANNEL_STATE), "TNC_STATE": str(static.TNC_STATE), @@ -178,65 +185,63 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler): "AUDIO_RMS": str(static.AUDIO_RMS), "BER": str(static.BER), "SNR": str(static.SNR), - "FREQUENCY" : str(static.HAMLIB_FREQUENCY), - "MODE" : str(static.HAMLIB_MODE), - "BANDWITH" : str(static.HAMLIB_BANDWITH), - "FFT" : str(static.FFT), - "SCATTER" : static.SCATTER, + "FREQUENCY": str(static.HAMLIB_FREQUENCY), + "MODE": str(static.HAMLIB_MODE), + "BANDWITH": str(static.HAMLIB_BANDWITH), + "FFT": str(static.FFT), + "SCATTER": static.SCATTER, "RX_BUFFER_LENGTH": str(len(static.RX_BUFFER)), "TX_N_MAX_RETRIES": str(static.TX_N_MAX_RETRIES), "ARQ_TX_N_FRAMES_PER_BURST": str(static.ARQ_TX_N_FRAMES_PER_BURST), "ARQ_TX_N_BURSTS": str(static.ARQ_TX_N_BURSTS), "ARQ_TX_N_CURRENT_ARQ_FRAME": str(int.from_bytes(bytes(static.ARQ_TX_N_CURRENT_ARQ_FRAME), "big")), - "ARQ_TX_N_TOTAL_ARQ_FRAMES": str(int.from_bytes(bytes(static.TX_BUFFER_SIZE), "big")), # WE NEED TO CHANGE THE JSON TO TX_BUFFER_SIZE?! + # WE NEED TO CHANGE THE JSON TO TX_BUFFER_SIZE?! + "ARQ_TX_N_TOTAL_ARQ_FRAMES": str(int.from_bytes(bytes(static.TX_BUFFER_SIZE), "big")), "ARQ_RX_FRAME_N_BURSTS": str(static.ARQ_RX_FRAME_N_BURSTS), "ARQ_RX_N_CURRENT_ARQ_FRAME": str(static.ARQ_RX_N_CURRENT_ARQ_FRAME), "ARQ_N_ARQ_FRAMES_PER_DATA_FRAME": str(int.from_bytes(bytes(static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME), "big")), - "ARQ_BYTES_PER_MINUTE" : str(static.ARQ_BYTES_PER_MINUTE), - "ARQ_BYTES_PER_MINUTE_BURST" : str(static.ARQ_BYTES_PER_MINUTE_BURST), - "ARQ_TRANSMISSION_PERCENT" : str(static.ARQ_TRANSMISSION_PERCENT), - "TOTAL_BYTES" : str(static.TOTAL_BYTES), - - "STATIONS" : [], - "EOF" : "EOF", + "ARQ_BYTES_PER_MINUTE": str(static.ARQ_BYTES_PER_MINUTE), + "ARQ_BYTES_PER_MINUTE_BURST": str(static.ARQ_BYTES_PER_MINUTE_BURST), + "ARQ_TRANSMISSION_PERCENT": str(static.ARQ_TRANSMISSION_PERCENT), + "TOTAL_BYTES": str(static.TOTAL_BYTES), + + "STATIONS": [], + "EOF": "EOF", } - + for i in range(0, len(static.HEARD_STATIONS)): - output["STATIONS"].append({"DXCALLSIGN": str(static.HEARD_STATIONS[i][0], 'utf-8'),"DXGRID": str(static.HEARD_STATIONS[i][1], 'utf-8'), "TIMESTAMP": static.HEARD_STATIONS[i][2], "DATATYPE": static.HEARD_STATIONS[i][3], "SNR": static.HEARD_STATIONS[i][4]}) - - - try: + output["STATIONS"].append({"DXCALLSIGN": str(static.HEARD_STATIONS[i][0], 'utf-8'), "DXGRID": str(static.HEARD_STATIONS[i][1], 'utf-8'),"TIMESTAMP": static.HEARD_STATIONS[i][2], "DATATYPE": static.HEARD_STATIONS[i][3], "SNR": static.HEARD_STATIONS[i][4]}) + + try: jsondata = json.dumps(output) except ValueError as e: print(e) - + try: self.request.sendall(bytes(jsondata, encoding)) except Exception as e: print(e) - if received_json["type"] == 'GET' and received_json["command"] == 'RX_BUFFER': output = { "COMMAND": "RX_BUFFER", - "DATA-ARRAY" : [], - "EOF" : "EOF", + "DATA-ARRAY": [], + "EOF": "EOF", } for i in range(0, len(static.RX_BUFFER)): - + rawdata = json.loads(static.RX_BUFFER[i][3]) - - output["DATA-ARRAY"].append({"DXCALLSIGN": str(static.RX_BUFFER[i][0], 'utf-8'),"DXGRID": str(static.RX_BUFFER[i][1], 'utf-8'), "TIMESTAMP": static.RX_BUFFER[i][2], "RXDATA": [rawdata]}) - + + output["DATA-ARRAY"].append({"DXCALLSIGN": str(static.RX_BUFFER[i][0], 'utf-8'), "DXGRID": str(static.RX_BUFFER[i][1], 'utf-8'), "TIMESTAMP": static.RX_BUFFER[i][2], "RXDATA": [rawdata]}) + jsondata = json.dumps(output) self.request.sendall(bytes(jsondata, encoding)) if received_json["type"] == 'SET' and received_json["command"] == 'DEL_RX_BUFFER': static.RX_BUFFER = [] - - #exception, if JSON cant be decoded - #except Exception as e: + # exception, if JSON cant be decoded + # except Exception as e: except: print("############ START OF ERROR #####################") print("SOCKET COMMAND ERROR: " + data) @@ -248,19 +253,22 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler): print("############ END OF ERROR #######################") print("reset of connection...") - #socketTimeout = 0 + #socketTimeout = 0 print("Client disconnected...") + def start_cmd_socket(): try: - logging.info("SRV | STARTING TCP/IP SOCKET FOR CMD ON PORT: " + str(static.PORT)) - socketserver.TCPServer.allow_reuse_address = True # https://stackoverflow.com/a/16641793 - cmdserver = ThreadedTCPServer((static.HOST, static.PORT), ThreadedTCPRequestHandler) + logging.info( + "SRV | STARTING TCP/IP SOCKET FOR CMD ON PORT: " + str(static.PORT)) + # https://stackoverflow.com/a/16641793 + socketserver.TCPServer.allow_reuse_address = True + cmdserver = ThreadedTCPServer( + (static.HOST, static.PORT), ThreadedTCPRequestHandler) server_thread = threading.Thread(target=cmdserver.serve_forever) server_thread.daemon = True - server_thread.start() - + server_thread.start() except: print("Socket error...")