added ARQ like behavior

send via socket "ACK:<DATA
TX requests a ACK from RX. RX then sends an ACK to TX. 
ACK will be requested 3 times, else timeout.

Todo: Frame ID, Code cleanup,...... and much much more
This commit is contained in:
DJ2LS 2020-12-25 22:55:56 +01:00 committed by GitHub
parent ae9a4b49cf
commit 4435ef602e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 103 additions and 13 deletions

View file

@ -116,7 +116,7 @@ class RF():
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,
@ -146,25 +146,52 @@ class RF():
while static.MODEM_RECEIVE == True: # Listne to audio until data arrives
#while 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 == "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 > 0:
if nbytes == self.bytes_per_frame: # make sure, we receive a full frame
print(bytes(bytes_out[:-2]))
#stream_rx.close()
self.c_lib.freedv_set_sync(self.freedv, 0)
#print(bytes(bytes_out))
# CHECK IF FRAME CONTAINS ACK------------------------
if bytes(bytes_out[:6]) == b'REQACK':
print("REQACK FRAME ERKANNT!!!!")
print("ADD TO SEND BUFFER")
time.sleep(5)
print("SEND ACK FRAME")
self.Transmit(b'ACK')
#----------------------------------------------------
# CHECK IF FRAME CONTAINS ACK------------------------
if bytes(bytes_out[:3]) == b'ACK':
print("ACK FRAME ERKANNT!!!!")
static.ACK_TIMEOUT = 1
static.ACK_RECEIVED = 1
static.ACK_RETRY = 3
#----------------------------------------------------
#return bytes(bytes_out[:-2])

View file

@ -28,3 +28,10 @@ AUDIO_SAMPLE_RATE = 8000
MODEM_SAMPLE_RATE = 8000
AUDIO_FRAMES_PER_BUFFER = 1024
AUDIO_CHANNELS = 1
#TNC DEFAULTS
TX_RETRIES = 3
ACK_RECEIVED = 0
ACK_TIMEOUT = 0
ACK_RETRY = 3

66
tnc.py
View file

@ -7,7 +7,8 @@ import threading
import modem
import static
#from other import *
import other
modem = modem.RF()
@ -20,8 +21,8 @@ class TCPRequestHandler(socketserver.BaseRequestHandler):
# interrupt listening loop "while true" by setting MODEM_RECEIVE to False
if len(self.data) > 0:
static.MODEM_RECEIVE = False
#if len(self.data) > 0:
# static.MODEM_RECEIVE = False
print("{} wrote:".format(self.client_address[0]))
@ -36,11 +37,66 @@ class TCPRequestHandler(socketserver.BaseRequestHandler):
# BROADCAST PARSER -----------------------------------------------------------
if self.data.startswith(b'BC:'):
static.MODEM_RECEIVE = False
static.MODEM_RECEIVE = True ####### FALSE....
print(static.MODEM_RECEIVE)
data = self.data.split(b'BC:')
daten = modem.Transmit(data[1])
static.MODEM_RECEIVE = True
print(static.MODEM_RECEIVE)
print(static.MODEM_RECEIVE)
# ACKNOWLEDGE PARSER -----------------------------------------------------------
if self.data.startswith(b'ACK:'):
static.MODEM_RECEIVE = True ############## FALSE
print(static.MODEM_RECEIVE)
data = self.data.split(b'ACK:')
data_out = data[1]
TXbuffer = [data_out[i:i+24] for i in range(0, len(data_out), 24)] # split incomming bytes to size of 30bytes, create a list and loop through it
TXbuffer_length = len(TXbuffer)
for i in range(TXbuffer_length): # LOOP THROUGH DATA LIST
#--------------------------------------------- BUILD DATA PACKET
ack = b'REQACK'
data_to_transmit = ack + TXbuffer[i]
print(len(data_to_transmit))
print(data_to_transmit)
#---------------------------------------------------------------
static.ACK_RETRY = 1
for static.ACK_RETRY in range(static.TX_RETRIES):
print("RETRY: " + str(static.ACK_RETRY))
print("SENDING")
static.ACK_RECEIVED = 0
daten = modem.Transmit(data_to_transmit)
# --------------------------- START TIMER
static.ACK_TIMEOUT = 0
timer = threading.Timer(10.0, other.timeout)
timer.start()
# --------------------------- WHILE TIMEOUT NOT REACHED LISTEN
print("WAITING FOR ACK")
while static.ACK_TIMEOUT == 0 and static.ACK_RECEIVED == 0:
static.MODEM_RECEIVE = True
if static.ACK_RECEIVED == 1:
static.ACK_RETRY = 3
break
if static.ACK_RECEIVED ==1:
break
print("GESCHAFFT!")