better pep8 conformity

This commit is contained in:
DJ2LS 2021-09-25 15:24:25 +02:00
parent 21eb8fa12b
commit 5c7e05ef70
4 changed files with 531 additions and 472 deletions

View file

@ -7,37 +7,38 @@ Created on Tue Dec 22 16:58:45 2020
""" """
import argparse import argparse
import threading import threading
import socketserver import socketserver
import pyaudio
import time import time
import ujson as json
import subprocess
import os import os
import static
import psutil
import sys import sys
import subprocess
import ujson as json
import psutil
import serial.tools.list_ports import serial.tools.list_ports
import pyaudio
import static
def start_daemon(): def start_daemon():
try: try:
print("SRV | STARTING TCP/IP SOCKET FOR CMD ON PORT: " + str(PORT)) print("SRV | STARTING TCP/IP SOCKET FOR CMD ON PORT: " + str(PORT))
socketserver.TCPServer.allow_reuse_address = True # https://stackoverflow.com/a/16641793 # https://stackoverflow.com/a/16641793
daemon = socketserver.TCPServer(('0.0.0.0', PORT), CMDTCPRequestHandler) socketserver.TCPServer.allow_reuse_address = True
daemon = socketserver.TCPServer(
('0.0.0.0', PORT), CMDTCPRequestHandler)
daemon.serve_forever() daemon.serve_forever()
finally: finally:
daemon.server_close() daemon.server_close()
class CMDTCPRequestHandler(socketserver.BaseRequestHandler): class CMDTCPRequestHandler(socketserver.BaseRequestHandler):
def handle(self): def handle(self):
print("Client connected...") print("Client connected...")
# loop through socket buffer until timeout is reached. then close buffer # loop through socket buffer until timeout is reached. then close buffer
socketTimeout = time.time() + 3 socketTimeout = time.time() + 3
while socketTimeout > time.time(): while socketTimeout > time.time():
@ -47,23 +48,23 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler):
#data = str(self.request.recv(1024), 'utf-8') #data = str(self.request.recv(1024), 'utf-8')
data = bytes() data = bytes()
# we need to loop through buffer until end of chunk is reached or timeout occured # we need to loop through buffer until end of chunk is reached or timeout occured
while True and socketTimeout > time.time(): while True and socketTimeout > time.time():
chunk = self.request.recv(45) chunk = self.request.recv(45)
data += chunk 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 break
data = data[:-1] # remove b'\n' data = data[:-1] # remove b'\n'
data = str(data, 'utf-8') data = str(data, 'utf-8')
if len(data) > 0: if len(data) > 0:
socketTimeout = time.time() + 3 socketTimeout = time.time() + 3
# convert data to json object # convert data to json object
# we need to do some error handling in case of socket timeout # we need to do some error handling in case of socket timeout
try: try:
# only read first line of string. multiple lines will cause an json error # only read first line of string. multiple lines will cause an json error
# this occurs possibly, if we are getting data too fast # this occurs possibly, if we are getting data too fast
@ -72,41 +73,44 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler):
# GET COMMANDS # GET COMMANDS
# "command" : "..." # "command" : "..."
# SET COMMANDS # SET COMMANDS
# "command" : "..." # "command" : "..."
# "parameter" : " ..." # "parameter" : " ..."
# DATA COMMANDS # DATA COMMANDS
# "command" : "..." # "command" : "..."
# "type" : "..." # "type" : "..."
# "dxcallsign" : "..." # "dxcallsign" : "..."
# "data" : "..." # "data" : "..."
# print(received_json) # print(received_json)
#print(received_json["type"]) # print(received_json["type"])
#print(received_json["command"]) # print(received_json["command"])
#try: # try:
if received_json["type"] == 'SET' and received_json["command"] == 'STARTTNC' and not static.TNCSTARTED: if received_json["type"] == 'SET' and received_json["command"] == 'STARTTNC' and not static.TNCSTARTED:
rx_audio = str(received_json["parameter"][0]["rx_audio"]) rx_audio = str(received_json["parameter"][0]["rx_audio"])
tx_audio = str(received_json["parameter"][0]["tx_audio"]) tx_audio = str(received_json["parameter"][0]["tx_audio"])
deviceid = str(received_json["parameter"][0]["deviceid"]) deviceid = str(received_json["parameter"][0]["deviceid"])
deviceport = str(received_json["parameter"][0]["deviceport"]) deviceport = str(
serialspeed = str(received_json["parameter"][0]["serialspeed"]) received_json["parameter"][0]["deviceport"])
pttprotocol = str(received_json["parameter"][0]["pttprotocol"]) serialspeed = str(
received_json["parameter"][0]["serialspeed"])
pttprotocol = str(
received_json["parameter"][0]["pttprotocol"])
pttport = str(received_json["parameter"][0]["pttport"]) pttport = str(received_json["parameter"][0]["pttport"])
print("---- STARTING TNC !") print("---- STARTING TNC !")
print(received_json["parameter"][0]) print(received_json["parameter"][0])
#command = "--rx "+ rx_audio +" \ # command = "--rx "+ rx_audio +" \
# --tx "+ tx_audio +" \ # --tx "+ tx_audio +" \
# --deviceport "+ deviceport +" \ # --deviceport "+ deviceport +" \
# --deviceid "+ deviceid + " \ # --deviceid "+ deviceid + " \
# --serialspeed "+ serialspeed + " \ # --serialspeed "+ serialspeed + " \
# --pttprotocol "+ pttprotocol + " \ # --pttprotocol "+ pttprotocol + " \
# --pttport "+ pttport # --pttport "+ pttport
# list of parameters, necessary for running subprocess command as a list # list of parameters, necessary for running subprocess command as a list
options = [] options = []
options.append('--rx') options.append('--rx')
@ -123,7 +127,7 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler):
options.append(pttprotocol) options.append(pttprotocol)
options.append('--pttport') options.append('--pttport')
options.append(pttport) options.append(pttport)
# try running tnc from binary, else run from source # try running tnc from binary, else run from source
# this helps running the tnc in a developer environment # this helps running the tnc in a developer environment
try: try:
@ -141,20 +145,20 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler):
command += options command += options
p = subprocess.Popen(command) p = subprocess.Popen(command)
print("running TNC from source...") print("running TNC from source...")
static.TNCPROCESS = p#.pid static.TNCPROCESS = p # .pid
static.TNCSTARTED = True static.TNCSTARTED = True
if received_json["type"] == 'SET' and received_json["command"] == 'STOPTNC': if received_json["type"] == 'SET' and received_json["command"] == 'STOPTNC':
parameter = received_json["parameter"]
static.TNCPROCESS.kill() static.TNCPROCESS.kill()
print("KILLING PROCESS ------------") print("KILLING PROCESS ------------")
#os.kill(static.TNCPROCESS, signal.SIGKILL) #os.kill(static.TNCPROCESS, signal.SIGKILL)
static.TNCSTARTED = False static.TNCSTARTED = False
if received_json["type"] == 'GET' and received_json["command"] == 'DAEMON_STATE': 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: if static.TNCSTARTED:
data["DAEMON_STATE"].append({"STATUS": "running"}) data["DAEMON_STATE"].append({"STATUS": "running"})
@ -164,36 +168,40 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler):
# UPDATE LIST OF AUDIO DEVICES # UPDATE LIST OF AUDIO DEVICES
p = pyaudio.PyAudio() p = pyaudio.PyAudio()
for i in range(0, p.get_device_count()): for i in range(0, p.get_device_count()):
maxInputChannels = p.get_device_info_by_host_api_device_index(0,i).get('maxInputChannels') maxInputChannels = p.get_device_info_by_host_api_device_index(
maxOutputChannels = p.get_device_info_by_host_api_device_index(0,i).get('maxOutputChannels') 0, i).get('maxInputChannels')
name = p.get_device_info_by_host_api_device_index(0,i).get('name') maxOutputChannels = p.get_device_info_by_host_api_device_index(
0, i).get('maxOutputChannels')
if maxInputChannels > 0: name = p.get_device_info_by_host_api_device_index(
data["INPUT_DEVICES"].append({"ID": i, "NAME" : str(name)}) 0, i).get('name')
if maxOutputChannels > 0:
data["OUTPUT_DEVICES"].append({"ID": i, "NAME" : str(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 # UPDATE LIST OF SERIAL DEVICES
ports = serial.tools.list_ports.comports() ports = serial.tools.list_ports.comports()
for port, desc, hwid in ports: 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) jsondata = json.dumps(data)
self.request.sendall(bytes(jsondata, encoding)) 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: except ValueError as e:
print("############ START OF ERROR #####################") print("############ START OF ERROR #####################")
print('DAEMON PROGRAM ERROR: %s' %str(e)) print('DAEMON PROGRAM ERROR: %s' % str(e))
print("Wrong command") print("Wrong command")
print(data) print(data)
print(e) 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] fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
print(exc_type, fname, exc_tb.tb_lineno) print(exc_type, fname, exc_tb.tb_lineno)
print("############ END OF ERROR #######################") print("############ END OF ERROR #######################")
@ -203,13 +211,11 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler):
if __name__ == '__main__': if __name__ == '__main__':
# --------------------------------------------GET PARAMETER INPUTS # --------------------------------------------GET PARAMETER INPUTS
PARSER = argparse.ArgumentParser(description='Simons TEST TNC') 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() ARGS = PARSER.parse_args()
PORT = ARGS.socket_port PORT = ARGS.socket_port
@ -217,9 +223,3 @@ if __name__ == '__main__':
DAEMON_THREAD = threading.Thread(target=start_daemon, name="daemon") DAEMON_THREAD = threading.Thread(target=start_daemon, name="daemon")
DAEMON_THREAD.start() DAEMON_THREAD.start()

View file

@ -15,13 +15,13 @@ import crcengine
import static import static
import data_handler import data_handler
def wait(seconds): def wait(seconds):
timeout = time.time() + seconds timeout = time.time() + seconds
while time.time() < timeout: while time.time() < timeout:
time.sleep(0.01) time.sleep(0.01)
def get_crc_8(data): def get_crc_8(data):
""" """
@ -50,30 +50,34 @@ def get_crc_16(data):
crc_data = crc_data.to_bytes(2, byteorder='big') crc_data = crc_data.to_bytes(2, byteorder='big')
return crc_data return crc_data
def watchdog(): def watchdog():
""" """
Author: DJ2LS Author: DJ2LS
watchdog master function. Frome here we call the watchdogs watchdog master function. Frome here we call the watchdogs
""" """
while True: while True:
time.sleep(0.01) time.sleep(0.01)
data_channel_keep_alive_watchdog() data_channel_keep_alive_watchdog()
def data_channel_keep_alive_watchdog(): def data_channel_keep_alive_watchdog():
""" """
Author: DJ2LS 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) time.sleep(0.01)
if static.ARQ_DATA_CHANNEL_LAST_RECEIVED + 30 > time.time(): if static.ARQ_DATA_CHANNEL_LAST_RECEIVED + 30 > time.time():
pass pass
else: else:
static.ARQ_DATA_CHANNEL_LAST_RECEIVED = 0 static.ARQ_DATA_CHANNEL_LAST_RECEIVED = 0
logging.info("DATA [" + str(static.MYCALLSIGN, 'utf-8') + "]<<T>>[" + str(static.DXCALLSIGN, 'utf-8') + "] [BER." + str(static.BER) + "]") logging.info("DATA [" + str(static.MYCALLSIGN, 'utf-8') + "]<<T>>[" + str(
static.DXCALLSIGN, 'utf-8') + "] [BER." + str(static.BER) + "]")
arq_reset_frame_machine() arq_reset_frame_machine()
@ -116,128 +120,141 @@ def arq_reset_frame_machine():
static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME = 0 static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME = 0
static.ARQ_FRAME_BOF_RECEIVED = False static.ARQ_FRAME_BOF_RECEIVED = False
static.ARQ_FRAME_EOF_RECEIVED = False static.ARQ_FRAME_EOF_RECEIVED = False
static.ARQ_RX_BURST_BUFFER = [] static.ARQ_RX_BURST_BUFFER = []
static.ARQ_RX_FRAME_BUFFER = [] static.ARQ_RX_FRAME_BUFFER = []
static.TNC_STATE = 'IDLE' static.TNC_STATE = 'IDLE'
static.ARQ_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.ARQ_SEND_KEEP_ALIVE = True
static.CHANNEL_STATE = 'RECEIVING_SIGNALLING' static.CHANNEL_STATE = 'RECEIVING_SIGNALLING'
static.ARQ_READY_FOR_DATA = False static.ARQ_READY_FOR_DATA = False
static.ARQ_START_OF_TRANSMISSION = 0 static.ARQ_START_OF_TRANSMISSION = 0
def calculate_transfer_rate(): def calculate_transfer_rate():
if static.ARQ_START_OF_TRANSMISSION > 0: if static.ARQ_START_OF_TRANSMISSION > 0:
static.TOTAL_TRANSMISSION_TIME = time.time() - static.ARQ_START_OF_TRANSMISSION static.TOTAL_TRANSMISSION_TIME = time.time() - static.ARQ_START_OF_TRANSMISSION
print("ARQ_N_ARQ_FRAMES_PER_DATA_FRAME " +
print("ARQ_N_ARQ_FRAMES_PER_DATA_FRAME " + str(static.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_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_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 arq_rx_n_current_arq_frame = static.ARQ_RX_N_CURRENT_ARQ_FRAME
if static.TX_BUFFER_SIZE == 0: if static.TX_BUFFER_SIZE == 0:
total_n_frames = arq_n_arq_frames_per_data_frame total_n_frames = arq_n_arq_frames_per_data_frame
elif arq_n_arq_frames_per_data_frame == 0: elif arq_n_arq_frames_per_data_frame == 0:
total_n_frames = static.TX_BUFFER_SIZE total_n_frames = static.TX_BUFFER_SIZE
else: else:
total_n_frames = 0 total_n_frames = 0
if static.TOTAL_TRANSMISSION_TIME > 0: if static.TOTAL_TRANSMISSION_TIME > 0:
#total_transmission_time = time.time() - static.ARQ_START_OF_TRANSMISSION #total_transmission_time = time.time() - static.ARQ_START_OF_TRANSMISSION
total_transmission_time = static.TOTAL_TRANSMISSION_TIME total_transmission_time = static.TOTAL_TRANSMISSION_TIME
print("total_transmission_time: " + str(total_transmission_time)) print("total_transmission_time: " + str(total_transmission_time))
print("static.TOTAL_BYTES: " + str(static.TOTAL_BYTES)) 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_bytes = static.ARQ_PAYLOAD_PER_FRAME * static.ARQ_N_RX_FRAMES_PER_BURSTS
burst_transmission_time = time.time() - static.ARQ_START_OF_BURST burst_transmission_time = time.time() - static.ARQ_START_OF_BURST
print("BURST TRANSMISSION TIME: " + str(burst_transmission_time)) print("BURST TRANSMISSION TIME: " + str(burst_transmission_time))
static.ARQ_BITS_PER_SECOND_BURST = int((burst_bytes * 8) / burst_transmission_time) static.ARQ_BITS_PER_SECOND_BURST = int(
static.ARQ_BYTES_PER_MINUTE_BURST = int(((burst_bytes) / burst_transmission_time) * 60) (burst_bytes * 8) / burst_transmission_time)
print("static.ARQ_BITS_PER_SECOND_BURST: " + str(static.ARQ_BITS_PER_SECOND_BURST)) static.ARQ_BYTES_PER_MINUTE_BURST = int(
print("static.ARQ_BYTES_PER_MINUTE_BURST: " + str(static.ARQ_BYTES_PER_MINUTE_BURST)) ((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 # PERCENTAGE FOR TRANSMITTING
if static.TX_BUFFER_SIZE > 0: if static.TX_BUFFER_SIZE > 0:
print("static.ARQ_N_SENT_FRAMES: " + str(static.ARQ_N_SENT_FRAMES)) 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 # PERCENTAGE FOR RECEIVING
elif arq_n_arq_frames_per_data_frame > 0: 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: else:
static.ARQ_TRANSMISSION_PERCENT = 0.0 static.ARQ_TRANSMISSION_PERCENT = 0.0
print("static.ARQ_TRANSMISSION_PERCENT: " + str(static.ARQ_TRANSMISSION_PERCENT)) 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_BYTES_PER_MINUTE: " + str(static.ARQ_BYTES_PER_MINUTE))
print("static.ARQ_BITS_PER_SECOND: " + str(static.ARQ_BITS_PER_SECOND)) 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] 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 # check if buffer empty
if len(static.HEARD_STATIONS) == 0: 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 # if not, we search and update
else: else:
for i in range(0, len(static.HEARD_STATIONS)): for i in range(0, len(static.HEARD_STATIONS)):
# update callsign with new timestamp # update callsign with new timestamp
if static.HEARD_STATIONS[i].count(dxcallsign) > 0: 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 break
# insert if nothing found # insert if nothing found
if i == len(static.HEARD_STATIONS) - 1: 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 break
# for idx, item in enumerate(static.HEARD_STATIONS): # for idx, item in enumerate(static.HEARD_STATIONS):
# if dxcallsign in item: # if dxcallsign in item:
# item = [dxcallsign, int(time.time())] # item = [dxcallsign, int(time.time())]
# static.HEARD_STATIONS[idx] = item # static.HEARD_STATIONS[idx] = item
def setup_logging(): def setup_logging():
""" """
Author: DJ2LS Author: DJ2LS
Set the custom logging format so we can use colors Set the custom logging format so we can use colors
# https://stackoverflow.com/questions/384076/how-can-i-color-python-logging-output # https://stackoverflow.com/questions/384076/how-can-i-color-python-logging-output
# 'DEBUG' : 37, # white # 'DEBUG' : 37, # white
# 'INFO' : 36, # cyan # 'INFO' : 36, # cyan
# 'WARNING' : 33, # yellow # 'WARNING' : 33, # yellow
# 'ERROR' : 31, # red # 'ERROR' : 31, # red
# 'CRITICAL': 41, # white on red bg # 'CRITICAL': 41, # white on red bg
""" """
logging.basicConfig(level=logging.INFO, \ logging.basicConfig(level=logging.INFO,
encoding='utf-8', \ encoding='utf-8',
format='%(asctime)s.%(msecs)03d %(levelname)s:\t%(message)s', \ format='%(asctime)s.%(msecs)03d %(levelname)s:\t%(message)s',
datefmt='%H:%M:%S', \ datefmt='%H:%M:%S',
handlers=[logging.FileHandler("codec2-FreeDATA-TNC.log"),logging.StreamHandler()] 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.addLevelName(logging.INFO, "\033[1;37m%s\033[1;0m" % logging.getLevelName(logging.INFO)) logging.DEBUG, "\033[1;36m%s\033[1;0m" % logging.getLevelName(logging.DEBUG))
logging.addLevelName(logging.WARNING, "\033[1;33m%s\033[1;0m" % logging.getLevelName(logging.WARNING)) 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" % "FAILED")
#logging.addLevelName( logging.ERROR, "\033[1;31m%s\033[1;0m" % logging.getLevelName(logging.ERROR)) #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(25, "\033[1;32m%s\033[1;0m" % "SUCCESS")
logging.addLevelName(24, "\033[1;34m%s\033[1;0m" % "DATA") logging.addLevelName(24, "\033[1;34m%s\033[1;0m" % "DATA")

View file

@ -5,25 +5,24 @@ Created on Wed Dec 23 07:04:24 2020
@author: DJ2LS @author: DJ2LS
""" """
import sys
import ctypes import ctypes
from ctypes import * from ctypes import *
import pathlib import pathlib
import pyaudio
import audioop import audioop
import asyncio #import asyncio
#import sys
import logging import logging
import time import time
import threading import threading
import atexit import atexit
import numpy as np
import pyaudio
import helpers import helpers
import static import static
import data_handler import data_handler
import sys
#sys.path.append("hamlib/linux") # sys.path.append("hamlib/linux")
try: try:
import Hamlib import Hamlib
print("running Hamlib from Sys Path") print("running Hamlib from Sys Path")
@ -34,7 +33,7 @@ else:
# place for rigctld # place for rigctld
pass pass
import numpy as np
#import rigctld #import rigctld
#rigctld = rigctld.Rigctld() #rigctld = rigctld.Rigctld()
@ -42,27 +41,28 @@ import numpy as np
MODEM_STATS_NR_MAX = 320 MODEM_STATS_NR_MAX = 320
MODEM_STATS_NC_MAX = 51 MODEM_STATS_NC_MAX = 51
class MODEMSTATS(ctypes.Structure): class MODEMSTATS(ctypes.Structure):
_fields_ = [ _fields_ = [
("Nc", ctypes.c_int), ("Nc", ctypes.c_int),
("snr_est", ctypes.c_float), ("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), ("nr", ctypes.c_int),
("sync", ctypes.c_int), ("sync", ctypes.c_int),
("foff", ctypes.c_float), ("foff", ctypes.c_float),
("rx_timing", ctypes.c_float), ("rx_timing", ctypes.c_float),
("clock_offset", ctypes.c_float), ("clock_offset", ctypes.c_float),
("sync_metric", ctypes.c_float), ("sync_metric", ctypes.c_float),
("pre", ctypes.c_int), ("pre", ctypes.c_int),
("post", ctypes.c_int), ("post", ctypes.c_int),
("uw_fails", ctypes.c_int), ("uw_fails", ctypes.c_int),
] ]
class RF(): class RF():
def __init__(self): def __init__(self):
# -------------------------------------------- LOAD FREEDV # -------------------------------------------- LOAD FREEDV
try: try:
# we check at first for libcodec2 in root - necessary if we want to run it inside a pyinstaller binary # 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 self.audio_writing_to_stream = False
# --------------------------------------------START DECODER THREAD # --------------------------------------------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() 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() PLAYBACK_THREAD.start()
self.fft_data = bytes() 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() FFT_THREAD.start()
# --------------------------------------------CONFIGURE HAMLIB # --------------------------------------------CONFIGURE HAMLIB
#my_rig.set_ptt(Hamlib.RIG_PTT_RIG,0) # 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_DTR,0)
#my_rig.set_ptt(Hamlib.RIG_PTT_SERIAL_RTS,1) # my_rig.set_ptt(Hamlib.RIG_PTT_SERIAL_RTS,1)
#self.my_rig.set_conf("dtr_state", "OFF") #self.my_rig.set_conf("dtr_state", "OFF")
#my_rig.set_conf("rts_state", "OFF") #my_rig.set_conf("rts_state", "OFF")
#self.my_rig.set_conf("ptt_type", "RTS") #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("serial_handshake", "None")
self.my_rig.set_conf("stop_bits", "1") self.my_rig.set_conf("stop_bits", "1")
self.my_rig.set_conf("data_bits", "8") self.my_rig.set_conf("data_bits", "8")
if static.HAMLIB_PTT_TYPE == 'RIG': if static.HAMLIB_PTT_TYPE == 'RIG':
self.hamlib_ptt_type = Hamlib.RIG_PTT_RIG self.hamlib_ptt_type = Hamlib.RIG_PTT_RIG
elif static.HAMLIB_PTT_TYPE == 'DTR-H': elif static.HAMLIB_PTT_TYPE == 'DTR-H':
self.hamlib_ptt_type = Hamlib.RIG_PTT_SERIAL_DTR self.hamlib_ptt_type = Hamlib.RIG_PTT_SERIAL_DTR
self.my_rig.set_conf("dtr_state", "HIGH") self.my_rig.set_conf("dtr_state", "HIGH")
self.my_rig.set_conf("ptt_type", "DTR") self.my_rig.set_conf("ptt_type", "DTR")
elif static.HAMLIB_PTT_TYPE == 'DTR-L': elif static.HAMLIB_PTT_TYPE == 'DTR-L':
self.hamlib_ptt_type = Hamlib.RIG_PTT_SERIAL_DTR self.hamlib_ptt_type = Hamlib.RIG_PTT_SERIAL_DTR
self.my_rig.set_conf("dtr_state", "LOW") self.my_rig.set_conf("dtr_state", "LOW")
self.my_rig.set_conf("ptt_type", "DTR") self.my_rig.set_conf("ptt_type", "DTR")
elif static.HAMLIB_PTT_TYPE == 'RTS': elif static.HAMLIB_PTT_TYPE == 'RTS':
self.hamlib_ptt_type = Hamlib.RIG_PTT_SERIAL_RTS self.hamlib_ptt_type = Hamlib.RIG_PTT_SERIAL_RTS
self.my_rig.set_conf("dtr_state", "OFF") 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': elif static.HAMLIB_PTT_TYPE == 'PARALLEL':
self.hamlib_ptt_type = Hamlib.RIG_PTT_PARALLEL self.hamlib_ptt_type = Hamlib.RIG_PTT_PARALLEL
elif static.HAMLIB_PTT_TYPE == 'MICDATA': elif static.HAMLIB_PTT_TYPE == 'MICDATA':
self.hamlib_ptt_type = Hamlib.RIG_PTT_RIG_MICDATA self.hamlib_ptt_type = Hamlib.RIG_PTT_RIG_MICDATA
elif static.HAMLIB_PTT_TYPE == 'CM108': elif static.HAMLIB_PTT_TYPE == 'CM108':
self.hamlib_ptt_type = Hamlib.RIG_PTT_CM108 self.hamlib_ptt_type = Hamlib.RIG_PTT_CM108
else: # static.HAMLIB_PTT_TYPE == 'RIG_PTT_NONE': else: # static.HAMLIB_PTT_TYPE == 'RIG_PTT_NONE':
self.hamlib_ptt_type = Hamlib.RIG_PTT_NONE self.hamlib_ptt_type = Hamlib.RIG_PTT_NONE
self.my_rig.open() self.my_rig.open()
atexit.register(self.my_rig.close) atexit.register(self.my_rig.close)
# set rig mode to USB # set rig mode to USB
self.my_rig.set_mode(Hamlib.RIG_MODE_USB) self.my_rig.set_mode(Hamlib.RIG_MODE_USB)
# start thread for getting hamlib data # 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() HAMLIB_THREAD.start()
except: except:
print("Unexpected error:", sys.exc_info()[0]) print("Unexpected error:", sys.exc_info()[0])
print("can't open rig") print("can't open rig")
sys.exit("hamlib error") sys.exit("hamlib error")
# -------------------------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------------------------
def ptt_and_wait(self, state): def ptt_and_wait(self, state):
static.PTT_STATE = state static.PTT_STATE = state
if state: if state:
self.my_rig.set_ptt(self.hamlib_ptt_type, 1) self.my_rig.set_ptt(self.hamlib_ptt_type, 1)
#rigctld.ptt_enable() # rigctld.ptt_enable()
ptt_toggle_timeout = time.time() + 0.5 ptt_toggle_timeout = time.time() + 0.5
while time.time() < ptt_toggle_timeout: while time.time() < ptt_toggle_timeout:
pass pass
else: else:
ptt_toggle_timeout = time.time() + 0.5 ptt_toggle_timeout = time.time() + 0.5
while time.time() < ptt_toggle_timeout: while time.time() < ptt_toggle_timeout:
pass 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): def play_audio(self):
while True: while True:
time.sleep(0.01) time.sleep(0.01)
#while len(self.streambuffer) > 0: # while len(self.streambuffer) > 0:
# time.sleep(0.01) # time.sleep(0.01)
if len(self.streambuffer) > 0 and self.audio_writing_to_stream: if len(self.streambuffer) > 0 and self.audio_writing_to_stream:
self.streambuffer = bytes(self.streambuffer) 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 # 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) time.sleep(0.1)
self.stream_tx.write(self.streambuffer) self.stream_tx.write(self.streambuffer)
# clear stream buffer after sending # clear stream buffer after sending
self.streambuffer = bytes() self.streambuffer = bytes()
self.audio_writing_to_stream = False self.audio_writing_to_stream = False
# -------------------------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------------------------
def transmit_signalling(self, data_out, count): def transmit_signalling(self, data_out, count):
state_before_transmit = static.CHANNEL_STATE state_before_transmit = static.CHANNEL_STATE
static.CHANNEL_STATE = 'SENDING_SIGNALLING' static.CHANNEL_STATE = 'SENDING_SIGNALLING'
#print(static.CHANNEL_STATE) # print(static.CHANNEL_STATE)
self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte) self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte)
freedv = self.c_lib.freedv_open(static.FREEDV_SIGNALLING_MODE) 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 payload_per_frame = bytes_per_frame - 2
n_nom_modem_samples = self.c_lib.freedv_get_n_nom_modem_samples(freedv) 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 # 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_modem_samples = self.c_lib.freedv_get_n_tx_modem_samples(freedv)
n_tx_postamble_modem_samples = self.c_lib.freedv_get_n_tx_postamble_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 = ctypes.c_short * n_tx_modem_samples
mod_out = mod_out() 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_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() mod_out_postamble = mod_out_postamble()
buffer = bytearray(payload_per_frame) # use this if CRC16 checksum is required ( DATA1-3) # 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)
# 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 = ctypes.c_ushort(self.c_lib.freedv_gen_crc16(
crc = crc.value.to_bytes(2, byteorder='big') # convert crc to 2 byte hex string 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 buffer += crc # append crc16 to buffer
data = (ctypes.c_ubyte * bytes_per_frame).from_buffer_copy(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_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.c_lib.freedv_rawdatapostambletx(freedv, mod_out_postamble)
self.streambuffer = bytearray() self.streambuffer = bytearray()
self.streambuffer += bytes(mod_out_preamble) self.streambuffer += bytes(mod_out_preamble)
self.streambuffer += bytes(mod_out) self.streambuffer += bytes(mod_out)
self.streambuffer += bytes(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]) self.streambuffer = bytes(converted_audio[0])
# append frame again with as much as in count defined # append frame again with as much as in count defined
for i in range(1, count): for i in range(1, count):
self.streambuffer += bytes(converted_audio[0]) self.streambuffer += bytes(converted_audio[0])
#print(len(self.streambuffer)) # print(len(self.streambuffer))
#self.streambuffer += bytes(converted_audio[0]) #self.streambuffer += bytes(converted_audio[0])
#print(len(self.streambuffer)) # print(len(self.streambuffer))
# -------------- transmit audio # -------------- transmit audio
#logging.debug("SENDING SIGNALLING FRAME " + str(data_out)) #logging.debug("SENDING SIGNALLING FRAME " + str(data_out))
##state_before_transmit = static.CHANNEL_STATE ##state_before_transmit = static.CHANNEL_STATE
##static.CHANNEL_STATE = 'SENDING_SIGNALLING' ##static.CHANNEL_STATE = 'SENDING_SIGNALLING'
while self.ptt_and_wait(True): while self.ptt_and_wait(True):
pass pass
self.audio_writing_to_stream = True self.audio_writing_to_stream = True
# wait until audio has been processed # wait until audio has been processed
while self.audio_writing_to_stream: while self.audio_writing_to_stream:
time.sleep(0.01) time.sleep(0.01)
static.CHANNEL_STATE = 'SENDING_SIGNALLING' static.CHANNEL_STATE = 'SENDING_SIGNALLING'
self.ptt_and_wait(False) self.ptt_and_wait(False)
## we have a problem with the receiving state # we have a problem with the receiving state
##static.CHANNEL_STATE = state_before_transmit ##static.CHANNEL_STATE = state_before_transmit
if state_before_transmit != 'RECEIVING_DATA': if state_before_transmit != 'RECEIVING_DATA':
static.CHANNEL_STATE = 'RECEIVING_SIGNALLING' static.CHANNEL_STATE = 'RECEIVING_SIGNALLING'
else: else:
static.CHANNEL_STATE = state_before_transmit static.CHANNEL_STATE = state_before_transmit
self.c_lib.freedv_close(freedv) self.c_lib.freedv_close(freedv)
# -------------------------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------------------------
# GET ARQ BURST FRAME VOM BUFFER AND MODULATE IT # GET ARQ BURST FRAME VOM BUFFER AND MODULATE IT
def transmit_arq_burst(self): def transmit_arq_burst(self):
# we could place this timing part inside the modem... # we could place this timing part inside the modem...
# lets see if this is a good idea.. # lets see if this is a good idea..
static.ARQ_DATA_CHANNEL_LAST_RECEIVED = int(time.time()) # we need to update our timeout timestamp # we need to update our timeout timestamp
static.ARQ_START_OF_BURST = int(time.time()) # 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 state_before_transmit = static.CHANNEL_STATE
static.CHANNEL_STATE = 'SENDING_DATA' static.CHANNEL_STATE = 'SENDING_DATA'
self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte) self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte)
freedv = self.c_lib.freedv_open(static.ARQ_DATA_CHANNEL_MODE) 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 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_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 # *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_modem_samples = self.c_lib.freedv_get_n_tx_modem_samples(freedv)
n_tx_postamble_modem_samples = self.c_lib.freedv_get_n_tx_postamble_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 = ctypes.c_short * n_tx_modem_samples
mod_out = mod_out() 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_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() mod_out_postamble = mod_out_postamble()
self.streambuffer = bytearray() self.streambuffer = bytearray()
self.c_lib.freedv_rawdatapreambletx(freedv, mod_out_preamble) self.c_lib.freedv_rawdatapreambletx(freedv, mod_out_preamble)
self.streambuffer += bytes(mod_out_preamble) self.streambuffer += bytes(mod_out_preamble)
if not static.ARQ_RPT_RECEIVED: if not static.ARQ_RPT_RECEIVED:
for n in range(0, static.ARQ_TX_N_FRAMES_PER_BURST): for n in range(0, static.ARQ_TX_N_FRAMES_PER_BURST):
# ---------------------------BUILD ARQ BURST --------------------------------------------------------------------- # ---------------------------BUILD ARQ BURST ---------------------------------------------------------------------
frame_type = 10 + n + 1 # static.ARQ_TX_N_FRAMES_PER_BURST frame_type = 10 + n + 1 # static.ARQ_TX_N_FRAMES_PER_BURST
frame_type = bytes([frame_type]) 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 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) n_total_arq_frame = len(static.TX_BUFFER)
#static.ARQ_TX_N_TOTAL_ARQ_FRAMES = n_total_arq_frame #static.ARQ_TX_N_TOTAL_ARQ_FRAMES = n_total_arq_frame
@ -355,18 +378,23 @@ class RF():
static.MYCALLSIGN_CRC8 + \ static.MYCALLSIGN_CRC8 + \
payload_data payload_data
buffer = bytearray(static.FREEDV_DATA_PAYLOAD_PER_FRAME) # create TX buffer # create TX buffer
buffer[:len(arqframe)] = arqframe # set buffersize to length of data which will be send 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 = ctypes.c_ushort(self.c_lib.freedv_gen_crc16(
crc = crc.value.to_bytes(2, byteorder='big') # convert crc to 2 byte hex string 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 buffer += crc # append crc16 to buffer
data = (ctypes.c_ubyte * static.FREEDV_DATA_BYTES_PER_FRAME).from_buffer_copy(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
# modulate DATA and safe it into mod_out pointer
self.c_lib.freedv_rawdatatx(freedv, mod_out, data)
self.streambuffer += bytes(mod_out) self.streambuffer += bytes(mod_out)
elif static.ARQ_RPT_RECEIVED: elif static.ARQ_RPT_RECEIVED:
@ -378,12 +406,14 @@ class RF():
frame_type = bytes([frame_type]) frame_type = bytes([frame_type])
try: 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: except:
print("modem buffer selection problem with ARQ RPT frames") print("modem buffer selection problem with ARQ RPT frames")
n_current_arq_frame = static.ARQ_N_SENT_FRAMES + missing_frame 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) n_total_arq_frame = len(static.TX_BUFFER)
#static.ARQ_TX_N_TOTAL_ARQ_FRAMES = n_total_arq_frame #static.ARQ_TX_N_TOTAL_ARQ_FRAMES = n_total_arq_frame
@ -396,28 +426,33 @@ class RF():
static.MYCALLSIGN_CRC8 + \ static.MYCALLSIGN_CRC8 + \
payload_data payload_data
buffer = bytearray(static.FREEDV_DATA_PAYLOAD_PER_FRAME) # create TX buffer # create TX buffer
buffer[:len(arqframe)] = arqframe # set buffersize to length of data which will be send 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 = ctypes.c_ushort(self.c_lib.freedv_gen_crc16(
crc = crc.value.to_bytes(2, byteorder='big') # convert crc to 2 byte hex string 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 buffer += crc # append crc16 to buffer
data = (ctypes.c_ubyte * static.FREEDV_DATA_BYTES_PER_FRAME).from_buffer_copy(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
# modulate DATA and safe it into mod_out pointer
self.c_lib.freedv_rawdatatx(freedv, mod_out, data)
self.streambuffer += bytes(mod_out) self.streambuffer += bytes(mod_out)
self.c_lib.freedv_rawdatapostambletx(freedv, mod_out_postamble) self.c_lib.freedv_rawdatapostambletx(freedv, mod_out_postamble)
self.streambuffer += bytes(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]) self.streambuffer = bytes(converted_audio[0])
# -------------- transmit audio # -------------- transmit audio
while self.ptt_and_wait(True): while self.ptt_and_wait(True):
pass pass
# this triggers writing buffer to audio stream # this triggers writing buffer to audio stream
@ -439,22 +474,23 @@ class RF():
# -------------------------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------------------------
def receive(self): def receive(self):
# DATAC0 # DATAC0
self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte) self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte)
datac0_freedv = self.c_lib.freedv_open(14) datac0_freedv = self.c_lib.freedv_open(14)
self.c_lib.freedv_get_bits_per_modem_frame(datac0_freedv) 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_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_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 # bytes_per_frame
datac0_bytes_out = datac0_bytes_out() #get pointer from bytes_out 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)
self.c_lib.freedv_set_frames_per_burst(datac0_freedv, 1)
datac0_modem_stats_snr = c_float() datac0_modem_stats_snr = c_float()
datac0_modem_stats_sync = c_int() datac0_modem_stats_sync = c_int()
datac0_buffer = bytes() datac0_buffer = bytes()
static.FREEDV_SIGNALLING_BYTES_PER_FRAME = datac0_bytes_per_frame static.FREEDV_SIGNALLING_BYTES_PER_FRAME = datac0_bytes_per_frame
static.FREEDV_SIGNALLING_PAYLOAD_PER_FRAME = datac0_bytes_per_frame - 2 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) self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte)
datac1_freedv = self.c_lib.freedv_open(10) 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_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_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 # bytes_per_frame
datac1_bytes_out = datac1_bytes_out() #get pointer from bytes_out datac1_bytes_out = (ctypes.c_ubyte * datac1_bytes_per_frame)
self.c_lib.freedv_set_frames_per_burst(datac1_freedv,1) 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_snr = c_float()
datac1_modem_stats_sync = c_int() datac1_modem_stats_sync = c_int()
datac1_buffer = bytes() datac1_buffer = bytes()
@ -474,10 +511,11 @@ class RF():
self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte) self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte)
datac3_freedv = self.c_lib.freedv_open(12) 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_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_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 # bytes_per_frame
datac3_bytes_out = datac3_bytes_out() #get pointer from bytes_out datac3_bytes_out = (ctypes.c_ubyte * datac3_bytes_per_frame)
self.c_lib.freedv_set_frames_per_burst(datac3_freedv,1) 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_snr = c_float()
datac3_modem_stats_sync = c_int() datac3_modem_stats_sync = c_int()
datac3_buffer = bytes() datac3_buffer = bytes()
@ -503,242 +541,240 @@ class RF():
''' '''
data_in = bytes() 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 #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 = 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 = data_in[0] # .rstrip(b'\x00')
self.fft_data = data_in self.fft_data = data_in
# we need to set nin * 2 beause of byte size in array handling # we need to set nin * 2 beause of byte size in array handling
datac0_nin = self.c_lib.freedv_nin(datac0_freedv) * 2 datac0_nin = self.c_lib.freedv_nin(datac0_freedv) * 2
datac1_nin = self.c_lib.freedv_nin(datac1_freedv) * 2 datac1_nin = self.c_lib.freedv_nin(datac1_freedv) * 2
datac3_nin = self.c_lib.freedv_nin(datac3_freedv) * 2 datac3_nin = self.c_lib.freedv_nin(datac3_freedv) * 2
# refill buffer only if every mode has worked with its data # 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)): 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 datac0_buffer += data_in
datac1_buffer += data_in datac1_buffer += data_in
datac3_buffer += data_in datac3_buffer += data_in
# DECODING DATAC0
# DECODING DATAC0
if len(datac0_buffer) >= (datac0_nin): if len(datac0_buffer) >= (datac0_nin):
datac0_audio = datac0_buffer[:datac0_nin] datac0_audio = datac0_buffer[:datac0_nin]
datac0_buffer = datac0_buffer[datac0_nin:] datac0_buffer = datac0_buffer[datac0_nin:]
#print(len(datac0_audio)) # print(len(datac0_audio))
self.c_lib.freedv_rawdatarx.argtype = [ctypes.POINTER(ctypes.c_ubyte), datac0_bytes_out, 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) sync = self.c_lib.freedv_get_rx_status(datac0_freedv)
if sync != 0 and nbytes != 0: if sync != 0 and nbytes != 0:
#calculate snr and scatter # calculate snr and scatter
self.get_scatter(datac0_freedv) self.get_scatter(datac0_freedv)
self.calculate_snr(datac0_freedv) self.calculate_snr(datac0_freedv)
datac0_task = threading.Thread(target=self.process_data, args=[datac0_bytes_out, datac0_freedv]) datac0_task = threading.Thread(target=self.process_data, args=[datac0_bytes_out, datac0_freedv])
datac0_task.start() datac0_task.start()
# DECODING DATAC1
# DECODING DATAC1
if len(datac1_buffer) >= (datac1_nin): if len(datac1_buffer) >= (datac1_nin):
datac1_audio = datac1_buffer[:datac1_nin] datac1_audio = datac1_buffer[:datac1_nin]
datac1_buffer = datac1_buffer[datac1_nin:] datac1_buffer = datac1_buffer[datac1_nin:]
#print(len(datac1_audio)) # print(len(datac1_audio))
self.c_lib.freedv_rawdatarx.argtype = [ctypes.POINTER(ctypes.c_ubyte), datac1_bytes_out, 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) sync = self.c_lib.freedv_get_rx_status(datac1_freedv)
if sync != 0 and nbytes != 0: if sync != 0 and nbytes != 0:
#calculate snr and scatter # calculate snr and scatter
self.get_scatter(datac1_freedv) self.get_scatter(datac1_freedv)
self.calculate_snr(datac1_freedv) self.calculate_snr(datac1_freedv)
datac1_task = threading.Thread(target=self.process_data, args=[datac1_bytes_out, datac1_freedv]) datac1_task = threading.Thread(target=self.process_data, args=[datac1_bytes_out, datac1_freedv])
datac1_task.start() datac1_task.start()
# DECODING DATAC3 # DECODING DATAC3
if len(datac3_buffer) >= (datac3_nin): if len(datac3_buffer) >= (datac3_nin):
datac3_audio = 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] 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) sync = self.c_lib.freedv_get_rx_status(datac3_freedv)
if sync != 0 and nbytes != 0: if sync != 0 and nbytes != 0:
#calculate snr and scatter # calculate snr and scatter
self.get_scatter(datac3_freedv) self.get_scatter(datac3_freedv)
self.calculate_snr(datac3_freedv) self.calculate_snr(datac3_freedv)
datac3_task = threading.Thread(target=self.process_data, args=[datac3_bytes_out, datac3_freedv]) datac3_task = threading.Thread(target=self.process_data, args=[datac3_bytes_out, datac3_freedv])
datac3_task.start() datac3_task.start()
# forward data only if broadcast or we are the receiver # 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 # 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 # 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): def process_data(self, bytes_out, freedv):
force = True force = True
print(bytes(bytes_out)) 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': 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: #self.c_lib.freedv_set_frames_per_burst(freedv_data, n_frames_per_burst);
if frame != 3 or force == True:
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))) # send payload data to arq checker without CRC16
if static.ARQ_RX_BURST_BUFFER.count(None) <= 1: data_handler.arq_data_received(bytes(bytes_out[:-2]))
logging.debug("FULL BURST BUFFER ---> UNSYNC")
self.c_lib.freedv_set_sync(freedv, 0)
else: #print("static.ARQ_RX_BURST_BUFFER.count(None) " + str(static.ARQ_RX_BURST_BUFFER.count(None)))
logging.critical("---------------------------SIMULATED MISSING FRAME") if static.ARQ_RX_BURST_BUFFER.count(None) <= 1:
force = True logging.debug("FULL BURST BUFFER ---> UNSYNC")
self.c_lib.freedv_set_sync(freedv, 0)
# BURST ACK else:
elif frametype == 60: logging.critical(
logging.debug("ACK RECEIVED....") "---------------------------SIMULATED MISSING FRAME")
data_handler.burst_ack_received() force = True
# FRAME ACK # BURST ACK
elif frametype == 61: elif frametype == 60:
logging.debug("FRAME ACK RECEIVED....") logging.debug("ACK RECEIVED....")
data_handler.frame_ack_received() data_handler.burst_ack_received()
# FRAME RPT # FRAME ACK
elif frametype == 62: elif frametype == 61:
logging.debug("REPEAT REQUEST RECEIVED....") logging.debug("FRAME ACK RECEIVED....")
data_handler.burst_rpt_received(bytes_out[:-2]) data_handler.frame_ack_received()
# FRAME NAK # FRAME RPT
elif frametype == 63: elif frametype == 62:
logging.debug("FRAME NAK RECEIVED....") logging.debug("REPEAT REQUEST RECEIVED....")
data_handler.frame_nack_received(bytes_out[:-2]) data_handler.burst_rpt_received(bytes_out[:-2])
# CQ FRAME
elif frametype == 200:
logging.debug("CQ RECEIVED....")
data_handler.received_cq(bytes_out[:-2])
# PING FRAME # FRAME NAK
elif frametype == 210: elif frametype == 63:
logging.debug("PING RECEIVED....") logging.debug("FRAME NAK RECEIVED....")
data_handler.received_ping(bytes_out[:-2]) data_handler.frame_nack_received(bytes_out[:-2])
# PING ACK # CQ FRAME
elif frametype == 211: elif frametype == 200:
logging.debug("PING ACK RECEIVED....") logging.debug("CQ RECEIVED....")
data_handler.received_ping_ack(bytes_out[:-2]) data_handler.received_cq(bytes_out[:-2])
# ARQ CONNECT # PING FRAME
elif frametype == 220: elif frametype == 210:
logging.info("ARQ CONNECT RECEIVED....") logging.debug("PING RECEIVED....")
data_handler.arq_received_connect(bytes_out[:-2]) data_handler.received_ping(bytes_out[:-2])
# ARQ CONNECT ACK / KEEP ALIVE # PING ACK
elif frametype == 221: elif frametype == 211:
logging.info("ARQ CONNECT ACK RECEIVED / KEEP ALIVE....") logging.debug("PING ACK RECEIVED....")
data_handler.arq_received_connect_keep_alive(bytes_out[:-2]) data_handler.received_ping_ack(bytes_out[:-2])
# ARQ CONNECT ACK / KEEP ALIVE # ARQ CONNECT
elif frametype == 222: # elif frametype == 220:
logging.debug("ARQ DISCONNECT RECEIVED") # logging.info("ARQ CONNECT RECEIVED....")
data_handler.arq_disconnect_received(bytes_out[:-2]) # data_handler.arq_received_connect(bytes_out[:-2])
# ARQ FILE TRANSFER RECEIVED! # ARQ CONNECT ACK / KEEP ALIVE
elif frametype == 225: # elif frametype == 221:
logging.debug("ARQ arq_received_data_channel_opener RECEIVED") # logging.info("ARQ CONNECT ACK RECEIVED / KEEP ALIVE....")
data_handler.arq_received_data_channel_opener(bytes_out[:-2]) # data_handler.arq_received_connect_keep_alive(bytes_out[:-2])
# ARQ CHANNEL IS OPENED # ARQ CONNECT ACK / KEEP ALIVE
elif frametype == 226: # elif frametype == 222:
logging.debug("ARQ arq_received_channel_is_open RECEIVED") # logging.debug("ARQ DISCONNECT RECEIVED")
data_handler.arq_received_channel_is_open(bytes_out[:-2]) # data_handler.arq_disconnect_received(bytes_out[:-2])
# ARQ CONNECT ACK / KEEP ALIVE # ARQ FILE TRANSFER RECEIVED!
elif frametype == 230: elif frametype == 225:
logging.debug("BEACON RECEIVED") logging.debug("ARQ arq_received_data_channel_opener RECEIVED")
data_handler.received_beacon(bytes_out[:-2]) data_handler.arq_received_data_channel_opener(bytes_out[:-2])
else: # ARQ CHANNEL IS OPENED
logging.info("OTHER FRAME: " + str(bytes_out[:-2])) elif frametype == 226:
print(frametype) 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 # ARQ CONNECT ACK / KEEP ALIVE
if frame == n_frames_per_burst: elif frametype == 230:
logging.debug("BEACON RECEIVED")
logging.debug("LAST FRAME ---> UNSYNC") data_handler.received_beacon(bytes_out[:-2])
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) else:
#bytes_out = bytes_out() # get pointer to bytes_out 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: else:
# for debugging purposes to receive all data # for debugging purposes to receive all data
pass pass
# print(bytes_out[:-2]) # print(bytes_out[:-2])
def get_scatter(self, freedv): def get_scatter(self, freedv):
modemStats = MODEMSTATS() modemStats = MODEMSTATS()
self.c_lib.freedv_get_modem_extended_stats.restype = None 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 = [] scatterdata = []
for i in range(MODEM_STATS_NC_MAX): for i in range(MODEM_STATS_NC_MAX):
for j in range(MODEM_STATS_NR_MAX): for j in range(MODEM_STATS_NR_MAX):
#check if odd or not to get every 2nd item for x # check if odd or not to get every 2nd item for x
if (j % 2) == 0: if (j % 2) == 0:
xsymbols = modemStats.rx_symbols[i][j] 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 # check if value 0.0 or has real data
if xsymbols != 0.0 and ysymbols != 0.0: 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 # only append scatter data if new data arrived
if len(scatterdata) > 0: if len(scatterdata) > 0:
static.SCATTER = scatterdata static.SCATTER = scatterdata
def calculate_ber(self, freedv): def calculate_ber(self, freedv):
Tbits = self.c_lib.freedv_get_total_bits(freedv) Tbits = self.c_lib.freedv_get_total_bits(freedv)
Terrs = self.c_lib.freedv_get_total_bit_errors(freedv) Terrs = self.c_lib.freedv_get_total_bit_errors(freedv)
if Tbits != 0: if Tbits != 0:
ber = (Terrs / Tbits) * 100 ber = (Terrs / Tbits) * 100
static.BER = int(ber) static.BER = int(ber)
self.c_lib.freedv_set_total_bit_errors(freedv, 0) self.c_lib.freedv_set_total_bit_errors(freedv, 0)
self.c_lib.freedv_set_total_bits(freedv, 0) self.c_lib.freedv_set_total_bits(freedv, 0)
def calculate_snr(self, freedv): def calculate_snr(self, freedv):
modem_stats_snr = c_float() modem_stats_snr = c_float()
modem_stats_sync = c_int() 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 modem_stats_snr = modem_stats_snr.value
try: try:
static.SNR = round(modem_stats_snr,1) static.SNR = round(modem_stats_snr, 1)
except: except:
static.SNR = 0 static.SNR = 0
def get_radio_stats(self): def get_radio_stats(self):
while True: while True:
time.sleep(0.1) time.sleep(0.1)
@ -748,14 +784,13 @@ class RF():
#static.HAMLIB_FREQUENCY = rigctld.get_frequency() #static.HAMLIB_FREQUENCY = rigctld.get_frequency()
#static.HAMLIB_MODE = rigctld.get_mode()[0] #static.HAMLIB_MODE = rigctld.get_mode()[0]
#static.HAMLIB_BANDWITH = rigctld.get_mode()[1] #static.HAMLIB_BANDWITH = rigctld.get_mode()[1]
def calculate_fft(self): def calculate_fft(self):
while True: while True:
time.sleep(0.01) time.sleep(0.01)
# WE NEED TO OPTIMIZE THIS! # WE NEED TO OPTIMIZE THIS!
data_in = self.fft_data data_in = self.fft_data
# https://gist.github.com/ZWMiller/53232427efc5088007cab6feee7c6e4c # https://gist.github.com/ZWMiller/53232427efc5088007cab6feee7c6e4c
audio_data = np.fromstring(data_in, np.int16) audio_data = np.fromstring(data_in, np.int16)
# Fast Fourier Transform, 10*log10(abs) is to scale it to dB # Fast Fourier Transform, 10*log10(abs) is to scale it to dB
@ -763,11 +798,11 @@ class RF():
try: try:
fftarray = np.fft.rfft(audio_data) 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 fftarray[fftarray == 0] = 1
dfft = 10.*np.log10(abs(fftarray)) dfft = 10.*np.log10(abs(fftarray))
dfftlist = dfft.tolist() dfftlist = dfft.tolist()
# send fft only if receiving # send fft only if receiving
if static.CHANNEL_STATE == 'RECEIVING_SIGNALLING' or static.CHANNEL_STATE == 'RECEIVING_DATA': if static.CHANNEL_STATE == 'RECEIVING_SIGNALLING' or static.CHANNEL_STATE == 'RECEIVING_DATA':
#static.FFT = dfftlist[20:100] #static.FFT = dfftlist[20:100]
@ -776,4 +811,3 @@ class RF():
print("setting fft = 0") print("setting fft = 0")
# else 0 # else 0
static.FFT = [0] * 400 static.FFT = [0] * 400

View file

@ -33,17 +33,19 @@ import static
import data_handler import data_handler
import helpers import helpers
import sys, os import sys
import os
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer): class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass pass
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler): class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
def handle(self): def handle(self):
print("Client connected...") print("Client connected...")
# loop through socket buffer until timeout is reached. then close buffer # loop through socket buffer until timeout is reached. then close buffer
socketTimeout = time.time() + 3 socketTimeout = time.time() + 3
while socketTimeout > time.time(): while socketTimeout > time.time():
@ -53,21 +55,21 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
#data = str(self.request.recv(1024), 'utf-8') #data = str(self.request.recv(1024), 'utf-8')
data = bytes() data = bytes()
# we need to loop through buffer until end of chunk is reached or timeout occured # we need to loop through buffer until end of chunk is reached or timeout occured
while True and socketTimeout > time.time(): while True and socketTimeout > time.time():
chunk = self.request.recv(71) # we keep amount of bytes short chunk = self.request.recv(71) # we keep amount of bytes short
data += chunk 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 break
data = data[:-1] # remove b'\n' data = data[:-1] # remove b'\n'
data = str(data, 'utf-8') data = str(data, 'utf-8')
if len(data) > 0: if len(data) > 0:
socketTimeout = time.time() + static.SOCKET_TIMEOUT socketTimeout = time.time() + static.SOCKET_TIMEOUT
# convert data to json object # convert data to json object
# we need to do some error handling in case of socket timeout or decoding issue # we need to do some error handling in case of socket timeout or decoding issue
try: try:
@ -78,7 +80,7 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
data = data.splitlines()[0] data = data.splitlines()[0]
received_json = json.loads(data) received_json = json.loads(data)
#except ValueError as e: # except ValueError as e:
# print("++++++++++++ START OF JSON ERROR +++++++++++++++++++++++") # print("++++++++++++ START OF JSON ERROR +++++++++++++++++++++++")
# print(e) # print(e)
# print("-----------------------------------") # print("-----------------------------------")
@ -86,29 +88,32 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
# print("++++++++++++ END OF JSON ERROR +++++++++++++++++++++++++") # print("++++++++++++ END OF JSON ERROR +++++++++++++++++++++++++")
# received_json = {} # received_json = {}
# break # break
#try: # try:
# CQ CQ CQ ----------------------------------------------------- # CQ CQ CQ -----------------------------------------------------
if received_json["command"] == "CQCQCQ": if received_json["command"] == "CQCQCQ":
#socketTimeout = 0 #socketTimeout = 0
#asyncio.run(data_handler.transmit_cq()) # asyncio.run(data_handler.transmit_cq())
CQ_THREAD = threading.Thread(target=data_handler.transmit_cq, args=[], name="CQ") CQ_THREAD = threading.Thread(
target=data_handler.transmit_cq, args=[], name="CQ")
CQ_THREAD.start() CQ_THREAD.start()
# PING ---------------------------------------------------------- # 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 # send ping frame and wait for ACK
dxcallsign = received_json["dxcallsign"] dxcallsign = received_json["dxcallsign"]
#asyncio.run(data_handler.transmit_ping(dxcallsign)) # asyncio.run(data_handler.transmit_ping(dxcallsign))
PING_THREAD = threading.Thread(target=data_handler.transmit_ping, args=[dxcallsign], name="CQ") PING_THREAD = threading.Thread(
target=data_handler.transmit_ping, args=[dxcallsign], name="CQ")
PING_THREAD.start() 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' 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()) static.ARQ_START_OF_TRANSMISSION = int(time.time())
dxcallsign = received_json["dxcallsign"] dxcallsign = received_json["dxcallsign"]
mode = int(received_json["mode"]) mode = int(received_json["mode"])
n_frames = int(received_json["n_frames"]) n_frames = int(received_json["n_frames"])
@ -116,12 +121,13 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
filetype = received_json["filetype"] filetype = received_json["filetype"]
data = received_json["data"] data = received_json["data"]
checksum = received_json["checksum"] checksum = received_json["checksum"]
static.DXCALLSIGN = bytes(dxcallsign, 'utf-8') 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 + '"}' #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} #dataframe = {filename: filename}
#data_out = bytes(received_json["data"], 'utf-8') #data_out = bytes(received_json["data"], 'utf-8')
dataframe = json.dumps(rawdata) dataframe = json.dumps(rawdata)
@ -141,9 +147,11 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
self.request.sendall(b'INVALID CALLSIGN') self.request.sendall(b'INVALID CALLSIGN')
else: else:
static.MYCALLSIGN = bytes(callsign, encoding) static.MYCALLSIGN = bytes(callsign, encoding)
static.MYCALLSIGN_CRC8 = helpers.get_crc_8(static.MYCALLSIGN) static.MYCALLSIGN_CRC8 = helpers.get_crc_8(
logging.info("CMD | MYCALLSIGN: " + str(static.MYCALLSIGN)) static.MYCALLSIGN)
logging.info("CMD | MYCALLSIGN: " +
str(static.MYCALLSIGN))
if received_json["type"] == 'SET' and received_json["command"] == 'MYGRID': if received_json["type"] == 'SET' and received_json["command"] == 'MYGRID':
mygrid = received_json["parameter"] mygrid = received_json["parameter"]
@ -152,25 +160,24 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
else: else:
static.MYGRID = bytes(mygrid, encoding) static.MYGRID = bytes(mygrid, encoding)
logging.info("CMD | MYGRID: " + str(static.MYGRID)) logging.info("CMD | MYGRID: " + str(static.MYGRID))
if received_json["type"] == 'GET' and received_json["command"] == 'STATION_INFO': if received_json["type"] == 'GET' and received_json["command"] == 'STATION_INFO':
output = { output = {
"COMMAND": "STATION_INFO", "COMMAND": "STATION_INFO",
"TIMESTAMP" : received_json["timestamp"], "TIMESTAMP": received_json["timestamp"],
"MY_CALLSIGN": str(static.MYCALLSIGN, encoding), "MY_CALLSIGN": str(static.MYCALLSIGN, encoding),
"DX_CALLSIGN": str(static.DXCALLSIGN, encoding), "DX_CALLSIGN": str(static.DXCALLSIGN, encoding),
"DX_GRID": str(static.DXGRID, encoding), "DX_GRID": str(static.DXGRID, encoding),
"EOF" : "EOF", "EOF": "EOF",
} }
jsondata = json.dumps(output) jsondata = json.dumps(output)
self.request.sendall(bytes(jsondata, encoding)) self.request.sendall(bytes(jsondata, encoding))
if received_json["type"] == 'GET' and received_json["command"] == 'TNC_STATE': if received_json["type"] == 'GET' and received_json["command"] == 'TNC_STATE':
output = { output = {
"COMMAND": "TNC_STATE", "COMMAND": "TNC_STATE",
"TIMESTAMP" : received_json["timestamp"], "TIMESTAMP": received_json["timestamp"],
"PTT_STATE": str(static.PTT_STATE), "PTT_STATE": str(static.PTT_STATE),
"CHANNEL_STATE": str(static.CHANNEL_STATE), "CHANNEL_STATE": str(static.CHANNEL_STATE),
"TNC_STATE": str(static.TNC_STATE), "TNC_STATE": str(static.TNC_STATE),
@ -178,65 +185,63 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
"AUDIO_RMS": str(static.AUDIO_RMS), "AUDIO_RMS": str(static.AUDIO_RMS),
"BER": str(static.BER), "BER": str(static.BER),
"SNR": str(static.SNR), "SNR": str(static.SNR),
"FREQUENCY" : str(static.HAMLIB_FREQUENCY), "FREQUENCY": str(static.HAMLIB_FREQUENCY),
"MODE" : str(static.HAMLIB_MODE), "MODE": str(static.HAMLIB_MODE),
"BANDWITH" : str(static.HAMLIB_BANDWITH), "BANDWITH": str(static.HAMLIB_BANDWITH),
"FFT" : str(static.FFT), "FFT": str(static.FFT),
"SCATTER" : static.SCATTER, "SCATTER": static.SCATTER,
"RX_BUFFER_LENGTH": str(len(static.RX_BUFFER)), "RX_BUFFER_LENGTH": str(len(static.RX_BUFFER)),
"TX_N_MAX_RETRIES": str(static.TX_N_MAX_RETRIES), "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_FRAMES_PER_BURST": str(static.ARQ_TX_N_FRAMES_PER_BURST),
"ARQ_TX_N_BURSTS": str(static.ARQ_TX_N_BURSTS), "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_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_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_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_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": str(static.ARQ_BYTES_PER_MINUTE),
"ARQ_BYTES_PER_MINUTE_BURST" : str(static.ARQ_BYTES_PER_MINUTE_BURST), "ARQ_BYTES_PER_MINUTE_BURST": str(static.ARQ_BYTES_PER_MINUTE_BURST),
"ARQ_TRANSMISSION_PERCENT" : str(static.ARQ_TRANSMISSION_PERCENT), "ARQ_TRANSMISSION_PERCENT": str(static.ARQ_TRANSMISSION_PERCENT),
"TOTAL_BYTES" : str(static.TOTAL_BYTES), "TOTAL_BYTES": str(static.TOTAL_BYTES),
"STATIONS" : [], "STATIONS": [],
"EOF" : "EOF", "EOF": "EOF",
} }
for i in range(0, len(static.HEARD_STATIONS)): 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]}) 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:
try:
jsondata = json.dumps(output) jsondata = json.dumps(output)
except ValueError as e: except ValueError as e:
print(e) print(e)
try: try:
self.request.sendall(bytes(jsondata, encoding)) self.request.sendall(bytes(jsondata, encoding))
except Exception as e: except Exception as e:
print(e) print(e)
if received_json["type"] == 'GET' and received_json["command"] == 'RX_BUFFER': if received_json["type"] == 'GET' and received_json["command"] == 'RX_BUFFER':
output = { output = {
"COMMAND": "RX_BUFFER", "COMMAND": "RX_BUFFER",
"DATA-ARRAY" : [], "DATA-ARRAY": [],
"EOF" : "EOF", "EOF": "EOF",
} }
for i in range(0, len(static.RX_BUFFER)): for i in range(0, len(static.RX_BUFFER)):
rawdata = json.loads(static.RX_BUFFER[i][3]) 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) jsondata = json.dumps(output)
self.request.sendall(bytes(jsondata, encoding)) self.request.sendall(bytes(jsondata, encoding))
if received_json["type"] == 'SET' and received_json["command"] == 'DEL_RX_BUFFER': if received_json["type"] == 'SET' and received_json["command"] == 'DEL_RX_BUFFER':
static.RX_BUFFER = [] static.RX_BUFFER = []
# exception, if JSON cant be decoded
#exception, if JSON cant be decoded # except Exception as e:
#except Exception as e:
except: except:
print("############ START OF ERROR #####################") print("############ START OF ERROR #####################")
print("SOCKET COMMAND ERROR: " + data) print("SOCKET COMMAND ERROR: " + data)
@ -248,19 +253,22 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
print("############ END OF ERROR #######################") print("############ END OF ERROR #######################")
print("reset of connection...") print("reset of connection...")
#socketTimeout = 0 #socketTimeout = 0
print("Client disconnected...") print("Client disconnected...")
def start_cmd_socket(): def start_cmd_socket():
try: try:
logging.info("SRV | STARTING TCP/IP SOCKET FOR CMD ON PORT: " + str(static.PORT)) logging.info(
socketserver.TCPServer.allow_reuse_address = True # https://stackoverflow.com/a/16641793 "SRV | STARTING TCP/IP SOCKET FOR CMD ON PORT: " + str(static.PORT))
cmdserver = ThreadedTCPServer((static.HOST, static.PORT), ThreadedTCPRequestHandler) # 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 = threading.Thread(target=cmdserver.serve_forever)
server_thread.daemon = True server_thread.daemon = True
server_thread.start() server_thread.start()
except: except:
print("Socket error...") print("Socket error...")