Merge pull request #17 from DJ2LS/ARQ

Dynamic ARQ v1
This commit is contained in:
DJ2LS 2021-02-08 16:06:55 +01:00 committed by GitHub
commit 53b7188187
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 775 additions and 773 deletions

View file

@ -2,6 +2,7 @@
## FreeDV- Just Another TNC Experiment
My first attempt to learn more about FreeDV and how to create a TNC which gets data from a TCP/IP socket
## Credits
David Rowe and the FreeDV team for developing the modem and libraries

569
arq.py
View file

@ -5,309 +5,356 @@ Created on Sun Dec 27 20:43:40 2020
@author: DJ2LS
"""
# CRC aller payloads via XOR scrambeln und dann eine CRC8 mitsenden
import logging
import crcengine
import threading
import time
from random import randrange
import static
import modem
import other
import helpers
import main
modem = modem.RF()
crc_algorithm = crcengine.new('crc16-ccitt-false') #load crc16 library
static.ARQ_PAYLOAD_PER_FRAME = static.FREEDV_PAYLOAD_PER_FRAME - 6
static.ARQ_PAYLOAD_PER_FRAME = static.FREEDV_DATA_PAYLOAD_PER_FRAME - 3 #6?!
static.ARQ_ACK_PAYLOAD_PER_FRAME = 14 - 2#
def arq_ack_timeout():
static.ARQ_ACK_TIMEOUT = 1
def data_received(data_in):
ARQ_N_RX_BURSTS = int.from_bytes(bytes(data_in[:1]), "big") - 10
static.ARQ_RX_BURST_BUFFER.append(data_in) #append data to RX BUFFER
print(ARQ_N_RX_BURSTS)
#while static.ACK_RX_TIMEOUT == 0: #define timeout where data has to be received untl error occurs
# arqframe = frame_type + \ # 1 [:1] # frame type and current number of arq frame of (current) burst
# bytes([static.ARQ_TX_N_FRAMES_PER_BURST]) + \ # 1 [1:2] # total number of arq frames per (current) burst
# static.ARQ_N_CURRENT_ARQ_FRAME + \ # 2 [2:4] # current arq frame number
# static.ARQ_N_TOTAL_ARQ_FRAMES + \ # 2 [4:6] # total number arq frames
# static.ARQ_BURST_PAYLOAD_CRC + \ # 2 [6:8] # arq crc
# payload_data # N [8:N] # payload data
if len(static.ARQ_RX_BURST_BUFFER) == ARQ_N_RX_BURSTS: #if received bursts are equal to burst number in frame
static.ARQ_N_FRAME = int.from_bytes(bytes(data_in[:1]), "big") - 10 #get number of burst frame
static.ARQ_N_RX_FRAMES_PER_BURSTS = int.from_bytes(bytes(data_in[1:2]), "big") #get number of bursts from received frame
static.ARQ_RX_N_CURRENT_ARQ_FRAME = int.from_bytes(bytes(data_in[2:4]), "big") #get current number of total frames
static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME = int.from_bytes(bytes(data_in[4:6]), "big") # get get total number of frames
static.ARQ_BURST_PAYLOAD_CRC = data_in[6:8]
burst_total_payload = bytearray()
for n_raw_frame in range(0,len(static.ARQ_RX_BURST_BUFFER)):
logging.debug("----------------------------------------------------------------")
logging.debug("ARQ_N_FRAME: " + str(static.ARQ_N_FRAME))
logging.debug("ARQ_N_RX_FRAMES_PER_BURSTS: " + str(static.ARQ_N_RX_FRAMES_PER_BURSTS))
logging.debug("ARQ_RX_N_CURRENT_ARQ_FRAME: " + str(static.ARQ_RX_N_CURRENT_ARQ_FRAME))
logging.debug("ARQ_N_ARQ_FRAMES_PER_DATA_FRAME: " + str(static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME))
logging.debug("static.ARQ_BURST_PAYLOAD_CRC: " + str(static.ARQ_BURST_PAYLOAD_CRC))
logging.debug("----------------------------------------------------------------")
arq_percent_burst = int((static.ARQ_N_FRAME / static.ARQ_N_RX_FRAMES_PER_BURSTS)*100)
arq_percent_frame = int(((static.ARQ_RX_N_CURRENT_ARQ_FRAME)/static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME)*100)
logging.info("ARQ | RX | ARQ FRAME [" + str(static.ARQ_N_FRAME) + "/" + str(static.ARQ_N_RX_FRAMES_PER_BURSTS) + "] [" + str(arq_percent_burst).zfill(3) + "%] --- TOTAL [" + str(static.ARQ_RX_N_CURRENT_ARQ_FRAME) + "/" + str(static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME) + "] [" + str(arq_percent_frame).zfill(3) + "%]" )
#allocate ARQ_RX_FRAME_BUFFER as a list with "None" if not already done. This should be done only once per burst!
# here we will save the N frame of a data frame to N list position so we can explicit search for it
if static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME != len(static.ARQ_RX_FRAME_BUFFER) and static.ARQ_RX_N_CURRENT_ARQ_FRAME == 1:
for i in range(0,static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME+1):
static.ARQ_RX_FRAME_BUFFER.insert(i,None)
#allocate ARQ_RX_BURST_BUFFER as a list with "None" if not already done. This should be done only once per burst!
# here we will save the N frame of a burst to N list position so we can explicit search for it
if static.ARQ_N_RX_FRAMES_PER_BURSTS != len(static.ARQ_RX_BURST_BUFFER) and static.ARQ_N_FRAME == 1:
for i in range(0,static.ARQ_N_RX_FRAMES_PER_BURSTS+1):
static.ARQ_RX_BURST_BUFFER.insert(i,None)
burst_frame = static.ARQ_RX_BURST_BUFFER[n_raw_frame] #get burst frame
burst_payload = burst_frame[3:] #remove frame type and burst CRC
burst_total_payload = burst_total_payload + burst_payload #stick bursts together
# now we add the incoming data to the specified position in our lists
static.ARQ_RX_BURST_BUFFER[static.ARQ_N_FRAME] = bytes(data_in)
static.ARQ_RX_FRAME_BUFFER[static.ARQ_RX_N_CURRENT_ARQ_FRAME] = bytes(data_in)
# -------------------------- ARQ BURST CHECKER
# run only if we recieved all ARQ FRAMES per ARQ BURST
burst_total_payload = bytearray()
if static.ARQ_N_FRAME == static.ARQ_N_RX_FRAMES_PER_BURSTS: #if received bursts are equal to burst number in frame
print(burst_total_payload)
burst_payload_crc = crc_algorithm(burst_total_payload)
burst_payload_crc = burst_payload_crc.to_bytes(2, byteorder='big')
print(burst_payload_crc)
if burst_payload_crc == data_in[1:3]: #IF burst payload crc and input crc are equal
print(data_in[1:3])
print("CRC EQUAL")
logging.info("TX | SENDING ACK [" + str(data_in[1:3]) +"]")
static.ARQ_RX_FRAME_BUFFER.append(burst_total_payload) # IF CRC TRUE APPEND burst_total_payload TO ARQ_RX_FRAME_BUFFER
print(data_in[7:9])
# -------- DETECT IF WE HAVE A FRAME HEADER
if data_in[7:9].startswith(b'\xAA\xAA'):
print("DAS IST DER ERSTE BURST MIT BOF!!!")
print("FRAME CRC = " + str(data_in[5:7]))
print("FRAME BURSTS = " + str(data_in[3:5]))
static.FRAME_CRC = data_in[5:7]
if data_in.rstrip(b'\x00').endswith(b'\xFF\xFF'):
print("DAS IST DER LETZTE BURST MIT EOF!!!")
# WENN DAS HIER ERFÜLLT IST, DANN KÖNNEN WIR MAL SCHAUEN WAS WIR AUSGEBEN KÖNNEN
print(len(static.ARQ_RX_FRAME_BUFFER))
total_frame = bytearray()
for b in range(len(static.ARQ_RX_FRAME_BUFFER)):
total_frame = total_frame + static.ARQ_RX_FRAME_BUFFER[b]
#print(total_frame)
payload = total_frame.split(b'\xAA\xAA')
payload = payload[1]
payload = payload.split(b'\xFF\xFF')
payload = payload[0]
frame_payload_crc = crc_algorithm(payload)
frame_payload_crc = frame_payload_crc.to_bytes(2, byteorder='big')
if static.FRAME_CRC == frame_payload_crc:
print("FRAME CRC PASST")
print(payload)
else:
print("FRAME CRC PASST NICHT")
print(static.FRAME_CRC)
print(frame_payload_crc)
print(payload)
#BUILDING ACK FRAME -----------------------------------------------
ack_frame = b'\7' + bytes(burst_payload_crc)
ack_buffer = bytearray(static.ARQ_PAYLOAD_PER_FRAME)
#here we get the total payload for the frame to calculate the crc
for n_raw_frame in range(1,len(static.ARQ_RX_BURST_BUFFER)):
# we need to check if we have a None or received data in list
if static.ARQ_RX_BURST_BUFFER[n_raw_frame] != None:
burst_frame = static.ARQ_RX_BURST_BUFFER[n_raw_frame] #get burst frame
burst_payload = burst_frame[8:] #remove frame type and burst CRC #4
burst_total_payload = burst_total_payload + burst_payload #stick bursts together
# ------------------ calculate CRC of BURST
burst_payload_crc = helpers.get_crc_16(burst_total_payload)
# IF BURST CRC IS CORRECT, APPEND BURST TO BUFFER AND SEND ACK FRAME
if burst_payload_crc == data_in[6:8]:
#BUILDING ACK FRAME FOR BURST -----------------------------------------------
#ack_payload = bytes(burst_payload_crc)
ack_frame = b'<'+ bytes(burst_payload_crc) # < = 60
ack_buffer = bytearray(static.ARQ_ACK_PAYLOAD_PER_FRAME)
ack_buffer[:len(ack_frame)] = ack_frame # set buffersize to length of data which will be send
#TRANSMIT ACK FRAME -----------------------------------------------
time.sleep(2)
modem.Transmit(ack_buffer)
static.ARQ_RX_BURST_BUFFER = []
#TRANSMIT ACK FRAME FOR BURST-----------------------------------------------
logging.info("ARQ | TX | ARQ BURST ACK [" + str(data_in[6:8].hex()) +"]")
modem.transmit_arq_ack(ack_buffer)
# ----------------------------------------------------------------
static.ARQ_RX_BURST_BUFFER = [] # CLEAR RX BURST BUFFER AFTER SENDING DATA
else: #IF burst payload crc and input crc are NOT equal
print("CRC NOT EQUAL!!!!!")
print(data_in[1:3])
static.ARQ_RX_BURST_BUFFER = []
logging.info("ARQ BURST CRC NOT EQUAL! [" + str(data_in[6:8]) + "]")
static.ARQ_RX_BURST_BUFFER = [] #erase ARQ RX Burst buffer
#if nframes are unequal to expected frames per burst
else:
#just a placeholder at this time
pass
# ---------------------------- FRAME MACHINE
# --------------- CHECK IF WE ARE MISSING FRAMES -------------------------------------------
#for frame in range(1,len(static.ARQ_RX_FRAME_BUFFER)):
# if static.ARQ_RX_FRAME_BUFFER[frame] == None:
# print("Missing frames:" + str(frame))
# --------------- IF LIST NOT CONTAINS "None" stick everything together
complete_data_frame = bytearray()
if static.ARQ_RX_FRAME_BUFFER.count(None) == 1: ## 1 because position 0 of list will alaways be None in our case
for frame in range(1,len(static.ARQ_RX_FRAME_BUFFER)):
raw_arq_frame = static.ARQ_RX_FRAME_BUFFER[frame]
arq_frame_payload = raw_arq_frame[8:]
# -------- DETECT IF WE RECEIVED A FRAME HEADER THEN SAVE DATA TO GLOBALS
if arq_frame_payload[2:4].startswith(static.FRAME_BOF):
static.FRAME_CRC = arq_frame_payload[:2]
static.ARQ_FRAME_BOF_RECEIVED = True
arq_frame_payload = arq_frame_payload.split(static.FRAME_BOF)
arq_frame_payload = arq_frame_payload[1]
# -------- DETECT IF WE RECEIVED A FRAME FOOTER THEN SAVE DATA TO GLOBALS
if arq_frame_payload.rstrip(b'\x00').endswith(static.FRAME_EOF):
static.ARQ_FRAME_EOF_RECEIVED = True
arq_frame_payload = arq_frame_payload.split(static.FRAME_EOF)
arq_frame_payload = arq_frame_payload[0]
# --------- AFTER WE SEPARATED BOF AND EOF, STICK EVERYTHING TOGETHER
complete_data_frame = complete_data_frame + arq_frame_payload
#check if Begin of Frame BOF and End of Frame EOF are received, then start calculating CRC and sticking everything together
if static.ARQ_FRAME_BOF_RECEIVED == True and static.ARQ_FRAME_EOF_RECEIVED == True:
frame_payload_crc = helpers.get_crc_16(complete_data_frame)
#IF THE FRAME PAYLOAD CRC IS EQUAL TO THE FRAME CRC WHICH IS KNOWN FROM THE HEADER --> SUCCESS
if frame_payload_crc == static.FRAME_CRC:
logging.info("ARQ | RX | DATA FRAME SUCESSFULLY RECEIVED! - TIME TO PARTY")
static.RX_BUFFER.append(complete_data_frame)
#BUILDING ACK FRAME FOR DATA FRAME -----------------------------------------------
ack_frame = b'='+ bytes(static.FRAME_CRC) # < = 61
ack_buffer = bytearray(static.ARQ_ACK_PAYLOAD_PER_FRAME)
ack_buffer[:len(ack_frame)] = ack_frame # set buffersize to length of data which will be send
#TRANSMIT ACK FRAME FOR BURST-----------------------------------------------
logging.info("ARQ | TX | ARQ DATA FRAME ACK [" + str(static.FRAME_CRC.hex()) +"]")
modem.transmit_arq_ack(ack_buffer)
# clearing buffers and resetting counters
static.ARQ_RX_BURST_BUFFER = []
static.ARQ_RX_FRAME_BUFFER = []
static.ARQ_FRAME_BOF_RECEIVED = False
static.ARQ_FRAME_EOF_RECEIVED = False
static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME = 0
#print("----------------------------------------------------------------")
#print(static.RX_BUFFER[-1])
#print("----------------------------------------------------------------")
else:
logging.info("ARQ | RX | DATA FRAME NOT SUCESSFULLY RECEIVED!")
def ack_received():
def burst_ack_received():
logging.info("RX | ACK RCVD!")
static.ACK_TIMEOUT = 1 #Force timer to stop waiting
static.ACK_RECEIVED = 1 #Force data loops of TNC to stop and continue with next frame
# static.ARQ_ACK_WAITING_FOR_ID
logging.debug("ARQ | RX | BURST ACK RCVD!")
static.ARQ_ACK_TIMEOUT = 1 #Force timer to stop waiting
static.ARQ_ACK_RECEIVED = 1 #Force data loops of TNC to stop and continue with next frame
def frame_ack_received():
logging.debug("ARQ | RX | FRAME ACK RCVD!")
static.ARQ_ACK_TIMEOUT = 1 #Force timer to stop waiting
static.ARQ_FRAME_ACK_RECEIVED = 1 #Force data loops of TNC to stop and continue with next frame
def transmit(data_out):
static.ARQ_PAYLOAD_PER_FRAME = static.FREEDV_PAYLOAD_PER_FRAME - 3
#----------------------- BUILD A FRAME WITH CRC AND N BURSTS
frame_BOF = b'\xAA\xAA'
frame_EOF = b'\xFF\xFF'
frame_header_length = 8
n_bursts_prediction = (len(data_out)+frame_header_length) // static.ARQ_PAYLOAD_PER_FRAME + ((len(data_out)+frame_header_length) % static.ARQ_PAYLOAD_PER_FRAME > 0) # aufrunden 3.2 = 4
n_bursts_prediction = n_bursts_prediction.to_bytes(2, byteorder='big') #65535
frame_payload_crc = crc_algorithm(data_out)
frame_payload_crc = frame_payload_crc.to_bytes(2, byteorder='big')
data_out = n_bursts_prediction + frame_payload_crc + frame_BOF + data_out + frame_EOF
# 2 2 2 N 2
print(data_out)
# --------------------------------------------- START OF MAIN DATA LOOP
static.TX_BUFFER = [data_out[i:i+static.ARQ_PAYLOAD_PER_FRAME] for i in range(0, len(data_out), static.ARQ_PAYLOAD_PER_FRAME)] # split incomming bytes to size of 30bytes - arq payload
static.TX_BUFFER_SIZE = len(static.TX_BUFFER)
static.ARQ_TX_N_FRAMES = n_frames_per_burst(len(data_out)) # DEFINE NUMBER OF FRAMES PER BURSTS
logging.info("TX | TOTAL PAYLOAD BYTES/FRAMES TO SEND: " + str(len(data_out)) + " / " + str(static.TX_BUFFER_SIZE))
#print(static.TX_BUFFER[2])
for n_raw_frame in range(0, static.TX_BUFFER_SIZE, static.ARQ_TX_N_FRAMES): # LOOP THROUGH DATA LIST with steps = ARQ_TX_N_FRAMES
# ----------- GENERATE PAYLOAD CRC FOR ARQ_TX_N_FRAMES
burst_total_payload = bytearray()
#----------------------------------------------------------------------------------------------------------
try: # DETECT IF LAST BURST
for i in range(static.ARQ_TX_N_FRAMES): #bytearray(b'111111111111111111111111222222222222222222222222')
# we need to make sure, payload data is always as long as static.ARQ_PAYLOAD_PER_FRAME beacuse of CRC!
burst_raw_payload = static.TX_BUFFER[n_raw_frame + i]
burst_payload = bytearray(static.ARQ_PAYLOAD_PER_FRAME)
burst_payload[:len(burst_raw_payload)] = burst_raw_payload # set buffersize to length of data which will be send
burst_total_payload = burst_total_payload + burst_payload
except IndexError: # IF LAST BURST DETECTED BUILD CRC WITH LESS FRAMES AND SET static.ARQ_TX_N_FRAMES TO VALUE OF REST!
print("LAST BURST!!!")
burst_total_payload = bytearray() # reset burst_total_payload because of possible input remaining of detecting loop one step above
n_last_burst = (static.TX_BUFFER_SIZE % n_raw_frame)
print(n_last_burst)
static.ARQ_TX_N_FRAMES = n_last_burst
for i in range(n_last_burst): #bytearray(b'111111111111111111111111222222222222222222222222')
burst_raw_payload = static.TX_BUFFER[n_raw_frame + i]
burst_payload = bytearray(static.ARQ_PAYLOAD_PER_FRAME)
burst_payload[:len(burst_raw_payload)] = burst_raw_payload # set buffersize to length of data which will be send
burst_total_payload = burst_total_payload + burst_payload
#----------------------------------------------------------------------------------------------------------
print(burst_total_payload)
burst_payload_crc = crc_algorithm(burst_total_payload)
burst_payload_crc = burst_payload_crc.to_bytes(2, byteorder='big')
print(burst_payload_crc)
static.ARQ_ACK_WAITING_FOR_ID = burst_payload_crc #set the global variable so we know for which ACK we are waiting for
#----------------------------------------------------------------------------------------------------------
#-------------------- BUILD ARQBURSTS
arqburst = []
for i in range(static.ARQ_TX_N_FRAMES):
frame_type = 10 + static.ARQ_TX_N_FRAMES
frame_type = bytes([frame_type])
payload_data = bytes(static.TX_BUFFER[n_raw_frame + i])
arqframe = frame_type + burst_payload_crc + payload_data
buffer = bytearray(static.FREEDV_PAYLOAD_PER_FRAME) # create TX buffer
buffer[:len(arqframe)] = arqframe # set buffersize to length of data which will be send
static.ARQ_PAYLOAD_PER_FRAME = static.FREEDV_DATA_PAYLOAD_PER_FRAME - 8 #3 ohne ARQ_TX_N_FRAMES_PER_BURST
frame_header_length = 4
arqburst.append(buffer)
n_arq_frames_per_data_frame = (len(data_out)+frame_header_length) // static.ARQ_PAYLOAD_PER_FRAME + ((len(data_out)+frame_header_length) % static.ARQ_PAYLOAD_PER_FRAME > 0) # aufrunden 3.2 = 4
#print(static.FREEDV_DATA_PAYLOAD_PER_FRAME)
#print(static.ARQ_PAYLOAD_PER_FRAME)
#print(n_bursts_prediction)
####static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME = n_arq_frames_per_data_frame.to_bytes(2, byteorder='big') #65535
frame_payload_crc = helpers.get_crc_16(data_out)
#print(frame_payload_crc)
# This is the total frame with frame header, which will be send
data_out = frame_payload_crc + static.FRAME_BOF + data_out + static.FRAME_EOF
# 2 2 N 2
#----------------------------------------------------------------------------------------------------------
# --------------------------------------------- LETS CREATE A BUFFER BY SPLITTING THE FILES INTO PEACES
static.TX_BUFFER = [data_out[i:i+static.ARQ_PAYLOAD_PER_FRAME] for i in range(0, len(data_out), static.ARQ_PAYLOAD_PER_FRAME)]
static.TX_BUFFER_SIZE = len(static.TX_BUFFER)
#print(static.TX_BUFFER)
logging.info("ARQ | TX | DATA FRAME --- BYTES: " + str(len(data_out)) + " ARQ FRAMES: " + str(static.TX_BUFFER_SIZE))
# --------------------------------------------- THIS IS THE MAIN LOOP-----------------------------------------------------------------
static.ARQ_N_SENT_FRAMES = 0 # SET N SENT FRAMES TO 0 FOR A NEW SENDING CYCLE
while static.ARQ_N_SENT_FRAMES <= static.TX_BUFFER_SIZE:
#print("static.ARQ_N_SENT_FRAMES: " + str(static.ARQ_N_SENT_FRAMES))
static.ARQ_TX_N_FRAMES_PER_BURST = get_n_frames_per_burst()
# ----------- CREATE FRAME TOTAL PAYLOAD TO BE ABLE TO CREATE CRC FOR IT
burst_total_payload = bytearray()
try: # DETECT IF LAST BURST TO PREVENT INDEX ERROR OF BUFFER
for i in range(static.ARQ_TX_N_FRAMES_PER_BURST): # Loop through TX_BUFFER LIST
# make sure we have always a filled buffer with the length of payload per frame
burst_raw_payload = static.TX_BUFFER[static.ARQ_N_SENT_FRAMES + i]
burst_payload = bytearray(static.ARQ_PAYLOAD_PER_FRAME)
burst_payload[:len(burst_raw_payload)] = burst_raw_payload # get frame from TX_BUFFER
burst_total_payload = burst_total_payload + burst_payload # append single frame to total payload buffer
except IndexError: # IF LAST BURST DETECTED BUILD CRC WITH LESS FRAMES AND SET static.ARQ_TX_N_FRAMES_PER_BURST TO VALUE OF REST!
burst_total_payload = bytearray() # reset burst_total_payload because of possible input remaining of detecting loop one step above
if static.ARQ_N_SENT_FRAMES == 0 and (static.ARQ_TX_N_FRAMES_PER_BURST > static.TX_BUFFER_SIZE): #WE CANT DO MODULO 0 --> CHECK IF FIRST FRAME == LAST FRAME
static.ARQ_TX_N_FRAMES_PER_BURST = static.TX_BUFFER_SIZE
elif static.ARQ_N_SENT_FRAMES == 1 and (static.ARQ_TX_N_FRAMES_PER_BURST > static.TX_BUFFER_SIZE): # MODULO 1 WILL ALWAYS BE 0 --> THIS FIXES IT
static.ARQ_TX_N_FRAMES_PER_BURST = static.TX_BUFFER_SIZE - static.ARQ_N_SENT_FRAMES
else:
static.ARQ_TX_N_FRAMES_PER_BURST = (static.TX_BUFFER_SIZE % static.ARQ_N_SENT_FRAMES)
#--------------------------------------------- N ATTEMPTS TO SEND BURSTS IF ACK FAILS
for static.TX_N_RETRIES in range(static.TX_N_MAX_RETRIES):
static.ACK_RECEIVED = 0
# ----------------------- Loop through ARQ FRAMES BUFFER with N = Numbers of frames which will be send at once
for n in range(static.ARQ_TX_N_FRAMES):
logging.info("TX | SENDING BURST " + str(n+1) + " / " + str(static.ARQ_TX_N_FRAMES))
modem.Transmit(arqburst[n])
time.sleep(2)
#modem.RF.Transmit(arqburst[n])
print(arqburst[n])
#print("ARQ_TX_N_FRAMES_PER_BURST OF LAST BURST: " + str(static.ARQ_TX_N_FRAMES_PER_BURST))
for i in range(static.ARQ_TX_N_FRAMES_PER_BURST): #bytearray(b'111111111111111111111111222222222222222222222222')
# --------------------------- START TIMER ---> IF TIMEOUT REACHED, ACK_TIMEOUT = 1
static.ACK_TIMEOUT = 0
timer = threading.Timer(static.ACK_TIMEOUT_SECONDS * static.ARQ_TX_N_FRAMES, other.timeout)
# make sure we have always a filled buffer with the length of payload per frame
burst_raw_payload = static.TX_BUFFER[static.ARQ_N_SENT_FRAMES + i]
burst_payload = bytearray(static.ARQ_PAYLOAD_PER_FRAME)
burst_payload[:len(burst_raw_payload)] = burst_raw_payload # get frame from TX_BUFFER
burst_total_payload = burst_total_payload + burst_payload # append single frame to total payload buffer
# ----------- GENERATE PAYLOAD CRC FOR ARQ_TX_N_FRAMES_PER_BURST
static.ARQ_BURST_PAYLOAD_CRC = helpers.get_crc_16(burst_total_payload)
#--------------------------------------------- N ATTEMPTS TO SEND BURSTS IF ACK RECEPTION FAILS
for static.TX_N_RETRIES in range(static.TX_N_MAX_RETRIES):
if static.ARQ_N_SENT_FRAMES+1 <= static.TX_BUFFER_SIZE:
logging.info("ARQ | TX | B:[" + str(static.ARQ_BURST_PAYLOAD_CRC.hex()) + "] F:[" + str(static.ARQ_N_SENT_FRAMES+1) + "-" + str(static.ARQ_N_SENT_FRAMES + static.ARQ_TX_N_FRAMES_PER_BURST) + "] | T:[" + str(static.ARQ_N_SENT_FRAMES) + "/" + str(static.TX_BUFFER_SIZE) + "] [" + str(int(static.ARQ_N_SENT_FRAMES/(static.TX_BUFFER_SIZE)*100)).zfill(3) + "%] | A:[" + str(static.TX_N_RETRIES+1) + "/" + str(static.TX_N_MAX_RETRIES) + "]")
# lets start a thread to transmit nonblocking
TRANSMIT_ARQ_BURST_THREAD = threading.Thread(target=modem.transmit_arq_burst, name="TRANSMIT_ARQ_BURST")
TRANSMIT_ARQ_BURST_THREAD.start()
# lets wait during sending. After sending is finished we will continue
while static.ARQ_STATE == 'SENDING_DATA':
time.sleep(0.05)
# --------------------------- START TIMER FOR WAITING FOR ACK ---> IF TIMEOUT REACHED, ACK_TIMEOUT = 1
#reset timer and ack state
static.ARQ_FRAME_ACK_RECEIVED = 0
static.ARQ_ACK_RECEIVED = 0
static.ARQ_ACK_TIMEOUT = 0
logging.debug("ARQ | RX | WAITING FOR BURST ACK")
static.ARQ_STATE = 'RECEIVING_ACK'
timer = threading.Timer(static.ARQ_ACK_TIMEOUT_SECONDS, arq_ack_timeout)
timer.start()
# --------------------------- WHILE TIMEOUT NOT REACHED AND NO ACK RECEIVED --> LISTEN
logging.info("TX | WAITING FOR ACK")
while static.ACK_TIMEOUT == 0 and static.ACK_RECEIVED == 0:
static.MODEM_RECEIVE = True
else:
logging.info("TX | ACK TIMEOUT - SENDING AGAIN")
#--------------- BREAK LOOP IF ACK HAS BEEN RECEIVED
if static.ACK_RECEIVED == 1:
#static.TX_N_RETRIES = 3
# --------------------------- WHILE TIMEOUT NOT REACHED AND NO ACK RECEIVED --> LISTEN
while static.ARQ_ACK_TIMEOUT == 0 and static.ARQ_ACK_RECEIVED == 0:
time.sleep(0.01) # lets reduce CPU load a little bit
#print(static.ARQ_STATE)
if static.ARQ_ACK_RECEIVED == 0 and static.ARQ_ACK_TIMEOUT == 1:
#logging.info("ARQ | RX | ACK TIMEOUT | SENDING ARQ BURST AGAIN")
pass
#--------------- BREAK LOOP IF ACK HAS BEEN RECEIVED OR FRAME ACK HAS BEEN RECEIVED
if static.ARQ_ACK_RECEIVED == 1:
#-----------IF ACK RECEIVED, INCREMENT ITERATOR FOR MAIN LOOP TO PROCEED WITH NEXT FRAMES/BURST
static.ARQ_N_SENT_FRAMES = static.ARQ_N_SENT_FRAMES + static.ARQ_TX_N_FRAMES_PER_BURST
break
#--------------- BREAK LOOP IF FRAME ACK HAS BEEN RECEIVED EARLIER AS EXPECTED
if static.ARQ_FRAME_ACK_RECEIVED == 1:
logging.info("ARQ | RX | EARLY FRAME ACK RECEIVED - STOPPING TX")
#static.ARQ_N_SENT_FRAMES = #static.TX_BUFFER_SIZE
static.ARQ_N_SENT_FRAMES = static.ARQ_N_SENT_FRAMES + static.ARQ_TX_N_FRAMES_PER_BURST
break
# ----------- if no ACK received and out of retries.....stop frame sending
if static.ACK_RECEIVED == 0:
logging.info("TX | NO ACK RECEIVED | FRAME NEEDS TO BE RESEND!")
break
if static.ARQ_ACK_RECEIVED == 0 and static.ARQ_FRAME_ACK_RECEIVED == 0 and static.ARQ_ACK_TIMEOUT == 1:
logging.info("ARQ | TX | NO BURST OR FRAME ACK RECEIVED | DATA SHOULD BE RESEND!")
print(bytes(static.TX_BUFFER[static.ARQ_N_SENT_FRAMES]))
break
#-------------------------BREAK TX BUFFER LOOP IF ALL PACKETS HAVE BEEN SENT AND WE GOT A FRAME ACK
if static.ARQ_N_SENT_FRAMES == static.TX_BUFFER_SIZE and static.ARQ_FRAME_ACK_RECEIVED == 1:
logging.info("ARQ | RX | REGULAR FRAME ACK RECEIVED - DATA TRANSMITTED!")
break
#-------------------------BREAK TX BUFFER LOOP IF ALL PACKETS HAVE BEEN SENT
if n_raw_frame == static.TX_BUFFER_SIZE:
break
# ------------ TIMER TO WAIT UNTIL NEXT PACKAGE WILL BE SEND TO PREVENT TIME ISSEUS
time.sleep(5)
logging.info("TX | BUFFER EMPTY")
# IF TX BUFFER IS EMPTY / ALL FRAMES HAVE BEEN SENT --> HERE WE COULD ADD AN static.VAR for IDLE STATE
# BURST MACHINE TO DEFINE N BURSTS PER FRAME
def n_frames_per_burst(len_data):
if len_data <= static.ARQ_PAYLOAD_PER_FRAME:
n_frames_per_burst = 1
else:
n_frames_per_burst = 1
return n_frames_per_burst
logging.info("ARQ | TX | BUFFER EMPTY")
# - RESET COUNTERS
static.ARQ_N_SENT_FRAMES = 0
static.ARQ_TX_N_FRAMES_PER_BURST = 0
static.ARQ_ACK_RECEIVED = 0
static.ARQ_FRAME_ACK_RECEIVED = 0
# BURST MACHINE TO DEFINE N BURSTS PER FRAME ---> LATER WE CAN USE CHANNEL MESSUREMENT TO SET FRAMES PER BURST
def get_n_frames_per_burst():
n_frames_per_burst = randrange(1,10)
#n_frames_per_burst = 1
return n_frames_per_burst

29
helpers.py Normal file
View file

@ -0,0 +1,29 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Dec 25 21:25:14 2020
@author: DJ2LS
"""
import time
import threading
import logging
import crcengine
import static
def get_crc_8(data):
crc_algorithm = crcengine.new('crc8-ccitt') #load crc8 library
crc_data = crc_algorithm(data)
crc_data = crc_data.to_bytes(1, byteorder='big')
return crc_data
def get_crc_16(data):
crc_algorithm = crcengine.new('crc16-ccitt-false') #load crc16 library
crc_data = crc_algorithm(data)
crc_data = crc_data.to_bytes(2, byteorder='big')
return crc_data

View file

@ -21,6 +21,6 @@ cmake -DCODEC2_BUILD_DIR=~/FreeDV-JATE/codec2/build_linux ../
make
cd ~/FreeDV-Socket-TNC/codec2/build_linux && rm -Rf *
cd ~/FreeDV-JATE/codec2/build_linux && rm -Rf *
cmake -DLPCNET_BUILD_DIR=~/FreeDV-JATE/LPCNet/build_linux ..
make

70
main.py
View file

@ -8,49 +8,45 @@ Created on Tue Dec 22 16:58:45 2020
"""
import socketserver
import threading
import argparse
import logging
import tnc
#import tnc
import static
import modem
modem = modem.RF()
#--------------------------------------------GET PARAMETER INPUTS
parser = argparse.ArgumentParser(description='Simons TEST TNC')
parser.add_argument('--rx', dest="audio_input_device", default=0, help="sound card for listening.", type=int)
parser.add_argument('--tx', dest="audio_output_device", default=0, help="sound card for transmitting.", type=int)
parser.add_argument('--port', dest="socket_port", default=3000, help="Set the port, the socket is listening on.", type=int)
args = parser.parse_args()
static.AUDIO_INPUT_DEVICE = args.audio_input_device
static.AUDIO_OUTPUT_DEVICE = args.audio_output_device
static.PORT = args.socket_port
#-------------------------------------------- DEFINE LOGGER
logger = logging.getLogger()
logger.setLevel("INFO") #DEBUG>INFO>WARNING>ERROR>CRITICAL
#--------------------------------------------START AUDIO THREAD
logging.info("STARTING AUDIO THREAD")
static.MODEM_RECEIVE = True
audio_receiver_thread = threading.Thread(target=modem.Receive, name="Audio Listener")
audio_receiver_thread.start()
#--------------------------------------------START SERVER
logging.info("STARTING TCP/IP SOCKET ON PORT " + str(static.PORT))
try:
socketserver.TCPServer.allow_reuse_address = True #https://stackoverflow.com/a/16641793
server = socketserver.TCPServer((static.HOST, static.PORT), tnc.TCPRequestHandler)
server.serve_forever()
finally:
server.server_close()
if __name__ == '__main__':
#--------------------------------------------GET PARAMETER INPUTS
parser = argparse.ArgumentParser(description='Simons TEST TNC')
parser.add_argument('--rx', dest="audio_input_device", default=0, help="sound card for listening.", type=int)
parser.add_argument('--tx', dest="audio_output_device", default=0, help="sound card for transmitting.", type=int)
parser.add_argument('--port', dest="socket_port", default=3000, help="Set the port, the socket is listening on.", type=int)
args = parser.parse_args()
static.AUDIO_INPUT_DEVICE = args.audio_input_device
static.AUDIO_OUTPUT_DEVICE = args.audio_output_device
static.PORT = args.socket_port
import tnc # we need to wait until we got all parameters from argparse
#-------------------------------------------- DEFINE LOGGER
logger = logging.getLogger()
logger.setLevel("INFO") #DEBUG>INFO>WARNING>ERROR>CRITICAL
#--------------------------------------------START SERVER
logging.info("STARTING TCP/IP SOCKET ON PORT " + str(static.PORT))
try:
socketserver.TCPServer.allow_reuse_address = True #https://stackoverflow.com/a/16641793
server = socketserver.TCPServer((static.HOST, static.PORT), tnc.TCPRequestHandler)
server.serve_forever()
finally:
server.server_close()

453
modem.py
View file

@ -10,174 +10,327 @@ import ctypes
from ctypes import *
import pathlib
import pyaudio
import audioop
import sys
import logging
import time
import threading
import helpers
import static
import arq
#arq = arq.ARQ()
class RF():
def __init__(self):
self.p = pyaudio.PyAudio()
self.defaultFrames = static.DEFAULT_FRAMES
self.audio_input_device = static.AUDIO_INPUT_DEVICE
self.audio_output_device = static.AUDIO_OUTPUT_DEVICE
self.tx_sample_state = static.TX_SAMPLE_STATE
self.rx_sample_state = static.RX_SAMPLE_STATE
self.audio_sample_rate = static.AUDIO_SAMPLE_RATE
self.modem_sample_rate = static.MODEM_SAMPLE_RATE
self.audio_frames_per_buffer = static.AUDIO_FRAMES_PER_BUFFER
self.audio_channels = static.AUDIO_CHANNELS
self.format = pyaudio.paInt16
self.stream = None
#self.data_input = "stdin"
self.data_input = "audio"
#self.data_output = "stdout"
self.data_output = "audio"
def __init__(self):
#-------------------------------------------- LOAD FREEDV
libname = pathlib.Path().absolute() / "codec2/build_linux/src/libcodec2.so"
self.c_lib = ctypes.CDLL(libname)
self.mode = static.FREEDV_MODE # define mode
self.freedv = self.c_lib.freedv_open(self.mode)
self.bytes_per_frame = int(self.c_lib.freedv_get_bits_per_modem_frame(self.freedv)/8)
self.payload_per_frame = self.bytes_per_frame -2
self.n_tx_modem_samples = self.c_lib.freedv_get_n_tx_modem_samples(self.freedv)*2 #get n_tx_modem_samples which defines the size of the modulation object
self.n_max_modem_samples = self.c_lib.freedv_get_n_max_modem_samples(self.freedv)
self.n_nom_modem_samples = self.c_lib.freedv_get_n_nom_modem_samples(self.freedv)
self.nin = self.c_lib.freedv_nin(self.freedv)
static.FREEDV_BYTES_PER_FRAME = self.bytes_per_frame
static.FREEDV_PAYLOAD_PER_FRAME = self.payload_per_frame
# MODULATION-OUT OBJECT
def ModulationOut(self):
return (c_short * self.n_tx_modem_samples)
# MODULATION-IN OBJECT
def ModulationIn(self):
return (c_short * (self.n_max_modem_samples))
# FRAME BYTES
# Pointer for changing buffer data type
def FrameBytes(self):
return (c_ubyte * self.bytes_per_frame)
#--------------------------------------------CREATE PYAUDIO INSTANCE
self.p = pyaudio.PyAudio()
#--------------------------------------------GET SUPPORTED SAMPLE RATES FROM SOUND DEVICE
#static.AUDIO_SAMPLE_RATE_RX = int(self.p.get_device_info_by_index(static.AUDIO_INPUT_DEVICE)['defaultSampleRate'])
#static.AUDIO_SAMPLE_RATE_TX = int(self.p.get_device_info_by_index(static.AUDIO_OUTPUT_DEVICE)['defaultSampleRate'])
static.AUDIO_SAMPLE_RATE_TX = 8000
static.AUDIO_SAMPLE_RATE_RX = 8000
#--------------------------------------------OPEN AUDIO CHANNEL RX
self.stream_rx = self.p.open(format=pyaudio.paInt16,
channels=static.AUDIO_CHANNELS,
rate=static.AUDIO_SAMPLE_RATE_RX,
frames_per_buffer=static.AUDIO_FRAMES_PER_BUFFER,
input=True,
input_device_index=static.AUDIO_INPUT_DEVICE,
)
#--------------------------------------------OPEN AUDIO CHANNEL TX
self.stream_tx = self.p.open(format=pyaudio.paInt16,
channels=1,
rate=static.AUDIO_SAMPLE_RATE_TX,
frames_per_buffer=static.AUDIO_FRAMES_PER_BUFFER, #n_nom_modem_samples
output=True,
output_device_index=static.AUDIO_OUTPUT_DEVICE, #static.AUDIO_OUTPUT_DEVICE
)
#--------------------------------------------START DECODER THREAD
FREEDV_DECODER_THREAD = threading.Thread(target=self.receive, args=[static.FREEDV_DATA_MODE,static.FREEDV_SIGNALLING_MODE], name="FREEDV_DECODER_THREAD")
FREEDV_DECODER_THREAD.start()
#--------------------------------------------------------------------------------------------------------
# GET DATA AND MODULATE IT
def Transmit(self,data_out):
mod_out = self.ModulationOut()() # new modulation object and get pointer to it
data_list = [data_out[i:i+self.payload_per_frame] for i in range(0, len(data_out), self.payload_per_frame)] # split incomming bytes to size of 30bytes, create a list and loop through it
def transmit(self,mode,data_out):
self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte)
freedv = self.c_lib.freedv_open(mode)
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)*2 #get n_tx_modem_samples which defines the size of the modulation object
mod_out = ctypes.c_short * n_tx_modem_samples
mod_out = mod_out()
mod_out_preamble = ctypes.c_short * n_tx_modem_samples #1760 for mode 10,11,12 #4000 for mode 9
mod_out_preamble = mod_out_preamble()
data_list = [data_out[i:i+payload_per_frame] for i in range(0, len(data_out), payload_per_frame)] # split incomming bytes to size of 30bytes, create a list and loop through it
data_list_length = len(data_list)
for i in range(data_list_length): # LOOP THROUGH DATA LIST
if self.mode < 10: # don't generate CRC16 for modes 0 - 9
buffer = bytearray(self.bytes_per_frame) # use this if no CRC16 checksum is required
buffer[:len(data_list[i])] = data_list[i] # set buffersize to length of data which will be send
if self.mode >= 10: #generate CRC16 for modes 10-12..
buffer = bytearray(self.payload_per_frame) # use this if CRC16 checksum is required ( DATA1-3)
buffer[:len(data_list[i])] = data_list[i] # set buffersize to length of data which will be send
crc = c_ushort(self.c_lib.freedv_gen_crc16(bytes(buffer), self.payload_per_frame)) # generate CRC16
crc = crc.value.to_bytes(2, byteorder='big') # convert crc to 2 byte hex string
buffer += crc # append crc16 to buffer
data = self.FrameBytes().from_buffer_copy(buffer) #change data format from bytearray to ctypes.u_byte and copy from buffer to data
buffer = bytearray(payload_per_frame) # use this if CRC16 checksum is required ( DATA1-3)
buffer[:len(data_list[i])] = data_list[i] # set buffersize to length of data which will be send
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
buffer += crc # append crc16 to buffer
self.c_lib.freedv_rawdatatx(self.freedv,mod_out,data) # modulate DATA and safe it into mod_out pointer
if self.data_output == "stdout":
sys.stdout.buffer.write(mod_out) # print data to terminal for piping the output to other programs
sys.stdout.flush() # flushing stdout
if self.data_output == "audio":
#print(self.audio_channels)
stream_tx = self.p.open(format=self.format,
channels=self.audio_channels,
rate=self.audio_sample_rate,
frames_per_buffer=self.n_nom_modem_samples,
output=True,
output_device_index=self.audio_output_device,
)
audio = audioop.ratecv(mod_out,2,1,self.modem_sample_rate, self.audio_sample_rate, self.tx_sample_state)
stream_tx.write(audio[0])
stream_tx.close()
return mod_out
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
# -------------- preamble area
# WE NEED TO ADJUST IT FOR SINGLE TRANSMISSION
txbuffer = bytearray()
txbuffer += bytes(mod_out_preamble)
txbuffer += bytes(mod_out)
txbuffer = txbuffer.rstrip(b'\x00')
# -------------- transmit audio
self.stream_tx.write(bytes(txbuffer))
#--------------------------------------------------------------------------------------------------------
def transmit_arq_ack(self,ack_buffer):
# DEMODULATE DATA AND RETURN IT
def Receive(self):
static.ARQ_STATE = 'SENDING_ACK'
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)
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)*2 #get n_tx_modem_samples which defines the size of the modulation object
mod_out = ctypes.c_short * n_tx_modem_samples
mod_out = mod_out()
mod_out_preamble = ctypes.c_short * (1760*2) #1760 for mode 10,11,12 #4000 for mode 9
mod_out_preamble = mod_out_preamble()
# Open Audio Channel once
stream_rx = self.p.open(format=self.format,
channels=self.audio_channels,
rate=self.audio_sample_rate,
frames_per_buffer=self.n_max_modem_samples,
input=True,
input_device_index=self.audio_input_device,
)
while static.MODEM_RECEIVE == True: # Listne to audio until data arrives
#if self.data_input == "stdin":
# samples = self.c_lib.freedv_nin(self.freedv)*2 ### MIT DER *2 funktioniert das irgendwie recht zuverlässig bei mode 5! Bei Mode 12 auch
# data_in = sys.stdin.buffer.read(samples)
if self.data_input == "audio":
data_in = stream_rx.read(self.c_lib.freedv_nin(self.freedv), exception_on_overflow = False)
#print(bytes(data_in))
buffer = bytearray(self.n_max_modem_samples*2) # N MAX SAMPLES * 2
buffer[:len(data_in)] = data_in # copy across what we have
self.ModulationIn()() #Create new ModulationIn Object
modulation = self.ModulationIn()# get an empty modulation array
modulation = modulation.from_buffer_copy(buffer) # copy buffer across and get a pointer to it.
bytes_out = self.FrameBytes()() # initilize a pointer to where bytes will be outputed
nbytes = self.c_lib.freedv_rawdatarx(self.freedv, bytes_out, data_in) # Demodulated data and get number of demodulated bytes
if nbytes == self.bytes_per_frame: # make sure, we receive a full frame
print(bytes(bytes_out[:-2]))
self.c_lib.freedv_set_sync(self.freedv, 0) #FORCE UNSYNC
# CHECK IF FRAMETYPE CONTAINS ACK------------------------
frametype = int.from_bytes(bytes(bytes_out[:1]), "big")
if 50 >= frametype >= 10 :
arq.data_received(bytes(bytes_out[:-2])) #send payload data to arq checker without CRC16
# CHECK IF FRAME CONTAINS ACK------------------------
if bytes(bytes_out[:1]) == b'\7':
arq.ack_received()
#return bytes(bytes_out[:-2])
buffer = bytearray(payload_per_frame) # use this if CRC16 checksum is required ( DATA1-3)
buffer[:len(ack_buffer)] = ack_buffer # set buffersize to length of data which will be send
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
buffer += crc # append crc16 to buffer
#print(bytes(buffer))
data = (ctypes.c_ubyte * bytes_per_frame).from_buffer_copy(buffer)
preamble_bytes = 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
txbuffer = bytearray()
txbuffer += bytes(mod_out_preamble)
txbuffer = txbuffer.rstrip(b'\x00') #lets remove unallocated memory because of wrong buffer :-/
txbuffer += bytes(mod_out)
txbuffer = txbuffer.rstrip(b'\x00') #lets remove unallocated memory because of wrong buffer :-/
# -------------- transmit audio
self.stream_tx.write(bytes(txbuffer))
self.stream_tx.write(bytes(txbuffer))
static.ARQ_STATE = 'RECEIVING_DATA'
#--------------------------------------------------------------------------------------------------------
# GET ARQ BURST FRAME VOM BUFFER AND MODULATE IT
def transmit_arq_burst(self):
static.ARQ_STATE = 'SENDING_DATA'
self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte)
freedv = self.c_lib.freedv_open(static.FREEDV_DATA_MODE)
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
mod_out = ctypes.c_short * n_tx_modem_samples
mod_out = mod_out()
mod_out_preamble = ctypes.c_short * (n_tx_modem_samples*2) #1760 for mode 10,11,12 #4000 for mode 9
mod_out_preamble = mod_out_preamble()
self.c_lib.freedv_rawdatapreambletx(freedv, mod_out_preamble);
txbuffer = bytearray()
txbuffer += bytes(mod_out_preamble)
txbuffer = txbuffer.rstrip(b'\x00') #lets remove unallocated memory because of wrong buffer :-/
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])
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')
n_total_arq_frame = len(static.TX_BUFFER)
static.ARQ_TX_N_TOTAL_ARQ_FRAMES = n_total_arq_frame.to_bytes(2, byteorder='big')
# 1 # frame type and current number of arq frame of burst
# 1 # total number of arq frames per (current) burst
# 2 # current arq frame number
# 2 # total number arq frames
# 2 # arq crc
# N # payload data
arqframe = frame_type + \
bytes([static.ARQ_TX_N_FRAMES_PER_BURST]) + \
static.ARQ_TX_N_CURRENT_ARQ_FRAME + \
static.ARQ_TX_N_TOTAL_ARQ_FRAMES + \
static.ARQ_BURST_PAYLOAD_CRC + \
payload_data
#print(arqframe)
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
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
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
txbuffer += bytes(mod_out)
txbuffer = txbuffer.rstrip(b'\x00') #lets remove unallocated memory because of wrong buffer :-/
# -------------- transmit audio
self.stream_tx.write(bytes(txbuffer))
static.ARQ_STATE = 'RECEIVING_ACK'
#--------------------------------------------------------------------------------------------------------
def receive(self,data_mode,signalling_mode):
self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte)
freedv_data = self.c_lib.freedv_open(data_mode)
freedv_signalling = self.c_lib.freedv_open(signalling_mode)
static.FREEDV_DATA_BYTES_PER_FRAME = int(self.c_lib.freedv_get_bits_per_modem_frame(freedv_data)/8)
static.FREEDV_DATA_PAYLOAD_PER_FRAME = static.FREEDV_DATA_BYTES_PER_FRAME -2
static.FREEDV_SIGNALLING_BYTES_PER_FRAME = int(self.c_lib.freedv_get_bits_per_modem_frame(freedv_signalling)/8)
static.FREEDV_SIGNALLING_PAYLOAD_PER_FRAME = static.FREEDV_SIGNALLING_BYTES_PER_FRAME -2
data_bytes_out = (ctypes.c_ubyte * static.FREEDV_DATA_BYTES_PER_FRAME)
data_bytes_out = data_bytes_out() #get pointer from bytes_out
signalling_bytes_out = (ctypes.c_ubyte * static.FREEDV_SIGNALLING_BYTES_PER_FRAME)
signalling_bytes_out = signalling_bytes_out() #get pointer from bytes_out
# with this we can interrupt receiving
while static.FREEDV_RECEIVE == True:
time.sleep(0.01)
# stuck in sync counter
stuck_in_sync_counter = 0
stuck_in_sync_10_counter = 0
#
while static.ARQ_STATE == 'RECEIVING_DATA':
time.sleep(0.01)
nin = self.c_lib.freedv_nin(freedv_data)
nin = int(nin*(static.AUDIO_SAMPLE_RATE_RX/static.MODEM_SAMPLE_RATE))
data_in = self.stream_rx.read(nin, exception_on_overflow = False)
data_in = data_in.rstrip(b'\x00')
#print(data_in)
self.c_lib.freedv_rawdatarx.argtype = [ctypes.POINTER(ctypes.c_ubyte), data_bytes_out, data_in] # check if really neccessary
nbytes = self.c_lib.freedv_rawdatarx(freedv_data, data_bytes_out, data_in) # demodulate audio
#print(self.c_lib.freedv_get_rx_status(freedv_data))
#-------------STUCK IN SYNC DETECTOR
stuck_in_sync_counter += 1
if self.c_lib.freedv_get_rx_status(freedv_data) == 10:
stuck_in_sync_10_counter += 1
#print(stuck_in_sync_counter)
if stuck_in_sync_counter == 33 and self.c_lib.freedv_get_rx_status(freedv_data) == 10:
print("stuck in sync #1 --> DOING UNSYNC")
self.c_lib.freedv_set_sync(freedv_data, 0) #FORCE UNSYNC
stuck_in_sync_counter = 0
stuck_in_sync_10_counter = 0
data_in = None
if stuck_in_sync_counter >= 66 and stuck_in_sync_10_counter >= 2:
print("stuck in sync #2 --> DOING UNSYNC")
self.c_lib.freedv_set_sync(freedv_data, 0) #FORCE UNSYNC
stuck_in_sync_counter = 0
stuck_in_sync_10_counter = 0
data_in = None
#-----------------------------------
#modem_stats_snr = c_float()
#modem_stats_sync = c_int()
#self.c_lib.freedv_get_modem_stats(freedv_data,byref(modem_stats_sync), byref(modem_stats_snr))
#modem_stats_snr = modem_stats_snr.value
#print(modem_stats_snr)
if nbytes == static.FREEDV_DATA_BYTES_PER_FRAME:
# counter reset for stuck in sync counter
stuck_in_sync_counter = 0
stuck_in_sync_10_counter = 0
#
# CHECK IF FRAMETYPE IS BETWEEN 10 and 50 ------------------------
frametype = int.from_bytes(bytes(data_bytes_out[:1]), "big")
frame = frametype - 10
n_frames_per_burst = int.from_bytes(bytes(data_bytes_out[1:2]), "big")
if 50 >= frametype >= 10 and len(data_bytes_out) > 30: # --> The length check filters out random strings without CRC
arq.data_received(bytes(data_bytes_out[:-2])) #send payload data to arq checker without CRC16
else:
print("MODE: " + str(data_mode) + " DATA: " + str(bytes(data_bytes_out)))
# NEEDS TO BE OPTIMIZED
# DO UNSYNC AFTER LAST BURST by checking the frame numbers agains the total frames per burst
if frame == n_frames_per_burst:
self.c_lib.freedv_set_sync(freedv_data, 0) #FORCE UNSYNC
# DETECT STUCK IN SYNC
# count rx status 10
# if 10 greater 2 after 6 then unsync
while static.ARQ_STATE == 'IDLE' or static.ARQ_STATE == 'RECEIVING_ACK':
time.sleep(0.01)
nin = self.c_lib.freedv_nin(freedv_signalling)
nin = int(nin*(static.AUDIO_SAMPLE_RATE_RX/static.MODEM_SAMPLE_RATE))
data_in = self.stream_rx.read(nin, exception_on_overflow = False)
data_in = data_in.rstrip(b'\x00')
self.c_lib.freedv_rawdatarx.argtype = [ctypes.POINTER(ctypes.c_ubyte), signalling_bytes_out, data_in] # check if really neccessary
nbytes = self.c_lib.freedv_rawdatarx(freedv_signalling, signalling_bytes_out, data_in) # demodulate audio
# CHECK IF FRAME CONTAINS ACK------------------------
frametype = int.from_bytes(bytes(signalling_bytes_out[:1]), "big")
# BURST ACK
if frametype == 60 and nbytes == static.FREEDV_SIGNALLING_BYTES_PER_FRAME:
arq.burst_ack_received()
# FRAME ACK
if frametype == 61 and nbytes == static.FREEDV_SIGNALLING_BYTES_PER_FRAME:
arq.frame_ack_received()
rxstatus = self.c_lib.freedv_get_rx_status(freedv_signalling)
#print(rxstatus)
if nbytes == static.FREEDV_SIGNALLING_BYTES_PER_FRAME or rxstatus == 10:
self.c_lib.freedv_set_sync(freedv_signalling, 0) #FORCE UNSYNC

View file

@ -1,18 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Dec 25 21:25:14 2020
@author: DJ2LS
"""
import time
import threading
import logging
import static
def timeout():
static.ACK_TIMEOUT = 1

View file

@ -3,17 +3,25 @@
"""
Created on Wed Dec 23 11:13:57 2020
@author: parallels
@author: DJ2LS
"""
# ADDITION MESSUREMENT:
#AUDIO TIME: 7.451462268829346 #12 # 1 FRAME + PREAMBLE
#MODULATION TIME: 0.002051115036010742 #12 # 1 FRAME + PREAMBLE
# Modem States
MODEM_RECEIVE = True
#MODULATION TIME: 0.004580974578857422 #12 # 2 FRAME + PREAMBLE
#AUDIO TIME: 14.750595331192017 #12 # 2 FRAME + PREAMBLE
# FreeDV Defaults
FREEDV_MODE = 12
FREEDV_BYTES_PER_FRAME = 0
FREEDV_PAYLOAD_PER_FRAME = 0
FREEDV_RECEIVE = True
FREEDV_DATA_MODE = 12
FREEDV_SIGNALLING_MODE = 14
FREEDV_DATA_BYTES_PER_FRAME = 0
FREEDV_DATA_PAYLOAD_PER_FRAME = 0
FREEDV_SIGNALLING_BYTES_PER_FRAME = 0
FREEDV_SIGNALLING_PAYLOAD_PER_FRAME = 0
# Server Defaults
HOST = "localhost"
@ -21,38 +29,78 @@ PORT = 3000
#AUdio Defaults
DEFAULT_FRAMES = 1024
AUDIO_INPUT_DEVICE = 1
AUDIO_OUTPUT_DEVICE = 1
TX_SAMPLE_STATE = None
RX_SAMPLE_STATE = None
AUDIO_SAMPLE_RATE = 8000
MODEM_SAMPLE_RATE = 8000
AUDIO_FRAMES_PER_BUFFER = 1024
#TX_SAMPLE_STATE = None
#RX_SAMPLE_STATE = None
#AUDIO_SAMPLE_RATE_RX = 44100
#AUDIO_SAMPLE_RATE_TX = 44100
MODEM_SAMPLE_RATE = 8000 #8000
AUDIO_FRAMES_PER_BUFFER = 2048
AUDIO_CHANNELS = 1
#TNC DEFAULTS
# ----ARQ STOP AND WAIT
# ARQ
TX_N_MAX_RETRIES = 3
TX_N_RETRIES = 3
ACK_RECEIVED = 0
ACK_TIMEOUT = 0
ACK_TIMEOUT_SECONDS = 15.0
ACK_RX_TIMEOUT = 0
ACK_RX_TIMEOUT_SECONDS = 15.0
TX_N_RETRIES = 0
ARQ_TX_N_FRAMES_PER_BURST = 0
ARQ_TX_N_BURSTS = 0
ARQ_TX_N_FRAMES = 2
ARQ_PAYLOAD_PER_FRAME = 0
ARQ_ACK_WAITING_FOR_ID = 0
ARQ_RX_BURST_BUFFER = []
ARQ_RX_FRAME_BUFFER = []
ARQ_RX_FRAME_N_BURSTS = 0
## TX
ARQ_TX_N_CURRENT_ARQ_FRAME = 0
ARQ_TX_N_TOTAL_ARQ_FRAMES = 0
##
## RX
ARQ_N_ARQ_FRAMES_PER_DATA_FRAME = 0 #total number of arq frames per data frame
ARQ_RX_N_CURRENT_ARQ_FRAME = 0
##
ARQ_N_RX_ARQ_FRAMES = 0 # total number of received frames
ARQ_N_RX_FRAMES_PER_BURSTS = 0 # NUMBER OF FRAMES WE ARE WAITING FOR --> GOT DATA FROM RECEIVED FRAME
ARQ_ACK_PAYLOAD_PER_FRAME = 0 # PAYLOAD per ACK frame
ARQ_ACK_RECEIVED = 0 # set to 1 if ACK received
ARQ_FRAME_ACK_RECEIVED = 0 # set to 1 if FRAME ACK received
ARQ_ACK_TIMEOUT = 0 # set to 1 if timeut reached
ARQ_ACK_TIMEOUT_SECONDS = 4.0 #timeout for waiting for ACK frames
FRAME_CRC = b''
FRAME_BOF = b'\xAA\xAA' #here we define 2 bytes for the BOF
FRAME_EOF = b'\xFF\xFF' #here we define 2 bytes for the EOF
ARQ_FRAME_BOF_RECEIVED = False # status, if we received a BOF of a data frame
ARQ_FRAME_EOF_RECEIVED = False # status, if we received a EOF of a data frame
ARQ_N_SENT_FRAMES = 0 #counter for already sent frames
# ARQ STATES:
# IDLE
# RECEIVING_DATA
# SENDING_DATA
# RECEIVING_ACK
# SENDING_ACK
# ACK_RECEIVED
#
#
#
ARQ_STATE = 'RECEIVING_DATA'
# ------- TX BUFFER
TX_BUFFER_SIZE = 0
TX_BUFFER = []
# ------- RX BUFFER
RX_BUFFER = []
RX_BUFFER_SIZE = 0

View file

@ -1,64 +0,0 @@
# TESTS
### TEST_RX.py
Receive string "HALLO" with a lot of debugging output
```
./TEST_TX.py | ./TEST_RX.py
```
Output should be:
```
SYNC
INPUT PARSER: 1760
INPUT LENGTH: 1760
BUFFER LENGTH: 1848
MODULATION LENGTH: 924
SYNC
b'HALLO\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15S'
INPUT PARSER: 1760
INPUT LENGTH: 1760
BUFFER LENGTH: 1848
MODULATION LENGTH: 924
SYNC
INPUT PARSER: 1760
```
### TEST_TX.py
Send string "HALLO"
```
./TEST_TX.py | ./freedv_data_raw_rx DATAC3 - - | hexdump -C
```
Output should be:
```
payload bytes_per_modem_frame: 30
00000000 54 45 53 54 00 00 00 00 00 00 00 00 00 00 00 00 |TEST............|
modem bufs processed: 22 output bytes: 30 output_frames: 1
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |..............|
0000001e
```
### Checksum comparison FREEDV vs CRCENGINE
```
###################### CHECKSUM COMPARISON FREEDV VS CRCENGINE ########
#https://crccalc.com
teststring = b'TEST'
# freedv crc16 checksum
crctest2 = c_ushort(self.c_lib.freedv_gen_crc16(teststring, len(teststring)))
print("FREEDV2: " + str(crctest2.value) + " = " + hex(crctest2.value))
#Python crc16 checksum
crc_algorithm = crcengine.new('crc16-ccitt-false') #load crc16 library
crctest3 = crc_algorithm(teststring)
print("CRCENGINE: " + str(crctest3) + " = " + hex(crctest3))
#######################################################################
```

View file

@ -1,111 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Dec 15 18:29:22 2020
@author: DJ2LS
"""
import ctypes
from ctypes import *
import pathlib
import binascii #required for string.to_bytes() function
import sys
def main():
modem = FreeDV() #Load FreeDV Class as "modem"
modem.Demodulate()
class FreeDV():
def __init__(self):
self.mode = 12 # define mode
libname = pathlib.Path().absolute() / "libcodec2.so"
self.c_lib = ctypes.CDLL(libname) # Load FreeDV shared libary
self.freedv = self.c_lib.freedv_open(self.mode) #Set FreeDV waveform ( 10,11,12 --> DATA1-3 )
self.bytes_per_frame = int(self.c_lib.freedv_get_bits_per_modem_frame(self.freedv)/8) #get bytes per frame from selected waveform
self.payload_per_frame = self.bytes_per_frame -2 #get frame payload because of 2byte CRC16 checksum
self.n_max_modem_samples = self.c_lib.freedv_get_n_max_modem_samples(self.freedv)
self.nin = self.c_lib.freedv_nin(self.freedv)
print("N MAX MODEM SAMPLES: " + str(self.n_max_modem_samples))
print("NIN: " + str(self.nin))
print("BYTES PER FRAME: " + str(self.bytes_per_frame))
print("---------------------------------")
# MODULATION-IN OBJECT
def ModulationIn(self):
return (c_short * (self.n_max_modem_samples)) ##
# Pointer for changing buffer data type
def FrameBytes(self):
return (c_ubyte * self.bytes_per_frame)
# Modulate function which returns modulated data
def Demodulate(self):
nin = self.c_lib.freedv_nin(self.freedv)
#while (self.c_lib.freedv_nin(self.freedv) == nin):
#while sys.stdin.buffer != 0:
while True:
samples = self.c_lib.freedv_nin(self.freedv)*2 ### MIT DER *2 funktioniert das irgendwie recht zuverlässig bei mode 5! Bei Mode 12 auch
data_in = sys.stdin.buffer.read(samples)
#buffer = bytearray(len(self.ModulationIn()())*sizeof(c_short)) # create empty byte array
#buffer = bytearray(len(self.ModulationIn()())*self.n_max_modem_samples) # create empty byte array
buffer = bytearray(self.n_max_modem_samples*2) # N MAX SAMPLES * 2
buffer[:len(data_in)] = data_in # copy across what we have
self.ModulationIn()() #Create new ModulationIn Object
modulation = self.ModulationIn()# get an empty modulation array
modulation = modulation.from_buffer_copy(buffer) # copy buffer across and get a pointer to it.
bytes_out = self.FrameBytes()() # initilize a pointer to where bytes will be outputed
nbytes = self.c_lib.freedv_rawdatarx(self.freedv, bytes_out, data_in) # Demodulated data and get number of demodulated bytes
#self.nin = self.c_lib.freedv_nin(self.freedv)
# ------------- SOME DEBUGGING OUTPUT
#print("INPUT PARSER: " + str(samples))
#print("INPUT LENGTH: " + str(len(data_in)))
#print("BUFFER LENGTH: " + str(len(buffer)))
#print("MODULATION LENGTH: " + str(len(modulation)))
#sync_state = self.c_lib.freedv_get_sync(self.freedv)
#if sync_state > 0:
# print("SYNC")
#else:
# print("NO SYNC")
# -------------
# print data to terminal if nbytes == bytes_per_frame for selected mode
if nbytes == self.bytes_per_frame:
print(bytes(bytes_out))
self.c_lib.freedv_set_sync(self.freedv, 0)
#Stop loop until data input is empty
#if len(data_in) == 0:
# False
main()

View file

@ -1,81 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sun Dec 13 13:45:58 2020
@author: DJ2LS
"""
import ctypes
from ctypes import *
import pathlib
import binascii #required for string.to_bytes() function
import sys
def main():
modem = FreeDV() #Load FreeDV Class as "modem"
data = b'HALLO' #byte string which will be send
modem.Modulate(data) #Call Modulate function, which modulates data and prints it to the terminal
class FreeDV():
def __init__(self):
self.mode = 12 # define mode
libname = pathlib.Path().absolute() / "libcodec2.so"
self.c_lib = ctypes.CDLL(libname) # Load FreeDV shared libary
self.freedv = self.c_lib.freedv_open(self.mode) #Set FreeDV waveform ( 10,11,12 --> DATAC1-3 )
self.bytes_per_frame = int(self.c_lib.freedv_get_bits_per_modem_frame(self.freedv)/8) #get bytes per frame from selected waveform
self.payload_per_frame = self.bytes_per_frame -2 #get frame payload because of 2byte CRC16 checksum
self.n_tx_modem_samples = self.c_lib.freedv_get_n_tx_modem_samples(self.freedv)*2 #get n_tx_modem_samples which defines the size of the modulation object
# MODULATION-OUT OBJECT
def ModulationOut(self):
return (c_short * self.n_tx_modem_samples) ##
# Pointer for changing buffer data type
def FrameBytes(self):
return (c_ubyte * self.bytes_per_frame)
# Modulate function which returns modulated data
def Modulate(self,data_out):
mod_out = self.ModulationOut()() # new modulation object and get pointer to it
data_list = [data_out[i:i+self.payload_per_frame] for i in range(0, len(data_out), self.payload_per_frame)] # split incomming bytes to size of 30bytes, create a list and loop through it
data_list_length = len(data_list)
for i in range(data_list_length): # LOOP THROUGH DATA LIST
if self.mode < 10: # don't generate CRC16 for modes 0 - 9
buffer = bytearray(self.bytes_per_frame) # use this if no CRC16 checksum is required
buffer[:len(data_list[i])] = data_list[i] # set buffersize to length of data which will be send
if self.mode >= 10: #generate CRC16 for modes 10-12..
buffer = bytearray(self.payload_per_frame) # use this if CRC16 checksum is required ( DATA1-3)
buffer[:len(data_list[i])] = data_list[i] # set buffersize to length of data which will be send
crc = c_ushort(self.c_lib.freedv_gen_crc16(bytes(buffer), self.payload_per_frame)) # generate CRC16
crc = crc.value.to_bytes(2, byteorder='big') # convert crc to 2 byte hex string
buffer += crc # append crc16 to buffer
data = self.FrameBytes().from_buffer_copy(buffer) #change data format from bytearray to ctypes.u_byte and copy from buffer to data
self.c_lib.freedv_rawdatatx(self.freedv,mod_out,data) # modulate DATA and safe it into mod_out pointer
sys.stdout.buffer.write(mod_out) # print data to terminal for piping the output to other programs
sys.stdout.flush() # flushing stdout
main()

Binary file not shown.

Binary file not shown.

56
tnc.py
View file

@ -1,37 +1,37 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Dec 25 21:25:14 2020
@author: DJ2LS
"""
import socketserver
import threading
import logging
import crcengine
import ctypes
from ctypes import *
import static
#from other import *
import other
import arq
#arq = arq.ARQ()
crc_algorithm = crcengine.new('crc16-ccitt-false') #load crc16 library
class TCPRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
self.data = bytes()
while True:
chunk = self.request.recv(8192)#.strip()
if chunk.endswith(b'\n'):
break
self.data += chunk
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip()
#self.data = self.request.recv(1024).strip()
### self.data = self.request.recv(1000000).strip()
# interrupt listening loop "while true" by setting MODEM_RECEIVE to False
#if len(self.data) > 0:
@ -46,29 +46,31 @@ class TCPRequestHandler(socketserver.BaseRequestHandler):
#if self.data == b'TEST':
#logging.info("DER TEST KLAPPT! HIER KOMMT DER COMMAND PARSER HIN!")
if self.data.startswith(b'SHOWBUFFERSIZE'):
self.request.sendall(bytes(static.RX_BUFFER[-1]))
print(static.RX_BUFFER_SIZE)
# BROADCAST PARSER -----------------------------------------------------------
if self.data.startswith(b'BC:'):
#import modem
#modem = modem.RF()
static.MODEM_RECEIVE = True ####### FALSE....
data = self.data.split(b'BC:')
#modem.Transmit(data[1])
static.MODEM_RECEIVE = True
# SEND AN ARQ FRAME -----------------------------------------------------------
if self.data.startswith(b'ACK:'):
static.MODEM_RECEIVE = True ############## FALSE
if self.data.startswith(b'ARQ:'):
data = self.data.split(b'ACK:')
data = self.data.split(b'ARQ:')
data_out = data[1]
arq.transmit(data_out)
#arq.transmit(data_out)
TRANSMIT_ARQ = threading.Thread(target=arq.transmit, args=[data_out], name="TRANSMIT_ARQ")
TRANSMIT_ARQ.start()