startet work on ARQ Go-Back-N

This commit is contained in:
DJ2LS 2020-12-27 22:38:49 +01:00 committed by GitHub
parent cf03ec2288
commit 8b9032f4a7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 158 additions and 66 deletions

117
arq.py Normal file
View file

@ -0,0 +1,117 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
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 static
import modem
import other
modem = modem.RF()
crc_algorithm = crcengine.new('crc16-ccitt-false') #load crc16 library
static.ARQ_PAYLOAD_PER_FRAME = static.FREEDV_PAYLOAD_PER_FRAME - 6
#class ARQ():
#
# def receive(bytes_in):
#
# print("TEST")
def receive(data_in):
print(data_in[:1])
def transmit(data_out):
static.ARQ_PAYLOAD_PER_FRAME = static.FREEDV_PAYLOAD_PER_FRAME - 6
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, create a list and loop through it
static.TX_BUFFER_SIZE = len(static.TX_BUFFER)
logging.info("TX | TOTAL PAYLOAD BYTES/FRAMES TO SEND: " + str(len(data_out)) + " / " + str(static.TX_BUFFER_SIZE))
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
print("N_RAW_FRAME: " + str(n_raw_frame))
# ----------- GENERATE PAYLOAD CRC FOR ARQ_TX_N_FRAMES
burst_total_payload = bytearray()
for i in range(static.ARQ_TX_N_FRAMES): #bytearray(b'111111111111111111111111222222222222222222222222')
burst_total_payload = burst_total_payload + static.TX_BUFFER[n_raw_frame + i]
burst_payload_crc = crc_algorithm(burst_total_payload)
burst_payload_crc = burst_payload_crc.to_bytes(2, byteorder='big') #b'\xa7\xd6'
print(burst_payload_crc)
#-------------------- BUILD ARQBURSTS
arqburst = []
for i in range(static.ARQ_TX_N_FRAMES):
#print(n_raw_frame)
#print(i)
#print(n_raw_frame + i)
#print(static.TX_BUFFER[n_raw_frame + i])
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
arqburst.append(arqframe)
#--------------------------------------------- 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])
#modem.RF.Transmit(arqburst[n])
print(arqburst[n])
# --------------------------- 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)
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
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
#-------------------------BREAK TX BUFFER LOOP IF ALL PACKETS HAVE BEEN SENT
if n_raw_frame == static.TX_BUFFER_SIZE:
break
logging.info("TX | BUFFER EMPTY")

View file

@ -15,6 +15,9 @@ import sys
import logging
import static
import arq
#arq = arq.ARQ()
@ -58,7 +61,8 @@ class RF():
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
@ -75,9 +79,11 @@ class RF():
return (c_ubyte * self.bytes_per_frame)
# 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
data_list_length = len(data_list)
@ -96,7 +102,8 @@ class RF():
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
@ -162,16 +169,21 @@ class RF():
print(bytes(bytes_out[:-2]))
self.c_lib.freedv_set_sync(self.freedv, 0)
#print(bytes(bytes_out))
# CHECK IF FRAMETYPE CONTAINS ACK------------------------
frametype = int.from_bytes(bytes(bytes_out[:1]), "big")
if 20 >= frametype >= 10 :
arq.receive(bytes(bytes_out))
# CHECK IF FRAME CONTAINS ACK------------------------
if bytes(bytes_out[:6]) == b'REQACK':
#if bytes(bytes_out[:6]) == b'REQACK':
logging.info("RX | ACK REQUESTED!")
time.sleep(5)
logging.info("TX | SENDING ACK FRAME")
self.Transmit(b'ACK')
#logging.info("RX | ACK REQUESTED!")
#time.sleep(5)
#logging.info("TX | SENDING ACK FRAME")
#self.Transmit(b'ACK')
#----------------------------------------------------
# CHECK IF FRAME CONTAINS ACK------------------------

View file

@ -8,13 +8,11 @@ Created on Fri Dec 25 21:25:14 2020
import time
import threading
import logging
import static
def timeout():
print("TIMEOUT REACHED!")
#static.ACK_TIMEOUT = seconds
#time.sleep(seconds)
static.ACK_TIMEOUT = 1

73
tnc.py
View file

@ -5,16 +5,25 @@
import socketserver
import threading
import logging
import crcengine
import ctypes
from ctypes import *
import modem
import static
#from other import *
import other
import arq
modem = modem.RF()
#arq = arq.ARQ()
crc_algorithm = crcengine.new('crc16-ccitt-false') #load crc16 library
class TCPRequestHandler(socketserver.BaseRequestHandler):
@ -41,69 +50,25 @@ class TCPRequestHandler(socketserver.BaseRequestHandler):
# BROADCAST PARSER -----------------------------------------------------------
if self.data.startswith(b'BC:'):
#import modem
#modem = modem.RF()
static.MODEM_RECEIVE = True ####### FALSE....
#print(static.MODEM_RECEIVE)
data = self.data.split(b'BC:')
daten = modem.Transmit(data[1])
#modem.Transmit(data[1])
static.MODEM_RECEIVE = True
#print(static.MODEM_RECEIVE)
# ACKNOWLEDGE PARSER -----------------------------------------------------------
# SEND AN ARQ FRAME -----------------------------------------------------------
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]
static.TX_BUFFER = [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
static.TX_BUFFER_SIZE = len(static.TX_BUFFER)
logging.info("TX | TOTAL PAYLOAD BYTES/FRAMES TO SEND: " + str(len(data_out)) + " / " + str(static.TX_BUFFER_SIZE))
for frame in range(static.TX_BUFFER_SIZE): # LOOP THROUGH DATA LIST
#--------------------------------------------- BUILD DATA PACKET
ack = b'REQACK'
data_to_transmit = ack + static.TX_BUFFER[frame]
logging.info("TX | SENDING FRAME " + str(frame+1) + " / " + str(static.TX_BUFFER_SIZE))
#---------------------------------------------------------------
#--------------------------------------------- ATTEMPTS TO SEND A MESSAGE IF ACK FAILS
for static.TX_N_RETRIES in range(static.TX_N_MAX_RETRIES):
# --------------------------- SEND FRAME
static.ACK_RECEIVED = 0
daten = modem.Transmit(data_to_transmit)
# --------------------------- START TIMER ---> IF TIMEOUT REACHED, ACK_TIMEOUT = 1
static.ACK_TIMEOUT = 0
timer = threading.Timer(static.ACK_TIMEOUT_SECONDS, other.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
#--------------- BREAK LOOP IF ACK HAS BEEN RECEIVED
if static.ACK_RECEIVED == 1:
static.TX_N_RETRIES = 3
break
#-------------------------BREAK TX BUFFER LOOP IF ALL PACKETS HAVE BEEN SENT
if frame == static.TX_BUFFER_SIZE:
break
logging.info("TX | BUFFER EMPTY")
arq.transmit(data_out)